~jil26/fabinterpreter/Qt_version

« back to all changes in this revision

Viewing changes to software/FabInterpreter/FabAtHomePrinter.cpp

  • Committer: Jeremy Cohen
  • Date: 2010-07-16 20:20:34 UTC
  • Revision ID: jeremyrcohen@gmail.com-20100716202034-nsdz43xg4r9hyhqh
Added signal/slot implementation. Still need to implement threads

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
 
3
3
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
4
4
FabAtHomePrinter::FabAtHomePrinter():
5
 
pausePrintFlag(false),
6
 
cancelPrintFlag(false),
7
 
redoPathFlag(false),
8
 
initialized(false),
9
 
printing(false),
10
 
paused(false)
 
5
        pausePrintFlag(false),
 
6
        cancelPrintFlag(false),
 
7
        redoPathFlag(false),
 
8
        initialized(false),
 
9
        printing(false),
 
10
        paused(false)
11
11
{
12
12
}
13
13
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
14
14
string FabAtHomePrinter::initialize(const string& filePath)
15
15
{
16
 
        if(!initialized)
17
 
        {
18
 
          string result = loadConfigFile(filePath);
19
 
          if(result.compare("") != 0)
20
 
          {
21
 
               return result;
22
 
          }
23
 
 
24
 
          //Connect to printer.
25
 
                stringstream ss;
26
 
                ss << "COM" << COM_PORT;
27
 
                unsigned int numModulesFound = NmcInit(const_cast<char*>(ss.str().c_str()), BAUD_RATE);
28
 
                if(numModulesFound < NUM_MODULES)
29
 
                {
30
 
                        ss.str("");
31
 
                        ss << "Found " << numModulesFound << " modules but need " << NUM_MODULES << " modules.";
32
 
                        return ss.str();
33
 
                }
34
 
          
35
 
          //Initialize all motors.
36
 
                for(map<string,Motor,LessThanString>::iterator i = motors.begin(); i != motors.end(); ++i)
37
 
                {
38
 
                        string result = i->second.initialize();
39
 
                        Util::assertTrue(result.compare("") == 0,result,__LINE__,__FILE__); 
40
 
                }
41
 
          
42
 
 
43
 
                initialized = true;
44
 
        }
45
 
        return "";
 
16
    if(!initialized)
 
17
    {
 
18
        string result = loadConfigFile(filePath);
 
19
        if(result.compare("") != 0)
 
20
        {
 
21
            return result;
 
22
        }
 
23
 
 
24
        //Connect to printer.
 
25
        stringstream ss;
 
26
        ss << "COM" << COM_PORT;
 
27
        unsigned int numModulesFound = NmcInit(const_cast<char*>(ss.str().c_str()), BAUD_RATE);
 
28
        if(numModulesFound < NUM_MODULES)
 
29
        {
 
30
            ss.str("");
 
31
            ss << "Found " << numModulesFound << " modules but need " << NUM_MODULES << " modules.";
 
32
            return ss.str();
 
33
        }
 
34
 
 
35
        //Initialize all motors.
 
36
        for(map<string,Motor,LessThanString>::iterator i = motors.begin(); i != motors.end(); ++i)
 
37
        {
 
38
            string result = i->second.initialize();
 
39
            Util::assertTrue(result.compare("") == 0,result,__LINE__,__FILE__);
 
40
        }
 
41
 
 
42
 
 
43
        initialized = true;
 
44
    }
 
45
    return "";
46
46
}
47
47
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
48
48
void FabAtHomePrinter::pausePrint()
49
49
{
50
 
        pausePrintFlag = true;
 
50
    pausePrintFlag = true;
51
51
}
52
52
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
53
53
void FabAtHomePrinter::cancelPrint()
54
54
{
55
 
        cancelPrintFlag = true;
 
55
    cancelPrintFlag = true;
56
56
}
57
57
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
58
58
void FabAtHomePrinter::redoPath()
59
59
{
60
 
        redoPathFlag = true;
 
60
    redoPathFlag = true;
61
61
}
62
62
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
63
63
void FabAtHomePrinter::equipBay(const string& bayName, const string& materialCalibrationName)
64
64
{
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;
70
70
}
71
71
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
72
72
int FabAtHomePrinter::numLoadedPaths()
73
73
{
74
 
        return model.paths.size();
 
74
    return model.paths.size();
75
75
}
76
76
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
77
77
int FabAtHomePrinter::numLoadedBays()
78
78
{
79
 
        return tool.bays.size();
 
79
    return tool.bays.size();
80
80
}
81
81
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
82
82
bool FabAtHomePrinter::initializePathMode()
83
83
{
84
 
        SetTangentTolerance(180.0f); //180.0f allows all angles.
85
 
        SetOrigin(0.0f, 0.0f, 0.0f);
86
 
        
87
 
     //aReset position of all motors.
88
 
     for(map<string,Motor,LessThanString>::iterator i = motors.begin(); i != motors.end(); ++i)
89
 
     {
90
 
          i->second.resetPosition();
91
 
     }
92
 
 
93
 
        return
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)
97
 
                && SetPathParams2
98
 
                (
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(),
104
 
                X_Y_Z_GROUP_ADDRESS,
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
110
 
                ) == 0;
 
84
    SetTangentTolerance(180.0f); //180.0f allows all angles.
 
85
    SetOrigin(0.0f, 0.0f, 0.0f);
 
86
 
 
87
    //aReset position of all motors.
 
88
    for(map<string,Motor,LessThanString>::iterator i = motors.begin(); i != motors.end(); ++i)
 
89
    {
 
90
        i->second.resetPosition();
 
91
    }
 
92
 
 
93
    return
 
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)
 
97
            && SetPathParams2
 
98
            (
 
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(),
 
104
                    X_Y_Z_GROUP_ADDRESS,
 
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
 
110
                    ) == 0;
111
111
}
112
112
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
113
113
string FabAtHomePrinter::loadConfigFile(string filePath)
114
114
{
115
 
     //Clear previously loaded data.
116
 
     axes.clear(); 
117
 
     motors.clear();
118
 
     tool.bays.clear();
119
 
 
120
 
     XMLParser parser;
121
 
     string result = parser.load(filePath);
122
 
     if(result.compare("") != 0)
123
 
     {
124
 
          return result;
125
 
     }
126
 
 
127
 
     //Load constants.
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"));
134
 
     
135
 
     //Load motors.
136
 
     unsigned int count = parser.count("fabAtHomePrinter 0\\electronics 0\\motor");
137
 
     for(unsigned int i = 0; i < count; ++i)
138
 
     {
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);
154
 
     }
155
 
     
156
 
     //Load axes.
157
 
     count = parser.count("fabAtHomePrinter 0\\axis");
158
 
     for(unsigned int i = 0; i < count; ++i)
159
 
     {
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())
164
 
          {
165
 
               return "Axis "+name+" references motor "+motorName+" which has not been loaded.";
166
 
          }
167
 
          axes[name] = Axis(name,&(motors.find(motorName)->second));
168
 
     }
169
 
 
170
 
     //Check that axes named X, Y, and Z were loaded.
171
 
     if(axes.find("X") == axes.end())
172
 
     {
173
 
          return "Must load an axis named X.";
174
 
     }
175
 
     if(axes.find("Y") == axes.end())
176
 
     {
177
 
          return "Must load an axis named Y.";
178
 
     }
179
 
     if(axes.find("Z") == axes.end())
180
 
     {
181
 
          return "Must load an axis named Z.";
182
 
     }
183
 
 
184
 
     //Load bays.
185
 
     count = parser.count("fabAtHomePrinter 0\\tool 0\\bay");
186
 
     for(unsigned int i = 0; i < count; ++i)
187
 
     {
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())
192
 
          {
193
 
               return "Bay "+name+" references motor "+motorName+" which has not been loaded.";
194
 
          }          
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));
199
 
     }
200
 
 
201
 
     //Check that at least one bay is loaded.
202
 
     if(tool.bays.size() == 0)
203
 
     {
204
 
          return "Must load at least one bay.";
205
 
     }
206
 
 
207
 
     return "";
 
115
    //Clear previously loaded data.
 
116
    axes.clear();
 
117
    motors.clear();
 
118
    tool.bays.clear();
 
119
 
 
120
    XMLParser parser;
 
121
    string result = parser.load(filePath);
 
122
    if(result.compare("") != 0)
 
123
    {
 
124
        return result;
 
125
    }
 
126
 
 
127
    //Load constants.
 
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"));
 
134
 
 
135
    //Load motors.
 
136
    unsigned int count = parser.count("fabAtHomePrinter 0\\electronics 0\\motor");
 
137
    for(unsigned int i = 0; i < count; ++i)
 
138
    {
 
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);
 
154
    }
 
155
 
 
156
    //Load axes.
 
157
    count = parser.count("fabAtHomePrinter 0\\axis");
 
158
    for(unsigned int i = 0; i < count; ++i)
 
159
    {
 
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())
 
164
        {
 
165
            return "Axis "+name+" references motor "+motorName+" which has not been loaded.";
 
166
        }
 
167
        axes[name] = Axis(name,&(motors.find(motorName)->second));
 
168
    }
 
169
 
 
170
    //Check that axes named X, Y, and Z were loaded.
 
171
    if(axes.find("X") == axes.end())
 
172
    {
 
173
        return "Must load an axis named X.";
 
174
    }
 
175
    if(axes.find("Y") == axes.end())
 
176
    {
 
177
        return "Must load an axis named Y.";
 
178
    }
 
179
    if(axes.find("Z") == axes.end())
 
180
    {
 
181
        return "Must load an axis named Z.";
 
182
    }
 
183
 
 
184
    //Load bays.
 
185
    count = parser.count("fabAtHomePrinter 0\\tool 0\\bay");
 
186
    for(unsigned int i = 0; i < count; ++i)
 
187
    {
 
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())
 
192
        {
 
193
            return "Bay "+name+" references motor "+motorName+" which has not been loaded.";
 
194
        }
 
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));
 
199
    }
 
200
 
 
201
    //Check that at least one bay is loaded.
 
202
    if(tool.bays.size() == 0)
 
203
    {
 
204
        return "Must load at least one bay.";
 
205
    }
 
206
 
 
207
    return "";
208
208
}
209
209
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
210
210
string FabAtHomePrinter::loadFabFile(string filePath)
211
211
{
212
 
      //Load the file.
213
 
         TiXmlDocument file;
214
 
         if(!file.LoadFile(filePath.c_str()))
215
 
         {
216
 
                return "Could not interpret "+filePath+" as a xml file.";
217
 
      }
218
 
 
219
 
     //Clear previously loaded data.
220
 
        materialCalibrations.clear();
221
 
        model.paths.clear();
222
 
 
223
 
     TiXmlNode* root(file.RootElement());
224
 
        for(TiXmlNode* child = root->FirstChild(); child != NULL; child = root->IterateChildren(child))
225
 
        {
226
 
                if(strcmp(child->Value(), "materialCalibration") == 0)
227
 
                {
228
 
                        loadMaterialCalibration(child);
229
 
                }
230
 
                else if(strcmp(child->Value(), "path") == 0)
231
 
                {
232
 
                        loadPath(child);
233
 
                }
234
 
          else if(strcmp(child->Value(), "printAcceleration") == 0)
235
 
          {
236
 
               PRINT_ACCELERATION = Util::assertType<double>(child->FirstChild()->Value());
237
 
          }
238
 
        }
239
 
         
240
 
     return "";
241
 
 
242
 
     /*     
 
212
    //Load the file.
 
213
    TiXmlDocument file;
 
214
    if(!file.LoadFile(filePath.c_str()))
 
215
    {
 
216
        return "Could not interpret "+filePath+" as a xml file.";
 
217
    }
 
218
 
 
219
    //Clear previously loaded data.
 
220
    materialCalibrations.clear();
 
221
    model.paths.clear();
 
222
 
 
223
    TiXmlNode* root(file.RootElement());
 
224
    for(TiXmlNode* child = root->FirstChild(); child != NULL; child = root->IterateChildren(child))
 
225
    {
 
226
        if(strcmp(child->Value(), "materialCalibration") == 0)
 
227
        {
 
228
            loadMaterialCalibration(child);
 
229
        }
 
230
        else if(strcmp(child->Value(), "path") == 0)
 
231
        {
 
232
            loadPath(child);
 
233
        }
 
234
        else if(strcmp(child->Value(), "printAcceleration") == 0)
 
235
        {
 
236
            PRINT_ACCELERATION = Util::assertType<double>(child->FirstChild()->Value());
 
237
        }
 
238
    }
 
239
 
 
240
    return "";
 
241
 
 
242
    /*
243
243
     XMLParser parser;
244
244
     string result = parser.load(filePath);
245
245
     if(result.compare("") != 0)
246
246
     {
247
247
          return result;
248
248
     }
249
 
   
 
249
 
250
250
        //Clear previously loaded data.
251
251
        materialCalibrations.clear();
252
252
        model.paths.clear();
296
296
     
297
297
     return "";
298
298
     */
299
 
     
 
299
 
300
300
}
301
301
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
302
302
bool FabAtHomePrinter::isPrinting()
303
303
{
304
 
     return printing;
 
304
    return printing;
305
305
}
306
306
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
307
307
bool FabAtHomePrinter::isPaused()
308
308
{
309
 
     return paused;
 
309
    return paused;
310
310
}
311
311
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
312
312
void FabAtHomePrinter::loadedMaterialCalibrations(vector<string>& result)
313
313
{
314
 
     for(map<string,MaterialCalibration,LessThanString>::iterator i = materialCalibrations.begin(); i != materialCalibrations.end(); ++i)
315
 
     {
316
 
          result.push_back(i->first);
317
 
     }
 
314
    for(map<string,MaterialCalibration,LessThanString>::iterator i = materialCalibrations.begin(); i != materialCalibrations.end(); ++i)
 
315
    {
 
316
        result.push_back(i->first);
 
317
    }
318
318
}
319
319
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
320
320
string FabAtHomePrinter::loadMaterialCalibration(TiXmlNode* node)
321
321
{
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);
333
 
     return "";
 
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);
 
333
    return "";
334
334
}
335
335
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
336
336
string FabAtHomePrinter::loadPath(TiXmlNode* node)
337
337
{
338
 
        vector<Point> points;
339
 
        string materialCalibrationName = node->FirstChild("materialCalibrationName")->FirstChild()->Value();
340
 
        if(materialCalibrations.find(materialCalibrationName) == materialCalibrations.end())
341
 
     {
342
 
          return "A path references material calibration "+materialCalibrationName+" which has not been loaded.";
343
 
     }
344
 
     for(TiXmlNode* child = node->FirstChild(); child != NULL; child = node->IterateChildren(child))
345
 
        {
346
 
                if(strcmp(child->Value(), "point") == 0)
347
 
                {
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));
352
 
                }
353
 
        }
354
 
        model.paths.push_back(Path(&materialCalibrations[materialCalibrationName],points));
355
 
        return "";
 
338
    vector<Point> points;
 
339
    string materialCalibrationName = node->FirstChild("materialCalibrationName")->FirstChild()->Value();
 
340
    if(materialCalibrations.find(materialCalibrationName) == materialCalibrations.end())
 
341
    {
 
342
        return "A path references material calibration "+materialCalibrationName+" which has not been loaded.";
 
343
    }
 
344
    for(TiXmlNode* child = node->FirstChild(); child != NULL; child = node->IterateChildren(child))
 
345
    {
 
346
        if(strcmp(child->Value(), "point") == 0)
 
347
        {
 
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));
 
352
        }
 
353
    }
 
354
    model.paths.push_back(Path(&materialCalibrations[materialCalibrationName],points));
 
355
    return "";
356
356
}
357
357
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
358
358
Bay* FabAtHomePrinter::findBay(MaterialCalibration* materialCalibration)
359
359
{
360
 
     for(map<string,Bay,LessThanString>::iterator i = tool.bays.begin(); i != tool.bays.end(); ++i)
361
 
     {
362
 
          if(materialCalibration == i->second.materialCalibration)
363
 
          {
364
 
               return &(i->second);
365
 
          }
366
 
     }
367
 
     return NULL;
 
360
    for(map<string,Bay,LessThanString>::iterator i = tool.bays.begin(); i != tool.bays.end(); ++i)
 
361
    {
 
362
        if(materialCalibration == i->second.materialCalibration)
 
363
        {
 
364
            return &(i->second);
 
365
        }
 
366
    }
 
367
    return NULL;
368
368
}
369
369
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
370
370
void FabAtHomePrinter::executePausePath(const Point& start)
371
371
{
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);
378
 
     paused = true;
379
 
     Util::messageBox("Execution has been paused.  Press OK to resume execution.");
380
 
     paused = false;
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);
 
378
    paused = true;
 
379
    Util::messageBox("Execution has been paused.  Press OK to resume execution.");
 
380
    paused = false;
 
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);
386
386
}
387
387
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
388
388
void FabAtHomePrinter::executeSetupPath(const Point& start, const Point& end, const double& clearance)
389
389
{
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);
397
397
}
398
398
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
399
399
/*
440
440
                        displayText = "Executing setup path.";
441
441
                        fabricationThread->ReportProgress(i);
442
442
                }
443
 
         
 
443
 
444
444
        //Move from the current position to the beginning of the current path.
445
445
                Point start(axes["X"].motor->getPosition(), axes["Y"].motor->getPosition(), axes["Z"].motor->getPosition()); //The current position.
446
446
          Point end = path.points[0]; //The first point of the current path.
447
447
          executeSetupPath(start, end, path.materialCalibration->CLEARANCE);
448
 
        
 
448
 
449
449
          //Update the display text.
450
450
                if(fabricationThread != NULL)
451
451
                {
511
511
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
512
512
void FabAtHomePrinter::executePath(const Path& path, Bay* bay, const bool flowDuringPath)
513
513
{
514
 
     if(flowDuringPath)
515
 
     {
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.
522
 
             if(pathdur < ssDur)
523
 
             {
524
 
                     scaledPathSpeed *= pathdur/ssDur;
525
 
             }
526
 
 
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;
537
 
          
538
 
          //Calculate where suckback begins.
539
 
             Point suckbackPoint;
540
 
             if(pathLengthWithoutSuckback >= path.length)
541
 
             {
542
 
                     suckbackPoint = path.points[path.points.size()-1];
543
 
             }
544
 
             else
545
 
             {
546
 
                     double beforeSuckbackLength = 0;
547
 
                     vector<Point>::const_iterator i = path.points.begin();
548
 
                     for(; beforeSuckbackLength + Point::calcDist(*i, *(i+1)) <= pathLengthWithoutSuckback; ++i)
549
 
                     {
550
 
                             beforeSuckbackLength += Point::calcDist(*i, *(i+1));
551
 
                     }
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);
558
 
             }
559
 
 
560
 
          //Execute the path.
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();
 
514
    if(flowDuringPath)
 
515
    {
 
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.
 
522
        if(pathdur < ssDur)
 
523
        {
 
524
            scaledPathSpeed *= pathdur/ssDur;
 
525
        }
 
526
 
 
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;
 
537
 
 
538
        //Calculate where suckback begins.
 
539
        Point suckbackPoint;
 
540
        if(pathLengthWithoutSuckback >= path.length)
 
541
        {
 
542
            suckbackPoint = path.points[path.points.size()-1];
 
543
        }
 
544
        else
 
545
        {
 
546
            double beforeSuckbackLength = 0;
 
547
            vector<Point>::const_iterator i = path.points.begin();
 
548
            for(; beforeSuckbackLength + Point::calcDist(*i, *(i+1)) <= pathLengthWithoutSuckback; ++i)
 
549
            {
 
550
                beforeSuckbackLength += Point::calcDist(*i, *(i+1));
 
551
            }
 
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);
 
558
        }
 
559
 
 
560
        //Execute the path.
 
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.
568
 
     }
569
 
     else
570
 
     {
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();
578
 
     }
 
567
        bay->motor->waitMove(); //Wait for bay movement to finish.
 
568
    }
 
569
    else
 
570
    {
 
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();
 
578
    }
579
579
}
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)
582
582
{
583
 
        int currIndex = 0;
584
 
        int res = -1;
585
 
     bool flowStarted = false;
586
 
        while(res != points.size()-1)
587
 
        {
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.
595
 
                currIndex = res;
596
 
        }
 
583
    int currIndex = 0;
 
584
    int res = -1;
 
585
    bool flowStarted = false;
 
586
    while(res != points.size()-1)
 
587
    {
 
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.
 
595
        currIndex = res;
 
596
    }
597
597
}
598
598
////////////////////////////////////////////////////////////////////////////////////////////////////////////////                
599
599
int FabAtHomePrinter::fillSegmentList(const vector<Point>& points, const int startIndex)
600
600
{
601
 
        if(points.size() == 0)
602
 
        {
603
 
                return -1;
604
 
        }
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)
607
 
        {
608
 
                int res = AddLineSeg((float)points[i].x, (float)points[i].y, (float)points[i].z);
609
 
                if(res == -1)
610
 
                {
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].
613
 
               return i-1;
614
 
                }
615
 
                if(res == -2)
616
 
                {
617
 
                        //The segment list is full.
618
 
                        return i-1;
619
 
                }
620
 
        }
621
 
        //All points have been inserted.
622
 
        return points.size()-1;
 
601
    if(points.size() == 0)
 
602
    {
 
603
        return -1;
 
604
    }
 
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)
 
607
    {
 
608
        int res = AddLineSeg((float)points[i].x, (float)points[i].y, (float)points[i].z);
 
609
        if(res == -1)
 
610
        {
 
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].
 
613
            return i-1;
 
614
        }
 
615
        if(res == -2)
 
616
        {
 
617
            //The segment list is full.
 
618
            return i-1;
 
619
        }
 
620
    }
 
621
    //All points have been inserted.
 
622
    return points.size()-1;
623
623
}
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)
626
626
{
627
 
     InitPath();
628
 
     if(startFlow)
629
 
     {
630
 
          bay->motor->moveAbsolute(bay->motor->getCommandedPosition()-pushoutDistance,pushoutVelocity,PRINT_ACCELERATION); //Start pushout.
631
 
     }
632
 
     while(AddPathPoints() == -2) //Start movement.
633
 
     {
634
 
     }
635
 
     if(startFlow)
636
 
     {
637
 
          bay->motor->waitMove(); //Wait for bay movement to finish.
638
 
          bay->motor->moveAbsolute(bay->motor->getCommandedPosition()-standardDistance,standardVelocity,PRINT_ACCELERATION); //Start standard flow.
639
 
     }
640
 
     double xDiff, yDiff;
641
 
     //Move points to the path pointer buffer while handling suckback.
642
 
     while(AddPathPoints() != -1 || startSuckback)
643
 
        {
644
 
          if(startSuckback)
645
 
          {
646
 
               xDiff = suckbackPoint.x - axes["X"].motor->getPosition();
647
 
               yDiff = suckbackPoint.y - axes["Y"].motor->getPosition();
648
 
               if(xDiff*xDiff+yDiff*yDiff < 0.25)
649
 
               {
650
 
                    bay->motor->moveAbsolute(bay->motor->getCommandedPosition()+suckbackDistance,suckbackVelocity,PRINT_ACCELERATION); //Start suckback.
651
 
                    startSuckback = false;
652
 
               }
653
 
          }
654
 
        }
 
627
    InitPath();
 
628
    if(startFlow)
 
629
    {
 
630
        bay->motor->moveAbsolute(bay->motor->getCommandedPosition()-pushoutDistance,pushoutVelocity,PRINT_ACCELERATION); //Start pushout.
 
631
    }
 
632
    while(AddPathPoints() == -2) //Start movement.
 
633
    {
 
634
    }
 
635
    if(startFlow)
 
636
    {
 
637
        bay->motor->waitMove(); //Wait for bay movement to finish.
 
638
        bay->motor->moveAbsolute(bay->motor->getCommandedPosition()-standardDistance,standardVelocity,PRINT_ACCELERATION); //Start standard flow.
 
639
    }
 
640
    double xDiff, yDiff;
 
641
    //Move points to the path pointer buffer while handling suckback.
 
642
    while(AddPathPoints() != -1 || startSuckback)
 
643
    {
 
644
        if(startSuckback)
 
645
        {
 
646
            xDiff = suckbackPoint.x - axes["X"].motor->getPosition();
 
647
            yDiff = suckbackPoint.y - axes["Y"].motor->getPosition();
 
648
            if(xDiff*xDiff+yDiff*yDiff < 0.25)
 
649
            {
 
650
                bay->motor->moveAbsolute(bay->motor->getCommandedPosition()+suckbackDistance,suckbackVelocity,PRINT_ACCELERATION); //Start suckback.
 
651
                startSuckback = false;
 
652
            }
 
653
        }
 
654
    }
655
655
}
656
656
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
657
657
bool FabAtHomePrinter::cleanUp()
658
658
{
659
 
        bool result;
660
 
        if(initialized)
661
 
        {
662
 
          //Perform cleanup for all motors.
663
 
          bool result = true;
664
 
          for(map<string,Motor,LessThanString>::iterator i = motors.begin(); i != motors.end(); ++i)
665
 
                {
666
 
                        result = result && i->second.cleanUp();
667
 
                }
668
 
                if(result)
669
 
                {
670
 
                        initialized = false;
671
 
                }
672
 
        }
673
 
        else
674
 
        {
675
 
                result = true;
676
 
        }
677
 
        return result;
 
659
    bool result;
 
660
    if(initialized)
 
661
    {
 
662
        //Perform cleanup for all motors.
 
663
        bool result = true;
 
664
        for(map<string,Motor,LessThanString>::iterator i = motors.begin(); i != motors.end(); ++i)
 
665
        {
 
666
            result = result && i->second.cleanUp();
 
667
        }
 
668
        if(result)
 
669
        {
 
670
            initialized = false;
 
671
        }
 
672
    }
 
673
    else
 
674
    {
 
675
        result = true;
 
676
    }
 
677
    return result;
678
678
}
679
679
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
680
680
FabAtHomePrinter::~FabAtHomePrinter()
681
681
{
682
 
     cleanUp();
 
682
    cleanUp();
683
683
}
684
684
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
685
 
 
686
void FabAtHomePrinter::stopMotors()
 
687
{
 
688
    //Stop all motors.
 
689
    axes["X"].motor->stop();
 
690
    axes["Y"].motor->stop();
 
691
    axes["Z"].motor->stop();
 
692
    int numLoadedBays = this->numLoadedBays();
 
693
    if(numLoadedBays >= 1)
 
694
    {
 
695
        tool.bays["Bay 0"].motor->stop();
 
696
    }
 
697
    if(numLoadedBays >= 2)
 
698
    {
 
699
        tool.bays["Bay 1"].motor->stop();
 
700
    }
 
701
    if(numLoadedBays >= 3)
 
702
    {
 
703
        tool.bays["Bay 2"].motor->stop();
 
704
    }
 
705
}
 
706
 
 
707
void FabAtHomePrinter::resetPos()
 
708
{
 
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)
 
715
    {
 
716
        tool.bays["Bay 0"].motor->resetPosition();
 
717
    }
 
718
    if(numLoadedBays >= 2)
 
719
    {
 
720
        tool.bays["Bay 1"].motor->resetPosition();
 
721
    }
 
722
    if(numLoadedBays >= 3)
 
723
    {
 
724
        tool.bays["Bay 2"].motor->resetPosition();
 
725
    }
 
726
}