00001
00002
00003 #ifndef SLAM_SLAM_EKF_HPP
00004 #define SLAM_SLAM_EKF_HPP
00005
00006 #include <string>
00007 #include <vector>
00008 #include <map>
00009
00010 #include "kernel/jafarException.hpp"
00011 #include "kernel/timingTools.hpp"
00012 #include "kernel/dataLog.hpp"
00013
00014 #include "jmath/jblas.hpp"
00015
00016 #include "geom/t3dEuler.hpp"
00017
00018 #include "filter/kalmanFilter.hpp"
00019
00020 #include "slam/baseSlam.hpp"
00021 #include "slam/slamException.hpp"
00022 #include "slam/mapManager.hpp"
00023 #include "slam/feature.hpp"
00024 #include "slam/pointFeature.hpp"
00025 #include "slam/segmentFeature.hpp"
00026 #include "slam/segmentAnchorPluckerFeature.hpp"
00027 #include "slam/segmentInvDepthFeature.hpp"
00028 #include "slam/slamEvents.hpp"
00029 #include "slam/poseCopy.hpp"
00030 #include "slam/robot.hpp"
00031
00032 namespace jafar {
00033 namespace slam {
00034 class BaseRobot;
00044 class SlamEkf : public BaseSlam, public jafar::kernel::DataLoggable {
00045
00046 private:
00047
00050 void initFeatureState(BaseFeature& feature,
00051 FeatureObserveModel& observeModel,
00052 Observation const& obs);
00053
00054 protected:
00055 bool m_deleteSensors;
00056
00057 unsigned int currentFrameIndex;
00058 unsigned int prevFrameIndex;
00059
00060 jafar::filter::BlockExtendedKalmanFilter filter;
00061
00062 double mahalanobisDistanceToRemoveLandmark;
00063
00064 std::size_t m_sizeRobotState;
00065 std::size_t m_sizeRobotPose;
00066
00067
00068
00069
00070 AbstractMapManager* mapManager;
00071
00072 typedef std::list<SlamEventListener*> SlamEventListenersList;
00073 SlamEventListenersList slamEventListeners;
00074
00076 bool enableInitCoordinateFrame;
00077
00078 typedef std::map<unsigned int, FeatureObserveModel*> FeatureObserveModelsContType;
00080 FeatureObserveModelsContType featureObserveModels;
00081
00082 class Stats
00083 {
00084 public:
00085 double poseUncertaintyVolume;
00086 double mapUncertaintyLevel;
00087 int prevNbFoundLandmarks;
00088 int nbFoundLandmarks;
00089 int nbLostLandmarks;
00090 int nbInconsistentLandmarks;
00091 int nbObservedLandmarks;
00092 int nframes;
00093
00094 Stats(): poseUncertaintyVolume(0), mapUncertaintyLevel(0), prevNbFoundLandmarks(0),
00095 nbFoundLandmarks(0), nbLostLandmarks(0), nbInconsistentLandmarks(0), nbObservedLandmarks(0),
00096 nframes(0) {}
00097 } stats;
00098
00103 virtual void observeNewFeature(Observation* obs_);
00104
00107 virtual void observeKnownFeature(Observation* obs_);
00108
00111 void observeKnownFeature(Observation const& obs, BaseFeature& feature, BaseFeatureObserveModel& model);
00112
00114 void applyConstraints(BaseFeature& feature);
00115
00117 void fixFeature(BaseFeature& feature);
00118
00119
00120
00122 void copyCurrentPoseAt(std::size_t index, int _robotId = 0);
00123
00125 geom::T3D* m_refToRobot;
00126 geom::T3D* m_robotToRef;
00127
00128 static BaseFeature* featureFactory(unsigned int id,
00129 BaseFeatureObserveModel& model);
00130 static BaseFeature* featureFactory(unsigned int id,
00131 FeatureModel& model, std::size_t sizeObs, Observation::ObservationType typeObs );
00132
00133 void writePoseCopyToFile(PoseCopy const& pc, std::string const& dir);
00134
00135
00136 unsigned short int nbInconsistentUpdates;
00137 unsigned short int nbNewLandmarks;
00138 unsigned short int nbObservedLandmarks;
00139 long updateElapsedTime;
00140
00141 virtual void writeLogHeader(jafar::kernel::DataLogger& log) const;
00142 virtual void writeLogData(jafar::kernel::DataLogger& log) const;
00143 virtual void writeLogStats(jafar::kernel::DataLogger& log) const;
00144
00145 jafar::kernel::DataLogger* p_masterLogger;
00146
00147 void logFeature(BaseFeature& f);
00148
00149 public:
00150
00151 typedef std::map<unsigned int, BaseFeature*> FeaturesMapType;
00153 FeaturesMapType featuresMap;
00154
00155 typedef std::map<unsigned int, PoseCopy*> PoseCopyContType;
00157 PoseCopyContType poseCopyCont;
00158
00159 typedef std::map<unsigned int, BaseRobot*> RobotsMapType;
00161 RobotsMapType robotsMap;
00162
00164 SlamEkf(std::size_t sizeMax_, std::size_t sizeRobotState_, std::size_t sizeRobotPose_);
00165 private:
00166 SlamEkf(const SlamEkf& ) : filter(0,0) { JFR_ASSERT(false, "Copying SlamEkf is not legal."); }
00167 SlamEkf& operator=(const SlamEkf& ) { JFR_ASSERT(false, "Copying SlamEkf is not legal."); }
00168 public:
00170 virtual ~SlamEkf();
00171
00173 virtual void init(boost::posix_time::time_duration const& curTime);
00174
00176 std::size_t sizeRobotPose() const {return m_sizeRobotPose;}
00177
00179 std::size_t sizeRobotState() const {return m_sizeRobotState;}
00180
00182 jblas::vec_range const& refPose(int _robotId = 0) const;
00183
00185 jblas::sym_mat_range const& refPoseCov(int _robotId = 0) const;
00186
00187 void enableAutoLogFeatures(jafar::kernel::DataLogger& masterLogger) {p_masterLogger = &masterLogger;}
00188
00190 jafar::filter::BlockExtendedKalmanFilter& getFilter() {return filter;};
00191
00193 jafar::filter::BlockExtendedKalmanFilter const& getFilter() const {return filter;};
00194
00196 FeaturesMapType const& getMap() const {return featuresMap;}
00197
00198 jafar::geom::T3D const& refToRobot() const {return *m_refToRobot;}
00199 jafar::geom::T3D const& robotToRef() const {return *m_robotToRef ;}
00200 void setRefToRobot(jafar::geom::T3DEuler const& refToRobot_);
00201
00202 void setRobotPose(jblas::vec const& robotPose, int _robotId = 0);
00203 void setRobotPoseCov(jblas::vec const& robotPose, jblas::sym_mat const& robotPoseCov, int _robotId = 0);
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214 FeatureObserveModel& getFeatureObserveModel(unsigned int sensorId = 0) const {
00215 FeatureObserveModelsContType::const_iterator it = featureObserveModels.find(sensorId);
00216 JFR_PRED_ERROR(it != featureObserveModels.end(),
00217 SlamException,
00218 SlamException::UNKNOWN_SENSOR,
00219 "Unknown sensor: " << sensorId);
00220 return *(it->second);
00221 }
00222
00223 unsigned int getCurrentFrameIndex() const {return currentFrameIndex;}
00224 unsigned int getPrevFrameIndex() const {return prevFrameIndex;}
00225
00226 void setMapManager(AbstractMapManager* mapManager_);
00227
00232 void setDeleteSensors( bool );
00236 void setSensor(FeatureObserveModel* model, int sensorId = 0);
00237
00238
00239
00240
00241
00242 void setRobotZ(double z, double zStdDev, int _robotId = 0);
00243
00244 void setRobotPitch(double pitch, double pitchStdDev, int _robotId = 0);
00245
00246 void setRobotRoll(double roll, double rollStdDev, int _robotId = 0);
00247
00251 virtual void setRobotToSensor(jblas::vec const& robotToSensor, int sensorId = 0);
00252 const jblas::vec& robotToSensor( int sensorId = 0) const;
00253
00257 virtual void setRobotToSensor(jblas::vec const& robotToSensor, jblas::vec const& robotToSensorStdDev,
00258 int sensorId = 0);
00259
00260 virtual void addEventListener(SlamEventListener& listener) {
00261 JFR_ASSERT( &listener != 0, "Can't add null listener");
00262 slamEventListeners.push_back(&listener);
00263
00264 }
00265
00266 virtual void removeEventListener(SlamEventListener& listener) {
00267 slamEventListeners.remove(&listener);
00268 }
00269
00270 bool hasFeature(unsigned int id, unsigned int _robotId = 0) const {
00271 return featuresMap.find(id) != featuresMap.end();
00272 };
00273
00274 virtual bool isFeatureKnown(unsigned int id) const {
00275
00276 return hasFeature(id);
00277 };
00278
00279
00280
00281
00282 BaseFeature& getFeature(unsigned int id) {
00283 FeaturesMapType::const_iterator feature_it = featuresMap.find(id);
00284 if (feature_it != featuresMap.end())
00285 return *(feature_it->second);
00286 else
00287 {
00288 JFR_DEBUG( "SlamEkf::getFeature: unknown feature " << id );
00289 JFR_ERROR(SlamException, SlamException::UNKNOWN_FEATURE,
00290 "SlamEkf::getFeature: unknown feature " << id);
00291 }
00292 }
00293
00294 BaseFeature const& getFeature(unsigned int id) const {
00295 FeaturesMapType::const_iterator feature_it = featuresMap.find(id);
00296 if (feature_it != featuresMap.end())
00297 return *(feature_it->second);
00298 else
00299 JFR_ERROR(SlamException, SlamException::UNKNOWN_FEATURE,
00300 "SlamEkf::getFeature: unknown feature " << id);
00301 }
00302
00304 virtual void removeFeature(unsigned int id);
00305
00309 PoseCopy const& copyCurrentRefPoseToMap(unsigned int id);
00310
00313 PoseCopy const& getPoseCopy(unsigned int id) const {
00314 PoseCopyContType::const_iterator poseIt = poseCopyCont.find(id);
00315 if (poseIt != poseCopyCont.end())
00316 return *(poseIt->second);
00317 else
00318 JFR_ERROR(SlamException, SlamException::UNKNOWN_POSE_COPY,
00319 "SlamEkf::getPoseCopy: unknown pose copy " << id);
00320 }
00321
00323 void removePoseCopy(unsigned int id);
00324
00328 void writePoseCopyToFile(unsigned int id, std::string const& dir);
00329 void writeAllPoseCopyToFile(std::string const& dir);
00330
00331 double getRobotPoseUncertaintyLevel(unsigned int robotId_ = 0) const;
00332
00333 void getRobotPose(jafar::geom::T3DEuler& pose, unsigned int _robotId = 0) const {
00334 if (refToRobot().isIdentity()) {
00335 pose.set(refPose(_robotId), refPoseCov(_robotId));
00336 }
00337 else {
00338 geom::T3DEuler worldToRef(refPose(_robotId), refPoseCov(_robotId));
00339 geom::T3D::compose(worldToRef, refToRobot(), pose);
00340 }
00341 }
00342
00347 void transform( const geom::T3DEuler& _transform );
00348
00349
00350
00354 std::size_t sizeMap() const {return featuresMap.size();}
00355 double getMapUncertaintyLevel() const;
00356
00357
00358 FeaturesMapType::iterator browseFeaturesIt;
00359 void beginBrowseFeatures();
00360 bool hasNextFeature();
00361 BaseFeature* nextFeature();
00365 BaseFeature* feature( unsigned int id );
00366
00372 virtual void predict(unsigned int _robotId, jblas::vec const& u);
00373
00377 BaseRobot* robot( unsigned int _id );
00381 const BaseRobot* robot( unsigned int ) const;
00382
00387 virtual void addRobot( BaseRobot* );
00388 virtual void addRobot( BaseRobot*, const jblas::vec& _robotState, const jblas::sym_mat& _robotStateCov );
00389 private:
00390 template<class SequenceType1, class SequenceType2>
00391 void processObservationsImpl(unsigned int frameIndex_,
00392 SequenceType1 const& knownObs,
00393 SequenceType2 const& newObs, unsigned int robotId_, int events_ )
00394 {
00395 nbInconsistentUpdates = 0;
00396 nbNewLandmarks = 0;
00397 nbObservedLandmarks = 0;
00398
00399 if( frameIndex_ != currentFrameIndex )
00400 {
00401 prevFrameIndex = currentFrameIndex;
00402 currentFrameIndex = frameIndex_;
00403 }
00404
00405 if( (events_ & SlamEventListener::BEGIN_PROCESS_OBSERVATIONS) == SlamEventListener::BEGIN_PROCESS_OBSERVATIONS )
00406 {
00407 for(SlamEventListenersList::iterator it = slamEventListeners.begin() ; it != slamEventListeners.end() ; ++it) {
00408 (*it)->beginProcessObservations(robotId_);
00409 }
00410 }
00411
00412 kernel::Chrono chrono;
00413
00414 for (typename SequenceType1::const_iterator it = knownObs.begin() ; it != knownObs.end() ; ++it) {
00415 observeKnownFeature(*it);
00416 }
00417
00418 for (typename SequenceType2::const_iterator it = newObs.begin() ; it != newObs.end() ; ++it) {
00419 observeNewFeature(*it);
00420 }
00421
00422
00423
00424 updateElapsedTime = chrono.elapsed();
00425
00426 if( (events_ & SlamEventListener::END_PROCESS_OBSERVATIONS) == SlamEventListener::END_PROCESS_OBSERVATIONS )
00427 {
00428 for(SlamEventListenersList::iterator it = slamEventListeners.begin() ; it != slamEventListeners.end() ; ++it) {
00429 (**it).endProcessObservations(robotId_);
00430 }
00431 }
00432 }
00433 public:
00434 virtual void processObservations(unsigned int frameIndex_,
00435 std::list<Observation*> const& knownObs,
00436 std::list<Observation*> const& newObs, unsigned int robotId_ = 0, int events_ = SlamEventListener::ALL )
00437 {
00438 processObservationsImpl( frameIndex_, knownObs, newObs, robotId_, events_ );
00439 }
00440 virtual void processObservations(unsigned int frameIndex_,
00441 std::vector<Observation*> const& knownObs,
00442 std::vector<Observation*> const& newObs, unsigned int robotId_ = 0, int events_ = SlamEventListener::ALL )
00443 {
00444 processObservationsImpl( frameIndex_, knownObs, newObs, robotId_ , events_);
00445 }
00446
00447 template<class SequenceType>
00448 void processObservations(unsigned int frameIndex_,
00449 SequenceType const& allObs, unsigned int robotId_ = 0, int events_ = SlamEventListener::ALL )
00450 {
00451
00452 SequenceType knownObs;
00453 SequenceType newObs;
00454
00455 for (typename SequenceType::const_iterator it = allObs.begin() ; it != allObs.end() ; ++it) {
00456 if ( isFeatureKnown((**it).id) )
00457 knownObs.push_back(*it);
00458 else
00459 newObs.push_back(*it);
00460 }
00461
00462 processObservations(frameIndex_, knownObs, newObs, robotId_, events_);
00463
00464 }
00465
00471
00628
00631
00636
00644