00001
00012 #ifndef SENSORABSLOC_HPP_
00013 #define SENSORABSLOC_HPP_
00014
00015 #include "jmath/jblas.hpp"
00016 #include "jmath/ublasExtra.hpp"
00017 #include "jmath/misc.hpp"
00018
00019 #include "rtslam/rtSlam.hpp"
00020 #include "rtslam/quatTools.hpp"
00021 #include "rtslam/sensorAbstract.hpp"
00022 #include "rtslam/innovation.hpp"
00023
00024 namespace jafar {
00025 namespace rtslam {
00026
00027 class SensorAbsloc;
00028 typedef boost::shared_ptr<SensorAbsloc> absloc_ptr_t;
00029
00037 class SensorAbsloc: public SensorProprioAbstract {
00038 protected:
00039 jblas::ind_array ia_rs;
00040 Innovation *innovation;
00041 Measurement *measurement;
00042 Expectation *expectation;
00043 jblas::mat EXP_rs;
00044 jblas::mat INN_rs;
00045 jblas::mat EXP_q;
00046 double mahaDist2;
00047 double sigMax;
00048 int inns;
00049 int dats;
00050 jblas::vec origin;
00051
00052 private:
00053 size_t indexE_Pos, indexE_OriEuler, indexE_Bundleobs, indexE_AbsVel, indexE_NormVel, indexE_Vel;
00054 int indexD_Pos, indexD_OriQuat, indexD_OriEuler, indexD_Bundleobs, indexD_AbsVel, indexD_NormVel, indexD_Vel;
00055 ublas::range indexR_Pos, indexR_OriQuat, indexR_AbsVel, indexR_AngVel;
00056 ublas::range indexJ_Pos, indexJ_OriQuat, indexJ_AbsVel, indexJ_AngVel;
00057 hardware::HardwareSensorProprioAbstract::CovType covType;
00058
00059 public:
00060
00061 std::vector<RobotAbstract::Quantity> returnQuants(bool needPose, bool needVel, bool needAngVel)
00062 {
00063 std::vector<RobotAbstract::Quantity> res;
00064 if (needPose) { res.push_back(RobotAbstract::qPos); res.push_back(RobotAbstract::qOriQuat); }
00065 if (needVel) res.push_back(RobotAbstract::qAbsVel);
00066 if (needAngVel) res.push_back(RobotAbstract::qAngVel);
00067 return res;
00068 }
00069
00070
00071
00072 SensorAbsloc(const robot_ptr_t & robPtr, const filtered_obj_t inFilter = UNFILTERED, double mahaDist = -1.0, double sigMax = 1e9,
00073 bool needPose = true, bool needVel = false, bool needAngVel = false):
00074 SensorProprioAbstract(robPtr, inFilter, 0, returnQuants(needPose, needVel, needAngVel)),
00075 ia_rs(ia_globalPose), innovation(NULL), measurement(NULL), expectation(NULL),
00076 mahaDist2(mahaDist*fabs(mahaDist)), sigMax(sigMax), inns(0), dats(0)
00077 {}
00078
00079 ~SensorAbsloc() { delete innovation; delete measurement; }
00080 virtual void setHardwareSensor(hardware::hardware_sensorprop_ptr_t hardwareSensorPtr_)
00081 {
00082 hardwareSensorPtr = hardwareSensorPtr_;
00083
00084 inns = hardwareSensorPtr->obsSize();
00085 dats = hardwareSensorPtr->dataSize();
00086 innovation = new Innovation(inns);
00087 measurement = new Measurement(inns);
00088 expectation = new Expectation(inns);
00089 EXP_rs.resize(inns, ia_rs.size(), false);
00090 INN_rs.resize(inns, ia_rs.size(), false);
00091 EXP_q.resize(3, 4, false);
00092
00093
00094 size_t indexE = 0;
00095
00096
00097 indexD_Pos = hardwareSensorPtr->getQuantity(hardware::HardwareSensorProprioAbstract::qPos);
00098 if (indexD_Pos >= 0) { indexE_Pos = indexE; indexE += hardwareSensorPtr->QuantityObsSizes[hardware::HardwareSensorProprioAbstract::qPos]; }
00099
00100 indexD_OriQuat = hardwareSensorPtr->getQuantity(hardware::HardwareSensorProprioAbstract::qOriQuat);
00101 if (indexD_OriQuat >= 0) { indexE_OriEuler = indexE; indexE += hardwareSensorPtr->QuantityObsSizes[hardware::HardwareSensorProprioAbstract::qOriEuler]; }
00102
00103 indexD_OriEuler = hardwareSensorPtr->getQuantity(hardware::HardwareSensorProprioAbstract::qOriEuler);
00104 if (indexD_OriEuler >= 0) { indexE_OriEuler = indexE; indexE += hardwareSensorPtr->QuantityObsSizes[hardware::HardwareSensorProprioAbstract::qOriEuler]; }
00105
00106 indexD_Bundleobs = hardwareSensorPtr->getQuantity(hardware::HardwareSensorProprioAbstract::qBundleobs);
00107 if (indexD_Bundleobs >= 0) { indexE_Bundleobs = indexE; indexE += hardwareSensorPtr->QuantityObsSizes[hardware::HardwareSensorProprioAbstract::qBundleobs]; }
00108
00109 indexD_AbsVel = hardwareSensorPtr->getQuantity(hardware::HardwareSensorProprioAbstract::qAbsVel);
00110 if (indexD_AbsVel >= 0) { indexE_AbsVel = indexE; indexE += hardwareSensorPtr->QuantityObsSizes[hardware::HardwareSensorProprioAbstract::qAbsVel]; }
00111
00112 indexD_NormVel = hardwareSensorPtr->getQuantity(hardware::HardwareSensorProprioAbstract::qNormVel);
00113 if (indexD_NormVel >= 0) { indexE_NormVel = indexE; indexE += hardwareSensorPtr->QuantityObsSizes[hardware::HardwareSensorProprioAbstract::qNormVel]; }
00114
00115 indexD_Vel = hardwareSensorPtr->getQuantity(hardware::HardwareSensorProprioAbstract::qVel);
00116 if (indexD_Vel >= 0) { indexE_Vel = indexE; indexE += hardwareSensorPtr->QuantityObsSizes[hardware::HardwareSensorProprioAbstract::qVel]; }
00117
00118 indexR_Pos = quantsState.getQuantity(RobotQuantity::qPos);
00119 indexR_OriQuat = quantsState.getQuantity(RobotQuantity::qOriQuat);
00120 indexR_AbsVel = quantsState.getQuantity(RobotQuantity::qAbsVel);
00121 indexR_AngVel = quantsState.getQuantity(RobotQuantity::qAngVel);
00122
00123 indexJ_Pos = quantsJacob.getQuantity(RobotQuantity::qPos);
00124 indexJ_OriQuat = quantsJacob.getQuantity(RobotQuantity::qOriQuat);
00125 indexJ_AbsVel = quantsJacob.getQuantity(RobotQuantity::qAbsVel);
00126 indexJ_AngVel = quantsJacob.getQuantity(RobotQuantity::qAngVel);
00127
00128 covType = hardwareSensorPtr->covType();
00129 }
00130
00131
00132 virtual void init(unsigned id)
00133 {
00134 RawInfos infos;
00135 queryAvailableRaws(infos);
00136
00137
00138 jblas::vec3 min_var; min_var(0) = min_var(1) = min_var(2) = 1e3;
00139 for(std::vector<RawInfo>::iterator it = infos.available.begin(); it != infos.available.end(); ++it)
00140 {
00141 hardwareSensorPtr->observeRaw((*it).id, reading);
00142 for(int i = 0; i < 3; ++i) if (reading.data(i+1+dats) < min_var(i)) min_var(i) = reading.data(i+1+dats);
00143 if ((*it).id == id) break;
00144 }
00145
00146
00147 jblas::vec3 average; average.clear();
00148 jblas::vec3 sum_coeffs; sum_coeffs.clear();
00149
00150 for(std::vector<RawInfo>::iterator it = infos.available.begin(); it != infos.available.end(); ++it)
00151 {
00152 hardwareSensorPtr->observeRaw((*it).id, reading);
00153 for(int i = 0; i < 3; ++i)
00154 if (reading.data(i+1+dats) < 2*min_var(i))
00155 { average(i) += reading.data(i+1)*reading.data(i+1+dats); sum_coeffs(i) += reading.data(i+1+dats); }
00156
00157 if ((*it).id == id) break;
00158 }
00159 for(int i = 0; i < 3; ++i) average(i) /= sum_coeffs(i);
00160
00161
00162
00163 for(int i = 0; i < 3; ++i) { reading.data(i+1) = average(i); reading.data(i+1+dats) = min_var(i); }
00164
00165 }
00166
00167
00168 virtual void process(unsigned id, double date_limit)
00169 {
00170
00171 if (robotPtr()->is_start_pos_abs_init) use_for_init = false;
00172
00173 if (use_for_init)
00174 init(id);
00175 else
00176 hardwareSensorPtr->getRaw(id, reading);
00177
00178 EXP_rs.clear();
00179 expectation->P() = jblas::zero_mat(inns);
00180 jblas::vec T = ublas::subrange(pose.x(), 0, 3);
00181 jblas::vec r = ublas::subrange(pose.x(), 3, 7);
00182 jblas::vec p = ublas::subrange(robotPtr()->pose.x(), 0, 3);
00183 jblas::vec q = ublas::subrange(robotPtr()->pose.x(), 3, 7);
00184 jblas::vec Tr = quaternion::rotate(q,T);
00185
00186 bool detect_faults = false;
00187
00188
00189 if (indexD_Pos >= 0)
00190 {
00191 for(size_t i = 0; i < 3; ++i) if (reading.data(indexD_Pos+i+dats) > sigMax) if (!use_for_init) return;
00192
00193
00194 quaternion::rotate_by_dq(q, T, EXP_q);
00195 ublas::subrange(EXP_rs, indexE_Pos,indexE_Pos+3, indexJ_Pos.start(), indexJ_Pos.start()+indexJ_Pos.size()) = jblas::identity_mat(3);
00196 ublas::subrange(EXP_rs, indexE_Pos,indexE_Pos+3, indexJ_OriQuat.start(), indexJ_OriQuat.start()+indexJ_OriQuat.size()) = EXP_q;
00197 ublas::subrange(expectation->x(), indexE_Pos,indexE_Pos+3) = p + Tr;
00198
00199
00200 ublas::subrange(measurement->x(), indexE_Pos,indexE_Pos+3) = ublas::subrange(reading.data, indexD_Pos,indexD_Pos+3) - robotPtr()->start_pos_abs;
00201 for(int i = 0; i < 3; ++i) measurement->P()(indexE_Pos+i,indexE_Pos+i) = jmath::sqr(reading.data(indexD_Pos+i+dats));
00202
00203 }
00204
00205
00206
00207
00208
00209
00210
00211
00212 if (indexD_OriQuat >= 0 || indexD_OriEuler >= 0)
00213 {
00214 bool isEuler = (indexD_OriEuler >= 0);
00215 size_t indexE = indexE_OriEuler;
00216
00217 size_t indexD = isEuler ? indexD_OriEuler : indexD_OriQuat;
00218 size_t sizeD = isEuler ? 3 : 4;
00219 for(size_t i = 0; i < sizeD; ++i) if (reading.data(indexD+i+dats) > sigMax) if (!use_for_init) return;
00220
00221
00222
00223 jblas::mat QR_q(4,4);
00224 jblas::vec4 qr = quaternion::qProd(q, r);
00225 quaternion::qProd_by_dq1(r, QR_q);
00226 jblas::mat ER_qr(3,4);
00227 jblas::vec3 er; quaternion::q2e(qr, er, ER_qr);
00228 jblas::mat ER_q = ublas::prod(ER_qr, QR_q);
00229 ublas::subrange(expectation->x(), indexE,indexE+3) = er;
00230 ublas::subrange(EXP_rs, indexE,indexE+3, indexJ_OriQuat.start(), indexJ_OriQuat.start()+indexJ_OriQuat.size()) = ER_q;
00231
00232
00233 if (isEuler)
00234 {
00235 ublas::subrange(measurement->x(), indexE,indexE+3) = ublas::subrange(reading.data, indexD_OriEuler,indexD_OriEuler+3);
00236 ublas::subrange(measurement->P(), indexE,indexE+3, indexE,indexE+3) =
00237 hardwareSensorPtr->extractDataCovBlock(indexD_OriEuler, 3);
00238 } else
00239 {
00240
00241 jblas::mat E_q(3,4); jblas::vec3 euler;
00242 quaternion::q2e(ublas::subrange(reading.data, indexD_OriQuat,indexD_OriQuat+4), euler, E_q);
00243 ublas::subrange(measurement->x(), indexE,indexE+3) = euler;
00244 jblas::sym_mat quat_P = hardwareSensorPtr->extractDataCovBlock(indexD_OriQuat, 4);
00245 ublas::subrange(measurement->P(), indexE,indexE+3, indexE,indexE+3) = prod_JPJt(quat_P, E_q);
00246 }
00247
00248
00249
00250 for(size_t i = indexE; i < indexE+3; ++i)
00251 {
00252 double inn = measurement->x()(i) - expectation->x()(i);
00253 if (inn > M_PI) measurement->x()(i) -= 2*M_PI; else
00254 if (inn < -M_PI) measurement->x()(i) += 2*M_PI;
00255 }
00256
00257
00258
00259 }
00260
00261
00262 if (indexD_Bundleobs >= 0)
00263 {
00264
00265 jblas::vec3 pos = ublas::subrange(reading.data, indexD_Bundleobs+0,indexD_Bundleobs+3);
00266 jblas::vec3 dir = ublas::subrange(reading.data, indexD_Bundleobs+3,indexD_Bundleobs+6);
00267
00268
00269 jblas::mat33 U_p;
00270 jblas::vec3 u = pos-p;
00271 jmath::ublasExtra::normalizeJac(u, U_p);
00272 jmath::ublasExtra::normalize(u);
00273 ublas::subrange(expectation->x(), indexE_Bundleobs,indexE_Bundleobs+3) = u;
00274 ublas::subrange(EXP_rs, indexE_Bundleobs,indexE_Bundleobs+3, indexJ_OriQuat.start(), indexJ_OriQuat.start()+indexJ_OriQuat.size()) = -U_p;
00275
00276 jblas::sym_mat Pos = hardwareSensorPtr->extractDataCovBlock(indexD_Bundleobs, 3);
00277 ublas::subrange(expectation->P(), indexE_Bundleobs,indexE_Bundleobs+3, indexE_Bundleobs,indexE_Bundleobs+3) = prod_JPJt(Pos, U_p);
00278
00279
00280 ublas::subrange(measurement->x(), indexE_Bundleobs,indexE_Bundleobs+3) = dir;
00281 ublas::subrange(measurement->P(), indexE_Bundleobs,indexE_Bundleobs+3, indexE_Bundleobs,indexE_Bundleobs+3) =
00282 ublasExtra::createSymMat(reading.data, dats+1, dats, 3, 3);
00283
00284 detect_faults = true;
00285 }
00286
00287
00288 if (indexD_NormVel >= 0)
00289 {
00290 if (reading.data(indexD_NormVel+0+dats) > sigMax) if (!use_for_init) return;
00291
00292 jblas::vec v = ublas::project(robotPtr()->state.x(), indexR_AbsVel);
00293
00294 JFR_ASSERT(ublas::norm_2(ublas::subrange(T,0,2)) < 1e-6, "Currently odometry is only supported with SlamOrigin vertically aligned with RobotOrigin");
00295
00296
00297
00298 jblas::mat NV_v(1, 3);
00299 expectation->x(indexE_NormVel) = ublasExtra::norm_2(v, NV_v);
00300 ublas::subrange(EXP_rs, indexE_NormVel,indexE_NormVel+1, indexJ_AbsVel.start(), indexJ_AbsVel.start()+indexJ_AbsVel.size()) = NV_v;
00301
00302 ublas::subrange(measurement->x(), indexE_NormVel,indexE_NormVel+1) = ublas::subrange(reading.data, indexD_NormVel,indexD_NormVel+1);
00303 measurement->P()(indexE_NormVel,indexE_NormVel) = jmath::sqr(reading.data(indexD_NormVel+1));
00304
00305 detect_faults = false;
00306 mahaDist2 = -1;
00307 }
00308
00309
00310 if (use_for_init)
00311 {
00312
00313
00314
00315 if (indexD_OriQuat >= 0 || indexD_OriEuler >= 0)
00316 {
00317 size_t indexE = indexE_OriEuler;
00318 jblas::mat Q_exp(4,3);
00319 quaternion::e2q(ublas::subrange(measurement->x(), indexE,indexE+3), q, Q_exp);
00320
00321 jblas::vec ri = quaternion::q2qc(r);
00322 q = quaternion::qProd(q, ri);
00323 jblas::mat Q_r(4,4);
00324 quaternion::qProd_by_dq1(ri, Q_r);
00325 Q_exp = ublas::prod(Q_r, Q_exp);
00326
00327 ublas::subrange(robotPtr()->pose.x(), 3, 7) = q;
00328 ublas::subrange(robotPtr()->pose.P(), 3,7, 3,7) = ublasExtra::prod_JPJt(
00329 ublas::subrange(measurement->P(), indexE,indexE+3, indexE,indexE+3), Q_exp);
00330
00331
00332 Tr = quaternion::rotate(q,T);
00333
00334 std::cout << "AbsLoc sets initial orientation q = " << ublas::subrange(robotPtr()->pose.x(), 3, 7) <<
00335 " e = " << quaternion::q2e(ublas::subrange(robotPtr()->pose.x(), 3, 7)) << std::endl;
00336 }
00337
00338 if (indexD_Pos >= 0)
00339 {
00340 robotPtr()->start_pos_abs = ublas::subrange(measurement->x(), indexE_Pos,indexE_Pos+3) - Tr - ublas::subrange(robotPtr()->state.x(),0,3);
00341 ublas::subrange(robotPtr()->pose.x(), 0, 3) = jblas::zero_vec(3);
00342 ublas::subrange(robotPtr()->pose.P(), 0,3, 0,3) = ublas::subrange(measurement->P(), indexE_Pos,indexE_Pos+3, indexE_Pos,indexE_Pos+3) +
00343 ublasExtra::prod_JPJt(ublas::subrange(robotPtr()->pose.P(), 3,7, 3,7), EXP_q);
00344
00345 std::cout << "AbsLoc has origin " << robotPtr()->start_pos_abs <<
00346 " ; initial position " << ublas::subrange(robotPtr()->pose.x(), 0,3) <<
00347 " ; initial position var " << ublas::subrange(robotPtr()->pose.P(), 0,3, 0,3) << std::endl;
00348 }
00349 } else
00350 {
00351
00352 expectation->P() += ublasExtra::prod_JPJt(ublas::project(robotPtr()->mapPtr()->filterPtr->P(), ia_rs, ia_rs), EXP_rs);
00353 innovation->x() = measurement->x() - expectation->x();
00354 innovation->P() = measurement->P() + expectation->P();
00355 INN_rs = -EXP_rs;
00356
00357
00358 bool integrate = true;
00359 if (mahaDist2 > 0.0)
00360 {
00361 double maha;
00362 if (!detect_faults)
00363 maha = innovation->mahalanobis();
00364 else
00365 {
00366
00367
00368
00369
00370 jafar::jmath::ublasExtra::lu_inv(expectation->P(), innovation->iP_);
00371 maha = ublasExtra::prod_xt_iP_x(innovation->iP_, innovation->x());
00372 }
00373 if (maha > mahaDist2) integrate = false;
00374 }
00375
00376
00377 if (integrate)
00378 {
00379 map_ptr_t mapPtr = robotPtr()->mapPtr();
00380 ind_array ia_x = mapPtr->ia_used_states();
00381 mapPtr->filterPtr->correct(ia_x,*innovation,INN_rs,ia_rs);
00382 }
00383 }
00384
00385 if (use_for_init)
00386 {
00387 use_for_init = false;
00388 robotPtr()->is_start_pos_abs_init = true;
00389 hardwareSensorPtr->getRaw(id, reading);
00390 }
00391
00392
00393 }
00394
00395
00396 };
00397 }}
00398
00399 #endif