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