poseupdate.cpp
Go to the documentation of this file.
00001 //=================================================================================================
00002 // Copyright (c) 2011, Johannes Meyer, TU Darmstadt
00003 // All rights reserved.
00004 
00005 // Redistribution and use in source and binary forms, with or without
00006 // modification, are permitted provided that the following conditions are met:
00007 //     * Redistributions of source code must retain the above copyright
00008 //       notice, this list of conditions and the following disclaimer.
00009 //     * Redistributions in binary form must reproduce the above copyright
00010 //       notice, this list of conditions and the following disclaimer in the
00011 //       documentation and/or other materials provided with the distribution.
00012 //     * Neither the name of the Flight Systems and Automatic Control group,
00013 //       TU Darmstadt, nor the names of its contributors may be used to
00014 //       endorse or promote products derived from this software without
00015 //       specific prior written permission.
00016 
00017 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00018 // ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00019 // WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00020 // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
00021 // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00022 // (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00023 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00024 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00025 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00026 // SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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; // 3 sigma
00056   max_position_z_error_ = 3.0; // 3 sigma
00057   max_yaw_error_ = 3.0; // 3 sigma
00058 
00059   max_velocity_xy_error_ = 3.0; // 3 sigma
00060   max_velocity_z_error_ = 3.0; // 3 sigma
00061   max_angular_rate_xy_error_ = 3.0; // 3 sigma
00062   max_angular_rate_z_error_ = 3.0; // 3 sigma
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   // fetch current state
00096   ColumnVector state = estimator.getState();
00097   SymmetricMatrix covariance = estimator.getCovariance();
00098 
00099   while (update.pose) {
00100     // convert incoming update information to Eigen
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     // information is the information matrix if interpret_covariance_as_information_matrix_ is true and a covariance matrix otherwise
00106     // zero elements are counted as zero information in any case
00107     SymmetricMatrix information(6);
00108     covarianceMsgToBfl(update.pose->pose.covariance, information);
00109 
00110     // forward state vector to the individual measurement models
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     // predict update pose using the estimated velocity and degrade information
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     // update PositionXY
00147     if (information(1,1) > 0.0 || information(2,2) > 0.0) {
00148       // fetch observation matrix H
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       // invert Iy if information is a covariance matrix
00157       if (!interpret_covariance_as_information_matrix_) Iy = Iy.inverse();
00158 
00159       // fixed_position_xy_stddev_ = 1.0;
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     // update PositionZ
00175     if (information(3,3) > 0.0) {
00176       // fetch observation matrix H
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       // invert Iy if information is a covariance matrix
00183       if (!interpret_covariance_as_information_matrix_) Iy = Iy.inverse();
00184 
00185       // fixed_position_z_stddev_ = 1.0;
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     // update Yaw
00201     if (information(6,6) > 0.0) {
00202       // fetch observation matrix H
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       // invert Iy if information is a covariance matrix
00209       if (!interpret_covariance_as_information_matrix_) Iy = Iy.inverse();
00210 
00211       // fixed_yaw_stddev_ = 5.0 * M_PI/180.0;
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     // convert incoming update information to Eigen
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     // information is the information matrix if interpret_covariance_as_information_matrix_ is true and a covariance matrix otherwise
00239     // zero elements are counted as zero information in any case
00240     SymmetricMatrix information(6);
00241     covarianceMsgToBfl(update.twist->twist.covariance, information);
00242 
00243     // forward state vector to the individual measurement models
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     // degrade information if the time difference is too large
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     // fetch observation matrix H
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     // invert Iy if information is a covariance matrix
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     // update VelocityXY
00288     if (information(1,1) > 0.0 || information(2,2) > 0.0) {
00289       status_flags_ |= STATE_XY_VELOCITY;
00290 
00291       // fixed_velocity_xy_stddev_ = 1.0;
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     // update VelocityZ
00299     if (information(3,3) > 0.0) {
00300       status_flags_ |= STATE_Z_VELOCITY;
00301 
00302       // fixed_velocity_z_stddev_ = 1.0;
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     // update RateXY
00310     if (information(4,4) > 0.0 || information(5,5) > 0.0) {
00311       // fixed_angular_rate_xy_stddev_ = 1.0;
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     // update RateZ
00319     if (information(6,6) > 0.0) {
00320       // fixed_angular_rate_z_stddev_ = 1.0;
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 //    if (beta > 0.8) {
00369 //      ROS_DEBUG_STREAM("Reducing update variance for " << text << " due to high information difference between Ix = [" << Ix << "] and Iy = [" << Iy << "]");
00370 //      beta = 0.8;
00371 //      alpha = 1.0 - beta;
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 //  SymmetricMatrix Ii(Ix * (alpha - 1) + Iy * beta);
00391 //  double innovation = Ii.determinant();
00392 //  ROS_DEBUG_STREAM_NAMED("poseupdate", "Ii = [" << Ii << "], innovation = " << innovation);
00393 
00394   // S_1 is equivalent to S^(-1) = (H*P*H^T + R)^(-1) in the standard Kalman gain
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; // may invalidate Px if &Pxy == &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   // ROS_DEBUG_STREAM_NAMED("poseupdate", "Jump yaw by " << (diff(1) * 180.0/M_PI) << " degrees. rotation = [" << rotation.coeffs().transpose() << "], S = [" << S << "].");
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 } // namespace hector_pose_estimation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends


hector_pose_estimation_core
Author(s): Johannes Meyer
autogenerated on Mon Jul 15 2013 16:48:43