00001 #include "Robots/SeaBeeIII/MapperI.H" 00002 00003 const ModelOptionCateg MOC_MapperI = 00004 { MOC_SORTPRI_3, "SeaBee Mapper Component Related Options" }; 00005 00006 const ModelOptionDef OPT_NumParticles = 00007 { MODOPT_ARG(int), "NumParticles", &MOC_MapperI, OPTEXP_CORE, 00008 "Number of particles to keep track of for the particle filter.\n" 00009 " Using more particles can make the position estimate more accurate\n" 00010 " but will consume more cpu resources", 00011 "num-particles", '\0', "<int>", "500"}; 00012 00013 const ModelOptionDef OPT_HeadingVariance = 00014 { MODOPT_ARG(float), "HeadingVariance", &MOC_MapperI, OPTEXP_CORE, 00015 "The amount of variance (in degrees) in the heading. Using a large number here will" 00016 " spread out the particles laterally as movement occurs.", 00017 "heading-var", '\0', "<float>", "3"}; 00018 00019 const ModelOptionDef OPT_SpeedVariance = 00020 { MODOPT_ARG(float), "SpeedVariance", &MOC_MapperI, OPTEXP_CORE, 00021 "The amount of variance in the speed (in feet/second). Using a large number here will" 00022 " spread out the particles in the direction of movement as movement occurs.", 00023 "speed-var", '\0', "<float>", "3"}; 00024 00025 // ###################################################################### 00026 MapperI::MapperI(int id, OptionManager& mgr, 00027 const std::string& descrName, const std::string& tagName) : 00028 RobotBrainComponent(mgr, descrName, tagName), 00029 itsNumParticles(&OPT_NumParticles, this, 0), 00030 itsHeadingVariance(&OPT_HeadingVariance, this, 0), 00031 itsSpeedVariance(&OPT_SpeedVariance, this, 0) 00032 { 00033 //Fill the particle buffer with particles - each having 00034 //equal probability 00035 Particle initialParticle; 00036 initialParticle.pos = Point2D<float>(0,0); 00037 initialParticle.P = 1.0/itsNumParticles.getVal(); 00038 itsParticles.resize(itsNumParticles.getVal(), initialParticle); 00039 } 00040 00041 // ###################################################################### 00042 MapperI::~MapperI() 00043 { 00044 00045 } 00046 00047 void MapperI::registerTopics() 00048 { 00049 LINFO("Registering Mapper Message"); 00050 this->registerPublisher("MapperMessageTopic"); 00051 this->registerSubscription("BeeStemMessageTopic"); 00052 this->registerSubscription("VisionObjectMessageTopic"); 00053 } 00054 00055 void MapperI::evolve() 00056 { 00057 00058 } 00059 00060 // ###################################################################### 00061 void MapperI::moveParticles(float speed, float heading, uint64 elapsedTicks) 00062 { 00063 //Grab a lock on the particles buffer 00064 IceUtil::Mutex::Lock lock(itsParticlesMutex); 00065 00066 double elapsedSecs = double(elapsedTicks) / double(itsSampleTimer.ticksPerSec()); 00067 00068 //Move each particle according to the reported speed/heading, but shuffled 00069 //a bit by some gaussian noise 00070 vector<Particle>::iterator partIt; 00071 for(partIt = itsParticles.begin(); partIt != itsParticles.end(); partIt++) 00072 { 00073 00074 //Consider this particle's heading and speed as drawn from a Gaussian 00075 //distribution with a mean around the reported heading and speed, but 00076 //with a variance specified by the user. 00077 float randHeading = heading + randomDoubleFromNormal(itsHeadingVariance.getVal()); 00078 float randSpeed = speed + randomDoubleFromNormal(itsSpeedVariance.getVal()); 00079 00080 //Calculate the change in X and Y for this particle due to the new heading and speed 00081 float dx = randSpeed * elapsedSecs * cos(randHeading); 00082 float dy = randSpeed * elapsedSecs * sin(randHeading); 00083 00084 //Add the change in position to the particles currently believed position 00085 partIt->pos += Point2D<float>(dx,dy); 00086 } 00087 } 00088 00089 Point2D<float> MapperI::resolvePosition() 00090 { 00091 Point2D<float> resolvedPos(0,0); 00092 00093 //Grab a lock on the particles buffer 00094 IceUtil::Mutex::Lock lock(itsParticlesMutex); 00095 00096 float totalProb = 0.0; 00097 00098 //Weighted average of all particles' coordinates 00099 vector<Particle>::iterator partIt; 00100 for(partIt = itsParticles.begin(); partIt != itsParticles.end(); partIt++) 00101 { 00102 resolvedPos.i += partIt->pos.i * partIt->P; 00103 resolvedPos.j += partIt->pos.j * partIt->P; 00104 totalProb += partIt->P; 00105 } 00106 00107 return resolvedPos / totalProb; 00108 00109 } 00110 00111 // ###################################################################### 00112 void MapperI::updateObservation(RobotSimEvents::SeaBeeObjectType obsObjType, 00113 bool forwardCamera, 00114 ImageIceMod::Point3DIce obsObjectPosition, 00115 ImageIceMod::Point3DIce obsObjectVariance) 00116 { 00117 //Grab a lock on the particles buffer 00118 IceUtil::Mutex::Lock lock(itsParticlesMutex); 00119 00120 vector<Particle>::iterator partIt; 00121 for(partIt = itsParticles.begin(); partIt != itsParticles.end(); partIt++) 00122 { 00123 00124 //Find the closest object of this type in our map 00125 MapObject matchedObject; 00126 float minDistance = -1; 00127 vector<MapObject>::iterator objIt; 00128 for(objIt = itsMap.begin(); objIt != itsMap.end(); objIt++) 00129 if(objIt->type == obsObjType) 00130 { 00131 float distance = objIt->pos.distance(partIt->pos); 00132 if(distance < minDistance || minDistance == -1) 00133 matchedObject = *objIt; 00134 } 00135 00136 00137 00138 00139 } 00140 } 00141 00142 // ###################################################################### 00143 void MapperI::updateMessage(const RobotSimEvents::EventMessagePtr& eMsg, 00144 const Ice::Current&) 00145 { 00146 //Get a retina message 00147 if(eMsg->ice_isA("::RobotSimEvents::BeeStemMessage")) 00148 { 00149 RobotSimEvents::BeeStemMessagePtr ccMsg = RobotSimEvents::BeeStemMessagePtr::dynamicCast(eMsg); 00150 float heading = ccMsg->compassHeading; 00151 float speed = ccMsg->desiredSpeed; 00152 00153 moveParticles(heading, speed, itsSampleTimer.getReset()); 00154 } 00155 if(eMsg->ice_isA("::RobotSimEvents::VisionObjectMessage")) 00156 { 00157 RobotSimEvents::VisionObjectMessagePtr voMsg = RobotSimEvents::VisionObjectMessagePtr::dynamicCast(eMsg); 00158 00159 RobotSimEvents::SeaBeeObjectType objType = voMsg->objectType; 00160 bool forwardCamera = voMsg->forwardCamera; 00161 ImageIceMod::Point3DIce objectPosition = voMsg->objectPosition; 00162 ImageIceMod::Point3DIce objectVariance = voMsg->objectVariance; 00163 00164 updateObservation(objType, forwardCamera, objectPosition, objectVariance); 00165 } 00166 00167 } 00168 00169