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/measurements/poseupdate.h>
00030 #include <hector_pose_estimation/pose_estimation.h>
00031 #include <hector_pose_estimation/bfl_conversions.h>
00032 #include <Eigen/Geometry>
00033
00034 #include <boost/bind.hpp>
00035
00036 namespace hector_pose_estimation {
00037
00038 PoseUpdate::PoseUpdate(const std::string& name)
00039 : Measurement(name)
00040 {
00041 fixed_alpha_ = 0.0;
00042 fixed_beta_ = 0.0;
00043 interpret_covariance_as_information_matrix_ = true;
00044
00045 fixed_position_xy_stddev_ = 0.0;
00046 fixed_position_z_stddev_ = 0.0;
00047 fixed_yaw_stddev_ = 0.0;
00048
00049 fixed_velocity_xy_stddev_ = 0.0;
00050 fixed_velocity_z_stddev_ = 0.0;
00051 fixed_angular_rate_xy_stddev_ = 0.0;
00052 fixed_angular_rate_z_stddev_ = 0.0;
00053
00054 max_time_difference_ = 1.0;
00055 max_position_xy_error_ = 3.0;
00056 max_position_z_error_ = 3.0;
00057 max_yaw_error_ = 3.0;
00058
00059 max_velocity_xy_error_ = 3.0;
00060 max_velocity_z_error_ = 3.0;
00061 max_angular_rate_xy_error_ = 3.0;
00062 max_angular_rate_z_error_ = 3.0;
00063
00064 jump_on_max_error_ = true;
00065
00066 parameters().add("fixed_alpha", fixed_alpha_);
00067 parameters().add("fixed_beta", fixed_beta_);
00068 parameters().add("interpret_covariance_as_information_matrix", interpret_covariance_as_information_matrix_);
00069
00070 parameters().add("fixed_position_xy_stddev", fixed_position_xy_stddev_);
00071 parameters().add("fixed_position_z_stddev", fixed_position_z_stddev_);
00072 parameters().add("fixed_yaw_stddev", fixed_yaw_stddev_);
00073 parameters().add("fixed_velocity_xy_stddev", fixed_velocity_xy_stddev_);
00074 parameters().add("fixed_velocity_z_stddev", fixed_velocity_z_stddev_);
00075 parameters().add("fixed_angular_rate_xy_stddev", fixed_angular_rate_xy_stddev_);
00076 parameters().add("fixed_angular_rate_z_stddev", fixed_angular_rate_z_stddev_);
00077 parameters().add("max_time_difference", max_time_difference_);
00078 parameters().add("max_position_xy_error", max_position_xy_error_ );
00079 parameters().add("max_position_z_error", max_position_z_error_);
00080 parameters().add("max_yaw_error", max_yaw_error_);
00081 parameters().add("max_velocity_xy_error", max_velocity_xy_error_ );
00082 parameters().add("max_velocity_z_error", max_velocity_z_error_);
00083 parameters().add("max_angular_rate_xy_error", max_angular_rate_xy_error_ );
00084 parameters().add("max_angular_rate_z_error", max_angular_rate_z_error_);
00085 parameters().add("jump_on_max_error", jump_on_max_error_);
00086 }
00087
00088 PoseUpdate::~PoseUpdate()
00089 {
00090 }
00091
00092 bool PoseUpdate::update(PoseEstimation &estimator, const MeasurementUpdate &update_) {
00093 Update const &update = static_cast<Update const &>(update_);
00094
00095
00096 ColumnVector state = estimator.getState();
00097 SymmetricMatrix covariance = estimator.getCovariance();
00098
00099 while (update.pose) {
00100
00101 Eigen::Vector3d update_pose(update.pose->pose.pose.position.x, update.pose->pose.pose.position.y, update.pose->pose.pose.position.z);
00102 Eigen::Quaterniond update_orientation(update.pose->pose.pose.orientation.w, update.pose->pose.pose.orientation.x, update.pose->pose.pose.orientation.y, update.pose->pose.pose.orientation.z);
00103 Eigen::Vector3d update_euler(update_orientation.toRotationMatrix().eulerAngles(2,1,0));
00104
00105
00106
00107 SymmetricMatrix information(6);
00108 covarianceMsgToBfl(update.pose->pose.covariance, information);
00109
00110
00111 position_xy_model_.ConditionalArgumentSet(0,state);
00112 position_z_model_.ConditionalArgumentSet(0,state);
00113 yaw_model_.ConditionalArgumentSet(0,state);
00114
00115 ROS_DEBUG_STREAM_NAMED("poseupdate", "PoseUpdate: state = [ " << state.transpose() << " ], P = [ " << covariance << " ]" << std::endl
00116 << "update: pose = [ " << update_pose.transpose() << " ], euler = [ " << update_euler.transpose() << " ], information = [ " << information << " ]");
00117 ROS_DEBUG_STREAM_NAMED("poseupdate", "dt = " << (estimator.getTimestamp() - update.pose->header.stamp).toSec() << " s");
00118
00119
00120 if (!update.pose->header.stamp.isZero()) {
00121 double dt = (estimator.getTimestamp() - update.pose->header.stamp).toSec();
00122 if (dt < 0.0) {
00123 ROS_DEBUG_STREAM_NAMED("poseupdate", "Ignoring pose update as it has a negative time difference: dt = " << dt << "s");
00124 break;
00125
00126 } else if (max_time_difference_ > 0.0 && dt >= max_time_difference_) {
00127 ROS_DEBUG_STREAM_NAMED("poseupdate", "Ignoring pose update as the time difference is too large: dt = " << dt << "s");
00128 break;
00129
00130 } else if (max_time_difference_ > 0.0){
00131 if (interpret_covariance_as_information_matrix_)
00132 information = information * (1.0 - dt/max_time_difference_);
00133 else
00134 information = information / (1.0 - dt/max_time_difference_);
00135 }
00136
00137 Eigen::Vector3d state_velocity(state.sub(VELOCITY_X, VELOCITY_Z));
00138 update_pose = update_pose + dt * state_velocity;
00139 #ifdef USE_RATE_SYSTEM_MODEL
00140 Eigen::Vector3d state_rate(state.sub(RATE_X,RATE_Z));
00141 Eigen::AngleAxisd state_angle_offset(state_rate.norm() * dt, state_rate.normalized());
00142 update_orientation = state_angle_offset * update_orientation;
00143 #endif
00144 }
00145
00146
00147 if (information(1,1) > 0.0 || information(2,2) > 0.0) {
00148
00149 Matrix H = position_xy_model_.dfGet(0);
00150 ColumnVector x(position_xy_model_.ExpectedValueGet());
00151 ColumnVector y(2);
00152 SymmetricMatrix Iy(information.sub(1,2,1,2));
00153 y(1) = update_pose.x();
00154 y(2) = update_pose.y();
00155
00156
00157 if (!interpret_covariance_as_information_matrix_) Iy = Iy.inverse();
00158
00159
00160 if (fixed_position_xy_stddev_ != 0.0) {
00161 Iy = 0.0;
00162 Iy(1,1) = Iy(2,2) = 1.0 / (fixed_position_xy_stddev_*fixed_position_xy_stddev_);
00163 }
00164
00165 ROS_DEBUG_STREAM_NAMED("poseupdate", "Position Update: ");
00166 ROS_DEBUG_STREAM_NAMED("poseupdate", " x = [" << x.transpose() << "], H = [ " << H << " ], Px = [" << (H*covariance*H.transpose()) << "], Ix = [ " << (H*covariance*H.transpose()).inverse() << "]");
00167 ROS_DEBUG_STREAM_NAMED("poseupdate", " y = [" << y.transpose() << "], Iy = [ " << Iy << " ]");
00168 double innovation = updateInternal(covariance, state, Iy, y - x, H, covariance, state, "position_xy", max_position_xy_error_, boost::bind(&PositionXYModel::updateState, position_xy_model_, _1, _2, _3, _4, _5));
00169 ROS_DEBUG_STREAM_NAMED("poseupdate", " ==> xy = [" << position_xy_model_.PredictionGet(ColumnVector(), state).transpose() << "], Pxy = [ " << (H*covariance*H.transpose()) << " ], innovation = " << innovation);
00170
00171 status_flags_ |= STATE_XY_POSITION;
00172 }
00173
00174
00175 if (information(3,3) > 0.0) {
00176
00177 Matrix H = position_z_model_.dfGet(0);
00178 ColumnVector x(position_z_model_.ExpectedValueGet());
00179 ColumnVector y(1); y(1) = update_pose.z();
00180 SymmetricMatrix Iy(information.sub(3,3,3,3));
00181
00182
00183 if (!interpret_covariance_as_information_matrix_) Iy = Iy.inverse();
00184
00185
00186 if (fixed_position_z_stddev_ != 0.0) {
00187 Iy = 0.0;
00188 Iy(1,1) = 1.0 / (fixed_position_z_stddev_*fixed_position_z_stddev_);
00189 }
00190
00191 ROS_DEBUG_STREAM_NAMED("poseupdate", "Height Update: ");
00192 ROS_DEBUG_STREAM_NAMED("poseupdate", " x = " << x(1) << ", H = [ " << H << " ], Px = [" << (H*covariance*H.transpose()) << "], Ix = [ " << (H*covariance*H.transpose()).inverse() << "]");
00193 ROS_DEBUG_STREAM_NAMED("poseupdate", " y = " << y(1) << ", Iy = [ " << Iy << " ]");
00194 double innovation = updateInternal(covariance, state, Iy, y - x, H, covariance, state, "position_z", max_position_z_error_, boost::bind(&PositionZModel::updateState, position_z_model_, _1, _2, _3, _4, _5));
00195 ROS_DEBUG_STREAM_NAMED("poseupdate", " ==> xy = " << position_z_model_.PredictionGet(ColumnVector(), state) << ", Pxy = [ " << (H*covariance*H.transpose()) << " ], innovation = " << innovation);
00196
00197 status_flags_ |= STATE_Z_POSITION;
00198 }
00199
00200
00201 if (information(6,6) > 0.0) {
00202
00203 Matrix H = yaw_model_.dfGet(0);
00204 ColumnVector x(yaw_model_.ExpectedValueGet());
00205 ColumnVector y(1); y(1) = update_euler(0);
00206 SymmetricMatrix Iy(information.sub(6,6,6,6));
00207
00208
00209 if (!interpret_covariance_as_information_matrix_) Iy = Iy.inverse();
00210
00211
00212 if (fixed_yaw_stddev_ != 0.0) {
00213 Iy = 0.0;
00214 Iy(1,1) = 1.0 / (fixed_yaw_stddev_*fixed_yaw_stddev_);
00215 }
00216
00217 ROS_DEBUG_STREAM_NAMED("poseupdate", "Yaw Update: ");
00218 ROS_DEBUG_STREAM_NAMED("poseupdate", " x = " << x(1) * 180.0/M_PI << "°, H = [ " << H << " ], Px = [" << (H*covariance*H.transpose()) << "], Ix = [ " << (H*covariance*H.transpose()).inverse() << "]");
00219 ROS_DEBUG_STREAM_NAMED("poseupdate", " y = " << y(1) * 180.0/M_PI << "°, Iy = [ " << Iy << " ]");
00220
00221 ColumnVector error(y - x);
00222 error(1) = error(1) - 2.0*M_PI * round(error(1) / (2.0*M_PI));
00223
00224 double innovation = updateInternal(covariance, state, Iy, error, H, covariance, state, "yaw", max_yaw_error_, boost::bind(&YawModel::updateState, yaw_model_, _1, _2, _3, _4, _5));
00225 ROS_DEBUG_STREAM_NAMED("poseupdate", " ==> xy = " << yaw_model_.PredictionGet(ColumnVector(), state) * 180.0/M_PI << "°, Pxy = [ " << (H*covariance*H.transpose()) << " ], innovation = " << innovation);
00226
00227 status_flags_ |= STATE_YAW;
00228 }
00229
00230 break;
00231 }
00232
00233 while (update.twist) {
00234
00235 Eigen::Vector3d update_linear(update.twist->twist.twist.linear.x, update.twist->twist.twist.linear.y, update.twist->twist.twist.linear.z);
00236 Eigen::Vector3d update_angular(update.twist->twist.twist.angular.x, update.twist->twist.twist.angular.y, update.twist->twist.twist.angular.z);
00237
00238
00239
00240 SymmetricMatrix information(6);
00241 covarianceMsgToBfl(update.twist->twist.covariance, information);
00242
00243
00244 twist_model_.ConditionalArgumentSet(0,state);
00245
00246 ROS_DEBUG_STREAM_NAMED("poseupdate", "TwistUpdate: state = [ " << state.transpose() << " ], P = [ " << covariance << " ]" << std::endl
00247 << " update: linear = [ " << update_linear.transpose() << " ], angular = [ " << update_angular.transpose() << " ], information = [ " << information << " ]");
00248 ROS_DEBUG_STREAM_NAMED("poseupdate", " dt = " << (estimator.getTimestamp() - update.twist->header.stamp).toSec() << " s");
00249
00250
00251 if (!update.twist->header.stamp.isZero()) {
00252 double dt = (estimator.getTimestamp() - update.twist->header.stamp).toSec();
00253 if (dt < 0.0) {
00254 ROS_DEBUG_STREAM_NAMED("poseupdate", "Ignoring twist update as it has a negative time difference: dt = " << dt << "s");
00255 break;
00256
00257 } else if (max_time_difference_ > 0.0 && dt >= max_time_difference_) {
00258 ROS_DEBUG_STREAM_NAMED("poseupdate", "Ignoring twist update as the time difference is too large: dt = " << dt << "s");
00259 break;
00260
00261 } else if (max_time_difference_ > 0.0){
00262 if (interpret_covariance_as_information_matrix_)
00263 information = information * (1.0 - dt/max_time_difference_);
00264 else
00265 information = information / (1.0 - dt/max_time_difference_);
00266 }
00267 }
00268
00269
00270 Matrix H = twist_model_.dfGet(0);
00271 ColumnVector x(twist_model_.ExpectedValueGet());
00272 TwistModel::NoiseCovariance Iy(information);
00273 TwistModel::MeasurementVector y;
00274 y(1) = update_linear.x();
00275 y(2) = update_linear.y();
00276 y(3) = update_linear.z();
00277 y(4) = update_angular.x();
00278 y(5) = update_angular.y();
00279 y(6) = update_angular.z();
00280
00281
00282 if (!interpret_covariance_as_information_matrix_) {
00283 ROS_DEBUG_NAMED("poseupdate", "Twist updates with covariance matrices are currently not supported");
00284 break;
00285 }
00286
00287
00288 if (information(1,1) > 0.0 || information(2,2) > 0.0) {
00289 status_flags_ |= STATE_XY_VELOCITY;
00290
00291
00292 if (fixed_velocity_xy_stddev_ != 0.0) {
00293 for(int i = 1; i <= 6; ++i) Iy(1,i) = Iy(2,i) = Iy(i,1) = Iy(i,2) = 0.0;
00294 Iy(1,1) = Iy(2,2) = 1.0 / (fixed_velocity_xy_stddev_*fixed_velocity_xy_stddev_);
00295 }
00296 }
00297
00298
00299 if (information(3,3) > 0.0) {
00300 status_flags_ |= STATE_Z_VELOCITY;
00301
00302
00303 if (fixed_velocity_z_stddev_ != 0.0) {
00304 for(int i = 1; i <= 6; ++i) Iy(3,i) = Iy(i,3) = 0.0;
00305 Iy(3,3) = 1.0 / (fixed_velocity_z_stddev_*fixed_velocity_z_stddev_);
00306 }
00307 }
00308
00309
00310 if (information(4,4) > 0.0 || information(5,5) > 0.0) {
00311
00312 if (fixed_angular_rate_xy_stddev_ != 0.0) {
00313 for(int i = 1; i <= 6; ++i) Iy(4,i) = Iy(4,i) = Iy(i,5) = Iy(i,5) = 0.0;
00314 Iy(4,4) = Iy(5,5) = 1.0 / (fixed_angular_rate_xy_stddev_*fixed_angular_rate_xy_stddev_);
00315 }
00316 }
00317
00318
00319 if (information(6,6) > 0.0) {
00320
00321 if (fixed_angular_rate_z_stddev_ != 0.0) {
00322 for(int i = 1; i <= 6; ++i) Iy(6,i) = Iy(i,6) = 0.0;
00323 Iy(6,6) = 1.0 / (fixed_angular_rate_z_stddev_*fixed_angular_rate_z_stddev_);
00324 }
00325 }
00326
00327 ROS_DEBUG_STREAM_NAMED("poseupdate", "Twist Update: ");
00328 ROS_DEBUG_STREAM_NAMED("poseupdate", " x = [" << x.transpose() << "], H = [ " << H << " ], Px = [" << (H*covariance*H.transpose()) << "], Ix = [ " << (H*covariance*H.transpose()).inverse() << "]");
00329 ROS_DEBUG_STREAM_NAMED("poseupdate", " y = [" << y.transpose() << "], Iy = [ " << Iy << " ]");
00330 double innovation = updateInternal(covariance, state, Iy, y - x, H, covariance, state, "twist");
00331 ROS_DEBUG_STREAM_NAMED("poseupdate", " ==> xy = [" << twist_model_.PredictionGet(ColumnVector(), state).transpose() << "], Pxy = [ " << (H*covariance*H.transpose()) << " ], innovation = " << innovation);
00332
00333 break;
00334 }
00335
00336 estimator.setState(state);
00337 estimator.setCovariance(covariance);
00338 estimator.updated();
00339 updated();
00340
00341 return true;
00342 }
00343
00344 double PoseUpdate::calculateOmega(const SymmetricMatrix &Ix, const SymmetricMatrix &Iy) const {
00345 double tr_x = static_cast<EigenMatrix>(Ix).trace();
00346 double tr_y = static_cast<EigenMatrix>(Iy).trace();
00347 return tr_y / (tr_x + tr_y);
00348 }
00349
00350 double PoseUpdate::updateInternal(const SymmetricMatrix &Px, const ColumnVector &x, const SymmetricMatrix &Iy, const ColumnVector &error, const Matrix &H, SymmetricMatrix &Pxy, ColumnVector &xy, const std::string& text, const double max_error, JumpFunction jump_function) {
00351 Matrix HT(H.transpose());
00352 SymmetricMatrix H_Px_HT(H*Px*HT);
00353
00354 if (H_Px_HT.determinant() <= 0) {
00355 ROS_WARN_STREAM("Ignoring poseupdate for " << text << " as the a-priori state covariance is zero!");
00356 return 0.0;
00357 }
00358 SymmetricMatrix Ix(H_Px_HT.inverse());
00359
00360 ROS_DEBUG_STREAM_NAMED("poseupdate", "H = [" << H << "]");
00361 ROS_DEBUG_STREAM_NAMED("poseupdate", "Ix = [" << Ix << "]");
00362
00363 double alpha = fixed_alpha_, beta = fixed_beta_;
00364 if (alpha == 0.0 && beta == 0.0) {
00365 beta = calculateOmega(Ix, Iy);
00366 alpha = 1.0 - beta;
00367
00368
00369
00370
00371
00372
00373 }
00374 ROS_DEBUG_STREAM_NAMED("poseupdate", "alpha = " << alpha << ", beta = " << beta);
00375
00376 if (max_error > 0.0) {
00377 double error2 = error.transpose() * Ix * (Ix + Iy).inverse() * Iy * error;
00378 if (error2 > max_error * max_error) {
00379 if (!jump_on_max_error_ || !jump_function) {
00380 ROS_WARN_STREAM_NAMED("poseupdate", "Ignoring poseupdate for " << text << " as the error [ " << error.transpose() << " ], |error| = " << sqrt(error2) << " sigma exceeds max_error!");
00381 return 0.0;
00382 } else {
00383 ROS_WARN_STREAM_NAMED("poseupdate", "Update for " << text << " with error [ " << error.transpose() << " ], |error| = " << sqrt(error2) << " sigma exceeds max_error!");
00384 jump_function(Px, x, error, Pxy, xy);
00385 return 0.0;
00386 }
00387 }
00388 }
00389
00390
00391
00392
00393
00394
00395 SymmetricMatrix S_1(Ix - Ix * (Ix * alpha + Iy * beta).inverse() * Ix);
00396 double innovation = S_1.determinant();
00397
00398 Pxy = Px - Px * HT * S_1 * H * Px;
00399 xy = x + Pxy * HT * Iy * beta * error;
00400
00401 ROS_DEBUG_STREAM_NAMED("poseupdate", "K = [" << (Pxy * HT * Iy * beta) << "]");
00402 ROS_DEBUG_STREAM_NAMED("poseupdate", "dx = [" << ( Pxy * HT * Iy * beta * error).transpose() << "]");
00403
00404 return innovation;
00405 }
00406
00407 ColumnVector PositionXYModel::ExpectedValueGet() const {
00408 y_(1) = x_(POSITION_X);
00409 y_(2) = x_(POSITION_Y);
00410 return y_;
00411 }
00412
00413 Matrix PositionXYModel::dfGet(unsigned int i) const {
00414 if (i != 0) return Matrix();
00415 C_(1,POSITION_X) = 1.0;
00416 C_(2,POSITION_Y) = 1.0;
00417 return C_;
00418 }
00419
00420 void PositionXYModel::updateState(const SymmetricMatrix &Px, const ColumnVector &x, const ColumnVector &diff, SymmetricMatrix &Pxy, ColumnVector &xy) const {
00421 xy = x;
00422 xy.sub(POSITION_X, POSITION_Y) = x.sub(POSITION_X, POSITION_Y) + diff;
00423 }
00424
00425 ColumnVector PositionZModel::ExpectedValueGet() const {
00426 y_(1) = x_(POSITION_Z);
00427 return y_;
00428 }
00429
00430 Matrix PositionZModel::dfGet(unsigned int i) const {
00431 if (i != 0) return Matrix();
00432 C_(1,POSITION_Z) = 1.0;
00433 return C_;
00434 }
00435
00436 void PositionZModel::updateState(const SymmetricMatrix &Px, const ColumnVector &x, const ColumnVector &diff, SymmetricMatrix &Pxy, ColumnVector &xy) const {
00437 xy = x;
00438 xy.sub(POSITION_Z, POSITION_Z) = x.sub(POSITION_Z, POSITION_Z) + diff;
00439 }
00440
00441 ColumnVector YawModel::ExpectedValueGet() const {
00442 const double qw = x_(QUATERNION_W);
00443 const double qx = x_(QUATERNION_X);
00444 const double qy = x_(QUATERNION_Y);
00445 const double qz = x_(QUATERNION_Z);
00446
00447 y_(1) = atan2(2*(qx*qy + qw*qz), qw*qw + qx*qx - qy*qy - qz*qz);
00448
00449 return y_;
00450 }
00451
00452 Matrix YawModel::dfGet(unsigned int i) const {
00453 if (i != 0) return Matrix();
00454
00455 const double qw = x_(QUATERNION_W);
00456 const double qx = x_(QUATERNION_X);
00457 const double qy = x_(QUATERNION_Y);
00458 const double qz = x_(QUATERNION_Z);
00459 const double t1 = qw*qw + qx*qx - qy*qy - qz*qz;
00460 const double t2 = 2*(qx*qy + qw*qz);
00461 const double t3 = 1.0 / (t1*t1 + t2*t2);
00462
00463 C_(1,QUATERNION_W) = 2.0 * t3 * (qz * t1 - qw * t2);
00464 C_(1,QUATERNION_X) = 2.0 * t3 * (qy * t1 - qx * t2);
00465 C_(1,QUATERNION_Y) = 2.0 * t3 * (qx * t1 + qy * t2);
00466 C_(1,QUATERNION_Z) = 2.0 * t3 * (qw * t1 + qz * t2);
00467
00468 return C_;
00469 }
00470
00471 void YawModel::updateState(const SymmetricMatrix &Px, const ColumnVector &x, const ColumnVector &diff, SymmetricMatrix &Pxy, ColumnVector &xy) const {
00472 Eigen::Quaterniond rotation(Eigen::AngleAxisd(diff(1), Eigen::Vector3d::UnitZ()));
00473
00474 Eigen::MatrixXd S(StateDimension, StateDimension); S.setIdentity();
00475 S.block(QUATERNION_W - 1, QUATERNION_W - 1, 4, 4) <<
00476 rotation.w(), -rotation.x(), -rotation.y(), -rotation.z(),
00477 rotation.x(), rotation.w(), -rotation.z(), rotation.y(),
00478 rotation.y(), rotation.z(), rotation.w(), -rotation.x(),
00479 rotation.z(), -rotation.y(), rotation.x(), rotation.w();
00480
00481 S.block(VELOCITY_X - 1, VELOCITY_X - 1, 3, 3) = rotation.toRotationMatrix().transpose();
00482 #ifdef USE_RATE_SYSTEM_MODEL
00483 S.block(RATE_X - 1, RATE_X - 1, 3, 3) = S.block(VELOCITY_X - 1, VELOCITY_X - 1, 3, 3);
00484 #endif // USE_RATE_SYSTEM_MODEL
00485
00486
00487
00488 xy = S * x;
00489 Pxy = S * Px * S.transpose();
00490 }
00491
00492 ColumnVector TwistModel::ExpectedValueGet() const {
00493 y_(1) = x_(VELOCITY_X);
00494 y_(2) = x_(VELOCITY_Y);
00495 y_(3) = x_(VELOCITY_Z);
00496 #ifdef USE_RATE_SYSTEM_MODEL
00497 y_(4) = x_(RATE_X);
00498 y_(5) = x_(RATE_Y);
00499 y_(6) = x_(RATE_Z);
00500 #else // USE_RATE_SYSTEM_MODEL
00501 y_(4) = 0.0;
00502 y_(5) = 0.0;
00503 y_(6) = 0.0;
00504 #endif // USE_RATE_SYSTEM_MODEL
00505 return y_;
00506 }
00507
00508 Matrix TwistModel::dfGet(unsigned int i) const {
00509 if (i != 0) return Matrix();
00510
00511 C_(1,VELOCITY_X) = 1.0;
00512 C_(2,VELOCITY_Y) = 1.0;
00513 C_(3,VELOCITY_Z) = 1.0;
00514 #ifdef USE_RATE_SYSTEM_MODEL
00515 C_(4,RATE_X) = 1.0;
00516 C_(5,RATE_Y) = 1.0;
00517 C_(6,RATE_Z) = 1.0;
00518 #endif // USE_RATE_SYSTEM_MODEL
00519 return C_;
00520 }
00521
00522 }