00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "TurtleMobility.h"
00020 #include "FWMath.h"
00021
00022
00023 Define_Module(TurtleMobility);
00024
00025
00031 void TurtleMobility::initialize(int stage)
00032 {
00033 LineSegmentsMobilityBase::initialize(stage);
00034
00035 debugEV << "initializing TurtleMobility stage " << stage << endl;
00036
00037 if(stage == 0)
00038 {
00039 turtleScript = par("turtleScript");
00040 nextStatement = turtleScript->getFirstChild();
00041
00042 move.setSpeed(1);
00043 angle = 0;
00044 borderPolicy = REFLECT;
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060 WATCH(angle);
00061 WATCH(borderPolicy);
00062 }
00063 else if(stage == 1){
00064 if(!world->use2D()) {
00065 opp_warning("This mobility module does not yet support 3 dimensional movement."\
00066 "Movements will probably be incorrect.");
00067 }
00068
00069 targetPos = move.getStartPos();
00070 stepTarget = move.getStartPos();
00071 targetTime = simTime();
00072 }
00073 }
00074
00075 void TurtleMobility::setTargetPosition()
00076 {
00077 resumeScript();
00078
00079 move.setStart(move.getStartPos(), simTime());
00080 }
00081
00082 void TurtleMobility::fixIfHostGetsOutside()
00083 {
00084 debugEV << "stepTarget: " << stepTarget.info() << " targetPos: " << targetPos.info() << " stepSize: " << stepSize.info()
00085 << " angle: " << angle << endl;
00086
00087 if( handleIfOutside(borderPolicy, stepTarget, targetPos, stepSize, angle) ){
00088
00089 debugEV << "stepTarget: " << stepTarget.info() << " targetPos: " << targetPos.info() << " stepSize: " << stepSize.info()
00090 << " angle: " << angle << endl;
00091
00092 }
00093 }
00094
00098 void TurtleMobility::resumeScript()
00099 {
00100 if (!nextStatement)
00101 {
00102 move.setSpeed(0);
00103 debugEV << "no statement found -> not moving!\n";
00104 return;
00105 }
00106
00107 simtime_t now = targetTime;
00108
00109
00110 while (nextStatement && targetTime==now)
00111 {
00112 executeStatement(nextStatement);
00113 gotoNextStatement();
00114 }
00115 }
00116
00117 void TurtleMobility::executeStatement(cXMLElement *stmt)
00118 {
00119 const char *tag = stmt->getTagName();
00120
00121 debugEV << "doing <" << tag << ">\n";
00122
00123 if (!strcmp(tag,"repeat"))
00124 {
00125 const char *nAttr = stmt->getAttribute("n");
00126 long n = -1;
00127 if (nAttr)
00128 {
00129 n = (long) getValue(nAttr);
00130 if (n<0)
00131 error("<repeat>: negative repeat count at %s", stmt->getSourceLocation());
00132 }
00133 loopVars.push(n);
00134 }
00135
00136
00137 else if (!strcmp(tag,"set"))
00138 {
00139 const char *speedAttr = stmt->getAttribute("speed");
00140 const char *angleAttr = stmt->getAttribute("angle");
00141 const char *xAttr = stmt->getAttribute("x");
00142 const char *yAttr = stmt->getAttribute("y");
00143 const char *bpAttr = stmt->getAttribute("borderPolicy");
00144 if (speedAttr)
00145 move.setSpeed(getValue(speedAttr));
00146 if (angleAttr)
00147 angle = getValue(angleAttr);
00148 if (xAttr)
00149 targetPos.setX(getValue(xAttr));
00150 if (yAttr)
00151 targetPos.setY(getValue(yAttr));
00152 if (move.getSpeed()<=0)
00153 error("<set>: speed is negative or zero at %s", stmt->getSourceLocation());
00154 if (bpAttr)
00155 {
00156 if (!strcmp(bpAttr,"reflect"))
00157 borderPolicy = REFLECT;
00158 else if (!strcmp(bpAttr,"wrap"))
00159 borderPolicy = WRAP;
00160 else if (!strcmp(bpAttr,"placerandomly"))
00161 borderPolicy = PLACERANDOMLY;
00162
00163 else if (!strcmp(bpAttr,"error"))
00164 borderPolicy = RAISEERROR;
00165 else
00166 error("<set>: value for attribute borderPolicy is invalid, should be "
00167 "'reflect', 'wrap', 'placerandomly' or 'error' at %s",
00168 stmt->getSourceLocation());
00169 }
00170 }
00171 else if (!strcmp(tag,"forward"))
00172 {
00173 const char *dAttr = stmt->getAttribute("d");
00174 const char *tAttr = stmt->getAttribute("t");
00175 if (!dAttr && !tAttr)
00176 error("<forward>: must have at least attribute 't' or 'd' (or both) at %s", stmt->getSourceLocation());
00177 double d, t;
00178 if (tAttr && dAttr)
00179 {
00180
00181 d = getValue(dAttr);
00182 t = getValue(tAttr);
00183 }
00184 else if (dAttr)
00185 {
00186
00187 d = getValue(dAttr);
00188 t = d / move.getSpeed();
00189 }
00190 else
00191 {
00192
00193 t = getValue(tAttr);
00194 d = move.getSpeed() * t;
00195 }
00196 if (t<0)
00197 error("<forward>: time (attribute t) is negative at %s", stmt->getSourceLocation());
00198 if (d<0)
00199 error("<forward>: distance (attribute d) is negative at %s", stmt->getSourceLocation());
00200
00201 targetPos.setX(targetPos.getX() + d * cos(PI * angle / 180));
00202 targetPos.setY(targetPos.getY() + d * sin(PI * angle / 180));
00203 targetTime += t;
00204 }
00205 else if (!strcmp(tag,"turn"))
00206 {
00207 const char *angleAttr = stmt->getAttribute("angle");
00208 if (!angleAttr)
00209 error("<turn>: required attribute 'angle' missing at %s", stmt->getSourceLocation());
00210 angle += getValue(angleAttr);
00211 }
00212 else if (!strcmp(tag,"wait"))
00213 {
00214 const char *tAttr = stmt->getAttribute("t");
00215 if (!tAttr)
00216 error("<wait>: required attribute 't' missing at %s", stmt->getSourceLocation());
00217 simtime_t t = getValue(tAttr);
00218 if (t<0)
00219 error("<wait>: time (attribute t) is negative (%s) at %s", SIMTIME_STR(t), stmt->getSourceLocation());
00220 targetTime += t;
00221 }
00222 else if (!strcmp(tag,"moveto"))
00223 {
00224 const char *xAttr = stmt->getAttribute("x");
00225 const char *yAttr = stmt->getAttribute("y");
00226 const char *tAttr = stmt->getAttribute("t");
00227
00228 if (xAttr)
00229 targetPos.setX(getValue(xAttr));
00230 if (yAttr)
00231 targetPos.setY(getValue(yAttr));
00232
00233 simtime_t t = tAttr ? getValue(tAttr) : move.getStartPos().distance(targetPos)/move.getSpeed();
00234 if (t<0)
00235 error("<wait>: time (attribute t) is negative at %s", stmt->getSourceLocation());
00236 targetTime += t;
00237 }
00238 else if (!strcmp(tag,"moveby"))
00239 {
00240 const char *xAttr = stmt->getAttribute("x");
00241 const char *yAttr = stmt->getAttribute("y");
00242 const char *tAttr = stmt->getAttribute("t");
00243 if (xAttr)
00244 targetPos.setX(targetPos.getX() + getValue(xAttr));
00245 if (yAttr)
00246 targetPos.setY(targetPos.getY() + getValue(yAttr));
00247
00248 simtime_t t = tAttr ? getValue(tAttr) : move.getStartPos().distance(targetPos)/move.getSpeed();
00249 if (t<0)
00250 error("<wait>: time (attribute t) is negative at %s", stmt->getSourceLocation());
00251 targetTime += t;
00252 }
00253 }
00254
00255 double TurtleMobility::getValue(const char *s)
00256 {
00257
00258 std::string str;
00259 if (strchr(s,'$'))
00260 {
00261 char strMaxX[32], strMaxY[32];
00262 sprintf(strMaxX, "%g", playgroundSizeX()-1);
00263 sprintf(strMaxY, "%g", playgroundSizeY()-1);
00264
00265 str = s;
00266 std::string::size_type pos;
00267 while ((pos = str.find("$MAXX")) != std::string::npos)
00268 str.replace(pos, sizeof("$MAXX")-1, strMaxX);
00269 while ((pos = str.find("$MAXY")) != std::string::npos)
00270 str.replace(pos, sizeof("$MAXY")-1, strMaxY);
00271 s = str.c_str();
00272 }
00273
00274
00275 cMsgPar tmp;
00276 if (!tmp.parse(s,'?'))
00277 error("wrong value '%s' around %s", s, nextStatement->getSourceLocation());
00278 return tmp.doubleValue();
00279 }
00280
00281 void TurtleMobility::gotoNextStatement()
00282 {
00283
00284 ASSERT(!nextStatement->getFirstChild() || (!strcmp(nextStatement->getTagName(),"repeat") && !loopVars.empty()));
00285
00286 if (nextStatement->getFirstChild() && (loopVars.top()!=0 || (loopVars.pop(),false)))
00287 {
00288
00289
00290 nextStatement = nextStatement->getFirstChild();
00291 }
00292 else if (!nextStatement->getNextSibling())
00293 {
00294
00295 ASSERT(nextStatement->getParentNode()==turtleScript ? loopVars.empty() : !loopVars.empty());
00296 if (!loopVars.empty())
00297 {
00298
00299 if (loopVars.top()!=-1)
00300 loopVars.top()--;
00301 if (loopVars.top()!=0)
00302 {
00303
00304 nextStatement = nextStatement->getParentNode()->getFirstChild();
00305 }
00306 else
00307 {
00308
00309 nextStatement = nextStatement->getParentNode();
00310 gotoNextStatement();
00311 }
00312 }
00313 else
00314 {
00315
00316 nextStatement = NULL;
00317 }
00318 }
00319 else
00320
00321 {
00322
00323 nextStatement = nextStatement->getNextSibling();
00324 }
00325 }
00326
00327