00001
00010 #ifndef __RobotAbstract_H__
00011 #define __RobotAbstract_H__
00012
00013
00014
00015
00016
00017 #include "kernel/jafarDebug.hpp"
00018 #include "kernel/IdFactory.hpp"
00019 #include "kernel/dataLog.hpp"
00020 #include "kernel/timingTools.hpp"
00021 #include "jmath/jblas.hpp"
00022 #include "jmath/indirectArray.hpp"
00023
00024 #include "rtslam/rtSlam.hpp"
00025 #include "rtslam/gaussian.hpp"
00026 #include "rtslam/mapObject.hpp"
00027 #include "rtslam/perturbation.hpp"
00028 #include "rtslam/quatTools.hpp"
00029
00030 #include "rtslam/mapAbstract.hpp"
00031 #include "rtslam/mapObject.hpp"
00032 #include "rtslam/parents.hpp"
00033
00034 #include "rtslam/hardwareSensorAbstract.hpp"
00035
00036 namespace jafar {
00037 namespace rtslam {
00038
00039
00040
00041 class SensorAbstract;
00042
00043 class RobotQuantity
00044 {
00045 public:
00055 enum Quantity { qPos, qOriQuat, qAbsVel, qAngVel, qAbsAcc, qAngAcc, qAbsJerk, qAngJerk, qG, qNormG, qNQuantity };
00056 static const int QuantityDataSizes[qNQuantity];
00057 typedef std::vector<Quantity> QuantityList;
00058 protected:
00059 size_t state_size;
00060 int quantities[qNQuantity];
00061 public:
00062 RobotQuantity()
00063 { clearQuantities(); }
00064 RobotQuantity(QuantityList quants)
00065 { clearQuantities(); for(QuantityList::iterator it = quants.begin(); it != quants.end(); ++it) registerRobotQuantity(*it); }
00066 RobotQuantity(RobotQuantity const & robQuant, QuantityList quants)
00067 { clearQuantities(); for(QuantityList::iterator it = quants.begin(); it != quants.end(); ++it) quantities[*it] = robQuant.quantities[*it]; }
00068
00070 virtual bool registerRobotQuantity(Quantity quantity)
00071 { if (quantities[quantity] < 0) { quantities[quantity] = state_size; state_size += QuantityDataSizes[quantity]; return false; } else return true; }
00073 virtual ublas::range allocateSensorQuantity(size_t size)
00074 { size_t pos = state_size; state_size += size; return ublas::range(pos, state_size); }
00076 virtual void clearQuantities()
00077 { for(int i = 0; i < qNQuantity; ++i) quantities[i] = -1; state_size = 0; }
00078
00079 inline bool hasQuantity(Quantity quantity)
00080 { return (quantities[quantity] >= 0); }
00081 inline ublas::range getQuantity(Quantity quantity)
00082 { return hasQuantity(quantity) ? ublas::range(quantities[quantity], quantities[quantity]+QuantityDataSizes[quantity]) : ublas::range(0,0); }
00083 inline jblas::ind_array getQuantities()
00084 { jblas::ind_array ia; for(int i = 0; i < qNQuantity; ++i) if (hasQuantity((Quantity)i)) ia = ia_union(ia, ia_set(getQuantity((Quantity)i))); return ia; }
00085 };
00086
00087
00093 class RobotAbstract: public MapObject,
00094 public ChildOf<MapAbstract>,
00095 public boost::enable_shared_from_this<RobotAbstract>,
00096 public ParentOf<SensorAbstract>,
00097 public kernel::DataLoggable,
00098 public RobotQuantity {
00099
00100 friend ostream& operator <<(ostream & s, RobotAbstract const & rob);
00101
00102 protected:
00103 bool constructed;
00104 static IdFactory robotIds;
00105 public:
00107 virtual bool registerRobotQuantity(Quantity quantity)
00108 {
00109 if (!RobotQuantity::registerRobotQuantity(quantity))
00110 {
00111 if (constructed) construct(mapPtr(), state_size, control.size(), perturbation.size());
00112 return false;
00113 } else
00114 return true;
00115 }
00116 virtual ublas::range allocateSensorQuantity(size_t size)
00117 {
00118 ublas::range r = RobotQuantity::allocateSensorQuantity(size);
00119 if (constructed) construct(mapPtr(), state_size, control.size(), perturbation.size());
00120 return r;
00121 }
00122
00123 enum type_enum {
00124 ODOMETRY, CONSTANT_VELOCITY, CONSTANT_MOTION_MODEL, INERTIAL, CENTERED_CONSTANT_VELOCITY
00125 };
00126 type_enum type;
00127
00128 sensor_ptr_t last_updated;
00129
00130
00131 ENABLE_LINK_TO_PARENT(MapAbstract,Map,RobotAbstract)
00132 ;
00133
00134 ENABLE_ACCESS_TO_PARENT(MapAbstract,map)
00135 ;
00136
00137 ENABLE_ACCESS_TO_CHILDREN(SensorAbstract,Sensor,sensor);
00138
00139 hardware::hardware_sensorprop_ptr_t hardwareEstimatorPtr;
00140 history_manager_ptr_t historyManager;
00141
00142 RobotAbstract(const map_ptr_t & _mapPtr);
00143
00151 void construct(const map_ptr_t & _mapPtr, const size_t _size_state, const size_t _size_control, const size_t _size_pert);
00152
00153
00154 virtual ~RobotAbstract() {
00155 }
00156
00157 void setPoseStd(double x, double y, double z,
00158 double roll, double pitch, double yaw,
00159 double xStd, double yStd, double zStd,
00160 double rollStd, double pitchStd, double yawStd,
00161 bool degrees = false);
00162 void setPositionStd(double x, double y, double z,
00163 double xStd, double yStd, double zStd);
00164 void setOrientationStd(double roll, double pitch, double yaw,
00165 double rollStd, double pitchStd, double yawStd,
00166 bool degrees = false);
00167
00168
00169 virtual std::string categoryName() const {
00170 return "ROBOT";
00171 }
00172
00173
00174 void setId(){id(robotIds.getId());}
00175
00176 Gaussian pose;
00177 vec control;
00178 Perturbation perturbation;
00179
00194 bool constantPerturbation;
00195 kernel::Timestamp self_time;
00196 double dt_or_dx;
00197 jblas::mat controls;
00198
00199 jblas::mat XNEW_x;
00200 jblas::mat XNEW_pert;
00201 jblas::sym_mat Q;
00202
00207 void setRobotPose(jblas::vec6 const & pose_euler, bool degrees = false);
00208 jblas::vec robot_pose;
00209
00213 void setInitialPose(double x, double y, double z,
00214 double roll, double pitch, double yaw,
00215 double xStd, double yStd, double zStd,
00216 double rollStd, double pitchStd, double yawStd,
00217 bool degrees = false);
00224 void setOrigin(double x, double y, double z)
00225 {
00226 start_pos_abs(0) = x;
00227 start_pos_abs(1) = y;
00228 start_pos_abs(2) = z;
00229 start_pos_abs += start_pos_export;
00230 is_start_pos_abs_init = true;
00231 }
00232
00233 jblas::vec start_pos_export;
00234 jblas::vec start_pos_abs;
00235 bool is_start_pos_abs_init;
00236
00239 void setInitialOrientation(double roll, double pitch, double yaw,
00240 double rollStd, double pitchStd, double yawStd,
00241 bool degrees = false);
00246 void getCurrentPose(double time, jblas::vec & x, jblas::sym_mat & P);
00250 template<class VEC, class SYM_MAT>
00251 void slamPoseToRobotPose(VEC & slam_x, SYM_MAT & slam_P, jblas::vec & robot_x, jblas::sym_mat & robot_P) const
00252 {
00253
00254 jblas::vec4 q = ublas::subrange(slam_x, 3, 7);
00255 jblas::mat Q_q(4,4), FQ_fq(7,7); FQ_fq.clear();
00256 ublasExtra::normalizeJac(q, Q_q);
00257 ublas::subrange(FQ_fq, 0,3, 0,3) = jblas::identity_mat(3);
00258 ublas::subrange(FQ_fq, 3,7, 3,7) = Q_q;
00259 slam_P = ublasExtra::prod_JPJt(slam_P, FQ_fq);
00260 ublasExtra::normalize(q);
00261 ublas::subrange(slam_x, 3, 7) = q;
00262
00263
00264 jblas::vec7 quat_pose = quaternion::composeFrames(slam_x, robot_pose);
00265 jblas::vec6 euler_pose;
00266 ublas::subrange(euler_pose, 0,3) = ublas::subrange(quat_pose, 0,3) + start_pos_export;
00267 mat E_q(3, 4);
00268 jblas::vec3 euler_ori;
00269 quaternion::q2e(ublas::subrange(quat_pose, 3, 7), euler_ori, E_q);
00270 ublas::subrange(euler_pose, 3,6) = euler_ori;
00271
00272
00273 mat FE_fq(6,7); FE_fq.clear();
00274 ublas::subrange(FE_fq,0,3,0,3) = identity_mat(3);
00275 ublas::subrange(FE_fq, 3,6,3,7) = E_q;
00276
00277 jblas::mat Q_s(7,7);
00278 quaternion::composeFrames_by_dglobal(slam_x, robot_pose, Q_s);
00279
00280 mat FE_s = ublas::prod(FE_fq, Q_s);
00281
00282 robot_x = euler_pose;
00283 robot_P = prod_JPJt(slam_P, FE_s);
00284 }
00285
00286
00287 boost::mutex mutex_extrapol;
00288 bool extrapol_up_to_date;
00289 double self_time_extrapol, self_time_extrapol_init, self_time_extrapol_inc;
00290 jblas::vec state_extrapol_x, state_extrapol_x_init, state_extrapol_x_inc;
00291 jblas::sym_mat state_extrapol_P, state_extrapol_P_init, state_extrapol_P_inc;
00292 vec control_extrapol;
00293 Perturbation perturbation_extrapol;
00294 double dt_or_dx_extrapol;
00295 jblas::mat controls_extrapol;
00296 jblas::mat XNEW_x_extrapol;
00297 jblas::mat XNEW_pert_extrapol;
00298 jblas::sym_mat Q_extrapol;
00299
00300
00301 virtual size_t mySize() = 0;
00302 virtual size_t mySize_control() = 0;
00303 virtual size_t mySize_perturbation() = 0;
00304 static size_t size_control() {
00305 return 0;
00306 }
00307 static size_t size_perturbation() {
00308 return 0;
00309 }
00310 void set_control(const vec & c) {
00311 JFR_ASSERT(c.size() == mySize_control(), "RobotAbstract::set_control(vec&, double): Sizes mismatch");
00312 control = c;
00313 }
00314 void set_perturbation(const Perturbation & _pert) {
00315 perturbation = _pert;
00316 }
00317
00318 void setHardwareEstimator(hardware::hardware_sensorprop_ptr_t hardwareEstimatorPtr_)
00319 {
00320 hardwareEstimatorPtr = hardwareEstimatorPtr_;
00321 }
00322
00323
00327 inline void init(const vec & _u, const vec & _U) {
00328 JFR_ASSERT(_u.size() >= control.size(), "robotAbstract.hpp: init: wrong control size.");
00329 control = ublas::subrange(_u, 0, control.size());
00330 vec x = state.x();
00331 vec xnew(x.size());
00332
00333 init_func(x, control, _U, xnew);
00334 state.x() = xnew;
00335 }
00336
00337 inline void init(const vec & _u) {
00338 JFR_ASSERT(_u.size() >= control.size(), "robotAbstract.hpp: init: wrong control size.");
00339 control = ublas::subrange(_u, 0, control.size());
00340 vec x = state.x();
00341 vec xnew(x.size());
00342
00343 init_func(x, control, xnew);
00344 state.x() = xnew;
00345 }
00346
00351 void move();
00352
00357
00358 inline void move(const vec & _u) {
00359 JFR_ASSERT(_u.size() >= control.size(), "robotAbstract.hpp: move: wrong control size.");
00360 control = ublas::subrange(_u, 0, control.size());
00361 move();
00362 }
00363
00364 bool computeControls(double time1, double time2, jblas::mat & controls, bool release) const;
00365
00366 virtual bool move(double time);
00367
00372 void move_extrapolate();
00373 void move_extrapolate(double time);
00374 void reinit_extrapolate();
00378 void move_fake(double time);
00379
00388 void computeStatePerturbation();
00389 void computeStatePerturbation_extrapol();
00390
00391 void applyConstraints()
00392 {
00393
00394 ublas::range iaOriQuat = getQuantity(qOriQuat);
00395 jblas::sym_mat Q(4,4); Q.clear();
00396 jblas::mat QN_q(4,4);
00397 jblas::vec q = ublas::project(state.x(), iaOriQuat);
00398 ublasExtra::normalizeJac(q, QN_q);
00399 ublas::project(state.x(), iaOriQuat) = ublasExtra::normalized(q);
00400 mapPtr()->filterPtr->predict(mapPtr()->ia_used_states(), QN_q, state.ia().compose(iaOriQuat), Q);
00401 }
00402
00403 virtual void writeLogHeader(kernel::DataLogger& log) const;
00404 virtual void writeLogData(kernel::DataLogger& log) const;
00405
00406 void stopDumping();
00407
00408 void setHistoryManager(history_manager_ptr_t hm) { historyManager = hm; }
00409
00410 protected:
00411
00412
00435 virtual void move_func(const vec & _x, const vec & _u, const vec& _n, const double _dt, vec & _xnew,
00436 mat & _XNEW_x, mat & _XNEW_pert, unsigned tempSet = 0) const = 0;
00445 virtual void init_func(const vec & _x, const vec & _u, const vec & _U, vec & _xnew) {}
00446 virtual void init_func(const vec & _x, const vec & _u, vec & _xnew) {}
00447
00448
00449 };
00450
00451 }
00452 }
00453
00454 #endif // #ifndef __RobotAbstract_H__
00455
00456
00457
00458
00459
00460
00461
00462