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

ArSick.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 "ArSick.h"
00030 #include "ArRobot.h"
00031 #include "ArSerialConnection.h"
00032 #include "ariaInternal.h"
00033 #include <time.h>
00034 
00035 ArSick::ArSick(size_t currentBufferSize, size_t cumulativeBufferSize, 
00036                         const char *name, bool addAriaExitCB) :
00037   ArRangeDeviceThreaded(currentBufferSize, cumulativeBufferSize, name, 32500),
00038   myRobotConnectCB(this, &ArSick::robotConnectCallback),
00039   mySimPacketHandler(this, &ArSick::simPacketHandler),
00040   mySensorInterpCB(this, &ArSick::sensorInterpCallback),
00041   mySickPacketReceiver(0, true),
00042   myAriaExitCB(this, &ArSick::disconnect, true)
00043 {
00044   myAriaExitCB.setName("ArSickExit");
00045   if (addAriaExitCB)
00046     Aria::addExitCallback(&myAriaExitCB, 10);
00047   configure();
00048   setSensorPosition(0, 0, 0);
00049   myAssembleReadings = new std::list<ArSensorReading *>;
00050   myCurrentReadings = new std::list<ArSensorReading *>;
00051   myRawReadings = myCurrentReadings;
00052   myIter = myAssembleReadings->begin();
00053   myConn = NULL;
00054   myRobot = NULL;
00055   myStartConnect = false;
00056   myRunningOnRobot = false;
00057   switchState(STATE_NONE);
00058   myProcessImmediately = false;
00059   myInterpolation = true;
00060   myTimeoutTime = 8;
00061   myRealConfigured = false;
00062 
00063   // default filter params
00064   setMinRange(125);
00065   setFilterNearDist(50);
00066   setFilterCumulativeMaxDist(6000);
00067   setFilterCumulativeInsertMaxDist(3000);
00068   setFilterCumulativeNearDist(200);
00069   setFilterCumulativeCleanDist(75);
00070   setFilterCumulativeMaxAge(30);
00071   setFilterCleanCumulativeInterval(1000);
00072 
00073   myLastCleanedCumulative.setToNow();
00074 
00075   setCurrentDrawingData(new ArDrawingData("polyDots", 
00076                                                                                   ArColor(0, 0, 255), 
00077                                                                                   80,  // mm diameter of dots
00078                                                                                   75), // layer above sonar 
00079                                                 true);
00080 
00081   setCumulativeDrawingData(new ArDrawingData("polyDots", 
00082                                                                                          ArColor(125, 125, 125), 
00083                                                                                          100, // mm diameter of dots
00084                                                                                          60), // layer below current range devices  
00085                                                    true);
00086 }
00087 
00088 ArSick::~ArSick()
00089 {
00090   if (myRobot != NULL)
00091   {
00092     myRobot->remRangeDevice(this);
00093     myRobot->remPacketHandler(&mySimPacketHandler);
00094     myRobot->remSensorInterpTask(&mySensorInterpCB);
00095     myRobot->addConnectCB(&myRobotConnectCB, ArListPos::FIRST);
00096   }
00097   lockDevice();
00098   if (isConnected())
00099   {
00100     disconnect();
00101   }
00102   unlockDevice();
00103 }
00104 
00105 void ArSick::robotConnectCallback(void)
00106 {
00107   const ArRobotParams *params;
00108   if (myRealConfigured || !myRobot->isConnected()) 
00109     return;
00110   params = myRobot->getRobotParams();
00111   myLaserFlipped = params->getLaserFlipped();
00112   myPowerControl = params->getLaserPowerControlled();
00113   
00114   if (myDegrees == DEGREES180)
00115     myOffsetAmount = 90;
00116   else if (myDegrees == DEGREES100)
00117     myOffsetAmount = 50;
00118   else
00119   {
00120     myOffsetAmount = 0;
00121     ArLog::log(ArLog::Terse,"ArSick::robotConnectCallback: bad degrees configured.\n");
00122   }
00123   
00124 
00125   if (myLaserFlipped)
00126     myOffsetAmount *= -1;
00127 
00128   if (myIncrement == INCREMENT_ONE)
00129     myIncrementAmount = 1.0;
00130   else if (myIncrement == INCREMENT_HALF)
00131     myIncrementAmount = 0.5;
00132   else
00133   {
00134     myIncrementAmount = 0;
00135     ArLog::log(ArLog::Terse,"ArSick::robotConnectCallback: bad increment configured.\n");
00136   }
00137   if (myLaserFlipped)
00138     myIncrementAmount *= -1;
00139 
00140   clearIgnoreReadings();
00141   ArArgumentBuilder builder;
00142   builder.add(myRobot->getRobotParams()->getLaserIgnore());
00143   size_t i;
00144   for (i = 0; i < builder.getArgc(); i++)
00145   {
00146     if (!builder.isArgDouble(i))
00147     {
00148       ArLog::log(ArLog::Normal, "ArRobotConfig::setIgnoreReadings: argument is not a double");
00149     }
00150     addIgnoreReading(builder.getArgDouble(i));
00151   }
00152 
00153   setSensorPosition(params->getLaserX(), params->getLaserY(), params->getLaserTh());
00154 }
00155 
00156 bool ArSick::isUsingSim(void)
00157 {
00158   return myUseSim;
00159 }
00160 
00161 bool ArSick::isControllingPower(void)
00162 {
00163   return myPowerControl;
00164 }
00165 
00166 bool ArSick::isLaserFlipped(void)
00167 {
00168   return myLaserFlipped;
00169 }
00170 
00171 ArSick::Degrees ArSick::getDegrees(void)
00172 {
00173   return myDegrees;
00174 }
00175 
00176 ArSick::Increment ArSick::getIncrement(void)
00177 {
00178   return myIncrement;
00179 }
00180 
00181 
00182 void ArSick::setIsUsingSim(bool usingSim)
00183 {
00184   myUseSim = usingSim;
00185 }
00186 
00187 void ArSick::setIsControllingPower(bool controlPower)
00188 {
00189   myPowerControl = controlPower;
00190 }
00191 
00192 void ArSick::setIsLaserFlipped(bool laserFlipped)
00193 {
00194   myLaserFlipped = laserFlipped;
00195 }
00196 
00197 
00198 void ArSick::setSensorPosition(double x, double y, double th)
00199 {
00200   mySensorPose.setPose(x, y, th);
00201 }
00202 
00203 void ArSick::setSensorPosition(ArPose pose)
00204 {
00205   mySensorPose = pose;
00206 }
00207 
00208 ArPose ArSick::getSensorPosition(void)
00209 {
00210   return mySensorPose;
00211 }
00212 
00213 double ArSick::getSensorPositionX(void)
00214 {
00215   return mySensorPose.getX();
00216 }
00217 
00218 double ArSick::getSensorPositionY(void)
00219 {
00220   return mySensorPose.getY();
00221 }
00222 
00223 double ArSick::getSensorPositionTh(void)
00224 {
00225   return mySensorPose.getTh();
00226 }
00227 
00228 
00229 void ArSick::setDeviceConnection(ArDeviceConnection *conn)
00230 {
00231   myConnLock.lock();
00232   myConn = conn; 
00233   mySickPacketReceiver.setDeviceConnection(conn); 
00234   myConnLock.unlock();
00235 }
00236 
00237 ArDeviceConnection *ArSick::getDeviceConnection(void)
00238 {
00239   return myConn;
00240 }
00241 
00251 void ArSick::setConnectionTimeoutTime(int mSecs)
00252 {
00253   if (mSecs > 0)
00254     myTimeoutTime = mSecs;
00255   else
00256     myTimeoutTime = 0;
00257 }
00258 
00264 int ArSick::getConnectionTimeoutTime(void)
00265 {
00266   return myTimeoutTime;
00267 }
00268 
00269 ArTime ArSick::getLastReadingTime(void)
00270 {
00271   return myLastReading;
00272 }
00273 
00274 void ArSick::setRobot(ArRobot *robot)
00275 {
00276   myRobot = robot;
00277   if (myRobot != NULL)
00278   {
00279     myRobot->addPacketHandler(&mySimPacketHandler, ArListPos::LAST);
00280     myRobot->addSensorInterpTask("sick", 90, &mySensorInterpCB);
00281     myRobot->addConnectCB(&myRobotConnectCB, ArListPos::FIRST);
00282     if (myRobot->isConnected())
00283       robotConnectCallback();
00284   }
00285   ArRangeDevice::setRobot(robot);
00286 }
00287 
00292 void ArSick::configure(bool useSim, bool powerControl,
00293                                 bool laserFlipped, BaudRate baud,
00294                                 Degrees deg, Increment incr)
00295 {
00296 
00297   myUseSim = useSim;
00298   myPowerControl = powerControl;
00299   myLaserFlipped = laserFlipped;
00300   myBaud = baud;
00301   myDegrees = deg;
00302   myIncrement = incr;
00303 
00304   if (myDegrees == DEGREES180)
00305     myOffsetAmount = 90;
00306   else if (myDegrees == DEGREES100)
00307     myOffsetAmount = 50;
00308   else
00309   {
00310     myOffsetAmount = 0;
00311     ArLog::log(ArLog::Terse,"ArSick::configure: bad degrees configured.\n");
00312   }
00313   
00314   if (myLaserFlipped)
00315     myOffsetAmount *= -1;
00316 
00317   if (myIncrement == INCREMENT_ONE)
00318     myIncrementAmount = 1.0;
00319   else if (myIncrement == INCREMENT_HALF)
00320     myIncrementAmount = 0.5;
00321   else
00322   {
00323     myIncrementAmount = 0;
00324     ArLog::log(ArLog::Terse,"ArSick::configure: bad increment configured.\n");
00325   }
00326 
00327   if (myLaserFlipped)
00328     myIncrementAmount *= -1;
00329 
00330   myRealConfigured = true;
00331 }
00332 
00337 void ArSick::configureShort(bool useSim, BaudRate baud,
00338                                 Degrees deg, Increment incr)
00339 {
00340 
00341   myUseSim = useSim;
00342   myPowerControl = true;
00343   myLaserFlipped = false;
00344   myBaud = baud;
00345   myDegrees = deg;
00346   myIncrement = incr;
00347 
00348   if (myDegrees == DEGREES180)
00349     myOffsetAmount = 90;
00350   else if (myDegrees == DEGREES100)
00351     myOffsetAmount = 50;
00352   else
00353   {
00354     myOffsetAmount = 0;
00355     ArLog::log(ArLog::Terse,"ArSick::configureShort: bad degrees configured.\n");
00356   }
00357   
00358   if (myLaserFlipped)
00359     myOffsetAmount *= -1;
00360 
00361   if (myIncrement == INCREMENT_ONE)
00362     myIncrementAmount = 1.0;
00363   else if (myIncrement == INCREMENT_HALF)
00364     myIncrementAmount = 0.5;
00365   else
00366   {
00367     myIncrementAmount = 0;
00368     ArLog::log(ArLog::Terse,"ArSick::configureShort: bad increment configured.\n");
00369   }
00370   if (myLaserFlipped)
00371     myIncrementAmount *= -1;
00372 
00373   myRealConfigured = false;
00374   // if we're connected, just have this set things
00375   if (myRobot != NULL && myRobot->isConnected())
00376     robotConnectCallback();
00377 }
00378 
00379 bool ArSick::simPacketHandler(ArRobotPacket *packet)
00380 {
00381   std::list<ArFunctor *>::iterator it;
00382 
00383   unsigned int totalNumReadings;
00384   unsigned int readingNumber;
00385   double atDeg;
00386   unsigned int i;
00387   ArSensorReading *reading;
00388   std::list<ArSensorReading *>::iterator tempIt;
00389   unsigned int newReadings;
00390   int range;
00391   ArPose encoderPose;
00392   std::list<double>::iterator ignoreIt;  
00393   bool ignore;
00394   
00395   if (packet->getID() != 0x60)
00396     return false;
00397 
00398   // if we got here, its the right type of packet
00399 
00400   //printf("Got in a packet from the simulator\n");
00401   lockDevice();
00402   //printf("1\n");
00403   if (!myUseSim)
00404   {
00405     ArLog::log(ArLog::Terse, "ArSick: Got a packet from the simulator with laser information, but the laser is not being simulated, major trouble.");
00406     unlockDevice();
00407     return true;
00408   }
00409   // ignore the positional information
00410   packet->bufToByte2();
00411   packet->bufToByte2();
00412   packet->bufToByte2();
00413   totalNumReadings = packet->bufToByte2(); // total for this reading
00414   readingNumber = packet->bufToByte2(); // which one we're on in this packet
00415   newReadings = packet->bufToUByte(); // how many are in this packet
00416   if (readingNumber == 0)
00417   {
00418     mySimPacketStart = myRobot->getPose();
00419     mySimPacketTrans = myRobot->getToGlobalTransform();
00420     mySimPacketEncoderTrans = myRobot->getEncoderTransform();
00421     mySimPacketCounter = myRobot->getCounter();
00422   }
00423   //printf("On reading number %d out of %d, new %d\n", readingNumber, totalNumReadings, newReadings);
00424   // if we have too many readings in our list of raw readings, pop the extras
00425   while (myAssembleReadings->size() > totalNumReadings)
00426   {
00427     ArLog::log(ArLog::Verbose, "ArSick::simPacketHandler, too many readings, popping one.\n");
00428     tempIt = myAssembleReadings->begin();
00429     if (tempIt != myAssembleReadings->end())
00430       delete (*tempIt);
00431     myAssembleReadings->pop_front();
00432   }
00433   
00434   // If we don't have any sensor readings created at all, make 'em all now
00435   if (myAssembleReadings->size() == 0)
00436     for (i = 0; i < totalNumReadings; i++)
00437       myAssembleReadings->push_back(new ArSensorReading);
00438   
00439   // Okay, we know where we're at, so get an iterator to the right spot, or 
00440   // make sure the one we keep around is in the right spot... if neither of
00441   // these trigger, then the iter should be in the right spot
00442   if ((readingNumber != myWhichReading + 1) || 
00443       totalNumReadings != myTotalNumReadings)
00444   {
00445     //printf("2\n");
00446     myWhichReading = readingNumber;
00447     myTotalNumReadings = totalNumReadings;
00448     for (i = 0, myIter = myAssembleReadings->begin(); i < readingNumber; i++)
00449     {
00450       tempIt = myIter;
00451       tempIt++;
00452       if (tempIt == myAssembleReadings->end() && (i + 1 != myTotalNumReadings))
00453         myAssembleReadings->push_back(new ArSensorReading);
00454       myIter++;
00455     }
00456   }
00457   else
00458   {
00459     //printf("3\n");
00460     myWhichReading = readingNumber;
00461   }
00462 
00463   atDeg = (mySensorPose.getTh() - myOffsetAmount + 
00464            readingNumber * myIncrementAmount);
00465   //printf("4\n");
00466   encoderPose = mySimPacketEncoderTrans.doInvTransform(mySimPacketStart);
00467   // while we have in the readings and have stuff left we can read 
00468   for (i = 0; 
00469        //        (myWhichReading < myTotalNumReadings && 
00470        //         packet->getReadLength() < packet->getLength() - 4);
00471        i < newReadings;
00472        i++, myWhichReading++, atDeg += myIncrementAmount)
00473   {
00474     reading = (*myIter);
00475     range = packet->bufToUByte2();
00476     ignore = false;
00477     for (ignoreIt = myIgnoreReadings.begin(); 
00478          ignoreIt != myIgnoreReadings.end();
00479          ignoreIt++)
00480     {
00481       //if (atDeg == 0)
00482       //printf("Ignoring %.0f\n", (*ignoreIt));
00483       if (ArMath::fabs(ArMath::subAngle(atDeg, *(ignoreIt))) < 1.0)
00484       {
00485         //printf("Ignoring %.0f\n", (*ignoreIt));
00486         ignore = true;
00487         break;
00488       }
00489     }
00490     if (myMaxRange != 0 && range < (int)myMinRange)
00491       ignore = true;
00492     if (myMaxRange != 0 && range > (int)myMaxRange)
00493       ignore = true;
00494     
00495     reading->resetSensorPosition(ArMath::roundInt(mySensorPose.getX()),
00496                                  ArMath::roundInt(mySensorPose.getY()),
00497                                  atDeg);
00498     //      printf("dist %d\n", dist);
00499     reading->newData(range, mySimPacketStart, 
00500                      encoderPose,
00501                      mySimPacketTrans,
00502                      mySimPacketCounter, packet->getTimeReceived(), ignore);
00503     //addReading(reading->getX(), reading->getY());
00504     tempIt = myIter;
00505     tempIt++;
00506     if (tempIt == myAssembleReadings->end() && 
00507         myWhichReading + 1 != myTotalNumReadings)
00508     {
00509       myAssembleReadings->push_back(new ArSensorReading);
00510     }
00511     myIter++;
00512   }
00513 
00514   // check if the sensor set is complete
00515   //printf("%d %d %d\n", newReadings, readingNumber, totalNumReadings);
00516   if (newReadings + readingNumber >= totalNumReadings)
00517   {
00518     // set ArRangeDevice buffer
00519     myRawReadings = myAssembleReadings;
00520     // switch internal buffers
00521     myAssembleReadings = myCurrentReadings;
00522     myCurrentReadings = myRawReadings;
00523     // We have in all the readings, now sort 'em and update the current ones
00524     filterReadings();
00525 
00526     if (myTimeLastSickPacket != time(NULL)) 
00527       {
00528         myTimeLastSickPacket = time(NULL);
00529         mySickPacCount = mySickPacCurrentCount;
00530         mySickPacCurrentCount = 0;
00531       }
00532     mySickPacCurrentCount++;
00533     myLastReading.setToNow();
00534     
00535     for (it = myDataCBList.begin(); it != myDataCBList.end(); it++)
00536       (*it)->invoke();
00537   }     
00538   
00539   unlockDevice();
00540   return true;
00541 }
00542 
00555 void ArSick::filterReadings()
00556 {
00557   std::list<ArSensorReading *>::iterator sensIt;
00558   ArSensorReading *sReading;
00559   double x, y;
00560   double squaredDist;
00561   double lastX = 0.0, lastY = 0.0;
00562   unsigned int i;
00563   double squaredNearDist = myFilterNearDist * myFilterNearDist; 
00564   ArTime len;
00565   len.setToNow();
00566 
00567   bool clean;
00568   if (myFilterCleanCumulativeInterval == 0 ||
00569       myLastCleanedCumulative.mSecSince() > myFilterCleanCumulativeInterval)
00570   {
00571     myLastCleanedCumulative.setToNow();
00572     clean = true;
00573   }
00574   else
00575   {
00576     clean = false;
00577   }
00578   
00579   sensIt = myRawReadings->begin();
00580   sReading = (*sensIt);
00581   myCurrentBuffer.setPoseTaken(sReading->getPoseTaken());
00582   myCurrentBuffer.setEncoderPoseTaken(sReading->getEncoderPoseTaken());
00583   //myCurrentBuffer.reset();
00584 
00585   // if we don't have any readings in the buffer yet, fill it up
00586   if (myCurrentBuffer.getBuffer()->size() == 0)
00587     for (i = 0; i < myRawReadings->size(); i++)
00588       myCurrentBuffer.getBuffer()->push_back(new ArPoseWithTime);
00589 
00590   i = 0;
00591   // walk the buffer of all the readings and see if we want to add them
00592   for (myCurrentBuffer.beginRedoBuffer();         
00593        sensIt != myRawReadings->end(); 
00594        ++sensIt)
00595   {
00596     sReading = (*sensIt);
00597     /*
00598     if (sReading->getIgnoreThisReading())
00599        printf("Ignoring %.0f %d\n", sReading->getSensorTh(),sReading->getRange());
00600     */
00601     // see if the reading is in the valid range
00602     if (!sReading->getIgnoreThisReading())
00603     {
00604       // get our coords
00605       x = sReading->getX();
00606       y = sReading->getY();
00607 
00608       
00609       // see if we're checking on the filter near dist... if we are
00610       // and the reading is a good one we'll check the cumulative
00611       // buffer
00612       if (squaredNearDist > 0.0000001)
00613       {
00614         // see where the last reading was
00615         squaredDist = (x-lastX)*(x-lastX) + (y-lastY)*(y-lastY);
00616         // see if the reading is far enough from the last reading
00617         if (squaredDist > squaredNearDist)              // moved enough
00618         {
00619           lastX = x;
00620           lastY = y;
00621           // since it was a good reading, see if we should toss it in
00622           // the cumulative buffer... 
00623           filterAddAndCleanCumulative(x, y, clean);
00624 
00625           /* we don't do this part anymore since it wound up leaving
00626           // too many things not really tehre... if its outside of our
00627           // sensor angle to use to filter then don't let this one
00628           // clean  (ArMath::fabs(sReading->getSensorTh()) > 50)
00629           // filterAddAndCleanCumulative(x, y, false); else*/
00630         }
00631         // it wasn't far enough, skip this one and go to the next one
00632         else
00633         {
00634           continue;             
00635         }
00636       }
00637       // we weren't filtering the readings, but see if it goes in the
00638       // cumulative buffer anyways
00639       else
00640       {
00641         filterAddAndCleanCumulative(x, y, clean);
00642       }
00643       // now drop the reading into the current buffer
00644       myCurrentBuffer.redoReading(x, y);
00645       i++;
00646     }
00647   }
00648   myCurrentBuffer.endRedoBuffer();
00649   /*  Put this in to see how long the cumulative filtering is taking  
00650   if (clean)
00651     printf("### %ld %d\n", len.mSecSince(), myCumulativeBuffer.getBuffer()->size());
00652     */
00653   
00654 }
00655 
00656 void ArSick::filterAddAndCleanCumulative(double x, double y, bool clean)
00657 {
00658   if (myCumulativeBuffer.getSize() == 0)
00659     return;
00660 
00661 
00662   std::list<ArPoseWithTime *>::iterator cit;
00663   bool addReading = true;
00664   double squaredDist;
00665 
00666   ArLineSegment line;
00667   double xTaken = myCurrentBuffer.getPoseTaken().getX();
00668   double yTaken = myCurrentBuffer.getPoseTaken().getY();
00669   ArPose intersection;
00670   ArPoseWithTime reading(x, y);
00671 
00672   // make sure we really want to clean
00673   if (clean && myFilterSquaredCumulativeCleanDist < 1)
00674     clean = false;
00675 
00676   squaredDist = ArMath::squaredDistanceBetween(x, y, xTaken, yTaken);
00677   // if we're not cleaning and its further than we're keeping track of
00678   // readings ignore it
00679   if (!clean && 
00680       myFilterSquaredCumulativeInsertMaxDist > 1 && 
00681       squaredDist > myFilterSquaredCumulativeInsertMaxDist)
00682     return;
00683   
00684   // if we're cleaning we start our sweep
00685   if (clean)
00686     myCumulativeBuffer.beginInvalidationSweep();
00687   // run through all the readings
00688   for (cit = getCumulativeBuffer()->begin(); 
00689        cit != getCumulativeBuffer()->end(); 
00690        ++cit)
00691   {
00692     // if its closer to a reading than the filter near dist, just return
00693     if (myFilterSquaredCumulativeNearDist < .0000001 ||
00694         (ArMath::squaredDistanceBetween(x, y, (*cit)->getX(), (*cit)->getY()) <
00695          myFilterSquaredCumulativeNearDist))
00696     {
00697       // if we're not cleaning it and its too close just return,
00698       // otherwise keep going (to clear out invalid readings)
00699       if (!clean)
00700         return;
00701       addReading = false;
00702     }
00703     // see if this reading invalidates some other readings by coming too close
00704     if (clean)
00705     {
00706       // set up our line
00707       line.newEndPoints(x, y, xTaken, yTaken);
00708       // see if the cumulative buffer reading perpindicular intersects
00709       // this line segment, and then see if its too close if it does
00710       if (line.getPerpPoint((*cit), &intersection) &&
00711           (intersection.squaredFindDistanceTo(*(*cit)) < 
00712                                        myFilterSquaredCumulativeCleanDist) &&
00713           (intersection.squaredFindDistanceTo(reading) > 50 * 50))
00714       {
00715         //printf("Found one too close to the line\n");
00716         myCumulativeBuffer.invalidateReading(cit);
00717       }
00718     }
00719   }
00720   // if we're cleaning finish the sweep
00721   if (clean)
00722     myCumulativeBuffer.endInvalidationSweep();
00723   // toss the reading in
00724   if (addReading)
00725     myCumulativeBuffer.addReading(x, y);
00726 
00727 }
00728 
00729 void ArSick::switchState(State state)
00730 {
00731   myStateMutex.lock();
00732   myState = state;
00733   myStateStart.setToNow();
00734   myStateMutex.unlock();
00735 }
00736 
00740 int ArSick::internalConnectHandler(void)
00741 {
00742   ArSickPacket *packet;
00743   ArSerialConnection *conn;
00744   int value;
00745 
00746   switch (myState)
00747   {
00748   case STATE_INIT:
00749     if (myConn->getStatus() != ArDeviceConnection::STATUS_OPEN)
00750     {
00751       if ((conn = dynamic_cast<ArSerialConnection *>(myConn)) != NULL)
00752       {
00753         conn->setBaud(9600);
00754       }
00755       if (!myConn->openSimple())
00756       {
00757         ArLog::log(ArLog::Terse,
00758                    "ArSick: Failed to connect to laser, could not open port.");
00759         switchState(STATE_NONE);
00760         failedConnect();
00761         return 2;
00762       }
00763     }
00764     if (!myPowerControl)
00765     {
00766       /*
00767       myPacket.empty();
00768       myPacket.uByteToBuf(0x20);
00769       myPacket.uByteToBuf(0x25);
00770       myPacket.finalizePacket();
00771       myConn->write(myPacket.getBuf(), myPacket.getLength());
00772       */
00773       switchState(STATE_CHANGE_BAUD);
00774       return internalConnectHandler();
00775     }
00776     ArLog::log(ArLog::Terse, "ArSick: waiting for laser to power on.");
00777     myPacket.empty();
00778     myPacket.uByteToBuf(0x10);
00779     myPacket.finalizePacket();
00780     if (myConn->write(myPacket.getBuf(), myPacket.getLength()))
00781     {
00782       switchState(STATE_WAIT_FOR_POWER_ON);
00783       return 0;
00784     }
00785     else
00786     {
00787       ArLog::log(ArLog::Terse,
00788                  "ArSick: Failed to connect to laser, could not send init.");
00789       switchState(STATE_NONE);
00790       failedConnect();
00791       return 2;
00792     }
00793     break;
00794   case STATE_WAIT_FOR_POWER_ON:
00795     while ((packet = mySickPacketReceiver.receivePacket()) != NULL)
00796     {
00797       if (packet->getID() == 0x90)
00798       {
00799         switchState(STATE_CHANGE_BAUD);
00800         return 0;
00801       }
00802     }
00803     if (myStateStart.secSince() > 65)
00804     {
00805       ArLog::log(ArLog::Terse,
00806                  "ArSick: Failed to connect to laser, no poweron received.");
00807       switchState(STATE_NONE);
00808       failedConnect();
00809       return 2;
00810     }
00811     break;
00812   case STATE_CHANGE_BAUD:
00813     myPacket.empty();
00814     myPacket.byteToBuf(0x20);
00815     if (myBaud == BAUD9600)
00816       myPacket.byteToBuf(0x42);
00817     else if (myBaud == BAUD19200)
00818       myPacket.byteToBuf(0x41);
00819     else if (myBaud == BAUD38400)
00820       myPacket.byteToBuf(0x40);
00821     myPacket.finalizePacket();
00822     if (myConn->write(myPacket.getBuf(), myPacket.getLength()))
00823     {
00824       ArUtil::sleep(20);
00825       if ((conn = dynamic_cast<ArSerialConnection *>(myConn)))
00826       {
00827         if (myBaud == BAUD9600)
00828           conn->setBaud(9600);
00829         else if (myBaud == BAUD19200)
00830           conn->setBaud(19200);
00831         else if (myBaud == BAUD38400)
00832           conn->setBaud(38400);
00833       }
00834       switchState(STATE_CONFIGURE);
00835       return 0;
00836     }
00837     else
00838     {
00839       ArLog::log(ArLog::Terse,
00840                  "ArSick: Failed to connect to laser, could not send baud command.");
00841       switchState(STATE_NONE);
00842       failedConnect();
00843       return 2;
00844     }
00845     break;
00846   case STATE_CONFIGURE:
00847     // wait at least a 100 ms for the baud to change
00848     if (myStateStart.mSecSince() < 300)
00849       return 0;
00850     myPacket.empty();
00851     myPacket.byteToBuf(0x3b);
00852     myPacket.uByte2ToBuf(abs(ArMath::roundInt(myOffsetAmount * 2)));
00853     myPacket.uByte2ToBuf(abs(ArMath::roundInt(myIncrementAmount * 100)));
00854     myPacket.finalizePacket();
00855     if (myConn->write(myPacket.getBuf(), myPacket.getLength()))
00856     {
00857       switchState(STATE_WAIT_FOR_CONFIGURE_ACK);
00858       return 0;
00859     }
00860     else
00861     {
00862       ArLog::log(ArLog::Terse,
00863                  "ArSick: Failed to connect to laser, could not send configure command.");
00864       switchState(STATE_NONE);
00865       failedConnect();
00866       return 2;
00867     }
00868     break;
00869   case STATE_WAIT_FOR_CONFIGURE_ACK:
00870     while ((packet = mySickPacketReceiver.receivePacket()) != NULL)
00871     {
00872       if (packet->getID() == 0xbb)
00873       {
00874         value = packet->bufToByte();
00875         if (value == 0)
00876         {
00877           ArLog::log(ArLog::Terse, 
00878                      "ArSick: Could not configure laser, failed connect.");
00879           switchState(STATE_NONE);
00880           failedConnect();
00881           return 2;
00882         }
00883         else if (value == 1)
00884         {
00885           // here
00886           //switchState(STATE_START_READINGS);
00887           switchState(STATE_INSTALL_MODE);
00888           return 0;
00889         }
00890         else
00891         {
00892           ArLog::log(ArLog::Terse, 
00893                      "ArSick: Could not configure laser, failed connect.");
00894           switchState(STATE_NONE);
00895           failedConnect();
00896           return 2;
00897         }
00898       }
00899       else if (packet->getID() == 0xb0)
00900       {
00901 
00902         ArLog::log(ArLog::Terse, "ArSick: extra data packet while waiting for configure ack");
00903         myPacket.empty();
00904         myPacket.uByteToBuf(0x20);
00905         myPacket.uByteToBuf(0x25);
00906         myPacket.finalizePacket();
00907         if (myConn->write(myPacket.getBuf(), myPacket.getLength()))
00908         {
00909           switchState(STATE_CONFIGURE);
00910           return 0;
00911         }
00912       }
00913       else
00914         ArLog::log(ArLog::Terse, "ArSick: Got a 0x%x\n", packet->getID());
00915     }
00916     if (myStateStart.mSecSince() > 10000)
00917     {
00918       ArLog::log(ArLog::Terse,
00919                  "ArSick: Failed to connect to laser, no configure acknowledgement received.");
00920       switchState(STATE_NONE);
00921       failedConnect();
00922       return 2;
00923     }
00924     break;
00925   case STATE_INSTALL_MODE:
00926     if (myStateStart.mSecSince() < 200)
00927       return 0;
00928     myPacket.empty();
00929     myPacket.byteToBuf(0x20);
00930     myPacket.byteToBuf(0x00);
00931     myPacket.strNToBuf("SICK_LMS", strlen("SICK_LMS"));
00932     myPacket.finalizePacket();
00933     if (myConn->write(myPacket.getBuf(), myPacket.getLength()))
00934     {
00935       switchState(STATE_WAIT_FOR_INSTALL_MODE_ACK);
00936       return 0;
00937     }
00938     else
00939     {
00940       ArLog::log(ArLog::Terse,
00941                  "ArSick: Failed to connect to laser, could not send start command.");
00942       switchState(STATE_NONE);
00943       failedConnect();
00944       return 2;
00945     }
00946     break;
00947   case STATE_WAIT_FOR_INSTALL_MODE_ACK:
00948     while ((packet = mySickPacketReceiver.receivePacket()) != NULL)
00949     {
00950       if (packet->getID() == 0xa0)
00951       {
00952         value = packet->bufToByte();
00953         if (value == 0)
00954         {
00955           //printf("Um, should set mode?\n");
00956           switchState(STATE_SET_MODE);
00957           return 0;
00958         }
00959         else if (value == 1)
00960         {
00961           ArLog::log(ArLog::Terse, 
00962                      "ArSick: Could not start laser, incorrect password.");
00963           switchState(STATE_NONE);
00964           failedConnect();
00965           return 2;
00966         }
00967         else if (value == 2)
00968         {
00969           ArLog::log(ArLog::Terse, 
00970                      "ArSick: Could not start laser, LMI fault.");
00971           switchState(STATE_NONE);
00972           failedConnect();
00973           return 2;
00974         }
00975         else
00976         {
00977           ArLog::log(ArLog::Terse, 
00978                      "ArSick: Could not start laser, unknown problem.");
00979           switchState(STATE_NONE);
00980           failedConnect();
00981           return 2;
00982         }
00983       }
00984       else if (packet->getID() == 0xb0)
00985       {
00986         
00987         ArLog::log(ArLog::Terse, "ArSick: extra data packet\n");
00988         myPacket.empty();
00989         myPacket.uByteToBuf(0x20);
00990         myPacket.uByteToBuf(0x25);
00991         myPacket.finalizePacket();
00992         if (myConn->write(myPacket.getBuf(), myPacket.getLength()))
00993         {
00994           switchState(STATE_INSTALL_MODE);
00995           return 0;
00996         }
00997       }
00998       else
00999         ArLog::log(ArLog::Terse, "ArSick: bad packet 0x%x\n", packet->getID());
01000     }
01001     if (myStateStart.mSecSince() > 10000)
01002     {
01003       ArLog::log(ArLog::Terse,
01004                  "ArSick: Failed to connect to laser, no install mode ack received.");
01005       switchState(STATE_NONE);
01006       return 2;
01007     }
01008     break;
01009   case STATE_SET_MODE:
01010     if (myStateStart.mSecSince() < 200)
01011       return 0;
01012     myPacket.empty();
01013     // type of packet
01014     myPacket.byteToBuf(0x77);
01015     // blanking
01016     myPacket.uByte2ToBuf(0);
01017     // peak threshhold, stop threshold
01018     myPacket.uByte2ToBuf(70);
01019     // the old peak threshhold thats probably broken
01020     // myPacket.uByte2ToBuf(0);
01021     // fog correction
01022     myPacket.uByteToBuf(0);
01023     // measurement Mode (fun one)
01024     myPacket.uByteToBuf(6);
01025     // unit value (fun one)
01026     myPacket.uByteToBuf(1);
01027     // temporary field set
01028     myPacket.uByteToBuf(0);
01029     // fields A & B as subtractive
01030     myPacket.uByteToBuf(0);
01031     // multiple evaluation
01032     myPacket.uByteToBuf(2);
01033     // restart
01034     myPacket.uByteToBuf(2);
01035     // restart time
01036     myPacket.uByteToBuf(0);
01037     // contour A as reference object size
01038     myPacket.uByteToBuf(0);
01039     // contour A positive range of tolerance
01040     myPacket.uByteToBuf(0);
01041     // contour A negative range of tolerance
01042     myPacket.uByteToBuf(0);
01043     // contour A starting angle
01044     myPacket.uByteToBuf(0);
01045     // contour A stopping angle
01046     myPacket.uByteToBuf(0);
01047     // contour B as reference object size
01048     myPacket.uByteToBuf(0);
01049     // contour B positive range of tolerance
01050     myPacket.uByteToBuf(0);
01051     // contour B negative range of tolerance
01052     myPacket.uByteToBuf(0);
01053     // contour B starting angle
01054     myPacket.uByteToBuf(0);
01055     // contour B stopping angle
01056     myPacket.uByteToBuf(0);
01057     // contour C as reference object size
01058     myPacket.uByteToBuf(0);
01059     // contour C positive range of tolerance
01060     myPacket.uByteToBuf(0);
01061     // contour C negative range of tolerance
01062     myPacket.uByteToBuf(0);
01063     // contour C starting angle
01064     myPacket.uByteToBuf(0);
01065     // contour C stopping angle
01066     myPacket.uByteToBuf(0);
01067     // pixel oriented evaluation
01068     myPacket.uByteToBuf(0);
01069     // mode for single meas value eval
01070     myPacket.uByteToBuf(0);
01071     // restart times for field b and field c
01072     myPacket.byte2ToBuf(0);
01073     // um, an extra one (sick quickstart manual says its 21 not 20 long)
01074     myPacket.uByteToBuf(0);
01075     
01076     myPacket.finalizePacket();
01077     //myPacket.log();
01078     //printf("Sending mode!\n");
01079     if (myConn->write(myPacket.getBuf(), myPacket.getLength()))
01080     {
01081       //printf("Set mode!\n");
01082       switchState(STATE_WAIT_FOR_SET_MODE_ACK);
01083       return 0;
01084     }
01085     else
01086     {
01087       ArLog::log(ArLog::Terse,
01088                  "ArSick: Failed to connect to laser, could not send set mode command.");
01089       switchState(STATE_NONE);
01090       failedConnect();
01091       return 2;
01092     }
01093     break;
01094   case STATE_WAIT_FOR_SET_MODE_ACK:
01095     while ((packet = mySickPacketReceiver.receivePacket()) != NULL)
01096     {
01097       if (packet->getID() == 0xF7)
01098       {
01099         //value = packet->bufToByte();
01100         //printf("YAY %d\n", value);
01101         //packet->log();
01102         switchState(STATE_START_READINGS);
01103         return 0;
01104       }
01105       else if (packet->getID() == 0xb0)
01106       {
01107         
01108         ArLog::log(ArLog::Terse, "ArSick: extra data packet\n");
01109         myPacket.empty();
01110         myPacket.uByteToBuf(0x20);
01111         myPacket.uByteToBuf(0x25);
01112         myPacket.finalizePacket();
01113         if (myConn->write(myPacket.getBuf(), myPacket.getLength()))
01114         {
01115           switchState(STATE_INSTALL_MODE);
01116           return 0;
01117         }
01118       }
01119       else if (packet->getID() == 0x92)
01120       {
01121         switchState(STATE_INSTALL_MODE);
01122         return 0;
01123       }
01124       else
01125         ArLog::log(ArLog::Terse, "ArSick: Got a 0x%x\n", packet->getID());
01126     }
01127     if (myStateStart.mSecSince() > 14000)
01128     {
01129       ArLog::log(ArLog::Terse,
01130                  "ArSick: Failed to connect to laser, no set mode acknowledgement received.");
01131       switchState(STATE_NONE);
01132       failedConnect();
01133       return 2;
01134     }
01135     break;
01136     case STATE_START_READINGS: 
01137       if (myStateStart.mSecSince() < 200)
01138       return 0;
01139     myPacket.empty();
01140     myPacket.byteToBuf(0x20);
01141     myPacket.byteToBuf(0x24);
01142     myPacket.finalizePacket();
01143     if (myConn->write(myPacket.getBuf(), myPacket.getLength()))
01144     {
01145       switchState(STATE_WAIT_FOR_START_ACK);
01146       return 0;
01147     }
01148     else
01149     {
01150       ArLog::log(ArLog::Terse,
01151                  "ArSick: Failed to connect to laser, could not send start command.");
01152       switchState(STATE_NONE);
01153       failedConnect();
01154       return 2;
01155     }
01156     break;
01157   case STATE_WAIT_FOR_START_ACK:
01158     while ((packet = mySickPacketReceiver.receivePacket()) != NULL)
01159     {
01160       if (packet->getID() == 0xa0)
01161       {
01162         value = packet->bufToByte();
01163         if (value == 0)
01164         {
01165           ArLog::log(ArLog::Terse, "ArSick: Connected to the laser.");
01166           switchState(STATE_CONNECTED);
01167           madeConnection();
01168           return 1;
01169         }
01170         else if (value == 1)
01171         {
01172           ArLog::log(ArLog::Terse, 
01173              "ArSick: Could not start laser laser, incorrect password.");
01174           switchState(STATE_NONE);
01175           failedConnect();
01176           return 2;
01177         }
01178         else if (value == 2)
01179         {
01180           ArLog::log(ArLog::Terse, 
01181                      "ArSick: Could not start laser laser, LMI fault.");
01182           switchState(STATE_NONE);
01183           failedConnect();
01184           return 2;
01185         }
01186         else
01187         {
01188           ArLog::log(ArLog::Terse, 
01189                      "ArSick: Could not start laser laser, unknown problem.");
01190           switchState(STATE_NONE);
01191           failedConnect();
01192           return 2;
01193         }
01194       }
01195     }
01196     if (myStateStart.mSecSince() > 1000)
01197     {
01198       ArLog::log(ArLog::Terse,
01199                  "ArSick: Failed to connect to laser, no start acknowledgement received.");
01200       switchState(STATE_NONE);
01201       failedConnect();
01202       return 2;
01203     }
01204     break;
01205   default:
01206     ArLog::log(ArLog::Verbose, "ArSick: In bad connection state\n");
01207     break;
01208   }
01209   return 0;
01210 }
01211 
01217 bool ArSick::internalConnectSim(void)
01218 {
01219   lockDevice();
01220   double offset = myOffsetAmount;
01221   double increment = myIncrementAmount;
01222   unlockDevice();
01223 
01224   myRobot->lock();
01225   // return true if we could send all the commands
01226   if (myRobot->comInt(36, -ArMath::roundInt(offset)) &&
01227       myRobot->comInt(37, ArMath::roundInt(offset)) &&
01228       myRobot->comInt(38, ArMath::roundInt(increment * 100.0)) &&
01229       myRobot->comInt(35, 1))
01230   {
01231     myRobot->unlock();
01232     switchState(STATE_CONNECTED);
01233     madeConnection();
01234     ArLog::log(ArLog::Terse, "ArSick: Connected to simulated laser.");
01235     return true;
01236   }
01237   else
01238   {
01239     switchState(STATE_NONE);
01240     failedConnect();
01241     ArLog::log(ArLog::Terse, 
01242                "ArSick: Failed to connect to simulated laser.");
01243     return false;
01244   }
01245 }
01246 
01259 void ArSick::addConnectCB(ArFunctor *functor, 
01260                                     ArListPos::Pos position)
01261 {
01262   if (position == ArListPos::FIRST)
01263     myConnectCBList.push_front(functor);
01264   else if (position == ArListPos::LAST)
01265     myConnectCBList.push_back(functor);
01266   else
01267     ArLog::log(ArLog::Terse, 
01268                "ArSick::myConnectCallbackList: Invalid position.");
01269 }
01270 
01275 void ArSick::remConnectCB(ArFunctor *functor)
01276 {
01277   myConnectCBList.remove(functor);
01278 }
01279 
01280 
01294 void ArSick::addFailedConnectCB(ArFunctor *functor, 
01295                                           ArListPos::Pos position)
01296 {
01297   if (position == ArListPos::FIRST)
01298     myFailedConnectCBList.push_front(functor);
01299   else if (position == ArListPos::LAST)
01300     myFailedConnectCBList.push_back(functor);
01301   else
01302     ArLog::log(ArLog::Terse, 
01303                "ArSick::myConnectCallbackList: Invalid position.");
01304 }
01305 
01310 void ArSick::remFailedConnectCB(ArFunctor *functor)
01311 {
01312   myFailedConnectCBList.remove(functor);
01313 }
01314 
01328 void ArSick::addDisconnectNormallyCB(ArFunctor *functor, 
01329                                                ArListPos::Pos position)
01330 {
01331   if (position == ArListPos::FIRST)
01332     myDisconnectNormallyCBList.push_front(functor);
01333   else if (position == ArListPos::LAST)
01334     myDisconnectNormallyCBList.push_back(functor);
01335   else
01336     ArLog::log(ArLog::Terse, 
01337                "ArSick::myConnectCallbackList: Invalid position.");
01338 }
01339 
01344 void ArSick::remDisconnectNormallyCB(ArFunctor *functor)
01345 {
01346   myDisconnectNormallyCBList.remove(functor);
01347 }
01348 
01365 void ArSick::addDisconnectOnErrorCB(ArFunctor *functor, 
01366                                               ArListPos::Pos position)
01367 {
01368   if (position == ArListPos::FIRST)
01369     myDisconnectOnErrorCBList.push_front(functor);
01370   else if (position == ArListPos::LAST)
01371     myDisconnectOnErrorCBList.push_back(functor);
01372   else
01373     ArLog::log(ArLog::Terse, 
01374                "ArSick::myConnectCallbackList: Invalid position");
01375 }
01376 
01381 void ArSick::remDisconnectOnErrorCB(ArFunctor *functor)
01382 {
01383   myDisconnectOnErrorCBList.remove(functor);
01384 }
01385 
01396 void ArSick::addDataCB(ArFunctor *functor, 
01397                                     ArListPos::Pos position)
01398 {
01399   if (position == ArListPos::FIRST)
01400     myDataCBList.push_front(functor);
01401   else if (position == ArListPos::LAST)
01402     myDataCBList.push_back(functor);
01403   else
01404     ArLog::log(ArLog::Terse, 
01405                "ArSick::addDataCB: Invalid position.");
01406 }
01407 
01412 void ArSick::remDataCB(ArFunctor *functor)
01413 {
01414   myDataCBList.remove(functor);
01415 }
01416 
01417 void ArSick::dropConnection(void)
01418 {
01419   std::list<ArFunctor *>::iterator it;  
01420 
01421   if (myState != STATE_CONNECTED)
01422     return;
01423 
01424   myCurrentBuffer.reset();
01425   myCumulativeBuffer.reset();
01426   ArLog::log(ArLog::Terse, 
01427              "ArSick:  Lost connection to the laser because of error.");
01428   switchState(STATE_NONE);
01429   for (it = myDisconnectOnErrorCBList.begin(); 
01430        it != myDisconnectOnErrorCBList.end(); 
01431        it++)
01432     (*it)->invoke();
01433   if (myConn != NULL)
01434     myConn->close();
01435 }
01436 
01437 void ArSick::failedConnect(void)
01438 {
01439   std::list<ArFunctor *>::iterator it;  
01440   
01441   switchState(STATE_NONE);
01442   for (it = myFailedConnectCBList.begin(); 
01443        it != myFailedConnectCBList.end(); 
01444        it++)
01445     (*it)->invoke();
01446   if (myConn != NULL)
01447     myConn->close();
01448 }
01449 
01450 void ArSick::madeConnection(void)
01451 {
01452   std::list<ArFunctor *>::iterator it;
01453 
01454   myLastReading.setToNow();
01455   for (it = myConnectCBList.begin(); it != myConnectCBList.end(); it++)
01456     (*it)->invoke();
01457 }
01458 
01472 bool ArSick::disconnect(bool doNotLockRobotForSim)
01473 {
01474   std::list<ArFunctor *>::iterator it;  
01475   bool ret;
01476   ArSerialConnection *conn;
01477 
01478   myStateMutex.lock();
01479   if (myState == STATE_NONE)
01480   {
01481     myStateMutex.unlock();
01482     return true;
01483   }
01484     
01485   if (myState != STATE_CONNECTED)
01486   {
01487     lockDevice();
01488     myConnLock.lock();
01489     myState = STATE_NONE;
01490     ret = myConn->close();
01491     myConnLock.unlock();
01492     unlockDevice();
01493     ArLog::log(ArLog::Terse, "ArSick: Disconnecting from laser that was not fully connected to...");
01494     ArLog::log(ArLog::Terse, "this may cause problems later.");
01495     myStateMutex.unlock();
01496     return ret;
01497   }
01498 
01499   myCurrentBuffer.reset();
01500   myCumulativeBuffer.reset();
01501   ArLog::log(ArLog::Terse, "ArSick: Disconnecting from laser.");
01502   myState = STATE_NONE;
01503   myStateMutex.unlock();
01504   for (it = myDisconnectNormallyCBList.begin(); 
01505        it != myDisconnectNormallyCBList.end(); 
01506        it++)
01507     (*it)->invoke();
01508   if (myUseSim)
01509   {
01510     if (myRobot == NULL)
01511       return false;
01512     if (!doNotLockRobotForSim)
01513       myRobot->lock();
01514     ret = myRobot->comInt(35, 1);
01515     if (!doNotLockRobotForSim)
01516       myRobot->unlock();
01517     return ret;
01518   }
01519   else
01520   {
01521     myConnLock.lock();
01522     while (mySickPacketReceiver.receivePacket() != NULL);
01523     myPacket.empty();
01524     myPacket.uByteToBuf(0x20);
01525     myPacket.uByteToBuf(0x25);
01526     myPacket.finalizePacket();
01527     ret = myConn->write(myPacket.getBuf(), myPacket.getLength());
01528     // put the thing back to 9600 baud
01529     ArUtil::sleep(1000);
01530     myPacket.empty();
01531     myPacket.byteToBuf(0x20);
01532     myPacket.byteToBuf(0x42);
01533     myPacket.finalizePacket();
01534     if (myConn->write(myPacket.getBuf(), myPacket.getLength()))
01535     {
01536       ArUtil::sleep(20);
01537       if ((conn = dynamic_cast<ArSerialConnection *>(myConn)))
01538           conn->setBaud(9600);
01539     } else
01540       ret = false;
01541     ret = ret && myConn->close();
01542     myConnLock.unlock();
01543     ArUtil::sleep(300);
01544     return ret;
01545   }
01546 }
01547 
01558 bool ArSick::blockingConnect(void)
01559 {
01560   int ret;
01561   // if we're using the sim
01562   if (myUseSim)
01563   {
01564     return internalConnectSim();
01565   }
01566   // if we're talking to a real laser
01567   else 
01568   {
01569     lockDevice();
01570     myConnLock.lock();
01571     switchState(STATE_INIT);
01572     unlockDevice();
01573     while (getRunningWithLock() && (ret = internalConnectHandler()) == 0)
01574       ArUtil::sleep(100);
01575     myConnLock.unlock();
01576     if (ret == 1)
01577       return true;
01578     else 
01579       return false;
01580   }
01581   return false;
01582 }
01583 
01600 bool ArSick::asyncConnect(void)
01601 {
01602   if (myState == STATE_CONNECTED)
01603   {
01604     ArLog::log(ArLog::Terse,"ArSick: already connected to laser.");
01605     return false;
01606   }
01607   if (myUseSim || getRunning() || myRunningOnRobot)
01608   {
01609     myStartConnect = true;
01610     return true;
01611   } 
01612   else
01613   {
01614     ArLog::log(ArLog::Terse, "ArSick: Could not connect, to make an async connection either the sim needs to be used, the device needs to be run or runAsync, or the device needs to be runOnRobot.");
01615     return false;
01616   }
01617 }
01618 
01626 bool ArSick::runOnRobot(void)
01627 {
01628   if (myRobot == NULL)
01629     return false;
01630   else
01631   {  
01632     myRunningOnRobot = true;
01633     if (getRunning())
01634       stopRunning();
01635     return true;
01636   }
01637 }
01638 
01639 void ArSick::processPacket(ArSickPacket *packet, ArPose pose,
01640                                     ArPose encoderPose,
01641                                     unsigned int counter,
01642                                     bool deinterlace,
01643                                     ArPose deinterlaceDelta)
01644 {
01645   std::list<ArFunctor *>::iterator it;  
01646   unsigned int value;
01647   unsigned int numReadings;
01648   unsigned int i;
01649   double atDeg;
01650   unsigned int onReading;
01651   ArSensorReading *reading;
01652   int dist;
01653   std::list<ArSensorReading *>::iterator tempIt;
01654   int multiplier;
01655   ArTransform transform;
01656   std::list<double>::iterator ignoreIt;  
01657   bool ignore;
01658 
01659   //if (packet->getID() != 0xb0)
01660   //printf("Got in packet of type 0x%x\n", packet->getID());
01661   if (packet->getID() == 0xb0)
01662   {
01663     value = packet->bufToUByte2();
01664     numReadings = value & 0x3ff;
01665     //printf("numreadings %d\n", numReadings);
01666     if (!(value & ArUtil::BIT14) && !(value & ArUtil::BIT15))
01667       multiplier = 10;
01668     else if ((value & ArUtil::BIT14) && !(value & ArUtil::BIT15))
01669       multiplier = 1;
01670     else if (!(value & ArUtil::BIT14) && (value & ArUtil::BIT15))
01671       multiplier = 100;
01672     else
01673     {
01674       ArLog::log(ArLog::Terse, 
01675                  "ArSick::processPacket: bad distance configuration in packet\n");
01676       multiplier = 0;
01677     }
01678     //printf("%ld ms after last reading.\n", myLastReading.mSecSince());
01679     /*printf("Reading number %d, complete %d, unit: %d %d:\n", numReadings,
01680       !(bool)(value & ArUtil::BIT13), (bool)(value & ArUtil::BIT14),
01681       (bool)(value & ArUtil::BIT15));*/
01682     while (myAssembleReadings->size() > numReadings)
01683     {
01684       ArLog::log(ArLog::Verbose, "ArSick::processPacket, too many readings, popping one.\n");
01685       tempIt = myAssembleReadings->begin();
01686       if (tempIt != myAssembleReadings->end())
01687         delete (*tempIt);
01688       myAssembleReadings->pop_front();
01689     }
01690     
01691     // If we don't have any sensor readings created at all, make 'em all 
01692     if (myAssembleReadings->size() == 0)
01693       for (i = 0; i < numReadings; i++)
01694         myAssembleReadings->push_back(new ArSensorReading);
01695 
01696     transform.setTransform(pose);
01697     //deinterlaceDelta = transform.doInvTransform(deinterlacePose);
01698     // printf("usePose2 %d, th1 %.0f th2 %.0f\n",  usePose2, pose.getTh(), pose2.getTh());
01699     for (atDeg = mySensorPose.getTh() - myOffsetAmount, onReading = 0,
01700          myIter = myAssembleReadings->begin();
01701          (onReading < numReadings && 
01702           packet->getReadLength() < packet->getLength() - 4);
01703          myWhichReading++, atDeg += myIncrementAmount, myIter++, onReading++)
01704     {
01705       reading = (*myIter);
01706       //reading->resetSensorPosition(0, 0, 0);
01707 
01708       //value = packet->bufToUByte2() & 0x1fff;
01709       //dist = (value & 0x1fff) * multiplier ;
01710       value = packet->bufToUByte2() & 0x7fff;
01711       dist = value * multiplier ;
01712       //printf("%d ", dist);
01713 
01714       ignore = false;
01715       for (ignoreIt = myIgnoreReadings.begin(); 
01716            ignoreIt != myIgnoreReadings.end();
01717            ignoreIt++)
01718       {
01719         if (ArMath::fabs(ArMath::subAngle(atDeg, *(ignoreIt))) < 1.0)
01720         {
01721           ignore = true;
01722           break;
01723         }
01724       }
01725       if (myMinRange != 0 && dist < (int)myMinRange)
01726         ignore = true;
01727       if (myMaxRange != 0 && dist > (int)myMaxRange)
01728         ignore = true;
01729       if (deinterlace && (onReading % 2) == 0)
01730       {
01731         reading->resetSensorPosition(
01732                ArMath::roundInt(mySensorPose.getX() + deinterlaceDelta.getX()),
01733                ArMath::roundInt(mySensorPose.getY() + deinterlaceDelta.getY()),
01734                ArMath::addAngle(atDeg, deinterlaceDelta.getTh()));
01735         reading->newData(dist, pose, encoderPose, transform, counter, 
01736                          packet->getTimeReceived(), ignore);
01737       }
01738       else
01739       {
01740         reading->resetSensorPosition(ArMath::roundInt(mySensorPose.getX()),
01741                                      ArMath::roundInt(mySensorPose.getY()),
01742                                      atDeg); 
01743         reading->newData(dist, pose, encoderPose, transform, counter, 
01744                          packet->getTimeReceived(), ignore);
01745       }
01746       /*
01747       reading->newData(onReading, 0, 0, 0,
01748                        ArTransform(), counter, 
01749                        packet->getTimeReceived());
01750       */
01751       tempIt = myIter;
01752       tempIt++;
01753       if (tempIt == myAssembleReadings->end() && 
01754           onReading + 1 != numReadings)
01755       {
01756         myAssembleReadings->push_back(new ArSensorReading);
01757       }
01758     }
01759     // set ArRangeDevice buffer, switch internal buffers
01760     myRawReadings = myAssembleReadings;
01761     //printf("Readings? 0x%x\n", myRawReadings);
01762     myAssembleReadings = myCurrentReadings;
01763     myCurrentReadings = myRawReadings;
01764     //printf("\n");
01765     myLastReading.setToNow();
01766     filterReadings();
01767     
01768     if (myTimeLastSickPacket != time(NULL)) 
01769     {
01770       myTimeLastSickPacket = time(NULL);
01771       mySickPacCount = mySickPacCurrentCount;
01772       mySickPacCurrentCount = 0;
01773     }
01774     mySickPacCurrentCount++;
01775     for (it = myDataCBList.begin(); it != myDataCBList.end(); it++)
01776       (*it)->invoke();
01777   }
01778 }
01779 
01780 void ArSick::runOnce(bool lockRobot)
01781 {
01782   ArSickPacket *packet;
01783   unsigned int counter;
01784   int ret;
01785   ArTime time;
01786   ArTime time2;
01787   ArPose pose;
01788   ArPose pose2;
01789   ArPose encoderPose;
01790 
01791   if (myProcessImmediately && myRobot != NULL)
01792   {
01793     if (lockRobot)
01794       myRobot->lock();
01795     pose = myRobot->getPose();
01796     counter = myRobot->getCounter();
01797     if (lockRobot)
01798       myRobot->unlock();
01799   }
01800 
01801   lockDevice();
01802   if (myState == STATE_CONNECTED && myTimeoutTime > 0 && 
01803       myLastReading.mSecSince() > myTimeoutTime * 1000)
01804   {
01805     dropConnection();
01806     unlockDevice();
01807     return;
01808   }
01809   if (myUseSim)
01810   {
01811     unlockDevice();
01812     return;
01813   }
01814   if (myState == STATE_CONNECTED)
01815   {
01816     unlockDevice();
01817     myConnLock.lock();
01818     packet = mySickPacketReceiver.receivePacket();
01819     myConnLock.unlock();
01820     lockDevice();
01821     // if we're attached to a robot and have a packet
01822     if (myRobot != NULL && packet != NULL && !myProcessImmediately)
01823     {
01824       myPackets.push_back(packet);
01825     }
01826     else if (myRobot != NULL && packet != NULL && myProcessImmediately)
01827     {
01828       unlockDevice();
01829       if (lockRobot && myInterpolation)
01830         myRobot->lock();
01831       // try to get the interpolated position, if we can't, just use
01832       // the robot's pose
01833       if (myInterpolation && (ret = myRobot->getPoseInterpPosition(
01834               packet->getTimeReceived(), &pose)) < 0)
01835         pose = myRobot->getPose();
01836       // try to get the interpolated encoder position, if we can't,
01837       // just fake it from the robot's pose and the encoder transform
01838       if (myInterpolation && (ret = myRobot->getEncoderPoseInterpPosition(
01839               packet->getTimeReceived(), &encoderPose)) < 0)
01840         encoderPose = myRobot->getEncoderTransform().doInvTransform(pose);
01841       if (lockRobot && myInterpolation)
01842         myRobot->unlock();
01843       lockDevice();
01844       processPacket(packet, pose, encoderPose, counter, false, ArPose());
01845     }
01846     else if (packet != NULL) // if there's no robot
01847     {
01848       processPacket(packet, pose, encoderPose, 0, false, ArPose());
01849       delete packet;
01850     }
01851   }
01852   unlockDevice();
01853   return;
01854 
01855 }
01856 
01857 int ArSick::getSickPacCount()
01858 {
01859   if (myTimeLastSickPacket == time(NULL))
01860     return mySickPacCount;
01861   if (myTimeLastSickPacket == time(NULL) - 1)
01862     return mySickPacCurrentCount;
01863   return 0;
01864 }
01865 
01872 void ArSick::setFilterNearDist(double dist)
01873 {
01874   if (dist >= 0)
01875     myFilterNearDist = dist;
01876   else
01877     ArLog::log(ArLog::Terse, "ArSick::setFilterNearDist given a distance less than 0.\n");
01878 
01879 }
01880 
01887 double ArSick::getFilterNearDist(void)
01888 {
01889   return myFilterNearDist;
01890 }
01891 
01892 
01898 void ArSick::setFilterCumulativeInsertMaxDist(double dist)
01899 {
01900   if (dist >= 0)
01901   {
01902     myFilterCumulativeInsertMaxDist = dist;
01903     myFilterSquaredCumulativeInsertMaxDist = dist * dist;
01904   }
01905   else
01906     ArLog::log(ArLog::Terse, "ArSick::setFilterCumulativeMaxDistDist given a distance less than 0.\n");
01907 }
01908 
01914 double ArSick::getFilterCumulativeInsertMaxDist(void)
01915 {
01916   return myFilterCumulativeInsertMaxDist;
01917 }
01918 
01924 void ArSick::setFilterCumulativeNearDist(double dist)
01925 {
01926   if (dist >= 0)
01927   {
01928     myFilterCumulativeNearDist = dist;
01929     myFilterSquaredCumulativeNearDist = dist * dist;
01930   }
01931   else
01932     ArLog::log(ArLog::Terse, "ArSick::setFilterCumulativeNearDistDist given a distance less than 0.\n");
01933 }
01934 
01940 double ArSick::getFilterCumulativeNearDist(void)
01941 {
01942   return myFilterCumulativeNearDist;
01943 }
01944 
01952 void ArSick::setFilterCumulativeCleanDist(double dist)
01953 {
01954   if (dist >= 0)
01955   {
01956     myFilterCumulativeCleanDist = dist;
01957     myFilterSquaredCumulativeCleanDist = dist * dist;
01958   }
01959   else
01960     ArLog::log(ArLog::Terse, "ArSick::setFilterCumulativeCleanDistDist given a distance less than 0.\n");
01961 }
01962 
01970 double ArSick::getFilterCumulativeCleanDist(void)
01971 {
01972   return myFilterCumulativeCleanDist;
01973 }
01974 
01980 void ArSick::setFilterCleanCumulativeInterval(int milliSeconds)
01981 {
01982   if (milliSeconds >= 0)
01983   {
01984     myFilterCleanCumulativeInterval = milliSeconds;
01985   }
01986   else
01987     ArLog::log(ArLog::Terse, "ArSick::setFilterCleanCumulativeInterval given a time less than 0.\n");
01988 }
01989 
01995 int ArSick::getFilterCleanCumulativeInterval(void)
01996 {
01997   return myFilterCleanCumulativeInterval;
01998 }
01999 
02000 
02001 
02002 void ArSick::sensorInterpCallback(void)
02003 {
02004   std::list<ArSickPacket *>::iterator it;
02005   std::list<ArSickPacket *> processed;
02006   ArSickPacket *packet;
02007   ArTime time;
02008   ArPose pose;
02009   int ret;
02010   int retEncoder;
02011   ArPose encoderPose;
02012   ArPose deinterlaceEncoderPose;
02013   bool deinterlace;
02014   ArTime deinterlaceTime;
02015   ArPose deinterlaceDelta;
02016   
02017   if (myRunningOnRobot)
02018     runOnce(false);
02019   
02020   lockDevice();
02021   for (it = myPackets.begin(); it != myPackets.end(); it++)
02022   {
02023     packet = (*it);
02024     time = packet->getTimeReceived();
02025     time.addMSec(-13);
02026     if ((ret = myRobot->getPoseInterpPosition(time, &pose)) == 1 &&
02027         (retEncoder = 
02028          myRobot->getEncoderPoseInterpPosition(time, &encoderPose)) == 1)
02029     {
02030       deinterlaceTime = packet->getTimeReceived();
02031       deinterlaceTime.addMSec(-27);
02032       
02033       if (myIncrement == INCREMENT_HALF && 
02034           (myRobot->getEncoderPoseInterpPosition(
02035                   deinterlaceTime, &deinterlaceEncoderPose)) == 1)
02036         deinterlace = true;
02037       else
02038         deinterlace = false;
02039 
02040       ArTransform deltaTransform;
02041       deltaTransform.setTransform(encoderPose);
02042       deinterlaceDelta = deltaTransform.doInvTransform(deinterlaceEncoderPose);
02043 
02044       processPacket(packet, pose, encoderPose, myRobot->getCounter(),
02045                     deinterlace, deinterlaceDelta);
02046       processed.push_back(packet);
02047     }
02048     else if (ret < -1 || retEncoder < -1)
02049     {
02050       if (myRobot->isConnected())
02051         ArLog::log(ArLog::Normal, "ArSick::processPacket: too old to process\n");
02052       else
02053       {
02054         processPacket(packet, pose, encoderPose, myRobot->getCounter(), false,
02055                       ArPose());
02056       }
02057       processed.push_back(packet);
02058     }
02059     else 
02060     {
02061       //ArLog::log(ArLog::Terse, "ArSick::processPacket: error %d from interpolation\n", ret);
02062       //printf("$$$ ret = %d\n", ret);
02063     }
02064   }
02065   while ((it = processed.begin()) != processed.end())
02066   {
02067     packet = (*it);
02068     myPackets.remove(packet);
02069     processed.pop_front();
02070     delete packet;
02071   }
02072   unlockDevice();
02073 }
02074 
02075 void *ArSick::runThread(void *arg)
02076 {
02077   while (getRunningWithLock())
02078   {
02079     lockDevice();
02080     if (myStartConnect)
02081     {
02082       myStartConnect = false;
02083       switchState(STATE_INIT);
02084       if (myUseSim)
02085       {
02086         unlockDevice();
02087         internalConnectSim();
02088       }
02089       else 
02090       {
02091         unlockDevice();
02092         while (getRunningWithLock())
02093         {
02094           lockDevice();
02095           myConnLock.lock();
02096           if (internalConnectHandler() != 0)
02097           {
02098             myConnLock.unlock();
02099             unlockDevice();
02100             break;
02101           }
02102           myConnLock.unlock();
02103           unlockDevice();
02104           ArUtil::sleep(1);
02105         }
02106       }
02107     } else
02108       unlockDevice();
02109     runOnce(true);
02110     ArUtil::sleep(1);
02111   }
02112   lockDevice();
02113   if (isConnected())
02114   {
02115     disconnect();
02116   }
02117   unlockDevice();
02118 
02119   return NULL;
02120 }
02121 
02129 void ArSick::applyTransform(ArTransform trans,
02130                                                 bool doCumulative)
02131 {
02132   myCurrentBuffer.applyTransform(trans);
02133   std::list<ArSensorReading *>::iterator it;
02134 
02135   for (it = myRawReadings->begin(); it != myRawReadings->end(); ++it)
02136     (*it)->applyTransform(trans);
02137 
02138   if (doCumulative)
02139     myCumulativeBuffer.applyTransform(trans);
02140 }

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