Main Page | Namespace List | Class Hierarchy | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

TurtleMobility Class Reference

#include <TurtleMobility.h>

Inheritance diagram for TurtleMobility:

LineSegmentsMobilityBase BasicMobility BasicModule INotifiable List of all members.

Detailed Description

LOGO-style movement model, with the script coming from XML. See NED file for more info.

Author:
Andras Varga


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


Member Function Documentation

void TurtleMobility::executeStatement cXMLElement *  nextStatement  )  [protected]
 

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 }

void TurtleMobility::fixIfHostGetsOutside  )  [protected, virtual]
 

Overridden from LineSegmentsMobilityBase.

Implements LineSegmentsMobilityBase.

00068 {
00069     handleIfOutside(borderPolicy, targetPos, step, angle);
00070 }

double TurtleMobility::getValue const char *  s  )  [protected]
 

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 }

void TurtleMobility::gotoNextStatement  )  [protected]
 

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 }

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.

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 }

void TurtleMobility::resumeScript  )  [protected]
 

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 }

void TurtleMobility::setTargetPosition  )  [protected, virtual]
 

Overridden from LineSegmentsMobilityBase. Invokes resumeScript().

Implements LineSegmentsMobilityBase.

00063 {
00064     resumeScript();
00065 }


Member Data Documentation

double TurtleMobility::angle [protected]
 

BorderPolicy TurtleMobility::borderPolicy [protected]
 

std::stack<long> TurtleMobility::loopVars [protected]
 

cXMLElement* TurtleMobility::nextStatement [protected]
 

double TurtleMobility::speed [protected]
 

cXMLElement* TurtleMobility::turtleScript [protected]
 


The documentation for this class was generated from the following files:
Generated on Sat Apr 1 20:52:25 2006 for INET Framework for OMNeT++/OMNEST by  doxygen 1.4.1