3
3
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4
4
FabAtHomePrinter::FabAtHomePrinter():
6
cancelPrintFlag(false),
6
cancelPrintFlag(false),
13
13
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
14
14
string FabAtHomePrinter::initialize(const string& filePath)
18
string result = loadConfigFile(filePath);
19
if(result.compare("") != 0)
26
ss << "COM" << COM_PORT;
27
unsigned int numModulesFound = NmcInit(const_cast<char*>(ss.str().c_str()), BAUD_RATE);
28
if(numModulesFound < NUM_MODULES)
31
ss << "Found " << numModulesFound << " modules but need " << NUM_MODULES << " modules.";
35
//Initialize all motors.
36
for(map<string,Motor,LessThanString>::iterator i = motors.begin(); i != motors.end(); ++i)
38
string result = i->second.initialize();
39
Util::assertTrue(result.compare("") == 0,result,__LINE__,__FILE__);
18
string result = loadConfigFile(filePath);
19
if(result.compare("") != 0)
26
ss << "COM" << COM_PORT;
27
unsigned int numModulesFound = NmcInit(const_cast<char*>(ss.str().c_str()), BAUD_RATE);
28
if(numModulesFound < NUM_MODULES)
31
ss << "Found " << numModulesFound << " modules but need " << NUM_MODULES << " modules.";
35
//Initialize all motors.
36
for(map<string,Motor,LessThanString>::iterator i = motors.begin(); i != motors.end(); ++i)
38
string result = i->second.initialize();
39
Util::assertTrue(result.compare("") == 0,result,__LINE__,__FILE__);
47
47
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
48
48
void FabAtHomePrinter::pausePrint()
50
pausePrintFlag = true;
50
pausePrintFlag = true;
52
52
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
53
53
void FabAtHomePrinter::cancelPrint()
55
cancelPrintFlag = true;
55
cancelPrintFlag = true;
57
57
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
58
58
void FabAtHomePrinter::redoPath()
62
62
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
63
63
void FabAtHomePrinter::equipBay(const string& bayName, const string& materialCalibrationName)
65
Util::assertTrue(tool.bays.find(bayName) != tool.bays.end(),"Trying to equip "+bayName+" with "+materialCalibrationName+" but bay has not been loaded.",__LINE__,__FILE__);
66
Util::assertTrue(materialCalibrationName.compare("") == 0 || materialCalibrations.find(materialCalibrationName) != materialCalibrations.end(),"Trying to equip "+bayName+" with "+materialCalibrationName+" but material calibration has not been loaded.",__LINE__,__FILE__);
67
Util::assertTrue(!isPrinting() || isPaused(),"Cannot equip bay at this time.",__LINE__,__FILE__);
68
MaterialCalibration* materialCalibration = materialCalibrationName.compare("") == 0 ? NULL : &(materialCalibrations.find(materialCalibrationName)->second);
69
tool.bays.find(bayName)->second.materialCalibration = materialCalibration;
65
Util::assertTrue(tool.bays.find(bayName) != tool.bays.end(),"Trying to equip "+bayName+" with "+materialCalibrationName+" but bay has not been loaded.",__LINE__,__FILE__);
66
Util::assertTrue(materialCalibrationName.compare("") == 0 || materialCalibrations.find(materialCalibrationName) != materialCalibrations.end(),"Trying to equip "+bayName+" with "+materialCalibrationName+" but material calibration has not been loaded.",__LINE__,__FILE__);
67
Util::assertTrue(!isPrinting() || isPaused(),"Cannot equip bay at this time.",__LINE__,__FILE__);
68
MaterialCalibration* materialCalibration = materialCalibrationName.compare("") == 0 ? NULL : &(materialCalibrations.find(materialCalibrationName)->second);
69
tool.bays.find(bayName)->second.materialCalibration = materialCalibration;
71
71
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
72
72
int FabAtHomePrinter::numLoadedPaths()
74
return model.paths.size();
74
return model.paths.size();
76
76
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
77
77
int FabAtHomePrinter::numLoadedBays()
79
return tool.bays.size();
79
return tool.bays.size();
81
81
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
82
82
bool FabAtHomePrinter::initializePathMode()
84
SetTangentTolerance(180.0f); //180.0f allows all angles.
85
SetOrigin(0.0f, 0.0f, 0.0f);
87
//aReset position of all motors.
88
for(map<string,Motor,LessThanString>::iterator i = motors.begin(); i != motors.end(); ++i)
90
i->second.resetPosition();
94
axes["X"].motor->setGroup(X_Y_Z_GROUP_ADDRESS, true)
95
&& axes["Y"].motor->setGroup(X_Y_Z_GROUP_ADDRESS, false)
96
&& axes["Z"].motor->setGroup(X_Y_Z_GROUP_ADDRESS, false)
99
P_30HZ, //path frequency
100
10, //Max number of points in the path point buffer at one time. Max value is 87. A higher value results in longer downloads to the path point buffer.
101
axes["X"].motor->getAddress(),
102
axes["Y"].motor->getAddress(),
103
axes["Z"].motor->getAddress(),
105
axes["X"].motor->getAddress(), //group leader
106
(float)axes["X"].motor->getCountsPerU(),
107
(float)axes["Y"].motor->getCountsPerU(),
108
(float)axes["Z"].motor->getCountsPerU(),
109
(float)PRINT_ACCELERATION
84
SetTangentTolerance(180.0f); //180.0f allows all angles.
85
SetOrigin(0.0f, 0.0f, 0.0f);
87
//aReset position of all motors.
88
for(map<string,Motor,LessThanString>::iterator i = motors.begin(); i != motors.end(); ++i)
90
i->second.resetPosition();
94
axes["X"].motor->setGroup(X_Y_Z_GROUP_ADDRESS, true)
95
&& axes["Y"].motor->setGroup(X_Y_Z_GROUP_ADDRESS, false)
96
&& axes["Z"].motor->setGroup(X_Y_Z_GROUP_ADDRESS, false)
99
P_30HZ, //path frequency
100
10, //Max number of points in the path point buffer at one time. Max value is 87. A higher value results in longer downloads to the path point buffer.
101
axes["X"].motor->getAddress(),
102
axes["Y"].motor->getAddress(),
103
axes["Z"].motor->getAddress(),
105
axes["X"].motor->getAddress(), //group leader
106
(float)axes["X"].motor->getCountsPerU(),
107
(float)axes["Y"].motor->getCountsPerU(),
108
(float)axes["Z"].motor->getCountsPerU(),
109
(float)PRINT_ACCELERATION
112
112
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
113
113
string FabAtHomePrinter::loadConfigFile(string filePath)
115
//Clear previously loaded data.
121
string result = parser.load(filePath);
122
if(result.compare("") != 0)
128
COM_PORT = Util::assertType<unsigned int>(parser.text("fabAtHomePrinter 0\\electronics 0\\comPort 0"));
129
NUM_MODULES = Util::assertType<unsigned int>(parser.text("fabAtHomePrinter 0\\electronics 0\\numModules 0"));
130
BAUD_RATE = Util::assertType<unsigned int>(parser.text("fabAtHomePrinter 0\\electronics 0\\baudRate 0"));
131
X_Y_Z_GROUP_ADDRESS = (byte)Util::assertType<unsigned int>(parser.text("fabAtHomePrinter 0\\electronics 0\\xyzGroupAddress 0"));
132
PLATFORM_DELTA = Util::assertType<double>(parser.text("fabAtHomePrinter 0\\motion 0\\platformDelta 0"));
133
OLD_MSPS = Util::assertType<double>(parser.text("fabAtHomePrinter 0\\motion 0\\oldMsps 0"));
136
unsigned int count = parser.count("fabAtHomePrinter 0\\electronics 0\\motor");
137
for(unsigned int i = 0; i < count; ++i)
139
string base = "fabAtHomePrinter 0\\electronics 0\\motor "+Util::toString(i)+"\\";
140
string name = parser.text(base+"name 0");
141
byte address = (byte)Util::assertType<unsigned int>(parser.text(base+"address 0"));
142
double countsPerDistanceUnit = Util::assertType<double>(parser.text(base+"countsPerDistanceUnit 0"));
143
short kp = Util::assertType<unsigned short>(parser.text(base+"kp 0"));
144
short kd = Util::assertType<unsigned short>(parser.text(base+"kd 0"));
145
short ki = Util::assertType<unsigned short>(parser.text(base+"ki 0"));
146
short il = Util::assertType<unsigned short>(parser.text(base+"il 0"));
147
byte ol = (byte)Util::assertType<unsigned int>(parser.text(base+"ol 0"));
148
byte cl = (byte)Util::assertType<unsigned int>(parser.text(base+"cl 0"));
149
short el = Util::assertType<unsigned short>(parser.text(base+"el 0"));
150
byte sr = (byte)Util::assertType<unsigned int>(parser.text(base+"sr 0"));
151
byte db = (byte)Util::assertType<unsigned int>(parser.text(base+"db 0"));
152
double ticksPerSecond = Util::assertType<double>(parser.text(base+"ticksPerSecond 0"));
153
motors[name] = Motor(name,address,countsPerDistanceUnit,ticksPerSecond,kp,kd,ki,il,ol,cl,el,sr,db);
157
count = parser.count("fabAtHomePrinter 0\\axis");
158
for(unsigned int i = 0; i < count; ++i)
160
string base = "fabAtHomePrinter 0\\axis "+Util::toString(i)+"\\";
161
string name = parser.text(base+"name 0");
162
string motorName = parser.text(base+"motorName 0");
163
if(motors.find(motorName) == motors.end())
165
return "Axis "+name+" references motor "+motorName+" which has not been loaded.";
167
axes[name] = Axis(name,&(motors.find(motorName)->second));
170
//Check that axes named X, Y, and Z were loaded.
171
if(axes.find("X") == axes.end())
173
return "Must load an axis named X.";
175
if(axes.find("Y") == axes.end())
177
return "Must load an axis named Y.";
179
if(axes.find("Z") == axes.end())
181
return "Must load an axis named Z.";
185
count = parser.count("fabAtHomePrinter 0\\tool 0\\bay");
186
for(unsigned int i = 0; i < count; ++i)
188
string base = "fabAtHomePrinter 0\\tool 0\\bay "+Util::toString(i)+"\\";
189
string name = parser.text(base+"name 0");
190
string motorName = parser.text(base+"motorName 0");
191
if(motors.find(motorName) == motors.end())
193
return "Bay "+name+" references motor "+motorName+" which has not been loaded.";
195
double x = Util::assertType<double>(parser.text(base+"location 0\\x 0"));
196
double y = Util::assertType<double>(parser.text(base+"location 0\\y 0"));
197
double z = Util::assertType<double>(parser.text(base+"location 0\\z 0"));
198
tool.bays[name] = Bay(name,Point(x,y,z),&(motors.find(motorName)->second));
201
//Check that at least one bay is loaded.
202
if(tool.bays.size() == 0)
204
return "Must load at least one bay.";
115
//Clear previously loaded data.
121
string result = parser.load(filePath);
122
if(result.compare("") != 0)
128
COM_PORT = Util::assertType<unsigned int>(parser.text("fabAtHomePrinter 0\\electronics 0\\comPort 0"));
129
NUM_MODULES = Util::assertType<unsigned int>(parser.text("fabAtHomePrinter 0\\electronics 0\\numModules 0"));
130
BAUD_RATE = Util::assertType<unsigned int>(parser.text("fabAtHomePrinter 0\\electronics 0\\baudRate 0"));
131
X_Y_Z_GROUP_ADDRESS = (byte)Util::assertType<unsigned int>(parser.text("fabAtHomePrinter 0\\electronics 0\\xyzGroupAddress 0"));
132
PLATFORM_DELTA = Util::assertType<double>(parser.text("fabAtHomePrinter 0\\motion 0\\platformDelta 0"));
133
OLD_MSPS = Util::assertType<double>(parser.text("fabAtHomePrinter 0\\motion 0\\oldMsps 0"));
136
unsigned int count = parser.count("fabAtHomePrinter 0\\electronics 0\\motor");
137
for(unsigned int i = 0; i < count; ++i)
139
string base = "fabAtHomePrinter 0\\electronics 0\\motor "+Util::toString(i)+"\\";
140
string name = parser.text(base+"name 0");
141
byte address = (byte)Util::assertType<unsigned int>(parser.text(base+"address 0"));
142
double countsPerDistanceUnit = Util::assertType<double>(parser.text(base+"countsPerDistanceUnit 0"));
143
short kp = Util::assertType<unsigned short>(parser.text(base+"kp 0"));
144
short kd = Util::assertType<unsigned short>(parser.text(base+"kd 0"));
145
short ki = Util::assertType<unsigned short>(parser.text(base+"ki 0"));
146
short il = Util::assertType<unsigned short>(parser.text(base+"il 0"));
147
byte ol = (byte)Util::assertType<unsigned int>(parser.text(base+"ol 0"));
148
byte cl = (byte)Util::assertType<unsigned int>(parser.text(base+"cl 0"));
149
short el = Util::assertType<unsigned short>(parser.text(base+"el 0"));
150
byte sr = (byte)Util::assertType<unsigned int>(parser.text(base+"sr 0"));
151
byte db = (byte)Util::assertType<unsigned int>(parser.text(base+"db 0"));
152
double ticksPerSecond = Util::assertType<double>(parser.text(base+"ticksPerSecond 0"));
153
motors[name] = Motor(name,address,countsPerDistanceUnit,ticksPerSecond,kp,kd,ki,il,ol,cl,el,sr,db);
157
count = parser.count("fabAtHomePrinter 0\\axis");
158
for(unsigned int i = 0; i < count; ++i)
160
string base = "fabAtHomePrinter 0\\axis "+Util::toString(i)+"\\";
161
string name = parser.text(base+"name 0");
162
string motorName = parser.text(base+"motorName 0");
163
if(motors.find(motorName) == motors.end())
165
return "Axis "+name+" references motor "+motorName+" which has not been loaded.";
167
axes[name] = Axis(name,&(motors.find(motorName)->second));
170
//Check that axes named X, Y, and Z were loaded.
171
if(axes.find("X") == axes.end())
173
return "Must load an axis named X.";
175
if(axes.find("Y") == axes.end())
177
return "Must load an axis named Y.";
179
if(axes.find("Z") == axes.end())
181
return "Must load an axis named Z.";
185
count = parser.count("fabAtHomePrinter 0\\tool 0\\bay");
186
for(unsigned int i = 0; i < count; ++i)
188
string base = "fabAtHomePrinter 0\\tool 0\\bay "+Util::toString(i)+"\\";
189
string name = parser.text(base+"name 0");
190
string motorName = parser.text(base+"motorName 0");
191
if(motors.find(motorName) == motors.end())
193
return "Bay "+name+" references motor "+motorName+" which has not been loaded.";
195
double x = Util::assertType<double>(parser.text(base+"location 0\\x 0"));
196
double y = Util::assertType<double>(parser.text(base+"location 0\\y 0"));
197
double z = Util::assertType<double>(parser.text(base+"location 0\\z 0"));
198
tool.bays[name] = Bay(name,Point(x,y,z),&(motors.find(motorName)->second));
201
//Check that at least one bay is loaded.
202
if(tool.bays.size() == 0)
204
return "Must load at least one bay.";
209
209
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
210
210
string FabAtHomePrinter::loadFabFile(string filePath)
214
if(!file.LoadFile(filePath.c_str()))
216
return "Could not interpret "+filePath+" as a xml file.";
219
//Clear previously loaded data.
220
materialCalibrations.clear();
223
TiXmlNode* root(file.RootElement());
224
for(TiXmlNode* child = root->FirstChild(); child != NULL; child = root->IterateChildren(child))
226
if(strcmp(child->Value(), "materialCalibration") == 0)
228
loadMaterialCalibration(child);
230
else if(strcmp(child->Value(), "path") == 0)
234
else if(strcmp(child->Value(), "printAcceleration") == 0)
236
PRINT_ACCELERATION = Util::assertType<double>(child->FirstChild()->Value());
214
if(!file.LoadFile(filePath.c_str()))
216
return "Could not interpret "+filePath+" as a xml file.";
219
//Clear previously loaded data.
220
materialCalibrations.clear();
223
TiXmlNode* root(file.RootElement());
224
for(TiXmlNode* child = root->FirstChild(); child != NULL; child = root->IterateChildren(child))
226
if(strcmp(child->Value(), "materialCalibration") == 0)
228
loadMaterialCalibration(child);
230
else if(strcmp(child->Value(), "path") == 0)
234
else if(strcmp(child->Value(), "printAcceleration") == 0)
236
PRINT_ACCELERATION = Util::assertType<double>(child->FirstChild()->Value());
243
243
XMLParser parser;
244
244
string result = parser.load(filePath);
245
245
if(result.compare("") != 0)
250
250
//Clear previously loaded data.
251
251
materialCalibrations.clear();
252
252
model.paths.clear();
301
301
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
302
302
bool FabAtHomePrinter::isPrinting()
306
306
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
307
307
bool FabAtHomePrinter::isPaused()
311
311
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
312
312
void FabAtHomePrinter::loadedMaterialCalibrations(vector<string>& result)
314
for(map<string,MaterialCalibration,LessThanString>::iterator i = materialCalibrations.begin(); i != materialCalibrations.end(); ++i)
316
result.push_back(i->first);
314
for(map<string,MaterialCalibration,LessThanString>::iterator i = materialCalibrations.begin(); i != materialCalibrations.end(); ++i)
316
result.push_back(i->first);
319
319
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
320
320
string FabAtHomePrinter::loadMaterialCalibration(TiXmlNode* node)
322
string name = node->FirstChild("name")->FirstChild()->Value();
323
double pathSpeed = Util::assertType<double>(node->FirstChild("pathSpeed")->FirstChild()->Value());
324
double pathWidth = Util::assertType<double>(node->FirstChild("pathWidth")->FirstChild()->Value());
325
double depositionRate = Util::assertType<double>(node->FirstChild("depositionRate")->FirstChild()->Value());
326
double pushout = Util::assertType<double>(node->FirstChild("pushout")->FirstChild()->Value());
327
double suckback = Util::assertType<double>(node->FirstChild("suckback")->FirstChild()->Value());
328
double suckbackDelay = Util::assertType<double>(node->FirstChild("suckbackDelay")->FirstChild()->Value());
329
double clearance = Util::assertType<double>(node->FirstChild("clearance")->FirstChild()->Value());
330
int pausePaths = Util::assertType<int>(node->FirstChild("pausePaths")->FirstChild()->Value());
331
double pitch = Util::assertType<double>(node->FirstChild("pitch")->FirstChild()->Value());
332
materialCalibrations[name] = MaterialCalibration(name,pathSpeed,pathWidth,depositionRate,pushout,suckback,suckbackDelay,clearance,pausePaths,pitch);
322
string name = node->FirstChild("name")->FirstChild()->Value();
323
double pathSpeed = Util::assertType<double>(node->FirstChild("pathSpeed")->FirstChild()->Value());
324
double pathWidth = Util::assertType<double>(node->FirstChild("pathWidth")->FirstChild()->Value());
325
double depositionRate = Util::assertType<double>(node->FirstChild("depositionRate")->FirstChild()->Value());
326
double pushout = Util::assertType<double>(node->FirstChild("pushout")->FirstChild()->Value());
327
double suckback = Util::assertType<double>(node->FirstChild("suckback")->FirstChild()->Value());
328
double suckbackDelay = Util::assertType<double>(node->FirstChild("suckbackDelay")->FirstChild()->Value());
329
double clearance = Util::assertType<double>(node->FirstChild("clearance")->FirstChild()->Value());
330
int pausePaths = Util::assertType<int>(node->FirstChild("pausePaths")->FirstChild()->Value());
331
double pitch = Util::assertType<double>(node->FirstChild("pitch")->FirstChild()->Value());
332
materialCalibrations[name] = MaterialCalibration(name,pathSpeed,pathWidth,depositionRate,pushout,suckback,suckbackDelay,clearance,pausePaths,pitch);
335
335
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
336
336
string FabAtHomePrinter::loadPath(TiXmlNode* node)
338
vector<Point> points;
339
string materialCalibrationName = node->FirstChild("materialCalibrationName")->FirstChild()->Value();
340
if(materialCalibrations.find(materialCalibrationName) == materialCalibrations.end())
342
return "A path references material calibration "+materialCalibrationName+" which has not been loaded.";
344
for(TiXmlNode* child = node->FirstChild(); child != NULL; child = node->IterateChildren(child))
346
if(strcmp(child->Value(), "point") == 0)
348
double x = Util::assertType<double>(child->FirstChild("x")->FirstChild()->Value());
349
double y = Util::assertType<double>(child->FirstChild("y")->FirstChild()->Value());
350
double z = Util::assertType<double>(child->FirstChild("z")->FirstChild()->Value());
351
points.push_back(Point(x,y,z));
354
model.paths.push_back(Path(&materialCalibrations[materialCalibrationName],points));
338
vector<Point> points;
339
string materialCalibrationName = node->FirstChild("materialCalibrationName")->FirstChild()->Value();
340
if(materialCalibrations.find(materialCalibrationName) == materialCalibrations.end())
342
return "A path references material calibration "+materialCalibrationName+" which has not been loaded.";
344
for(TiXmlNode* child = node->FirstChild(); child != NULL; child = node->IterateChildren(child))
346
if(strcmp(child->Value(), "point") == 0)
348
double x = Util::assertType<double>(child->FirstChild("x")->FirstChild()->Value());
349
double y = Util::assertType<double>(child->FirstChild("y")->FirstChild()->Value());
350
double z = Util::assertType<double>(child->FirstChild("z")->FirstChild()->Value());
351
points.push_back(Point(x,y,z));
354
model.paths.push_back(Path(&materialCalibrations[materialCalibrationName],points));
357
357
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
358
358
Bay* FabAtHomePrinter::findBay(MaterialCalibration* materialCalibration)
360
for(map<string,Bay,LessThanString>::iterator i = tool.bays.begin(); i != tool.bays.end(); ++i)
362
if(materialCalibration == i->second.materialCalibration)
360
for(map<string,Bay,LessThanString>::iterator i = tool.bays.begin(); i != tool.bays.end(); ++i)
362
if(materialCalibration == i->second.materialCalibration)
369
369
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
370
370
void FabAtHomePrinter::executePausePath(const Point& start)
372
vector<Point> pausePathPoints(2);
373
//Move the platform down.
374
pausePathPoints.clear();
375
pausePathPoints.push_back(start);
376
pausePathPoints.push_back(Point(start.x, start.y, start.z + PLATFORM_DELTA));
377
executePath(Path(NULL,pausePathPoints),NULL,false);
379
Util::messageBox("Execution has been paused. Press OK to resume execution.");
381
//Move the platform up.
382
pausePathPoints.clear();
383
pausePathPoints.push_back(Point(start.x, start.y, start.z + PLATFORM_DELTA));
384
pausePathPoints.push_back(start);
385
executePath(Path(NULL,pausePathPoints),NULL,false);
372
vector<Point> pausePathPoints(2);
373
//Move the platform down.
374
pausePathPoints.clear();
375
pausePathPoints.push_back(start);
376
pausePathPoints.push_back(Point(start.x, start.y, start.z + PLATFORM_DELTA));
377
executePath(Path(NULL,pausePathPoints),NULL,false);
379
Util::messageBox("Execution has been paused. Press OK to resume execution.");
381
//Move the platform up.
382
pausePathPoints.clear();
383
pausePathPoints.push_back(Point(start.x, start.y, start.z + PLATFORM_DELTA));
384
pausePathPoints.push_back(start);
385
executePath(Path(NULL,pausePathPoints),NULL,false);
387
387
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
388
388
void FabAtHomePrinter::executeSetupPath(const Point& start, const Point& end, const double& clearance)
390
vector<Point> setupPathPoints(4);
391
setupPathPoints.clear();
392
setupPathPoints.push_back(start);
393
setupPathPoints.push_back(Point(start.x, start.y, start.z + clearance));
394
setupPathPoints.push_back(Point(end.x, end.y, start.z + clearance));
395
setupPathPoints.push_back(end);
396
executePath(Path(NULL,setupPathPoints),NULL,false);
390
vector<Point> setupPathPoints(4);
391
setupPathPoints.clear();
392
setupPathPoints.push_back(start);
393
setupPathPoints.push_back(Point(start.x, start.y, start.z + clearance));
394
setupPathPoints.push_back(Point(end.x, end.y, start.z + clearance));
395
setupPathPoints.push_back(end);
396
executePath(Path(NULL,setupPathPoints),NULL,false);
398
398
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
511
511
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
512
512
void FabAtHomePrinter::executePath(const Path& path, Bay* bay, const bool flowDuringPath)
516
//Want to achieve a steady state during path execution so scale the path speed if necessary. Copied from model 1 code.
517
double scaledPathSpeed = path.materialCalibration->PATH_SPEED;
518
//pathdur is the duration of the path in seconds from nominal start of material flow to stop.
519
double pathdur = path.length / path.materialCalibration->PATH_SPEED + path.materialCalibration->SUCKBACK + path.materialCalibration->SUCKBACK_DELAY;
520
//Check for problematic path too short to reach steady state.
521
double ssDur = path.materialCalibration->SUCKBACK + path.materialCalibration->SUCKBACK_DELAY + 10 * path.materialCalibration->PATH_WIDTH/path.materialCalibration->PATH_SPEED; //Try to estimate duration of a path which reaches steady state.
524
scaledPathSpeed *= pathdur/ssDur;
527
//Calculate motion values.
528
double suckpathdist = (path.materialCalibration->SUCKBACK - path.materialCalibration->SUCKBACK_DELAY) * scaledPathSpeed; //suckpathdist is the distance from the end of the path at which to start suckback.
529
double pathLengthWithoutSuckback = path.length - suckpathdist;
530
double pushoutDistance = path.materialCalibration->PUSHOUT * OLD_MSPS * path.materialCalibration->PITCH;
531
double pushoutVelocity = path.materialCalibration->PUSHOUT == 0 ? 0 : pushoutDistance / path.materialCalibration->PUSHOUT;
532
double suckbackDistance = path.materialCalibration->SUCKBACK * OLD_MSPS * path.materialCalibration->PITCH;
533
double suckbackVelocity = path.materialCalibration->SUCKBACK == 0 ? 0 : suckbackDistance / path.materialCalibration->SUCKBACK;
534
double standardDistance = pathLengthWithoutSuckback * path.materialCalibration->DEPOSITION_RATE;
535
double timeUntilSuckback = pathLengthWithoutSuckback / scaledPathSpeed;
536
double standardVelocity = standardDistance / timeUntilSuckback;
538
//Calculate where suckback begins.
540
if(pathLengthWithoutSuckback >= path.length)
542
suckbackPoint = path.points[path.points.size()-1];
546
double beforeSuckbackLength = 0;
547
vector<Point>::const_iterator i = path.points.begin();
548
for(; beforeSuckbackLength + Point::calcDist(*i, *(i+1)) <= pathLengthWithoutSuckback; ++i)
550
beforeSuckbackLength += Point::calcDist(*i, *(i+1));
552
//Suckback should start somewhere on the line with endpoints *i and *(i+1).
553
double diff = pathLengthWithoutSuckback - beforeSuckbackLength;
554
double length = Point::calcDist(*i, *(i+1));
555
Point v((i+1)->x - i->x, (i+1)->y - i->y, (i+1)->z - i->z); //v is the vector from *i to *(i+1).
556
Point vDirection = Point(v.x/length, v.y/length, v.z/length);
557
suckbackPoint = Point(i->x+diff*vDirection.x, i->y+diff*vDirection.y, i->z+diff*vDirection.z);
561
SetFeedrate((float)scaledPathSpeed); //Feedrate is the path speed.
562
executePoints(path.points, bay, flowDuringPath, pushoutDistance, pushoutVelocity, standardDistance, standardVelocity, suckbackDistance, suckbackVelocity, suckbackPoint);
563
//Wait for axis movement to finish.
564
axes["X"].motor->waitMove();
516
//Want to achieve a steady state during path execution so scale the path speed if necessary. Copied from model 1 code.
517
double scaledPathSpeed = path.materialCalibration->PATH_SPEED;
518
//pathdur is the duration of the path in seconds from nominal start of material flow to stop.
519
double pathdur = path.length / path.materialCalibration->PATH_SPEED + path.materialCalibration->SUCKBACK + path.materialCalibration->SUCKBACK_DELAY;
520
//Check for problematic path too short to reach steady state.
521
double ssDur = path.materialCalibration->SUCKBACK + path.materialCalibration->SUCKBACK_DELAY + 10 * path.materialCalibration->PATH_WIDTH/path.materialCalibration->PATH_SPEED; //Try to estimate duration of a path which reaches steady state.
524
scaledPathSpeed *= pathdur/ssDur;
527
//Calculate motion values.
528
double suckpathdist = (path.materialCalibration->SUCKBACK - path.materialCalibration->SUCKBACK_DELAY) * scaledPathSpeed; //suckpathdist is the distance from the end of the path at which to start suckback.
529
double pathLengthWithoutSuckback = path.length - suckpathdist;
530
double pushoutDistance = path.materialCalibration->PUSHOUT * OLD_MSPS * path.materialCalibration->PITCH;
531
double pushoutVelocity = path.materialCalibration->PUSHOUT == 0 ? 0 : pushoutDistance / path.materialCalibration->PUSHOUT;
532
double suckbackDistance = path.materialCalibration->SUCKBACK * OLD_MSPS * path.materialCalibration->PITCH;
533
double suckbackVelocity = path.materialCalibration->SUCKBACK == 0 ? 0 : suckbackDistance / path.materialCalibration->SUCKBACK;
534
double standardDistance = pathLengthWithoutSuckback * path.materialCalibration->DEPOSITION_RATE;
535
double timeUntilSuckback = pathLengthWithoutSuckback / scaledPathSpeed;
536
double standardVelocity = standardDistance / timeUntilSuckback;
538
//Calculate where suckback begins.
540
if(pathLengthWithoutSuckback >= path.length)
542
suckbackPoint = path.points[path.points.size()-1];
546
double beforeSuckbackLength = 0;
547
vector<Point>::const_iterator i = path.points.begin();
548
for(; beforeSuckbackLength + Point::calcDist(*i, *(i+1)) <= pathLengthWithoutSuckback; ++i)
550
beforeSuckbackLength += Point::calcDist(*i, *(i+1));
552
//Suckback should start somewhere on the line with endpoints *i and *(i+1).
553
double diff = pathLengthWithoutSuckback - beforeSuckbackLength;
554
double length = Point::calcDist(*i, *(i+1));
555
Point v((i+1)->x - i->x, (i+1)->y - i->y, (i+1)->z - i->z); //v is the vector from *i to *(i+1).
556
Point vDirection = Point(v.x/length, v.y/length, v.z/length);
557
suckbackPoint = Point(i->x+diff*vDirection.x, i->y+diff*vDirection.y, i->z+diff*vDirection.z);
561
SetFeedrate((float)scaledPathSpeed); //Feedrate is the path speed.
562
executePoints(path.points, bay, flowDuringPath, pushoutDistance, pushoutVelocity, standardDistance, standardVelocity, suckbackDistance, suckbackVelocity, suckbackPoint);
563
//Wait for axis movement to finish.
564
axes["X"].motor->waitMove();
565
565
axes["Y"].motor->waitMove();
566
566
axes["Z"].motor->waitMove();
567
bay->motor->waitMove(); //Wait for bay movement to finish.
571
//No flow during path.
572
SetFeedrate(10); //Feedrate is the path speed.
573
executePoints(path.points,NULL,flowDuringPath,0,0,0,0,0,0,Point());
574
//Wait for axis movement to finish.
575
axes["X"].motor->waitMove();
576
axes["Y"].motor->waitMove();
577
axes["Z"].motor->waitMove();
567
bay->motor->waitMove(); //Wait for bay movement to finish.
571
//No flow during path.
572
SetFeedrate(10); //Feedrate is the path speed.
573
executePoints(path.points,NULL,flowDuringPath,0,0,0,0,0,0,Point());
574
//Wait for axis movement to finish.
575
axes["X"].motor->waitMove();
576
axes["Y"].motor->waitMove();
577
axes["Z"].motor->waitMove();
580
580
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
581
581
void FabAtHomePrinter::executePoints(const vector<Point>& points, Bay* bay, const bool flowDuringPath, double pushoutDistance, double pushoutVelocity, double standardDistance, double standardVelocity, double suckbackDistance, double suckbackVelocity, const Point& suckbackPoint)
585
bool flowStarted = false;
586
while(res != points.size()-1)
588
//Invariant: currIndex is the next index to be added to the segment list.
589
res = fillSegmentList(points, currIndex);
590
//Invariant: res is the most recent index that was added to the segment list.
591
//The segment list has been filled so start downloading.
592
downloadSegmentList(bay, flowDuringPath && !flowStarted, flowDuringPath && res == points.size()-1, pushoutDistance, pushoutVelocity, standardDistance, standardVelocity, suckbackDistance, suckbackVelocity,suckbackPoint);
593
flowStarted = flowDuringPath;
594
//The next index to be added to the segment list is the most recent index that was added to the segment list.
585
bool flowStarted = false;
586
while(res != points.size()-1)
588
//Invariant: currIndex is the next index to be added to the segment list.
589
res = fillSegmentList(points, currIndex);
590
//Invariant: res is the most recent index that was added to the segment list.
591
//The segment list has been filled so start downloading.
592
downloadSegmentList(bay, flowDuringPath && !flowStarted, flowDuringPath && res == points.size()-1, pushoutDistance, pushoutVelocity, standardDistance, standardVelocity, suckbackDistance, suckbackVelocity,suckbackPoint);
593
flowStarted = flowDuringPath;
594
//The next index to be added to the segment list is the most recent index that was added to the segment list.
598
598
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
599
599
int FabAtHomePrinter::fillSegmentList(const vector<Point>& points, const int startIndex)
601
if(points.size() == 0)
605
ClearSegList((float)points[startIndex].x, (float)points[startIndex].y, (float)points[startIndex].z);
606
for(unsigned int i = startIndex+1; i < points.size(); ++i)
608
int res = AddLineSeg((float)points[i].x, (float)points[i].y, (float)points[i].z);
611
//points[i-2], points[i-1], and points[i] form two consecutive line segments that are not tangent.
612
//Stop at points[i-1].
617
//The segment list is full.
621
//All points have been inserted.
622
return points.size()-1;
601
if(points.size() == 0)
605
ClearSegList((float)points[startIndex].x, (float)points[startIndex].y, (float)points[startIndex].z);
606
for(unsigned int i = startIndex+1; i < points.size(); ++i)
608
int res = AddLineSeg((float)points[i].x, (float)points[i].y, (float)points[i].z);
611
//points[i-2], points[i-1], and points[i] form two consecutive line segments that are not tangent.
612
//Stop at points[i-1].
617
//The segment list is full.
621
//All points have been inserted.
622
return points.size()-1;
624
624
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
625
625
void FabAtHomePrinter::downloadSegmentList(Bay* bay, const bool startFlow, bool startSuckback, double pushoutDistance, double pushoutVelocity, double standardDistance, double standardVelocity, double suckbackDistance, double suckbackVelocity, const Point& suckbackPoint)
630
bay->motor->moveAbsolute(bay->motor->getCommandedPosition()-pushoutDistance,pushoutVelocity,PRINT_ACCELERATION); //Start pushout.
632
while(AddPathPoints() == -2) //Start movement.
637
bay->motor->waitMove(); //Wait for bay movement to finish.
638
bay->motor->moveAbsolute(bay->motor->getCommandedPosition()-standardDistance,standardVelocity,PRINT_ACCELERATION); //Start standard flow.
641
//Move points to the path pointer buffer while handling suckback.
642
while(AddPathPoints() != -1 || startSuckback)
646
xDiff = suckbackPoint.x - axes["X"].motor->getPosition();
647
yDiff = suckbackPoint.y - axes["Y"].motor->getPosition();
648
if(xDiff*xDiff+yDiff*yDiff < 0.25)
650
bay->motor->moveAbsolute(bay->motor->getCommandedPosition()+suckbackDistance,suckbackVelocity,PRINT_ACCELERATION); //Start suckback.
651
startSuckback = false;
630
bay->motor->moveAbsolute(bay->motor->getCommandedPosition()-pushoutDistance,pushoutVelocity,PRINT_ACCELERATION); //Start pushout.
632
while(AddPathPoints() == -2) //Start movement.
637
bay->motor->waitMove(); //Wait for bay movement to finish.
638
bay->motor->moveAbsolute(bay->motor->getCommandedPosition()-standardDistance,standardVelocity,PRINT_ACCELERATION); //Start standard flow.
641
//Move points to the path pointer buffer while handling suckback.
642
while(AddPathPoints() != -1 || startSuckback)
646
xDiff = suckbackPoint.x - axes["X"].motor->getPosition();
647
yDiff = suckbackPoint.y - axes["Y"].motor->getPosition();
648
if(xDiff*xDiff+yDiff*yDiff < 0.25)
650
bay->motor->moveAbsolute(bay->motor->getCommandedPosition()+suckbackDistance,suckbackVelocity,PRINT_ACCELERATION); //Start suckback.
651
startSuckback = false;
656
656
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
657
657
bool FabAtHomePrinter::cleanUp()
662
//Perform cleanup for all motors.
664
for(map<string,Motor,LessThanString>::iterator i = motors.begin(); i != motors.end(); ++i)
666
result = result && i->second.cleanUp();
662
//Perform cleanup for all motors.
664
for(map<string,Motor,LessThanString>::iterator i = motors.begin(); i != motors.end(); ++i)
666
result = result && i->second.cleanUp();
679
679
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
680
680
FabAtHomePrinter::~FabAtHomePrinter()
684
684
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
686
void FabAtHomePrinter::stopMotors()
689
axes["X"].motor->stop();
690
axes["Y"].motor->stop();
691
axes["Z"].motor->stop();
692
int numLoadedBays = this->numLoadedBays();
693
if(numLoadedBays >= 1)
695
tool.bays["Bay 0"].motor->stop();
697
if(numLoadedBays >= 2)
699
tool.bays["Bay 1"].motor->stop();
701
if(numLoadedBays >= 3)
703
tool.bays["Bay 2"].motor->stop();
707
void FabAtHomePrinter::resetPos()
709
//Reset position of all motors.
710
axes["X"].motor->resetPosition();
711
axes["Y"].motor->resetPosition();
712
axes["Z"].motor->resetPosition();
713
int numLoadedBays = this->numLoadedBays();
714
if(numLoadedBays >= 1)
716
tool.bays["Bay 0"].motor->resetPosition();
718
if(numLoadedBays >= 2)
720
tool.bays["Bay 1"].motor->resetPosition();
722
if(numLoadedBays >= 3)
724
tool.bays["Bay 2"].motor->resetPosition();