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

ArSick.cpp

00001 /*
00002 MobileRobots Advanced Robotics Interface for Applications (ARIA)
00003 Copyright (C) 2004, 2005 ActivMedia Robotics LLC
00004 Copyright (C) 2006, 2007 MobileRobots Inc.
00005 
00006      This program is free software; you can redistribute it and/or modify
00007      it under the terms of the GNU General Public License as published by
00008      the Free Software Foundation; either version 2 of the License, or
00009      (at your option) any later version.
00010 
00011      This program is distributed in the hope that it will be useful,
00012      but WITHOUT ANY WARRANTY; without even the implied warranty of
00013      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014      GNU General Public License for more details.
00015 
00016      You should have received a copy of the GNU General Public License
00017      along with this program; if not, write to the Free Software
00018      Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00019 
00020 If you wish to redistribute ARIA under different terms, contact 
00021 MobileRobots for information about a commercial version of ARIA at 
00022 robots@mobilerobots.com or 
00023 MobileRobots Inc, 19 Columbia Drive, Amherst, NH 03031; 800-639-9481
00024 */
00025 
00026 #include "ArExport.h"
00027 #include "ariaOSDef.h"
00028 #include "ArSick.h"
00029 #include "ArRobot.h"
00030 #include "ArSerialConnection.h"
00031 #include "ariaInternal.h"
00032 #include <time.h>
00033 
00034 AREXPORT ArSick::ArSick(size_t currentBufferSize, size_t cumulativeBufferSize, 
00035             const char *name, bool addAriaExitCB) :
00036   ArRangeDeviceThreaded(currentBufferSize, cumulativeBufferSize, name, 32500),
00037   myRobotConnectCB(this, &ArSick::robotConnectCallback),
00038   mySimPacketHandler(this, &ArSick::simPacketHandler),
00039   mySensorInterpCB(this, &ArSick::sensorInterpCallback),
00040   mySickPacketReceiver(0, true),
00041   myAriaExitCB(this, &ArSick::disconnect, true)
00042 {
00043   myAriaExitCB.setName("ArSickExit");
00044   if (addAriaExitCB)
00045     Aria::addExitCallback(&myAriaExitCB, 10);
00046   mySimPacketHandler.setName("ArSick");
00047   configure();
00048   setRangeInformation();
00049   setSensorPosition(0, 0, 0);
00050   myAssembleReadings = new std::list<ArSensorReading *>;
00051   myCurrentReadings = new std::list<ArSensorReading *>;
00052   myRawReadings = myCurrentReadings;
00053   myIter = myAssembleReadings->begin();
00054   myConn = NULL;
00055   myRobot = NULL;
00056   myStartConnect = false;
00057   myRunningOnRobot = false;
00058   switchState(STATE_NONE);
00059   myProcessImmediately = false;
00060   myInterpolation = true;
00061   myTimeoutTime = 8;
00062   myRealConfigured = false;
00063 
00064   // default filter params
00065   setMinRange(125);
00066   setFilterNearDist(50);
00067   setFilterCumulativeMaxDist(6000);
00068   setFilterCumulativeInsertMaxDist(3000);
00069   setFilterCumulativeNearDist(200);
00070   setFilterCumulativeCleanDist(75);
00071   setFilterCumulativeMaxAge(30);
00072   setFilterCleanCumulativeInterval(1000);
00073 
00074   myLastCleanedCumulative.setToNow();
00075 
00076   setCurrentDrawingData(new ArDrawingData("polyDots", 
00077                                           ArColor(0, 0, 255), 
00078                                           80,  // mm diameter of dots
00079                                           75), // layer above sonar 
00080                         true);
00081 
00082   setCumulativeDrawingData(new ArDrawingData("polyDots", 
00083                                              ArColor(125, 125, 125), 
00084                                              100, // mm diameter of dots
00085                                              60), // layer below current range devices  
00086                            true);
00087 }
00088 
00089 AREXPORT ArSick::~ArSick()
00090 {
00091   if (myRobot != NULL)
00092   {
00093     myRobot->remRangeDevice(this);
00094     myRobot->remPacketHandler(&mySimPacketHandler);
00095     myRobot->remSensorInterpTask(&mySensorInterpCB);
00096     myRobot->addConnectCB(&myRobotConnectCB, ArListPos::FIRST);
00097   }
00098   lockDevice();
00099   if (isConnected())
00100   {
00101     disconnect();
00102   }
00103   unlockDevice();
00104 }
00105 
00107 AREXPORT void ArSick::robotConnectCallback(void)
00108 {
00109   const ArRobotParams *params;
00110   if (myRealConfigured || !myRobot->isConnected()) 
00111     return;
00112   params = myRobot->getRobotParams();
00113   myLaserFlipped = params->getLaserFlipped();
00114   myPowerControl = params->getLaserPowerControlled();
00115   
00116   if (myDegrees == DEGREES180)
00117     myOffsetAmount = 90;
00118   else if (myDegrees == DEGREES100)
00119     myOffsetAmount = 50;
00120   else
00121   {
00122     myOffsetAmount = 0;
00123     ArLog::log(ArLog::Terse,"ArSick::robotConnectCallback: bad degrees configured.\n");
00124   }
00125   
00126 
00127   if (myLaserFlipped)
00128     myOffsetAmount *= -1;
00129 
00130   if (myIncrement == INCREMENT_ONE)
00131     myIncrementAmount = 1.0;
00132   else if (myIncrement == INCREMENT_HALF)
00133     myIncrementAmount = 0.5;
00134   else
00135   {
00136     myIncrementAmount = 0;
00137     ArLog::log(ArLog::Terse,"ArSick::robotConnectCallback: bad increment configured.\n");
00138   }
00139   if (myLaserFlipped)
00140     myIncrementAmount *= -1;
00141 
00142   clearIgnoreReadings();
00143   ArArgumentBuilder builder;
00144   builder.add(myRobot->getRobotParams()->getLaserIgnore());
00145   size_t i;
00146   for (i = 0; i < builder.getArgc(); i++)
00147   {
00148     if (!builder.isArgDouble(i))
00149     {
00150       ArLog::log(ArLog::Normal, "ArRobotConfig::setIgnoreReadings: argument is not a double");
00151     }
00152     addIgnoreReading(builder.getArgDouble(i));
00153   }
00154 
00155   setSensorPosition(params->getLaserX(), params->getLaserY(), params->getLaserTh());
00156 }
00157 
00158 AREXPORT bool ArSick::isUsingSim(void)
00159 {
00160   return myUseSim;
00161 }
00162 
00163 AREXPORT bool ArSick::isControllingPower(void)
00164 {
00165   return myPowerControl;
00166 }
00167 
00168 AREXPORT bool ArSick::isLaserFlipped(void)
00169 {
00170   return myLaserFlipped;
00171 }
00172 
00173 AREXPORT ArSick::Degrees ArSick::getDegrees(void)
00174 {
00175   return myDegrees;
00176 }
00177 
00178 AREXPORT ArSick::Increment ArSick::getIncrement(void)
00179 {
00180   return myIncrement;
00181 }
00182 
00183 AREXPORT ArSick::Bits ArSick::getBits(void) { return myBits; }
00184 AREXPORT ArSick::Units ArSick::getUnits(void) { return myUnits; }
00185 
00186 AREXPORT void ArSick::setIsUsingSim(bool usingSim)
00187 {
00188   myUseSim = usingSim;
00189 }
00190 
00191 AREXPORT void ArSick::setIsControllingPower(bool controlPower)
00192 {
00193   myPowerControl = controlPower;
00194 }
00195 
00196 AREXPORT void ArSick::setIsLaserFlipped(bool laserFlipped)
00197 {
00198   myLaserFlipped = laserFlipped;
00199 }
00200 
00201 
00202 AREXPORT void ArSick::setSensorPosition(double x, double y, double th)
00203 {
00204   mySensorPose.setPose(x, y, th);
00205 }
00206 
00207 AREXPORT void ArSick::setSensorPosition(ArPose pose)
00208 {
00209   mySensorPose = pose;
00210 }
00211 
00212 AREXPORT ArPose ArSick::getSensorPosition(void)
00213 {
00214   return mySensorPose;
00215 }
00216 
00217 AREXPORT double ArSick::getSensorPositionX(void)
00218 {
00219   return mySensorPose.getX();
00220 }
00221 
00222 AREXPORT double ArSick::getSensorPositionY(void)
00223 {
00224   return mySensorPose.getY();
00225 }
00226 
00227 AREXPORT double ArSick::getSensorPositionTh(void)
00228 {
00229   return mySensorPose.getTh();
00230 }
00231 
00232 
00233 AREXPORT void ArSick::setDeviceConnection(ArDeviceConnection *conn)
00234 {
00235   myConnLock.lock();
00236   myConn = conn; 
00237   mySickPacketReceiver.setDeviceConnection(conn); 
00238   myConnLock.unlock();
00239 }
00240 
00241 AREXPORT ArDeviceConnection *ArSick::getDeviceConnection(void)
00242 {
00243   return myConn;
00244 }
00245 
00255 AREXPORT void ArSick::setConnectionTimeoutTime(int mSecs)
00256 {
00257   if (mSecs > 0)
00258     myTimeoutTime = mSecs;
00259   else
00260     myTimeoutTime = 0;
00261 }
00262 
00269 AREXPORT int ArSick::getConnectionTimeoutTime(void)
00270 {
00271   return myTimeoutTime;
00272 }
00273 
00274 AREXPORT ArTime ArSick::getLastReadingTime(void)
00275 {
00276   return myLastReading;
00277 }
00278 
00279 AREXPORT void ArSick::setRobot(ArRobot *robot)
00280 {
00281   myRobot = robot;
00282   if (myRobot != NULL)
00283   {
00284     myRobot->addPacketHandler(&mySimPacketHandler, ArListPos::LAST);
00285     myRobot->addSensorInterpTask("sick", 90, &mySensorInterpCB);
00286     myRobot->addConnectCB(&myRobotConnectCB, ArListPos::FIRST);
00287     if (myRobot->isConnected())
00288       robotConnectCallback();
00289   }
00290   ArRangeDevice::setRobot(robot);
00291 }
00292 
00305 AREXPORT void ArSick::configure(bool useSim, bool powerControl,
00306                 bool laserFlipped, BaudRate baud,
00307                 Degrees deg, Increment incr)
00308 {
00309 
00310   myUseSim = useSim;
00311   myPowerControl = powerControl;
00312   myLaserFlipped = laserFlipped;
00313   myBaud = baud;
00314   myDegrees = deg;
00315   myIncrement = incr;
00316 
00317   if (myDegrees == DEGREES180)
00318     myOffsetAmount = 90;
00319   else if (myDegrees == DEGREES100)
00320     myOffsetAmount = 50;
00321   else
00322   {
00323     myOffsetAmount = 0;
00324     ArLog::log(ArLog::Terse,"ArSick::configure: bad degrees configured.\n");
00325   }
00326   
00327   if (myLaserFlipped)
00328     myOffsetAmount *= -1;
00329 
00330   if (myIncrement == INCREMENT_ONE)
00331     myIncrementAmount = 1.0;
00332   else if (myIncrement == INCREMENT_HALF)
00333     myIncrementAmount = 0.5;
00334   else
00335   {
00336     myIncrementAmount = 0;
00337     ArLog::log(ArLog::Terse,"ArSick::configure: bad increment configured.\n");
00338   }
00339 
00340   if (myLaserFlipped)
00341     myIncrementAmount *= -1;
00342 
00343   myRealConfigured = true;
00344 }
00345 
00349 AREXPORT void ArSick::configureShort(bool useSim, BaudRate baud,
00350                 Degrees deg, Increment incr)
00351 {
00352 
00353   myUseSim = useSim;
00354   myPowerControl = true;
00355   myLaserFlipped = false;
00356   myBaud = baud;
00357   myDegrees = deg;
00358   myIncrement = incr;
00359 
00360   if (myDegrees == DEGREES180)
00361     myOffsetAmount = 90;
00362   else if (myDegrees == DEGREES100)
00363     myOffsetAmount = 50;
00364   else
00365   {
00366     myOffsetAmount = 0;
00367     ArLog::log(ArLog::Terse,"ArSick::configureShort: bad degrees configured.\n");
00368   }
00369   
00370   if (myLaserFlipped)
00371     myOffsetAmount *= -1;
00372 
00373   if (myIncrement == INCREMENT_ONE)
00374     myIncrementAmount = 1.0;
00375   else if (myIncrement == INCREMENT_HALF)
00376     myIncrementAmount = 0.5;
00377   else
00378   {
00379     myIncrementAmount = 0;
00380     ArLog::log(ArLog::Terse,"ArSick::configureShort: bad increment configured.\n");
00381   }
00382   if (myLaserFlipped)
00383     myIncrementAmount *= -1;
00384 
00385   myRealConfigured = false;
00386   // if we're connected, just have this set things
00387   if (myRobot != NULL && myRobot->isConnected())
00388     robotConnectCallback();
00389 }
00390 
00396 AREXPORT void ArSick::setRangeInformation(Bits bits, Units units)
00397 {
00398   myUnits = units;
00399   myBits = bits;
00400 }
00401 
00402 
00404 AREXPORT bool ArSick::simPacketHandler(ArRobotPacket *packet)
00405 {
00406   std::list<ArFunctor *>::iterator it;
00407 
00408   unsigned int totalNumReadings;
00409   unsigned int readingNumber;
00410   double atDeg;
00411   unsigned int i;
00412   ArSensorReading *reading;
00413   std::list<ArSensorReading *>::iterator tempIt;
00414   unsigned int newReadings;
00415   int range;
00416   int refl = 0;
00417   ArPose encoderPose;
00418   std::list<double>::iterator ignoreIt;  
00419   bool ignore;
00420   
00421   if (packet->getID() != 0x60 && packet->getID() != 0x61)
00422     return false;
00423 
00424   bool isExtendedPacket = (packet->getID() == 0x61);
00425    
00426   // if we got here, its the right type of packet
00427 
00428   //printf("Got in a packet from the simulator\n");
00429   lockDevice();
00430   //printf("1\n");
00431   if (!myUseSim)
00432   {
00433     ArLog::log(ArLog::Terse, "ArSick: Got a packet from the simulator with laser information, but the laser is not being simulated, major trouble.");
00434     unlockDevice();
00435     return true;
00436   }
00437   if(!isExtendedPacket)
00438   {
00439     // ignore the positional information
00440     packet->bufToByte2();
00441     packet->bufToByte2();
00442     packet->bufToByte2();
00443   }
00444   totalNumReadings = packet->bufToByte2(); // total for this reading
00445   readingNumber = packet->bufToByte2(); // which one we're on in this packet
00446   newReadings = packet->bufToUByte(); // how many are in this packet
00447   if (readingNumber == 0)
00448   {
00449     mySimPacketStart = myRobot->getPose();
00450     mySimPacketTrans = myRobot->getToGlobalTransform();
00451     mySimPacketEncoderTrans = myRobot->getEncoderTransform();
00452     mySimPacketCounter = myRobot->getCounter();
00453   }
00454   //printf("ArSick::simPacketHandler: On reading number %d out of %d, new %d\n", readingNumber, totalNumReadings, newReadings);
00455   // if we have too many readings in our list of raw readings, pop the extras
00456   while (myAssembleReadings->size() > totalNumReadings)
00457   {
00458     ArLog::log(ArLog::Verbose, "ArSick::simPacketHandler, too many readings, popping one.\n");
00459     tempIt = myAssembleReadings->begin();
00460     if (tempIt != myAssembleReadings->end())
00461       delete (*tempIt);
00462     myAssembleReadings->pop_front();
00463   }
00464   
00465   // If we don't have any sensor readings created at all, make 'em all now
00466   if (myAssembleReadings->size() == 0)
00467     for (i = 0; i < totalNumReadings; i++)
00468       myAssembleReadings->push_back(new ArSensorReading);
00469   
00470   // Okay, we know where we're at, so get an iterator to the right spot, or 
00471   // make sure the one we keep around is in the right spot... if neither of
00472   // these trigger, then the iter should be in the right spot
00473   if ((readingNumber != myWhichReading + 1) || 
00474       totalNumReadings != myTotalNumReadings)
00475   {
00476     //printf("2\n");
00477     myWhichReading = readingNumber;
00478     myTotalNumReadings = totalNumReadings;
00479     for (i = 0, myIter = myAssembleReadings->begin(); i < readingNumber; i++)
00480     {
00481       tempIt = myIter;
00482       tempIt++;
00483       if (tempIt == myAssembleReadings->end() && (i + 1 != myTotalNumReadings))
00484     myAssembleReadings->push_back(new ArSensorReading);
00485       myIter++;
00486     }
00487   }
00488   else
00489   {
00490     //printf("3\n");
00491     myWhichReading = readingNumber;
00492   }
00493 
00494   atDeg = (mySensorPose.getTh() - myOffsetAmount + 
00495        readingNumber * myIncrementAmount);
00496   //printf("4\n");
00497   encoderPose = mySimPacketEncoderTrans.doInvTransform(mySimPacketStart);
00498   // while we have in the readings and have stuff left we can read 
00499   for (i = 0; 
00500        //    (myWhichReading < myTotalNumReadings && 
00501        //     packet->getReadLength() < packet->getLength() - 4);
00502        i < newReadings;
00503        i++, myWhichReading++, atDeg += myIncrementAmount)
00504   {
00505     reading = (*myIter);
00506     range = packet->bufToUByte2();
00507     if(isExtendedPacket)
00508     {
00509       refl = packet->bufToUByte();
00510       packet->bufToUByte(); // don't need this byte for anything yet
00511       packet->bufToUByte(); // don't need this byte for anything yet
00512     }
00513     ignore = false;
00514     for (ignoreIt = myIgnoreReadings.begin(); 
00515      ignoreIt != myIgnoreReadings.end();
00516      ignoreIt++)
00517     {
00518       //if (atDeg == 0)
00519       //printf("Ignoring %.0f\n", (*ignoreIt));
00520       if (ArMath::fabs(ArMath::subAngle(atDeg, *(ignoreIt))) < 1.0)
00521       {
00522     //printf("Ignoring %.0f\n", (*ignoreIt));
00523     ignore = true;
00524     break;
00525       }
00526     }
00527     if (myMaxRange != 0 && range < (int)myMinRange)
00528       ignore = true;
00529     if (myMaxRange != 0 && range > (int)myMaxRange)
00530       ignore = true;
00531     
00532     reading->resetSensorPosition(ArMath::roundInt(mySensorPose.getX()),
00533                  ArMath::roundInt(mySensorPose.getY()),
00534                  atDeg);
00535     //      printf("dist %d\n", dist);
00536     reading->newData(range, mySimPacketStart, 
00537              encoderPose,
00538              mySimPacketTrans,
00539              mySimPacketCounter, packet->getTimeReceived(), ignore, refl);
00540     
00541     //addReading(reading->getX(), reading->getY());
00542     tempIt = myIter;
00543     tempIt++;
00544     if (tempIt == myAssembleReadings->end() && 
00545     myWhichReading + 1 != myTotalNumReadings)
00546     {
00547       myAssembleReadings->push_back(new ArSensorReading);
00548     }
00549     myIter++;
00550   }
00551 
00552   // check if the sensor set is complete
00553   //printf("%d %d %d\n", newReadings, readingNumber, totalNumReadings);
00554   if (newReadings + readingNumber >= totalNumReadings)
00555   {
00556     // set ArRangeDevice buffer
00557     myRawReadings = myAssembleReadings;
00558     // switch internal buffers
00559     myAssembleReadings = myCurrentReadings;
00560     myCurrentReadings = myRawReadings;
00561     // We have in all the readings, now sort 'em and update the current ones
00562     filterReadings();
00563 
00564     if (myTimeLastSickPacket != time(NULL)) 
00565       {
00566     myTimeLastSickPacket = time(NULL);
00567     mySickPacCount = mySickPacCurrentCount;
00568     mySickPacCurrentCount = 0;
00569       }
00570     mySickPacCurrentCount++;
00571     myLastReading.setToNow();
00572     
00573     for (it = myDataCBList.begin(); it != myDataCBList.end(); it++)
00574       (*it)->invoke();
00575   } 
00576   
00577   unlockDevice();
00578   return true;
00579 }
00580 
00596 void ArSick::filterReadings()
00597 {
00598   std::list<ArSensorReading *>::iterator sensIt;
00599   ArSensorReading *sReading;
00600   double x, y;
00601   double squaredDist;
00602   double lastX = 0.0, lastY = 0.0;
00603   unsigned int i;
00604   double squaredNearDist = myFilterNearDist * myFilterNearDist; 
00605   ArTime len;
00606   len.setToNow();
00607 
00608   bool clean;
00609   if (myFilterCleanCumulativeInterval == 0 ||
00610       myLastCleanedCumulative.mSecSince() > myFilterCleanCumulativeInterval)
00611   {
00612     myLastCleanedCumulative.setToNow();
00613     clean = true;
00614   }
00615   else
00616   {
00617     clean = false;
00618   }
00619   
00620   sensIt = myRawReadings->begin();
00621   sReading = (*sensIt);
00622   myCurrentBuffer.setPoseTaken(sReading->getPoseTaken());
00623   myCurrentBuffer.setEncoderPoseTaken(sReading->getEncoderPoseTaken());
00624   //myCurrentBuffer.reset();
00625 
00626   // if we don't have any readings in the buffer yet, fill it up
00627   /* MPL commented this out since if we had no valid readings it'd
00628    * leak memory like a sieve
00629 
00630   if (myCurrentBuffer.getBuffer()->size() == 0)
00631     for (i = 0; i < myRawReadings->size(); i++)
00632       myCurrentBuffer.getBuffer()->push_back(new ArPoseWithTime);
00633   */
00634 
00635   i = 0;
00636   // walk the buffer of all the readings and see if we want to add them
00637   for (myCurrentBuffer.beginRedoBuffer();     
00638        sensIt != myRawReadings->end(); 
00639        ++sensIt)
00640   {
00641     sReading = (*sensIt);
00642     /*
00643     if (sReading->getIgnoreThisReading())
00644        printf("Ignoring %.0f %d\n", sReading->getSensorTh(),sReading->getRange());
00645     */
00646     // see if the reading is in the valid range
00647     if (!sReading->getIgnoreThisReading())
00648     {
00649       // get our coords
00650       x = sReading->getX();
00651       y = sReading->getY();
00652 
00653       
00654       // see if we're checking on the filter near dist... if we are
00655       // and the reading is a good one we'll check the cumulative
00656       // buffer
00657       if (squaredNearDist > 0.0000001)
00658       {
00659     // see where the last reading was
00660     squaredDist = (x-lastX)*(x-lastX) + (y-lastY)*(y-lastY);
00661     // see if the reading is far enough from the last reading
00662     if (squaredDist > squaredNearDist)      // moved enough
00663     {
00664       lastX = x;
00665       lastY = y;
00666       // since it was a good reading, see if we should toss it in
00667       // the cumulative buffer... 
00668       filterAddAndCleanCumulative(x, y, clean);
00669 
00670       /* we don't do this part anymore since it wound up leaving
00671       // too many things not really tehre... if its outside of our
00672       // sensor angle to use to filter then don't let this one
00673       // clean  (ArMath::fabs(sReading->getSensorTh()) > 50)
00674       // filterAddAndCleanCumulative(x, y, false); else*/
00675     }
00676     // it wasn't far enough, skip this one and go to the next one
00677     else
00678     {
00679       continue;     
00680     }
00681       }
00682       // we weren't filtering the readings, but see if it goes in the
00683       // cumulative buffer anyways
00684       else
00685       {
00686     filterAddAndCleanCumulative(x, y, clean);
00687       }
00688       // now drop the reading into the current buffer
00689       myCurrentBuffer.redoReading(x, y);
00690       i++;
00691     }
00692   }
00693   myCurrentBuffer.endRedoBuffer();
00694   /*  Put this in to see how long the cumulative filtering is taking  
00695   if (clean)
00696     printf("### %ld %d\n", len.mSecSince(), myCumulativeBuffer.getBuffer()->size());
00697     */
00698   
00699 }
00700 
00702 void ArSick::filterAddAndCleanCumulative(double x, double y, bool clean)
00703 {
00704   if (myCumulativeBuffer.getSize() == 0)
00705     return;
00706 
00707 
00708   std::list<ArPoseWithTime *>::iterator cit;
00709   bool addReading = true;
00710   double squaredDist;
00711 
00712   ArLineSegment line;
00713   double xTaken = myCurrentBuffer.getPoseTaken().getX();
00714   double yTaken = myCurrentBuffer.getPoseTaken().getY();
00715   ArPose intersection;
00716   ArPoseWithTime reading(x, y);
00717 
00718   // make sure we really want to clean
00719   if (clean && myFilterSquaredCumulativeCleanDist < 1)
00720     clean = false;
00721 
00722   squaredDist = ArMath::squaredDistanceBetween(x, y, xTaken, yTaken);
00723   // if we're not cleaning and its further than we're keeping track of
00724   // readings ignore it
00725   if (!clean && 
00726       myFilterSquaredCumulativeInsertMaxDist > 1 && 
00727       squaredDist > myFilterSquaredCumulativeInsertMaxDist)
00728     return;
00729   
00730   // if we're cleaning we start our sweep
00731   if (clean)
00732     myCumulativeBuffer.beginInvalidationSweep();
00733   // run through all the readings
00734   for (cit = getCumulativeBuffer()->begin(); 
00735        cit != getCumulativeBuffer()->end(); 
00736        ++cit)
00737   {
00738     // if its closer to a reading than the filter near dist, just return
00739     if (myFilterSquaredCumulativeNearDist < .0000001 ||
00740     (ArMath::squaredDistanceBetween(x, y, (*cit)->getX(), (*cit)->getY()) <
00741      myFilterSquaredCumulativeNearDist))
00742     {
00743       // if we're not cleaning it and its too close just return,
00744       // otherwise keep going (to clear out invalid readings)
00745       if (!clean)
00746     return;
00747       addReading = false;
00748     }
00749     // see if this reading invalidates some other readings by coming too close
00750     if (clean)
00751     {
00752       // set up our line
00753       line.newEndPoints(x, y, xTaken, yTaken);
00754       // see if the cumulative buffer reading perpindicular intersects
00755       // this line segment, and then see if its too close if it does
00756       if (line.getPerpPoint((*cit), &intersection) &&
00757       (intersection.squaredFindDistanceTo(*(*cit)) < 
00758                                    myFilterSquaredCumulativeCleanDist) &&
00759       (intersection.squaredFindDistanceTo(reading) > 50 * 50))
00760       {
00761     //printf("Found one too close to the line\n");
00762     myCumulativeBuffer.invalidateReading(cit);
00763       }
00764     }
00765   }
00766   // if we're cleaning finish the sweep
00767   if (clean)
00768     myCumulativeBuffer.endInvalidationSweep();
00769   // toss the reading in
00770   if (addReading)
00771     myCumulativeBuffer.addReading(x, y);
00772 
00773 }
00774 
00776 AREXPORT void ArSick::switchState(State state)
00777 {
00778   myStateMutex.lock();
00779   myState = state;
00780   myStateStart.setToNow();
00781   myStateMutex.unlock();
00782 }
00783 
00788 AREXPORT int ArSick::internalConnectHandler(void)
00789 {
00790   ArSickPacket *packet;
00791   ArSerialConnection *conn;
00792   int value;
00793 
00794   switch (myState)
00795   {
00796   case STATE_INIT:
00797     if (myConn->getStatus() != ArDeviceConnection::STATUS_OPEN)
00798     {
00799       if ((conn = dynamic_cast<ArSerialConnection *>(myConn)) != NULL)
00800       {
00801     conn->setBaud(9600);
00802       }
00803       if (!myConn->openSimple())
00804       {
00805     ArLog::log(ArLog::Terse,
00806            "ArSick: Failed to connect to laser, could not open port.");
00807     switchState(STATE_NONE);
00808     failedConnect();
00809     return 2;
00810       }
00811     }
00812     if (!myPowerControl)
00813     {
00814       /*
00815       myPacket.empty();
00816       myPacket.uByteToBuf(0x20);
00817       myPacket.uByteToBuf(0x25);
00818       myPacket.finalizePacket();
00819       myConn->write(myPacket.getBuf(), myPacket.getLength());
00820       */
00821       switchState(STATE_CHANGE_BAUD);
00822       return internalConnectHandler();
00823     }
00824     ArLog::log(ArLog::Terse, "ArSick: waiting for laser to power on.");
00825     myPacket.empty();
00826     myPacket.uByteToBuf(0x10);
00827     myPacket.finalizePacket();
00828     if (myConn->write(myPacket.getBuf(), myPacket.getLength()))
00829     {
00830       switchState(STATE_WAIT_FOR_POWER_ON);
00831       return 0;
00832     }
00833     else
00834     {
00835       ArLog::log(ArLog::Terse,
00836          "ArSick: Failed to connect to laser, could not send init.");
00837       switchState(STATE_NONE);
00838       failedConnect();
00839       return 2;
00840     }
00841     break;
00842   case STATE_WAIT_FOR_POWER_ON:
00843     while ((packet = mySickPacketReceiver.receivePacket()) != NULL)
00844     {
00845       if (packet->getID() == 0x90)
00846       {
00847     switchState(STATE_CHANGE_BAUD);
00848     return 0;
00849       }
00850     }
00851     if (myStateStart.secSince() > 65)
00852     {
00853       ArLog::log(ArLog::Terse,
00854          "ArSick: Failed to connect to laser, no poweron received.");
00855       switchState(STATE_NONE);
00856       failedConnect();
00857       return 2;
00858     }
00859     break;
00860   case STATE_CHANGE_BAUD:
00861     myPacket.empty();
00862     myPacket.byteToBuf(0x20);
00863     if (myBaud == BAUD9600)
00864       myPacket.byteToBuf(0x42);
00865     else if (myBaud == BAUD19200)
00866       myPacket.byteToBuf(0x41);
00867     else if (myBaud == BAUD38400)
00868       myPacket.byteToBuf(0x40);
00869     myPacket.finalizePacket();
00870     if (myConn->write(myPacket.getBuf(), myPacket.getLength()))
00871     {
00872       ArUtil::sleep(20);
00873       if ((conn = dynamic_cast<ArSerialConnection *>(myConn)))
00874       {
00875     if (myBaud == BAUD9600)
00876       conn->setBaud(9600);
00877     else if (myBaud == BAUD19200)
00878       conn->setBaud(19200);
00879     else if (myBaud == BAUD38400)
00880       conn->setBaud(38400);
00881       }
00882       switchState(STATE_CONFIGURE);
00883       return 0;
00884     }
00885     else
00886     {
00887       ArLog::log(ArLog::Terse,
00888          "ArSick: Failed to connect to laser, could not send baud command.");
00889       switchState(STATE_NONE);
00890       failedConnect();
00891       return 2;
00892     }
00893     break;
00894   case STATE_CONFIGURE:
00895     // wait at least a 100 ms for the baud to change
00896     if (myStateStart.mSecSince() < 300)
00897       return 0;
00898     myPacket.empty();
00899     myPacket.byteToBuf(0x3b);
00900     myPacket.uByte2ToBuf(abs(ArMath::roundInt(myOffsetAmount * 2)));
00901     myPacket.uByte2ToBuf(abs(ArMath::roundInt(myIncrementAmount * 100)));
00902     myPacket.finalizePacket();
00903     if (myConn->write(myPacket.getBuf(), myPacket.getLength()))
00904     {
00905       switchState(STATE_WAIT_FOR_CONFIGURE_ACK);
00906       return 0;
00907     }
00908     else
00909     {
00910       ArLog::log(ArLog::Terse,
00911          "ArSick: Failed to connect to laser, could not send configure command.");
00912       switchState(STATE_NONE);
00913       failedConnect();
00914       return 2;
00915     }
00916     break;
00917   case STATE_WAIT_FOR_CONFIGURE_ACK:
00918     while ((packet = mySickPacketReceiver.receivePacket()) != NULL)
00919     {
00920       if (packet->getID() == 0xbb)
00921       {
00922     value = packet->bufToByte();
00923     if (value == 0)
00924     {
00925       ArLog::log(ArLog::Terse, 
00926              "ArSick: Could not configure laser, failed connect.");
00927       switchState(STATE_NONE);
00928       failedConnect();
00929       return 2;
00930     }
00931     else if (value == 1)
00932     {
00933       // here
00934       //switchState(STATE_START_READINGS);
00935       switchState(STATE_INSTALL_MODE);
00936       return 0;
00937     }
00938     else
00939     {
00940       ArLog::log(ArLog::Terse, 
00941              "ArSick: Could not configure laser, failed connect.");
00942       switchState(STATE_NONE);
00943       failedConnect();
00944       return 2;
00945     }
00946       }
00947       else if (packet->getID() == 0xb0)
00948       {
00949 
00950     ArLog::log(ArLog::Terse, "ArSick: extra data packet while waiting for configure ack");
00951     myPacket.empty();
00952     myPacket.uByteToBuf(0x20);
00953     myPacket.uByteToBuf(0x25);
00954     myPacket.finalizePacket();
00955     if (myConn->write(myPacket.getBuf(), myPacket.getLength()))
00956     {
00957       switchState(STATE_CONFIGURE);
00958       return 0;
00959     }
00960       }
00961       else
00962     ArLog::log(ArLog::Terse, "ArSick: Got a 0x%x\n", packet->getID());
00963     }
00964     if (myStateStart.mSecSince() > 10000)
00965     {
00966       ArLog::log(ArLog::Terse,
00967          "ArSick: Failed to connect to laser, no configure acknowledgement received.");
00968       switchState(STATE_NONE);
00969       failedConnect();
00970       return 2;
00971     }
00972     break;
00973   case STATE_INSTALL_MODE:
00974     if (myStateStart.mSecSince() < 200)
00975       return 0;
00976     myPacket.empty();
00977     myPacket.byteToBuf(0x20);
00978     myPacket.byteToBuf(0x00);
00979     myPacket.strNToBuf("SICK_LMS", strlen("SICK_LMS"));
00980     myPacket.finalizePacket();
00981     if (myConn->write(myPacket.getBuf(), myPacket.getLength()))
00982     {
00983       switchState(STATE_WAIT_FOR_INSTALL_MODE_ACK);
00984       return 0;
00985     }
00986     else
00987     {
00988       ArLog::log(ArLog::Terse,
00989          "ArSick: Failed to connect to laser, could not send start command.");
00990       switchState(STATE_NONE);
00991       failedConnect();
00992       return 2;
00993     }
00994     break;
00995   case STATE_WAIT_FOR_INSTALL_MODE_ACK:
00996     while ((packet = mySickPacketReceiver.receivePacket()) != NULL)
00997     {
00998       if (packet->getID() == 0xa0)
00999       {
01000     value = packet->bufToByte();
01001     if (value == 0)
01002     {
01003       //printf("Um, should set mode?\n");
01004       switchState(STATE_SET_MODE);
01005       return 0;
01006     }
01007     else if (value == 1)
01008     {
01009       ArLog::log(ArLog::Terse, 
01010              "ArSick: Could not start laser, incorrect password.");
01011       switchState(STATE_NONE);
01012       failedConnect();
01013       return 2;
01014     }
01015     else if (value == 2)
01016     {
01017       ArLog::log(ArLog::Terse, 
01018              "ArSick: Could not start laser, LMI fault.");
01019       switchState(STATE_NONE);
01020       failedConnect();
01021       return 2;
01022     }
01023     else
01024     {
01025       ArLog::log(ArLog::Terse, 
01026              "ArSick: Could not start laser, unknown problem.");
01027       switchState(STATE_NONE);
01028       failedConnect();
01029       return 2;
01030     }
01031       }
01032       else if (packet->getID() == 0xb0)
01033       {
01034     
01035     ArLog::log(ArLog::Terse, "ArSick: extra data packet\n");
01036     myPacket.empty();
01037     myPacket.uByteToBuf(0x20);
01038     myPacket.uByteToBuf(0x25);
01039     myPacket.finalizePacket();
01040     if (myConn->write(myPacket.getBuf(), myPacket.getLength()))
01041     {
01042       switchState(STATE_INSTALL_MODE);
01043       return 0;
01044     }
01045       }
01046       else
01047     ArLog::log(ArLog::Terse, "ArSick: bad packet 0x%x\n", packet->getID());
01048     }
01049     if (myStateStart.mSecSince() > 10000)
01050     {
01051       ArLog::log(ArLog::Terse,
01052          "ArSick: Failed to connect to laser, no install mode ack received.");
01053       switchState(STATE_NONE);
01054       return 2;
01055     }
01056     break;
01057   case STATE_SET_MODE:
01058     if (myStateStart.mSecSince() < 200)
01059       return 0;
01060     myPacket.empty();
01061     // type of packet
01062     myPacket.byteToBuf(0x77);
01063     // blanking
01064     myPacket.uByte2ToBuf(0);
01065     // peak threshhold, stop threshold
01066     myPacket.uByte2ToBuf(70);
01067     // the old peak threshhold thats probably broken
01068     // myPacket.uByte2ToBuf(0);
01069     // fog correction
01070     myPacket.uByteToBuf(0);
01071     // measurement Mode (fun one) (we can switch this now)
01072     // next line was the previous permanent one
01073     // myPacket.uByteToBuf(6);
01074     int maxRange;
01075     maxRange = 8;
01076     if (myBits == BITS_1REFLECTOR)
01077     {
01078       myPacket.uByteToBuf(5);
01079       maxRange *= 4;
01080     }
01081     else if (myBits == BITS_2REFLECTOR)
01082     {
01083       myPacket.uByteToBuf(3);
01084       maxRange *= 2;
01085     }
01086     else if (myBits == BITS_3REFLECTOR)
01087     {
01088       myPacket.uByteToBuf(1);
01089       maxRange *= 1;
01090     }
01091     else
01092     {
01093       ArLog::log(ArLog::Terse, "ArSick: Bits set to unknown value");
01094       myPacket.uByteToBuf(5);
01095       maxRange *= 4;
01096     }
01097     // unit value (fun one), we can swithc this now
01098     // next line was the previous permanent one
01099     //myPacket.uByteToBuf(1);
01100     if (myUnits == UNITS_1MM)
01101     {
01102       maxRange *= 1000;
01103       myPacket.uByteToBuf(1);
01104     }
01105     else if (myUnits == UNITS_10CM)
01106     {
01107       maxRange = 150000;
01108       myPacket.uByteToBuf(2);
01109     }
01110     else if (myUnits == UNITS_1CM)
01111     {
01112       maxRange *= 10000;
01113       myPacket.uByteToBuf(0);
01114     }
01115     else
01116     {
01117       ArLog::log(ArLog::Terse, "ArSick: Units set to unknown value");
01118       maxRange *= 1000;
01119       myPacket.uByteToBuf(1);
01120     }
01121     setMaxRange(maxRange);
01122     // temporary field set
01123     myPacket.uByteToBuf(0);
01124     // fields A & B as subtractive
01125     myPacket.uByteToBuf(0);
01126     // multiple evaluation
01127     myPacket.uByteToBuf(2);
01128     // restart
01129     myPacket.uByteToBuf(2);
01130     // restart time
01131     myPacket.uByteToBuf(0);
01132     // contour A as reference object size
01133     myPacket.uByteToBuf(0);
01134     // contour A positive range of tolerance
01135     myPacket.uByteToBuf(0);
01136     // contour A negative range of tolerance
01137     myPacket.uByteToBuf(0);
01138     // contour A starting angle
01139     myPacket.uByteToBuf(0);
01140     // contour A stopping angle
01141     myPacket.uByteToBuf(0);
01142     // contour B as reference object size
01143     myPacket.uByteToBuf(0);
01144     // contour B positive range of tolerance
01145     myPacket.uByteToBuf(0);
01146     // contour B negative range of tolerance
01147     myPacket.uByteToBuf(0);
01148     // contour B starting angle
01149     myPacket.uByteToBuf(0);
01150     // contour B stopping angle
01151     myPacket.uByteToBuf(0);
01152     // contour C as reference object size
01153     myPacket.uByteToBuf(0);
01154     // contour C positive range of tolerance
01155     myPacket.uByteToBuf(0);
01156     // contour C negative range of tolerance
01157     myPacket.uByteToBuf(0);
01158     // contour C starting angle
01159     myPacket.uByteToBuf(0);
01160     // contour C stopping angle
01161     myPacket.uByteToBuf(0);
01162     // pixel oriented evaluation
01163     myPacket.uByteToBuf(0);
01164     // mode for single meas value eval
01165     myPacket.uByteToBuf(0);
01166     // restart times for field b and field c
01167     myPacket.byte2ToBuf(0);
01168     // um, an extra one (sick quickstart manual says its 21 not 20 long)
01169     myPacket.uByteToBuf(0);
01170     
01171     myPacket.finalizePacket();
01172     //myPacket.log();
01173     //printf("Sending mode!\n");
01174     if (myConn->write(myPacket.getBuf(), myPacket.getLength()))
01175     {
01176       //printf("Set mode!\n");
01177       switchState(STATE_WAIT_FOR_SET_MODE_ACK);
01178       return 0;
01179     }
01180     else
01181     {
01182       ArLog::log(ArLog::Terse,
01183          "ArSick: Failed to connect to laser, could not send set mode command.");
01184       switchState(STATE_NONE);
01185       failedConnect();
01186       return 2;
01187     }
01188     break;
01189   case STATE_WAIT_FOR_SET_MODE_ACK:
01190     while ((packet = mySickPacketReceiver.receivePacket()) != NULL)
01191     {
01192       if (packet->getID() == 0xF7)
01193       {
01194     //value = packet->bufToByte();
01195     //printf("YAY %d\n", value);
01196     //packet->log();
01197     switchState(STATE_START_READINGS);
01198     return 0;
01199       }
01200       else if (packet->getID() == 0xb0)
01201       {
01202     
01203     ArLog::log(ArLog::Terse, "ArSick: extra data packet\n");
01204     myPacket.empty();
01205     myPacket.uByteToBuf(0x20);
01206     myPacket.uByteToBuf(0x25);
01207     myPacket.finalizePacket();
01208     if (myConn->write(myPacket.getBuf(), myPacket.getLength()))
01209     {
01210       switchState(STATE_INSTALL_MODE);
01211       return 0;
01212     }
01213       }
01214       else if (packet->getID() == 0x92)
01215       {
01216     switchState(STATE_INSTALL_MODE);
01217     return 0;
01218       }
01219       else
01220     ArLog::log(ArLog::Terse, "ArSick: Got a 0x%x\n", packet->getID());
01221     }
01222     if (myStateStart.mSecSince() > 14000)
01223     {
01224       ArLog::log(ArLog::Terse,
01225          "ArSick: Failed to connect to laser, no set mode acknowledgement received.");
01226       switchState(STATE_NONE);
01227       failedConnect();
01228       return 2;
01229     }
01230     break;
01231     case STATE_START_READINGS: 
01232       if (myStateStart.mSecSince() < 200)
01233       return 0;
01234     myPacket.empty();
01235     myPacket.byteToBuf(0x20);
01236     myPacket.byteToBuf(0x24);
01237     myPacket.finalizePacket();
01238     if (myConn->write(myPacket.getBuf(), myPacket.getLength()))
01239     {
01240       switchState(STATE_WAIT_FOR_START_ACK);
01241       return 0;
01242     }
01243     else
01244     {
01245       ArLog::log(ArLog::Terse,
01246          "ArSick: Failed to connect to laser, could not send start command.");
01247       switchState(STATE_NONE);
01248       failedConnect();
01249       return 2;
01250     }
01251     break;
01252   case STATE_WAIT_FOR_START_ACK:
01253     while ((packet = mySickPacketReceiver.receivePacket()) != NULL)
01254     {
01255       if (packet->getID() == 0xa0)
01256       {
01257     value = packet->bufToByte();
01258     if (value == 0)
01259     {
01260       ArLog::log(ArLog::Terse, "ArSick: Connected to the laser.");
01261       switchState(STATE_CONNECTED);
01262       madeConnection();
01263       return 1;
01264     }
01265     else if (value == 1)
01266     {
01267       ArLog::log(ArLog::Terse, 
01268          "ArSick: Could not start laser laser, incorrect password.");
01269       switchState(STATE_NONE);
01270       failedConnect();
01271       return 2;
01272     }
01273     else if (value == 2)
01274     {
01275       ArLog::log(ArLog::Terse, 
01276              "ArSick: Could not start laser laser, LMI fault.");
01277       switchState(STATE_NONE);
01278       failedConnect();
01279       return 2;
01280     }
01281     else
01282     {
01283       ArLog::log(ArLog::Terse, 
01284              "ArSick: Could not start laser laser, unknown problem.");
01285       switchState(STATE_NONE);
01286       failedConnect();
01287       return 2;
01288     }
01289       }
01290     }
01291     if (myStateStart.mSecSince() > 1000)
01292     {
01293       ArLog::log(ArLog::Terse,
01294          "ArSick: Failed to connect to laser, no start acknowledgement received.");
01295       switchState(STATE_NONE);
01296       failedConnect();
01297       return 2;
01298     }
01299     break;
01300   default:
01301     ArLog::log(ArLog::Verbose, "ArSick: In bad connection state\n");
01302     break;
01303   }
01304   return 0;
01305 }
01306 
01312 AREXPORT bool ArSick::internalConnectSim(void)
01313 {
01314   lockDevice();
01315   double offset = myOffsetAmount;
01316   double increment = myIncrementAmount;
01317   unlockDevice();
01318 
01319   myRobot->lock();
01320   // return true if we could send all the commands
01321   if (myRobot->comInt(36, -ArMath::roundInt(offset)) &&   // Start angle
01322       myRobot->comInt(37, ArMath::roundInt(offset)) &&    // End angle
01323       myRobot->comInt(38, ArMath::roundInt(increment * 100.0)) && // increment
01324       myRobot->comInt(35, 2)) // Enable sending data, with extended info 
01326   {
01327     myRobot->unlock();
01328     switchState(STATE_CONNECTED);
01329     madeConnection();
01330     ArLog::log(ArLog::Terse, "ArSick: Connected to simulated laser.");
01331     return true;
01332   }
01333   else
01334   {
01335     switchState(STATE_NONE);
01336     failedConnect();
01337     ArLog::log(ArLog::Terse, 
01338            "ArSick: Failed to connect to simulated laser.");
01339     return false;
01340   }
01341 }
01342 
01354 AREXPORT void ArSick::addConnectCB(ArFunctor *functor, 
01355                     ArListPos::Pos position)
01356 {
01357   if (position == ArListPos::FIRST)
01358     myConnectCBList.push_front(functor);
01359   else if (position == ArListPos::LAST)
01360     myConnectCBList.push_back(functor);
01361   else
01362     ArLog::log(ArLog::Terse, 
01363            "ArSick::myConnectCallbackList: Invalid position.");
01364 }
01365 
01370 AREXPORT void ArSick::remConnectCB(ArFunctor *functor)
01371 {
01372   myConnectCBList.remove(functor);
01373 }
01374 
01375 
01388 AREXPORT void ArSick::addFailedConnectCB(ArFunctor *functor, 
01389                       ArListPos::Pos position)
01390 {
01391   if (position == ArListPos::FIRST)
01392     myFailedConnectCBList.push_front(functor);
01393   else if (position == ArListPos::LAST)
01394     myFailedConnectCBList.push_back(functor);
01395   else
01396     ArLog::log(ArLog::Terse, 
01397            "ArSick::myConnectCallbackList: Invalid position.");
01398 }
01399 
01404 AREXPORT void ArSick::remFailedConnectCB(ArFunctor *functor)
01405 {
01406   myFailedConnectCBList.remove(functor);
01407 }
01408 
01422 AREXPORT void ArSick::addDisconnectNormallyCB(ArFunctor *functor, 
01423                            ArListPos::Pos position)
01424 {
01425   if (position == ArListPos::FIRST)
01426     myDisconnectNormallyCBList.push_front(functor);
01427   else if (position == ArListPos::LAST)
01428     myDisconnectNormallyCBList.push_back(functor);
01429   else
01430     ArLog::log(ArLog::Terse, 
01431            "ArSick::myConnectCallbackList: Invalid position.");
01432 }
01433 
01438 AREXPORT void ArSick::remDisconnectNormallyCB(ArFunctor *functor)
01439 {
01440   myDisconnectNormallyCBList.remove(functor);
01441 }
01442 
01459 AREXPORT void ArSick::addDisconnectOnErrorCB(ArFunctor *functor, 
01460                           ArListPos::Pos position)
01461 {
01462   if (position == ArListPos::FIRST)
01463     myDisconnectOnErrorCBList.push_front(functor);
01464   else if (position == ArListPos::LAST)
01465     myDisconnectOnErrorCBList.push_back(functor);
01466   else
01467     ArLog::log(ArLog::Terse, 
01468            "ArSick::myConnectCallbackList: Invalid position");
01469 }
01470 
01475 AREXPORT void ArSick::remDisconnectOnErrorCB(ArFunctor *functor)
01476 {
01477   myDisconnectOnErrorCBList.remove(functor);
01478 }
01479 
01490 AREXPORT void ArSick::addDataCB(ArFunctor *functor, 
01491                     ArListPos::Pos position)
01492 {
01493   if (position == ArListPos::FIRST)
01494     myDataCBList.push_front(functor);
01495   else if (position == ArListPos::LAST)
01496     myDataCBList.push_back(functor);
01497   else
01498     ArLog::log(ArLog::Terse, 
01499            "ArSick::addDataCB: Invalid position.");
01500 }
01501 
01506 AREXPORT void ArSick::remDataCB(ArFunctor *functor)
01507 {
01508   myDataCBList.remove(functor);
01509 }
01510 
01512 AREXPORT void ArSick::dropConnection(void)
01513 {
01514   std::list<ArFunctor *>::iterator it;  
01515 
01516   if (myState != STATE_CONNECTED)
01517     return;
01518 
01519   myCurrentBuffer.reset();
01520   myCumulativeBuffer.reset();
01521   ArLog::log(ArLog::Terse, 
01522          "ArSick:  Lost connection to the laser because of error.");
01523   switchState(STATE_NONE);
01524   for (it = myDisconnectOnErrorCBList.begin(); 
01525        it != myDisconnectOnErrorCBList.end(); 
01526        it++)
01527     (*it)->invoke();
01528   if (myConn != NULL)
01529     myConn->close();
01530 }
01531 
01533 AREXPORT void ArSick::failedConnect(void)
01534 {
01535   std::list<ArFunctor *>::iterator it;  
01536   
01537   switchState(STATE_NONE);
01538   for (it = myFailedConnectCBList.begin(); 
01539        it != myFailedConnectCBList.end(); 
01540        it++)
01541     (*it)->invoke();
01542   if (myConn != NULL)
01543     myConn->close();
01544 }
01545 
01547 AREXPORT void ArSick::madeConnection(void)
01548 {
01549   std::list<ArFunctor *>::iterator it;
01550 
01551   myLastReading.setToNow();
01552   for (it = myConnectCBList.begin(); it != myConnectCBList.end(); it++)
01553     (*it)->invoke();
01554 }
01555 
01569 AREXPORT bool ArSick::disconnect(bool doNotLockRobotForSim)
01570 {
01571   std::list<ArFunctor *>::iterator it;  
01572   bool ret;
01573   ArSerialConnection *conn;
01574 
01575   myStateMutex.lock();
01576   if (myState == STATE_NONE)
01577   {
01578     myStateMutex.unlock();
01579     return true;
01580   }
01581     
01582   if (myState != STATE_CONNECTED)
01583   {
01584     lockDevice();
01585     myConnLock.lock();
01586     myState = STATE_NONE;
01587     ret = myConn->close();
01588     myConnLock.unlock();
01589     unlockDevice();
01590     ArLog::log(ArLog::Terse, "ArSick: Disconnecting from laser that was not fully connected to...");
01591     ArLog::log(ArLog::Terse, "this may cause problems later.");
01592     myStateMutex.unlock();
01593     return ret;
01594   }
01595 
01596   myCurrentBuffer.reset();
01597   myCumulativeBuffer.reset();
01598   ArLog::log(ArLog::Terse, "ArSick: Disconnecting from laser.");
01599   myState = STATE_NONE;
01600   myStateMutex.unlock();
01601   for (it = myDisconnectNormallyCBList.begin(); 
01602        it != myDisconnectNormallyCBList.end(); 
01603        it++)
01604     (*it)->invoke();
01605   if (myUseSim)
01606   {
01607     if (myRobot == NULL)
01608       return false;
01609     if (!doNotLockRobotForSim)
01610       myRobot->lock();
01611     ret = myRobot->comInt(35, 2); // 2=extendend info request
01613     if (!doNotLockRobotForSim)
01614       myRobot->unlock();
01615     return ret;
01616   }
01617   else
01618   {
01619     myConnLock.lock();
01620     while (mySickPacketReceiver.receivePacket() != NULL);
01621     myPacket.empty();
01622     myPacket.uByteToBuf(0x20);
01623     myPacket.uByteToBuf(0x25);
01624     myPacket.finalizePacket();
01625     ret = myConn->write(myPacket.getBuf(), myPacket.getLength());
01626     // put the thing back to 9600 baud
01627     ArUtil::sleep(1000);
01628     myPacket.empty();
01629     myPacket.byteToBuf(0x20);
01630     myPacket.byteToBuf(0x42);
01631     myPacket.finalizePacket();
01632     if (myConn->write(myPacket.getBuf(), myPacket.getLength()))
01633     {
01634       ArUtil::sleep(20);
01635       if ((conn = dynamic_cast<ArSerialConnection *>(myConn)))
01636       conn->setBaud(9600);
01637     } else
01638       ret = false;
01639     ret = ret && myConn->close();
01640     myConnLock.unlock();
01641     ArUtil::sleep(300);
01642     return ret;
01643   }
01644 }
01645 
01666 AREXPORT bool ArSick::blockingConnect(void)
01667 {
01668   int ret;
01669   // if we're using the sim
01670   if (myUseSim)
01671   {
01672     return internalConnectSim();
01673   }
01674   // if we're talking to a real laser
01675   else 
01676   {
01677     if (myConn == NULL)
01678     {
01679       ArLog::log(ArLog::Terse, "ArSick: Invalid device connection, cannot connect.");
01680       return false; // Nobody ever set the device connection.
01681     }
01682 
01683     lockDevice();
01684     myConnLock.lock();
01685     switchState(STATE_INIT);
01686     unlockDevice();
01687     while (getRunningWithLock() && (ret = internalConnectHandler()) == 0)
01688       ArUtil::sleep(100);
01689     myConnLock.unlock();
01690     if (ret == 1)
01691       return true;
01692     else 
01693       return false;
01694   }
01695   return false;
01696 }
01697 
01714 AREXPORT bool ArSick::asyncConnect(void)
01715 {
01716   if (myState == STATE_CONNECTED)
01717   {
01718     ArLog::log(ArLog::Terse,"ArSick: already connected to laser.");
01719     return false;
01720   }
01721   if (myUseSim || getRunning() || myRunningOnRobot)
01722   {
01723     myStartConnect = true;
01724     return true;
01725   } 
01726   else
01727   {
01728     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.");
01729     return false;
01730   }
01731 }
01732 
01741 AREXPORT bool ArSick::runOnRobot(void)
01742 {
01743   if (myRobot == NULL)
01744     return false;
01745   else
01746   {  
01747     myRunningOnRobot = true;
01748     if (getRunning())
01749       stopRunning();
01750     return true;
01751   }
01752 }
01753 
01755 AREXPORT void ArSick::processPacket(ArSickPacket *packet, ArPose pose,
01756                     ArPose encoderPose,
01757                     unsigned int counter,
01758                     bool deinterlace,
01759                     ArPose deinterlaceDelta)
01760 {
01761   std::list<ArFunctor *>::iterator it;  
01762   unsigned int rawValue;
01763   unsigned int value;
01764   unsigned int reflector = 0;
01765   unsigned int numReadings;
01766   unsigned int i;
01767   double atDeg;
01768   unsigned int onReading;
01769   ArSensorReading *reading;
01770   int dist;
01771   std::list<ArSensorReading *>::iterator tempIt;
01772   int multiplier;
01773   ArTransform transform;
01774   std::list<double>::iterator ignoreIt;  
01775   bool ignore;
01776 
01777   ArTime arTime;
01778   arTime = packet->getTimeReceived();
01779   arTime.addMSec(-13);
01780 
01781   ArTime deinterlaceTime;
01782   deinterlaceTime = packet->getTimeReceived();
01783   deinterlaceTime.addMSec(-27);
01784   
01785   //if (packet->getID() != 0xb0)
01786   //printf("Got in packet of type 0x%x\n", packet->getID());
01787   if (packet->getID() == 0xb0)
01788   {
01789     value = packet->bufToUByte2();
01790     numReadings = value & 0x3ff;
01791     //printf("numreadings %d\n", numReadings);
01792     if (!(value & ArUtil::BIT14) && !(value & ArUtil::BIT15))
01793       multiplier = 10;
01794     else if ((value & ArUtil::BIT14) && !(value & ArUtil::BIT15))
01795       multiplier = 1;
01796     else if (!(value & ArUtil::BIT14) && (value & ArUtil::BIT15))
01797       multiplier = 100;
01798     else
01799     {
01800       ArLog::log(ArLog::Terse, 
01801          "ArSick::processPacket: bad distance configuration in packet\n");
01802       multiplier = 0;
01803     }
01804     //printf("%ld ms after last reading.\n", myLastReading.mSecSince());
01805     /*printf("Reading number %d, complete %d, unit: %d %d:\n", numReadings,
01806       !(bool)(value & ArUtil::BIT13), (bool)(value & ArUtil::BIT14),
01807       (bool)(value & ArUtil::BIT15));*/
01808     while (myAssembleReadings->size() > numReadings)
01809     {
01810       ArLog::log(ArLog::Verbose, "ArSick::processPacket, too many readings, popping one.\n");
01811       tempIt = myAssembleReadings->begin();
01812       if (tempIt != myAssembleReadings->end())
01813     delete (*tempIt);
01814       myAssembleReadings->pop_front();
01815     }
01816     
01817     // If we don't have any sensor readings created at all, make 'em all 
01818     if (myAssembleReadings->size() == 0)
01819       for (i = 0; i < numReadings; i++)
01820     myAssembleReadings->push_back(new ArSensorReading);
01821 
01822     transform.setTransform(pose);
01823     //deinterlaceDelta = transform.doInvTransform(deinterlacePose);
01824     // printf("usePose2 %d, th1 %.0f th2 %.0f\n",  usePose2, pose.getTh(), pose2.getTh());
01825     for (atDeg = mySensorPose.getTh() - myOffsetAmount, onReading = 0,
01826      myIter = myAssembleReadings->begin();
01827      (onReading < numReadings && 
01828       packet->getReadLength() < packet->getLength() - 4);
01829      myWhichReading++, atDeg += myIncrementAmount, myIter++, onReading++)
01830     {
01831       reading = (*myIter);
01832       //reading->resetSensorPosition(0, 0, 0);
01833 
01834       //value = packet->bufToUByte2() & 0x1fff;
01835       //dist = (value & 0x1fff) * multiplier ;
01836 
01837       rawValue = packet->bufToUByte2();
01838       if (myBits == BITS_1REFLECTOR)
01839       {
01840     dist = (rawValue & 0x7fff) * multiplier;
01841     reflector = ((rawValue & 0x8000) >> 15) << 2;
01842       }
01843       else if (myBits == BITS_2REFLECTOR)
01844       {
01845     dist = (rawValue & 0x3fff) * multiplier;
01846     reflector = ((rawValue & 0xc000) >> 14) << 1 ;
01847       }
01848       else if (myBits == BITS_3REFLECTOR)
01849       {
01850     dist = (rawValue & 0x1fff) * multiplier;
01851     reflector = ((rawValue & 0xe000) >> 13);
01852       }
01853       // just trap for if we don't know what it is, this shouldn't
01854       // happen though
01855       else
01856       {
01857     dist = (rawValue & 0x7fff) * multiplier;
01858     reflector = 0;
01859       }
01860       // there are 3 reflector bits (its already been normalized above
01861       // to that range) so now we need to shift it another 5 so we get
01862       // 0-255.
01863       reflector = reflector << 5;
01864 
01865       ignore = false;
01866       for (ignoreIt = myIgnoreReadings.begin(); 
01867        ignoreIt != myIgnoreReadings.end();
01868        ignoreIt++)
01869       {
01870     if (ArMath::fabs(ArMath::subAngle(atDeg, *(ignoreIt))) < 1.0)
01871     {
01872       ignore = true;
01873       break;
01874     }
01875       }
01876       if (myMinRange != 0 && dist < (int)myMinRange)
01877     ignore = true;
01878       if (myMaxRange != 0 && dist > (int)myMaxRange)
01879     ignore = true;
01880       if (deinterlace && (onReading % 2) == 0)
01881       {
01882     reading->resetSensorPosition(
01883            ArMath::roundInt(mySensorPose.getX() + deinterlaceDelta.getX()),
01884            ArMath::roundInt(mySensorPose.getY() + deinterlaceDelta.getY()),
01885            ArMath::addAngle(atDeg, deinterlaceDelta.getTh()));
01886     reading->newData(dist, pose, encoderPose, transform, counter, 
01887              deinterlaceTime, ignore, reflector);
01888       }
01889       else
01890       {
01891     reading->resetSensorPosition(ArMath::roundInt(mySensorPose.getX()),
01892                      ArMath::roundInt(mySensorPose.getY()),
01893                      atDeg); 
01894     reading->newData(dist, pose, encoderPose, transform, counter, 
01895              arTime, ignore, reflector);
01896       }
01897       /*
01898       reading->newData(onReading, 0, 0, 0,
01899                ArTransform(), counter, 
01900                packet->getTimeReceived());
01901       */
01902       tempIt = myIter;
01903       tempIt++;
01904       if (tempIt == myAssembleReadings->end() && 
01905       onReading + 1 != numReadings)
01906       {
01907     myAssembleReadings->push_back(new ArSensorReading);
01908       }
01909     }
01910     // set ArRangeDevice buffer, switch internal buffers
01911     myRawReadings = myAssembleReadings;
01912     //printf("Readings? 0x%x\n", myRawReadings);
01913     myAssembleReadings = myCurrentReadings;
01914     myCurrentReadings = myRawReadings;
01915     //printf("\n");
01916     myLastReading.setToNow();
01917     filterReadings();
01918     
01919     if (myTimeLastSickPacket != time(NULL)) 
01920     {
01921       myTimeLastSickPacket = time(NULL);
01922       mySickPacCount = mySickPacCurrentCount;
01923       mySickPacCurrentCount = 0;
01924     }
01925     mySickPacCurrentCount++;
01926     for (it = myDataCBList.begin(); it != myDataCBList.end(); it++)
01927       (*it)->invoke();
01928   }
01929 }
01930 
01932 AREXPORT void ArSick::runOnce(bool lockRobot)
01933 {
01934   ArSickPacket *packet;
01935   unsigned int counter;
01936   int ret;
01937   ArTime time;
01938   ArTime time2;
01939   ArPose pose;
01940   ArPose pose2;
01941   ArPose encoderPose;
01942 
01943   if (myProcessImmediately && myRobot != NULL)
01944   {
01945     if (lockRobot)
01946       myRobot->lock();
01947     pose = myRobot->getPose();
01948     counter = myRobot->getCounter();
01949     if (lockRobot)
01950       myRobot->unlock();
01951   }
01952 
01953   lockDevice();
01954   if (myState == STATE_CONNECTED && myTimeoutTime > 0 && 
01955       myLastReading.mSecSince() > myTimeoutTime * 1000)
01956   {
01957     dropConnection();
01958     unlockDevice();
01959     return;
01960   }
01961   if (myUseSim)
01962   {
01963     unlockDevice();
01964     return;
01965   }
01966   if (myState == STATE_CONNECTED)
01967   {
01968     unlockDevice();
01969     myConnLock.lock();
01970     packet = mySickPacketReceiver.receivePacket();
01971     myConnLock.unlock();
01972     lockDevice();
01973     // if we're attached to a robot and have a packet
01974     if (myRobot != NULL && packet != NULL && !myProcessImmediately)
01975     {
01976       myPackets.push_back(packet);
01977     }
01978     else if (myRobot != NULL && packet != NULL && myProcessImmediately)
01979     {
01980       unlockDevice();
01981       if (lockRobot && myInterpolation)
01982     myRobot->lock();
01983       // try to get the interpolated position, if we can't, just use
01984       // the robot's pose
01985       if (myInterpolation && (ret = myRobot->getPoseInterpPosition(
01986           packet->getTimeReceived(), &pose)) < 0)
01987     pose = myRobot->getPose();
01988       // try to get the interpolated encoder position, if we can't,
01989       // just fake it from the robot's pose and the encoder transform
01990       if (myInterpolation && (ret = myRobot->getEncoderPoseInterpPosition(
01991           packet->getTimeReceived(), &encoderPose)) < 0)
01992     encoderPose = myRobot->getEncoderTransform().doInvTransform(pose);
01993       if (lockRobot && myInterpolation)
01994     myRobot->unlock();
01995       lockDevice();
01996       processPacket(packet, pose, encoderPose, counter, false, ArPose());
01997     }
01998     else if (packet != NULL) // if there's no robot
01999     {
02000       processPacket(packet, pose, encoderPose, 0, false, ArPose());
02001       delete packet;
02002     }
02003   }
02004   unlockDevice();
02005   return;
02006 
02007 }
02008 
02009 AREXPORT int ArSick::getSickPacCount()
02010 {
02011   if (myTimeLastSickPacket == time(NULL))
02012     return mySickPacCount;
02013   if (myTimeLastSickPacket == time(NULL) - 1)
02014     return mySickPacCurrentCount;
02015   return 0;
02016 }
02017 
02024 AREXPORT void ArSick::setFilterNearDist(double dist)
02025 {
02026   if (dist >= 0)
02027     myFilterNearDist = dist;
02028   else
02029     ArLog::log(ArLog::Terse, "ArSick::setFilterNearDist given a distance less than 0.\n");
02030 
02031 }
02032 
02039 AREXPORT double ArSick::getFilterNearDist(void)
02040 {
02041   return myFilterNearDist;
02042 }
02043 
02044 
02050 AREXPORT void ArSick::setFilterCumulativeInsertMaxDist(double dist)
02051 {
02052   if (dist >= 0)
02053   {
02054     myFilterCumulativeInsertMaxDist = dist;
02055     myFilterSquaredCumulativeInsertMaxDist = dist * dist;
02056   }
02057   else
02058     ArLog::log(ArLog::Terse, "ArSick::setFilterCumulativeMaxDistDist given a distance less than 0.\n");
02059 }
02060 
02066 AREXPORT double ArSick::getFilterCumulativeInsertMaxDist(void)
02067 {
02068   return myFilterCumulativeInsertMaxDist;
02069 }
02070 
02076 AREXPORT void ArSick::setFilterCumulativeNearDist(double dist)
02077 {
02078   if (dist >= 0)
02079   {
02080     myFilterCumulativeNearDist = dist;
02081     myFilterSquaredCumulativeNearDist = dist * dist;
02082   }
02083   else
02084     ArLog::log(ArLog::Terse, "ArSick::setFilterCumulativeNearDistDist given a distance less than 0.\n");
02085 }
02086 
02092 AREXPORT double ArSick::getFilterCumulativeNearDist(void)
02093 {
02094   return myFilterCumulativeNearDist;
02095 }
02096 
02104 AREXPORT void ArSick::setFilterCumulativeCleanDist(double dist)
02105 {
02106   if (dist >= 0)
02107   {
02108     myFilterCumulativeCleanDist = dist;
02109     myFilterSquaredCumulativeCleanDist = dist * dist;
02110   }
02111   else
02112     ArLog::log(ArLog::Terse, "ArSick::setFilterCumulativeCleanDistDist given a distance less than 0.\n");
02113 }
02114 
02122 AREXPORT double ArSick::getFilterCumulativeCleanDist(void)
02123 {
02124   return myFilterCumulativeCleanDist;
02125 }
02126 
02132 AREXPORT void ArSick::setFilterCleanCumulativeInterval(int milliSeconds)
02133 {
02134   if (milliSeconds >= 0)
02135   {
02136     myFilterCleanCumulativeInterval = milliSeconds;
02137   }
02138   else
02139     ArLog::log(ArLog::Terse, "ArSick::setFilterCleanCumulativeInterval given a time less than 0.\n");
02140 }
02141 
02147 AREXPORT int ArSick::getFilterCleanCumulativeInterval(void)
02148 {
02149   return myFilterCleanCumulativeInterval;
02150 }
02151 
02152 
02153 
02155 AREXPORT void ArSick::sensorInterpCallback(void)
02156 {
02157   std::list<ArSickPacket *>::iterator it;
02158   std::list<ArSickPacket *> processed;
02159   ArSickPacket *packet;
02160   ArTime time;
02161   ArPose pose;
02162   int ret;
02163   int retEncoder;
02164   ArPose encoderPose;
02165   ArPose deinterlaceEncoderPose;
02166   bool deinterlace;
02167   ArTime deinterlaceTime;
02168   ArPose deinterlaceDelta;
02169   
02170   if (myRunningOnRobot)
02171     runOnce(false);
02172 
02173   lockDevice();
02174 
02175   if (myIncrement == INCREMENT_HALF)
02176     adjustRawReadings(true);
02177   else
02178     adjustRawReadings(false);
02179 
02180   for (it = myPackets.begin(); it != myPackets.end(); it++)
02181   {
02182     packet = (*it);
02183     time = packet->getTimeReceived();
02184     time.addMSec(-13);
02185     if ((ret = myRobot->getPoseInterpPosition(time, &pose)) == 1 &&
02186     (retEncoder = 
02187      myRobot->getEncoderPoseInterpPosition(time, &encoderPose)) == 1)
02188     {
02189       deinterlaceTime = packet->getTimeReceived();
02190       deinterlaceTime.addMSec(-27);
02191       
02192       if (myIncrement == INCREMENT_HALF && 
02193       (myRobot->getEncoderPoseInterpPosition(
02194           deinterlaceTime, &deinterlaceEncoderPose)) == 1)
02195     deinterlace = true;
02196       else
02197     deinterlace = false;
02198 
02199       ArTransform deltaTransform;
02200       deltaTransform.setTransform(encoderPose);
02201       deinterlaceDelta = deltaTransform.doInvTransform(deinterlaceEncoderPose);
02202 
02203       processPacket(packet, pose, encoderPose, myRobot->getCounter(),
02204             deinterlace, deinterlaceDelta);
02205       processed.push_back(packet);
02206     }
02207     else if (ret < -1 || retEncoder < -1)
02208     {
02209       if (myRobot->isConnected())
02210     ArLog::log(ArLog::Normal, "ArSick::processPacket: too old to process\n");
02211       else
02212       {
02213     processPacket(packet, pose, encoderPose, myRobot->getCounter(), false,
02214               ArPose());
02215       }
02216       processed.push_back(packet);
02217     }
02218     else 
02219     {
02220       //ArLog::log(ArLog::Terse, "ArSick::processPacket: error %d from interpolation\n", ret);
02221       //printf("$$$ ret = %d\n", ret);
02222     }
02223   }
02224   while ((it = processed.begin()) != processed.end())
02225   {
02226     packet = (*it);
02227     myPackets.remove(packet);
02228     processed.pop_front();
02229     delete packet;
02230   }
02231   unlockDevice();
02232 }
02233 
02235 AREXPORT void *ArSick::runThread(void *arg)
02236 {
02237   while (getRunningWithLock())
02238   {
02239     lockDevice();
02240     if (myStartConnect)
02241     {
02242       myStartConnect = false;
02243       switchState(STATE_INIT);
02244       if (myUseSim)
02245       {
02246     unlockDevice();
02247     internalConnectSim();
02248       }
02249       else 
02250       {
02251     unlockDevice();
02252     while (getRunningWithLock())
02253     {
02254       lockDevice();
02255       myConnLock.lock();
02256       if (internalConnectHandler() != 0)
02257       {
02258         myConnLock.unlock();
02259         unlockDevice();
02260         break;
02261       }
02262       myConnLock.unlock();
02263       unlockDevice();
02264       ArUtil::sleep(1);
02265     }
02266       }
02267     } else
02268       unlockDevice();
02269     runOnce(true);
02270     ArUtil::sleep(1);
02271   }
02272   lockDevice();
02273   if (isConnected())
02274   {
02275     disconnect();
02276   }
02277   unlockDevice();
02278 
02279   return NULL;
02280 }
02281 
02290 AREXPORT void ArSick::applyTransform(ArTransform trans,
02291                                                 bool doCumulative)
02292 {
02293   myCurrentBuffer.applyTransform(trans);
02294   std::list<ArSensorReading *>::iterator it;
02295 
02296   for (it = myRawReadings->begin(); it != myRawReadings->end(); ++it)
02297     (*it)->applyTransform(trans);
02298 
02299   if (doCumulative)
02300     myCumulativeBuffer.applyTransform(trans);
02301 }

Generated on Tue Feb 20 10:51:41 2007 for Aria by  doxygen 1.4.0