#include <TurtleMobility.h>
Protected Member Functions | |
virtual void | initialize (int) |
Initializes mobility model parameters. | |
virtual void | setTargetPosition () |
Overridden from LineSegmentsMobilityBase. Invokes resumeScript(). | |
virtual void | fixIfHostGetsOutside () |
Overridden from LineSegmentsMobilityBase. | |
virtual void | resumeScript () |
Process next statements from script. | |
virtual void | executeStatement (cXMLElement *nextStatement) |
Execute the given statement. | |
virtual double | getValue (const char *s) |
Parse attrs in the script -- accepts things like "uniform(10,50) as well. | |
virtual void | gotoNextStatement () |
Advance nextStatement pointer. | |
Protected Attributes | |
cXMLElement * | turtleScript |
cXMLElement * | nextStatement |
double | speed |
double | angle |
BorderPolicy | borderPolicy |
std::stack< long > | loopVars |
void TurtleMobility::initialize | ( | int | stage | ) | [protected, virtual] |
Initializes mobility model parameters.
Reads the parameters. If the host is not stationary it calculates a random position and schedules a timer to trigger the first movement
Reimplemented from LineSegmentsMobilityBase.
00031 { 00032 LineSegmentsMobilityBase::initialize(stage); 00033 00034 EV << "initializing TurtleMobility stage " << stage << endl; 00035 00036 if (stage == 1) 00037 { 00038 turtleScript = par("turtleScript"); 00039 nextStatement = turtleScript->getFirstChild(); 00040 00041 speed = 1; 00042 angle = 0; 00043 borderPolicy = REFLECT; 00044 00045 // a dirty trick to extract starting position out of the script 00046 // (start doing it, but then rewind to the beginning) 00047 resumeScript(); 00048 targetPos = pos; 00049 targetTime = simTime(); 00050 nextStatement = turtleScript->getFirstChild(); 00051 while (!loopVars.empty()) loopVars.pop(); 00052 00053 updatePosition(); 00054 00055 WATCH(speed); 00056 WATCH(angle); 00057 //WATCH(borderPolicy); 00058 } 00059 }
void TurtleMobility::setTargetPosition | ( | ) | [protected, virtual] |
Overridden from LineSegmentsMobilityBase. Invokes resumeScript().
Implements LineSegmentsMobilityBase.
00062 { 00063 resumeScript(); 00064 }
void TurtleMobility::fixIfHostGetsOutside | ( | ) | [protected, virtual] |
Overridden from LineSegmentsMobilityBase.
Implements LineSegmentsMobilityBase.
00067 { 00068 handleIfOutside(borderPolicy, targetPos, step, angle); 00069 }
void TurtleMobility::resumeScript | ( | ) | [protected, virtual] |
Process next statements from script.
Will set a new targetTime and targetPos
Referenced by initialize(), and setTargetPosition().
00075 { 00076 if (!nextStatement) 00077 { 00078 stationary = true; 00079 return; 00080 } 00081 00082 simtime_t now = targetTime; 00083 00084 // interpret statement 00085 while (nextStatement && targetTime==now) 00086 { 00087 executeStatement(nextStatement); 00088 gotoNextStatement(); 00089 } 00090 }
void TurtleMobility::executeStatement | ( | cXMLElement * | nextStatement | ) | [protected, virtual] |
Execute the given statement.
Referenced by resumeScript().
00093 { 00094 const char *tag = stmt->getTagName(); 00095 00096 EV << "doing <" << tag << ">\n"; 00097 00098 if (!strcmp(tag,"repeat")) 00099 { 00100 const char *nAttr = stmt->getAttribute("n"); 00101 long n = -1; // infinity -- that's the default 00102 if (nAttr) 00103 { 00104 n = (long) getValue(nAttr); 00105 if (n<0) 00106 error("<repeat>: negative repeat count at %s", stmt->getSourceLocation()); 00107 } 00108 loopVars.push(n); 00109 } 00110 else if (!strcmp(tag,"set")) 00111 { 00112 const char *speedAttr = stmt->getAttribute("speed"); 00113 const char *angleAttr = stmt->getAttribute("angle"); 00114 const char *xAttr = stmt->getAttribute("x"); 00115 const char *yAttr = stmt->getAttribute("y"); 00116 const char *bpAttr = stmt->getAttribute("borderPolicy"); 00117 if (speedAttr) 00118 speed = getValue(speedAttr); 00119 if (angleAttr) 00120 angle = getValue(angleAttr); 00121 if (xAttr) 00122 targetPos.x = pos.x = getValue(xAttr); 00123 if (yAttr) 00124 targetPos.y = pos.y = getValue(yAttr); 00125 if (speed<=0) 00126 error("<set>: speed is negative or zero at %s", stmt->getSourceLocation()); 00127 if (bpAttr) 00128 { 00129 if (!strcmp(bpAttr,"reflect")) 00130 borderPolicy = REFLECT; 00131 else if (!strcmp(bpAttr,"wrap")) 00132 borderPolicy = WRAP; 00133 else if (!strcmp(bpAttr,"placerandomly")) 00134 borderPolicy = PLACERANDOMLY; 00135 else if (!strcmp(bpAttr,"error")) 00136 borderPolicy = RAISEERROR; 00137 else 00138 error("<set>: value for attribute borderPolicy is invalid, should be " 00139 "'reflect', 'wrap', 'placerandomly' or 'error' at %s", 00140 stmt->getSourceLocation()); 00141 } 00142 } 00143 else if (!strcmp(tag,"forward")) 00144 { 00145 const char *dAttr = stmt->getAttribute("d"); 00146 const char *tAttr = stmt->getAttribute("t"); 00147 if (!dAttr && !tAttr) 00148 error("<forward>: must have at least attribute 't' or 'd' (or both) at %s", stmt->getSourceLocation()); 00149 double d, t; 00150 if (tAttr && dAttr) 00151 { 00152 // cover distance d in time t (current speed is ignored) 00153 d = getValue(dAttr); 00154 t = getValue(tAttr); 00155 } 00156 else if (dAttr) 00157 { 00158 // travel distance d at current speed 00159 d = getValue(dAttr); 00160 t = d / speed; 00161 } 00162 else // tAttr only 00163 { 00164 // travel for time t at current speed 00165 t = getValue(tAttr); 00166 d = speed * t; 00167 } 00168 if (t<0) 00169 error("<forward>: time (attribute t) is negative at %s", stmt->getSourceLocation()); 00170 if (d<0) 00171 error("<forward>: distance (attribute d) is negative at %s", stmt->getSourceLocation()); 00172 // FIXME handle zeros properly... 00173 targetPos.x += d * cos(PI * angle / 180); 00174 targetPos.y += d * sin(PI * angle / 180); 00175 targetTime += t; 00176 } 00177 else if (!strcmp(tag,"turn")) 00178 { 00179 const char *angleAttr = stmt->getAttribute("angle"); 00180 if (!angleAttr) 00181 error("<turn>: required attribute 'angle' missing at %s", stmt->getSourceLocation()); 00182 angle += getValue(angleAttr); 00183 } 00184 else if (!strcmp(tag,"wait")) 00185 { 00186 const char *tAttr = stmt->getAttribute("t"); 00187 if (!tAttr) 00188 error("<wait>: required attribute 't' missing at %s", stmt->getSourceLocation()); 00189 double t = getValue(tAttr); 00190 if (t<0) 00191 error("<wait>: time (attribute t) is negative (%g) at %s", t, stmt->getSourceLocation()); 00192 targetTime += t; // targetPos is unchanged 00193 } 00194 else if (!strcmp(tag,"moveto")) 00195 { 00196 const char *xAttr = stmt->getAttribute("x"); 00197 const char *yAttr = stmt->getAttribute("y"); 00198 const char *tAttr = stmt->getAttribute("t"); 00199 if (xAttr) 00200 targetPos.x = getValue(xAttr); 00201 if (yAttr) 00202 targetPos.y = getValue(yAttr); 00203 // travel to targetPos at current speed, or get there in time t (ignoring current speed then) 00204 double t = tAttr ? getValue(tAttr) : pos.distance(targetPos)/speed; 00205 if (t<0) 00206 error("<wait>: time (attribute t) is negative at %s", stmt->getSourceLocation()); 00207 targetTime += t; 00208 } 00209 else if (!strcmp(tag,"moveby")) 00210 { 00211 const char *xAttr = stmt->getAttribute("x"); 00212 const char *yAttr = stmt->getAttribute("y"); 00213 const char *tAttr = stmt->getAttribute("t"); 00214 if (xAttr) 00215 targetPos.x += getValue(xAttr); 00216 if (yAttr) 00217 targetPos.y += getValue(yAttr); 00218 // travel to targetPos at current speed, or get there in time t (ignoring current speed then) 00219 double t = tAttr ? getValue(tAttr) : pos.distance(targetPos)/speed; 00220 if (t<0) 00221 error("<wait>: time (attribute t) is negative at %s", stmt->getSourceLocation()); 00222 targetTime += t; 00223 } 00224 }
double TurtleMobility::getValue | ( | const char * | s | ) | [protected, virtual] |
Parse attrs in the script -- accepts things like "uniform(10,50) as well.
Referenced by executeStatement().
00227 { 00228 // first, textually replace $MAXX and $MAXY with their actual values 00229 std::string str; 00230 if (strchr(s,'$')) 00231 { 00232 char strMaxX[32], strMaxY[32]; 00233 sprintf(strMaxX, "%g", getPlaygroundSizeX()-1); 00234 sprintf(strMaxY, "%g", getPlaygroundSizeY()-1); 00235 00236 str = s; 00237 std::string::size_type pos; 00238 while ((pos = str.find("$MAXX")) != std::string::npos) 00239 str.replace(pos, sizeof("$MAXX")-1, strMaxX); 00240 while ((pos = str.find("$MAXY")) != std::string::npos) 00241 str.replace(pos, sizeof("$MAXY")-1, strMaxY); 00242 s = str.c_str(); 00243 } 00244 00245 // then use cDynamicExpression to evaluate the string 00246 try { 00247 cDynamicExpression expr; 00248 expr.parse(s); 00249 return expr.doubleValue(this); 00250 } 00251 catch (std::exception& e) { 00252 throw cRuntimeError(this, "wrong value '%s' around %s: %s", s, nextStatement->getSourceLocation(), e.what()); 00253 } 00254 }
void TurtleMobility::gotoNextStatement | ( | ) | [protected, virtual] |
Advance nextStatement pointer.
Referenced by resumeScript().
00257 { 00258 // "statement either doesn't have a child, or it's a <repeat> and loop count is already pushed on the stack" 00259 ASSERT(!nextStatement->getFirstChild() || (!strcmp(nextStatement->getTagName(),"repeat") && !loopVars.empty())); 00260 00261 if (nextStatement->getFirstChild() && (loopVars.top()!=0 || (loopVars.pop(),false))) // !=0: positive or -1 00262 { 00263 // statement must be a <repeat> if it has children; repeat count>0 must be 00264 // on the stack; let's start doing the body. 00265 nextStatement = nextStatement->getFirstChild(); 00266 } 00267 else if (!nextStatement->getNextSibling()) 00268 { 00269 // no sibling -- either end of <repeat> body, or end of script 00270 ASSERT(nextStatement->getParentNode()==turtleScript ? loopVars.empty() : !loopVars.empty()); 00271 if (!loopVars.empty()) 00272 { 00273 // decrement and check loop counter 00274 if (loopVars.top()!=-1) // -1 means infinity 00275 loopVars.top()--; 00276 if (loopVars.top()!=0) // positive or -1 00277 { 00278 // go to beginning of <repeat> block again 00279 nextStatement = nextStatement->getParentNode()->getFirstChild(); 00280 } 00281 else 00282 { 00283 // end of loop -- locate next statement after the <repeat> 00284 nextStatement = nextStatement->getParentNode(); 00285 gotoNextStatement(); 00286 } 00287 } 00288 else 00289 { 00290 // end of script 00291 nextStatement = NULL; 00292 } 00293 } 00294 else 00295 { 00296 // go to next statement (must exist -- see "if" above) 00297 nextStatement = nextStatement->getNextSibling(); 00298 } 00299 }
cXMLElement* TurtleMobility::turtleScript [protected] |
Referenced by gotoNextStatement(), and initialize().
cXMLElement* TurtleMobility::nextStatement [protected] |
Referenced by getValue(), gotoNextStatement(), initialize(), and resumeScript().
double TurtleMobility::speed [protected] |
Referenced by executeStatement(), and initialize().
double TurtleMobility::angle [protected] |
Referenced by executeStatement(), fixIfHostGetsOutside(), and initialize().
BorderPolicy TurtleMobility::borderPolicy [protected] |
Referenced by executeStatement(), fixIfHostGetsOutside(), and initialize().
std::stack<long> TurtleMobility::loopVars [protected] |
Referenced by executeStatement(), gotoNextStatement(), and initialize().