Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members | Related Pages

ArRobot.cpp

00001 /*
00002 ActivMedia Robotics Interface for Applications (ARIA)
00003 Copyright (C) 2004,2005 ActivMedia Robotics, LLC
00004 
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 ActivMedia Robotics for information about a commercial version of ARIA at 
00022 robots@activmedia.com or 
00023 ActivMedia Robotics, 19 Columbia Drive, Amherst, NH 03031; 800-639-9481
00024 
00025 */
00026 
00027 #include "ArExport.h"
00028 #include "ariaOSDef.h"
00029 #include <time.h>
00030 #include <ctype.h>
00031 
00032 #include "ArRobot.h"
00033 #include "ArLog.h"
00034 #include "ArDeviceConnection.h"
00035 #include "ArTcpConnection.h"
00036 #include "ArSerialConnection.h"
00037 #include "ArLogFileConnection.h"
00038 #include "ariaUtil.h"
00039 #include "ArSocket.h"
00040 #include "ArCommands.h"
00041 #include "ArRobotTypes.h"
00042 #include "ArSignalHandler.h"
00043 #include "ArPriorityResolver.h"
00044 #include "ArAction.h"
00045 #include "ArRangeDevice.h"
00046 #include "ArRobotConfigPacketReader.h"
00047 #include "ariaInternal.h"
00048 
00069 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   myPtz = NULL;
00095   myKeyHandler = NULL;
00096   myKeyHandlerCB = NULL;
00097 
00098   myConn = NULL;
00099 
00100   myOwnTheResolver = false;
00101 
00102   myBlockingConnectRun = false;
00103   myAsyncConnectFlag = false;
00104 
00105   myLogMovementSent = false;
00106   myLogMovementReceived = false;
00107   myLogVelocitiesReceived = false;
00108 
00109   myPacketsSentTracking = false;
00110   myPacketsReceivedTracking = false;
00111   myPacketsReceivedTrackingCount = false;
00112   myPacketsReceivedTrackingStarted.setToNow();
00113 
00114   myCycleTime = 100;
00115   myCycleWarningTime = 250;
00116   myConnectionCycleMultiplier = 2;
00117   myTimeoutTime = 8000;
00118   myStabilizingTime = 0;
00119   myCounter = 1;
00120   myResolver = NULL;
00121   myNumSonar = 0;
00122 
00123   myRequestedIOPackets = false;
00124   myRequestedEncoderPackets = false;
00125   myEncoderCorrectionCB = NULL;
00126 
00127   myCycleChained = true;
00128 
00129   myMoveDoneDist = 40;
00130   myHeadingDoneDiff = 3;
00131 
00132   myOrigRobotConfig = NULL;
00133   reset();
00134   if (normalInit)
00135     init();
00136   
00137   mySyncLoop.setRobot(this);
00138 
00139   if (doSigHandle)
00140     Aria::addRobot(this);
00141   if (addAriaExitCallback)
00142   {
00143     Aria::addExitCallback(&myAriaExitCB, 0);
00144     myAddedAriaExitCB = true;
00145   }
00146   else
00147   {
00148     myAddedAriaExitCB = false;
00149   }
00150 }
00151 
00152 
00153 
00154 ArRobot::~ArRobot()
00155 {
00156   ArResolver::ActionMap::iterator it;
00157 
00158   stopRunning();
00159   delete mySyncTaskRoot;
00160   ArUtil::deleteSetPairs(mySonars.begin(), mySonars.end());
00161   Aria::delRobot(this);
00162 
00163   if (myKeyHandlerCB != NULL)
00164     delete myKeyHandlerCB;
00165 
00166   for (it = myActions.begin(); it != myActions.end(); ++it)
00167   {
00168     (*it).second->setRobot(NULL);
00169   }
00170 }
00171 
00172 
00177 void ArRobot::init(void)
00178 {
00179   setUpPacketHandlers();
00180   setUpSyncList();
00181   myOwnTheResolver = true;
00182   myResolver = new ArPriorityResolver;
00183 }
00184 
00195 void ArRobot::run(bool stopRunIfNotConnected)
00196 {
00197   if (mySyncLoop.getRunning())
00198   {
00199     ArLog::log(ArLog::Terse, 
00200                "The robot is already running, cannot run it again.");
00201     return;
00202   }
00203   mySyncLoop.setRunning(true);
00204   mySyncLoop.stopRunIfNotConnected(stopRunIfNotConnected);
00205   mySyncLoop.runInThisThread();
00206 }
00207 
00213 bool ArRobot::isRunning(void) const
00214 {
00215   return mySyncLoop.getRunning();
00216 }
00217 
00227 void ArRobot::runAsync(bool stopRunIfNotConnected)
00228 {
00229   if (mySyncLoop.getRunning())
00230   {
00231     ArLog::log(ArLog::Terse, 
00232                "The robot is already running, cannot run it again.");
00233     return;
00234   }
00235   mySyncLoop.stopRunIfNotConnected(stopRunIfNotConnected);
00236   // Joinable, but do NOT lower priority. The robot thread is the most
00237   // important one around.
00238   mySyncLoop.create(true, false);
00239 }
00240 
00249 void ArRobot::stopRunning(bool doDisconnect)
00250 {
00251   if (myKeyHandler != NULL)
00252     myKeyHandler->restore();
00253   mySyncLoop.stopRunning();
00254   myBlockingConnectRun = false;
00255   if (doDisconnect && (isConnected() || myIsStabilizing))
00256   {
00257     waitForRunExit();
00258     disconnect();
00259   }
00260   wakeAllWaitingThreads();
00261 }
00262 
00263 void ArRobot::setUpSyncList(void)
00264 {
00265   mySyncTaskRoot = new ArSyncTask("SyncTasks");
00266   mySyncTaskRoot->setWarningTimeCB(&myGetCycleWarningTimeCB);
00267   mySyncTaskRoot->setNoTimeWarningCB(&myGetNoTimeWarningThisCycleCB);
00268   mySyncTaskRoot->addNewLeaf("Packet Handler", 85, &myPacketHandlerCB);
00269   mySyncTaskRoot->addNewLeaf("Robot Locker", 70, &myRobotLockerCB);
00270   mySyncTaskRoot->addNewBranch("Sensor Interp", 65);
00271   mySyncTaskRoot->addNewLeaf("Action Handler", 55, &myActionHandlerCB);
00272   mySyncTaskRoot->addNewLeaf("State Reflector", 45, &myStateReflectorCB);
00273   mySyncTaskRoot->addNewBranch("User Tasks", 25);
00274   mySyncTaskRoot->addNewLeaf("Robot Unlocker", 20, &myRobotUnlockerCB);
00275 }
00276 
00277 
00278 void ArRobot::setUpPacketHandlers(void)
00279 {
00280   addPacketHandler(&myMotorPacketCB, ArListPos::FIRST);
00281   addPacketHandler(&myEncoderPacketCB, ArListPos::LAST);
00282   addPacketHandler(&myIOPacketCB, ArListPos::LAST);
00283 }
00284 
00285 void ArRobot::reset(void)
00286 {
00287   myInterpolation.reset();
00288   myEncoderInterpolation.reset();
00289   if (myOrigRobotConfig != NULL)
00290     delete myOrigRobotConfig;
00291   myOrigRobotConfig = new ArRobotConfigPacketReader(this, true);
00292   myFirstEncoderPose = true;
00293   //myEncoderPose.setPose(0, 0, 0);
00294   //myEncoderPoseTaken.setToNow();
00295   //myRawEncoderPose.setPose(0, 0, 0);
00296   //myGlobalPose.setPose(0, 0, 0);
00297   //myEncoderTransform.setTransform(myEncoderPose, myGlobalPose);
00298   myTransVelMax = 0;
00299   myTransAccel = 0;
00300   myTransDecel = 0;
00301   myRotVelMax = 0;
00302   myRotAccel = 0;
00303   myRotDecel = 0;
00304 
00305   myLeftVel = 0;
00306   myRightVel = 0;
00307   myBatteryVoltage = 13;
00308   myBatteryAverager.clear();
00309   myBatteryAverager.add(myBatteryVoltage);
00310   myStallValue = 0;
00311   myControl = 0;
00312   myFlags = 0;
00313   myCompass = 0;
00314   myAnalogPortSelected = 0;
00315   myAnalog = 0;
00316   myDigIn = 0;
00317   myDigOut = 0;
00318   myIOAnalogSize = 0;
00319   myIODigInSize = 0;
00320   myIODigOutSize = 0;
00321   myLastIOPacketReceivedTime.setSec(0);
00322   myLastIOPacketReceivedTime.setMSec(0);
00323   myVel = 0;
00324   myRotVel = 0;
00325   myChargeState = CHARGING_UNKNOWN;
00326   myLastX = 0;
00327   myLastY = 0;
00328   myLastTh = 0;
00329   mySentPulse = false;
00330   myIsConnected = false;
00331   myIsStabilizing = false;
00332 
00333   myTransVal = 0;
00334   myTransVal2 = 0;
00335   myTransType = TRANS_NONE;
00336   myLastTransVal = 0;
00337   myLastTransVal2 = 0;
00338   myLastTransType = TRANS_NONE;
00339   myLastTransSent.setToNow();
00340   myActionTransSet = false;
00341   myLastActionRotStopped = false;
00342   myLastActionRotHeading = false;
00343 
00344   myRotVal = 0;
00345   myLastRotVal = 0;
00346   myRotType = ROT_NONE;
00347   myLastRotType = ROT_NONE;
00348   myLastRotSent.setToNow();
00349   myActionRotSet = false;
00350 
00351   myLastPulseSent.setToNow();
00352 
00353   myDirectPrecedenceTime = 0;
00354   myStateReflectionRefreshTime = 500;
00355 
00356   myActionDesired.reset();
00357 
00358   myMotorPacCurrentCount = 0;
00359   myMotorPacCount = 0;
00360   myTimeLastMotorPacket = 0;
00361 
00362   mySonarPacCurrentCount = 0;
00363   mySonarPacCount = 0;
00364   myTimeLastSonarPacket = 0;
00365 
00366   myLeftEncoder = 0;
00367   myRightEncoder = 0;
00368 
00369   myWarnedAboutExtraSonar = false;
00370 }
00371 
00372 void ArRobot::setTransVelMax(double vel)
00373 {
00374   if (vel > myAbsoluteMaxTransVel)
00375   {
00376     ArLog::log(ArLog::Terse, "ArRobot: transVelMax of %g is over the absolute max of %g, ignoring", vel, myAbsoluteMaxTransVel);
00377     return;
00378   }
00379   myTransVelMax = vel;
00380 }
00381 
00382 void ArRobot::setTransAccel(double acc)
00383 {
00384   myTransAccel = acc;
00385 }
00386 
00387 void ArRobot::setTransDecel(double decel)
00388 {
00389   myTransDecel = ArMath::fabs(decel);
00390 }
00391 
00392 void ArRobot::setRotVelMax(double vel)
00393 {
00394   if (vel > myAbsoluteMaxRotVel)
00395   {
00396     ArLog::log(ArLog::Terse, "ArRobot: rotVelMax of %g is over the absolute max of %g, ignoring", vel, myAbsoluteMaxRotVel);
00397     return;
00398   }
00399   myRotVelMax = vel;
00400 }
00401 
00402 void ArRobot::setRotAccel(double acc)
00403 {
00404   myRotAccel = acc;
00405 }
00406 
00407 void ArRobot::setRotDecel(double decel)
00408 {
00409   myRotDecel = ArMath::fabs(decel);
00410 }
00411 
00412 double ArRobot::getTransVelMax(void) const
00413 {
00414   return myTransVelMax;
00415 }
00416 
00417 double ArRobot::getTransAccel(void) const
00418 {
00419   return myTransAccel;
00420 }
00421 
00422 double ArRobot::getTransDecel(void) const
00423 {
00424   return myTransDecel;
00425 }
00426 
00427 double ArRobot::getRotVelMax(void) const
00428 {
00429   return myRotVelMax;
00430 }
00431 
00432 double ArRobot::getRotAccel(void) const
00433 {
00434   return myRotAccel;
00435 }
00436 
00437 double ArRobot::getRotDecel(void) const
00438 {
00439   return myRotDecel;
00440 }
00441 
00450 void ArRobot::setDeviceConnection(ArDeviceConnection *connection)
00451 {
00452   myConn = connection;
00453   mySender.setDeviceConnection(myConn);
00454   myReceiver.setDeviceConnection(myConn);
00455 }
00456 
00465 ArDeviceConnection *ArRobot::getDeviceConnection(void) const
00466 {
00467   return myConn;
00468 }
00469 
00480 void ArRobot::setConnectionTimeoutTime(int mSecs)
00481 {
00482   if (mSecs > 0)
00483     myTimeoutTime = mSecs;
00484   else
00485     myTimeoutTime = 0;
00486 }
00487 
00494 int ArRobot::getConnectionTimeoutTime(void) const
00495 {
00496   return myTimeoutTime;
00497 }
00498 
00504 ArTime ArRobot::getLastPacketTime(void) const
00505 {
00506   return myLastPacketReceivedTime;
00507 }
00539 bool ArRobot::asyncConnect(void)
00540 {
00541   if (!mySyncLoop.getRunning() || isConnected())
00542     return false;
00543   
00544   myAsyncConnectFlag = true;
00545   myBlockingConnectRun = false;
00546   myAsyncConnectState = -1;
00547   return true;
00548 }
00549 
00580 bool ArRobot::blockingConnect(void)
00581 {
00582   int ret = 0;
00583 
00584   lock();
00585   if (myIsConnected)
00586     disconnect();
00587   myBlockingConnectRun = true;
00588   myAsyncConnectState = -1;
00589   while ((ret = asyncConnectHandler(true)) == 0 && myBlockingConnectRun)
00590     ArUtil::sleep(ArMath::roundInt(getCycleTime() * .80));
00591   unlock();
00592   if (ret == 1)
00593     return true;
00594   else
00595     return false;
00596 }
00597 
00613 int ArRobot::asyncConnectHandler(bool tryHarderToConnect)
00614 {
00615   int ret = 0;
00616   ArRobotPacket *packet;
00617   ArRobotPacket *tempPacket = NULL;
00618   char robotSubType[255];
00619   int i;
00620   int len;
00621   std::string str;
00622   ArTime endTime;
00623   int timeToWait;
00624   ArSerialConnection *serConn;
00625 
00626   endTime.setToNow();
00627   endTime.addMSec(getCycleTime()*myConnectionCycleMultiplier);
00628   
00629   myNoTimeWarningThisCycle = true;
00630 
00631   // if this is -1, then we're doing initialization stuff, then returning
00632   if (myAsyncConnectState == -1)
00633   {
00634     myAsyncConnectSentChangeBaud = false;
00635     myAsyncConnectNoPacketCount = 0;
00636     myAsyncConnectTimesTried = 0;
00637     reset();
00638     if (myConn == NULL)
00639     {
00640       ArLog::log(ArLog::Terse, "Cannot connect, no connection has been set.");
00641       failedConnect();
00642       return 2;
00643     }
00644     
00645     if (myConn->getStatus() != ArDeviceConnection::STATUS_OPEN) 
00646     {
00647       if (!myConn->openSimple())
00648       {
00649         /*str = myConn->getStatusMessage(myConn->getStatus());
00650           ArLog::log(ArLog::Terse, "Trying to connect to robot but connection not opened, it is %s", str.c_str());*/
00651         ArLog::log(ArLog::Terse, 
00652                    "Could not connect, because open on the device connection failed.");
00653         failedConnect();
00654         return 2;
00655       }
00656     }
00657 
00658     // check for log file connection: just return success
00659     if (dynamic_cast<ArLogFileConnection *>(myConn))
00660     {
00661       ArLogFileConnection *con = dynamic_cast<ArLogFileConnection *>(myConn);
00662       myRobotName = con->myName;
00663       myRobotType = con->myType;
00664       myRobotSubType = con->mySubtype;
00665       if (con->havePose)        // we know where to move
00666         moveTo(con->myPose);
00667       setCycleChained(false);   // don't process packets all at once
00668       madeConnection();
00669       finishedConnection();
00670       return 1;
00671     }
00672 
00673 
00674     if (dynamic_cast<ArSerialConnection *>(myConn))
00675     {
00676       myConn->write("WMS2\15", strlen("WMS2\15"));
00677     }
00678     // here we're flushing out all previously received packets
00679     while ( endTime.mSecTo() > 0 && myReceiver.receivePacket(0) != NULL);
00680 
00681     myAsyncConnectState = 0;
00682     return 0;
00683   }
00684 
00685   if (myAsyncConnectState >= 3)
00686   {
00687     bool handled;
00688     std::list<ArRetFunctor1<bool, ArRobotPacket *> *>::iterator it;
00689     while ((packet = myReceiver.receivePacket(0)) != NULL)
00690     {
00691       //printf("0x%x\n", packet->getID());
00692       for (handled = false, it = myPacketHandlerList.begin(); 
00693            it != myPacketHandlerList.end() && handled == false; 
00694            it++)
00695       {
00696         if ((*it) != NULL && (*it)->invokeR(packet)) 
00697           handled = true;
00698         else
00699           packet->resetRead();
00700       }
00701     }
00702   }
00703 
00704   if (myAsyncConnectState == 3)
00705   {
00706     //if (!myOrigRobotConfig->hasPacketBeenRequested())
00707     if (!myOrigRobotConfig->hasPacketArrived())
00708     {
00709       myOrigRobotConfig->requestPacket();
00710     }
00711     // if we've gotten our config packet or if we've timed out then
00712     // set our vel and acc/decel params and skip to the next part
00713     if (myOrigRobotConfig->hasPacketArrived() || 
00714         myAsyncStartedConnection.mSecSince() > 1000)
00715     {
00716       bool gotConfig;
00717       // if we have data from the robot use that
00718       if (myOrigRobotConfig->hasPacketArrived())
00719       {
00720         gotConfig = true;
00721         setAbsoluteMaxTransVel(myOrigRobotConfig->getTransVelTop());
00722         setAbsoluteMaxRotVel(myOrigRobotConfig->getRotVelTop());
00723         setTransVelMax(myOrigRobotConfig->getTransVelMax());
00724         setTransAccel(myOrigRobotConfig->getTransAccel());
00725         setTransDecel(myOrigRobotConfig->getTransDecel());
00726         setRotVelMax(myOrigRobotConfig->getRotVelMax());
00727         setRotAccel(myOrigRobotConfig->getRotAccel());
00728         setRotDecel(myOrigRobotConfig->getRotDecel());
00729       }
00730       // if our absolute maximums weren't set then set them
00731       else
00732       {
00733         gotConfig = false;
00734         setAbsoluteMaxTransVel(myParams->getAbsoluteMaxVelocity());
00735         setAbsoluteMaxRotVel(myParams->getAbsoluteMaxRotVelocity());
00736       }
00737       // okay we got in that data, now put over it any of the things
00738       // that we got from the robot parameter file... if we don't have
00739       // max vels from above or the parameters then use the absolutes
00740       // which we do have for everything
00741       if (ArMath::fabs(myParams->getTransVelMax()) > 1)
00742         setTransVelMax(myParams->getTransVelMax());
00743       else if (!gotConfig)
00744         setTransVelMax(myParams->getAbsoluteMaxVelocity());
00745       if (ArMath::fabs(myParams->getRotVelMax()) > 1)
00746         setRotVelMax(myParams->getRotVelMax());
00747       else if (!gotConfig)
00748         setRotVelMax(myParams->getAbsoluteMaxRotVelocity());
00749       if (ArMath::fabs(myParams->getTransAccel()) > 1)
00750         setTransAccel(myParams->getTransAccel());
00751       if (ArMath::fabs(myParams->getTransDecel()) > 1)
00752         setTransDecel(myParams->getTransDecel());
00753       if (ArMath::fabs(myParams->getRotAccel()) > 1)
00754         setRotAccel(myParams->getRotAccel());
00755       if (ArMath::fabs(myParams->getRotDecel()) > 1)
00756         setRotDecel(myParams->getRotDecel());
00757       myAsyncConnectState = 4;
00758     }
00759     else
00760       return 0;
00761   }
00762   // we want to see if we should switch baud
00763   if (myAsyncConnectState == 4)
00764   {
00765     serConn = dynamic_cast<ArSerialConnection *>(myConn);
00766     // if we didn't get a config packet or we can't change the baud or
00767     // we aren't using a serial port then don't switch the baud
00768     if (!myOrigRobotConfig->hasPacketArrived() || 
00769         !myOrigRobotConfig->getResetBaud() || 
00770         serConn == NULL ||
00771         myParams->getSwitchToBaudRate() == 0)
00772     {
00773       // if we're using a serial connection store our baud rate
00774       if (serConn != NULL)
00775         myAsyncConnectStartBaud = serConn->getBaud();
00776       myAsyncConnectState = 5;
00777     }
00778     // if we did get a packet and can change baud send the command
00779     else if (!myAsyncConnectSentChangeBaud)
00780     {
00781       // if we're using a serial connection store our baud rate
00782       if (serConn != NULL)
00783         myAsyncConnectStartBaud = serConn->getBaud();
00784 
00785       int baudNum = -1;
00786       
00787       // first suck up all the packets we have now
00788       while ((packet = myReceiver.receivePacket(0)) != NULL);
00789       if (myParams->getSwitchToBaudRate() == 9600)
00790         baudNum = 0;
00791       else if (myParams->getSwitchToBaudRate() == 19200)
00792         baudNum = 1;
00793       else if (myParams->getSwitchToBaudRate() == 38400)
00794         baudNum = 2;
00795       else if (myParams->getSwitchToBaudRate() == 57600)
00796         baudNum = 3;
00797       else if (myParams->getSwitchToBaudRate() == 115200)
00798         baudNum = 4;
00799       else
00800       {
00801         ArLog::log(ArLog::Normal, "Warning: SwitchToBaud is set to %d baud, ignoring.",
00802                    myParams->getSwitchToBaudRate());
00803         ArLog::log(ArLog::Normal, "\tGood bauds are 9600 19200 38400 56800 116200.");
00804         myAsyncConnectState = 5;
00805         baudNum = -1;
00806         return 0;
00807       }
00808       if (baudNum != -1)
00809       {
00810         // now switch it over
00811         comInt(ArCommands::HOSTBAUD, baudNum);
00812         ArUtil::sleep(10);
00813         myAsyncConnectSentChangeBaud = true;
00814         myAsyncConnectStartedChangeBaud.setToNow();
00815         serConn->setBaud(myParams->getSwitchToBaudRate());
00816         //serConn->setBaud(19200);
00817         ArUtil::sleep(10);
00818         com(0);
00819         return 0;
00820       }
00821     }
00822     // if we did send the command then wait and see if we get any packets back
00823     else
00824     {
00825       packet = myReceiver.receivePacket(100);
00826       com(0);
00827       // if we got any packet we're good
00828       if (packet != NULL)
00829       {
00830         myAsyncConnectState = 5;
00831       }
00832       // if we didn't get it and its been 500 ms then fail
00833       else if (myAsyncConnectStartedChangeBaud.mSecSince() > 900)
00834       {
00835         ArLog::log(ArLog::Verbose, "Controller did not switch to baud, reset to %d baud.", myAsyncConnectStartBaud);
00836         serConn->setBaud(myAsyncConnectStartBaud);
00837         myAsyncConnectState = 5;
00838       }
00839       else
00840         return 0;
00841     }    
00842   }
00843 
00844   if (myAsyncConnectState == 5)
00845   {
00846     if (!myIsStabilizing)
00847       startStabilization();
00848     if (myStabilizingTime == 0 || 
00849         myStartedStabilizing.mSecSince() > myStabilizingTime)
00850     {
00851       finishedConnection();
00852       return 1;
00853     }
00854     else
00855       return 0;
00856   }
00857 
00858   // here we've gone beyond the initialization, so read set a time limit,
00859   // read in one packet, then if its a bad packet type, read in all the 
00860   // packets there are to read... if its a good packet, continue with sequence
00861   myAsyncConnectTimesTried++;
00862   ArLog::log(ArLog::Normal, "Syncing %d", myAsyncConnectState);
00863   mySender.com(myAsyncConnectState);
00864   //  packet = myReceiver.receivePacket(endTime.mSecTo());
00865   packet = myReceiver.receivePacket(1000);
00866   
00867   if (packet != NULL) 
00868   {
00869     ret = packet->getID();
00870     //printf("Got a packet %d\n", ret);
00871         
00872     if (ret == 50)
00873     {
00874       ArLog::log(ArLog::Normal, "Attempting to close previous connection.");
00875       comInt(ArCommands::CLOSE,1);
00876       while (endTime.mSecTo() > 0)
00877       {
00878         timeToWait = endTime.mSecTo();
00879         if (timeToWait < 0)
00880           timeToWait = 0;
00881         tempPacket = myReceiver.receivePacket(timeToWait);
00882         if (tempPacket != NULL)
00883           ArLog::log(ArLog::Verbose, "Got in another packet!");
00884         if (tempPacket != NULL && tempPacket->getID() == 50)
00885           comInt(ArCommands::CLOSE,1);
00886       }
00887       myAsyncConnectState = 0;
00888     } 
00889     else if (ret == 255)
00890     {
00891       ArLog::log(ArLog::Normal, "Attempting to correct syncCount");
00892       /*
00893       while (endTime.mSecTo() > 0)
00894       {
00895         timeToWait = endTime.mSecTo();
00896         if (timeToWait < 0)
00897           timeToWait = 0;
00898         tempPacket = myReceiver.receivePacket(timeToWait);
00899         if (tempPacket != NULL)
00900           ArLog::log(ArLog::Verbose, "Got in another packet!");
00901       }
00902       */
00903       while ((tempPacket = myReceiver.receivePacket(0)) != NULL);
00904 
00905       if (tempPacket != NULL && tempPacket->getID() == 0)
00906         myAsyncConnectState = 1;
00907       else
00908         myAsyncConnectState = 0;
00909       return 0;
00910     } 
00911     else if  (ret != myAsyncConnectState++)
00912     {
00913       myAsyncConnectState = 0;
00914     }
00915   }
00916   else 
00917   {
00918     ArLog::log(ArLog::Normal, "No packet.");
00919     myAsyncConnectNoPacketCount++;
00920     if ((myAsyncConnectNoPacketCount > 5
00921          && myAsyncConnectNoPacketCount >= myAsyncConnectTimesTried)
00922         || (myAsyncConnectNoPacketCount > 10))
00923     {
00924       ArLog::log(ArLog::Terse, "Could not connect, no robot responding.");
00925       failedConnect();
00926       return 2;
00927     }
00928 
00929       /* This code to connect the radio modems should never really be needed 
00930          so is being removed for now
00931          if (myAsyncConnectNoPacketCount >= 4)
00932          {
00933          
00934          if (tryHarderToConnect && dynamic_cast<ArSerialConnection *>(myConn))
00935          {
00936          ArLog::log(ArLog::Normal, 
00937          "Radio modem may not connected, trying to connect it.");
00938          ArUtil::sleep(1000);
00939          myConn->write("|||\15", strlen("!!!\15"));
00940          ArUtil::sleep(60);
00941          myConn->write("WMN\15", strlen("WMN\15"));
00942          ArUtil::sleep(60);
00943          myConn->write("WMS2\15", strlen("WMS2\15"));
00944          ArUtil::sleep(1000);
00945          } 
00946          else if (dynamic_cast<ArSerialConnection *>(myConn))
00947          {
00948          ArLog::log(ArLog::Normal,
00949          "Radio modem may not connected, trying to connect it.");
00950          myConn->write("WMS2\15", strlen("WMS2\15"));
00951          ArUtil::sleep(60);
00952          }
00953          }
00954       */
00955     
00956     // If we get no response first we dump close commands at the thing
00957     // in different bauds (if its a serial connection)
00958     if (myAsyncConnectNoPacketCount == 2 && 
00959         myAsyncConnectNoPacketCount >= myAsyncConnectTimesTried &&
00960         (serConn = dynamic_cast<ArSerialConnection *>(myConn)) != NULL)
00961     {
00962       int origBaud;
00963       ArLog::log(ArLog::Normal, "Trying to close possible old connection");
00964       origBaud = serConn->getBaud();
00965       serConn->setBaud(9600);
00966       comInt(ArCommands::CLOSE,1);
00967       ArUtil::sleep(3);
00968       serConn->setBaud(38400);
00969       comInt(ArCommands::CLOSE,1);
00970       ArUtil::sleep(3);
00971       serConn->setBaud(115200);
00972       comInt(ArCommands::CLOSE,1);
00973       ArUtil::sleep(3);
00974       serConn->setBaud(19200);
00975       comInt(ArCommands::CLOSE,1);
00976       ArUtil::sleep(3);
00977       serConn->setBaud(57600);
00978       comInt(ArCommands::CLOSE,1);
00979       ArUtil::sleep(3);
00980       serConn->setBaud(origBaud);
00981     }
00982 
00983     if (myAsyncConnectNoPacketCount > 3)
00984     {
00985       ArLog::log(ArLog::Normal,
00986                  " Robot may be connected but not open, trying to dislodge.");
00987       mySender.comInt(ArCommands::OPEN,1);
00988     }
00989     
00990     myAsyncConnectState = 0;
00991   }
00992   // if we've connected and have a packet get the connection
00993   // information from it
00994   if (myAsyncConnectState == 3 && packet != NULL) 
00995   {
00996     char nameBuf[512];
00997     ArLog::log(ArLog::Terse, "Connected to robot.");
00998     packet->bufToStr(nameBuf, 512);
00999     myRobotName = nameBuf;
01000     ArLog::log(ArLog::Normal, "Name: %s", myRobotName.c_str());
01001     packet->bufToStr(nameBuf, 512);
01002     myRobotType = nameBuf;
01003     ArLog::log(ArLog::Normal, "Type: %s", myRobotType.c_str());
01004     packet->bufToStr(nameBuf, 512);
01005     myRobotSubType = nameBuf;
01006     strcpy(robotSubType, myRobotSubType.c_str());
01007     len = strlen(robotSubType);
01008     for (i = 0; i < len; i++)
01009       robotSubType[i] = tolower(robotSubType[i]);
01010     myRobotSubType = robotSubType;
01011     ArLog::log(ArLog::Normal, "Subtype: %s", myRobotSubType.c_str());
01012     ArUtil::sleep(getCycleTime());
01013     mySender.comInt(ArCommands::OPEN,1);
01014     if (!madeConnection())
01015     {
01016       mySender.comInt(ArCommands::CLOSE,1);
01017       failedConnect();
01018       return 2;
01019     }
01020 
01021     // now we return off so we can handle the rest of connecting, if
01022     // you're just using this for your own connections you can skip
01023     // this part because its really connected now
01024     myAsyncStartedConnection.setToNow();
01025     return asyncConnectHandler(tryHarderToConnect);
01026   }
01027   if (myAsyncConnectTimesTried > 50)
01028   {
01029     failedConnect();
01030     return 2;
01031   }
01032   return 0;
01033 }
01034 
01038 bool ArRobot::loadParamFile(const char *file)
01039 {
01040   if (myParams != NULL)
01041     delete myParams;
01042 
01043   myParams = new ArRobotGeneric("");
01044   if (!myParams->parseFile(file, false, true))
01045   {
01046     ArLog::log(ArLog::Normal, "ArRobot::loadParamFile: Could not find file '%s' to load.", file);
01047     return false;
01048   }
01049   processParamFile();
01050   ArLog::log(ArLog::Normal, "Loaded robot parameters from %s.", file);
01051   return true;
01052 }
01053 
01054 void ArRobot::processParamFile(void)
01055 {
01056   for (int i = 0; i < myParams->getNumSonar(); ++i)
01057   {
01058     //printf("sonar %d %d %d %d\n", i, myParams->getSonarX(i),
01059     //myParams->getSonarY(i), myParams->getSonarTh(i));
01060     if (mySonars.find(i) == mySonars.end())
01061     {
01062       mySonars[i] = new ArSensorReading(myParams->getSonarX(i),
01063                                         myParams->getSonarY(i), 
01064                                         myParams->getSonarTh(i));
01065       mySonars[i]->setIgnoreThisReading(true);
01066     }
01067     else
01068     {
01069       mySonars[i]->resetSensorPosition(myParams->getSonarX(i),
01070                                       myParams->getSonarY(i), 
01071                                       myParams->getSonarTh(i));
01072       mySonars[i]->setIgnoreThisReading(true);
01073     }
01074     if ((i + 1) > myNumSonar)
01075       myNumSonar = i + 1;
01076   }
01077   //myRobotType = myParams->getClassName();
01078   //myRobotSubType = myParams->getSubClassName();
01079   myAbsoluteMaxTransVel = myParams->getAbsoluteMaxVelocity();
01080   myAbsoluteMaxRotVel = myParams->getAbsoluteMaxRotVelocity();
01081 }
01082 
01083 
01084 bool ArRobot::madeConnection(void)
01085 {
01086   std::string subTypeParamName;
01087   std::string paramFileName;
01088   bool loadedSubTypeParam;
01089   bool loadedNameParam;
01090   bool hadDefault = true;
01091   
01092   if (myParams != NULL)
01093     delete myParams;
01094   
01095   // Find the robot parameters to load and get them into the structure we have
01096   if (ArUtil::strcmp(myRobotSubType, "p2dx") == 0)
01097     myParams = new ArRobotP2DX;
01098   else if (ArUtil::strcmp(myRobotSubType, "p2ce") == 0)
01099     myParams = new ArRobotP2CE;
01100   else if (ArUtil::strcmp(myRobotSubType, "p2de") == 0)
01101     myParams = new ArRobotP2DXe;
01102   else if (ArUtil::strcmp(myRobotSubType, "p2df") == 0)
01103     myParams = new ArRobotP2DF;
01104   else if (ArUtil::strcmp(myRobotSubType, "p2d8") == 0)
01105     myParams = new ArRobotP2D8;
01106   else if (ArUtil::strcmp(myRobotSubType, "amigo") == 0)
01107     myParams = new ArRobotAmigo;
01108   else if (ArUtil::strcmp(myRobotSubType, "amigo-sh") == 0)
01109     myParams = new ArRobotAmigoSh;
01110   else if (ArUtil::strcmp(myRobotSubType, "p2at") == 0)
01111     myParams = new ArRobotP2AT;
01112   else if (ArUtil::strcmp(myRobotSubType, "p2at8") == 0)
01113     myParams = new ArRobotP2AT8;
01114   else if (ArUtil::strcmp(myRobotSubType, "p2it") == 0)
01115     myParams = new ArRobotP2IT;
01116   else if (ArUtil::strcmp(myRobotSubType, "p2pb") == 0)
01117     myParams = new ArRobotP2PB;
01118   else if (ArUtil::strcmp(myRobotSubType, "p2pp") == 0)
01119     myParams = new ArRobotP2PP;
01120   else if (ArUtil::strcmp(myRobotSubType, "p3at") == 0)
01121     myParams = new ArRobotP3AT;
01122   else if (ArUtil::strcmp(myRobotSubType, "p3dx") == 0)
01123     myParams = new ArRobotP3DX;
01124   else if (ArUtil::strcmp(myRobotSubType, "perfpb") == 0)
01125     myParams = new ArRobotPerfPB;
01126   else if (ArUtil::strcmp(myRobotSubType, "pion1m") == 0)
01127     myParams = new ArRobotPion1M;
01128   else if (ArUtil::strcmp(myRobotSubType, "pion1x") == 0)
01129     myParams = new ArRobotPion1X;
01130   else if (ArUtil::strcmp(myRobotSubType, "psos1m") == 0)
01131     myParams = new ArRobotPsos1M;
01132   else if (ArUtil::strcmp(myRobotSubType, "psos43m") == 0)
01133     myParams = new ArRobotPsos43M;
01134   else if (ArUtil::strcmp(myRobotSubType, "psos1x") == 0)
01135     myParams = new ArRobotPsos1X;
01136   else if (ArUtil::strcmp(myRobotSubType, "pionat") == 0)
01137     myParams = new ArRobotPionAT;
01138   else if (ArUtil::strcmp(myRobotSubType, "mappr") == 0)
01139     myParams = new ArRobotMapper;
01140   else if (ArUtil::strcmp(myRobotSubType, "powerbot") == 0)
01141     myParams = new ArRobotPowerBot;
01142   else if (ArUtil::strcmp(myRobotSubType, "p2d8+") == 0)
01143     myParams = new ArRobotP2D8Plus;
01144   else if (ArUtil::strcmp(myRobotSubType, "p2at8+") == 0)
01145     myParams = new ArRobotP2AT8Plus;
01146   else if (ArUtil::strcmp(myRobotSubType, "perfpb+") == 0)
01147     myParams = new ArRobotPerfPBPlus;
01148   else if (ArUtil::strcmp(myRobotSubType, "p3dx-sh") == 0)
01149     myParams = new ArRobotP3DXSH;
01150   else if (ArUtil::strcmp(myRobotSubType, "p3at-sh") == 0)
01151     myParams = new ArRobotP3ATSH;
01152   else if (ArUtil::strcmp(myRobotSubType, "p3atiw-sh") == 0)
01153     myParams = new ArRobotP3ATIWSH;
01154   else if (ArUtil::strcmp(myRobotSubType, "patrolbot-sh") == 0)
01155     myParams = new ArRobotPatrolBotSH;
01156   else if (ArUtil::strcmp(myRobotSubType, "peoplebot-sh") == 0)
01157     myParams = new ArRobotPeopleBotSH;
01158   else if (ArUtil::strcmp(myRobotSubType, "powerbot-sh") == 0)
01159     myParams = new ArRobotPowerBotSH;
01160   else if (ArUtil::strcmp(myRobotSubType, "wheelchair-sh") == 0)
01161     myParams = new ArRobotWheelchairSH;
01162   else
01163   {
01164     hadDefault = false;
01165     myParams = new ArRobotGeneric(myRobotName.c_str());
01166   }
01167   
01168   // load up the param file for the subtype
01169   paramFileName = Aria::getDirectory();
01170   paramFileName += "params/";
01171   paramFileName += myRobotSubType;
01172   paramFileName += ".p";
01173   if ((loadedSubTypeParam = myParams->parseFile(paramFileName.c_str(), true, true)))
01174       ArLog::log(ArLog::Normal, 
01175                  "Loaded robot parameters from %s.p", 
01176                  myRobotSubType.c_str());
01177   /* If the above line was replaced with this one line
01178      paramFile->load(); 
01179      then the sonartest (and lots of other stuff probably) would break
01180   */
01181   // then the one for the particular name, if we can
01182   paramFileName = Aria::getDirectory();
01183   paramFileName += "params/";
01184   paramFileName += myRobotName;
01185   paramFileName += ".p";
01186   if ((loadedNameParam = myParams->parseFile(paramFileName.c_str(),
01187                                              true, true)))
01188   {
01189     if (loadedSubTypeParam)
01190       ArLog::log(ArLog::Normal, 
01191  "Loaded robot parameters from %s.p on top of %s.p robot parameters", 
01192                  myRobotName.c_str(), myRobotSubType.c_str());
01193     else
01194       ArLog::log(ArLog::Normal, "Loaded robot parameters from %s.p", 
01195                  myRobotName.c_str());
01196   }
01197    
01198   if (!loadedSubTypeParam && !loadedNameParam)
01199   {
01200     if (hadDefault)
01201       ArLog::log(ArLog::Normal, "Using default parameters for a %s robot", 
01202                  myRobotSubType.c_str());
01203     else
01204     {
01205       ArLog::log(ArLog::Terse, "Error: Have no parameters for this robot, bad configuration or out of date Aria");
01206       return false;
01207     }
01208   }
01209 
01210   processParamFile();
01211 
01212   if (myParams->getRequestIOPackets() || myRequestedIOPackets)
01213     comInt(ArCommands::IOREQUEST, 2);
01214 
01215   if(myParams->getRequestEncoderPackets() || myRequestedEncoderPackets)
01216     comInt(ArCommands::ENCODER, 2);
01217 
01218   return true;
01219 }
01220 
01221 void ArRobot::requestEncoderPackets(void)
01222 {
01223   comInt(ArCommands::ENCODER, 2);
01224   myRequestedEncoderPackets = true;
01225 }
01226 
01227 void ArRobot::requestIOPackets(void)
01228 {
01229   comInt(ArCommands::IOREQUEST, 2);
01230   myRequestedIOPackets = true;
01231 }
01232 
01233 void ArRobot::stopEncoderPackets(void)
01234 {
01235   comInt(ArCommands::ENCODER, 0);
01236   myRequestedEncoderPackets = false;
01237 }
01238 
01239 void ArRobot::stopIOPackets(void)
01240 {
01241   comInt(ArCommands::IOREQUEST, 0);
01242   myRequestedIOPackets = false;
01243 }
01244 
01245 void ArRobot::startStabilization(void)
01246 {
01247   std::list<ArFunctor *>::iterator it;
01248   myIsStabilizing = true;
01249   myStartedStabilizing.setToNow();
01250 
01251   for (it = myStabilizingCBList.begin(); 
01252        it != myStabilizingCBList.end(); 
01253        it++)
01254     (*it)->invoke();
01255 
01256 }
01257 
01258 void ArRobot::finishedConnection(void)
01259 {
01260   std::list<ArFunctor *>::iterator it;
01261 
01262   myIsStabilizing = false;
01263   myIsConnected = true;
01264   myAsyncConnectFlag = false;
01265   myBlockingConnectRun = false;
01266   
01267   for (it = myConnectCBList.begin(); it != myConnectCBList.end(); it++)
01268     (*it)->invoke();
01269   myLastPacketReceivedTime.setToNow();
01270 
01271   wakeAllConnWaitingThreads();
01272 }
01273 
01274 void ArRobot::failedConnect(void)
01275 {
01276   std::list<ArFunctor *>::iterator it;  
01277   
01278   myAsyncConnectFlag = false;
01279   myBlockingConnectRun = false;
01280   ArLog::log(ArLog::Terse, "Failed to connect to robot.");
01281   myIsConnected = false;
01282   for (it = myFailedConnectCBList.begin(); 
01283        it != myFailedConnectCBList.end(); 
01284        it++)
01285     (*it)->invoke();
01286 
01287   if (myConn != NULL)
01288     myConn->close();
01289   wakeAllConnOrFailWaitingThreads();
01290 }
01291 
01301 bool ArRobot::disconnect(void)
01302 {
01303   std::list<ArFunctor *>::iterator it;  
01304   bool ret;
01305   ArSerialConnection *serConn;
01306 
01307   if (!myIsConnected && !myIsStabilizing)
01308     return true;
01309   
01310   ArLog::log(ArLog::Terse, "Disconnecting from robot.");
01311   myNoTimeWarningThisCycle = true;
01312   myIsConnected = false;
01313   myIsStabilizing = false;
01314   if (myIsConnected)
01315   {
01316     for (it = myDisconnectNormallyCBList.begin(); 
01317          it != myDisconnectNormallyCBList.end(); 
01318          it++)
01319       (*it)->invoke();
01320   }
01321   ret = mySender.comInt(ArCommands::CLOSE, 1);
01322   ArUtil::sleep(1000);
01323   if (ret == true)
01324   {
01325     if (myConn != NULL)
01326     {
01327       ret = myConn->close();
01328       if ((serConn = dynamic_cast<ArSerialConnection *>(myConn)) != NULL)
01329         serConn->setBaud(myAsyncConnectStartBaud);
01330     } 
01331     else
01332       ret = false;
01333   } 
01334   else if (myConn != NULL)
01335     myConn->close();
01336     
01337   return ret;
01338 }
01339 
01340 void ArRobot::dropConnection(void)
01341 {
01342   std::list<ArFunctor *>::iterator it;  
01343 
01344   if (!myIsConnected)
01345     return;
01346 
01347   ArLog::log(ArLog::Terse, "Lost connection to the robot because of error.");
01348   myIsConnected = false;
01349   for (it = myDisconnectOnErrorCBList.begin(); 
01350        it != myDisconnectOnErrorCBList.end(); 
01351        it++)
01352     (*it)->invoke();
01353 
01354   if (myConn != NULL)
01355     myConn->close();
01356   return;
01357 }
01358 
01359 void ArRobot::cancelConnection(void)
01360 {
01361   //std::list<ArFunctor *>::iterator it;  
01362 
01363   ArLog::log(ArLog::Verbose, "Cancelled connection to the robot because of command.");
01364   myIsConnected = false;
01365   myNoTimeWarningThisCycle = true;
01366   myIsStabilizing = false;
01367   return;
01368 }
01369 
01379 void ArRobot::stop(void)
01380 {
01381   comInt(ArCommands::VEL, 0);
01382   comInt(ArCommands::RVEL, 0);
01383   setVel(0);
01384   setRotVel(0);
01385   myLastActionTransVal = 0;
01386   myLastActionRotStopped = true;
01387   myLastActionRotHeading = false;
01388 }
01389 
01396 void ArRobot::setVel(double velocity)
01397 {
01398   myTransType = TRANS_VEL;
01399   myTransVal = velocity;
01400   myTransVal2 = 0;
01401   myTransSetTime.setToNow();
01402 }
01403 
01418 void ArRobot::setVel2(double leftVelocity, double rightVelocity)
01419 {
01420   myTransType = TRANS_VEL2;
01421   myTransVal = leftVelocity;
01422   myTransVal2 = rightVelocity;
01423   myRotType = ROT_IGNORE;
01424   myRotVal = 0;
01425   myTransSetTime.setToNow();
01426 }
01427 
01435 void ArRobot::move(double distance)
01436 {
01437   myTransType = TRANS_DIST_NEW;
01438   myTransDistStart = getPose();
01439   myTransVal = distance;
01440   myTransVal2 = 0;
01441   myTransSetTime.setToNow();
01442 }
01443 
01458 bool ArRobot::isMoveDone(double delta)
01459 {
01460   if (fabs(delta) < 0.001)
01461     delta = myMoveDoneDist;
01462   if (myTransType != TRANS_DIST && myTransType != TRANS_DIST_NEW)
01463     return true;                // no distance command operative
01464   if (myTransDistStart.findDistanceTo(getPose()) <
01465       fabs(myTransVal) - delta)
01466     return false;
01467   return true;
01468 }
01469 
01470 
01483 bool ArRobot::isHeadingDone(double delta) const
01484 {
01485   if (fabs(delta) < 0.001)
01486     delta = myHeadingDoneDiff;
01487   if (myRotType != ROT_HEADING)
01488     return true;                // no heading command operative
01489   if(fabs(ArMath::subAngle(getTh(), myRotVal)) > delta)
01490     return false;
01491   return true;
01492 }
01493 
01494 
01495 
01502 void ArRobot::setHeading(double heading)
01503 {
01504   myRotVal = heading;
01505   myRotType = ROT_HEADING;
01506   myRotSetTime.setToNow();
01507   if (myTransType == TRANS_VEL2)
01508   {
01509     myTransType = TRANS_IGNORE;
01510     myTransVal = 0;
01511     myTransVal2 = 0;
01512   }
01513 }
01514 
01521 void ArRobot::setRotVel(double velocity)
01522 {
01523   myRotVal = velocity;
01524   myRotType = ROT_VEL;
01525   myRotSetTime.setToNow();
01526   if (myTransType == TRANS_VEL2)
01527   {
01528     myTransType = TRANS_IGNORE;
01529     myTransVal = 0;
01530     myTransVal2 = 0;
01531   }
01532 }
01533 
01540 void ArRobot::setDeltaHeading(double deltaHeading)
01541 {
01542   myRotVal = ArMath::addAngle(getTh(), deltaHeading);
01543   myRotType = ROT_HEADING;
01544   myRotSetTime.setToNow();
01545   if (myTransType == TRANS_VEL2)
01546   {
01547     myTransType = TRANS_IGNORE;
01548     myTransVal = 0;
01549     myTransVal2 = 0;
01550   }
01551 }
01552 
01566 bool ArRobot::setAbsoluteMaxTransVel(double maxVel)
01567 {
01568   if (maxVel < 0)
01569     return false;
01570   myAbsoluteMaxTransVel = maxVel;
01571   if (getTransVelMax() > myAbsoluteMaxTransVel)
01572     setTransVelMax(myAbsoluteMaxTransVel);
01573   return true;
01574 }
01575 
01587 bool ArRobot::setAbsoluteMaxRotVel(double maxVel)
01588 {
01589   if (maxVel < 0)
01590     return false;
01591   myAbsoluteMaxRotVel = maxVel;
01592   if (getRotVelMax() > myAbsoluteMaxRotVel)
01593     setRotVelMax(myAbsoluteMaxRotVel);
01594   return true;
01595 }
01596 
01601 int ArRobot::getIOAnalog(int num) const
01602 {
01603   if (num <= getIOAnalogSize())
01604     return myIOAnalog[num];
01605   else
01606     return 0;
01607 }
01608 
01612 double ArRobot::getIOAnalogVoltage(int num) const
01613 {
01614   if (num <= getIOAnalogSize())
01615   {
01616     return (myIOAnalog[num] & 0xfff) * .0048828;
01617   }
01618   else
01619     return 0;
01620 }
01621 
01622 unsigned char ArRobot::getIODigIn(int num) const
01623 {
01624   if (num <= getIODigInSize())
01625     return myIODigIn[num];
01626   else
01627     return (unsigned char) 0;
01628 }
01629 
01630 unsigned char  ArRobot::getIODigOut(int num) const
01631 {
01632   if (num <= getIODigOutSize())
01633     return myIODigOut[num];
01634   else
01635     return (unsigned char) 0;
01636 }
01637 
01641 const ArRobotParams *ArRobot::getRobotParams(void) const
01642 {
01643   return myParams;
01644 }
01645 
01650 const ArRobotConfigPacketReader *ArRobot::getOrigRobotConfig(void) const
01651 {
01652   return myOrigRobotConfig;
01653 }
01654   
01665 void ArRobot::addPacketHandler(
01666         ArRetFunctor1<bool, ArRobotPacket *> *functor, 
01667         ArListPos::Pos position) 
01668 {
01669   if (position == ArListPos::FIRST)
01670     myPacketHandlerList.push_front(functor);
01671   else if (position == ArListPos::LAST)
01672     myPacketHandlerList.push_back(functor);
01673   else
01674     ArLog::log(ArLog::Terse, "ArRobot::addPacketHandler: Invalid position.");
01675 
01676 }
01677 
01682 void ArRobot::remPacketHandler(
01683         ArRetFunctor1<bool, ArRobotPacket *> *functor)
01684 {
01685   myPacketHandlerList.remove(functor);
01686 }
01687 
01698 void ArRobot::addConnectCB(ArFunctor *functor, 
01699                                     ArListPos::Pos position)
01700 {
01701   if (position == ArListPos::FIRST)
01702     myConnectCBList.push_front(functor);
01703   else if (position == ArListPos::LAST)
01704     myConnectCBList.push_back(functor);
01705   else
01706     ArLog::log(ArLog::Terse, 
01707                "ArRobot::addConnectCallback: Invalid position.");
01708 }
01709 
01714 void ArRobot::remConnectCB(ArFunctor *functor)
01715 {
01716   myConnectCBList.remove(functor);
01717 }
01718 
01719 
01733 void ArRobot::addFailedConnectCB(ArFunctor *functor, 
01734                                           ArListPos::Pos position)
01735 {
01736   if (position == ArListPos::FIRST)
01737     myFailedConnectCBList.push_front(functor);
01738   else if (position == ArListPos::LAST)
01739     myFailedConnectCBList.push_back(functor);
01740   else
01741     ArLog::log(ArLog::Terse, 
01742                "ArRobot::addFailedCallback: Invalid position.");
01743 }
01744 
01749 void ArRobot::remFailedConnectCB(ArFunctor *functor)
01750 {
01751   myFailedConnectCBList.remove(functor);
01752 }
01753 
01765 void ArRobot::addDisconnectNormallyCB(ArFunctor *functor, 
01766                                                ArListPos::Pos position)
01767 {
01768   if (position == ArListPos::FIRST)
01769     myDisconnectNormallyCBList.push_front(functor);
01770   else if (position == ArListPos::LAST)
01771     myDisconnectNormallyCBList.push_back(functor);
01772   else
01773     ArLog::log(ArLog::Terse, 
01774                "ArRobot::addDisconnectNormallyCB: Invalid position.");
01775 }
01776 
01781 void ArRobot::remDisconnectNormallyCB(ArFunctor *functor)
01782 {
01783   myDisconnectNormallyCBList.remove(functor);
01784 }
01785 
01802 void ArRobot::addDisconnectOnErrorCB(ArFunctor *functor, 
01803                                               ArListPos::Pos position)
01804 {
01805   if (position == ArListPos::FIRST)
01806     myDisconnectOnErrorCBList.push_front(functor);
01807   else if (position == ArListPos::LAST)
01808     myDisconnectOnErrorCBList.push_back(functor);
01809   else
01810     ArLog::log(ArLog::Terse, 
01811                "ArRobot::addDisconnectOnErrorCB: Invalid position");
01812 }
01813 
01818 void ArRobot::remDisconnectOnErrorCB(ArFunctor *functor)
01819 {
01820   myDisconnectOnErrorCBList.remove(functor);
01821 }
01822 
01834 void ArRobot::addRunExitCB(ArFunctor *functor,
01835                                     ArListPos::Pos position)
01836 {
01837   if (position == ArListPos::FIRST)
01838     myRunExitCBList.push_front(functor);
01839   else if (position == ArListPos::LAST)
01840     myRunExitCBList.push_back(functor);
01841   else
01842     ArLog::log(ArLog::Terse, "ArRobot::addRunExitCB: Invalid position");
01843 }
01844 
01849 void ArRobot::remRunExitCB(ArFunctor *functor)
01850 {
01851   myRunExitCBList.remove(functor);
01852 }
01853 
01866 void ArRobot::addStabilizingCB(ArFunctor *functor, 
01867                                        ArListPos::Pos position)
01868 {
01869   if (position == ArListPos::FIRST)
01870     myStabilizingCBList.push_front(functor);
01871   else if (position == ArListPos::LAST)
01872     myStabilizingCBList.push_back(functor);
01873   else
01874     ArLog::log(ArLog::Terse, 
01875                "ArRobot::addConnectCallback: Invalid position.");
01876 }
01877 
01882 void ArRobot::remStabilizingCB(ArFunctor *functor)
01883 {
01884   myStabilizingCBList.remove(functor);
01885 }
01886 
01887 
01888 std::list<ArFunctor *> * ArRobot::getRunExitListCopy()
01889 {
01890   return(new std::list<ArFunctor *>(myRunExitCBList));
01891 }
01892 
01908 ArRobot::WaitState ArRobot::waitForConnect(unsigned int msecs)
01909 {
01910   int ret;
01911 
01912   if (isConnected())
01913     return(WAIT_CONNECTED);
01914 
01915   if (msecs == 0)
01916     ret=myConnectCond.wait();
01917   else
01918     ret=myConnectCond.timedWait(msecs);
01919 
01920   if (ret == ArCondition::STATUS_WAIT_INTR)
01921     return(WAIT_INTR);
01922   else if (ret == ArCondition::STATUS_WAIT_TIMEDOUT)
01923     return(WAIT_TIMEDOUT);
01924   else if (ret == 0)
01925     return(WAIT_CONNECTED);
01926   else
01927     return(WAIT_FAIL);
01928 }
01929 
01939 ArRobot::WaitState
01940 ArRobot::waitForConnectOrConnFail(unsigned int msecs)
01941 {
01942   int ret;
01943 
01944   if (isConnected())
01945     return(WAIT_CONNECTED);
01946 
01947   if (msecs == 0)
01948     ret=myConnOrFailCond.wait();
01949   else
01950     ret=myConnOrFailCond.timedWait(msecs);
01951 
01952   if (ret == ArCondition::STATUS_WAIT_INTR)
01953     return(WAIT_INTR);
01954   else if (ret == ArCondition::STATUS_WAIT_TIMEDOUT)
01955     return(WAIT_TIMEDOUT);
01956   else if (ret == 0)
01957   {
01958     if (isConnected())
01959       return(WAIT_CONNECTED);
01960     else
01961       return(WAIT_FAILED_CONN);
01962   }
01963   else
01964     return(WAIT_FAIL);
01965 }
01966 
01975 ArRobot::WaitState ArRobot::waitForRunExit(unsigned int msecs)
01976 {
01977   int ret;
01978 
01979   if (!isRunning())
01980     return(WAIT_RUN_EXIT);
01981 
01982   if (msecs == 0)
01983     ret=myRunExitCond.wait();
01984   else
01985     ret=myRunExitCond.timedWait(msecs);
01986 
01987   if (ret == ArCondition::STATUS_WAIT_INTR)
01988     return(WAIT_INTR);
01989   else if (ret == ArCondition::STATUS_WAIT_TIMEDOUT)
01990     return(WAIT_TIMEDOUT);
01991   else if (ret == 0)
01992     return(WAIT_RUN_EXIT);
01993   else
01994     return(WAIT_FAIL);
01995 }
01996 
02004 void ArRobot::wakeAllWaitingThreads()
02005 {
02006   wakeAllConnWaitingThreads();
02007   wakeAllRunExitWaitingThreads();
02008 }
02009 
02015 void ArRobot::wakeAllConnWaitingThreads()
02016 {
02017   myConnectCond.broadcast();
02018   myConnOrFailCond.broadcast();
02019 }
02020 
02027 void ArRobot::wakeAllConnOrFailWaitingThreads()
02028 {
02029   myConnOrFailCond.broadcast();
02030 }
02031 
02037 void ArRobot::wakeAllRunExitWaitingThreads()
02038 {
02039   myRunExitCond.broadcast();
02040 }
02041 
02049 ArSyncTask *ArRobot::getSyncTaskRoot(void)
02050 {
02051   return mySyncTaskRoot;
02052 }
02053 
02070 bool ArRobot::addUserTask(const char *name, int position, 
02071                                       ArFunctor *functor, 
02072                                       ArTaskState::State *state)
02073 {
02074   ArSyncTask *proc;
02075   if (mySyncTaskRoot == NULL)
02076     return false;
02077 
02078   proc = mySyncTaskRoot->findNonRecursive("User Tasks");
02079   if (proc == NULL)
02080     return false;
02081   
02082   proc->addNewLeaf(name, position, functor, state);
02083   return true;  
02084 }
02085 
02090 void ArRobot::remUserTask(const char *name)
02091 {
02092   ArSyncTask *proc;
02093   ArSyncTask *userProc;
02094 
02095   if (mySyncTaskRoot == NULL)
02096     return;
02097 
02098   proc = mySyncTaskRoot->findNonRecursive("User Tasks");
02099   if (proc == NULL)
02100     return;
02101   
02102   userProc = proc->findNonRecursive(name);
02103   if (userProc == NULL)
02104     return;
02105 
02106   
02107   delete userProc;
02108 
02109 }
02110 
02115 void ArRobot::remUserTask(ArFunctor *functor)
02116 {
02117   ArSyncTask *proc;
02118   ArSyncTask *userProc;
02119 
02120   if (mySyncTaskRoot == NULL)
02121     return;
02122 
02123   proc = mySyncTaskRoot->findNonRecursive("User Tasks");
02124   if (proc == NULL)
02125     return;
02126   
02127   
02128   userProc = proc->findNonRecursive(functor);
02129   if (userProc == NULL)
02130     return;
02131 
02132   
02133   delete userProc;
02134 
02135 }
02136 
02148 bool ArRobot::addSensorInterpTask(const char *name, int position, 
02149                                               ArFunctor *functor,
02150                                               ArTaskState::State *state)
02151 {
02152   ArSyncTask *proc;
02153   if (mySyncTaskRoot == NULL)
02154     return false;
02155 
02156   proc = mySyncTaskRoot->findNonRecursive("Sensor Interp");
02157   if (proc == NULL)
02158     return false;
02159   
02160   proc->addNewLeaf(name, position, functor, state);
02161   return true;  
02162 }
02163 
02168 void ArRobot::remSensorInterpTask(const char *name)
02169 {
02170   ArSyncTask *proc;
02171   ArSyncTask *sensorInterpProc;
02172 
02173   if (mySyncTaskRoot == NULL)
02174     return;
02175 
02176   proc = mySyncTaskRoot->findNonRecursive("Sensor Interp");
02177   if (proc == NULL)
02178     return;
02179   
02180   sensorInterpProc = proc->findNonRecursive(name);
02181   if (sensorInterpProc == NULL)
02182     return;
02183 
02184   
02185   delete sensorInterpProc;
02186 
02187 }
02188 
02193 void ArRobot::remSensorInterpTask(ArFunctor *functor)
02194 {
02195   ArSyncTask *proc;
02196   ArSyncTask *sensorInterpProc;
02197 
02198   if (mySyncTaskRoot == NULL)
02199     return;
02200 
02201   proc = mySyncTaskRoot->findNonRecursive("Sensor Interp");
02202   if (proc == NULL)
02203     return;
02204   
02205   
02206   sensorInterpProc = proc->findNonRecursive(functor);
02207   if (sensorInterpProc == NULL)
02208     return;
02209 
02210   
02211   delete sensorInterpProc;
02212 
02213 }
02214 
02218 void ArRobot::logUserTasks(void) const
02219 {
02220   ArSyncTask *proc;
02221   if (mySyncTaskRoot == NULL)
02222     return;
02223 
02224   proc = mySyncTaskRoot->findNonRecursive("User Tasks");
02225   if (proc == NULL)
02226     return;
02227 
02228   proc->log();
02229 }
02230 
02234 void ArRobot::logAllTasks(void) const
02235 {
02236   if (mySyncTaskRoot != NULL)
02237     mySyncTaskRoot->log();
02238 }
02239 
02245 ArSyncTask *ArRobot::findUserTask(const char *name)
02246 {
02247   ArSyncTask *proc;
02248   if (mySyncTaskRoot == NULL)
02249     return NULL;
02250 
02251   proc = mySyncTaskRoot->findNonRecursive("User Tasks");
02252   if (proc == NULL)
02253     return NULL;
02254 
02255   return proc->find(name);
02256 }
02257 
02263 ArSyncTask *ArRobot::findUserTask(ArFunctor *functor)
02264 {
02265   ArSyncTask *proc;
02266   if (mySyncTaskRoot == NULL)
02267     return NULL;
02268 
02269   proc = mySyncTaskRoot->findNonRecursive("User Tasks");
02270   if (proc == NULL)
02271     return NULL;
02272 
02273   return proc->find(functor);
02274 }
02275 
02281 ArSyncTask *ArRobot::findTask(const char *name)
02282 {
02283   if (mySyncTaskRoot != NULL)
02284     return mySyncTaskRoot->find(name);
02285   else
02286     return NULL;
02287 
02288 }
02289 
02295 ArSyncTask *ArRobot::findTask(ArFunctor *functor)
02296 {
02297   if (mySyncTaskRoot != NULL)
02298     return mySyncTaskRoot->find(functor);
02299   else
02300     return NULL;
02301 
02302 }
02303 
02317 bool ArRobot::addAction(ArAction *action, int priority)
02318 {
02319   if (action == NULL)
02320   {
02321     ArLog::log(ArLog::Terse, 
02322       "ArRobot::addAction: an attempt was made to add a NULL action pointer");
02323     return false;
02324   }
02325   
02326   action->setRobot(this);
02327   myActions.insert(std::pair<int, ArAction *>(priority, action));
02328   return true;
02329 }
02330 
02338 bool ArRobot::remAction(const char *actionName)
02339 {
02340   ArResolver::ActionMap::iterator it;
02341   ArAction *act;
02342 
02343   for (it = myActions.begin(); it != myActions.end(); ++it)
02344   {
02345     act = (*it).second;
02346     if (strcmp(actionName, act->getName()) == 0)
02347       break;
02348   }
02349   if (it != myActions.end())
02350   {
02351     myActions.erase(it);
02352     return true;
02353   }
02354   return false;
02355 
02356 }
02357 
02365 bool ArRobot::remAction(ArAction *action)
02366 {
02367   ArResolver::ActionMap::iterator it;
02368   ArAction *act;
02369 
02370   for (it = myActions.begin(); it != myActions.end(); ++it)
02371   {
02372     act = (*it).second;
02373     if (act == action)
02374       break;
02375   }
02376   if (it != myActions.end())
02377   {
02378     myActions.erase(it);
02379     return true;
02380   }
02381   return false;
02382 
02383 }
02384 
02385 
02392 ArAction *ArRobot::findAction(const char *actionName)
02393 {
02394   ArResolver::ActionMap::reverse_iterator it;
02395   ArAction *act;
02396   
02397   for (it = myActions.rbegin(); it != myActions.rend(); ++it)
02398   {
02399     act = (*it).second;
02400     if (strcmp(actionName, act->getName()) == 0)
02401       return act;
02402   }
02403   return NULL;
02404 }
02405 
02415 ArResolver::ActionMap *ArRobot::getActionMap(void)
02416 {
02417   return &myActions;
02418 }
02419 
02420 void ArRobot::deactivateActions(void)
02421 {
02422   ArResolver::ActionMap *am;
02423   ArResolver::ActionMap::iterator amit;
02424   
02425   am = getActionMap();
02426   if (am == NULL)
02427   {
02428     ArLog::log(ArLog::Terse, 
02429             "ArRobot::deactivateActions: NULL action map... failed.");
02430     return;
02431   }
02432   for (amit = am->begin(); amit != am->end(); amit++)
02433     (*amit).second->deactivate();
02434   
02435 
02436 }
02437 
02438 
02439 void ArRobot::logActions(void) const
02440 {
02441   ArResolver::ActionMap::const_reverse_iterator it;
02442   int lastPriority;
02443   bool first = true;
02444 
02445   ArLog::log(ArLog::Terse, "The action list (%d of them):\n", myActions.size());
02446   for (it = myActions.rbegin(); it != myActions.rend(); ++it)
02447   {
02448     if (first || lastPriority != (*it).first) 
02449     {
02450       ArLog::log(ArLog::Terse, "Priority %d:", (*it).first);
02451       first = false;
02452       lastPriority = (*it).first;
02453     }
02454     (*it).second->log(false);
02455   }
02456     
02457 }
02458 
02459 ArResolver *ArRobot::getResolver(void)
02460 {
02461   return myResolver;
02462 }
02463 
02464 void ArRobot::setResolver(ArResolver *resolver)
02465 {
02466   if (myOwnTheResolver)
02467   {
02468     delete myResolver;
02469     myResolver = NULL;
02470   }
02471 
02472   myResolver = resolver;
02473 }
02474 
02486 void ArRobot::stateReflector(void)
02487 {
02488   short transVal;
02489   short transVal2;
02490   short maxVel;
02491   short maxNegVel;
02492   double maxTransVel;
02493   double maxNegTransVel;
02494   double maxRotVel;
02495   double transAccel;
02496   double transDecel;
02497   short rotVal;
02498   double rotAccel;
02499   double rotDecel;
02500   bool rotStopped = false;
02501   bool rotHeading = false;
02502   double encTh;
02503   double rawTh;
02504 
02505 
02506   if (!myIsConnected)
02507     return;
02508 
02509   // if this is true actions can't go
02510   if ((myTransType != TRANS_NONE && myDirectPrecedenceTime == 0) ||
02511       (myTransType != TRANS_NONE && myDirectPrecedenceTime != 0 && 
02512        myTransSetTime.mSecSince() < myDirectPrecedenceTime))
02513   {
02514     myActionTransSet = false;
02515     transVal = ArMath::roundShort(myTransVal);
02516     transVal2 = 0;
02517 
02518     if (hasSettableVelMaxes() && 
02519         ArMath::fabs(myLastSentTransVelMax - myTransVelMax) >= 1)
02520     {
02521       comInt(ArCommands::SETV,
02522              ArMath::roundShort(myTransVelMax));
02523       myLastSentTransVelMax = myTransVelMax;
02524       if (myLogMovementSent)
02525         ArLog::log(ArLog::Normal, "Non-action trans max vel of %d", 
02526                    ArMath::roundShort(myTransVelMax));
02527     }
02528 
02529     if (hasSettableAccsDecs() && ArMath::fabs(myTransAccel) > 1 && 
02530         ArMath::fabs(myLastSentTransAccel - myTransAccel) >= 1)
02531     {
02532       comInt(ArCommands::SETA,
02533              ArMath::roundShort(myTransAccel));
02534       myLastSentTransAccel = myTransAccel;
02535       if (myLogMovementSent)
02536         ArLog::log(ArLog::Normal, "Non-action trans accel of %d", 
02537                    ArMath::roundShort(myTransAccel));
02538     }
02539 
02540     if (hasSettableAccsDecs() && ArMath::fabs(myTransDecel) > 1 &&
02541         ArMath::fabs(myLastSentTransDecel - myTransDecel) >= 1)
02542     {
02543       comInt(ArCommands::SETA,
02544              -ArMath::roundShort(myTransDecel));
02545       myLastSentTransDecel = myTransDecel;
02546       if (myLogMovementSent)
02547         ArLog::log(ArLog::Normal, "Non-action trans decel of %d", 
02548                    -ArMath::roundShort(myTransDecel));
02549     }
02550 
02551     if (myTransType == TRANS_VEL)
02552     {
02553       maxVel = ArMath::roundShort(myTransVelMax);
02554       if (transVal > maxVel)
02555         transVal = maxVel;
02556       if (transVal < -maxVel)
02557         transVal = -maxVel;
02558       if (myLastTransVal != transVal || myLastTransType != myTransType ||
02559           (myLastTransSent.mSecSince() >= myStateReflectionRefreshTime))
02560       {
02561         comInt(ArCommands::VEL, ArMath::roundShort(transVal));
02562         myLastTransSent.setToNow();
02563         if (myLogMovementSent)
02564           ArLog::log(ArLog::Normal, "Non-action trans vel of %d", 
02565                      ArMath::roundShort(transVal));
02566         //printf("Sent command vel!\n");
02567       }
02568     }
02569     else if (myTransType == TRANS_VEL2)
02570     {
02571       if (ArMath::roundShort(myTransVal/myParams->getVel2Divisor()) > 128)
02572         transVal = 128;
02573       else if (ArMath::roundShort(myTransVal/myParams->getVel2Divisor()) < -128)
02574         transVal = -128;
02575       else 
02576         transVal = ArMath::roundShort(myTransVal/myParams->getVel2Divisor());
02577       if (ArMath::roundShort(myTransVal2/myParams->getVel2Divisor()) > 128)
02578         transVal2 = 128;
02579       else if (ArMath::roundShort(myTransVal2/myParams->getVel2Divisor()) < -128)
02580         transVal2 = -128;
02581       else 
02582         transVal2 = ArMath::roundShort(myTransVal2/myParams->getVel2Divisor());
02583       if (myLastTransVal != transVal || myLastTransVal2 != transVal2 || 
02584           myLastTransType != myTransType ||
02585           (myLastTransSent.mSecSince() >= myStateReflectionRefreshTime))
02586       {
02587         com2Bytes(ArCommands::VEL2, transVal, transVal2);
02588         myLastTransSent.setToNow();
02589         if (myLogMovementSent)
02590           ArLog::log(ArLog::Normal, "Non-action vel2 of %d %d", 
02591                      transVal, transVal2);
02592         //printf("Sent command vel2!\n");
02593       }
02594     }
02595     else if (myTransType == TRANS_DIST_NEW || myTransType == TRANS_DIST)
02596     {
02597       // if the robot doesn't have its own distance command
02598       if (!myParams->hasMoveCommand())
02599       {
02600         double distGone;
02601         double distToGo;
02602         double vel;
02603 
02604         myTransType = TRANS_DIST;
02605         distGone = myTransDistStart.findDistanceTo(getPose());
02606         distToGo = fabs(fabs(myTransVal) - distGone);
02607         if (distGone > fabs(myTransVal) || 
02608             (distToGo < 10 && fabs(getVel()) < 30))
02609         {
02610           comInt(ArCommands::VEL, 0);
02611           myTransType = TRANS_VEL;
02612           myTransVal = 0;
02613         }
02614         vel = sqrt(distToGo * 200 * 2);
02615         if (vel > getTransVelMax())
02616           vel = getTransVelMax();
02617         if (myTransVal < 0)
02618           vel *= -1;
02619         comInt(ArCommands::VEL, ArMath::roundShort(vel));
02620         if (myLogMovementSent)
02621           ArLog::log(ArLog::Normal, "Non-action move-helper of %d", 
02622                      ArMath::roundShort(vel));
02623       }
02624       else if (myParams->hasMoveCommand() && myTransType == TRANS_DIST_NEW) 
02625       {
02626         comInt(ArCommands::MOVE, transVal);
02627         myLastTransSent.setToNow();
02628         myTransType = TRANS_DIST;
02629         if (myLogMovementSent)
02630           ArLog::log(ArLog::Normal, "Non-action move of %d", 
02631                      transVal);
02632       }
02633       else if (myTransType == TRANS_DIST && 
02634           (myLastTransSent.mSecSince() >= myStateReflectionRefreshTime))
02635       {
02636         com(0);
02637         myLastPulseSent.setToNow();
02638         myLastTransSent.setToNow();
02639         //printf("Sent pulse for dist!\n");
02640         if (myLogMovementSent)
02641           ArLog::log(ArLog::Normal, "Non-action pulse for dist");
02642       }
02643       //printf("Sent command move!\n");
02644     }
02645     else if (myTransType == TRANS_IGNORE)
02646     {
02647       //printf("No trans command sent\n");
02648     }
02649     else
02650       ArLog::log(ArLog::Terse, 
02651                  "ArRobot::stateReflector: Invalid translational type %d.",
02652                  myTransType);
02653     myLastTransVal = transVal;
02654     myLastTransVal2 = transVal2;
02655     myLastTransType = myTransType;
02656   }
02657   else // if actions can go
02658   {
02659     if (hasSettableVelMaxes() && 
02660         ArMath::fabs(myLastSentTransVelMax - myTransVelMax) >= 1)
02661     {
02662       comInt(ArCommands::SETV,
02663              ArMath::roundShort(myTransVelMax));
02664       myLastSentTransVelMax = myTransVelMax;
02665       if (myLogMovementSent)
02666         ArLog::log(ArLog::Normal, "Action-but-robot trans max vel of %d", 
02667                    ArMath::roundShort(myTransVelMax));
02668     }
02669     
02670     // first we'll handle all of the accel decel things
02671     if (myActionDesired.getTransAccelStrength() >= 
02672         ArActionDesired::MIN_STRENGTH)
02673     {
02674       transAccel = ArMath::roundShort(myActionDesired.getTransAccel());
02675       if (hasSettableAccsDecs() && ArMath::fabs(transAccel) > 1 &&
02676           ArMath::fabs(myLastSentTransAccel - transAccel) >= 1)
02677       {
02678         comInt(ArCommands::SETA,
02679                ArMath::roundShort(transAccel));
02680         myLastSentTransAccel = transAccel;
02681         if (myLogMovementSent)
02682           ArLog::log(ArLog::Normal, "Action trans accel of %d", 
02683                      ArMath::roundShort(transAccel));
02684       }
02685     }
02686     else if (hasSettableAccsDecs() && ArMath::fabs(myTransAccel) > 1 && 
02687         ArMath::fabs(myLastSentTransAccel - myTransAccel) >= 1)
02688     {
02689       comInt(ArCommands::SETA,
02690              ArMath::roundShort(myTransAccel));
02691       myLastSentTransAccel = myTransAccel;
02692       if (myLogMovementSent)
02693         ArLog::log(ArLog::Normal, "Action-but-robot trans accel of %d", 
02694                    ArMath::roundShort(myTransAccel));
02695     }
02696 
02697     if (myActionDesired.getTransDecelStrength() >=
02698         ArActionDesired::MIN_STRENGTH)
02699     {
02700       transDecel = ArMath::roundShort(myActionDesired.getTransDecel());
02701       if (hasSettableAccsDecs() && ArMath::fabs(transDecel) > 1 &&
02702           ArMath::fabs(myLastSentTransDecel - transDecel) >= 1)
02703       {
02704         comInt(ArCommands::SETA,
02705                -ArMath::roundShort(transDecel));
02706         myLastSentTransDecel = transDecel;
02707         if (myLogMovementSent)
02708           ArLog::log(ArLog::Normal, "Action trans decel of %d", 
02709                      -ArMath::roundShort(transDecel));
02710       }
02711     }
02712     else if (hasSettableAccsDecs() && ArMath::fabs(myTransDecel) > 1 &&
02713         ArMath::fabs(myLastSentTransDecel - myTransDecel) >= 1)
02714     {
02715       comInt(ArCommands::SETA,
02716              -ArMath::roundShort(myTransDecel));
02717       myLastSentTransDecel = myTransDecel;
02718       if (myLogMovementSent)
02719         ArLog::log(ArLog::Normal, "Action-but-robot trans decel of %d", 
02720                    -ArMath::roundShort(myTransDecel));
02721     }
02722 
02723     if (myActionDesired.getMaxVelStrength() >= ArActionDesired::MIN_STRENGTH)
02724     {
02725       maxTransVel = myActionDesired.getMaxVel();
02726       if (maxTransVel > myTransVelMax)
02727         maxTransVel = myTransVelMax;
02728     }
02729     else
02730       maxTransVel = myTransVelMax;
02731 
02732     if (myActionDesired.getMaxNegVelStrength() >= 
02733         ArActionDesired::MIN_STRENGTH)
02734     {
02735       maxNegTransVel = -ArMath::fabs(myActionDesired.getMaxNegVel());
02736       if (maxNegTransVel < -myTransVelMax)
02737         maxNegTransVel = -myTransVelMax;
02738     }
02739     else
02740       maxNegTransVel = -myTransVelMax;
02741     
02742     if (myActionDesired.getVelStrength() >= ArActionDesired::MIN_STRENGTH)
02743     {
02744       transVal = ArMath::roundShort(myActionDesired.getVel());
02745       myActionTransSet = true;
02746     }
02747     else
02748     {
02749       transVal = myLastActionTransVal;
02750     }
02751 
02752     maxVel = ArMath::roundShort(maxTransVel);
02753     maxNegVel = ArMath::roundShort(maxNegTransVel);
02754     if (transVal > maxVel)
02755       transVal = maxVel;
02756     if (transVal < maxNegVel)
02757       transVal = maxNegVel;
02758 
02759     if (myActionTransSet && 
02760         (myLastTransSent.mSecSince() >= myStateReflectionRefreshTime ||
02761          transVal != myLastActionTransVal))                          
02762     {
02763       comInt(ArCommands::VEL, ArMath::roundShort(transVal));
02764       myLastTransSent.setToNow();
02765       if (myLogMovementSent)
02766         ArLog::log(ArLog::Normal, "Action trans vel of %d", 
02767                    ArMath::roundShort(transVal));      
02768     }
02769     myLastActionTransVal = transVal;
02770   }
02771 
02772   // if this is true actions can't go
02773   if ((myRotType != ROT_NONE && myDirectPrecedenceTime == 0) ||
02774       (myRotType != ROT_NONE && myDirectPrecedenceTime != 0 && 
02775        myRotSetTime.mSecSince() < myDirectPrecedenceTime))
02776   {
02777     if (hasSettableVelMaxes() && 
02778         ArMath::fabs(myLastSentRotVelMax - myRotVelMax) >= 1)
02779     {
02780       comInt(ArCommands::SETRV,
02781              ArMath::roundShort(myRotVelMax));
02782       myLastSentRotVelMax = myRotVelMax;
02783     }
02784     if (hasSettableAccsDecs() && ArMath::fabs(myRotAccel) > 1 &&
02785         ArMath::fabs(myLastSentRotAccel - myRotAccel) >= 1)
02786     {
02787       comInt(ArCommands::SETRA,
02788              ArMath::roundShort(myRotAccel));
02789       myLastSentRotAccel = myRotAccel;
02790       if (myLogMovementSent)
02791         ArLog::log(ArLog::Normal, "%25sNon-action rot accel of %d", "",
02792                    ArMath::roundShort(myRotAccel));      
02793     }
02794     if (hasSettableAccsDecs() && ArMath::fabs(myRotDecel) > 1 &&
02795         ArMath::fabs(myLastSentRotDecel - myRotDecel) >= 1)
02796     {
02797       comInt(ArCommands::SETRA,
02798              -ArMath::roundShort(myRotDecel));
02799       myLastSentRotDecel = myRotDecel;
02800       if (myLogMovementSent)
02801         ArLog::log(ArLog::Normal, "%25sNon-action rot decel of %d", "",
02802                    -ArMath::roundShort(myRotDecel));      
02803     }
02804 
02805     myActionRotSet = false;
02806     rotVal = ArMath::roundShort(myRotVal);
02807     if (myRotType == ROT_HEADING)
02808     {
02809       encTh = ArMath::subAngle(myRotVal, myEncoderTransform.getTh());
02810       rawTh = ArMath::addAngle(encTh, 
02811                                ArMath::subAngle(myRawEncoderPose.getTh(),
02812                                                 myEncoderPose.getTh()));
02813       rotVal = ArMath::roundShort(rawTh);
02814 
02815       // if we were using a different heading type, a different heading
02816       // our heading doesn't match what we want it to be, or its been a while
02817       // since we sent the heading, send it again
02818       if (myLastRotVal != rotVal || myLastRotType != myRotType ||
02819           fabs(ArMath::subAngle(rotVal, getTh())) > 1 ||
02820           (myLastRotSent.mSecSince() >= myStateReflectionRefreshTime))
02821       {
02822         comInt(ArCommands::HEAD, rotVal);
02823         myLastRotSent.setToNow();
02824         //printf("sent command, heading\n");
02825         if (myLogMovementSent)
02826           ArLog::log(ArLog::Normal, 
02827              "%25sNon-action rot heading of %d (encoder %d, raw %d)",
02828                      "",
02829                      ArMath::roundShort(myRotVal),
02830                      ArMath::roundShort(encTh),
02831                      ArMath::roundShort(rotVal));
02832       }
02833     }
02834     else if (myRotType == ROT_VEL)
02835     {
02836       if (myLastRotVal != rotVal || myLastRotType != myRotType ||
02837           (myLastRotSent.mSecSince() >= myStateReflectionRefreshTime))
02838       {
02839         comInt(ArCommands::RVEL, rotVal);
02840         myLastRotSent.setToNow();
02841         if (myLogMovementSent)
02842           ArLog::log(ArLog::Normal, "%25sNon-action rot vel of %d", "",
02843                      rotVal);      
02844         //printf("sent command, rot vel\n");
02845       }
02846     }
02847     else if (myRotType == ROT_IGNORE)
02848     {
02849       //printf("Not sending any command, rot is set to ignore");
02850     }
02851     else
02852       ArLog::log(ArLog::Terse, 
02853                  "ArRobot::stateReflector: Invalid rotation type %d.",
02854                  myRotType);
02855     myLastRotVal = rotVal;
02856     myLastRotType = myRotType;
02857   }
02858   else // if the action can fire
02859   {
02860     // first we'll handle all of the accel decel things
02861     if (myActionDesired.getMaxRotVelStrength() >=
02862         ArActionDesired::MIN_STRENGTH)
02863     {
02864       maxRotVel = myActionDesired.getMaxRotVel();
02865       if (maxRotVel > myAbsoluteMaxRotVel)
02866         maxRotVel = myAbsoluteMaxRotVel;
02867       maxRotVel = ArMath::roundShort(maxRotVel);
02868       if (ArMath::fabs(myLastSentRotVelMax - maxRotVel) >= 1)
02869       {
02870         myLastSentRotVelMax = maxRotVel;
02871         comInt(ArCommands::SETRV, 
02872                ArMath::roundShort(maxRotVel));
02873         if (myLogMovementSent)
02874           ArLog::log(ArLog::Normal, "%25sAction rot vel max of %d", "",
02875                      ArMath::roundShort(maxRotVel));
02876       }
02877     }
02878     else if (hasSettableVelMaxes() && 
02879              ArMath::fabs(myLastSentRotVelMax - myRotVelMax) >= 1)
02880     {
02881       comInt(ArCommands::SETRV,
02882              ArMath::roundShort(myRotVelMax));
02883       myLastSentRotVelMax = myRotVelMax;
02884       if (myLogMovementSent)
02885         ArLog::log(ArLog::Normal, 
02886                    "%25sAction-but-robot rot vel max of %d", 
02887                    "",  ArMath::roundShort(myRotVelMax));      
02888     }
02889 
02890     if (myActionDesired.getRotAccelStrength() >= ArActionDesired::MIN_STRENGTH)
02891     {
02892       rotAccel = ArMath::roundShort(myActionDesired.getRotAccel());
02893       if (ArMath::fabs(myLastSentRotAccel - rotAccel) >= 1)
02894       {
02895         comInt(ArCommands::SETRA,
02896                ArMath::roundShort(rotAccel));
02897         myLastSentRotAccel = rotAccel;
02898         if (myLogMovementSent)
02899           ArLog::log(ArLog::Normal, "%25sAction rot accel of %d", "",
02900                      ArMath::roundShort(rotAccel));
02901       }
02902     }
02903     else if (hasSettableAccsDecs() && ArMath::fabs(myRotAccel) > 1 &&
02904         ArMath::fabs(myLastSentRotAccel - myRotAccel) >= 1)
02905     {
02906       comInt(ArCommands::SETRA,
02907              ArMath::roundShort(myRotAccel));
02908       myLastSentRotAccel = myRotAccel;
02909       if (myLogMovementSent)
02910         ArLog::log(ArLog::Normal, "%25sAction-but-robot rot accel of %d", 
02911                    "", ArMath::roundShort(myRotAccel));      
02912     }
02913 
02914     if (myActionDesired.getRotDecelStrength() >= ArActionDesired::MIN_STRENGTH)
02915     {
02916       rotDecel = ArMath::roundShort(myActionDesired.getRotDecel());
02917       if (ArMath::fabs(myLastSentRotDecel - rotDecel) >= 1)
02918       {
02919         comInt(ArCommands::SETRA,
02920                -ArMath::roundShort(rotDecel));
02921         myLastSentRotDecel = rotDecel;
02922         if (myLogMovementSent)
02923           ArLog::log(ArLog::Normal, "%25sAction rot decel of %d", "",
02924                      -ArMath::roundShort(rotDecel));
02925       }
02926     }
02927     else if (hasSettableAccsDecs() && ArMath::fabs(myRotDecel) > 1 &&
02928         ArMath::fabs(myLastSentRotDecel - myRotDecel) >= 1)
02929     {
02930       comInt(ArCommands::SETRA,
02931              -ArMath::roundShort(myRotDecel));
02932       myLastSentRotDecel = myRotDecel;
02933       if (myLogMovementSent)
02934         ArLog::log(ArLog::Normal, "%25sAction-but-robot rot decel of %d", 
02935                    "", -ArMath::roundShort(myRotDecel));      
02936     }
02937 
02938 
02939 
02940     if (myActionDesired.getDeltaHeadingStrength() >=
02941                                              ArActionDesired::MIN_STRENGTH)
02942     {
02943       if (ArMath::roundShort(myActionDesired.getDeltaHeading()) == 0)
02944       {
02945         rotStopped = true;
02946         rotVal = 0;
02947         rotHeading = false;
02948       }
02949       else
02950       {
02951         //printf("delta %.0f\n", myActionDesired.getDeltaHeading());
02952         //encTh = ArMath::subAngle(myRotVal, myEncoderTransform.getTh());
02953         encTh = ArMath::subAngle(
02954                 ArMath::addAngle(myActionDesired.getDeltaHeading(), 
02955                                  getTh()),
02956                 myEncoderTransform.getTh());
02957         //printf("final th %.0f\n", th);
02958         rawTh = ArMath::addAngle(encTh, 
02959                                  ArMath::subAngle(myRawEncoderPose.getTh(),
02960                                                   myEncoderPose.getTh()));
02961         rotVal = ArMath::roundShort(rawTh);
02962         rotStopped = false;
02963         rotHeading = true;
02964       }
02965       myActionRotSet = true;
02966     } 
02967     else if (myActionDesired.getRotVelStrength() >=
02968                                              ArActionDesired::MIN_STRENGTH)
02969     {
02970       if (ArMath::roundShort(myActionDesired.getRotVel()) == 0)
02971       {
02972         rotStopped = true;
02973         rotVal = 0;
02974         rotHeading = false;
02975       }
02976       else
02977       {
02978         rotStopped = false;
02979         rotVal = ArMath::roundShort(myActionDesired.getRotVel());
02980         rotHeading = false;
02981       }
02982       myActionRotSet = true;
02983     }
02984     else
02985     {
02986       rotStopped = myLastActionRotStopped;
02987       rotVal = myLastActionRotVal;
02988       rotHeading = myLastActionRotHeading;
02989     }
02990 
02991     if (myActionRotSet && 
02992         (myLastRotSent.mSecSince() > myStateReflectionRefreshTime ||
02993          rotStopped != myLastActionRotStopped || 
02994          rotVal != myLastActionRotVal || 
02995          rotHeading != myLastActionRotHeading))
02996     {
02997       if (rotStopped)
02998       {
02999         comInt(ArCommands::RVEL, 0);
03000         if (myLogMovementSent)
03001           ArLog::log(ArLog::Normal, 
03002                      "%25sAction rot vel of 0 (rotStopped)",
03003                      "");
03004       }
03005       else if (rotHeading)
03006       {
03007         comInt(ArCommands::HEAD, rotVal);
03008         if (myLogMovementSent)
03009           ArLog::log(ArLog::Normal, 
03010                      "%25sAction rot heading of %d (encoder %d, raw %d)",
03011                      "",
03012                      ArMath::roundShort(ArMath::addAngle(
03013                              myActionDesired.getDeltaHeading(), 
03014                              getTh())),
03015                      ArMath::roundShort(encTh),
03016                      ArMath::roundShort(rotVal));
03017       }
03018       else
03019       {
03020         comInt(ArCommands::RVEL, rotVal);
03021         if (myLogMovementSent)
03022           ArLog::log(ArLog::Normal, "%25sAction rot vel of %d", "", 
03023                      rotVal);
03024       }
03025       myLastRotSent.setToNow();
03026     }               
03027     
03028     myLastActionRotVal = rotVal;
03029     myLastActionRotStopped = rotStopped;
03030     myLastActionRotHeading = rotHeading;
03031   }
03032 
03033   if (myLastRotSent.mSecSince() > myStateReflectionRefreshTime &&
03034       myLastTransSent.mSecSince() > myStateReflectionRefreshTime &&
03035       myLastPulseSent.mSecSince() > myStateReflectionRefreshTime)
03036   {
03037     com(ArCommands::PULSE);
03038     myLastPulseSent.setToNow();
03039     if (myLogMovementSent)
03040       ArLog::log(ArLog::Normal, "Pulse"); 
03041 
03042   }
03043 }
03044 
03045 bool ArRobot::handlePacket(ArRobotPacket *packet)
03046 {
03047   std::list<ArRetFunctor1<bool, ArRobotPacket *> *>::iterator it;
03048   bool handled;
03049 
03050   lock();
03051   //printf("ms since last packet %ld this type 0x%x\n", myLastPacketReceivedTime.mSecSince(packet->getTimeReceived()), packet->getID());
03052   myLastPacketReceivedTime = packet->getTimeReceived();
03053   if (packet->getID() == 0xff) 
03054   {
03055     ArLog::log(ArLog::Terse, "Losing connection because robot was reset.");
03056     dropConnection();
03057     unlock();
03058     return false;
03059   }
03060 
03061   for (handled = false, it = myPacketHandlerList.begin(); 
03062        it != myPacketHandlerList.end() && handled == false; 
03063        it++)
03064   {
03065     if ((*it) != NULL && (*it)->invokeR(packet)) 
03066       handled = true;
03067     else
03068       packet->resetRead();
03069   }
03070   if (!handled)
03071     ArLog::log(ArLog::Normal, 
03072                "No packet handler wanted packet with ID: 0x%x", 
03073                packet->getID());
03074   unlock();
03075   return handled;
03076 }
03077 
03078 
03079 /* @note You must first start the encoder packet stream by calling
03080  * requestEncoderPackets() before this function will return encoder values.
03081  */
03082 long int ArRobot::getLeftEncoder()
03083 {
03084   return myLeftEncoder;
03085 }
03086 
03087 /* @note You must first start the encoder packet stream by calling
03088  * requestEncoderPackets() before this function will return encoder values.
03089  */
03090 long int ArRobot::getRightEncoder()
03091 {
03092   return myRightEncoder;
03093 }
03094 
03095 
03100 void ArRobot::robotLocker(void)
03101 {
03102   lock();
03103 }
03104 
03109 void ArRobot::robotUnlocker(void)
03110 {
03111   unlock();
03112 }
03113 
03120 void ArRobot::packetHandler(void)
03121 {
03122   ArRobotPacket *packet;
03123   int timeToWait;
03124   ArTime start;
03125   bool sipHandled = false;
03126 
03127   if (myAsyncConnectFlag)
03128   {
03129     lock();
03130     asyncConnectHandler(false);
03131     unlock();
03132     return;
03133   }
03134 
03135   if (!isConnected())
03136     return;
03137 
03138   start.setToNow();
03139   /*
03140     The basic idea is that if we're chained to the sip we run through
03141     and see if we have any packets available now (like if we got
03142     backed up), we only check this for half the cycle time
03143     though... if we know the cycle time of the robot (from config)
03144     then we go for half that, if we don't know the cycle time of the
03145     robot (from config) then we go for half of whatever our cycle time
03146     is set to
03147 
03148     if we don't have any packets waiting then we chill and wait for
03149     it, if we got one, just get on with it
03150   **/
03151   packet = NULL;
03152   // read all the packets that are available
03153   while ((packet = myReceiver.receivePacket(0)) != NULL)
03154   {
03155     if (myPacketsReceivedTracking)
03156     {
03157       ArLog::log(ArLog::Normal, 
03158                  "Rcvd: prePacket (%ld) 0x%x at %ld (%ld)", 
03159                  myPacketsReceivedTrackingCount, 
03160                  packet->getID(), start.mSecSince(), 
03161                  myPacketsReceivedTrackingStarted.mSecSince());
03162       myPacketsReceivedTrackingCount++;
03163     }
03164 
03165     handlePacket(packet);
03166     if ((packet->getID() & 0xf0) == 0x30)
03167       sipHandled = true;
03168     packet = NULL;
03169 
03170     // if we've taken too long here then break
03171     if ((getOrigRobotConfig()->hasPacketArrived() &&
03172          start.mSecSince() > getOrigRobotConfig()->getSipCycleTime() / 2) ||
03173         (!getOrigRobotConfig()->hasPacketArrived() &&
03174          (unsigned int) start.mSecSince() > myCycleTime / 2))
03175     {
03176       break;
03177     }
03178   }
03179 
03180   if (isCycleChained())
03181     timeToWait = getCycleTime() * 2 - start.mSecSince();
03182   
03183   // if we didn't get a sip and we're chained to the sip, wait for the sip
03184   while (isCycleChained() && !sipHandled && isRunning() && 
03185          (packet = myReceiver.receivePacket(timeToWait)) != NULL)
03186   {
03187     if (myPacketsReceivedTracking)
03188     {
03189       ArLog::log(ArLog::Normal, "Rcvd: Packet (%ld) 0x%x at %ld (%ld)", 
03190                  myPacketsReceivedTrackingCount, 
03191                  packet->getID(), start.mSecSince(), 
03192                  myPacketsReceivedTrackingStarted.mSecSince());
03193       myPacketsReceivedTrackingCount++;
03194     }
03195 
03196     handlePacket(packet);
03197     if ((packet->getID() & 0xf0) == 0x30)
03198       break;
03199     timeToWait = getCycleTime() * 2 - start.mSecSince();
03200     if (timeToWait < 0)
03201       timeToWait = 0;
03202   }
03203 
03204   if (myTimeoutTime > 0 && 
03205       ((-myLastPacketReceivedTime.mSecTo()) > myTimeoutTime))
03206   {
03207     ArLog::log(ArLog::Terse, 
03208                "Losing connection because nothing received from robot in %d milliseconds.", 
03209                myTimeoutTime);
03210     dropConnection();
03211   }
03212 
03213   if (myPacketsReceivedTracking)
03214     ArLog::log(ArLog::Normal, "Rcvd: time taken %ld", start.mSecSince());
03215 
03216 }
03217 
03225 void ArRobot::actionHandler(void)
03226 {
03227   ArActionDesired *actDesired;
03228 
03229   if (myResolver == NULL || myActions.size() == 0 || !isConnected())
03230     return;
03231   
03232   actDesired = myResolver->resolve(&myActions, this);
03233   
03234   myActionDesired.reset();
03235 
03236   if (actDesired == NULL)
03237     return;
03238 
03239   myActionDesired.merge(actDesired);  
03240 }
03241 
03250 void ArRobot::setCycleWarningTime(unsigned int ms)
03251 {
03252   myCycleWarningTime = ms;
03253   // we don't have to send it down because the functor gets it each cycle
03254 }
03255 
03264 unsigned int ArRobot::getCycleWarningTime(void) const
03265 {
03266   return myCycleWarningTime;
03267 }
03268 
03277 unsigned int ArRobot::getCycleWarningTime(void)
03278 {
03279   return myCycleWarningTime;
03280 }
03281 
03289 void ArRobot::setCycleTime(unsigned int ms)
03290 {
03291   myCycleTime = ms;
03292 }
03293 
03306 void ArRobot::setStabilizingTime(int mSecs)
03307 {
03308   if (mSecs > 0)
03309     myStabilizingTime = mSecs;
03310   else
03311     myStabilizingTime = 0;
03312 }
03313 
03319 int ArRobot::getStabilizingTime(void) const
03320 {
03321   return myStabilizingTime;
03322 }
03323 
03331 unsigned int ArRobot::getCycleTime(void) const
03332 {
03333   return myCycleTime;
03334 }
03335 
03336 
03337 
03346 void ArRobot::setConnectionCycleMultiplier(unsigned int multiplier)
03347 {
03348   myConnectionCycleMultiplier = multiplier;
03349 }
03350 
03358 unsigned int ArRobot::getConnectionCycleMultiplier(void) const
03359 {
03360   return myConnectionCycleMultiplier;
03361 }
03362 
03363 
03370 void ArRobot::loopOnce(void)
03371 {
03372   if (mySyncTaskRoot != NULL)
03373     mySyncTaskRoot->run();
03374   
03375   incCounter();
03376 }
03377 
03378 
03379 // DigIn IR logic is reverse.  0 means broken, 1 means not broken
03380 
03381 bool ArRobot::isLeftTableSensingIRTriggered(void) const
03382 {
03383   if (myParams->haveTableSensingIR())
03384   {
03385     if (myParams->haveNewTableSensingIR() && myIODigInSize > 3)
03386       return !(getIODigIn(3) & ArUtil::BIT1);
03387     else
03388       return !(getDigIn() & ArUtil::BIT0);
03389   }
03390   return 0;
03391 }
03392 
03393 bool ArRobot::isRightTableSensingIRTriggered(void) const
03394 {
03395   if (myParams->haveTableSensingIR())
03396   {
03397     if (myParams->haveNewTableSensingIR() && myIODigInSize > 3) 
03398       return !(getIODigIn(3) & ArUtil::BIT0);
03399     else
03400       return !(getDigIn() & ArUtil::BIT1);
03401   }
03402   return 0;
03403 }
03404 
03405 bool ArRobot::isLeftBreakBeamTriggered(void) const
03406 {
03407   if (myParams->haveTableSensingIR())
03408   {
03409     if (myParams->haveNewTableSensingIR() && myIODigInSize > 3) 
03410       return !(getIODigIn(3) & ArUtil::BIT2);
03411     else
03412       return !(getDigIn() & ArUtil::BIT3);
03413   }
03414   return 0;
03415 }
03416 
03417 bool ArRobot::isRightBreakBeamTriggered(void) const
03418 {
03419   if (myParams->haveTableSensingIR())
03420   {
03421     if (myParams->haveNewTableSensingIR() && myIODigInSize > 3) 
03422       return !(getIODigIn(3) & ArUtil::BIT3);
03423     else
03424       return !(getDigIn() & ArUtil::BIT2);
03425   }
03426   return 0;
03427 }
03428 
03429 int ArRobot::getMotorPacCount(void) const
03430 {
03431   if (myTimeLastMotorPacket == time(NULL))
03432     return myMotorPacCount;
03433   if (myTimeLastMotorPacket == time(NULL) - 1)
03434     return myMotorPacCurrentCount;
03435   return 0;
03436 }
03437 
03438 int ArRobot::getSonarPacCount(void) const
03439 {
03440   if (myTimeLastSonarPacket == time(NULL))
03441     return mySonarPacCount;
03442   if (myTimeLastSonarPacket == time(NULL) - 1)
03443     return mySonarPacCurrentCount;
03444   return 0;
03445 }
03446 
03447 
03448 bool ArRobot::processMotorPacket(ArRobotPacket *packet)
03449 {
03450   int x, y, th, qx, qy, qth; 
03451   double deltaX, deltaY, deltaTh;
03452 
03453   int numReadings;
03454   int sonarNum;
03455   int sonarRange;
03456 
03457   if (packet->getID() != 0x32 && packet->getID() != 0x33) 
03458     return false;
03459 
03460   // upkeep the counting variable
03461   if (myTimeLastMotorPacket != time(NULL)) 
03462   {
03463     myTimeLastMotorPacket = time(NULL);
03464     myMotorPacCount = myMotorPacCurrentCount;
03465     myMotorPacCurrentCount = 0;
03466   }
03467   myMotorPacCurrentCount++;
03468 
03469   x = (packet->bufToUByte2() & 0x7fff);
03470   y = (packet->bufToUByte2() & 0x7fff);
03471   th = packet->bufToByte2();
03472 
03473   if (myFirstEncoderPose)
03474   {
03475     qx = 0;
03476     qy = 0;
03477     qth = 0;
03478     myFirstEncoderPose = false;
03479     myRawEncoderPose.setPose(
03480             myParams->getDistConvFactor() * x,
03481             myParams->getDistConvFactor() * y, 
03482             ArMath::radToDeg(myParams->getAngleConvFactor() * (double)th));
03483     myEncoderPose = myRawEncoderPose;
03484     myEncoderTransform.setTransform(myEncoderPose, myGlobalPose);
03485   }
03486   else 
03487   {
03488     qx = x - myLastX;
03489     qy = y - myLastY;
03490     qth = th - myLastTh;
03491   }
03492 
03493 
03494   //ArLog::log(ArLog::Terse, "Damnit qx %d qy %d,  x %d y %d,  lastx %d lasty %d", qx, qy, x, y, myLastX, myLastY);  
03495   myLastX = x;
03496   myLastY = y;
03497   myLastTh = th;
03498 
03499   if (qx > 0x1000) 
03500     qx -= 0x8000;
03501   if (qx < -0x1000)
03502     qx += 0x8000;
03503 
03504   if (qy > 0x1000) 
03505     qy -= 0x8000;
03506   if (qy < -0x1000)
03507     qy += 0x8000;
03508   
03509   deltaX = myParams->getDistConvFactor() * (double)qx;
03510   deltaY = myParams->getDistConvFactor() * (double)qy;
03511   deltaTh = ArMath::radToDeg(myParams->getAngleConvFactor() * (double)qth);
03512   //encoderTh = ArMath::radToDeg(myParams->getAngleConvFactor() * (double)(th));
03513 
03514 
03515   // encoder stuff was here
03516 
03517 
03518 
03519   myLeftVel = myParams->getVelConvFactor() * packet->bufToByte2();
03520   myRightVel = myParams->getVelConvFactor() * packet->bufToByte2();
03521   myVel = (myLeftVel + myRightVel)/2.0;
03522   myRotVel = ArMath::radToDeg((myRightVel - myLeftVel) / 2.0 * 
03523                                     myParams->getDiffConvFactor());
03524 
03525   myBatteryVoltage = packet->bufToUByte() * .1;
03526   myBatteryAverager.add(myBatteryVoltage);
03527   myStallValue = packet->bufToByte2();
03528   
03529   //ArLog::log("x %.1f y %.1f th %.1f vel %.1f voltage %.1f", myX, myY, myTh, 
03530   //myVel, myBatteryVoltage);
03531 
03532   myControl = ArMath::fixAngle(ArMath::radToDeg(myParams->getAngleConvFactor() *
03533                                   (packet->bufToByte2() - th)));
03534   myFlags = packet->bufToUByte2();
03535   myCompass = 2*packet->bufToUByte();
03536   
03537   for (numReadings = packet->bufToByte(); numReadings > 0; numReadings--)
03538   {
03539     sonarNum = packet->bufToByte();
03540     sonarRange = ArMath::roundInt(
03541             (double)packet->bufToUByte2() * myParams->getRangeConvFactor());
03542     processNewSonar(sonarNum, sonarRange, packet->getTimeReceived());
03543   }
03544   
03545   if (packet->getDataLength() - packet->getDataReadLength() > 0)
03546   {
03547     myAnalogPortSelected = packet->bufToUByte2();
03548     myAnalog = packet->bufToByte();
03549     myDigIn = packet->bufToByte();
03550     myDigOut = packet->bufToByte();
03551   }
03552 
03553   if (packet->getDataLength() - packet->getDataReadLength() > 0)
03554     myRealBatteryVoltage = packet->bufToUByte2() * .1;
03555   else
03556     myRealBatteryVoltage = myBatteryVoltage;
03557 
03558   myRealBatteryAverager.add(myRealBatteryVoltage);
03559 
03560   if (packet->getDataLength() - packet->getDataReadLength() > 0)
03561     myChargeState = (ChargeState) packet->bufToUByte();
03562   else
03563     myChargeState = CHARGING_UNKNOWN;
03564 
03565   /*
03566     Okay how this works is like so.  
03567 
03568     We keep around the raw encoder position, because we must use this
03569     to find differences between last position and this position.
03570     
03571     We find the difference in x and y positions (deltaX and deltaY)
03572     and keep these around for later use, but we also add these to our
03573     raw encoder readings for X and Y.  We also find the change in
03574     angle (deltaTh), which is used for inertial corrections, and added
03575     to the raw encoder heading to find which the current raw encoder
03576     heading.
03577 
03578 
03579     From here there are two paths:
03580 
03581     Path 1) Have a callback.  If we have a callback it means that we
03582     have an inertial nav device of some kind.  If this is the case,
03583     then we pass the callback the delta between last position and
03584     current position, along with the time of the current position,
03585     then the callback gives us back a new delta theta (deltaTh).  We
03586     then need to rotate the deltaX and deltaY into our corrected
03587     encoder space.  We do this by making a transform that takes the
03588     raw encoder heading and transforms it to what our new heading is
03589     (adding deltaTh to our current encoder th), and then applying that
03590     transform, taking the results as our new deltaX and deltaY.
03591 
03592     Path 2) We have no callback, we just use the heading that came
03593     back from the robot as our delta theta (deltaTh);
03594 
03595     From here the two paths unify again.  deltaX and deltaY are added
03596     to the encoder pose (this is the corrected encoder pose), and the
03597     encoder heading is set to the newTh.
03598 
03599     Note that this leaves a difference between rawEncoder heading and
03600     our heading, which is fine, BUT if you are sending heading
03601     commands to the robot you need to compenstate for the difference
03602     between these. 
03603     
03604     Note above that we return deltaTh instead of just heading so that
03605     we can turn inertial on and off without losing track of where
03606     we're at... since we're just adding in deltas from the heading it
03607     doesn't matter how we switch around the callback.
03608     
03609   **/
03610 
03611   myRawEncoderPose.setX(myRawEncoderPose.getX() + deltaX);
03612   myRawEncoderPose.setY(myRawEncoderPose.getY() + deltaY);
03613   myRawEncoderPose.setTh(myRawEncoderPose.getTh() + deltaTh);
03614 
03615   // check if there is a correction callback, if there is get the new
03616   // heading out of it instead of using the raw encoder heading
03617   if (myEncoderCorrectionCB != NULL)
03618   {
03619     ArPoseWithTime deltaPose(deltaX, deltaY, deltaTh,
03620                              packet->getTimeReceived());
03621     deltaTh = myEncoderCorrectionCB->invokeR(deltaPose);   
03622     ArTransform trans(ArPose(0, 0, myRawEncoderPose.getTh()),
03623                       ArPose(0, 0,
03624                              ArMath::addAngle(myEncoderPose.getTh(), 
03625                                               deltaTh)));
03626 
03627     ArPose rotatedDelta = trans.doTransform(ArPose(deltaX, deltaY, 0));
03628 
03629     deltaX = rotatedDelta.getX();
03630     deltaY = rotatedDelta.getY();
03631   }
03632 
03633   myEncoderPose.setTime(packet->getTimeReceived());
03634   myEncoderPose.setX(myEncoderPose.getX() + deltaX);
03635   myEncoderPose.setY(myEncoderPose.getY() + deltaY);
03636   myEncoderPose.setTh(ArMath::addAngle(myEncoderPose.getTh(), deltaTh));
03637 
03638   myGlobalPose = myEncoderTransform.doTransform(myEncoderPose);
03639 
03640   if (myLogMovementReceived)
03641     ArLog::log(ArLog::Normal, 
03642                "Global (%5.0f %5.0f %5.0f) Encoder (%5.0f %5.0f %5.0f) Raw (%5.0f %5.0f %5.0f)",
03643                myGlobalPose.getX(), myGlobalPose.getY(),
03644                myGlobalPose.getTh(),
03645                myEncoderPose.getX(), myEncoderPose.getY(),
03646                myEncoderPose.getTh(),
03647                myRawEncoderPose.getX(), myRawEncoderPose.getY(), 
03648                myRawEncoderPose.getTh());
03649 
03650   if (myLogVelocitiesReceived)
03651     ArLog::log(ArLog::Normal, 
03652                "     TransVel: %5.0f RotVel: %5.0f LeftVel: %5.0f RightVel: %5.0f Heading %5.0f",
03653                getVel(), getRotVel(), getLeftVel(), getRightVel(), 
03654                getTh());
03655 
03656   //ArLog::log(ArLog::Terse, "(%.0f %.0f) (%.0f %.0f)", deltaX, deltaY, myGlobalPose.getX(),         myGlobalPose.getY());
03657   
03658   myInterpolation.addReading(packet->getTimeReceived(), myGlobalPose);
03659   myEncoderInterpolation.addReading(packet->getTimeReceived(), myEncoderPose);
03660 
03661   return true;
03662 }
03663 
03664 void ArRobot::processNewSonar(char number, int range, 
03665                                        ArTime timeReceived)
03666 {
03675   std::map<int, ArSensorReading *>::iterator it;
03676   ArSensorReading *sonar;
03677   ArTransform encoderTrans;
03678   ArPose encoderPose;
03679 
03680   if ((it = mySonars.find(number)) != mySonars.end())
03681   {
03682     sonar = (*it).second;
03683     sonar->newData(range, getPose(), getEncoderPose(), getToGlobalTransform(), 
03684                    getCounter(), timeReceived); 
03685     if (myTimeLastSonarPacket != time(NULL)) 
03686     {
03687       myTimeLastSonarPacket = time(NULL);
03688       mySonarPacCount = mySonarPacCurrentCount;
03689       mySonarPacCurrentCount = 0;
03690     }
03691     mySonarPacCurrentCount++;
03692   }
03693   else if (!myWarnedAboutExtraSonar)
03694   {
03695     ArLog::log(ArLog::Normal, "Robot gave back extra sonar reading!  Either the parameter file for the robot or the firmware needs updating.");
03696     myWarnedAboutExtraSonar = true;
03697   }
03698 }
03699 
03700 
03701 
03702 bool ArRobot::processEncoderPacket(ArRobotPacket *packet)
03703 {
03704   if (packet->getID() != 0x90)
03705     return false;
03706   myLeftEncoder = packet->bufToByte4();
03707   myRightEncoder = packet->bufToByte4();
03708   return true;
03709 }
03710 
03711 bool ArRobot::processIOPacket(ArRobotPacket *packet)
03712 {
03713   int i, num;
03714 
03715   if (packet->getID() != 0xf0)
03716     return false;
03717 
03718   myLastIOPacketReceivedTime = packet->getTimeReceived();
03719 
03720   // number of DigIn bytes
03721   num = packet->bufToUByte();
03722   for (i = 0; i < num; ++i)
03723     myIODigIn[i] = packet->bufToUByte();
03724   myIODigInSize = num;
03725 
03726   // number of DigOut bytes
03727   num = packet->bufToUByte();
03728   for (i = 0; i < num; ++i)
03729     myIODigOut[i] = packet->bufToUByte();
03730   myIODigOutSize = num;
03731 
03732   // number of A/D bytes
03733   num = packet->bufToUByte();
03734   for (i = 0; i < num; ++i)
03735     myIOAnalog[i] = packet->bufToUByte2();
03736   myIOAnalogSize = num;
03737 
03738   return true;
03739 }
03740 
03750 int ArRobot::getSonarRange(int num) const
03751 {
03752   std::map<int, ArSensorReading *>::const_iterator it;
03753   
03754   if ((it = mySonars.find(num)) != mySonars.end())
03755     return (*it).second->getRange();
03756   else
03757     return -1;
03758 }
03759 
03768 bool ArRobot::isSonarNew(int num) const
03769 {
03770   std::map<int, ArSensorReading *>::const_iterator it;
03771   
03772   if ((it = mySonars.find(num)) != mySonars.end())
03773     return (*it).second->isNew(getCounter());
03774   else
03775     return false;
03776 }
03777 
03790 ArSensorReading *ArRobot::getSonarReading(int num) const
03791 {
03792   std::map<int, ArSensorReading *>::const_iterator it;
03793   
03794   if ((it = mySonars.find(num)) != mySonars.end())
03795     return (*it).second;
03796   else
03797     return NULL;
03798 }
03799 
03800 
03806 bool ArRobot::com(unsigned char command)
03807 {
03808   if (myPacketsSentTracking)
03809     ArLog::log(ArLog::Normal, "Sent: com(%d)", command);
03810   return mySender.com(command);
03811 }
03812 
03819 bool ArRobot::comInt(unsigned char command, short int argument)
03820 {
03821   if (myPacketsSentTracking)
03822     ArLog::log(ArLog::Normal, "Sent: comInt(%d, %d)", command, argument);
03823   return mySender.comInt(command, argument);
03824 }
03825 
03833 bool ArRobot::com2Bytes(unsigned char command, char high, char low)
03834 {
03835   if (myPacketsSentTracking)
03836     ArLog::log(ArLog::Normal, "Sent: com2Bytes(%d, %d, %d)", command, 
03837                high, low);
03838   return mySender.com2Bytes(command, high, low);
03839 }
03840 
03847 bool ArRobot::comStr(unsigned char command, const char *argument)
03848 {
03849   if (myPacketsSentTracking)
03850     ArLog::log(ArLog::Normal, "Sent: comStr(%d, '%s')", command, 
03851                argument);
03852   return mySender.comStr(command, argument);
03853 }
03854 
03862 bool ArRobot::comStrN(unsigned char command, const char *str, 
03863                                int size)
03864 {
03865   if (myPacketsSentTracking)
03866   {
03867     char strBuf[512];
03868     strncpy(strBuf, str, size);
03869     strBuf[size] = '\0';
03870     ArLog::log(ArLog::Normal, "Sent: comStrN(%d, '%s') (size %d)",
03871                command, strBuf, size);
03872   }
03873   return mySender.comStrN(command, str, size);
03874 }
03875 
03876 int ArRobot::getClosestSonarRange(double startAngle, double endAngle) const
03877 {
03878   int num;
03879   num = getClosestSonarNumber(startAngle, endAngle);
03880   if (num == -1)
03881     return -1;
03882   else 
03883     return getSonarRange(num);
03884 }
03885 
03886 int ArRobot::getClosestSonarNumber(double startAngle, double endAngle) const
03887 {
03888   int i;
03889   ArSensorReading *sonar;
03890   int closestReading;
03891   int closestSonar;
03892   bool noReadings = true;
03893 
03894   for (i = 0; i < getNumSonar(); i++) 
03895   {
03896     sonar = getSonarReading(i);
03897     if (sonar == NULL)
03898     {
03899       ArLog::log(ArLog::Terse, "Have an empty sonar at number %d, there should be %d sonar.", i, getNumSonar());
03900       continue;
03901     }
03902     if (ArMath::angleBetween(sonar->getSensorTh(), startAngle, endAngle))
03903     {
03904       if (noReadings)
03905       {
03906         closestReading = sonar->getRange();
03907         closestSonar = i;
03908         noReadings = false;
03909       }
03910       else if (sonar->getRange() < closestReading)
03911       {
03912         closestReading = sonar->getRange();
03913         closestSonar = i;
03914       }
03915     }
03916   }
03917 
03918   if (noReadings)
03919     return -1;
03920   else
03921     return closestSonar;
03922 }
03923 
03924 void ArRobot::addRangeDevice(ArRangeDevice *device)
03925 {
03926   device->setRobot(this);
03927   myRangeDeviceList.push_front(device);
03928 }
03929 
03933 void ArRobot::remRangeDevice(const char *name)
03934 {
03935   std::list<ArRangeDevice *>::iterator it;
03936   for (it = myRangeDeviceList.begin(); it != myRangeDeviceList.end(); ++it)
03937   {
03938     if (strcmp(name, (*it)->getName()) == 0)
03939     {
03940       myRangeDeviceList.erase(it);
03941       return;
03942     }
03943   }
03944 }
03945 
03949 void ArRobot::remRangeDevice(ArRangeDevice *device)
03950 {
03951   std::list<ArRangeDevice *>::iterator it;
03952   for (it = myRangeDeviceList.begin(); it != myRangeDeviceList.end(); ++it)
03953   {
03954     if ((*it) == device)
03955     {
03956       myRangeDeviceList.erase(it);
03957       return;
03958     }
03959   }
03960 }
03961 
03966 ArRangeDevice *ArRobot::findRangeDevice(const char *name)
03967 {
03968   std::list<ArRangeDevice *>::iterator it;
03969   ArRangeDevice *device;
03970 
03971   for (it = myRangeDeviceList.begin(); it != myRangeDeviceList.end(); ++it)
03972   {
03973     device = (*it);
03974     if (strcmp(name, device->getName()) == 0)
03975     {
03976       return device;
03977     }
03978   }
03979   return NULL;
03980 }
03981 
03986 const ArRangeDevice *ArRobot::findRangeDevice(const char *name) const
03987 {
03988   std::list<ArRangeDevice *>::const_iterator it;
03989   ArRangeDevice *device;
03990 
03991   for (it = myRangeDeviceList.begin(); it != myRangeDeviceList.end(); ++it)
03992   {
03993     device = (*it);
03994     if (strcmp(name, device->getName()) == 0)
03995     {
03996       return device;
03997     }
03998   }
03999   return NULL;
04000 }
04001 
04008 std::list<ArRangeDevice *> *ArRobot::getRangeDeviceList(void)
04009 {
04010   return &myRangeDeviceList;
04011 }
04012 
04016 bool ArRobot::hasRangeDevice(ArRangeDevice *device) const
04017 {
04018   std::list<ArRangeDevice *>::const_iterator it;
04019   for (it = myRangeDeviceList.begin(); it != myRangeDeviceList.end(); ++it)
04020   {
04021     if ((*it) == device)
04022       return true;
04023   }
04024   return false;
04025 }
04026 
04046 double ArRobot::checkRangeDevicesCurrentPolar(double startAngle,
04047                                                        double endAngle,
04048                                                        double *angle) const
04049 {
04050   double closest, closeAngle, tempDist, tempAngle;
04051   std::list<ArRangeDevice *>::const_iterator it;
04052   ArRangeDevice *device;
04053   bool foundOne = false;
04054 
04055   for (it = myRangeDeviceList.begin(); it != myRangeDeviceList.end(); ++it)
04056   {
04057     device = (*it);
04058     device->lockDevice();
04059     if (!foundOne || 
04060         (tempDist = device->currentReadingPolar(startAngle, endAngle,
04061                                                 &tempAngle)) < closest)
04062     {
04063       if (!foundOne)
04064       {
04065         closest = device->currentReadingPolar(startAngle, endAngle, 
04066                                               &closeAngle);
04067       }
04068       else
04069       {
04070         closest = tempDist;
04071         closeAngle = tempAngle;
04072       }
04073       foundOne = true;
04074     }
04075     device->unlockDevice();
04076   }
04077   if (!foundOne)
04078     return -1;
04079   if (angle != NULL)
04080     *angle = closeAngle;
04081   return closest;
04082   
04083 }
04084 
04104 double ArRobot::checkRangeDevicesCumulativePolar(double startAngle,
04105                                                        double endAngle,
04106                                                        double *angle) const
04107 {
04108   double closest, closeAngle, tempDist, tempAngle;
04109   std::list<ArRangeDevice *>::const_iterator it;
04110   ArRangeDevice *device;
04111   bool foundOne = false;
04112 
04113   for (it = myRangeDeviceList.begin(); it != myRangeDeviceList.end(); ++it)
04114   {
04115     device = (*it);
04116     device->lockDevice();
04117     if (!foundOne || 
04118         (tempDist = device->cumulativeReadingPolar(startAngle, endAngle,
04119                                                  &tempAngle)) < closest)
04120     {
04121       if (!foundOne)
04122       {
04123         closest = device->cumulativeReadingPolar(startAngle, endAngle, 
04124                                               &closeAngle);
04125       }
04126       else
04127       {
04128         closest = tempDist;
04129         closeAngle = tempAngle;
04130       }
04131       foundOne = true;
04132     }
04133     device->unlockDevice();
04134   }
04135   if (!foundOne)
04136     return -1;
04137   if (angle != NULL)
04138     *angle = closeAngle;
04139   return closest;
04140   
04141 }
04142 
04159 double ArRobot::checkRangeDevicesCurrentBox(double x1, double y1,
04160                                                      double x2, double y2,
04161                                                      ArPose *readingPos) const
04162 {
04163 
04164   double closest, tempDist;
04165   ArPose closestPos, tempPos;
04166   std::list<ArRangeDevice *>::const_iterator it;
04167   ArRangeDevice *device;
04168   bool foundOne = false;
04169 
04170   for (it = myRangeDeviceList.begin(); it != myRangeDeviceList.end(); ++it)
04171   {
04172     device = (*it);
04173     device->lockDevice();
04174     if (!foundOne || 
04175         (tempDist = device->currentReadingBox(x1, y1, x2, y2, &tempPos)) < closest)
04176     {
04177       if (!foundOne)
04178       {
04179         closest = device->currentReadingBox(x1, y1, x2, y2, &closestPos);
04180       }
04181       else
04182       {
04183         closest = tempDist;
04184         closestPos = tempPos;
04185       }
04186       foundOne = true;
04187     }
04188     device->unlockDevice();
04189   }
04190   if (!foundOne)
04191     return -1;
04192   if (readingPos != NULL)
04193     *readingPos = closestPos;
04194   return closest;
04195 }
04196 
04213 double ArRobot::checkRangeDevicesCumulativeBox(double x1, double y1,
04214                                                      double x2, double y2,
04215                                                      ArPose *readingPos) const
04216 {
04217 
04218   double closest, tempDist;
04219   ArPose closestPos, tempPos;
04220   std::list<ArRangeDevice *>::const_iterator it;
04221   ArRangeDevice *device;
04222   bool foundOne = false;
04223 
04224   for (it = myRangeDeviceList.begin(); it != myRangeDeviceList.end(); ++it)
04225   {
04226     device = (*it);
04227     device->lockDevice();
04228     if (!foundOne || 
04229         (tempDist = device->cumulativeReadingBox(x1, y1, x2, y2, &tempPos)) < closest)
04230     {
04231       if (!foundOne)
04232       {
04233         closest = device->cumulativeReadingBox(x1, y1, x2, y2, &closestPos);
04234       }
04235       else
04236       {
04237         closest = tempDist;
04238         closestPos = tempPos;
04239       }
04240       foundOne = true;
04241     }
04242     device->unlockDevice();
04243   }
04244   if (!foundOne)
04245     return -1;
04246   if (readingPos != NULL)
04247     *readingPos = closestPos;
04248   return closest;
04249 }
04250 
04255 void ArRobot::moveTo(ArPose pose, bool doCumulative)
04256 {
04257   std::list<ArRangeDevice *>::iterator it;
04258   ArSensorReading *son;
04259   int i;
04260 
04261   // we need to get this one now because changing the encoder
04262   // transform and global pose will change the local transform
04263   ArTransform localTransform;
04264   localTransform = getToLocalTransform();
04265 
04266   myEncoderTransform.setTransform(myEncoderPose, pose);
04267   myGlobalPose = myEncoderTransform.doTransform(myEncoderPose);
04268 
04269   for (it = myRangeDeviceList.begin(); it != myRangeDeviceList.end(); it++)
04270   {
04271     (*it)->lockDevice();
04272     (*it)->applyTransform(localTransform, doCumulative);
04273     (*it)->applyTransform(getToGlobalTransform(), doCumulative);
04274     (*it)->unlockDevice();
04275   }
04276 
04277   for (i = 0; i < getNumSonar(); i++)
04278   {
04279     son = getSonarReading(i);
04280     if (son != NULL)
04281     {
04282       son->applyTransform(localTransform);
04283       son->applyTransform(getToGlobalTransform());
04284     }
04285   }
04286 
04287   //ArLog::log(ArLog::Normal, "Robot moved to %.0f %.0f %.1f", getX(), getY(), getTh());
04288 }
04289 
04295 void ArRobot::moveTo(ArPose poseTo, ArPose poseFrom,
04296                               bool doCumulative)
04297 {
04298   std::list<ArRangeDevice *>::iterator it;
04299   ArSensorReading *son;
04300   int i;
04301 
04302   ArPose result = myEncoderTransform.doInvTransform(poseFrom);
04303 
04304   // we need to get this one now because changing the encoder
04305   // transform and global pose will change the local transform
04306   ArTransform localTransform;
04307   localTransform = getToLocalTransform();
04308 
04309   myEncoderTransform.setTransform(result, poseTo);
04310   myGlobalPose = myEncoderTransform.doTransform(myEncoderPose);
04311 
04312   for (it = myRangeDeviceList.begin(); it != myRangeDeviceList.end(); it++)
04313   {
04314     (*it)->lockDevice();
04315     (*it)->applyTransform(localTransform, doCumulative);
04316     (*it)->applyTransform(getToGlobalTransform(), doCumulative);
04317     (*it)->unlockDevice();
04318   }
04319 
04320   for (i = 0; i < getNumSonar(); i++)
04321   {
04322     son = getSonarReading(i);
04323     if (son != NULL)
04324     {
04325       son->applyTransform(localTransform);
04326       son->applyTransform(getToGlobalTransform());
04327     }
04328   }
04329 
04330   //ArLog::log(ArLog::Normal, "Robot moved to %.0f %.0f %.1f", getX(), getY(), getTh());
04331 }
04332 
04337 void ArRobot::setEncoderTransform(ArPose deadReconPos, 
04338                                     ArPose globalPos)
04339 {
04340   myEncoderTransform.setTransform(deadReconPos, globalPos);
04341   myGlobalPose = myEncoderTransform.doTransform(myEncoderPose);
04342 }
04343 
04347 void ArRobot::setEncoderTransform(ArPose transformPos)
04348 {
04349   myEncoderTransform.setTransform(transformPos);
04350   myGlobalPose = myEncoderTransform.doTransform(myEncoderPose);
04351 }
04352 
04356 ArTransform ArRobot::getEncoderTransform(void) const
04357 {
04358   return myEncoderTransform;
04359 }
04360 
04364 void ArRobot::setDeadReconPose(ArPose pose)
04365 {
04366   myEncoderPose.setPose(pose);
04367   myEncoderTransform.setTransform(myEncoderPose, myGlobalPose);
04368   myGlobalPose = myEncoderTransform.doTransform(myEncoderPose);
04369 }
04370 
04371 
04376 ArTransform ArRobot::getToGlobalTransform(void) const
04377 {
04378   ArTransform trans;
04379   ArPose origin(0, 0, 0);
04380   ArPose pose = getPose();
04381 
04382   trans.setTransform(origin, pose);
04383   return trans;
04384 }
04385 
04390 ArTransform ArRobot::getToLocalTransform(void) const
04391 {
04392   ArTransform trans;
04393   ArPose origin(0, 0, 0);
04394   ArPose pose = getPose();
04395 
04396   trans.setTransform(pose, origin);
04397   return trans;
04398 }
04399 
04407 void ArRobot::applyTransform(ArTransform trans, bool doCumulative)
04408 {
04409   std::list<ArRangeDevice *>::iterator it;
04410   ArSensorReading *son;
04411   int i;
04412   
04413   for (it = myRangeDeviceList.begin(); it != myRangeDeviceList.end(); it++)
04414   {
04415       (*it)->lockDevice();
04416       (*it)->applyTransform(trans, doCumulative);
04417       (*it)->unlockDevice();
04418   }
04419 
04420   for (i = 0; i < getNumSonar(); i++)
04421   {
04422     son = getSonarReading(i);
04423     if (son != NULL)
04424       son->applyTransform(trans);
04425   }
04426 }
04427 
04428 const char *ArRobot::getName(void) const
04429 {
04430   return myName.c_str();
04431 }
04432 
04433 void ArRobot::setName(const char * name)
04434 {
04435         std::list<ArRobot *> *robotList;
04436     std::list<ArRobot *>::iterator it;
04437     int i;
04438     char buf[1024];
04439  
04440  if (name != NULL)
04441   {
04442     myName = name;
04443   }
04444   else
04445   {
04446 
04447     
04448 
04449     robotList = Aria::getRobotList();
04450     for (i = 1, it = robotList->begin(); it != robotList->end(); it++, i++)
04451     {
04452       if (this == (*it))
04453       {
04454             if (i == 1)
04455                         myName = "robot";
04456                 else
04457                 {
04458                         sprintf(buf, "robot%d", i);
04459                         myName = buf;
04460                 }
04461             return;
04462       }
04463     }
04464     sprintf(buf, "robot%d", robotList->size());
04465     myName = buf;
04466    }
04467 }
04468 
04479 void ArRobot::setEncoderCorrectionCallback(
04480         ArRetFunctor1<double, ArPoseWithTime> *functor)
04481 {
04482   myEncoderCorrectionCB = functor;
04483 }
04490 ArRetFunctor1<double, ArPoseWithTime> * 
04491 ArRobot::getEncoderCorrectionCallback(void) const
04492 {
04493   return myEncoderCorrectionCB;
04494 }
04495 
04506 void ArRobot::setDirectMotionPrecedenceTime(int mSec)
04507 {
04508   if (mSec < 0) 
04509     myDirectPrecedenceTime = 0;
04510   else
04511     myDirectPrecedenceTime = mSec;
04512 }
04513 
04523 unsigned int ArRobot::getDirectMotionPrecedenceTime(void) const
04524 {
04525   return myDirectPrecedenceTime;
04526 }
04527 
04528 
04535 void ArRobot::clearDirectMotion(void)
04536 {
04537   myTransType = TRANS_NONE;
04538   myLastTransType = TRANS_NONE;
04539   myRotType = ROT_NONE;
04540   myLastRotType = ROT_NONE;
04541   myLastActionTransVal = 0;
04542   myLastActionRotStopped = true;
04543   myLastActionRotHeading = false;
04544 }
04545 
04553 void ArRobot::stopStateReflection(void)
04554 {
04555   myTransType = TRANS_IGNORE;
04556   myLastTransType = TRANS_IGNORE;
04557   myRotType = ROT_IGNORE;
04558   myLastRotType = ROT_IGNORE;
04559 }
04560 
04565 bool ArRobot::isDirectMotion(void) const
04566 {
04567   if (myTransType ==  TRANS_NONE && myLastTransType == TRANS_NONE &&
04568       myRotType == ROT_NONE && myLastRotType == ROT_NONE)
04569     return false;
04570   else
04571     return true;
04572 }
04573 
04574 
04578 void ArRobot::enableMotors()
04579 {
04580   comInt(ArCommands::ENABLE, 1);
04581 }
04582 
04586 void ArRobot::disableMotors()
04587 {
04588   comInt(ArCommands::ENABLE, 0);
04589 }
04590 
04591 
04600 void ArRobot::setStateReflectionRefreshTime(int mSec)
04601 {
04602   if (mSec < 0)
04603     myStateReflectionRefreshTime = 0;
04604   else
04605     myStateReflectionRefreshTime = mSec;
04606 }
04607 
04615 int ArRobot::getStateReflectionRefreshTime(void) const
04616 {
04617   return myStateReflectionRefreshTime;
04618 }
04619 
04635 void ArRobot::attachKeyHandler(ArKeyHandler *keyHandler, 
04636                                         bool exitOnEscape, 
04637                                         bool useExitNotShutdown)
04638 {
04639   if (myKeyHandlerCB != NULL)
04640     delete myKeyHandlerCB;
04641   myKeyHandlerCB = new ArFunctorC<ArKeyHandler>(keyHandler, 
04642                                             &ArKeyHandler::checkKeys);
04643   addSensorInterpTask("Key Handler", 50, myKeyHandlerCB);
04644 
04645   myKeyHandler = keyHandler;
04646   myKeyHandlerUseExitNotShutdown = useExitNotShutdown;
04647   if (exitOnEscape)
04648     keyHandler->addKeyHandler(ArKeyHandler::ESCAPE, &myKeyHandlerExitCB);
04649 }
04650 
04651 ArKeyHandler *ArRobot::getKeyHandler(void) const
04652 {
04653   return myKeyHandler;
04654 }
04655 
04656 void ArRobot::keyHandlerExit(void)
04657 {
04658   ArLog::log(ArLog::Terse, "Escape was pressed, program is exiting.");
04659   // if we're using exit not the keyhandler then call Aria::exit
04660   // instead of shutdown, this call never returns
04661   if (myKeyHandlerUseExitNotShutdown)
04662     Aria::exit();
04663   stopRunning();
04664   unlock();
04665   Aria::shutdown();
04666 }
04667 
04668 void ArRobot::setPacketsReceivedTracking(bool packetsReceivedTracking)
04669 {
04670   myPacketsReceivedTracking = packetsReceivedTracking;
04671   myPacketsReceivedTrackingCount = 0; 
04672   myPacketsReceivedTrackingStarted.setToNow(); 
04673 }
04674 
04675 void ArRobot::ariaExitCallback(void)
04676 {
04677   mySyncLoop.stopRunIfNotConnected(false);
04678   disconnect();
04679 }
04680 
04686 ArRobot::ChargeState ArRobot::getChargeState(void) const
04687 {
04688   return myChargeState;
04689 }

Generated on Wed Oct 19 12:56:36 2005 for Aria by  doxygen 1.4.0