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.
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

Member Function Documentation

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 }


Member Data Documentation

cXMLElement* TurtleMobility::turtleScript [protected]

Referenced by gotoNextStatement(), and initialize().

cXMLElement* TurtleMobility::nextStatement [protected]

double TurtleMobility::speed [protected]

Referenced by executeStatement(), and initialize().

double TurtleMobility::angle [protected]

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


The documentation for this class was generated from the following files:

Generated on Fri Mar 20 18:51:22 2009 for INET Framework for OMNeT++/OMNEST by  doxygen 1.5.5