ArRobot.cpp

00001 /*
00002 MobileRobots Advanced Robotics Interface for Applications (ARIA)
00003 Copyright (C) 2004,2005 ActivMedia Robotics LLC
00004 Copyright (C) 2006 MobileRobots, Inc.
00005 
00006      This program is free software; you can redistribute it and/or modify
00007      it under the terms of the GNU General Public License as published by
00008      the Free Software Foundation; either version 2 of the License, or
00009      (at your option) any later version.
00010 
00011      This program is distributed in the hope that it will be useful,
00012      but WITHOUT ANY WARRANTY; without even the implied warranty of
00013      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014      GNU General Public License for more details.
00015 
00016      You should have received a copy of the GNU General Public License
00017      along with this program; if not, write to the Free Software
00018      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 
00020 If you wish to redistribute ARIA under different terms, contact 
00021 MobileRobots for information about a commercial version of ARIA at 
00022 robots@mobilerobots.com or 
00023 MobileRobots Inc, 19 Columbia Drive, Amherst, NH 03031; 800-639-9481
00024 */
00025 
00026 #include "ArExport.h"
00027 #include "ariaOSDef.h"
00028 #include <time.h>
00029 #include <ctype.h>
00030 
00031 #include "ArRobot.h"
00032 #include "ArLog.h"
00033 #include "ArDeviceConnection.h"
00034 #include "ArTcpConnection.h"
00035 #include "ArSerialConnection.h"
00036 #include "ArLogFileConnection.h"
00037 #include "ariaUtil.h"
00038 #include "ArSocket.h"
00039 #include "ArCommands.h"
00040 #include "ArRobotTypes.h"
00041 #include "ArSignalHandler.h"
00042 #include "ArPriorityResolver.h"
00043 #include "ArAction.h"
00044 #include "ArRangeDevice.h"
00045 #include "ArRobotConfigPacketReader.h"
00046 #include "ariaInternal.h"
00047 
00069 AREXPORT ArRobot::ArRobot(const char *name, bool obsolete, 
00070               bool doSigHandle, bool normalInit,
00071               bool addAriaExitCallback) :
00072   myMotorPacketCB(this, &ArRobot::processMotorPacket),
00073   myEncoderPacketCB(this, &ArRobot::processEncoderPacket),
00074   myIOPacketCB(this, &ArRobot::processIOPacket),
00075   myPacketHandlerCB(this, &ArRobot::packetHandler),
00076   myActionHandlerCB(this, &ArRobot::actionHandler),
00077   myStateReflectorCB(this, &ArRobot::stateReflector),
00078   myRobotLockerCB(this, &ArRobot::robotLocker),
00079   myRobotUnlockerCB(this, &ArRobot::robotUnlocker),
00080   myKeyHandlerExitCB(this, &ArRobot::keyHandlerExit),
00081   myGetCycleWarningTimeCB(this, &ArRobot::getCycleWarningTime),
00082   myGetNoTimeWarningThisCycleCB(this, &ArRobot::getNoTimeWarningThisCycle),
00083   myBatteryAverager(20),
00084   myRealBatteryAverager(20),
00085   myAriaExitCB(this, &ArRobot::ariaExitCallback)
00086 {
00087   setName(name);
00088   myAriaExitCB.setName("ArRobotExit");
00089   myNoTimeWarningThisCycle = false;
00090   myGlobalPose.setPose(0, 0, 0);
00091 
00092   myParams = new ArRobotGeneric("");
00093 
00094   myMotorPacketCB.setName("ArRobot::motorPacket");
00095   myEncoderPacketCB.setName("ArRobot::encoderPacket");
00096   myIOPacketCB.setName("ArRobot::IOPacket");
00097 
00098   myPtz = NULL;
00099   myKeyHandler = NULL;
00100   myKeyHandlerCB = NULL;
00101 
00102   myConn = NULL;
00103 
00104   myOwnTheResolver = false;
00105 
00106   myBlockingConnectRun = false;
00107   myAsyncConnectFlag = false;
00108 
00109   myLogMovementSent = false;
00110   myLogMovementReceived = false;
00111   myLogVelocitiesReceived = false;
00112   myLogActions = false;
00113   myLastVel = 0;
00114   myLastRotVel = 0;
00115   myLastHeading = 0;
00116   myLastCalculatedRotVel = 0;
00117 
00118   myPacketsSentTracking = false;
00119   myPacketsReceivedTracking = false;
00120   myPacketsReceivedTrackingCount = false;
00121   myPacketsReceivedTrackingStarted.setToNow();
00122 
00123   myCycleTime = 100;
00124   myCycleWarningTime = 250;
00125   myConnectionCycleMultiplier = 2;
00126   myTimeoutTime = 8000;
00127   myStabilizingTime = 0;
00128   myCounter = 1;
00129   myResolver = NULL;
00130   myNumSonar = 0;
00131 
00132   myRequestedIOPackets = false;
00133   myRequestedEncoderPackets = false;
00134   myEncoderCorrectionCB = NULL;
00135 
00136   myCycleChained = true;
00137 
00138   myMoveDoneDist = 40;
00139   myHeadingDoneDiff = 3;
00140 
00141   myOrigRobotConfig = NULL;
00142   reset();
00143   if (normalInit)
00144     init();
00145   
00146   mySyncLoop.setRobot(this);
00147 
00148   if (doSigHandle)
00149     Aria::addRobot(this);
00150   if (addAriaExitCallback)
00151   {
00152     Aria::addExitCallback(&myAriaExitCB, 0);
00153     myAddedAriaExitCB = true;
00154   }
00155   else
00156   {
00157     myAddedAriaExitCB = false;
00158   }
00159 
00160   myConnectWithNoParams = false;
00161 }
00162 
00163 
00164 
00165 AREXPORT ArRobot::~ArRobot()
00166 {
00167   ArResolver::ActionMap::iterator it;
00168 
00169   stopRunning();
00170   delete mySyncTaskRoot;
00171   ArUtil::deleteSetPairs(mySonars.begin(), mySonars.end());
00172   Aria::delRobot(this);
00173 
00174   if (myKeyHandlerCB != NULL)
00175     delete myKeyHandlerCB;
00176 
00177   for (it = myActions.begin(); it != myActions.end(); ++it)
00178   {
00179     (*it).second->setRobot(NULL);
00180   }
00181 }
00182 
00183 
00188 AREXPORT void ArRobot::init(void)
00189 {
00190   setUpPacketHandlers();
00191   setUpSyncList();
00192   myOwnTheResolver = true;
00193   myResolver = new ArPriorityResolver;
00194 }
00195 
00206 AREXPORT void ArRobot::run(bool stopRunIfNotConnected)
00207 {
00208   if (mySyncLoop.getRunning())
00209   {
00210     ArLog::log(ArLog::Terse, 
00211            "The robot is already running, cannot run it again.");
00212     return;
00213   }
00214   mySyncLoop.setRunning(true);
00215   mySyncLoop.stopRunIfNotConnected(stopRunIfNotConnected);
00216   mySyncLoop.runInThisThread();
00217 }
00218 
00224 AREXPORT bool ArRobot::isRunning(void) const
00225 {
00226   return mySyncLoop.getRunning();
00227 }
00228 
00238 AREXPORT void ArRobot::runAsync(bool stopRunIfNotConnected)
00239 {
00240   if (mySyncLoop.getRunning())
00241   {
00242     ArLog::log(ArLog::Terse, 
00243            "The robot is already running, cannot run it again.");
00244     return;
00245   }
00246   mySyncLoop.stopRunIfNotConnected(stopRunIfNotConnected);
00247   // Joinable, but do NOT lower priority. The robot thread is the most
00248   // important one around.
00249   mySyncLoop.create(true, false);
00250 }
00251 
00260 AREXPORT void ArRobot::stopRunning(bool doDisconnect)
00261 {
00262   if (myKeyHandler != NULL)
00263     myKeyHandler->restore();
00264   mySyncLoop.stopRunning();
00265   myBlockingConnectRun = false;
00266   if (doDisconnect && (isConnected() || myIsStabilizing))
00267   {
00268     waitForRunExit();
00269     disconnect();
00270   }
00271   wakeAllWaitingThreads();
00272 }
00273 
00274 AREXPORT void ArRobot::setUpSyncList(void)
00275 {
00276   mySyncTaskRoot = new ArSyncTask("SyncTasks");
00277   mySyncTaskRoot->setWarningTimeCB(&myGetCycleWarningTimeCB);
00278   mySyncTaskRoot->setNoTimeWarningCB(&myGetNoTimeWarningThisCycleCB);
00279   mySyncTaskRoot->addNewLeaf("Packet Handler", 85, &myPacketHandlerCB);
00280   mySyncTaskRoot->addNewLeaf("Robot Locker", 70, &myRobotLockerCB);
00281   mySyncTaskRoot->addNewBranch("Sensor Interp", 65);
00282   mySyncTaskRoot->addNewLeaf("Action Handler", 55, &myActionHandlerCB);
00283   mySyncTaskRoot->addNewLeaf("State Reflector", 45, &myStateReflectorCB);
00284   mySyncTaskRoot->addNewBranch("User Tasks", 25);
00285   mySyncTaskRoot->addNewLeaf("Robot Unlocker", 20, &myRobotUnlockerCB);
00286 }
00287 
00288 
00289 AREXPORT void ArRobot::setUpPacketHandlers(void)
00290 {
00291   addPacketHandler(&myMotorPacketCB, ArListPos::FIRST);
00292   addPacketHandler(&myEncoderPacketCB, ArListPos::LAST);
00293   addPacketHandler(&myIOPacketCB, ArListPos::LAST);
00294 }
00295 
00296 void ArRobot::reset(void)
00297 {
00298   resetOdometer();
00299   myInterpolation.reset();
00300   myEncoderInterpolation.reset();
00301   if (myOrigRobotConfig != NULL)
00302     delete myOrigRobotConfig;
00303   myOrigRobotConfig = new ArRobotConfigPacketReader(this, true);
00304   myFirstEncoderPose = true;
00305   //myEncoderPose.setPose(0, 0, 0);
00306   //myEncoderPoseTaken.setToNow();
00307   //myRawEncoderPose.setPose(0, 0, 0);
00308   //myGlobalPose.setPose(0, 0, 0);
00309   //myEncoderTransform.setTransform(myEncoderPose, myGlobalPose);
00310   myTransVelMax = 0;
00311   myTransAccel = 0;
00312   myTransDecel = 0;
00313   myRotVelMax = 0;
00314   myRotAccel = 0;
00315   myRotDecel = 0;
00316 
00317   myRobotLengthFront = 0;
00318   myRobotLengthRear = 0;
00319 
00320   myLeftVel = 0;
00321   myRightVel = 0;
00322   myBatteryVoltage = 13;
00323   myBatteryAverager.clear();
00324   myBatteryAverager.add(myBatteryVoltage);
00325   myStallValue = 0;
00326   myControl = 0;
00327   myFlags = 0;
00328   myFaultFlags = 0;
00329   myHasFaultFlags = 0;
00330   myCompass = 0;
00331   myAnalogPortSelected = 0;
00332   myAnalog = 0;
00333   myDigIn = 0;
00334   myDigOut = 0;
00335   myIOAnalogSize = 0;
00336   myIODigInSize = 0;
00337   myIODigOutSize = 0;
00338   myLastIOPacketReceivedTime.setSec(0);
00339   myLastIOPacketReceivedTime.setMSec(0);
00340   myVel = 0;
00341   myRotVel = 0;
00342   myChargeState = CHARGING_UNKNOWN;
00343   myLastX = 0;
00344   myLastY = 0;
00345   myLastTh = 0;
00346   mySentPulse = false;
00347   myIsConnected = false;
00348   myIsStabilizing = false;
00349 
00350   myTransVal = 0;
00351   myTransVal2 = 0;
00352   myTransType = TRANS_NONE;
00353   myLastTransVal = 0;
00354   myLastTransVal2 = 0;
00355   myLastTransType = TRANS_NONE;
00356   myLastTransSent.setToNow();
00357   myActionTransSet = false;
00358   myLastActionRotStopped = false;
00359   myLastActionRotHeading = false;
00360 
00361   myRotVal = 0;
00362   myLastRotVal = 0;
00363   myRotType = ROT_NONE;
00364   myLastRotType = ROT_NONE;
00365   myLastRotSent.setToNow();
00366   myActionRotSet = false;
00367 
00368   myLastPulseSent.setToNow();
00369 
00370   myDirectPrecedenceTime = 0;
00371   myStateReflectionRefreshTime = 500;
00372 
00373   myActionDesired.reset();
00374 
00375   myMotorPacCurrentCount = 0;
00376   myMotorPacCount = 0;
00377   myTimeLastMotorPacket = 0;
00378 
00379   mySonarPacCurrentCount = 0;
00380   mySonarPacCount = 0;
00381   myTimeLastSonarPacket = 0;
00382 
00383   myLeftEncoder = 0;
00384   myRightEncoder = 0;
00385 
00386   myWarnedAboutExtraSonar = false;
00387 }
00388 
00389 AREXPORT void ArRobot::setTransVelMax(double vel)
00390 {
00391   if (vel > myAbsoluteMaxTransVel)
00392   {
00393     ArLog::log(ArLog::Terse, "ArRobot: setTransVelMax of %g is over the absolute max of %g, capping it", vel, myAbsoluteMaxTransVel);
00394     vel = myAbsoluteMaxTransVel;
00395   }
00396   myTransVelMax = vel;
00397 }
00398 
00399 AREXPORT void ArRobot::setTransAccel(double acc)
00400 {
00401   if (acc > myAbsoluteMaxTransAccel)
00402   {
00403     ArLog::log(ArLog::Terse, "ArRobot: setTransAccel of %g is over the absolute max of %g, capping it", acc, myAbsoluteMaxTransAccel);
00404     acc = myAbsoluteMaxTransAccel;
00405   }
00406   myTransAccel = acc;
00407 }
00408 
00409 AREXPORT void ArRobot::setTransDecel(double decel)
00410 {
00411   if (fabs(decel) > myAbsoluteMaxTransDecel)
00412   {
00413     ArLog::log(ArLog::Terse, "ArRobot: setTransDecel of %g is over the absolute max of %g, capping it", decel, myAbsoluteMaxTransDecel);
00414     decel = myAbsoluteMaxTransDecel;
00415   }
00416   myTransDecel = ArMath::fabs(decel);
00417 }
00418 
00419 AREXPORT void ArRobot::setRotVelMax(double vel)
00420 {
00421   if (vel > myAbsoluteMaxRotVel)
00422   {
00423     ArLog::log(ArLog::Terse, "ArRobot: rotVelMax of %g is over the absolute max of %g, capping it", vel, myAbsoluteMaxRotVel);
00424     vel = myAbsoluteMaxRotVel;
00425   }
00426   myRotVelMax = vel;
00427 }
00428 
00429 AREXPORT void ArRobot::setRotAccel(double acc)
00430 {
00431   if (acc > myAbsoluteMaxRotAccel)
00432   {
00433     ArLog::log(ArLog::Terse, "ArRobot: setRotAccel of %g is over the absolute max of %g, capping it", acc, myAbsoluteMaxRotAccel);
00434     acc = myAbsoluteMaxRotAccel;
00435   }
00436   myRotAccel = acc;
00437 }
00438 
00439 AREXPORT void ArRobot::setRotDecel(double decel)
00440 {
00441   if (fabs(decel) > myAbsoluteMaxRotDecel)
00442   {
00443     ArLog::log(ArLog::Terse, "ArRobot: setRotDecel of %g is over the absolute max of %g, capping it", decel, myAbsoluteMaxRotDecel);
00444     decel = myAbsoluteMaxRotDecel;
00445   }
00446   myRotDecel = ArMath::fabs(decel);
00447 }
00448 
00449 AREXPORT double ArRobot::getTransVelMax(void) const
00450 {
00451   return myTransVelMax;
00452 }
00453 
00454 AREXPORT double ArRobot::getTransAccel(void) const
00455 {
00456   return myTransAccel;
00457 }
00458 
00459 AREXPORT double ArRobot::getTransDecel(void) const
00460 {
00461   return myTransDecel;
00462 }
00463 
00464 AREXPORT double ArRobot::getRotVelMax(void) const
00465 {
00466   return myRotVelMax;
00467 }
00468 
00469 AREXPORT double ArRobot::getRotAccel(void) const
00470 {
00471   return myRotAccel;
00472 }
00473 
00474 AREXPORT double ArRobot::getRotDecel(void) const
00475 {
00476   return myRotDecel;
00477 }
00478 
00487 AREXPORT void ArRobot::setDeviceConnection(ArDeviceConnection *connection)
00488 {
00489   myConn = connection;
00490   mySender.setDeviceConnection(myConn);
00491   myReceiver.setDeviceConnection(myConn);
00492 }
00493 
00502 AREXPORT ArDeviceConnection *ArRobot::getDeviceConnection(void) const
00503 {
00504   return myConn;
00505 }
00506 
00517 AREXPORT void ArRobot::setConnectionTimeoutTime(int mSecs)
00518 {
00519   if (mSecs > 0)
00520     myTimeoutTime = mSecs;
00521   else
00522     myTimeoutTime = 0;
00523 }
00524 
00531 AREXPORT int ArRobot::getConnectionTimeoutTime(void) const
00532 {
00533   return myTimeoutTime;
00534 }
00535 
00541 AREXPORT ArTime ArRobot::getLastPacketTime(void) const
00542 {
00543   return myLastPacketReceivedTime;
00544 }
00576 AREXPORT bool ArRobot::asyncConnect(void)
00577 {
00578   if (!mySyncLoop.getRunning() || isConnected())
00579     return false;
00580   
00581   myAsyncConnectFlag = true;
00582   myBlockingConnectRun = false;
00583   myAsyncConnectState = -1;
00584   return true;
00585 }
00586 
00617 AREXPORT bool ArRobot::blockingConnect(void)
00618 {
00619   int ret = 0;
00620 
00621   lock();
00622   if (myIsConnected)
00623     disconnect();
00624   myBlockingConnectRun = true;
00625   myAsyncConnectState = -1;
00626   while ((ret = asyncConnectHandler(true)) == 0 && myBlockingConnectRun)
00627     ArUtil::sleep(ArMath::roundInt(getCycleTime() * .80));
00628   unlock();
00629   if (ret == 1)
00630     return true;
00631   else
00632     return false;
00633 }
00634 
00650 AREXPORT int ArRobot::asyncConnectHandler(bool tryHarderToConnect)
00651 {
00652   int ret = 0;
00653   ArRobotPacket *packet;
00654   ArRobotPacket *tempPacket = NULL;
00655   char robotSubType[255];
00656   int i;
00657   int len;
00658   std::string str;
00659   ArTime endTime;
00660   int timeToWait;
00661   ArSerialConnection *serConn;
00662 
00663   endTime.setToNow();
00664   endTime.addMSec(getCycleTime()*myConnectionCycleMultiplier);
00665   
00666   myNoTimeWarningThisCycle = true;
00667 
00668   // if this is -1, then we're doing initialization stuff, then returning
00669   if (myAsyncConnectState == -1)
00670   {
00671     myAsyncConnectSentChangeBaud = false;
00672     myAsyncConnectNoPacketCount = 0;
00673     myAsyncConnectTimesTried = 0;
00674     reset();
00675     if (myConn == NULL)
00676     {
00677       ArLog::log(ArLog::Terse, "Cannot connect, no connection has been set.");
00678       failedConnect();
00679       return 2;
00680     }
00681     
00682     if (myConn->getStatus() != ArDeviceConnection::STATUS_OPEN) 
00683     {
00684       if (!myConn->openSimple())
00685       {
00686     /*str = myConn->getStatusMessage(myConn->getStatus());
00687       ArLog::log(ArLog::Terse, "Trying to connect to robot but connection not opened, it is %s", str.c_str());*/
00688         ArLog::log(ArLog::Terse, 
00689                    "Could not connect, because open on the device connection failed.");
00690         failedConnect();
00691         return 2;
00692       }
00693     }
00694 
00695     // check for log file connection: just return success
00696     if (dynamic_cast<ArLogFileConnection *>(myConn))
00697     {
00698       ArLogFileConnection *con = dynamic_cast<ArLogFileConnection *>(myConn);
00699       myRobotName = con->myName;
00700       myRobotType = con->myType;
00701       myRobotSubType = con->mySubtype;
00702       if (con->havePose)        // we know where to move
00703         moveTo(con->myPose);
00704       setCycleChained(false);   // don't process packets all at once
00705       madeConnection();
00706       finishedConnection();
00707       return 1;
00708     }
00709 
00710 
00711     if (dynamic_cast<ArSerialConnection *>(myConn))
00712     {
00713       myConn->write("WMS2\15", strlen("WMS2\15"));
00714     }
00715     // here we're flushing out all previously received packets
00716     while ( endTime.mSecTo() > 0 && myReceiver.receivePacket(0) != NULL);
00717 
00718     myAsyncConnectState = 0;
00719     return 0;
00720   }
00721 
00722   if (myAsyncConnectState >= 3)
00723   {
00724     bool handled;
00725     std::list<ArRetFunctor1<bool, ArRobotPacket *> *>::iterator it;
00726     while ((packet = myReceiver.receivePacket(0)) != NULL)
00727     {
00728       //printf("0x%x\n", packet->getID());
00729       for (handled = false, it = myPacketHandlerList.begin(); 
00730        it != myPacketHandlerList.end() && handled == false; 
00731        it++)
00732       {
00733     if ((*it) != NULL && (*it)->invokeR(packet)) 
00734       handled = true;
00735     else
00736       packet->resetRead();
00737       }
00738     }
00739   }
00740 
00741   if (myAsyncConnectState == 3)
00742   {
00743     //if (!myOrigRobotConfig->hasPacketBeenRequested())
00744     if (!myOrigRobotConfig->hasPacketArrived())
00745     {
00746       myOrigRobotConfig->requestPacket();
00747     }
00748     // if we've gotten our config packet or if we've timed out then
00749     // set our vel and acc/decel params and skip to the next part
00750     if (myOrigRobotConfig->hasPacketArrived() || 
00751     myAsyncStartedConnection.mSecSince() > 1000)
00752     {
00753       bool gotConfig;
00754       // if we have data from the robot use that
00755       if (myOrigRobotConfig->hasPacketArrived())
00756       {
00757     gotConfig = true;
00758     setAbsoluteMaxTransVel(myOrigRobotConfig->getTransVelTop());
00759     setAbsoluteMaxTransAccel(myOrigRobotConfig->getTransAccelTop());
00760     setAbsoluteMaxTransDecel(myOrigRobotConfig->getTransAccelTop());
00761     setAbsoluteMaxRotVel(myOrigRobotConfig->getRotVelTop());
00762     setAbsoluteMaxRotAccel(myOrigRobotConfig->getRotAccelTop());
00763     setAbsoluteMaxRotDecel(myOrigRobotConfig->getRotAccelTop());
00764     setTransVelMax(myOrigRobotConfig->getTransVelMax());
00765     setTransAccel(myOrigRobotConfig->getTransAccel());
00766     setTransDecel(myOrigRobotConfig->getTransDecel());
00767     setRotVelMax(myOrigRobotConfig->getRotVelMax());
00768     setRotAccel(myOrigRobotConfig->getRotAccel());
00769     setRotDecel(myOrigRobotConfig->getRotDecel());
00770       }
00771       // if our absolute maximums weren't set then set them
00772       else
00773       {
00774     gotConfig = false;
00775     setAbsoluteMaxTransVel(myParams->getAbsoluteMaxVelocity());
00776     setAbsoluteMaxTransAccel(1000);
00777     setAbsoluteMaxTransDecel(1000);
00778     setAbsoluteMaxRotVel(myParams->getAbsoluteMaxRotVelocity());
00779     setAbsoluteMaxRotAccel(100);
00780     setAbsoluteMaxRotDecel(100);
00781       }
00782       // okay we got in that data, now put over it any of the things
00783       // that we got from the robot parameter file... if we don't have
00784       // max vels from above or the parameters then use the absolutes
00785       // which we do have for everything
00786       if (ArMath::fabs(myParams->getTransVelMax()) > 1)
00787     setTransVelMax(myParams->getTransVelMax());
00788       else if (!gotConfig)
00789     setTransVelMax(myParams->getAbsoluteMaxVelocity());
00790       if (ArMath::fabs(myParams->getRotVelMax()) > 1)
00791     setRotVelMax(myParams->getRotVelMax());
00792       else if (!gotConfig)
00793     setRotVelMax(myParams->getAbsoluteMaxRotVelocity());
00794       if (ArMath::fabs(myParams->getTransAccel()) > 1)
00795     setTransAccel(myParams->getTransAccel());
00796       if (ArMath::fabs(myParams->getTransDecel()) > 1)
00797     setTransDecel(myParams->getTransDecel());
00798       if (ArMath::fabs(myParams->getRotAccel()) > 1)
00799     setRotAccel(myParams->getRotAccel());
00800       if (ArMath::fabs(myParams->getRotDecel()) > 1)
00801     setRotDecel(myParams->getRotDecel());
00802       myAsyncConnectState = 4;
00803     }
00804     else
00805       return 0;
00806   }
00807   // we want to see if we should switch baud
00808   if (myAsyncConnectState == 4)
00809   {
00810     serConn = dynamic_cast<ArSerialConnection *>(myConn);
00811     // if we didn't get a config packet or we can't change the baud or
00812     // we aren't using a serial port then don't switch the baud
00813     if (!myOrigRobotConfig->hasPacketArrived() || 
00814     !myOrigRobotConfig->getResetBaud() || 
00815     serConn == NULL ||
00816     myParams->getSwitchToBaudRate() == 0)
00817     {
00818       // if we're using a serial connection store our baud rate
00819       if (serConn != NULL)
00820     myAsyncConnectStartBaud = serConn->getBaud();
00821       myAsyncConnectState = 5;
00822     }
00823     // if we did get a packet and can change baud send the command
00824     else if (!myAsyncConnectSentChangeBaud)
00825     {
00826       // if we're using a serial connection store our baud rate
00827       if (serConn != NULL)
00828     myAsyncConnectStartBaud = serConn->getBaud();
00829 
00830       int baudNum = -1;
00831       
00832       // first suck up all the packets we have now
00833       while ((packet = myReceiver.receivePacket(0)) != NULL);
00834       if (myParams->getSwitchToBaudRate() == 9600)
00835     baudNum = 0;
00836       else if (myParams->getSwitchToBaudRate() == 19200)
00837     baudNum = 1;
00838       else if (myParams->getSwitchToBaudRate() == 38400)
00839     baudNum = 2;
00840       else if (myParams->getSwitchToBaudRate() == 57600)
00841     baudNum = 3;
00842       else if (myParams->getSwitchToBaudRate() == 115200)
00843     baudNum = 4;
00844       else
00845       {
00846     ArLog::log(ArLog::Normal, "Warning: SwitchToBaud is set to %d baud, ignoring.",
00847            myParams->getSwitchToBaudRate());
00848     ArLog::log(ArLog::Normal, "\tGood bauds are 9600 19200 38400 56800 116200.");
00849     myAsyncConnectState = 5;
00850     baudNum = -1;
00851     return 0;
00852       }
00853       if (baudNum != -1)
00854       {
00855     // now switch it over
00856     comInt(ArCommands::HOSTBAUD, baudNum);
00857     ArUtil::sleep(10);
00858     myAsyncConnectSentChangeBaud = true;
00859     myAsyncConnectStartedChangeBaud.setToNow();
00860     serConn->setBaud(myParams->getSwitchToBaudRate());
00861     //serConn->setBaud(19200);
00862     ArUtil::sleep(10);
00863     com(0);
00864     return 0;
00865       }
00866     }
00867     // if we did send the command then wait and see if we get any packets back
00868     else
00869     {
00870       packet = myReceiver.receivePacket(100);
00871       com(0);
00872       // if we got any packet we're good
00873       if (packet != NULL)
00874       {
00875     myAsyncConnectState = 5;
00876       }
00877       // if we didn't get it and its been 500 ms then fail
00878       else if (myAsyncConnectStartedChangeBaud.mSecSince() > 900)
00879       {
00880     ArLog::log(ArLog::Verbose, "Controller did not switch to baud, reset to %d baud.", myAsyncConnectStartBaud);
00881     serConn->setBaud(myAsyncConnectStartBaud);
00882     myAsyncConnectState = 5;
00883       }
00884       else
00885     return 0;
00886     }    
00887   }
00888 
00889   if (myAsyncConnectState == 5)
00890   {
00891     if (!myIsStabilizing)
00892       startStabilization();
00893     if (myStabilizingTime == 0 || 
00894     myStartedStabilizing.mSecSince() > myStabilizingTime)
00895     {
00896       finishedConnection();
00897       return 1;
00898     }
00899     else
00900       return 0;
00901   }
00902 
00903   // here we've gone beyond the initialization, so read set a time limit,
00904   // read in one packet, then if its a bad packet type, read in all the 
00905   // packets there are to read... if its a good packet, continue with sequence
00906   myAsyncConnectTimesTried++;
00907   ArLog::log(ArLog::Normal, "Syncing %d", myAsyncConnectState);
00908   mySender.com(myAsyncConnectState);
00909   //  packet = myReceiver.receivePacket(endTime.mSecTo());
00910   packet = myReceiver.receivePacket(1000);
00911   
00912   if (packet != NULL) 
00913   {
00914     ret = packet->getID();
00915     //printf("Got a packet %d\n", ret);
00916     
00917     if (ret == 50)
00918     {
00919       ArLog::log(ArLog::Normal, "Attempting to close previous connection.");
00920       comInt(ArCommands::CLOSE,1);
00921       while (endTime.mSecTo() > 0)
00922       {
00923     timeToWait = endTime.mSecTo();
00924     if (timeToWait < 0)
00925       timeToWait = 0;
00926     tempPacket = myReceiver.receivePacket(timeToWait);
00927     if (tempPacket != NULL)
00928       ArLog::log(ArLog::Verbose, "Got in another packet!");
00929     if (tempPacket != NULL && tempPacket->getID() == 50)
00930       comInt(ArCommands::CLOSE,1);
00931       }
00932       myAsyncConnectState = 0;
00933     } 
00934     else if (ret == 255)
00935     {
00936       ArLog::log(ArLog::Normal, "Attempting to correct syncCount");
00937       /*
00938       while (endTime.mSecTo() > 0)
00939       {
00940     timeToWait = endTime.mSecTo();
00941     if (timeToWait < 0)
00942       timeToWait = 0;
00943     tempPacket = myReceiver.receivePacket(timeToWait);
00944     if (tempPacket != NULL)
00945       ArLog::log(ArLog::Verbose, "Got in another packet!");
00946       }
00947       */
00948       while ((tempPacket = myReceiver.receivePacket(0)) != NULL);
00949 
00950       if (tempPacket != NULL && tempPacket->getID() == 0)
00951     myAsyncConnectState = 1;
00952       else
00953     myAsyncConnectState = 0;
00954       return 0;
00955     } 
00956     else if  (ret != myAsyncConnectState++)
00957     {
00958       myAsyncConnectState = 0;
00959     }
00960   }
00961   else 
00962   {
00963     ArLog::log(ArLog::Normal, "No packet.");
00964     myAsyncConnectNoPacketCount++;
00965     if ((myAsyncConnectNoPacketCount > 5
00966      && myAsyncConnectNoPacketCount >= myAsyncConnectTimesTried)
00967     || (myAsyncConnectNoPacketCount > 10))
00968     {
00969       ArLog::log(ArLog::Terse, "Could not connect, no robot responding.");
00970       failedConnect();
00971       return 2;
00972     }
00973 
00974       /* This code to connect the radio modems should never really be needed 
00975      so is being removed for now
00976      if (myAsyncConnectNoPacketCount >= 4)
00977      {
00978      
00979      if (tryHarderToConnect && dynamic_cast<ArSerialConnection *>(myConn))
00980      {
00981      ArLog::log(ArLog::Normal, 
00982      "Radio modem may not connected, trying to connect it.");
00983      ArUtil::sleep(1000);
00984      myConn->write("|||\15", strlen("!!!\15"));
00985      ArUtil::sleep(60);
00986      myConn->write("WMN\15", strlen("WMN\15"));
00987      ArUtil::sleep(60);
00988      myConn->write("WMS2\15", strlen("WMS2\15"));
00989      ArUtil::sleep(1000);
00990      } 
00991      else if (dynamic_cast<ArSerialConnection *>(myConn))
00992      {
00993      ArLog::log(ArLog::Normal,
00994      "Radio modem may not connected, trying to connect it.");
00995      myConn->write("WMS2\15", strlen("WMS2\15"));
00996      ArUtil::sleep(60);
00997      }
00998      }
00999       */
01000     
01001     // If we get no response first we dump close commands at the thing
01002     // in different bauds (if its a serial connection)
01003     if (myAsyncConnectNoPacketCount == 2 && 
01004     myAsyncConnectNoPacketCount >= myAsyncConnectTimesTried &&
01005     (serConn = dynamic_cast<ArSerialConnection *>(myConn)) != NULL)
01006     {
01007       int origBaud;
01008       ArLog::log(ArLog::Normal, "Trying to close possible old connection");
01009       origBaud = serConn->getBaud();
01010       serConn->setBaud(9600);
01011       comInt(ArCommands::CLOSE,1);
01012       ArUtil::sleep(3);
01013       serConn->setBaud(38400);
01014       comInt(ArCommands::CLOSE,1);
01015       ArUtil::sleep(3);
01016       serConn->setBaud(115200);
01017       comInt(ArCommands::CLOSE,1);
01018       ArUtil::sleep(3);
01019       serConn->setBaud(19200);
01020       comInt(ArCommands::CLOSE,1);
01021       ArUtil::sleep(3);
01022       serConn->setBaud(57600);
01023       comInt(ArCommands::CLOSE,1);
01024       ArUtil::sleep(3);
01025       serConn->setBaud(origBaud);
01026     }
01027 
01028     if (myAsyncConnectNoPacketCount > 3)
01029     {
01030       ArLog::log(ArLog::Normal,
01031          " Robot may be connected but not open, trying to dislodge.");
01032       mySender.comInt(ArCommands::OPEN,1);
01033     }
01034     
01035     myAsyncConnectState = 0;
01036   }
01037   // if we've connected and have a packet get the connection
01038   // information from it
01039   if (myAsyncConnectState == 3 && packet != NULL) 
01040   {
01041     char nameBuf[512];
01042     ArLog::log(ArLog::Terse, "Connected to robot.");
01043     packet->bufToStr(nameBuf, 512);
01044     myRobotName = nameBuf;
01045     ArLog::log(ArLog::Normal, "Name: %s", myRobotName.c_str());
01046     packet->bufToStr(nameBuf, 512);
01047     myRobotType = nameBuf;
01048     ArLog::log(ArLog::Normal, "Type: %s", myRobotType.c_str());
01049     packet->bufToStr(nameBuf, 512);
01050     myRobotSubType = nameBuf;
01051     strcpy(robotSubType, myRobotSubType.c_str());
01052     len = strlen(robotSubType);
01053     for (i = 0; i < len; i++)
01054       robotSubType[i] = tolower(robotSubType[i]);
01055     myRobotSubType = robotSubType;
01056     ArLog::log(ArLog::Normal, "Subtype: %s", myRobotSubType.c_str());
01057     ArUtil::sleep(getCycleTime());
01058     mySender.comInt(ArCommands::OPEN,1);
01059     if (!madeConnection())
01060     {
01061       mySender.comInt(ArCommands::CLOSE,1);
01062       failedConnect();
01063       return 2;
01064     }
01065 
01066     // now we return off so we can handle the rest of connecting, if
01067     // you're just using this for your own connections you can skip
01068     // this part because its really connected now
01069     myAsyncStartedConnection.setToNow();
01070     return asyncConnectHandler(tryHarderToConnect);
01071   }
01072   if (myAsyncConnectTimesTried > 50)
01073   {
01074     failedConnect();
01075     return 2;
01076   }
01077   return 0;
01078 }
01079 
01083 AREXPORT bool ArRobot::loadParamFile(const char *file)
01084 {
01085   if (myParams != NULL)
01086     delete myParams;
01087 
01088   myParams = new ArRobotGeneric("");
01089   if (!myParams->parseFile(file, false, true))
01090   {
01091     ArLog::log(ArLog::Normal, "ArRobot::loadParamFile: Could not find file '%s' to load.", file);
01092     return false;
01093   }
01094   processParamFile();
01095   ArLog::log(ArLog::Normal, "Loaded robot parameters from %s.", file);
01096   return true;
01097 }
01098 
01099 AREXPORT void ArRobot::processParamFile(void)
01100 {
01101   for (int i = 0; i < myParams->getNumSonar(); ++i)
01102   {
01103     //printf("sonar %d %d %d %d\n", i, myParams->getSonarX(i),
01104     //myParams->getSonarY(i), myParams->getSonarTh(i));
01105     if (mySonars.find(i) == mySonars.end())
01106     {
01107       mySonars[i] = new ArSensorReading(myParams->getSonarX(i),
01108                     myParams->getSonarY(i), 
01109                     myParams->getSonarTh(i));
01110       mySonars[i]->setIgnoreThisReading(true);
01111     }
01112     else
01113     {
01114       mySonars[i]->resetSensorPosition(myParams->getSonarX(i),
01115                       myParams->getSonarY(i), 
01116                       myParams->getSonarTh(i));
01117       mySonars[i]->setIgnoreThisReading(true);
01118     }
01119     if ((i + 1) > myNumSonar)
01120       myNumSonar = i + 1;
01121   }
01122   //myRobotType = myParams->getClassName();
01123   //myRobotSubType = myParams->getSubClassName();
01124   myAbsoluteMaxTransVel = myParams->getAbsoluteMaxVelocity();
01125   myAbsoluteMaxRotVel = myParams->getAbsoluteMaxRotVelocity();
01126 
01127   if (myParams->getRobotLengthFront() == 0)
01128     myRobotLengthFront = myParams->getRobotLength() / 2.0;
01129   else
01130     myRobotLengthFront = myParams->getRobotLengthFront();
01131 
01132   if (myParams->getRobotLengthRear() == 0)
01133     myRobotLengthRear = myParams->getRobotLength() / 2.0;
01134   else
01135     myRobotLengthRear = myParams->getRobotLengthRear();
01136 }
01137 
01138 
01139 AREXPORT bool ArRobot::madeConnection(void)
01140 {
01141   std::string subTypeParamName;
01142   std::string paramFileName;
01143   bool loadedSubTypeParam;
01144   bool loadedNameParam;
01145   bool hadDefault = true;
01146   
01147   if (myParams != NULL)
01148     delete myParams;
01149   
01150   // Find the robot parameters to load and get them into the structure we have
01151   if (ArUtil::strcmp(myRobotSubType, "p2dx") == 0)
01152     myParams = new ArRobotP2DX;
01153   else if (ArUtil::strcmp(myRobotSubType, "p2ce") == 0)
01154     myParams = new ArRobotP2CE;
01155   else if (ArUtil::strcmp(myRobotSubType, "p2de") == 0)
01156     myParams = new ArRobotP2DXe;
01157   else if (ArUtil::strcmp(myRobotSubType, "p2df") == 0)
01158     myParams = new ArRobotP2DF;
01159   else if (ArUtil::strcmp(myRobotSubType, "p2d8") == 0)
01160     myParams = new ArRobotP2D8;
01161   else if (ArUtil::strcmp(myRobotSubType, "amigo") == 0)
01162     myParams = new ArRobotAmigo;
01163   else if (ArUtil::strcmp(myRobotSubType, "amigo-sh") == 0)
01164     myParams = new ArRobotAmigoSh;
01165   else if (ArUtil::strcmp(myRobotSubType, "p2at") == 0)
01166     myParams = new ArRobotP2AT;
01167   else if (ArUtil::strcmp(myRobotSubType, "p2at8") == 0)
01168     myParams = new ArRobotP2AT8;
01169   else if (ArUtil::strcmp(myRobotSubType, "p2it") == 0)
01170     myParams = new ArRobotP2IT;
01171   else if (ArUtil::strcmp(myRobotSubType, "p2pb") == 0)
01172     myParams = new ArRobotP2PB;
01173   else if (ArUtil::strcmp(myRobotSubType, "p2pp") == 0)
01174     myParams = new ArRobotP2PP;
01175   else if (ArUtil::strcmp(myRobotSubType, "p3at") == 0)
01176     myParams = new ArRobotP3AT;
01177   else if (ArUtil::strcmp(myRobotSubType, "p3dx") == 0)
01178     myParams = new ArRobotP3DX;
01179   else if (ArUtil::strcmp(myRobotSubType, "perfpb") == 0)
01180     myParams = new ArRobotPerfPB;
01181   else if (ArUtil::strcmp(myRobotSubType, "pion1m") == 0)
01182     myParams = new ArRobotPion1M;
01183   else if (ArUtil::strcmp(myRobotSubType, "pion1x") == 0)
01184     myParams = new ArRobotPion1X;
01185   else if (ArUtil::strcmp(myRobotSubType, "psos1m") == 0)
01186     myParams = new ArRobotPsos1M;
01187   else if (ArUtil::strcmp(myRobotSubType, "psos43m") == 0)
01188     myParams = new ArRobotPsos43M;
01189   else if (ArUtil::strcmp(myRobotSubType, "psos1x") == 0)
01190     myParams = new ArRobotPsos1X;
01191   else if (ArUtil::strcmp(myRobotSubType, "pionat") == 0)
01192     myParams = new ArRobotPionAT;
01193   else if (ArUtil::strcmp(myRobotSubType, "mappr") == 0)
01194     myParams = new ArRobotMapper;
01195   else if (ArUtil::strcmp(myRobotSubType, "powerbot") == 0)
01196     myParams = new ArRobotPowerBot;
01197   else if (ArUtil::strcmp(myRobotSubType, "p2d8+") == 0)
01198     myParams = new ArRobotP2D8Plus;
01199   else if (ArUtil::strcmp(myRobotSubType, "p2at8+") == 0)
01200     myParams = new ArRobotP2AT8Plus;
01201   else if (ArUtil::strcmp(myRobotSubType, "perfpb+") == 0)
01202     myParams = new ArRobotPerfPBPlus;
01203   else if (ArUtil::strcmp(myRobotSubType, "p3dx-sh") == 0)
01204     myParams = new ArRobotP3DXSH;
01205   else if (ArUtil::strcmp(myRobotSubType, "p3at-sh") == 0)
01206     myParams = new ArRobotP3ATSH;
01207   else if (ArUtil::strcmp(myRobotSubType, "p3atiw-sh") == 0)
01208     myParams = new ArRobotP3ATIWSH;
01209   else if (ArUtil::strcmp(myRobotSubType, "patrolbot-sh") == 0)
01210     myParams = new ArRobotPatrolBotSH;
01211   else if (ArUtil::strcmp(myRobotSubType, "peoplebot-sh") == 0)
01212     myParams = new ArRobotPeopleBotSH;
01213   else if (ArUtil::strcmp(myRobotSubType, "powerbot-sh") == 0)
01214     myParams = new ArRobotPowerBotSH;
01215   else if (ArUtil::strcmp(myRobotSubType, "wheelchair-sh") == 0)
01216     myParams = new ArRobotWheelchairSH;
01217   else
01218   {
01219     hadDefault = false;
01220     myParams = new ArRobotGeneric(myRobotName.c_str());
01221   }
01222 
01223   // load up the param file for the subtype
01224   paramFileName = Aria::getDirectory();
01225   paramFileName += "params/";
01226   paramFileName += myRobotSubType;
01227   paramFileName += ".p";
01228   if ((loadedSubTypeParam = myParams->parseFile(paramFileName.c_str(), true, true)))
01229       ArLog::log(ArLog::Normal, 
01230          "Loaded robot parameters from %s.p", 
01231          myRobotSubType.c_str());
01232   /* If the above line was replaced with this one line
01233      paramFile->load(); 
01234      then the sonartest (and lots of other stuff probably) would break
01235   */
01236   // then the one for the particular name, if we can
01237   paramFileName = Aria::getDirectory();
01238   paramFileName += "params/";
01239   paramFileName += myRobotName;
01240   paramFileName += ".p";
01241   if ((loadedNameParam = myParams->parseFile(paramFileName.c_str(),
01242                          true, true)))
01243   {
01244     if (loadedSubTypeParam)
01245       ArLog::log(ArLog::Normal, 
01246  "Loaded robot parameters from %s.p on top of %s.p robot parameters", 
01247          myRobotName.c_str(), myRobotSubType.c_str());
01248     else
01249       ArLog::log(ArLog::Normal, "Loaded robot parameters from %s.p", 
01250          myRobotName.c_str());
01251   }
01252    
01253   if (!loadedSubTypeParam && !loadedNameParam)
01254   {
01255     if (hadDefault)
01256       ArLog::log(ArLog::Normal, "Using default parameters for a %s robot", 
01257          myRobotSubType.c_str());
01258     else
01259     {
01260       ArLog::log(ArLog::Terse, "Error: Have no parameters for this robot, bad configuration or out of date Aria");
01261       // in the default state (not connecting if we don't have params)
01262       // we will return false... if we can connect without params then
01263       // we'll keep going (this really shouldn't be used except by
01264       // downloaders and such)
01265       if (!myConnectWithNoParams)
01266     return false;
01267     }
01268   }
01269 
01270   processParamFile();
01271 
01272   if (myParams->getRequestIOPackets() || myRequestedIOPackets)
01273     comInt(ArCommands::IOREQUEST, 2);
01274 
01275   if(myParams->getRequestEncoderPackets() || myRequestedEncoderPackets)
01276     comInt(ArCommands::ENCODER, 2);
01277 
01278   return true;
01279 }
01280 
01286 AREXPORT void ArRobot::requestEncoderPackets(void)
01287 {
01288   comInt(ArCommands::ENCODER, 2);
01289   myRequestedEncoderPackets = true;
01290 }
01291 
01292 AREXPORT void ArRobot::requestIOPackets(void)
01293 {
01294   comInt(ArCommands::IOREQUEST, 2);
01295   myRequestedIOPackets = true;
01296 }
01297 
01298 AREXPORT void ArRobot::stopEncoderPackets(void)
01299 {
01300   comInt(ArCommands::ENCODER, 0);
01301   myRequestedEncoderPackets = false;
01302 }
01303 
01304 AREXPORT void ArRobot::stopIOPackets(void)
01305 {
01306   comInt(ArCommands::IOREQUEST, 0);
01307   myRequestedIOPackets = false;
01308 }
01309 
01310 AREXPORT void ArRobot::startStabilization(void)
01311 {
01312   std::list<ArFunctor *>::iterator it;
01313   myIsStabilizing = true;
01314   myStartedStabilizing.setToNow();
01315 
01316   for (it = myStabilizingCBList.begin(); 
01317        it != myStabilizingCBList.end(); 
01318        it++)
01319     (*it)->invoke();
01320 
01321 }
01322 
01323 AREXPORT void ArRobot::finishedConnection(void)
01324 {
01325   std::list<ArFunctor *>::iterator it;
01326 
01327   myIsStabilizing = false;
01328   myIsConnected = true;
01329   myAsyncConnectFlag = false;
01330   myBlockingConnectRun = false;
01331   resetOdometer();
01332   
01333   for (it = myConnectCBList.begin(); it != myConnectCBList.end(); it++)
01334     (*it)->invoke();
01335   myLastPacketReceivedTime.setToNow();
01336 
01337   wakeAllConnWaitingThreads();
01338 }
01339 
01340 AREXPORT void ArRobot::failedConnect(void)
01341 {
01342   std::list<ArFunctor *>::iterator it;  
01343   
01344   myAsyncConnectFlag = false;
01345   myBlockingConnectRun = false;
01346   ArLog::log(ArLog::Terse, "Failed to connect to robot.");
01347   myIsConnected = false;
01348   for (it = myFailedConnectCBList.begin(); 
01349        it != myFailedConnectCBList.end(); 
01350        it++)
01351     (*it)->invoke();
01352 
01353   if (myConn != NULL)
01354     myConn->close();
01355   wakeAllConnOrFailWaitingThreads();
01356 }
01357 
01367 AREXPORT bool ArRobot::disconnect(void)
01368 {
01369   std::list<ArFunctor *>::iterator it;  
01370   bool ret;
01371   ArSerialConnection *serConn;
01372 
01373   if (!myIsConnected && !myIsStabilizing)
01374     return true;
01375   
01376   ArLog::log(ArLog::Terse, "Disconnecting from robot.");
01377   myNoTimeWarningThisCycle = true;
01378   myIsConnected = false;
01379   myIsStabilizing = false;
01380   if (myIsConnected)
01381   {
01382     for (it = myDisconnectNormallyCBList.begin(); 
01383      it != myDisconnectNormallyCBList.end(); 
01384      it++)
01385       (*it)->invoke();
01386   }
01387   ret = mySender.comInt(ArCommands::CLOSE, 1);
01388   ArUtil::sleep(1000);
01389   if (ret == true)
01390   {
01391     if (myConn != NULL)
01392     {
01393       ret = myConn->close();
01394       if ((serConn = dynamic_cast<ArSerialConnection *>(myConn)) != NULL)
01395         serConn->setBaud(myAsyncConnectStartBaud);
01396     } 
01397     else
01398       ret = false;
01399   } 
01400   else if (myConn != NULL)
01401     myConn->close();
01402     
01403   return ret;
01404 }
01405 
01406 AREXPORT void ArRobot::dropConnection(void)
01407 {
01408   std::list<ArFunctor *>::iterator it;  
01409 
01410   if (!myIsConnected)
01411     return;
01412 
01413   ArLog::log(ArLog::Terse, "Lost connection to the robot because of error.");
01414   myIsConnected = false;
01415   for (it = myDisconnectOnErrorCBList.begin(); 
01416        it != myDisconnectOnErrorCBList.end(); 
01417        it++)
01418     (*it)->invoke();
01419 
01420   if (myConn != NULL)
01421     myConn->close();
01422   return;
01423 }
01424 
01425 AREXPORT void ArRobot::cancelConnection(void)
01426 {
01427   //std::list<ArFunctor *>::iterator it;  
01428 
01429   ArLog::log(ArLog::Verbose, "Cancelled connection to the robot because of command.");
01430   myIsConnected = false;
01431   myNoTimeWarningThisCycle = true;
01432   myIsStabilizing = false;
01433   return;
01434 }
01435 
01445 AREXPORT void ArRobot::stop(void)
01446 {
01447   comInt(ArCommands::VEL, 0);
01448   comInt(ArCommands::RVEL, 0);
01449   setVel(0);
01450   setRotVel(0);
01451   myLastActionTransVal = 0;
01452   myLastActionRotStopped = true;
01453   myLastActionRotHeading = false;
01454 }
01455 
01462 AREXPORT void ArRobot::setVel(double velocity)
01463 {
01464   myTransType = TRANS_VEL;
01465   myTransVal = velocity;
01466   myTransVal2 = 0;
01467   myTransSetTime.setToNow();
01468 }
01469 
01484 AREXPORT void ArRobot::setVel2(double leftVelocity, double rightVelocity)
01485 {
01486   myTransType = TRANS_VEL2;
01487   myTransVal = leftVelocity;
01488   myTransVal2 = rightVelocity;
01489   myRotType = ROT_IGNORE;
01490   myRotVal = 0;
01491   myTransSetTime.setToNow();
01492 }
01493 
01504 AREXPORT void ArRobot::move(double distance)
01505 {
01506   myTransType = TRANS_DIST_NEW;
01507   myTransDistStart = getPose();
01508   myTransVal = distance;
01509   myTransVal2 = 0;
01510   myTransSetTime.setToNow();
01511 }
01512 
01527 AREXPORT bool ArRobot::isMoveDone(double delta)
01528 {
01529   if (fabs(delta) < 0.001)
01530     delta = myMoveDoneDist;
01531   if (myTransType != TRANS_DIST && myTransType != TRANS_DIST_NEW)
01532     return true;        // no distance command operative
01533   if (myTransDistStart.findDistanceTo(getPose()) <
01534       fabs(myTransVal) - delta)
01535     return false;
01536   return true;
01537 }
01538 
01539 
01552 AREXPORT bool ArRobot::isHeadingDone(double delta) const
01553 {
01554   if (fabs(delta) < 0.001)
01555     delta = myHeadingDoneDiff;
01556   if (myRotType != ROT_HEADING)
01557     return true;        // no heading command operative
01558   if(fabs(ArMath::subAngle(getTh(), myRotVal)) > delta)
01559     return false;
01560   return true;
01561 }
01562 
01563 
01564 
01571 AREXPORT void ArRobot::setHeading(double heading)
01572 {
01573   myRotVal = heading;
01574   myRotType = ROT_HEADING;
01575   myRotSetTime.setToNow();
01576   if (myTransType == TRANS_VEL2)
01577   {
01578     myTransType = TRANS_IGNORE;
01579     myTransVal = 0;
01580     myTransVal2 = 0;
01581   }
01582 }
01583 
01590 AREXPORT void ArRobot::setRotVel(double velocity)
01591 {
01592   myRotVal = velocity;
01593   myRotType = ROT_VEL;
01594   myRotSetTime.setToNow();
01595   if (myTransType == TRANS_VEL2)
01596   {
01597     myTransType = TRANS_IGNORE;
01598     myTransVal = 0;
01599     myTransVal2 = 0;
01600   }
01601 }
01602 
01609 AREXPORT void ArRobot::setDeltaHeading(double deltaHeading)
01610 {
01611   myRotVal = ArMath::addAngle(getTh(), deltaHeading);
01612   myRotType = ROT_HEADING;
01613   myRotSetTime.setToNow();
01614   if (myTransType == TRANS_VEL2)
01615   {
01616     myTransType = TRANS_IGNORE;
01617     myTransVal = 0;
01618     myTransVal2 = 0;
01619   }
01620 }
01621 
01635 AREXPORT bool ArRobot::setAbsoluteMaxTransVel(double maxVel)
01636 {
01637   if (maxVel < 0)
01638     return false;
01639   myAbsoluteMaxTransVel = maxVel;
01640   if (getTransVelMax() > myAbsoluteMaxTransVel)
01641     setTransVelMax(myAbsoluteMaxTransVel);
01642   return true;
01643 }
01644 
01658 AREXPORT bool ArRobot::setAbsoluteMaxTransAccel(double maxAccel)
01659 {
01660   if (maxAccel < 0)
01661     return false;
01662   myAbsoluteMaxTransAccel = maxAccel;
01663   if (getTransAccel() > myAbsoluteMaxTransAccel)
01664     setTransAccel(myAbsoluteMaxTransAccel);
01665   return true;
01666 }
01667 
01681 AREXPORT bool ArRobot::setAbsoluteMaxTransDecel(double maxDecel)
01682 {
01683   if (maxDecel < 0)
01684     return false;
01685   myAbsoluteMaxTransDecel = maxDecel;
01686   if (getTransDecel() > myAbsoluteMaxTransDecel)
01687     setTransDecel(myAbsoluteMaxTransDecel);
01688   return true;
01689 }
01690 
01702 AREXPORT bool ArRobot::setAbsoluteMaxRotVel(double maxVel)
01703 {
01704   if (maxVel < 0)
01705     return false;
01706   myAbsoluteMaxRotVel = maxVel;
01707   if (getRotVelMax() > myAbsoluteMaxRotVel)
01708     setRotVelMax(myAbsoluteMaxRotVel);
01709   return true;
01710 }
01711 
01725 AREXPORT bool ArRobot::setAbsoluteMaxRotAccel(double maxAccel)
01726 {
01727   if (maxAccel < 0)
01728     return false;
01729   myAbsoluteMaxRotAccel = maxAccel;
01730   if (getRotAccel() > myAbsoluteMaxRotAccel)
01731     setRotAccel(myAbsoluteMaxRotAccel);
01732   return true;
01733 }
01734 
01748 AREXPORT bool ArRobot::setAbsoluteMaxRotDecel(double maxDecel)
01749 {
01750   if (maxDecel < 0)
01751     return false;
01752   myAbsoluteMaxRotDecel = maxDecel;
01753   if (getRotDecel() > myAbsoluteMaxRotDecel)
01754     setRotDecel(myAbsoluteMaxRotDecel);
01755   return true;
01756 }
01757 
01762 AREXPORT int ArRobot::getIOAnalog(int num) const
01763 {
01764   if (num <= getIOAnalogSize())
01765     return myIOAnalog[num];
01766   else
01767     return 0;
01768 }
01769 
01773 AREXPORT double ArRobot::getIOAnalogVoltage(int num) const
01774 {
01775   if (num <= getIOAnalogSize())
01776   {
01777     return (myIOAnalog[num] & 0xfff) * .0048828;
01778   }
01779   else
01780     return 0;
01781 }
01782 
01783 AREXPORT unsigned char ArRobot::getIODigIn(int num) const
01784 {
01785   if (num <= getIODigInSize())
01786     return myIODigIn[num];
01787   else
01788     return (unsigned char) 0;
01789 }
01790 
01791 AREXPORT unsigned char  ArRobot::getIODigOut(int num) const
01792 {
01793   if (num <= getIODigOutSize())
01794     return myIODigOut[num];
01795   else
01796     return (unsigned char) 0;
01797 }
01798 
01802 AREXPORT const ArRobotParams *ArRobot::getRobotParams(void) const
01803 {
01804   return myParams;
01805 }
01806 
01811 AREXPORT const ArRobotConfigPacketReader *ArRobot::getOrigRobotConfig(void) const
01812 {
01813   return myOrigRobotConfig;
01814 }
01815   
01832 AREXPORT void ArRobot::addPacketHandler(
01833     ArRetFunctor1<bool, ArRobotPacket *> *functor, 
01834     ArListPos::Pos position) 
01835 {
01836   if (position == ArListPos::FIRST)
01837     myPacketHandlerList.push_front(functor);
01838   else if (position == ArListPos::LAST)
01839     myPacketHandlerList.push_back(functor);
01840   else
01841     ArLog::log(ArLog::Terse, "ArRobot::addPacketHandler: Invalid position.");
01842 
01843 }
01844 
01849 AREXPORT void ArRobot::remPacketHandler(
01850     ArRetFunctor1<bool, ArRobotPacket *> *functor)
01851 {
01852   myPacketHandlerList.remove(functor);
01853 }
01854 
01865 AREXPORT void ArRobot::addConnectCB(ArFunctor *functor, 
01866                     ArListPos::Pos position)
01867 {
01868   if (position == ArListPos::FIRST)
01869     myConnectCBList.push_front(functor);
01870   else if (position == ArListPos::LAST)
01871     myConnectCBList.push_back(functor);
01872   else
01873     ArLog::log(ArLog::Terse, 
01874            "ArRobot::addConnectCallback: Invalid position.");
01875 }
01876 
01881 AREXPORT void ArRobot::remConnectCB(ArFunctor *functor)
01882 {
01883   myConnectCBList.remove(functor);
01884 }
01885 
01886 
01900 AREXPORT void ArRobot::addFailedConnectCB(ArFunctor *functor, 
01901                       ArListPos::Pos position)
01902 {
01903   if (position == ArListPos::FIRST)
01904     myFailedConnectCBList.push_front(functor);
01905   else if (position == ArListPos::LAST)
01906     myFailedConnectCBList.push_back(functor);
01907   else
01908     ArLog::log(ArLog::Terse, 
01909            "ArRobot::addFailedCallback: Invalid position.");
01910 }
01911 
01916 AREXPORT void ArRobot::remFailedConnectCB(ArFunctor *functor)
01917 {
01918   myFailedConnectCBList.remove(functor);
01919 }
01920 
01932 AREXPORT void ArRobot::addDisconnectNormallyCB(ArFunctor *functor, 
01933                            ArListPos::Pos position)
01934 {
01935   if (position == ArListPos::FIRST)
01936     myDisconnectNormallyCBList.push_front(functor);
01937   else if (position == ArListPos::LAST)
01938     myDisconnectNormallyCBList.push_back(functor);
01939   else
01940     ArLog::log(ArLog::Terse, 
01941            "ArRobot::addDisconnectNormallyCB: Invalid position.");
01942 }
01943 
01948 AREXPORT void ArRobot::remDisconnectNormallyCB(ArFunctor *functor)
01949 {
01950   myDisconnectNormallyCBList.remove(functor);
01951 }
01952 
01969 AREXPORT void ArRobot::addDisconnectOnErrorCB(ArFunctor *functor, 
01970                           ArListPos::Pos position)
01971 {
01972   if (position == ArListPos::FIRST)
01973     myDisconnectOnErrorCBList.push_front(functor);
01974   else if (position == ArListPos::LAST)
01975     myDisconnectOnErrorCBList.push_back(functor);
01976   else
01977     ArLog::log(ArLog::Terse, 
01978            "ArRobot::addDisconnectOnErrorCB: Invalid position");
01979 }
01980 
01985 AREXPORT void ArRobot::remDisconnectOnErrorCB(ArFunctor *functor)
01986 {
01987   myDisconnectOnErrorCBList.remove(functor);
01988 }
01989 
02001 AREXPORT void ArRobot::addRunExitCB(ArFunctor *functor,
02002                     ArListPos::Pos position)
02003 {
02004   if (position == ArListPos::FIRST)
02005     myRunExitCBList.push_front(functor);
02006   else if (position == ArListPos::LAST)
02007     myRunExitCBList.push_back(functor);
02008   else
02009     ArLog::log(ArLog::Terse, "ArRobot::addRunExitCB: Invalid position");
02010 }
02011 
02016 AREXPORT void ArRobot::remRunExitCB(ArFunctor *functor)
02017 {
02018   myRunExitCBList.remove(functor);
02019 }
02020 
02033 AREXPORT void ArRobot::addStabilizingCB(ArFunctor *functor, 
02034                        ArListPos::Pos position)
02035 {
02036   if (position == ArListPos::FIRST)
02037     myStabilizingCBList.push_front(functor);
02038   else if (position == ArListPos::LAST)
02039     myStabilizingCBList.push_back(functor);
02040   else
02041     ArLog::log(ArLog::Terse, 
02042            "ArRobot::addConnectCallback: Invalid position.");
02043 }
02044 
02049 AREXPORT void ArRobot::remStabilizingCB(ArFunctor *functor)
02050 {
02051   myStabilizingCBList.remove(functor);
02052 }
02053 
02054 
02055 AREXPORT std::list<ArFunctor *> * ArRobot::getRunExitListCopy()
02056 {
02057   return(new std::list<ArFunctor *>(myRunExitCBList));
02058 }
02059 
02075 AREXPORT ArRobot::WaitState ArRobot::waitForConnect(unsigned int msecs)
02076 {
02077   int ret;
02078 
02079   if (isConnected())
02080     return(WAIT_CONNECTED);
02081 
02082   if (msecs == 0)
02083     ret=myConnectCond.wait();
02084   else
02085     ret=myConnectCond.timedWait(msecs);
02086 
02087   if (ret == ArCondition::STATUS_WAIT_INTR)
02088     return(WAIT_INTR);
02089   else if (ret == ArCondition::STATUS_WAIT_TIMEDOUT)
02090     return(WAIT_TIMEDOUT);
02091   else if (ret == 0)
02092     return(WAIT_CONNECTED);
02093   else
02094     return(WAIT_FAIL);
02095 }
02096 
02106 AREXPORT ArRobot::WaitState
02107 ArRobot::waitForConnectOrConnFail(unsigned int msecs)
02108 {
02109   int ret;
02110 
02111   if (isConnected())
02112     return(WAIT_CONNECTED);
02113 
02114   if (msecs == 0)
02115     ret=myConnOrFailCond.wait();
02116   else
02117     ret=myConnOrFailCond.timedWait(msecs);
02118 
02119   if (ret == ArCondition::STATUS_WAIT_INTR)
02120     return(WAIT_INTR);
02121   else if (ret == ArCondition::STATUS_WAIT_TIMEDOUT)
02122     return(WAIT_TIMEDOUT);
02123   else if (ret == 0)
02124   {
02125     if (isConnected())
02126       return(WAIT_CONNECTED);
02127     else
02128       return(WAIT_FAILED_CONN);
02129   }
02130   else
02131     return(WAIT_FAIL);
02132 }
02133 
02142 AREXPORT ArRobot::WaitState ArRobot::waitForRunExit(unsigned int msecs)
02143 {
02144   int ret;
02145 
02146   if (!isRunning())
02147     return(WAIT_RUN_EXIT);
02148 
02149   if (msecs == 0)
02150     ret=myRunExitCond.wait();
02151   else
02152     ret=myRunExitCond.timedWait(msecs);
02153 
02154   if (ret == ArCondition::STATUS_WAIT_INTR)
02155     return(WAIT_INTR);
02156   else if (ret == ArCondition::STATUS_WAIT_TIMEDOUT)
02157     return(WAIT_TIMEDOUT);
02158   else if (ret == 0)
02159     return(WAIT_RUN_EXIT);
02160   else
02161     return(WAIT_FAIL);
02162 }
02163 
02171 AREXPORT void ArRobot::wakeAllWaitingThreads()
02172 {
02173   wakeAllConnWaitingThreads();
02174   wakeAllRunExitWaitingThreads();
02175 }
02176 
02182 AREXPORT void ArRobot::wakeAllConnWaitingThreads()
02183 {
02184   myConnectCond.broadcast();
02185   myConnOrFailCond.broadcast();
02186 }
02187 
02194 AREXPORT void ArRobot::wakeAllConnOrFailWaitingThreads()
02195 {
02196   myConnOrFailCond.broadcast();
02197 }
02198 
02204 AREXPORT void ArRobot::wakeAllRunExitWaitingThreads()
02205 {
02206   myRunExitCond.broadcast();
02207 }
02208 
02216 AREXPORT ArSyncTask *ArRobot::getSyncTaskRoot(void)
02217 {
02218   return mySyncTaskRoot;
02219 }
02220 
02237 AREXPORT bool ArRobot::addUserTask(const char *name, int position, 
02238                       ArFunctor *functor, 
02239                       ArTaskState::State *state)
02240 {
02241   ArSyncTask *proc;
02242   if (mySyncTaskRoot == NULL)
02243     return false;
02244 
02245   proc = mySyncTaskRoot->findNonRecursive("User Tasks");
02246   if (proc == NULL)
02247     return false;
02248   
02249   proc->addNewLeaf(name, position, functor, state);
02250   return true;  
02251 }
02252 
02257 AREXPORT void ArRobot::remUserTask(const char *name)
02258 {
02259   ArSyncTask *proc;
02260   ArSyncTask *userProc;
02261 
02262   if (mySyncTaskRoot == NULL)
02263     return;
02264 
02265   proc = mySyncTaskRoot->findNonRecursive("User Tasks");
02266   if (proc == NULL)
02267     return;
02268   
02269   userProc = proc->findNonRecursive(name);
02270   if (userProc == NULL)
02271     return;
02272 
02273   
02274   delete userProc;
02275 
02276 }
02277 
02282 AREXPORT void ArRobot::remUserTask(ArFunctor *functor)
02283 {
02284   ArSyncTask *proc;
02285   ArSyncTask *userProc;
02286 
02287   if (mySyncTaskRoot == NULL)
02288     return;
02289 
02290   proc = mySyncTaskRoot->findNonRecursive("User Tasks");
02291   if (proc == NULL)
02292     return;
02293   
02294   
02295   userProc = proc->findNonRecursive(functor);
02296   if (userProc == NULL)
02297     return;
02298 
02299   
02300   delete userProc;
02301 
02302 }
02303 
02315 AREXPORT bool ArRobot::addSensorInterpTask(const char *name, int position, 
02316                           ArFunctor *functor,
02317                           ArTaskState::State *state)
02318 {
02319   ArSyncTask *proc;
02320   if (mySyncTaskRoot == NULL)
02321     return false;
02322 
02323   proc = mySyncTaskRoot->findNonRecursive("Sensor Interp");
02324   if (proc == NULL)
02325     return false;
02326   
02327   proc->addNewLeaf(name, position, functor, state);
02328   return true;  
02329 }
02330 
02335 AREXPORT void ArRobot::remSensorInterpTask(const char *name)
02336 {
02337   ArSyncTask *proc;
02338   ArSyncTask *sensorInterpProc;
02339 
02340   if (mySyncTaskRoot == NULL)
02341     return;
02342 
02343   proc = mySyncTaskRoot->findNonRecursive("Sensor Interp");
02344   if (proc == NULL)
02345     return;
02346   
02347   sensorInterpProc = proc->findNonRecursive(name);
02348   if (sensorInterpProc == NULL)
02349     return;
02350 
02351   
02352   delete sensorInterpProc;
02353 
02354 }
02355 
02360 AREXPORT void ArRobot::remSensorInterpTask(ArFunctor *functor)
02361 {
02362   ArSyncTask *proc;
02363   ArSyncTask *sensorInterpProc;
02364 
02365   if (mySyncTaskRoot == NULL)
02366     return;
02367 
02368   proc = mySyncTaskRoot->findNonRecursive("Sensor Interp");
02369   if (proc == NULL)
02370     return;
02371   
02372   
02373   sensorInterpProc = proc->findNonRecursive(functor);
02374   if (sensorInterpProc == NULL)
02375     return;
02376 
02377   
02378   delete sensorInterpProc;
02379 
02380 }
02381 
02385 AREXPORT void ArRobot::logUserTasks(void) const
02386 {
02387   ArSyncTask *proc;
02388   if (mySyncTaskRoot == NULL)
02389     return;
02390 
02391   proc = mySyncTaskRoot->findNonRecursive("User Tasks");
02392   if (proc == NULL)
02393     return;
02394 
02395   proc->log();
02396 }
02397 
02401 AREXPORT void ArRobot::logAllTasks(void) const
02402 {
02403   if (mySyncTaskRoot != NULL)
02404     mySyncTaskRoot->log();
02405 }
02406 
02412 AREXPORT ArSyncTask *ArRobot::findUserTask(const char *name)
02413 {
02414   ArSyncTask *proc;
02415   if (mySyncTaskRoot == NULL)
02416     return NULL;
02417 
02418   proc = mySyncTaskRoot->findNonRecursive("User Tasks");
02419   if (proc == NULL)
02420     return NULL;
02421 
02422   return proc->find(name);
02423 }
02424 
02430 AREXPORT ArSyncTask *ArRobot::findUserTask(ArFunctor *functor)
02431 {
02432   ArSyncTask *proc;
02433   if (mySyncTaskRoot == NULL)
02434     return NULL;
02435 
02436   proc = mySyncTaskRoot->findNonRecursive("User Tasks");
02437   if (proc == NULL)
02438     return NULL;
02439 
02440   return proc->find(functor);
02441 }
02442 
02448 AREXPORT ArSyncTask *ArRobot::findTask(const char *name)
02449 {
02450   if (mySyncTaskRoot != NULL)
02451     return mySyncTaskRoot->find(name);
02452   else
02453     return NULL;
02454 
02455 }
02456 
02462 AREXPORT ArSyncTask *ArRobot::findTask(ArFunctor *functor)
02463 {
02464   if (mySyncTaskRoot != NULL)
02465     return mySyncTaskRoot->find(functor);
02466   else
02467     return NULL;
02468 
02469 }
02470 
02492 AREXPORT bool ArRobot::addAction(ArAction *action, int priority)
02493 {
02494   if (action == NULL)
02495   {
02496     ArLog::log(ArLog::Terse, 
02497       "ArRobot::addAction: an attempt was made to add a NULL action pointer");
02498     return false;
02499   }
02500   
02501   action->setRobot(this);
02502   myActions.insert(std::pair<int, ArAction *>(priority, action));
02503   return true;
02504 }
02505 
02516 AREXPORT bool ArRobot::remAction(const char *actionName)
02517 {
02518   ArResolver::ActionMap::iterator it;
02519   ArAction *act;
02520 
02521   for (it = myActions.begin(); it != myActions.end(); ++it)
02522   {
02523     act = (*it).second;
02524     if (strcmp(actionName, act->getName()) == 0)
02525       break;
02526   }
02527   if (it != myActions.end())
02528   {
02529     myActions.erase(it);
02530     return true;
02531   }
02532   return false;
02533 
02534 }
02535 
02546 AREXPORT bool ArRobot::remAction(ArAction *action)
02547 {
02548   ArResolver::ActionMap::iterator it;
02549   ArAction *act;
02550 
02551   for (it = myActions.begin(); it != myActions.end(); ++it)
02552   {
02553     act = (*it).second;
02554     if (act == action)
02555       break;
02556   }
02557   if (it != myActions.end())
02558   {
02559     myActions.erase(it);
02560     return true;
02561   }
02562   return false;
02563 
02564 }
02565 
02566 
02576 AREXPORT ArAction *ArRobot::findAction(const char *actionName)
02577 {
02578   ArResolver::ActionMap::reverse_iterator it;
02579   ArAction *act;
02580   
02581   for (it = myActions.rbegin(); it != myActions.rend(); ++it)
02582   {
02583     act = (*it).second;
02584     if (strcmp(actionName, act->getName()) == 0)
02585       return act;
02586   }
02587   return NULL;
02588 }
02589 
02600 AREXPORT ArResolver::ActionMap *ArRobot::getActionMap(void)
02601 {
02602   return &myActions;
02603 }
02604 
02605 AREXPORT void ArRobot::deactivateActions(void)
02606 {
02607   ArResolver::ActionMap *am;
02608   ArResolver::ActionMap::iterator amit;
02609   
02610   am = getActionMap();
02611   if (am == NULL)
02612   {
02613     ArLog::log(ArLog::Terse, 
02614             "ArRobot::deactivateActions: NULL action map... failed.");
02615     return;
02616   }
02617   for (amit = am->begin(); amit != am->end(); amit++)
02618     (*amit).second->deactivate();
02619   
02620 
02621 }
02622 
02623 
02624 AREXPORT void ArRobot::logActions(bool logDeactivated) const
02625 {
02626   ArResolver::ActionMap::const_reverse_iterator it;
02627   int lastPriority;
02628   bool first = true;
02629   const ArAction *action;
02630 
02631   if (logDeactivated)
02632     ArLog::log(ArLog::Terse, "The action list (%d total):", 
02633            myActions.size());
02634   else
02635     ArLog::log(ArLog::Terse, "The active action list:");
02636 
02637   for (it = myActions.rbegin(); it != myActions.rend(); ++it)
02638   {
02639     action = (*it).second;
02640     if ((logDeactivated || action->isActive()) &&
02641     (first || lastPriority != (*it).first))
02642     {
02643       ArLog::log(ArLog::Terse, "Priority %d:", (*it).first);
02644       first = false;
02645       lastPriority = (*it).first;
02646     }
02647     action->log(false);
02648   }
02649 }
02650 
02651 AREXPORT ArResolver *ArRobot::getResolver(void)
02652 {
02653   return myResolver;
02654 }
02655 
02656 AREXPORT void ArRobot::setResolver(ArResolver *resolver)
02657 {
02658   if (myOwnTheResolver)
02659   {
02660     delete myResolver;
02661     myResolver = NULL;
02662   }
02663 
02664   myResolver = resolver;
02665 }
02666 
02678 AREXPORT void ArRobot::stateReflector(void)
02679 {
02680   short transVal;
02681   short transVal2;
02682   short maxVel;
02683   short maxNegVel;
02684   double maxTransVel;
02685   double maxNegTransVel;
02686   double maxRotVel;
02687   double transAccel;
02688   double transDecel;
02689   short rotVal;
02690   double rotAccel;
02691   double rotDecel;
02692   bool rotStopped = false;
02693   bool rotHeading = false;
02694   double encTh;
02695   double rawTh;
02696 
02697 
02698   if (!myIsConnected)
02699     return;
02700 
02701   myTryingToMove = false;
02702 
02703   // if this is true actions can't go
02704   if ((myTransType != TRANS_NONE && myDirectPrecedenceTime == 0) ||
02705       (myTransType != TRANS_NONE && myDirectPrecedenceTime != 0 && 
02706        myTransSetTime.mSecSince() < myDirectPrecedenceTime))
02707   {
02708     myActionTransSet = false;
02709     transVal = ArMath::roundShort(myTransVal);
02710     transVal2 = 0;
02711 
02712     if (hasSettableVelMaxes() && 
02713     ArMath::fabs(myLastSentTransVelMax - myTransVelMax) >= 1)
02714     {
02715       comInt(ArCommands::SETV,
02716          ArMath::roundShort(myTransVelMax));
02717       myLastSentTransVelMax = myTransVelMax;
02718       if (myLogMovementSent)
02719     ArLog::log(ArLog::Normal, "Non-action trans max vel of %d", 
02720            ArMath::roundShort(myTransVelMax));
02721     }
02722 
02723     if (hasSettableAccsDecs() && ArMath::fabs(myTransAccel) > 1 && 
02724     ArMath::fabs(myLastSentTransAccel - myTransAccel) >= 1)
02725     {
02726       comInt(ArCommands::SETA,
02727          ArMath::roundShort(myTransAccel));
02728       myLastSentTransAccel = myTransAccel;
02729       if (myLogMovementSent)
02730     ArLog::log(ArLog::Normal, "Non-action trans accel of %d", 
02731            ArMath::roundShort(myTransAccel));
02732     }
02733 
02734     if (hasSettableAccsDecs() && ArMath::fabs(myTransDecel) > 1 &&
02735     ArMath::fabs(myLastSentTransDecel - myTransDecel) >= 1)
02736     {
02737       comInt(ArCommands::SETA,
02738          -ArMath::roundShort(myTransDecel));
02739       myLastSentTransDecel = myTransDecel;
02740       if (myLogMovementSent)
02741     ArLog::log(ArLog::Normal, "Non-action trans decel of %d", 
02742            -ArMath::roundShort(myTransDecel));
02743     }
02744 
02745     if (myTransType == TRANS_VEL)
02746     {
02747       maxVel = ArMath::roundShort(myTransVelMax);
02748       if (transVal > maxVel)
02749     transVal = maxVel;
02750       if (transVal < -maxVel)
02751     transVal = -maxVel;
02752       if (myLastTransVal != transVal || myLastTransType != myTransType ||
02753       (myLastTransSent.mSecSince() >= myStateReflectionRefreshTime))
02754       {
02755     comInt(ArCommands::VEL, ArMath::roundShort(transVal));
02756     myLastTransSent.setToNow();
02757     if (myLogMovementSent)
02758       ArLog::log(ArLog::Normal, "Non-action trans vel of %d", 
02759              ArMath::roundShort(transVal));
02760     //printf("Sent command vel!\n");
02761       }
02762       if (fabs((double)transVal) > (double).5)
02763     myTryingToMove = true;
02764     }
02765     else if (myTransType == TRANS_VEL2)
02766     {
02767       if (ArMath::roundShort(myTransVal/myParams->getVel2Divisor()) > 128)
02768     transVal = 128;
02769       else if (ArMath::roundShort(myTransVal/myParams->getVel2Divisor()) < -128)
02770     transVal = -128;
02771       else 
02772     transVal = ArMath::roundShort(myTransVal/myParams->getVel2Divisor());
02773       if (ArMath::roundShort(myTransVal2/myParams->getVel2Divisor()) > 128)
02774     transVal2 = 128;
02775       else if (ArMath::roundShort(myTransVal2/myParams->getVel2Divisor()) < -128)
02776     transVal2 = -128;
02777       else 
02778     transVal2 = ArMath::roundShort(myTransVal2/myParams->getVel2Divisor());
02779       if (myLastTransVal != transVal || myLastTransVal2 != transVal2 || 
02780       myLastTransType != myTransType ||
02781       (myLastTransSent.mSecSince() >= myStateReflectionRefreshTime))
02782       {
02783     com2Bytes(ArCommands::VEL2, transVal, transVal2);
02784     myLastTransSent.setToNow();
02785     if (myLogMovementSent)
02786       ArLog::log(ArLog::Normal, "Non-action vel2 of %d %d", 
02787              transVal, transVal2);
02788     //printf("Sent command vel2!\n");
02789       }
02790       if (fabs((double)transVal) > (double).5 || fabs((double)transVal2) > (double).5)
02791     myTryingToMove = true;
02792     }
02793     else if (myTransType == TRANS_DIST_NEW || myTransType == TRANS_DIST)
02794     {
02795       // if the robot doesn't have its own distance command
02796       if (!myParams->hasMoveCommand())
02797       {
02798     double distGone;
02799     double distToGo;
02800     double vel;
02801 
02802     myTransType = TRANS_DIST;
02803     distGone = myTransDistStart.findDistanceTo(getPose());
02804     distToGo = fabs(fabs(myTransVal) - distGone);
02805     if (distGone > fabs(myTransVal) || 
02806         (distToGo < 10 && fabs(getVel()) < 30))
02807     {
02808       comInt(ArCommands::VEL, 0);
02809       myTransType = TRANS_VEL;
02810       myTransVal = 0;
02811     }
02812     else
02813       myTryingToMove = true;
02814     vel = sqrt(distToGo * 200 * 2);
02815     if (vel > getTransVelMax())
02816       vel = getTransVelMax();
02817     if (myTransVal < 0)
02818       vel *= -1;
02819     comInt(ArCommands::VEL, ArMath::roundShort(vel));
02820     if (myLogMovementSent)
02821       ArLog::log(ArLog::Normal, "Non-action move-helper of %d", 
02822              ArMath::roundShort(vel));
02823       }
02824       else if (myParams->hasMoveCommand() && myTransType == TRANS_DIST_NEW) 
02825       {
02826     comInt(ArCommands::MOVE, transVal);
02827     myLastTransSent.setToNow();
02828     myTransType = TRANS_DIST;
02829     if (myLogMovementSent)
02830       ArLog::log(ArLog::Normal, "Non-action move of %d", 
02831              transVal);
02832     myTryingToMove = true;
02833       }
02834       else if (myTransType == TRANS_DIST && 
02835       (myLastTransSent.mSecSince() >= myStateReflectionRefreshTime))
02836       {
02837     com(0);
02838     myLastPulseSent.setToNow();
02839     myLastTransSent.setToNow();
02840     //printf("Sent pulse for dist!\n");
02841     if (myLogMovementSent)
02842       ArLog::log(ArLog::Normal, "Non-action pulse for dist");
02843       }
02844       //printf("Sent command move!\n");
02845     }
02846     else if (myTransType == TRANS_IGNORE)
02847     {
02848       //printf("No trans command sent\n");
02849     }
02850     else
02851       ArLog::log(ArLog::Terse, 
02852          "ArRobot::stateReflector: Invalid translational type %d.",
02853          myTransType);
02854     myLastTransVal = transVal;
02855     myLastTransVal2 = transVal2;
02856     myLastTransType = myTransType;
02857   }
02858   else // if actions can go
02859   {
02860     if (hasSettableVelMaxes() && 
02861     ArMath::fabs(myLastSentTransVelMax - myTransVelMax) >= 1)
02862     {
02863       comInt(ArCommands::SETV,
02864          ArMath::roundShort(myTransVelMax));
02865       myLastSentTransVelMax = myTransVelMax;
02866       if (myLogMovementSent)
02867     ArLog::log(ArLog::Normal, "Action-but-robot trans max vel of %d", 
02868            ArMath::roundShort(myTransVelMax));
02869     }
02870     
02871     // first we'll handle all of the accel decel things
02872     if (myActionDesired.getTransAccelStrength() >= 
02873     ArActionDesired::MIN_STRENGTH)
02874     {
02875       transAccel = ArMath::roundShort(myActionDesired.getTransAccel());
02876       if (hasSettableAccsDecs() && ArMath::fabs(transAccel) > 1 &&
02877       ArMath::fabs(myLastSentTransAccel - transAccel) >= 1)
02878       {
02879     comInt(ArCommands::SETA,
02880            ArMath::roundShort(transAccel));
02881     myLastSentTransAccel = transAccel;
02882     if (myLogMovementSent)
02883       ArLog::log(ArLog::Normal, "Action trans accel of %d", 
02884              ArMath::roundShort(transAccel));
02885       }
02886     }
02887     else if (hasSettableAccsDecs() && ArMath::fabs(myTransAccel) > 1 && 
02888     ArMath::fabs(myLastSentTransAccel - myTransAccel) >= 1)
02889     {
02890       comInt(ArCommands::SETA,
02891          ArMath::roundShort(myTransAccel));
02892       myLastSentTransAccel = myTransAccel;
02893       if (myLogMovementSent)
02894     ArLog::log(ArLog::Normal, "Action-but-robot trans accel of %d", 
02895            ArMath::roundShort(myTransAccel));
02896     }
02897 
02898     if (myActionDesired.getTransDecelStrength() >=
02899     ArActionDesired::MIN_STRENGTH)
02900     {
02901       transDecel = ArMath::roundShort(myActionDesired.getTransDecel());
02902       if (hasSettableAccsDecs() && ArMath::fabs(transDecel) > 1 &&
02903       ArMath::fabs(myLastSentTransDecel - transDecel) >= 1)
02904       {
02905     comInt(ArCommands::SETA,
02906            -ArMath::roundShort(transDecel));
02907     myLastSentTransDecel = transDecel;
02908     if (myLogMovementSent)
02909       ArLog::log(ArLog::Normal, "Action trans decel of %d", 
02910              -ArMath::roundShort(transDecel));
02911       }
02912     }
02913     else if (hasSettableAccsDecs() && ArMath::fabs(myTransDecel) > 1 &&
02914     ArMath::fabs(myLastSentTransDecel - myTransDecel) >= 1)
02915     {
02916       comInt(ArCommands::SETA,
02917          -ArMath::roundShort(myTransDecel));
02918       myLastSentTransDecel = myTransDecel;
02919       if (myLogMovementSent)
02920     ArLog::log(ArLog::Normal, "Action-but-robot trans decel of %d", 
02921            -ArMath::roundShort(myTransDecel));
02922     }
02923 
02924     if (myActionDesired.getMaxVelStrength() >= ArActionDesired::MIN_STRENGTH)
02925     {
02926       maxTransVel = myActionDesired.getMaxVel();
02927       if (maxTransVel > myTransVelMax)
02928     maxTransVel = myTransVelMax;
02929     }
02930     else
02931       maxTransVel = myTransVelMax;
02932 
02933     if (myActionDesired.getMaxNegVelStrength() >= 
02934     ArActionDesired::MIN_STRENGTH)
02935     {
02936       maxNegTransVel = -ArMath::fabs(myActionDesired.getMaxNegVel());
02937       if (maxNegTransVel < -myTransVelMax)
02938     maxNegTransVel = -myTransVelMax;
02939     }
02940     else
02941       maxNegTransVel = -myTransVelMax;
02942     
02943     if (myActionDesired.getVelStrength() >= ArActionDesired::MIN_STRENGTH)
02944     {
02945       transVal = ArMath::roundShort(myActionDesired.getVel());
02946       myActionTransSet = true;
02947     }
02948     else
02949     {
02950       transVal = myLastActionTransVal;
02951     }
02952 
02953     if (fabs((double)transVal) > (double).5)
02954       myTryingToMove = true;
02955 
02956     maxVel = ArMath::roundShort(maxTransVel);
02957     maxNegVel = ArMath::roundShort(maxNegTransVel);
02958     if (transVal > maxVel)
02959       transVal = maxVel;
02960     if (transVal < maxNegVel)
02961       transVal = maxNegVel;
02962 
02963     if (myActionTransSet && 
02964     (myLastTransSent.mSecSince() >= myStateReflectionRefreshTime ||
02965      transVal != myLastActionTransVal))              
02966     {
02967       comInt(ArCommands::VEL, ArMath::roundShort(transVal));
02968       myLastTransSent.setToNow();
02969       if (myLogMovementSent)
02970     ArLog::log(ArLog::Normal, "Action trans vel of %d", 
02971            ArMath::roundShort(transVal));      
02972     }
02973     myLastActionTransVal = transVal;
02974   }
02975 
02976   // if this is true actions can't go
02977   if ((myRotType != ROT_NONE && myDirectPrecedenceTime == 0) ||
02978       (myRotType != ROT_NONE && myDirectPrecedenceTime != 0 && 
02979        myRotSetTime.mSecSince() < myDirectPrecedenceTime))
02980   {
02981     if (hasSettableVelMaxes() && 
02982     ArMath::fabs(myLastSentRotVelMax - myRotVelMax) >= 1)
02983     {
02984       comInt(ArCommands::SETRV,
02985          ArMath::roundShort(myRotVelMax));
02986       myLastSentRotVelMax = myRotVelMax;
02987     }
02988     if (hasSettableAccsDecs() && ArMath::fabs(myRotAccel) > 1 &&
02989     ArMath::fabs(myLastSentRotAccel - myRotAccel) >= 1)
02990     {
02991       comInt(ArCommands::SETRA,
02992          ArMath::roundShort(myRotAccel));
02993       myLastSentRotAccel = myRotAccel;
02994       if (myLogMovementSent)
02995     ArLog::log(ArLog::Normal, "%25sNon-action rot accel of %d", "",
02996            ArMath::roundShort(myRotAccel));      
02997     }
02998     if (hasSettableAccsDecs() && ArMath::fabs(myRotDecel) > 1 &&
02999     ArMath::fabs(myLastSentRotDecel - myRotDecel) >= 1)
03000     {
03001       comInt(ArCommands::SETRA,
03002          -ArMath::roundShort(myRotDecel));
03003       myLastSentRotDecel = myRotDecel;
03004       if (myLogMovementSent)
03005     ArLog::log(ArLog::Normal, "%25sNon-action rot decel of %d", "",
03006            -ArMath::roundShort(myRotDecel));      
03007     }
03008 
03009     myActionRotSet = false;
03010     rotVal = ArMath::roundShort(myRotVal);
03011     if (myRotType == ROT_HEADING)
03012     {
03013       encTh = ArMath::subAngle(myRotVal, myEncoderTransform.getTh());
03014       rawTh = ArMath::addAngle(encTh, 
03015                    ArMath::subAngle(myRawEncoderPose.getTh(),
03016                         myEncoderPose.getTh()));
03017       rotVal = ArMath::roundShort(rawTh);
03018 
03019       // if we were using a different heading type, a different heading
03020       // our heading doesn't match what we want it to be, or its been a while
03021       // since we sent the heading, send it again
03022       if (myLastRotVal != rotVal || myLastRotType != myRotType ||
03023       fabs(ArMath::subAngle(rotVal, getTh())) > 1 ||
03024       (myLastRotSent.mSecSince() >= myStateReflectionRefreshTime))
03025       {
03026     comInt(ArCommands::HEAD, rotVal);
03027     myLastRotSent.setToNow();
03028     //printf("sent command, heading\n");
03029     if (myLogMovementSent)
03030       ArLog::log(ArLog::Normal, 
03031          "%25sNon-action rot heading of %d (encoder %d, raw %d)",
03032              "",
03033              ArMath::roundShort(myRotVal),
03034              ArMath::roundShort(encTh),
03035              ArMath::roundShort(rotVal));
03036       }
03037       if (fabs(ArMath::subAngle(rotVal, getTh())) > 1)
03038     myTryingToMove = true;
03039     }
03040     else if (myRotType == ROT_VEL)
03041     {
03042       if (myLastRotVal != rotVal || myLastRotType != myRotType ||
03043       (myLastRotSent.mSecSince() >= myStateReflectionRefreshTime))
03044       {
03045     comInt(ArCommands::RVEL, rotVal);
03046     myLastRotSent.setToNow();
03047     if (myLogMovementSent)
03048       ArLog::log(ArLog::Normal, "%25sNon-action rot vel of %d", "",
03049              rotVal);      
03050     //printf("sent command, rot vel\n");
03051     if (fabs((double)rotVal) > (double).5)
03052       myTryingToMove = true;
03053       }
03054     }
03055     else if (myRotType == ROT_IGNORE)
03056     {
03057       //printf("Not sending any command, rot is set to ignore");
03058     }
03059     else
03060       ArLog::log(ArLog::Terse, 
03061          "ArRobot::stateReflector: Invalid rotation type %d.",
03062          myRotType);
03063     myLastRotVal = rotVal;
03064     myLastRotType = myRotType;
03065   }
03066   else // if the action can fire
03067   {
03068     // first we'll handle all of the accel decel things
03069     if (myActionDesired.getMaxRotVelStrength() >=
03070     ArActionDesired::MIN_STRENGTH)
03071     {
03072       maxRotVel = myActionDesired.getMaxRotVel();
03073       if (maxRotVel > myAbsoluteMaxRotVel)
03074     maxRotVel = myAbsoluteMaxRotVel;
03075       maxRotVel = ArMath::roundShort(maxRotVel);
03076       if (ArMath::fabs(myLastSentRotVelMax - maxRotVel) >= 1)
03077       {
03078     myLastSentRotVelMax = maxRotVel;
03079     comInt(ArCommands::SETRV, 
03080            ArMath::roundShort(maxRotVel));
03081     if (myLogMovementSent)
03082       ArLog::log(ArLog::Normal, "%25sAction rot vel max of %d", "",
03083              ArMath::roundShort(maxRotVel));
03084       }
03085     }
03086     else if (hasSettableVelMaxes() && 
03087          ArMath::fabs(myLastSentRotVelMax - myRotVelMax) >= 1)
03088     {
03089       comInt(ArCommands::SETRV,
03090          ArMath::roundShort(myRotVelMax));
03091       myLastSentRotVelMax = myRotVelMax;
03092       if (myLogMovementSent)
03093     ArLog::log(ArLog::Normal, 
03094            "%25sAction-but-robot rot vel max of %d", 
03095            "",  ArMath::roundShort(myRotVelMax));      
03096     }
03097 
03098     if (myActionDesired.getRotAccelStrength() >= ArActionDesired::MIN_STRENGTH)
03099     {
03100       rotAccel = ArMath::roundShort(myActionDesired.getRotAccel());
03101       if (ArMath::fabs(myLastSentRotAccel - rotAccel) >= 1)
03102       {
03103     comInt(ArCommands::SETRA,
03104            ArMath::roundShort(rotAccel));
03105     myLastSentRotAccel = rotAccel;
03106     if (myLogMovementSent)
03107       ArLog::log(ArLog::Normal, "%25sAction rot accel of %d", "",
03108              ArMath::roundShort(rotAccel));
03109       }
03110     }
03111     else if (hasSettableAccsDecs() && ArMath::fabs(myRotAccel) > 1 &&
03112     ArMath::fabs(myLastSentRotAccel - myRotAccel) >= 1)
03113     {
03114       comInt(ArCommands::SETRA,
03115          ArMath::roundShort(myRotAccel));
03116       myLastSentRotAccel = myRotAccel;
03117       if (myLogMovementSent)
03118     ArLog::log(ArLog::Normal, "%25sAction-but-robot rot accel of %d", 
03119            "", ArMath::roundShort(myRotAccel));      
03120     }
03121 
03122     if (myActionDesired.getRotDecelStrength() >= ArActionDesired::MIN_STRENGTH)
03123     {
03124       rotDecel = ArMath::roundShort(myActionDesired.getRotDecel());
03125       if (ArMath::fabs(myLastSentRotDecel - rotDecel) >= 1)
03126       {
03127     comInt(ArCommands::SETRA,
03128            -ArMath::roundShort(rotDecel));
03129     myLastSentRotDecel = rotDecel;
03130     if (myLogMovementSent)
03131       ArLog::log(ArLog::Normal, "%25sAction rot decel of %d", "",
03132              -ArMath::roundShort(rotDecel));
03133       }
03134     }
03135     else if (hasSettableAccsDecs() && ArMath::fabs(myRotDecel) > 1 &&
03136     ArMath::fabs(myLastSentRotDecel - myRotDecel) >= 1)
03137     {
03138       comInt(ArCommands::SETRA,
03139          -ArMath::roundShort(myRotDecel));
03140       myLastSentRotDecel = myRotDecel;
03141       if (myLogMovementSent)
03142     ArLog::log(ArLog::Normal, "%25sAction-but-robot rot decel of %d", 
03143            "", -ArMath::roundShort(myRotDecel));      
03144     }
03145 
03146 
03147 
03148     if (myActionDesired.getDeltaHeadingStrength() >=
03149                                          ArActionDesired::MIN_STRENGTH)
03150     {
03151       if (ArMath::roundShort(myActionDesired.getDeltaHeading()) == 0)
03152       {
03153     rotStopped = true;
03154     rotVal = 0;
03155     rotHeading = false;
03156       }
03157       else
03158       {
03159     //printf("delta %.0f\n", myActionDesired.getDeltaHeading());
03160     //encTh = ArMath::subAngle(myRotVal, myEncoderTransform.getTh());
03161     encTh = ArMath::subAngle(
03162         ArMath::addAngle(myActionDesired.getDeltaHeading(), 
03163                  getTh()),
03164         myEncoderTransform.getTh());
03165     //printf("final th %.0f\n", th);
03166     rawTh = ArMath::addAngle(encTh, 
03167                  ArMath::subAngle(myRawEncoderPose.getTh(),
03168                           myEncoderPose.getTh()));
03169     rotVal = ArMath::roundShort(rawTh);
03170     rotStopped = false;
03171     rotHeading = true;
03172     myTryingToMove = true;
03173       }
03174       myActionRotSet = true;
03175     } 
03176     else if (myActionDesired.getRotVelStrength() >=
03177                                          ArActionDesired::MIN_STRENGTH)
03178     {
03179       if (ArMath::roundShort(myActionDesired.getRotVel()) == 0)
03180       {
03181     rotStopped = true;
03182     rotVal = 0;
03183     rotHeading = false;
03184       }
03185       else
03186       {
03187     rotStopped = false;
03188     rotVal = ArMath::roundShort(myActionDesired.getRotVel());
03189     rotHeading = false;
03190     myTryingToMove = true;
03191       }
03192       myActionRotSet = true;
03193     }
03194     else
03195     {
03196       rotStopped = myLastActionRotStopped;
03197       rotVal = myLastActionRotVal;
03198       rotHeading = myLastActionRotHeading;
03199     }
03200 
03201     if (myActionRotSet && 
03202     (myLastRotSent.mSecSince() > myStateReflectionRefreshTime ||
03203      rotStopped != myLastActionRotStopped || 
03204      rotVal != myLastActionRotVal || 
03205      rotHeading != myLastActionRotHeading))
03206     {
03207       if (rotStopped)
03208       {
03209     comInt(ArCommands::RVEL, 0);
03210     if (myLogMovementSent)
03211       ArLog::log(ArLog::Normal, 
03212              "%25sAction rot vel of 0 (rotStopped)",
03213              "");
03214       }
03215       else if (rotHeading)
03216       {
03217     comInt(ArCommands::HEAD, rotVal);
03218     if (myLogMovementSent)
03219       ArLog::log(ArLog::Normal, 
03220              "%25sAction rot heading of %d (encoder %d, raw %d)",
03221              "",
03222              ArMath::roundShort(ArMath::addAngle(
03223                  myActionDesired.getDeltaHeading(), 
03224                  getTh())),
03225              ArMath::roundShort(encTh),
03226              ArMath::roundShort(rotVal));
03227       }
03228       else
03229       {
03230     comInt(ArCommands::RVEL, rotVal);
03231     if (myLogMovementSent)
03232       ArLog::log(ArLog::Normal, "%25sAction rot vel of %d", "", 
03233              rotVal);
03234       }
03235       myLastRotSent.setToNow();
03236     }           
03237     
03238     myLastActionRotVal = rotVal;
03239     myLastActionRotStopped = rotStopped;
03240     myLastActionRotHeading = rotHeading;
03241   }
03242 
03243   if (myLastRotSent.mSecSince() > myStateReflectionRefreshTime &&
03244       myLastTransSent.mSecSince() > myStateReflectionRefreshTime &&
03245       myLastPulseSent.mSecSince() > myStateReflectionRefreshTime)
03246   {
03247     com(ArCommands::PULSE);
03248     myLastPulseSent.setToNow();
03249     if (myLogMovementSent)
03250       ArLog::log(ArLog::Normal, "Pulse"); 
03251 
03252   }
03253 }
03254 
03255 AREXPORT bool ArRobot::handlePacket(ArRobotPacket *packet)
03256 {
03257   std::list<ArRetFunctor1<bool, ArRobotPacket *> *>::iterator it;
03258   bool handled;
03259 
03260   lock();
03261   //printf("ms since last packet %ld this type 0x%x\n", myLastPacketReceivedTime.mSecSince(packet->getTimeReceived()), packet->getID());
03262   myLastPacketReceivedTime = packet->getTimeReceived();
03263   if (packet->getID() == 0xff) 
03264   {
03265     ArLog::log(ArLog::Terse, "Losing connection because robot was reset.");
03266     dropConnection();
03267     unlock();
03268     return false;
03269   }
03270 
03271   for (handled = false, it = myPacketHandlerList.begin(); 
03272        it != myPacketHandlerList.end() && handled == false; 
03273        it++)
03274   {
03275     if ((*it) != NULL && (*it)->invokeR(packet)) 
03276       handled = true;
03277     else
03278       packet->resetRead();
03279   }
03280   if (!handled)
03281     ArLog::log(ArLog::Normal, 
03282            "No packet handler wanted packet with ID: 0x%x", 
03283            packet->getID());
03284   unlock();
03285   return handled;
03286 }
03287 
03288 
03292 AREXPORT long int ArRobot::getLeftEncoder()
03293 {
03294   return myLeftEncoder;
03295 }
03296 
03300 AREXPORT long int ArRobot::getRightEncoder()
03301 {
03302   return myRightEncoder;
03303 }
03304 
03305 
03310 AREXPORT void ArRobot::robotLocker(void)
03311 {
03312   lock();
03313 }
03314 
03319 AREXPORT void ArRobot::robotUnlocker(void)
03320 {
03321   unlock();
03322 }
03323 
03330 AREXPORT void ArRobot::packetHandler(void)
03331 {
03332   ArRobotPacket *packet;
03333   int timeToWait;
03334   ArTime start;
03335   bool sipHandled = false;
03336 
03337   if (myAsyncConnectFlag)
03338   {
03339     lock();
03340     asyncConnectHandler(false);
03341     unlock();
03342     return;
03343   }
03344 
03345   if (!isConnected())
03346     return;
03347 
03348   start.setToNow();
03349   /*
03350     The basic idea is that if we're chained to the sip we run through
03351     and see if we have any packets available now (like if we got
03352     backed up), we only check this for half the cycle time
03353     though... if we know the cycle time of the robot (from config)
03354     then we go for half that, if we don't know the cycle time of the
03355     robot (from config) then we go for half of whatever our cycle time
03356     is set to
03357 
03358     if we don't have any packets waiting then we chill and wait for
03359     it, if we got one, just get on with it
03360   **/
03361   packet = NULL;
03362   // read all the packets that are available
03363   while ((packet = myReceiver.receivePacket(0)) != NULL)
03364   {
03365     if (myPacketsReceivedTracking)
03366     {
03367       ArLog::log(ArLog::Normal, 
03368          "Rcvd: prePacket (%ld) 0x%x at %ld (%ld)", 
03369          myPacketsReceivedTrackingCount, 
03370          packet->getID(), start.mSecSince(), 
03371          myPacketsReceivedTrackingStarted.mSecSince());
03372       myPacketsReceivedTrackingCount++;
03373     }
03374 
03375     handlePacket(packet);
03376     if ((packet->getID() & 0xf0) == 0x30)
03377       sipHandled = true;
03378     packet = NULL;
03379 
03380     // if we've taken too long here then break
03381     if ((getOrigRobotConfig()->hasPacketArrived() &&
03382      start.mSecSince() > getOrigRobotConfig()->getSipCycleTime() / 2) ||
03383     (!getOrigRobotConfig()->hasPacketArrived() &&
03384      (unsigned int) start.mSecSince() > myCycleTime / 2))
03385     {
03386       break;
03387     }
03388   }
03389 
03390   if (isCycleChained())
03391     timeToWait = getCycleTime() * 2 - start.mSecSince();
03392   
03393   // if we didn't get a sip and we're chained to the sip, wait for the sip
03394   while (isCycleChained() && !sipHandled && isRunning() && 
03395      (packet = myReceiver.receivePacket(timeToWait)) != NULL)
03396   {
03397     if (myPacketsReceivedTracking)
03398     {
03399       ArLog::log(ArLog::Normal, "Rcvd: Packet (%ld) 0x%x at %ld (%ld)", 
03400          myPacketsReceivedTrackingCount, 
03401          packet->getID(), start.mSecSince(), 
03402          myPacketsReceivedTrackingStarted.mSecSince());
03403       myPacketsReceivedTrackingCount++;
03404     }
03405 
03406     handlePacket(packet);
03407     if ((packet->getID() & 0xf0) == 0x30)
03408       break;
03409     timeToWait = getCycleTime() * 2 - start.mSecSince();
03410     if (timeToWait < 0)
03411       timeToWait = 0;
03412   }
03413 
03414   if (myTimeoutTime > 0 && 
03415       ((-myLastPacketReceivedTime.mSecTo()) > myTimeoutTime))
03416   {
03417     ArLog::log(ArLog::Terse, 
03418            "Losing connection because nothing received from robot in %d milliseconds.", 
03419            myTimeoutTime);
03420     dropConnection();
03421   }
03422 
03423   if (myPacketsReceivedTracking)
03424     ArLog::log(ArLog::Normal, "Rcvd: time taken %ld", start.mSecSince());
03425 
03426 }
03427 
03435 AREXPORT void ArRobot::actionHandler(void)
03436 {
03437   ArActionDesired *actDesired;
03438 
03439   if (myResolver == NULL || myActions.size() == 0 || !isConnected())
03440     return;
03441   
03442   actDesired = myResolver->resolve(&myActions, this, myLogActions);
03443   
03444   myActionDesired.reset();
03445 
03446   if (actDesired == NULL)
03447     return;
03448 
03449   myActionDesired.merge(actDesired);  
03450 
03451   if (myLogActions)
03452   {
03453     ArLog::log(ArLog::Normal, "Final resolved desired:");
03454     myActionDesired.log();
03455   }
03456 }
03457 
03466 AREXPORT void ArRobot::setCycleWarningTime(unsigned int ms)
03467 {
03468   myCycleWarningTime = ms;
03469   // we don't have to send it down because the functor gets it each cycle
03470 }
03471 
03480 AREXPORT unsigned int ArRobot::getCycleWarningTime(void) const
03481 {
03482   return myCycleWarningTime;
03483 }
03484 
03493 AREXPORT unsigned int ArRobot::getCycleWarningTime(void)
03494 {
03495   return myCycleWarningTime;
03496 }
03497 
03505 AREXPORT void ArRobot::setCycleTime(unsigned int ms)
03506 {
03507   myCycleTime = ms;
03508 }
03509 
03522 AREXPORT void ArRobot::setStabilizingTime(int mSecs)
03523 {
03524   if (mSecs > 0)
03525     myStabilizingTime = mSecs;
03526   else
03527     myStabilizingTime = 0;
03528 }
03529 
03535 AREXPORT int ArRobot::getStabilizingTime(void) const
03536 {
03537   return myStabilizingTime;
03538 }
03539 
03547 AREXPORT unsigned int ArRobot::getCycleTime(void) const
03548 {
03549   return myCycleTime;
03550 }
03551 
03552 
03553 
03562 AREXPORT void ArRobot::setConnectionCycleMultiplier(unsigned int multiplier)
03563 {
03564   myConnectionCycleMultiplier = multiplier;
03565 }
03566 
03574 AREXPORT unsigned int ArRobot::getConnectionCycleMultiplier(void) const
03575 {
03576   return myConnectionCycleMultiplier;
03577 }
03578 
03579 
03586 AREXPORT void ArRobot::loopOnce(void)
03587 {
03588   if (mySyncTaskRoot != NULL)
03589     mySyncTaskRoot->run();
03590   
03591   incCounter();
03592 }
03593 
03594 
03595 // DigIn IR logic is reverse.  0 means broken, 1 means not broken
03596 
03597 AREXPORT bool ArRobot::isLeftTableSensingIRTriggered(void) const
03598 {
03599   if (myParams->haveTableSensingIR())
03600   {
03601     if (myParams->haveNewTableSensingIR() && myIODigInSize > 3)
03602       return !(getIODigIn(3) & ArUtil::BIT1);
03603     else
03604       return !(getDigIn() & ArUtil::BIT0);
03605   }
03606   return 0;
03607 }
03608 
03609 AREXPORT bool ArRobot::isRightTableSensingIRTriggered(void) const
03610 {
03611   if (myParams->haveTableSensingIR())
03612   {
03613     if (myParams->haveNewTableSensingIR() && myIODigInSize > 3) 
03614       return !(getIODigIn(3) & ArUtil::BIT0);
03615     else
03616       return !(getDigIn() & ArUtil::BIT1);
03617   }
03618   return 0;
03619 }
03620 
03621 AREXPORT bool ArRobot::isLeftBreakBeamTriggered(void) const
03622 {
03623   if (myParams->haveTableSensingIR())
03624   {
03625     if (myParams->haveNewTableSensingIR() && myIODigInSize > 3) 
03626       return !(getIODigIn(3) & ArUtil::BIT2);
03627     else
03628       return !(getDigIn() & ArUtil::BIT3);
03629   }
03630   return 0;
03631 }
03632 
03633 AREXPORT bool ArRobot::isRightBreakBeamTriggered(void) const
03634 {
03635   if (myParams->haveTableSensingIR())
03636   {
03637     if (myParams->haveNewTableSensingIR() && myIODigInSize > 3) 
03638       return !(getIODigIn(3) & ArUtil::BIT3);
03639     else
03640       return !(getDigIn() & ArUtil::BIT2);
03641   }
03642   return 0;
03643 }
03644 
03645 AREXPORT int ArRobot::getMotorPacCount(void) const
03646 {
03647   if (myTimeLastMotorPacket == time(NULL))
03648     return myMotorPacCount;
03649   if (myTimeLastMotorPacket == time(NULL) - 1)
03650     return myMotorPacCurrentCount;
03651   return 0;
03652 }
03653 
03654 AREXPORT int ArRobot::getSonarPacCount(void) const
03655 {
03656   if (myTimeLastSonarPacket == time(NULL))
03657     return mySonarPacCount;
03658   if (myTimeLastSonarPacket == time(NULL) - 1)
03659     return mySonarPacCurrentCount;
03660   return 0;
03661 }
03662 
03663 
03664 AREXPORT bool ArRobot::processMotorPacket(ArRobotPacket *packet)
03665 {
03666   int x, y, th, qx, qy, qth; 
03667   double deltaX, deltaY, deltaTh;
03668 
03669   int numReadings;
03670   int sonarNum;
03671   int sonarRange;
03672 
03673   if (packet->getID() != 0x32 && packet->getID() != 0x33) 
03674     return false;
03675 
03676   // upkeep the counting variable
03677   if (myTimeLastMotorPacket != time(NULL)) 
03678   {
03679     myTimeLastMotorPacket = time(NULL);
03680     myMotorPacCount = myMotorPacCurrentCount;
03681     myMotorPacCurrentCount = 0;
03682   }
03683   myMotorPacCurrentCount++;
03684 
03685   x = (packet->bufToUByte2() & 0x7fff);
03686   y = (packet->bufToUByte2() & 0x7fff);
03687   th = packet->bufToByte2();
03688 
03689   if (myFirstEncoderPose)
03690   {
03691     qx = 0;
03692     qy = 0;
03693     qth = 0;
03694     myFirstEncoderPose = false;
03695     myRawEncoderPose.setPose(
03696         myParams->getDistConvFactor() * x,
03697         myParams->getDistConvFactor() * y, 
03698         ArMath::radToDeg(myParams->getAngleConvFactor() * (double)th));
03699     myEncoderPose = myRawEncoderPose;
03700     myEncoderTransform.setTransform(myEncoderPose, myGlobalPose);
03701   }
03702   else 
03703   {
03704     qx = x - myLastX;
03705     qy = y - myLastY;
03706     qth = th - myLastTh;
03707   }
03708 
03709 
03710   //ArLog::log(ArLog::Terse, "Damnit qx %d qy %d,  x %d y %d,  lastx %d lasty %d", qx, qy, x, y, myLastX, myLastY);  
03711   myLastX = x;
03712   myLastY = y;
03713   myLastTh = th;
03714 
03715   if (qx > 0x1000) 
03716     qx -= 0x8000;
03717   if (qx < -0x1000)
03718     qx += 0x8000;
03719 
03720   if (qy > 0x1000) 
03721     qy -= 0x8000;
03722   if (qy < -0x1000)
03723     qy += 0x8000;
03724   
03725   deltaX = myParams->getDistConvFactor() * (double)qx;
03726   deltaY = myParams->getDistConvFactor() * (double)qy;
03727   deltaTh = ArMath::radToDeg(myParams->getAngleConvFactor() * (double)qth);
03728   //encoderTh = ArMath::radToDeg(myParams->getAngleConvFactor() * (double)(th));
03729 
03730 
03731   // encoder stuff was here
03732 
03733 
03734 
03735   myLeftVel = myParams->getVelConvFactor() * packet->bufToByte2();
03736   myRightVel = myParams->getVelConvFactor() * packet->bufToByte2();
03737   myVel = (myLeftVel + myRightVel)/2.0;
03738 
03739   myBatteryVoltage = packet->bufToUByte() * .1;
03740   myBatteryAverager.add(myBatteryVoltage);
03741   myStallValue = packet->bufToByte2();
03742   
03743   //ArLog::log("x %.1f y %.1f th %.1f vel %.1f voltage %.1f", myX, myY, myTh, 
03744   //myVel, myBatteryVoltage);
03745 
03746   myControl = ArMath::fixAngle(ArMath::radToDeg(myParams->getAngleConvFactor() *
03747                   (packet->bufToByte2() - th)));
03748   myFlags = packet->bufToUByte2();
03749   myCompass = 2*packet->bufToUByte();
03750   
03751   for (numReadings = packet->bufToByte(); numReadings > 0; numReadings--)
03752   {
03753     sonarNum = packet->bufToByte();
03754     sonarRange = ArMath::roundInt(
03755         (double)packet->bufToUByte2() * myParams->getRangeConvFactor());
03756     processNewSonar(sonarNum, sonarRange, packet->getTimeReceived());
03757   }
03758   
03759   if (packet->getDataLength() - packet->getDataReadLength() > 0)
03760   {
03761     myAnalogPortSelected = packet->bufToUByte2();
03762     myAnalog = packet->bufToByte();
03763     myDigIn = packet->bufToByte();
03764     myDigOut = packet->bufToByte();
03765   }
03766 
03767   if (packet->getDataLength() - packet->getDataReadLength() > 0)
03768     myRealBatteryVoltage = packet->bufToUByte2() * .1;
03769   else
03770     myRealBatteryVoltage = myBatteryVoltage;
03771 
03772   myRealBatteryAverager.add(myRealBatteryVoltage);
03773 
03774   if (packet->getDataLength() - packet->getDataReadLength() > 0)
03775     myChargeState = (ChargeState) packet->bufToUByte();
03776   else
03777     myChargeState = CHARGING_UNKNOWN;
03778 
03779   if (packet->getDataLength() - packet->getDataReadLength() > 0)
03780     myRotVel = (double)packet->bufToByte2() / 10.0;
03781   else
03782     myRotVel = ArMath::radToDeg((myRightVel - myLeftVel) / 2.0 * 
03783                 myParams->getDiffConvFactor());
03784 
03785   if (packet->getDataLength() - packet->getDataReadLength() > 0)
03786   {
03787     myHasFaultFlags = true;
03788     myFaultFlags = packet->bufToUByte2();  
03789   }
03790   else
03791   {
03792     myHasFaultFlags = false;
03793     myFaultFlags = packet->bufToUByte2();  
03794   }
03795   /*
03796     Okay how this works is like so.  
03797 
03798     We keep around the raw encoder position, because we must use this
03799     to find differences between last position and this position.
03800     
03801     We find the difference in x and y positions (deltaX and deltaY)
03802     and keep these around for later use, but we also add these to our
03803     raw encoder readings for X and Y.  We also find the change in
03804     angle (deltaTh), which is used for inertial corrections, and added
03805     to the raw encoder heading to find which the current raw encoder
03806     heading.
03807 
03808 
03809     From here there are two paths:
03810 
03811     Path 1) Have a callback.  If we have a callback it means that we
03812     have an inertial nav device of some kind.  If this is the case,
03813     then we pass the callback the delta between last position and
03814     current position, along with the time of the current position,
03815     then the callback gives us back a new delta theta (deltaTh).  We
03816     then need to rotate the deltaX and deltaY into our corrected
03817     encoder space.  We do this by making a transform that takes the
03818     raw encoder heading and transforms it to what our new heading is
03819     (adding deltaTh to our current encoder th), and then applying that
03820     transform, taking the results as our new deltaX and deltaY.
03821 
03822     Path 2) We have no callback, we just use the heading that came
03823     back from the robot as our delta theta (deltaTh);
03824 
03825     From here the two paths unify again.  deltaX and deltaY are added
03826     to the encoder pose (this is the corrected encoder pose), and the
03827     encoder heading is set to the newTh.
03828 
03829     Note that this leaves a difference between rawEncoder heading and
03830     our heading, which is fine, BUT if you are sending heading
03831     commands to the robot you need to compenstate for the difference
03832     between these. 
03833     
03834     Note above that we return deltaTh instead of just heading so that
03835     we can turn inertial on and off without losing track of where
03836     we're at... since we're just adding in deltas from the heading it
03837     doesn't matter how we switch around the callback.
03838     
03839   **/
03840 
03841   myRawEncoderPose.setX(myRawEncoderPose.getX() + deltaX);
03842   myRawEncoderPose.setY(myRawEncoderPose.getY() + deltaY);
03843   myRawEncoderPose.setTh(myRawEncoderPose.getTh() + deltaTh);
03844 
03845   // check if there is a correction callback, if there is get the new
03846   // heading out of it instead of using the raw encoder heading
03847   if (myEncoderCorrectionCB != NULL)
03848   {
03849     ArPoseWithTime deltaPose(deltaX, deltaY, deltaTh,
03850                  packet->getTimeReceived());
03851     deltaTh = myEncoderCorrectionCB->invokeR(deltaPose);   
03852     ArTransform trans(ArPose(0, 0, myRawEncoderPose.getTh()),
03853               ArPose(0, 0,
03854                  ArMath::addAngle(myEncoderPose.getTh(), 
03855                           deltaTh)));
03856 
03857     ArPose rotatedDelta = trans.doTransform(ArPose(deltaX, deltaY, 0));
03858 
03859     deltaX = rotatedDelta.getX();
03860     deltaY = rotatedDelta.getY();
03861   }
03862 
03863   myEncoderPose.setTime(packet->getTimeReceived());
03864   myEncoderPose.setX(myEncoderPose.getX() + deltaX);
03865   myEncoderPose.setY(myEncoderPose.getY() + deltaY);
03866   myEncoderPose.setTh(ArMath::addAngle(myEncoderPose.getTh(), deltaTh));
03867 
03868   myGlobalPose = myEncoderTransform.doTransform(myEncoderPose);
03869 
03870   myOdometerDegrees += fabs(deltaTh);
03871   myOdometerDistance += sqrt(fabs(deltaX * deltaX + deltaY * deltaY));
03872 
03873   if (myLogMovementReceived)
03874     ArLog::log(ArLog::Normal, 
03875            "Global (%5.0f %5.0f %5.0f) Encoder (%5.0f %5.0f %5.0f) Raw (%5.0f %5.0f %5.0f) Rawest (%5d %5d %5d) Delta (%5.0f %5.0f %5.0f) Conv %5.2f",
03876            myGlobalPose.getX(), myGlobalPose.getY(),
03877            myGlobalPose.getTh(),
03878            myEncoderPose.getX(), myEncoderPose.getY(),
03879            myEncoderPose.getTh(),
03880            myRawEncoderPose.getX(), myRawEncoderPose.getY(), 
03881            myRawEncoderPose.getTh(), x, y, th, deltaX, deltaY, deltaTh,
03882            myParams->getDistConvFactor());        
03883 
03884   if (myLogVelocitiesReceived)
03885     ArLog::log(ArLog::Normal, 
03886            "     TransVel: %4.0f RotVel: %4.0f(%4.0f) Heading %4.0f TransAcc %4.0f RotAcc %4.0f(%4.0f)",
03887            myVel, myRotVel, myLastHeading - getTh(), getTh(), 
03888            myVel - myLastVel, myRotVel - myLastRotVel,
03889            myLastCalculatedRotVel - (myLastHeading - getTh()));
03890   myLastVel = myVel;
03891   myLastRotVel = myRotVel;
03892   myLastHeading = getTh();
03893   myLastCalculatedRotVel = myLastHeading - getTh();
03894 
03895   //ArLog::log(ArLog::Terse, "(%.0f %.0f) (%.0f %.0f)", deltaX, deltaY, myGlobalPose.getX(),         myGlobalPose.getY());
03896   
03897   myInterpolation.addReading(packet->getTimeReceived(), myGlobalPose);
03898   myEncoderInterpolation.addReading(packet->getTimeReceived(), myEncoderPose);
03899 
03900   return true;
03901 }
03902 
03903 AREXPORT void ArRobot::processNewSonar(char number, int range, 
03904                        ArTime timeReceived)
03905 {
03914   std::map<int, ArSensorReading *>::iterator it;
03915   ArSensorReading *sonar;
03916   ArTransform encoderTrans;
03917   ArPose encoderPose;
03918 
03919   if ((it = mySonars.find(number)) != mySonars.end())
03920   {
03921     sonar = (*it).second;
03922     sonar->newData(range, getPose(), getEncoderPose(), getToGlobalTransform(), 
03923            getCounter(), timeReceived); 
03924     if (myTimeLastSonarPacket != time(NULL)) 
03925     {
03926       myTimeLastSonarPacket = time(NULL);
03927       mySonarPacCount = mySonarPacCurrentCount;
03928       mySonarPacCurrentCount = 0;
03929     }
03930     mySonarPacCurrentCount++;
03931   }
03932   else if (!myWarnedAboutExtraSonar)
03933   {
03934     ArLog::log(ArLog::Normal, "Robot gave back extra sonar reading!  Either the parameter file for the robot or the firmware needs updating.");
03935     myWarnedAboutExtraSonar = true;
03936   }
03937 }
03938 
03939 
03940 
03941 AREXPORT bool ArRobot::processEncoderPacket(ArRobotPacket *packet)
03942 {
03943   if (packet->getID() != 0x90)
03944     return false;
03945   myLeftEncoder = packet->bufToByte4();
03946   myRightEncoder = packet->bufToByte4();
03947   return true;
03948 }
03949 
03950 AREXPORT bool ArRobot::processIOPacket(ArRobotPacket *packet)
03951 {
03952   int i, num;
03953 
03954   if (packet->getID() != 0xf0)
03955     return false;
03956 
03957   myLastIOPacketReceivedTime = packet->getTimeReceived();
03958 
03959   // number of DigIn bytes
03960   num = packet->bufToUByte();
03961   for (i = 0; i < num; ++i)
03962     myIODigIn[i] = packet->bufToUByte();
03963   myIODigInSize = num;
03964 
03965   // number of DigOut bytes
03966   num = packet->bufToUByte();
03967   for (i = 0; i < num; ++i)
03968     myIODigOut[i] = packet->bufToUByte();
03969   myIODigOutSize = num;
03970 
03971   // number of A/D bytes
03972   num = packet->bufToUByte();
03973   for (i = 0; i < num; ++i)
03974     myIOAnalog[i] = packet->bufToUByte2();
03975   myIOAnalogSize = num;
03976 
03977   return true;
03978 }
03979 
03989 AREXPORT int ArRobot::getSonarRange(int num) const
03990 {
03991   std::map<int, ArSensorReading *>::const_iterator it;
03992   
03993   if ((it = mySonars.find(num)) != mySonars.end())
03994     return (*it).second->getRange();
03995   else
03996     return -1;
03997 }
03998 
04009 AREXPORT bool ArRobot::isSonarNew(int num) const
04010 {
04011   std::map<int, ArSensorReading *>::const_iterator it;
04012   
04013   if ((it = mySonars.find(num)) != mySonars.end())
04014     return (*it).second->isNew(getCounter());
04015   else
04016     return false;
04017 }
04018 
04031 AREXPORT ArSensorReading *ArRobot::getSonarReading(int num) const
04032 {
04033   std::map<int, ArSensorReading *>::const_iterator it;
04034   
04035   if ((it = mySonars.find(num)) != mySonars.end())
04036     return (*it).second;
04037   else
04038     return NULL;
04039 }
04040 
04041 
04047 AREXPORT bool ArRobot::com(unsigned char command)
04048 {
04049   if (myPacketsSentTracking)
04050     ArLog::log(ArLog::Normal, "Sent: com(%d)", command);
04051   return mySender.com(command);
04052 }
04053 
04060 AREXPORT bool ArRobot::comInt(unsigned char command, short int argument)
04061 {
04062   if (myPacketsSentTracking)
04063     ArLog::log(ArLog::Normal, "Sent: comInt(%d, %d)", command, argument);
04064   return mySender.comInt(command, argument);
04065 }
04066 
04074 AREXPORT bool ArRobot::com2Bytes(unsigned char command, char high, char low)
04075 {
04076   if (myPacketsSentTracking)
04077     ArLog::log(ArLog::Normal, "Sent: com2Bytes(%d, %d, %d)", command, 
04078            high, low);
04079   return mySender.com2Bytes(command, high, low);
04080 }
04081 
04088 AREXPORT bool ArRobot::comStr(unsigned char command, const char *argument)
04089 {
04090   if (myPacketsSentTracking)
04091     ArLog::log(ArLog::Normal, "Sent: comStr(%d, '%s')", command, 
04092            argument);
04093   return mySender.comStr(command, argument);
04094 }
04095 
04105 AREXPORT bool ArRobot::comStrN(unsigned char command, const char *str, 
04106                    int size)
04107 {
04108   if (myPacketsSentTracking)
04109   {
04110     char strBuf[512];
04111     strncpy(strBuf, str, size);
04112     strBuf[size] = '\0';
04113     ArLog::log(ArLog::Normal, "Sent: comStrN(%d, '%s') (size %d)",
04114            command, strBuf, size);
04115   }
04116   return mySender.comStrN(command, str, size);
04117 }
04118 
04119 AREXPORT bool ArRobot::comDataN(unsigned char command, const char* data, int size)
04120 {
04121   if(myPacketsSentTracking)
04122   {
04123     ArLog::log(ArLog::Normal, "Sent: comDataN(%d, <data...>) (size %d)", command, size);
04124   }
04125   return mySender.comDataN(command, data, size);
04126 }
04127 
04128 
04129 AREXPORT int ArRobot::getClosestSonarRange(double startAngle, double endAngle) const
04130 {
04131   int num;
04132   num = getClosestSonarNumber(startAngle, endAngle);
04133   if (num == -1)
04134     return -1;
04135   else 
04136     return getSonarRange(num);
04137 }
04138 
04139 AREXPORT int ArRobot::getClosestSonarNumber(double startAngle, double endAngle) const
04140 {
04141   int i;
04142   ArSensorReading *sonar;
04143   int closestReading;
04144   int closestSonar;
04145   bool noReadings = true;
04146 
04147   for (i = 0; i < getNumSonar(); i++) 
04148   {
04149     sonar = getSonarReading(i);
04150     if (sonar == NULL)
04151     {
04152       ArLog::log(ArLog::Terse, "Have an empty sonar at number %d, there should be %d sonar.", i, getNumSonar());
04153       continue;
04154     }
04155     if (ArMath::angleBetween(sonar->getSensorTh(), startAngle, endAngle))
04156     {
04157       if (noReadings)
04158       {
04159     closestReading = sonar->getRange();
04160     closestSonar = i;
04161     noReadings = false;
04162       }
04163       else if (sonar->getRange() < closestReading)
04164       {
04165     closestReading = sonar->getRange();
04166     closestSonar = i;
04167       }
04168     }
04169   }
04170 
04171   if (noReadings)
04172     return -1;
04173   else
04174     return closestSonar;
04175 }
04176 
04177 AREXPORT void ArRobot::addRangeDevice(ArRangeDevice *device)
04178 {
04179   device->setRobot(this);
04180   myRangeDeviceList.push_front(device);
04181 }
04182 
04186 AREXPORT void ArRobot::remRangeDevice(const char *name)
04187 {
04188   std::list<ArRangeDevice *>::iterator it;
04189   for (it = myRangeDeviceList.begin(); it != myRangeDeviceList.end(); ++it)
04190   {
04191     if (strcmp(name, (*it)->getName()) == 0)
04192     {
04193       myRangeDeviceList.erase(it);
04194       return;
04195     }
04196   }
04197 }
04198 
04202 AREXPORT void ArRobot::remRangeDevice(ArRangeDevice *device)
04203 {
04204   std::list<ArRangeDevice *>::iterator it;
04205   for (it = myRangeDeviceList.begin(); it != myRangeDeviceList.end(); ++it)
04206   {
04207     if ((*it) == device)
04208     {
04209       myRangeDeviceList.erase(it);
04210       return;
04211     }
04212   }
04213 }
04214 
04219 AREXPORT ArRangeDevice *ArRobot::findRangeDevice(const char *name)
04220 {
04221   std::list<ArRangeDevice *>::iterator it;
04222   ArRangeDevice *device;
04223 
04224   for (it = myRangeDeviceList.begin(); it != myRangeDeviceList.end(); ++it)
04225   {
04226     device = (*it);
04227     if (strcmp(name, device->getName()) == 0)
04228     {
04229       return device;
04230     }
04231   }
04232   return NULL;
04233 }
04234 
04239 AREXPORT const ArRangeDevice *ArRobot::findRangeDevice(const char *name) const
04240 {
04241   std::list<ArRangeDevice *>::const_iterator it;
04242   ArRangeDevice *device;
04243 
04244   for (it = myRangeDeviceList.begin(); it != myRangeDeviceList.end(); ++it)
04245   {
04246     device = (*it);
04247     if (strcmp(name, device->getName()) == 0)
04248     {
04249       return device;
04250     }
04251   }
04252   return NULL;
04253 }
04254 
04261 AREXPORT std::list<ArRangeDevice *> *ArRobot::getRangeDeviceList(void)
04262 {
04263   return &myRangeDeviceList;
04264 }
04265 
04269 AREXPORT bool ArRobot::hasRangeDevice(ArRangeDevice *device) const
04270 {
04271   std::list<ArRangeDevice *>::const_iterator it;
04272   for (it = myRangeDeviceList.begin(); it != myRangeDeviceList.end(); ++it)
04273   {
04274     if ((*it) == device)
04275       return true;
04276   }
04277   return false;
04278 }
04279 
04294 AREXPORT double ArRobot::checkRangeDevicesCurrentPolar(
04295     double startAngle, double endAngle, double *angle, 
04296     const ArRangeDevice **rangeDevice,
04297     bool useLocationDependentDevices) const
04298 {
04299   double closest = 32000;
04300   double closeAngle, tempDist, tempAngle;
04301   std::list<ArRangeDevice *>::const_iterator it;
04302   ArRangeDevice *device;
04303   bool foundOne = false;
04304   const ArRangeDevice *closestRangeDevice = NULL;
04305 
04306   for (it = myRangeDeviceList.begin(); it != myRangeDeviceList.end(); ++it)
04307   {
04308     device = (*it);
04309     device->lockDevice();
04310     if (!useLocationDependentDevices && device->isLocationDependent())
04311     {
04312       device->unlockDevice();
04313       continue;
04314     }
04315     if (!foundOne || 
04316     (tempDist = device->currentReadingPolar(startAngle, endAngle,
04317                         &tempAngle)) < closest)
04318     {
04319       if (!foundOne)
04320       {
04321     closest = device->currentReadingPolar(startAngle, endAngle, 
04322                           &closeAngle);
04323     closestRangeDevice = device;
04324       }
04325       else
04326       {
04327     closest = tempDist;
04328     closeAngle = tempAngle;
04329     closestRangeDevice = device;
04330       }
04331       foundOne = true;
04332     }
04333     device->unlockDevice();
04334   }
04335   if (!foundOne)
04336     return -1;
04337   if (angle != NULL)
04338     *angle = closeAngle;
04339   if (rangeDevice != NULL)
04340     *rangeDevice = closestRangeDevice;
04341   return closest;
04342   
04343 }
04344 
04345 
04358 AREXPORT double ArRobot::checkRangeDevicesCumulativePolar(
04359     double startAngle, double endAngle, double *angle, 
04360     const ArRangeDevice **rangeDevice, 
04361     bool useLocationDependentDevices) const
04362 {
04363   double closest = 32000;
04364   double closeAngle, tempDist, tempAngle;
04365   std::list<ArRangeDevice *>::const_iterator it;
04366   ArRangeDevice *device;
04367   bool foundOne = false;
04368   const ArRangeDevice *closestRangeDevice = NULL;
04369 
04370   for (it = myRangeDeviceList.begin(); it != myRangeDeviceList.end(); ++it)
04371   {
04372     device = (*it);
04373     device->lockDevice();
04374     if (!useLocationDependentDevices && device->isLocationDependent())
04375     {
04376       device->unlockDevice();
04377       continue;
04378     }
04379     if (!foundOne || 
04380     (tempDist = device->cumulativeReadingPolar(startAngle, endAngle,
04381                          &tempAngle)) < closest)
04382     {
04383       if (!foundOne)
04384       {
04385     closest = device->cumulativeReadingPolar(startAngle, endAngle, 
04386                           &closeAngle);
04387     closestRangeDevice = device;
04388       }
04389       else
04390       {
04391     closest = tempDist;
04392     closeAngle = tempAngle;
04393     closestRangeDevice = device;
04394       }
04395       foundOne = true;
04396     }
04397     device->unlockDevice();
04398   }
04399   if (!foundOne)
04400     return -1;
04401   if (angle != NULL)
04402     *angle = closeAngle;
04403   if (rangeDevice != NULL)
04404     *rangeDevice = closestRangeDevice;
04405   return closest;
04406   
04407 }
04408 
04425 AREXPORT double ArRobot::checkRangeDevicesCurrentBox(
04426     double x1, double y1, double x2, double y2, ArPose *readingPos,
04427     const ArRangeDevice **rangeDevice, 
04428     bool useLocationDependentDevices) const
04429 {
04430 
04431   double closest = 32000;
04432   double tempDist;
04433   ArPose closestPos, tempPos;
04434   std::list<ArRangeDevice *>::const_iterator it;
04435   ArRangeDevice *device;
04436   bool foundOne = false;
04437   const ArRangeDevice *closestRangeDevice = NULL;
04438 
04439   for (it = myRangeDeviceList.begin(); it != myRangeDeviceList.end(); ++it)
04440   {
04441     device = (*it);
04442     device->lockDevice();
04443     if (!useLocationDependentDevices && device->isLocationDependent())
04444     {
04445       device->unlockDevice();
04446       continue;
04447     }
04448     if (!foundOne || 
04449     (tempDist = device->currentReadingBox(x1, y1, x2, y2, &tempPos)) < closest)
04450     {
04451       if (!foundOne)
04452       {
04453     closest = device->currentReadingBox(x1, y1, x2, y2, &closestPos);
04454     closestRangeDevice = device;
04455       }
04456       else
04457       {
04458     closest = tempDist;
04459     closestPos = tempPos;
04460     closestRangeDevice = device;
04461       }
04462       foundOne = true;
04463     }
04464     device->unlockDevice();
04465   }
04466   if (!foundOne)
04467     return -1;
04468   if (readingPos != NULL)
04469     *readingPos = closestPos;
04470   if (rangeDevice != NULL)
04471     *rangeDevice = closestRangeDevice;
04472   return closest;
04473 }
04474 
04491 AREXPORT double ArRobot::checkRangeDevicesCumulativeBox(
04492     double x1, double y1, double x2, double y2, ArPose *readingPos,
04493     const ArRangeDevice **rangeDevice, 
04494     bool useLocationDependentDevices) const
04495 {
04496 
04497   double closest = 32000;
04498   double tempDist;
04499   ArPose closestPos, tempPos;
04500   std::list<ArRangeDevice *>::const_iterator it;
04501   ArRangeDevice *device;
04502   bool foundOne = false;
04503   const ArRangeDevice *closestRangeDevice = NULL;
04504 
04505   for (it = myRangeDeviceList.begin(); it != myRangeDeviceList.end(); ++it)
04506   {
04507     device = (*it);
04508     device->lockDevice();
04509     if (!useLocationDependentDevices && device->isLocationDependent())
04510     {
04511       device->unlockDevice();
04512       continue;
04513     }
04514     if (!foundOne || 
04515     (tempDist = device->cumulativeReadingBox(x1, y1, x2, y2, &tempPos)) < closest)
04516     {
04517       if (!foundOne)
04518       {
04519     closest = device->cumulativeReadingBox(x1, y1, x2, y2, &closestPos);
04520     closestRangeDevice = device;
04521       }
04522       else
04523       {
04524     closest = tempDist;
04525     closestPos = tempPos;
04526     closestRangeDevice = device;
04527       }
04528       foundOne = true;
04529     }
04530     device->unlockDevice();
04531   }
04532   if (!foundOne)
04533     return -1;
04534   if (readingPos != NULL)
04535     *readingPos = closestPos;
04536   if (rangeDevice != NULL)
04537     *rangeDevice = closestRangeDevice;
04538   return closest;
04539 }
04540 
04553 AREXPORT void ArRobot::moveTo(ArPose pose, bool doCumulative)
04554 {
04555   std::list<ArRangeDevice *>::iterator it;
04556   ArSensorReading *son;
04557   int i;
04558 
04559   // we need to get this one now because changing the encoder
04560   // transform and global pose will change the local transform
04561   ArTransform localTransform;
04562   localTransform = getToLocalTransform();
04563 
04564   myEncoderTransform.setTransform(myEncoderPose, pose);
04565   myGlobalPose = myEncoderTransform.doTransform(myEncoderPose);
04566 
04567   for (it = myRangeDeviceList.begin(); it != myRangeDeviceList.end(); it++)
04568   {
04569     (*it)->lockDevice();
04570     (*it)->applyTransform(localTransform, doCumulative);
04571     (*it)->applyTransform(getToGlobalTransform(), doCumulative);
04572     (*it)->unlockDevice();
04573   }
04574 
04575   for (i = 0; i < getNumSonar(); i++)
04576   {
04577     son = getSonarReading(i);
04578     if (son != NULL)
04579     {
04580       son->applyTransform(localTransform);
04581       son->applyTransform(getToGlobalTransform());
04582     }
04583   }
04584 
04585   //ArLog::log(ArLog::Normal, "Robot moved to %.0f %.0f %.1f", getX(), getY(), getTh());
04586 }
04587 
04603 AREXPORT void ArRobot::moveTo(ArPose poseTo, ArPose poseFrom,
04604                   bool doCumulative)
04605 {
04606   std::list<ArRangeDevice *>::iterator it;
04607   ArSensorReading *son;
04608   int i;
04609 
04610   ArPose result = myEncoderTransform.doInvTransform(poseFrom);
04611 
04612   // we need to get this one now because changing the encoder
04613   // transform and global pose will change the local transform
04614   ArTransform localTransform;
04615   localTransform = getToLocalTransform();
04616 
04617   myEncoderTransform.setTransform(result, poseTo);
04618   myGlobalPose = myEncoderTransform.doTransform(myEncoderPose);
04619 
04620   for (it = myRangeDeviceList.begin(); it != myRangeDeviceList.end(); it++)
04621   {
04622     (*it)->lockDevice();
04623     (*it)->applyTransform(localTransform, doCumulative);
04624     (*it)->applyTransform(getToGlobalTransform(), doCumulative);
04625     (*it)->unlockDevice();
04626   }
04627 
04628   for (i = 0; i < getNumSonar(); i++)
04629   {
04630     son = getSonarReading(i);
04631     if (son != NULL)
04632     {
04633       son->applyTransform(localTransform);
04634       son->applyTransform(getToGlobalTransform());
04635     }
04636   }
04637 
04638   //ArLog::log(ArLog::Normal, "Robot moved to %.0f %.0f %.1f", getX(), getY(), getTh());
04639 }
04640 
04645 AREXPORT void ArRobot::setEncoderTransform(ArPose deadReconPos, 
04646                     ArPose globalPos)
04647 {
04648   myEncoderTransform.setTransform(deadReconPos, globalPos);
04649   myGlobalPose = myEncoderTransform.doTransform(myEncoderPose);
04650 }
04651 
04655 AREXPORT void ArRobot::setEncoderTransform(ArPose transformPos)
04656 {
04657   myEncoderTransform.setTransform(transformPos);
04658   myGlobalPose = myEncoderTransform.doTransform(myEncoderPose);
04659 }
04660 
04664 AREXPORT ArTransform ArRobot::getEncoderTransform(void) const
04665 {
04666   return myEncoderTransform;
04667 }
04668 
04672 AREXPORT void ArRobot::setDeadReconPose(ArPose pose)
04673 {
04674   myEncoderPose.setPose(pose);
04675   myEncoderTransform.setTransform(myEncoderPose, myGlobalPose);
04676   myGlobalPose = myEncoderTransform.doTransform(myEncoderPose);
04677 }
04678 
04679 
04684 AREXPORT ArTransform ArRobot::getToGlobalTransform(void) const
04685 {
04686   ArTransform trans;
04687   ArPose origin(0, 0, 0);
04688   ArPose pose = getPose();
04689 
04690   trans.setTransform(origin, pose);
04691   return trans;
04692 }
04693 
04698 AREXPORT ArTransform ArRobot::getToLocalTransform(void) const
04699 {
04700   ArTransform trans;
04701   ArPose origin(0, 0, 0);
04702   ArPose pose = getPose();
04703 
04704   trans.setTransform(pose, origin);
04705   return trans;
04706 }
04707 
04715 AREXPORT void ArRobot::applyTransform(ArTransform trans, bool doCumulative)
04716 {
04717   std::list<ArRangeDevice *>::iterator it;
04718   ArSensorReading *son;
04719   int i;
04720   
04721   for (it = myRangeDeviceList.begin(); it != myRangeDeviceList.end(); it++)
04722   {
04723       (*it)->lockDevice();
04724       (*it)->applyTransform(trans, doCumulative);
04725       (*it)->unlockDevice();
04726   }
04727 
04728   for (i = 0; i < getNumSonar(); i++)
04729   {
04730     son = getSonarReading(i);
04731     if (son != NULL)
04732       son->applyTransform(trans);
04733   }
04734 }
04735 
04736 AREXPORT const char *ArRobot::getName(void) const
04737 {
04738   return myName.c_str();
04739 }
04740 
04741 AREXPORT void ArRobot::setName(const char * name)
04742 {
04743     std::list<ArRobot *> *robotList;
04744     std::list<ArRobot *>::iterator it;
04745     int i;
04746     char buf[1024];
04747  
04748  if (name != NULL)
04749   {
04750     myName = name;
04751   }
04752   else
04753   {
04754 
04755     
04756 
04757     robotList = Aria::getRobotList();
04758     for (i = 1, it = robotList->begin(); it != robotList->end(); it++, i++)
04759     {
04760       if (this == (*it))
04761       {
04762         if (i == 1)
04763             myName = "robot";
04764         else
04765         {
04766             sprintf(buf, "robot%d", i);
04767             myName = buf;
04768         }
04769         return;
04770       }
04771     }
04772     sprintf(buf, "robot%d", robotList->size());
04773     myName = buf;
04774    }
04775 }
04776 
04787 AREXPORT void ArRobot::setEncoderCorrectionCallback(
04788     ArRetFunctor1<double, ArPoseWithTime> *functor)
04789 {
04790   myEncoderCorrectionCB = functor;
04791 }
04798 AREXPORT ArRetFunctor1<double, ArPoseWithTime> * 
04799 ArRobot::getEncoderCorrectionCallback(void) const
04800 {
04801   return myEncoderCorrectionCB;
04802 }
04803 
04814 AREXPORT void ArRobot::setDirectMotionPrecedenceTime(int mSec)
04815 {
04816   if (mSec < 0) 
04817     myDirectPrecedenceTime = 0;
04818   else
04819     myDirectPrecedenceTime = mSec;
04820 }
04821 
04831 AREXPORT unsigned int ArRobot::getDirectMotionPrecedenceTime(void) const
04832 {
04833   return myDirectPrecedenceTime;
04834 }
04835 
04836 
04843 AREXPORT void ArRobot::clearDirectMotion(void)
04844 {
04845   myTransType = TRANS_NONE;
04846   myLastTransType = TRANS_NONE;
04847   myRotType = ROT_NONE;
04848   myLastRotType = ROT_NONE;
04849   myLastActionTransVal = 0;
04850   myLastActionRotStopped = true;
04851   myLastActionRotHeading = false;
04852 }
04853 
04861 AREXPORT void ArRobot::stopStateReflection(void)
04862 {
04863   myTransType = TRANS_IGNORE;
04864   myLastTransType = TRANS_IGNORE;
04865   myRotType = ROT_IGNORE;
04866   myLastRotType = ROT_IGNORE;
04867 }
04868 
04873 AREXPORT bool ArRobot::isDirectMotion(void) const
04874 {
04875   if (myTransType ==  TRANS_NONE && myLastTransType == TRANS_NONE &&
04876       myRotType == ROT_NONE && myLastRotType == ROT_NONE)
04877     return false;
04878   else
04879     return true;
04880 }
04881 
04882 
04886 AREXPORT void ArRobot::enableMotors()
04887 {
04888   comInt(ArCommands::ENABLE, 1);
04889 }
04890 
04894 AREXPORT void ArRobot::disableMotors()
04895 {
04896   comInt(ArCommands::ENABLE, 0);
04897 }
04898 
04902 AREXPORT void ArRobot::enableSonar()
04903 {
04904   comInt(ArCommands::SONAR, 1);
04905 }
04906 
04910 AREXPORT void ArRobot::disableSonar()
04911 {
04912   comInt(ArCommands::SONAR, 0);
04913 }
04914 
04915 
04924 AREXPORT void ArRobot::setStateReflectionRefreshTime(int mSec)
04925 {
04926   if (mSec < 0)
04927     myStateReflectionRefreshTime = 0;
04928   else
04929     myStateReflectionRefreshTime = mSec;
04930 }
04931 
04939 AREXPORT int ArRobot::getStateReflectionRefreshTime(void) const
04940 {
04941   return myStateReflectionRefreshTime;
04942 }
04943 
04959 AREXPORT void ArRobot::attachKeyHandler(ArKeyHandler *keyHandler, 
04960                     bool exitOnEscape, 
04961                     bool useExitNotShutdown)
04962 {
04963   if (myKeyHandlerCB != NULL)
04964     delete myKeyHandlerCB;
04965   myKeyHandlerCB = new ArFunctorC<ArKeyHandler>(keyHandler, 
04966                         &ArKeyHandler::checkKeys);
04967   addSensorInterpTask("Key Handler", 50, myKeyHandlerCB);
04968 
04969   myKeyHandler = keyHandler;
04970   myKeyHandlerUseExitNotShutdown = useExitNotShutdown;
04971   if (exitOnEscape)
04972     keyHandler->addKeyHandler(ArKeyHandler::ESCAPE, &myKeyHandlerExitCB);
04973 }
04974 
04975 AREXPORT ArKeyHandler *ArRobot::getKeyHandler(void) const
04976 {
04977   return myKeyHandler;
04978 }
04979 
04980 AREXPORT void ArRobot::keyHandlerExit(void)
04981 {
04982   ArLog::log(ArLog::Terse, "Escape was pressed, program is exiting.");
04983   // if we're using exit not the keyhandler then call Aria::exit
04984   // instead of shutdown, this call never returns
04985   if (myKeyHandlerUseExitNotShutdown)
04986     Aria::exit();
04987   stopRunning();
04988   unlock();
04989   Aria::shutdown();
04990 }
04991 
04992 AREXPORT void ArRobot::setPacketsReceivedTracking(bool packetsReceivedTracking)
04993 {
04994   myPacketsReceivedTracking = packetsReceivedTracking;
04995   myPacketsReceivedTrackingCount = 0; 
04996   myPacketsReceivedTrackingStarted.setToNow(); 
04997 }
04998 
04999 AREXPORT void ArRobot::ariaExitCallback(void)
05000 {
05001   mySyncLoop.stopRunIfNotConnected(false);
05002   disconnect();
05003 }
05004 
05010 AREXPORT ArRobot::ChargeState ArRobot::getChargeState(void) const
05011 {
05012   return myChargeState;
05013 }
05014 
05015 AREXPORT void ArRobot::resetOdometer(void)
05016 {
05017   myOdometerDistance = 0;
05018   myOdometerDegrees = 0;
05019   myOdometerStart.setToNow();
05020 }

Generated on Fri Dec 1 10:55:13 2006 for Aria by  doxygen 1.4.7