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

ArRangeDevice.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 "ArRangeDevice.h"
00029 #include "ArRobot.h"
00030 
00067 AREXPORT ArRangeDevice::ArRangeDevice(size_t currentBufferSize,
00068                       size_t cumulativeBufferSize, 
00069                       const char *name, 
00070                       unsigned int maxRange,
00071                       int maxSecondsToKeepCurrent, 
00072                       int maxSecondsToKeepCumulative,
00073                       double maxDistToKeepCumulative,
00074                       bool locationDependent) :
00075   myCurrentBuffer(currentBufferSize),
00076   myCumulativeBuffer(cumulativeBufferSize),
00077   myFilterCB(this, &ArRangeDevice::filterCallback)
00078 {
00079   myRobot = NULL;
00080   myName = name;
00081   myMaxRange = maxRange;
00082   myRawReadings = NULL;
00083   myAdjustedRawReadings = NULL;
00084   setMaxSecondsToKeepCurrent(maxSecondsToKeepCurrent);
00085   setMaxSecondsToKeepCumulative(maxSecondsToKeepCumulative);
00086   setMaxDistToKeepCumulative(maxDistToKeepCumulative);
00087   myCurrentDrawingData = NULL;
00088   myOwnCurrentDrawingData = false;
00089   myCumulativeDrawingData = NULL;
00090   myOwnCumulativeDrawingData = false;
00091   myIsLocationDependent = locationDependent;
00092 }
00093 
00094 AREXPORT ArRangeDevice::~ArRangeDevice()
00095 {
00096   if (myRobot != NULL)
00097     myRobot->remSensorInterpTask(&myFilterCB);
00098   if (myCurrentDrawingData != NULL && myOwnCurrentDrawingData)
00099   {
00100     delete myCurrentDrawingData;
00101     myCurrentDrawingData = NULL;
00102     myOwnCurrentDrawingData = false;
00103   }
00104   if (myCumulativeDrawingData != NULL && myOwnCumulativeDrawingData)
00105   {
00106     delete myCumulativeDrawingData;
00107     myCumulativeDrawingData = NULL;
00108     myOwnCumulativeDrawingData = false;
00109   }
00110 }
00111 
00112 
00113 AREXPORT const char * ArRangeDevice::getName(void) const
00114 { 
00115   return myName.c_str(); 
00116 }
00117 
00118 AREXPORT void ArRangeDevice::setRobot(ArRobot *robot) 
00119 { 
00120   char buf[512];
00121   sprintf(buf, "filter %s", getName());
00122 
00123   if (myRobot != NULL)
00124     myRobot->remSensorInterpTask(&myFilterCB);
00125 
00126   myRobot = robot;
00127 
00128   if (myRobot != NULL)
00129     myRobot->addSensorInterpTask(buf, 100, &myFilterCB);
00130 }
00131 
00132 AREXPORT ArRobot *ArRangeDevice::getRobot(void) 
00133 {
00134   return myRobot; 
00135 }
00136 
00137 AREXPORT void ArRangeDevice::filterCallback(void)
00138 {
00139   std::list<ArPoseWithTime *>::iterator it;
00140 
00141   lockDevice();
00142   // first filter the current readings based on time
00143   if (myMaxSecondsToKeepCurrent > 0 && 
00144       myCurrentBuffer.getSize() > 0)
00145   {
00146     // just walk through and make sure nothings too far away
00147     myCurrentBuffer.beginInvalidationSweep();
00148     for (it = getCurrentBuffer()->begin(); 
00149      it != getCurrentBuffer()->end(); 
00150      ++it)
00151     {
00152       if ((*it)->getTime().secSince() >= myMaxSecondsToKeepCurrent)
00153     myCurrentBuffer.invalidateReading(it);
00154     }
00155     myCurrentBuffer.endInvalidationSweep();
00156   }
00157   
00158   // okay done with current, now do the cumulative
00159   bool doingDist = true;
00160   bool doingAge = true;
00161 
00162   if (myCumulativeBuffer.getSize() == 0)
00163   {
00164     unlockDevice();
00165     return;
00166   }
00167 
00168   double squaredFarDist = (myMaxDistToKeepCumulative * 
00169                myMaxDistToKeepCumulative);
00170 
00171   if (squaredFarDist < 1)
00172     doingDist = false;
00173   if (myMaxSecondsToKeepCumulative <= 0)
00174     doingAge = false;
00175             
00176   if (!doingDist && !doingAge)
00177   {
00178     unlockDevice();
00179     return;
00180   }
00181 
00182   // just walk through and make sure nothings too far away
00183   myCumulativeBuffer.beginInvalidationSweep();
00184   for (it = getCumulativeBuffer()->begin(); 
00185        it != getCumulativeBuffer()->end(); 
00186        ++it)
00187   {
00188     // if its closer to a reading than the filter near dist, just return
00189     if (doingDist && 
00190     myRobot->getPose().squaredFindDistanceTo(*(*it)) > squaredFarDist)
00191       myCumulativeBuffer.invalidateReading(it);
00192     else if (doingAge && 
00193          (*it)->getTime().secSince() >= myMaxSecondsToKeepCumulative)
00194       myCumulativeBuffer.invalidateReading(it);
00195   }
00196   myCumulativeBuffer.endInvalidationSweep();
00197   unlockDevice();
00198 }
00199 
00208 AREXPORT void ArRangeDevice::setCurrentBufferSize(size_t size)
00209 {
00210   myCurrentBuffer.setSize(size);
00211 }
00212 
00221 AREXPORT void ArRangeDevice::setCumulativeBufferSize(size_t size)
00222 {
00223   myCumulativeBuffer.setSize(size);
00224 }
00225 
00226 AREXPORT void ArRangeDevice::addReading(double x, double y)
00227 {
00228   myCurrentBuffer.addReading(x, y);
00229   myCumulativeBuffer.addReading(x, y);
00230 }
00231 
00255 AREXPORT double ArRangeDevice::currentReadingPolar(double startAngle,
00256                            double endAngle,
00257                            double *angle) const
00258 {
00259   ArPose pose;
00260   if (myRobot != NULL)
00261     pose = myRobot->getPose();
00262   else
00263     {
00264       ArLog::log(ArLog::Normal, "ArRangeDevice %s: NULL robot, won't get polar reading correctly", getName());
00265       pose.setPose(0, 0);
00266     }
00267   return myCurrentBuffer.getClosestPolar(startAngle, endAngle, 
00268                      pose,
00269                      myMaxRange,
00270                      angle);
00271 }
00272 
00294 AREXPORT double ArRangeDevice::cumulativeReadingPolar(double startAngle,
00295                               double endAngle,
00296                               double *angle) const
00297 {
00298   ArPose pose;
00299   if (myRobot != NULL)
00300     pose = myRobot->getPose();
00301   else
00302     {
00303       ArLog::log(ArLog::Normal, "ArRangeDevice %s: NULL robot, won't get polar reading correctly", getName());
00304       pose.setPose(0, 0);
00305     }
00306   return myCumulativeBuffer.getClosestPolar(startAngle, endAngle, 
00307                         pose,
00308                         myMaxRange,
00309                         angle);
00310 }
00311 
00324 AREXPORT double ArRangeDevice::currentReadingBox(double x1, double y1, 
00325                          double x2, double y2,
00326                          ArPose *pose) const
00327 {
00328   ArPose robotPose;
00329   if (myRobot != NULL)
00330       robotPose = myRobot->getPose();
00331   else
00332     {
00333       ArLog::log(ArLog::Normal, "ArRangeDevice %s: NULL robot, won't get reading box correctly", getName());
00334       robotPose.setPose(0, 0);
00335     }
00336   return myCurrentBuffer.getClosestBox(x1, y1, x2, y2, robotPose,
00337                        myMaxRange, pose);
00338 }
00339 
00353 AREXPORT double ArRangeDevice::cumulativeReadingBox(double x1, double y1, 
00354                          double x2, double y2,
00355                          ArPose *pose) const
00356 {
00357   ArPose robotPose;
00358   if (myRobot != NULL)
00359     robotPose = myRobot->getPose();
00360   else
00361     {
00362       ArLog::log(ArLog::Normal, "ArRangeDevice %s: NULL robot, won't get reading box correctly", getName());
00363       robotPose.setPose(0, 0);
00364     }
00365   return myCumulativeBuffer.getClosestBox(x1, y1, x2, y2, 
00366                       robotPose,
00367                       myMaxRange, pose);
00368 }
00369 
00377 AREXPORT void ArRangeDevice::applyTransform(ArTransform trans, 
00378                         bool doCumulative)
00379 {
00380   myCurrentBuffer.applyTransform(trans);
00381   if (doCumulative)
00382     myCumulativeBuffer.applyTransform(trans);
00383 }
00384 
00389 AREXPORT std::vector<ArSensorReading> *ArRangeDevice::getRawReadingsAsVector(void)
00390 {
00391   
00392   std::list<ArSensorReading *>::const_iterator it;
00393   myRawReadingsVector.clear();
00394   // if we don't have any return an empty list
00395   if (myRawReadings == NULL)
00396     return &myRawReadingsVector;
00397   myRawReadingsVector.reserve(myRawReadings->size());
00398   for (it = myRawReadings->begin(); it != myRawReadings->end(); it++)
00399     myRawReadingsVector.insert(myRawReadingsVector.begin(), *(*it));
00400   return &myRawReadingsVector;
00401 }
00402 
00407 AREXPORT std::vector<ArSensorReading> *ArRangeDevice::getAdjustedRawReadingsAsVector(void)
00408 {
00409   
00410   std::list<ArSensorReading *>::const_iterator it;
00411   myAdjustedRawReadingsVector.clear();
00412   // if we don't have any return an empty list
00413   if (myAdjustedRawReadings == NULL)
00414     return &myRawReadingsVector;
00415   myAdjustedRawReadingsVector.reserve(myRawReadings->size());
00416   for (it = myAdjustedRawReadings->begin(); 
00417        it != myAdjustedRawReadings->end(); 
00418        it++)
00419     myAdjustedRawReadingsVector.insert(myAdjustedRawReadingsVector.begin(), 
00420                        *(*it));
00421   return &myAdjustedRawReadingsVector;
00422 }
00423 
00424 
00425 AREXPORT void ArRangeDevice::setCurrentDrawingData(ArDrawingData *data, 
00426                            bool takeOwnershipOfData)
00427 {
00428   if (myCurrentDrawingData != NULL && myOwnCurrentDrawingData)
00429   {
00430     delete myCurrentDrawingData;
00431     myCurrentDrawingData = NULL;
00432     myOwnCurrentDrawingData = false;
00433   }
00434   myCurrentDrawingData = data; 
00435   myOwnCurrentDrawingData = takeOwnershipOfData; 
00436 }
00437 
00438 AREXPORT  void ArRangeDevice::setCumulativeDrawingData(ArDrawingData *data, 
00439                               bool takeOwnershipOfData)
00440 {
00441   if (myCumulativeDrawingData != NULL && myOwnCumulativeDrawingData)
00442   {
00443     delete myCumulativeDrawingData;
00444     myCumulativeDrawingData = NULL;
00445     myOwnCumulativeDrawingData = false;
00446   }
00447   myCumulativeDrawingData = data; 
00448   myOwnCumulativeDrawingData = takeOwnershipOfData; 
00449 }
00450 
00451 AREXPORT void ArRangeDevice::adjustRawReadings(bool interlaced)
00452 {
00453   std::list<ArSensorReading *>::iterator rawIt;
00454 
00455   // make sure we have raw readings and a robot, and a delay to
00456   // correct for (note that if we don't have a delay to correct for
00457   // but have already been adjusting (ie someone changed the delay)
00458   // we'll just keep adjusting)
00459   if (myRawReadings == NULL || myRobot == NULL || 
00460       (myAdjustedRawReadings == NULL && myRobot->getOdometryDelay() == 0))
00461     return;
00462   
00463 
00464   // if we don't already have a list then make one
00465   if (myAdjustedRawReadings == NULL)
00466     myAdjustedRawReadings = new std::list<ArSensorReading *>;
00467   
00468   // if we've already adjusted these readings then don't do it again
00469   if (myRawReadings->begin() != myRawReadings->end() &&
00470       myRawReadings->front()->getAdjusted())
00471     return;
00472 
00473   std::list<ArSensorReading *>::iterator adjIt;
00474   ArSensorReading *adjReading;
00475   ArSensorReading *rawReading;
00476 
00477   ArTransform trans;
00478   ArTransform encTrans;
00479   ArTransform interlacedTrans;
00480   ArTransform interlacedEncTrans;
00481 
00482   bool first = true;
00483   bool second = true;
00484 
00485   int onReading;
00486   for (rawIt = myRawReadings->begin(), adjIt = myAdjustedRawReadings->begin(), 
00487        onReading = 0; 
00488        rawIt != myRawReadings->end(); 
00489        rawIt++, onReading++)
00490   {
00491     rawReading = (*rawIt);
00492     if (adjIt != myAdjustedRawReadings->end())
00493     {
00494       adjReading = (*adjIt);
00495       adjIt++;
00496     }
00497     else
00498     {
00499       adjReading = new ArSensorReading;
00500       myAdjustedRawReadings->push_back(adjReading);
00501     }
00502     (*adjReading) = (*rawReading);
00503     if (first || (interlaced && second))
00504     {
00505       ArPose origPose;
00506       ArPose corPose;
00507       ArPose origEncPose;
00508       ArPose corEncPose;
00509       ArTime corTime;
00510 
00511 
00512       corTime = rawReading->getTimeTaken();
00513       corTime.addMSec(-myRobot->getOdometryDelay());
00514       if (myRobot->getPoseInterpPosition(corTime, 
00515                      &corPose) == 1 && 
00516       myRobot->getEncoderPoseInterpPosition(corTime, 
00517                         &corEncPose) == 1)
00518       {
00519     origPose = rawReading->getPoseTaken();
00520     origEncPose = rawReading->getEncoderPoseTaken();
00521     /*
00522     printf("Difference was %g %g %g (rotVel %.0f, rotvel/40 %g)\n", 
00523            origEncPose.getX() - corEncPose.getX(),
00524            origEncPose.getY() - corEncPose.getY(),
00525            origEncPose.getTh() - corEncPose.getTh(),
00526            myRobot->getRotVel(), myRobot->getRotVel() / 40);
00527     */
00528     if (first)
00529     {
00530       trans.setTransform(origPose, corPose);
00531       encTrans.setTransform(origEncPose, corEncPose);
00532     }
00533     else if (interlaced && second)
00534     {
00535       interlacedTrans.setTransform(origPose, corPose);
00536       interlacedEncTrans.setTransform(origEncPose, corEncPose);
00537     }
00538       }
00539       else
00540       {
00541     //printf("Couldn't correct\n");
00542       }
00543 
00544       if (first)
00545     first = false;
00546       else if (interlaced && second)
00547     second = false;
00548 
00549     }
00550     if (!interlaced && (onReading % 2) == 0)
00551     {
00552       adjReading->applyTransform(trans);
00553       adjReading->applyEncoderTransform(encTrans);
00554     }
00555     else
00556     {
00557       adjReading->applyTransform(interlacedTrans);
00558       adjReading->applyEncoderTransform(interlacedEncTrans);
00559     }
00560     /*
00561     if (fabs(adjReading->getEncoderPoseTaken().getX() - 
00562          corEncPose.getX()) > 1 ||
00563     fabs(adjReading->getEncoderPoseTaken().getY() - 
00564          corEncPose.getY()) > 1 || 
00565     fabs(ArMath::subAngle(adjReading->getEncoderPoseTaken().getTh(), 
00566                   corEncPose.getTh())) > .2)
00567       printf("(%.0f %.0f %.0f) should be (%.0f %.0f %.0f)\n", 
00568          adjReading->getEncoderPoseTaken().getX(),
00569          adjReading->getEncoderPoseTaken().getY(),
00570          adjReading->getEncoderPoseTaken().getTh(),
00571          corEncPose.getX(), corEncPose.getY(),  corEncPose.getTh());
00572     */
00573     adjReading->setAdjusted(true);
00574     rawReading->setAdjusted(true);
00575   }  
00576 }

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