00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029 #include <hector_pose_estimation/system/generic_quaternion_system_model.h>
00030 #include <hector_pose_estimation/pose_estimation.h>
00031 #include <hector_pose_estimation/filter/set_filter.h>
00032
00033 namespace hector_pose_estimation {
00034
00035 template class System_<GenericQuaternionSystemModel>;
00036
00037 GenericQuaternionSystemModel::GenericQuaternionSystemModel()
00038 {
00039 angular_acceleration_stddev_ = 360.0 * M_PI/180.0;
00040
00041
00042 velocity_stddev_ = 0.0;
00043
00044
00045 parameters().addAlias("gravity", gravity_);
00046 parameters().add("angular_acceleration_stddev", angular_acceleration_stddev_);
00047 parameters().addAlias("rate_stddev", rate_stddev_);
00048 parameters().addAlias("acceleration_stddev", acceleration_stddev_);
00049 parameters().add("velocity_stddev", velocity_stddev_);
00050 }
00051
00052 GenericQuaternionSystemModel::~GenericQuaternionSystemModel()
00053 {
00054 }
00055
00056 bool GenericQuaternionSystemModel::init(PoseEstimation& estimator, State& state)
00057 {
00058 gyro_ = System::create(new GyroModel, "gyro");
00059 accelerometer_ = System::create(new AccelerometerModel, "accelerometer");
00060
00061 gravity_ = estimator.parameters().get("gravity_magnitude");
00062 rate_stddev_ = gyro_->parameters().get("stddev");
00063 acceleration_stddev_ = accelerometer_->parameters().get("stddev");
00064
00065 imu_ = estimator.registerInput<InputType>("raw_imu");
00066 estimator.addSystem(gyro_, "gyro");
00067 estimator.addSystem(accelerometer_, "accelerometer");
00068 return true;
00069 }
00070
00071 void GenericQuaternionSystemModel::getPrior(State &state) {
00072 if (state.getOrientationIndex() >= 0) {
00073 state.P()(State::QUATERNION_W,State::QUATERNION_W) = 0.25 * 1.0;
00074 state.P()(State::QUATERNION_X,State::QUATERNION_X) = 0.25 * 1.0;
00075 state.P()(State::QUATERNION_Y,State::QUATERNION_Y) = 0.25 * 1.0;
00076 state.P()(State::QUATERNION_Z,State::QUATERNION_Z) = 0.25 * 1.0;
00077 }
00078
00079 if (state.getRateIndex() >= 0) {
00080 state.P()(State::RATE_X,State::RATE_X) = pow(0.0 * M_PI/180.0, 2);
00081 state.P()(State::RATE_Y,State::RATE_Y) = pow(0.0 * M_PI/180.0, 2);
00082 state.P()(State::RATE_Z,State::RATE_Z) = pow(0.0 * M_PI/180.0, 2);
00083 }
00084
00085 if (state.getPositionIndex() >= 0) {
00086 state.P()(State::POSITION_X,State::POSITION_X) = 0.0;
00087 state.P()(State::POSITION_Y,State::POSITION_Y) = 0.0;
00088 state.P()(State::POSITION_Z,State::POSITION_Z) = 0.0;
00089 }
00090
00091 if (state.getVelocityIndex() >= 0) {
00092 state.P()(State::VELOCITY_X,State::VELOCITY_X) = 0.0;
00093 state.P()(State::VELOCITY_Y,State::VELOCITY_Y) = 0.0;
00094 state.P()(State::VELOCITY_Z,State::VELOCITY_Z) = 0.0;
00095 }
00096 }
00097
00098 bool GenericQuaternionSystemModel::prepareUpdate(State& state, double dt)
00099 {
00100 if (state.getAccelerationIndex() >= 0)
00101 acceleration = state.getAcceleration();
00102 else
00103 acceleration = imu_->getAcceleration() + accelerometer_->getModel()->getBias();
00104
00105 if (state.getRateIndex() >= 0)
00106 rate = state.getRate();
00107 else
00108 rate = imu_->getRate() + gyro_->getModel()->getBias();
00109
00110 state.getRotationMatrix(R);
00111 return true;
00112 }
00113
00114 void GenericQuaternionSystemModel::getDerivative(StateVector& x_dot, const State& state)
00115 {
00116 State::ConstOrientationType q(state.getOrientation());
00117 State::ConstVelocityType v(state.getVelocity());
00118
00119
00120 x_dot = 0.0;
00121
00122 if (state.getOrientationIndex() >= 0) {
00123 x_dot(State::QUATERNION_W) = 0.5*( (-rate.x())*q.x()+(-rate.y())*q.y()+(-rate.z())*q.z());
00124 x_dot(State::QUATERNION_X) = 0.5*(( rate.x())*q.w() +( rate.z())*q.y()+(-rate.y())*q.z());
00125 x_dot(State::QUATERNION_Y) = 0.5*(( rate.y())*q.w()+(-rate.z())*q.x() +( rate.x())*q.z());
00126 x_dot(State::QUATERNION_Z) = 0.5*(( rate.z())*q.w()+( rate.y())*q.x()+(-rate.x())*q.y() );
00127 }
00128
00129 #ifdef VELOCITY_IN_BODY_FRAME
00130 ColumnVector3 wxv = rate.cross(v);
00131
00132 if (state.getSystemStatus() & STATE_VELOCITY_XY && state.getVelocityIndex() >= 0) {
00133 x_dot(State::VELOCITY_X) = acceleration.x() - wxv.x() + R(2,0) * gravity_;
00134 x_dot(State::VELOCITY_Y) = acceleration.y() - wxv.y() + R(2,1) * gravity_;
00135 }
00136 if (state.getSystemStatus() & STATE_VELOCITY_Z && state.getVelocityIndex() >= 0) {
00137 x_dot(State::VELOCITY_Z) = acceleration.z() - wxv.z() + R(2,2) * gravity_;
00138 }
00139
00140 if (state.getSystemStatus() & STATE_POSITION_XY) {
00141 x_dot(State::POSITION_X) = R(0,0)*v.x() + R(0,1)*v.y() + R(0,2)*v.z();
00142 x_dot(State::POSITION_Y) = R(1,0)*v.x() + R(1,1)*v.y() + R(1,2)*v.z();
00143 }
00144 if (state.getSystemStatus() & STATE_POSITION_Z) {
00145 x_dot(State::POSITION_Z) = R(2,0)*v.x() + R(2,1)*v.y() + R(2,2)*v.z();
00146 }
00147
00148 #else
00149 if (state.getSystemStatus() & STATE_VELOCITY_XY && state.getVelocityIndex() >= 0) {
00150 x_dot(State::VELOCITY_X) = R(0,0)*acceleration.x() + R(0,1)*acceleration.y() + R(0,2)*acceleration.z();
00151 x_dot(State::VELOCITY_Y) = R(1,0)*acceleration.x() + R(1,1)*acceleration.y() + R(1,2)*acceleration.z();
00152 }
00153 if (state.getSystemStatus() & STATE_VELOCITY_Z && state.getVelocityIndex() >= 0) {
00154 x_dot(State::VELOCITY_Z) = R(2,0)*acceleration.x() + R(2,1)*acceleration.y() + R(2,2)*acceleration.z() + gravity_;
00155 }
00156
00157 if (state.getSystemStatus() & STATE_POSITION_XY) {
00158 x_dot(State::POSITION_X) = v.x();
00159 x_dot(State::POSITION_Y) = v.y();
00160 }
00161 if (state.getSystemStatus() & STATE_POSITION_Z) {
00162 x_dot(State::POSITION_Z) = v.z();
00163 }
00164 #endif // VELOCITY_IN_BODY_FRAME
00165 }
00166
00167 void GenericQuaternionSystemModel::getSystemNoise(NoiseVariance& Q, const State& state, bool init)
00168 {
00169 if (init) {
00170 if (state.getRateIndex() >= 0)
00171 Q(State::RATE_X,State::RATE_X) = Q(State::RATE_Y,State::RATE_Y) = Q(State::RATE_Z,State::RATE_Z) = pow(angular_acceleration_stddev_, 2);
00172 if (state.getPositionIndex() >= 0)
00173 Q(State::POSITION_X,State::POSITION_X) = Q(State::POSITION_Y,State::POSITION_Y) = Q(State::POSITION_Z,State::POSITION_Z) = pow(velocity_stddev_, 2);
00174 if (state.getRateIndex() >= 0)
00175 Q(State::VELOCITY_X,State::VELOCITY_X) = Q(State::VELOCITY_Y,State::VELOCITY_Y) = Q(State::VELOCITY_Z,State::VELOCITY_Z) = pow(acceleration_stddev_, 2);
00176
00177
00178
00179 }
00180
00181 if ((double) rate_stddev_ > 0.0 && state.getOrientationIndex() >= 0) {
00182 State::ConstOrientationType q(state.getOrientation());
00183 double rate_variance_4 = 0.25 * pow(rate_stddev_, 2);
00184 Q(State::QUATERNION_W,State::QUATERNION_W) = rate_variance_4 * (q.x()*q.x()+q.y()*q.y()+q.z()*q.z());
00185 Q(State::QUATERNION_X,State::QUATERNION_X) = rate_variance_4 * (q.w()*q.w()+q.y()*q.y()+q.z()*q.z());
00186 Q(State::QUATERNION_Y,State::QUATERNION_Y) = rate_variance_4 * (q.w()*q.w()+q.x()*q.x()+q.z()*q.z());
00187 Q(State::QUATERNION_Z,State::QUATERNION_Z) = rate_variance_4 * (q.w()*q.w()+q.x()*q.x()+q.y()*q.y());
00188 }
00189 }
00190
00191 void GenericQuaternionSystemModel::getStateJacobian(SystemMatrix& A, const State& state, bool)
00192 {
00193 State::ConstOrientationType q(state.getOrientation());
00194 State::ConstVelocityType v(state.getVelocity());
00195
00196 A = 0.0;
00197
00198
00199
00200 if (state.getOrientationIndex() >= 0) {
00201 A(State::QUATERNION_W,State::QUATERNION_X) = (-0.5*rate.x());
00202 A(State::QUATERNION_W,State::QUATERNION_Y) = (-0.5*rate.y());
00203 A(State::QUATERNION_W,State::QUATERNION_Z) = (-0.5*rate.z());
00204 A(State::QUATERNION_X,State::QUATERNION_W) = ( 0.5*rate.x());
00205 A(State::QUATERNION_X,State::QUATERNION_Y) = ( 0.5*rate.z());
00206 A(State::QUATERNION_X,State::QUATERNION_Z) = (-0.5*rate.y());
00207 A(State::QUATERNION_Y,State::QUATERNION_W) = ( 0.5*rate.y());
00208 A(State::QUATERNION_Y,State::QUATERNION_X) = (-0.5*rate.z());
00209 A(State::QUATERNION_Y,State::QUATERNION_Z) = ( 0.5*rate.x());
00210 A(State::QUATERNION_Z,State::QUATERNION_W) = ( 0.5*rate.z());
00211 A(State::QUATERNION_Z,State::QUATERNION_X) = ( 0.5*rate.y());
00212 A(State::QUATERNION_Z,State::QUATERNION_Y) = (-0.5*rate.x());
00213
00214 if (state.getRateIndex() >= 0) {
00215 A(State::QUATERNION_W,State::RATE_X) = -0.5*q.x();
00216 A(State::QUATERNION_W,State::RATE_Y) = -0.5*q.y();
00217 A(State::QUATERNION_W,State::RATE_Z) = -0.5*q.z();
00218
00219 A(State::QUATERNION_X,State::RATE_X) = 0.5*q.w();
00220 A(State::QUATERNION_X,State::RATE_Y) = -0.5*q.z();
00221 A(State::QUATERNION_X,State::RATE_Z) = 0.5*q.y();
00222
00223 A(State::QUATERNION_Y,State::RATE_X) = 0.5*q.z();
00224 A(State::QUATERNION_Y,State::RATE_Y) = 0.5*q.w();
00225 A(State::QUATERNION_Y,State::RATE_Z) = -0.5*q.x();
00226
00227 A(State::QUATERNION_Z,State::RATE_X) = -0.5*q.y();
00228 A(State::QUATERNION_Z,State::RATE_Y) = 0.5*q.x();
00229 A(State::QUATERNION_Z,State::RATE_Z) = 0.5*q.w();
00230 }
00231 }
00232
00233 #ifdef VELOCITY_IN_BODY_FRAME
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243 if (state.getVelocityIndex() >= 0 && state.getSystemStatus() & STATE_VELOCITY_XY) {
00244 if (state.getRateIndex() >= 0) {
00245 A(State::VELOCITY_X,State::RATE_X) = 0.0;
00246 A(State::VELOCITY_X,State::RATE_Y) = -v.z();
00247 A(State::VELOCITY_X,State::RATE_Z) = v.y();
00248
00249 A(State::VELOCITY_Y,State::RATE_X) = v.z();
00250 A(State::VELOCITY_Y,State::RATE_Y) = 0.0;
00251 A(State::VELOCITY_Y,State::RATE_Z) = -v.x();
00252 }
00253
00254 A(State::VELOCITY_X,State::VELOCITY_X) = 0.0;
00255 A(State::VELOCITY_X,State::VELOCITY_Y) = rate.z();
00256 A(State::VELOCITY_X,State::VELOCITY_Z) = -rate.y();
00257
00258 A(State::VELOCITY_Y,State::VELOCITY_X) = -rate.z();
00259 A(State::VELOCITY_Y,State::VELOCITY_Y) = 0.0;
00260 A(State::VELOCITY_Y,State::VELOCITY_Z) = rate.x();
00261
00262 if (state.getOrientationIndex() >= 0) {
00263 A(State::VELOCITY_X,State::QUATERNION_W) = -2.0*q.y()*gravity_;
00264 A(State::VELOCITY_X,State::QUATERNION_X) = 2.0*q.z()*gravity_;
00265 A(State::VELOCITY_X,State::QUATERNION_Y) = -2.0*q.w()*gravity_;
00266 A(State::VELOCITY_X,State::QUATERNION_Z) = 2.0*q.x()*gravity_;
00267
00268 A(State::VELOCITY_Y,State::QUATERNION_W) = 2.0*q.x()*gravity_;
00269 A(State::VELOCITY_Y,State::QUATERNION_X) = 2.0*q.w()*gravity_;
00270 A(State::VELOCITY_Y,State::QUATERNION_Y) = 2.0*q.z()*gravity_;
00271 A(State::VELOCITY_Y,State::QUATERNION_Z) = 2.0*q.y()*gravity_;
00272 }
00273 }
00274
00275 if (state.getVelocityIndex() >= 0 && state.getSystemStatus() & STATE_VELOCITY_Z) {
00276 if (state.getRateIndex() >= 0) {
00277 A(State::VELOCITY_Z,State::RATE_X) = -v.y();
00278 A(State::VELOCITY_Z,State::RATE_Y) = v.x();
00279 A(State::VELOCITY_Z,State::RATE_Z) = 0.0;
00280 }
00281
00282 A(State::VELOCITY_Z,State::VELOCITY_X) = rate.y();
00283 A(State::VELOCITY_Z,State::VELOCITY_Y) = -rate.x();
00284 A(State::VELOCITY_Z,State::VELOCITY_Z) = 0.0;
00285
00286 if (state.getOrientationIndex() >= 0) {
00287 A(State::VELOCITY_Z,State::QUATERNION_W) = 2.0*q.w()*gravity_;
00288 A(State::VELOCITY_Z,State::QUATERNION_X) = -2.0*q.x()*gravity_;
00289 A(State::VELOCITY_Z,State::QUATERNION_Y) = -2.0*q.y()*gravity_;
00290 A(State::VELOCITY_Z,State::QUATERNION_Z) = 2.0*q.z()*gravity_;
00291 }
00292 }
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302 if (state.getPositionIndex() >= 0 && state.getSystemStatus() & STATE_POSITION_XY) {
00303 if (state.getOrientationIndex() >= 0) {
00304 A(State::POSITION_X,State::QUATERNION_W) = -2.0*q.z()*v.y()+2.0*q.y()*v.z()+2.0*q.w()*v.x();
00305 A(State::POSITION_X,State::QUATERNION_X) = 2.0*q.y()*v.y()+2.0*q.z()*v.z()+2.0*q.x()*v.x();
00306 A(State::POSITION_X,State::QUATERNION_Y) = -2.0*q.y()*v.x()+2.0*q.x()*v.y()+2.0*q.w()*v.z();
00307 A(State::POSITION_X,State::QUATERNION_Z) = -2.0*q.z()*v.x()-2.0*q.w()*v.y()+2.0*q.x()*v.z();
00308
00309 A(State::POSITION_Y,State::QUATERNION_W) = 2.0*q.z()*v.x()-2.0*q.x()*v.z()+2.0*q.w()*v.y();
00310 A(State::POSITION_Y,State::QUATERNION_X) = 2.0*q.y()*v.x()-2.0*q.x()*v.y()-2.0*q.w()*v.z();
00311 A(State::POSITION_Y,State::QUATERNION_Y) = 2.0*q.x()*v.x()+2.0*q.z()*v.z()+2.0*q.y()*v.y();
00312 A(State::POSITION_Y,State::QUATERNION_Z) = 2.0*q.w()*v.x()-2.0*q.z()*v.y()+2.0*q.y()*v.z();
00313 }
00314
00315 if (state.getVelocityIndex() >= 0) {
00316 A(State::POSITION_X,State::VELOCITY_X) = R(0,0);
00317 A(State::POSITION_X,State::VELOCITY_Y) = R(0,1);
00318 A(State::POSITION_X,State::VELOCITY_Z) = R(0,2);
00319
00320 A(State::POSITION_Y,State::VELOCITY_X) = R(1,0);
00321 A(State::POSITION_Y,State::VELOCITY_Y) = R(1,1);
00322 A(State::POSITION_Y,State::VELOCITY_Z) = R(1,2);
00323 }
00324 }
00325
00326 if (state.getPositionIndex() >= 0 && state.getSystemStatus() & STATE_POSITION_Z) {
00327 if (state.getOrientationIndex() >= 0) {
00328 A(State::POSITION_Z,State::QUATERNION_W) = -2.0*q.y()*v.x()+2.0*q.x()*v.y()+2.0*q.w()*v.z();
00329 A(State::POSITION_Z,State::QUATERNION_X) = 2.0*q.z()*v.x()+2.0*q.w()*v.y()-2.0*q.x()*v.z();
00330 A(State::POSITION_Z,State::QUATERNION_Y) = -2.0*q.w()*v.x()+2.0*q.z()*v.y()-2.0*q.y()*v.z();
00331 A(State::POSITION_Z,State::QUATERNION_Z) = 2.0*q.x()*v.x()+2.0*q.y()*v.y()+2.0*q.z()*v.z();
00332 }
00333
00334 if (state.getVelocityIndex() >= 0) {
00335 A(State::POSITION_Z,State::VELOCITY_X) = R(2,0);
00336 A(State::POSITION_Z,State::VELOCITY_Y) = R(2,1);
00337 A(State::POSITION_Z,State::VELOCITY_Z) = R(2,2);
00338 }
00339 }
00340
00341 #else
00342
00343 if (state.getVelocityIndex() >= 0 && state.getOrientationIndex() >= 0) {
00344 if (state.getSystemStatus() & STATE_VELOCITY_XY) {
00345 A(State::VELOCITY_X,State::QUATERNION_W) = (-2.0*q.z()*acceleration.y()+2.0*q.y()*acceleration.z()+2.0*q.w()*acceleration.x());
00346 A(State::VELOCITY_X,State::QUATERNION_X) = ( 2.0*q.y()*acceleration.y()+2.0*q.z()*acceleration.z()+2.0*q.x()*acceleration.x());
00347 A(State::VELOCITY_X,State::QUATERNION_Y) = (-2.0*q.y()*acceleration.x()+2.0*q.x()*acceleration.y()+2.0*q.w()*acceleration.z());
00348 A(State::VELOCITY_X,State::QUATERNION_Z) = (-2.0*q.z()*acceleration.x()-2.0*q.w()*acceleration.y()+2.0*q.x()*acceleration.z());
00349
00350 A(State::VELOCITY_Y,State::QUATERNION_W) = (2.0*q.z()*acceleration.x()-2.0*q.x()*acceleration.z()+2.0*q.w()*acceleration.y());
00351 A(State::VELOCITY_Y,State::QUATERNION_X) = (2.0*q.y()*acceleration.x()-2.0*q.x()*acceleration.y()-2.0*q.w()*acceleration.z());
00352 A(State::VELOCITY_Y,State::QUATERNION_Y) = (2.0*q.x()*acceleration.x()+2.0*q.z()*acceleration.z()+2.0*q.y()*acceleration.y());
00353 A(State::VELOCITY_Y,State::QUATERNION_Z) = (2.0*q.w()*acceleration.x()-2.0*q.z()*acceleration.y()+2.0*q.y()*acceleration.z());
00354 }
00355
00356 if (state.getSystemStatus() & STATE_VELOCITY_Z) {
00357 A(State::VELOCITY_Z,State::QUATERNION_W) = (-2.0*q.y()*acceleration.x()+2.0*q.x()*acceleration.y()+2.0*q.w()*acceleration.z());
00358 A(State::VELOCITY_Z,State::QUATERNION_X) = ( 2.0*q.z()*acceleration.x()+2.0*q.w()*acceleration.y()-2.0*q.x()*acceleration.z());
00359 A(State::VELOCITY_Z,State::QUATERNION_Y) = (-2.0*q.w()*acceleration.x()+2.0*q.z()*acceleration.y()-2.0*q.y()*acceleration.z());
00360 A(State::VELOCITY_Z,State::QUATERNION_Z) = ( 2.0*q.x()*acceleration.x()+2.0*q.y()*acceleration.y()+2.0*q.z()*acceleration.z());
00361 }
00362 }
00363
00364 if (state.getPositionIndex() >= 0 && state.getVelocityIndex() >= 0) {
00365 if (state.getSystemStatus() & STATE_POSITION_XY) {
00366 A(State::POSITION_X,State::VELOCITY_X) = 1.0;
00367 A(State::POSITION_Y,State::VELOCITY_Y) = 1.0;
00368 }
00369
00370 if (state.getSystemStatus() & STATE_POSITION_Z) {
00371 A(State::POSITION_Z,State::VELOCITY_Z) = 1.0;
00372 }
00373 }
00374 #endif // VELOCITY_IN_BODY_FRAME
00375
00376 }
00377
00378 void GenericQuaternionSystemModel::getInputJacobian(InputMatrix& B, const State& state, bool init)
00379 {
00380 throw std::runtime_error("not implemented");
00381 }
00382
00383 SystemStatus GenericQuaternionSystemModel::getStatusFlags(const State& state)
00384 {
00385 SystemStatus flags = state.getMeasurementStatus();
00386
00387 if (flags & STATE_POSITION_XY) flags |= STATE_VELOCITY_XY;
00388 if (flags & STATE_POSITION_Z) flags |= STATE_VELOCITY_Z;
00389 if (flags & STATE_VELOCITY_XY) flags |= STATE_ROLLPITCH;
00390 if (flags & STATE_ROLLPITCH) flags |= STATE_RATE_XY;
00391 #ifndef USE_RATE_SYSTEM_MODEL
00392 flags |= STATE_RATE_XY | STATE_RATE_Z;
00393 #endif
00394 return flags;
00395 }
00396
00397 }