pose_estimation.cpp
Go to the documentation of this file.
00001 //=================================================================================================
00002 // Copyright (c) 2011, Johannes Meyer and Martin Nowara, 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/pose_estimation.h>
00030 #include <hector_pose_estimation/filter/ekf.h>
00031 #include <hector_pose_estimation/global_reference.h>
00032 
00033 #include <hector_pose_estimation/system/imu_input.h>
00034 #include <hector_pose_estimation/system/imu_model.h>
00035 
00036 #include <boost/weak_ptr.hpp>
00037 
00038 namespace hector_pose_estimation {
00039 
00040 namespace {
00041   static PoseEstimation *the_instance = 0;
00042 }
00043 
00044 PoseEstimation::PoseEstimation(const SystemPtr& system)
00045   : rate_update_(new Rate("rate"))
00046   , gravity_update_(new Gravity ("gravity"))
00047   , zerorate_update_(new ZeroRate("zerorate"))
00048 {
00049   if (!the_instance) the_instance = this;
00050   if (system) addSystem(system);
00051 
00052   world_frame_ = "/world";
00053   nav_frame_ = "nav";
00054   base_frame_ = "base_link";
00055   stabilized_frame_ = "base_stabilized";
00056   footprint_frame_ = "base_footprint";
00057   // position_frame_ = "base_position";
00058   alignment_time_ = 0.0;
00059   gravity_ = -9.8065;
00060 
00061   parameters().add("world_frame", world_frame_);
00062   parameters().add("nav_frame", nav_frame_);
00063   parameters().add("base_frame", base_frame_);
00064   parameters().add("stabilized_frame", stabilized_frame_);
00065   parameters().add("footprint_frame", footprint_frame_);
00066   parameters().add("position_frame", position_frame_);
00067   parameters().add(globalReference()->parameters());
00068   parameters().add("alignment_time", alignment_time_);
00069   parameters().add("gravity_magnitude", gravity_);
00070 
00071   // add default measurements
00072   addMeasurement(rate_update_);
00073   addMeasurement(gravity_update_);
00074   addMeasurement(zerorate_update_);
00075 }
00076 
00077 PoseEstimation::~PoseEstimation()
00078 {
00079   cleanup();
00080 }
00081 
00082 PoseEstimation *PoseEstimation::Instance() {
00083   if (!the_instance) the_instance = new PoseEstimation();
00084   return the_instance;
00085 }
00086 
00087 bool PoseEstimation::init()
00088 {
00089   // initialize global reference
00090   globalReference()->updated();
00091 
00092   // check if system is initialized
00093   if (systems_.empty()) return false;
00094 
00095   // create new filter
00096   filter_.reset(new filter::EKF);
00097 
00098   // initialize measurements (new systems could be added during initialization!)
00099   for(Measurements::iterator it = measurements_.begin(); it != measurements_.end(); ++it)
00100     if (!(*it)->init(*this, state())) return false;
00101 
00102   // initialize systems (new systems could be added during initialization!)
00103   for(Systems::iterator it = systems_.begin(); it != systems_.end(); ++it)
00104     if (!(*it)->init(*this, state())) return false;
00105 
00106   // initialize filter
00107   filter_->init(*this);
00108 
00109   // call setFilter for each system and each measurement
00110   for(Systems::iterator it = systems_.begin(); it != systems_.end(); ++it)
00111     (*it)->setFilter(filter_.get());
00112   for(Measurements::iterator it = measurements_.begin(); it != measurements_.end(); ++it)
00113     (*it)->setFilter(filter_.get());
00114 
00115   // reset (or initialize) filter and measurements
00116   reset();
00117 
00118   return true;
00119 }
00120 
00121 void PoseEstimation::cleanup()
00122 {
00123   // cleanup system
00124   for(Systems::iterator it = systems_.begin(); it != systems_.end(); ++it) (*it)->cleanup();
00125 
00126   // cleanup measurements
00127   for(Measurements::iterator it = measurements_.begin(); it != measurements_.end(); ++it) (*it)->cleanup();
00128 
00129   // delete filter instance
00130   if (filter_) filter_.reset();
00131 }
00132 
00133 void PoseEstimation::reset()
00134 {
00135   // check if system is initialized
00136   if (systems_.empty()) return;
00137 
00138   // set initial status
00139   if (filter_) filter_->reset();
00140 
00141   // restart alignment
00142   alignment_start_ = ros::Time();
00143   if (alignment_time_ > 0) {
00144     state().setSystemStatus(STATUS_ALIGNMENT);
00145   }
00146 
00147   // reset systems and measurements
00148   for(Systems::iterator it = systems_.begin(); it != systems_.end(); ++it) {
00149     (*it)->reset(state());
00150     (*it)->getPrior(state());
00151   }
00152 
00153   for(Measurements::iterator it = measurements_.begin(); it != measurements_.end(); ++it) {
00154     (*it)->reset(state());
00155   }
00156 
00157   updated();
00158 }
00159 
00160 void PoseEstimation::update(ros::Time new_timestamp)
00161 {
00162   // check if system is initialized
00163   if (systems_.empty()) return;
00164 
00165   ros::Duration dt;
00166   if (!getTimestamp().isZero()) dt = new_timestamp - getTimestamp();
00167   setTimestamp(new_timestamp);
00168 
00169   // do the update step
00170   update(dt.toSec());
00171 }
00172 
00173 void PoseEstimation::update(double dt)
00174 {
00175   // check dt
00176   if (dt < -1.0)
00177     reset();
00178   else if (dt < 0.0)
00179     return;
00180   else if (dt > 1.0)
00181     dt = 1.0;
00182 
00183   // check if system and filter is initialized
00184   if (systems_.empty() || !filter_) return;
00185 
00186   // filter rate measurement first
00187   boost::shared_ptr<ImuInput> imu = boost::shared_dynamic_cast<ImuInput>(getInput("imu"));
00188   state().setRate(imu->getRate());
00189   state().setAcceleration(imu->getAcceleration());
00190 
00191 #ifdef USE_RATE_SYSTEM_MODEL
00192   if (imu && rate_update_) {
00193     rate_update_->update(Rate::Update(imu->getRate()));
00194   }
00195 #endif // USE_RATE_SYSTEM_MODEL
00196 
00197   // time update step
00198   filter_->predict(systems_, dt);
00199 
00200   // pseudo measurement updates (if required)
00201   gravity_update_->update(Gravity::Update(imu->getAcceleration()));
00202   zerorate_update_->update(ZeroRate::Update());
00203 
00204   // measurement updates
00205   filter_->correct(measurements_);
00206 
00207   // increase timeout timer for measurements
00208   for(Measurements::iterator it = measurements_.begin(); it != measurements_.end(); it++) {
00209     const MeasurementPtr& measurement = *it;
00210     measurement->increase_timer(dt);
00211   }
00212 
00213   // check for invalid state
00214   if (!state().valid()) {
00215     ROS_FATAL("Invalid state, resetting...");
00216     reset();
00217     return;
00218   }
00219 
00220   // updated hook
00221   updated();
00222 
00223   // switch overall system status
00224   if (inSystemStatus(STATUS_ALIGNMENT)) {
00225     if (alignment_start_.isZero()) alignment_start_ = getTimestamp();
00226     if ((getTimestamp() - alignment_start_).toSec() >= alignment_time_) {
00227       updateSystemStatus(STATUS_DEGRADED, STATUS_ALIGNMENT);
00228     }
00229   } else if (inSystemStatus(STATE_ROLLPITCH | STATE_YAW | STATE_POSITION_XY | STATE_POSITION_Z)) {
00230     updateSystemStatus(STATUS_READY, STATUS_DEGRADED);
00231   } else {
00232     updateSystemStatus(STATUS_DEGRADED, STATUS_READY);
00233   }
00234 }
00235 
00236 void PoseEstimation::updated() {
00237   for(Systems::iterator it = systems_.begin(); it != systems_.end(); ++it) {
00238     (*it)->limitState(state());
00239   }
00240 }
00241 
00242 const SystemPtr& PoseEstimation::addSystem(const SystemPtr& system, const std::string& name) {
00243   if (!name.empty() && system->getName().empty()) system->setName(name);
00244   parameters().add(system->getName(), system->parameters());
00245   return systems_.add(system, system->getName());
00246 }
00247 
00248 InputPtr PoseEstimation::addInput(const InputPtr& input, const std::string& name)
00249 {
00250   if (!name.empty()) input->setName(name);
00251   return inputs_.add(input, input->getName());
00252 }
00253 
00254 InputPtr PoseEstimation::setInput(const Input& value, std::string name)
00255 {
00256   if (name.empty()) name = value.getName();
00257   InputPtr input = inputs_.get(name);
00258   if (!input) {
00259     ROS_WARN("Set input \"%s\", but this input is not registered by any system model.", name.c_str());
00260     return InputPtr();
00261   }
00262 
00263   *input = value;
00264   return input;
00265 }
00266 
00267 const MeasurementPtr& PoseEstimation::addMeasurement(const MeasurementPtr& measurement, const std::string& name) {
00268   if (!name.empty()) measurement->setName(name);
00269   parameters().add(measurement->getName(), measurement->parameters());
00270   return measurements_.add(measurement, measurement->getName());
00271 }
00272 
00273 const State::Vector& PoseEstimation::getStateVector() {
00274 //  if (state_is_dirty_) {
00275 //    state_ = filter_->PostGet()->ExpectedValueGet();
00276 //    state_is_dirty_ = false;
00277 //  }
00278   return state().getVector();
00279 }
00280 
00281 const State::Covariance& PoseEstimation::getCovariance() {
00282 //  if (covariance_is_dirty_) {
00283 //    covariance_ = filter_->PostGet()->CovarianceGet();
00284 //    covariance_is_dirty_ = false;
00285 //  }
00286   return state().getCovariance();
00287 }
00288 
00289 SystemStatus PoseEstimation::getSystemStatus() const {
00290   return state().getSystemStatus();
00291 }
00292 
00293 SystemStatus PoseEstimation::getMeasurementStatus() const {
00294   return state().getMeasurementStatus();
00295 }
00296 
00297 bool PoseEstimation::inSystemStatus(SystemStatus test_status) const {
00298   return state().inSystemStatus(test_status);
00299 }
00300 
00301 bool PoseEstimation::setSystemStatus(SystemStatus new_status) {
00302   return state().setSystemStatus(new_status);
00303 }
00304 
00305 bool PoseEstimation::setMeasurementStatus(SystemStatus new_measurement_status) {
00306   return state().setMeasurementStatus(new_measurement_status);
00307 }
00308 
00309 bool PoseEstimation::updateSystemStatus(SystemStatus set, SystemStatus clear) {
00310   return state().updateSystemStatus(set, clear);
00311 }
00312 
00313 bool PoseEstimation::updateMeasurementStatus(SystemStatus set, SystemStatus clear) {
00314   return state().updateMeasurementStatus(set, clear);
00315 }
00316 
00317 const ros::Time& PoseEstimation::getTimestamp() const {
00318   return state().getTimestamp();
00319 }
00320 
00321 void PoseEstimation::setTimestamp(const ros::Time& timestamp) {
00322   state().setTimestamp(timestamp);
00323 }
00324 
00325 void PoseEstimation::getHeader(std_msgs::Header& header) {
00326   header.stamp = getTimestamp();
00327   header.frame_id = nav_frame_;
00328 }
00329 
00330 void PoseEstimation::getState(nav_msgs::Odometry& msg, bool with_covariances) {
00331   getHeader(msg.header);
00332   getPose(msg.pose.pose);
00333   getVelocity(msg.twist.twist.linear);
00334   getRate(msg.twist.twist.angular);
00335   msg.child_frame_id = base_frame_;
00336 
00337   if (with_covariances) {
00338     State::ConstOrientationType q(state().getOrientation());
00339 
00340     // The quat_to_angular_rate matrix transforms the orientation uncertainty from quaternions to an angular uncertainty (given in world-fixed coordinates)
00341     Eigen::Matrix<ScalarType,3,4> quat_to_angular_rate;
00342     quat_to_angular_rate << -q.x(),  q.w(), -q.z(),  q.y(),
00343                             -q.y(),  q.z(),  q.w(), -q.x(),
00344                             -q.z(), -q.y(),  q.x(),  q.w();
00345     quat_to_angular_rate *= 2.0;
00346 
00347     State::Covariance covariance(state().getCovariance());
00348     Eigen::Map< Eigen::Matrix<geometry_msgs::PoseWithCovariance::_covariance_type::value_type,6,6> >  pose_covariance_msg(msg.pose.covariance.data());
00349     Eigen::Map< Eigen::Matrix<geometry_msgs::TwistWithCovariance::_covariance_type::value_type,6,6> > twist_covariance_msg(msg.twist.covariance.data());
00350 
00351     // position covariance
00352     if (state().getPositionIndex() >= 0) {
00353       pose_covariance_msg.block<3,3>(0,0) = covariance.block<3,3>(state().getPositionIndex(), state().getPositionIndex());
00354     }
00355 
00356     // rotation covariance (world-fixed)
00357     if (state().getOrientationIndex() >= 0) {
00358       pose_covariance_msg.block<3,3>(3,3) = quat_to_angular_rate * covariance.block<4,4>(state().getOrientationIndex(), state().getOrientationIndex()) * quat_to_angular_rate.transpose();
00359     }
00360 
00361     // position/orientation cross variance
00362     if (state().getPositionIndex() >= 0 && state().getOrientationIndex() >= 0) {
00363       pose_covariance_msg.block<3,3>(0,3) = covariance.block<3,4>(state().getPositionIndex(), state().getOrientationIndex()) * quat_to_angular_rate.transpose();
00364       pose_covariance_msg.block<3,3>(3,0) = pose_covariance_msg.block<3,3>(0,3).transpose();
00365     }
00366 
00367     // velocity covariance
00368     if (state().getVelocityIndex() >= 0) {
00369       twist_covariance_msg.block<3,3>(0,0) = covariance.block<3,3>(state().getVelocityIndex(), state().getVelocityIndex());
00370     }
00371 
00372     // angular rate covariance
00373     if (state().getRateIndex() >= 0) {
00374       twist_covariance_msg.block<3,3>(3,3) = covariance.block<3,3>(state().getRateIndex(), state().getRateIndex());
00375     }
00376 
00377     // cross velocity/angular_rate variance
00378     if (state().getVelocityIndex() >= 0 && state().getRateIndex() >= 0) {
00379       pose_covariance_msg.block<3,3>(0,3) = covariance.block<3,3>(state().getVelocityIndex(), state().getRateIndex());
00380       pose_covariance_msg.block<3,3>(3,0) = pose_covariance_msg.block<3,3>(0,3).transpose();
00381     }
00382   }
00383 }
00384 
00385 void PoseEstimation::getPose(tf::Pose& pose) {
00386   tf::Quaternion quaternion;
00387   getPosition(pose.getOrigin());
00388   getOrientation(quaternion);
00389   pose.setRotation(quaternion);
00390 }
00391 
00392 void PoseEstimation::getPose(tf::Stamped<tf::Pose>& pose) {
00393   getPose(static_cast<tf::Pose &>(pose));
00394   pose.stamp_ = getTimestamp();
00395   pose.frame_id_ = nav_frame_;
00396 }
00397 
00398 void PoseEstimation::getPose(geometry_msgs::Pose& pose) {
00399   getPosition(pose.position);
00400   getOrientation(pose.orientation);
00401 }
00402 
00403 void PoseEstimation::getPose(geometry_msgs::PoseStamped& pose) {
00404   getHeader(pose.header);
00405   getPose(pose.pose);
00406 }
00407 
00408 void PoseEstimation::getPosition(tf::Point& point) {
00409   State::ConstPositionType position(state().getPosition());
00410   point = tf::Point(position.x(), position.y(), position.z());
00411 }
00412 
00413 void PoseEstimation::getPosition(tf::Stamped<tf::Point>& point) {
00414   getPosition(static_cast<tf::Point &>(point));
00415   point.stamp_ = getTimestamp();
00416   point.frame_id_ = nav_frame_;
00417 }
00418 
00419 void PoseEstimation::getPosition(geometry_msgs::Point& point) {
00420   State::ConstPositionType position(state().getPosition());
00421   point.x = position.x();
00422   point.y = position.y();
00423   point.z = position.z();
00424 }
00425 
00426 void PoseEstimation::getPosition(geometry_msgs::PointStamped& point) {
00427   getHeader(point.header);
00428   getPosition(point.point);
00429 }
00430 
00431 void PoseEstimation::getGlobalPosition(double &latitude, double &longitude, double &altitude) {
00432   State::ConstPositionType position(state().getPosition());
00433   double north =  position.x() * globalReference()->heading().cos - position.y() * globalReference()->heading().sin;
00434   double east  = -position.x() * globalReference()->heading().sin - position.y() * globalReference()->heading().cos;
00435   latitude  = globalReference()->position().latitude  + north / globalReference()->radius().north;
00436   longitude = globalReference()->position().longitude + east  / globalReference()->radius().east;
00437   altitude  = globalReference()->position().altitude  + position.z();
00438 }
00439 
00440 void PoseEstimation::getGlobalPosition(sensor_msgs::NavSatFix& global)
00441 {
00442   getHeader(global.header);
00443   global.header.frame_id = world_frame_;
00444 
00445   if ((getSystemStatus() & STATE_POSITION_XY) && globalReference()->hasPosition()) {
00446     global.status.status = sensor_msgs::NavSatStatus::STATUS_FIX;
00447   } else {
00448     global.status.status = sensor_msgs::NavSatStatus::STATUS_NO_FIX;
00449   }
00450 
00451   getGlobalPosition(global.latitude, global.longitude, global.altitude);
00452   global.latitude  *= 180.0/M_PI;
00453   global.longitude *= 180.0/M_PI;
00454 
00455   if (getSystemStatus() & STATE_POSITION_XY) {
00456     global.status.status = sensor_msgs::NavSatStatus::STATUS_FIX;
00457   } else {
00458     global.status.status = sensor_msgs::NavSatStatus::STATUS_NO_FIX;
00459   }
00460 }
00461 
00462 void PoseEstimation::getOrientation(tf::Quaternion& quaternion) {
00463   Quaternion orientation(state().getOrientation());
00464   quaternion = tf::Quaternion(orientation.x(), orientation.y(), orientation.z(), orientation.w());
00465 }
00466 
00467 void PoseEstimation::getOrientation(tf::Stamped<tf::Quaternion>& quaternion) {
00468   getOrientation(static_cast<tf::Quaternion &>(quaternion));
00469   quaternion.stamp_ = getTimestamp();
00470   quaternion.frame_id_ = nav_frame_;
00471 }
00472 
00473 void PoseEstimation::getOrientation(geometry_msgs::Quaternion& quaternion) {
00474   Quaternion orientation(state().getOrientation());
00475   quaternion.w = orientation.w();
00476   quaternion.x = orientation.x();
00477   quaternion.y = orientation.y();
00478   quaternion.z = orientation.z();
00479 }
00480 
00481 void PoseEstimation::getOrientation(geometry_msgs::QuaternionStamped& quaternion) {
00482   getHeader(quaternion.header);
00483   getOrientation(quaternion.quaternion);
00484 }
00485 
00486 void PoseEstimation::getOrientation(double &yaw, double &pitch, double &roll) {
00487   tf::Quaternion quaternion;
00488   getOrientation(quaternion);
00489 #ifdef TF_MATRIX3x3_H
00490   tf::Matrix3x3(quaternion).getRPY(roll, pitch, yaw);
00491 #else
00492   btMatrix3x3(quaternion).getRPY(roll, pitch, yaw);
00493 #endif
00494 }
00495 
00496 void PoseEstimation::getImuWithBiases(geometry_msgs::Vector3& linear_acceleration, geometry_msgs::Vector3& angular_velocity) {
00497   boost::shared_ptr<const ImuInput>  input     = boost::shared_dynamic_cast<const ImuInput>(getInput("imu"));
00498   boost::shared_ptr<const Accelerometer> accel = boost::shared_dynamic_cast<const Accelerometer>(getSystem("accelerometer"));
00499 
00500   if (input) {
00501     linear_acceleration.x = input->getAcceleration().x();
00502     linear_acceleration.y = input->getAcceleration().y();
00503     linear_acceleration.z = input->getAcceleration().z();
00504   } else {
00505     linear_acceleration.x = 0.0;
00506     linear_acceleration.y = 0.0;
00507     linear_acceleration.z = 0.0;
00508   }
00509 
00510   if (accel) {
00511     linear_acceleration.x += accel->getModel()->getBias().x();
00512     linear_acceleration.y += accel->getModel()->getBias().y();
00513     linear_acceleration.z += accel->getModel()->getBias().z();
00514   }
00515 
00516   getRate(angular_velocity);
00517 }
00518 
00519 void PoseEstimation::getVelocity(tf::Vector3& vector) {
00520   State::ConstVelocityType velocity(state().getVelocity());
00521   vector = tf::Vector3(velocity.x(), velocity.y(), velocity.z());
00522 }
00523 
00524 void PoseEstimation::getVelocity(tf::Stamped<tf::Vector3>& vector) {
00525   getVelocity(static_cast<tf::Vector3 &>(vector));
00526   vector.stamp_ = getTimestamp();
00527 #ifdef VELOCITY_IN_BODY_FRAME
00528   vector.frame_id_ = base_frame_;
00529 #else
00530   vector.frame_id_ = nav_frame_;
00531 #endif
00532 }
00533 
00534 void PoseEstimation::getVelocity(geometry_msgs::Vector3& vector) {
00535   State::ConstVelocityType velocity(state().getVelocity());
00536   vector.x = velocity.x();
00537   vector.y = velocity.y();
00538   vector.z = velocity.z();
00539 }
00540 
00541 void PoseEstimation::getVelocity(geometry_msgs::Vector3Stamped& vector) {
00542   getHeader(vector.header);
00543 #ifdef VELOCITY_IN_BODY_FRAME
00544   vector.header.frame_id = base_frame_;
00545 #endif
00546   getVelocity(vector.vector);
00547 }
00548 
00549 void PoseEstimation::getRate(tf::Vector3& vector) {
00550   geometry_msgs::Vector3 rate;
00551   getRate(rate);
00552   vector = tf::Vector3(rate.x, rate.y, rate.z);
00553 }
00554 
00555 void PoseEstimation::getRate(tf::Stamped<tf::Vector3>& vector) {
00556   getRate(static_cast<tf::Vector3 &>(vector));
00557   vector.stamp_ = getTimestamp();
00558 #ifdef VELOCITY_IN_BODY_FRAME
00559   vector.frame_id_ = base_frame_;
00560 #else
00561   vector.frame_id_ = nav_frame_;
00562 #endif
00563 }
00564 
00565 void PoseEstimation::getRate(geometry_msgs::Vector3& vector) {
00566   if (state().getRateIndex() >= 0) {
00567     State::ConstRateType rate(state().getRate());
00568     vector.x    = rate.x();
00569     vector.y    = rate.y();
00570     vector.z    = rate.z();
00571 
00572   } else {
00573     boost::shared_ptr<const ImuInput> input = boost::shared_dynamic_cast<const ImuInput>(getInput("imu"));
00574     boost::shared_ptr<const Gyro> gyro      = boost::shared_dynamic_cast<const Gyro>(getSystem("gyro"));
00575 
00576     if (input) {
00577       vector.x = input->getRate().x();
00578       vector.y = input->getRate().y();
00579       vector.z = input->getRate().z();
00580     } else {
00581       vector.x = 0.0;
00582       vector.y = 0.0;
00583       vector.z = 0.0;
00584     }
00585 
00586     if (gyro) {
00587       vector.x += gyro->getModel()->getBias().x();
00588       vector.y += gyro->getModel()->getBias().y();
00589       vector.z += gyro->getModel()->getBias().z();
00590     }
00591   }
00592 }
00593 
00594 void PoseEstimation::getRate(geometry_msgs::Vector3Stamped& vector) {
00595   getHeader(vector.header);
00596   getRate(vector.vector);
00597 
00598   if (state().getRateIndex() >= 0) {
00599 #ifdef VELOCITY_IN_BODY_FRAME
00600     vector.header.frame_id = base_frame_;
00601 #else
00602     vector.header.frame_id = nav_frame_;
00603 #endif
00604   } else {
00605     vector.header.frame_id = base_frame_;
00606   }
00607 }
00608 
00609 void PoseEstimation::getBias(geometry_msgs::Vector3& angular_velocity, geometry_msgs::Vector3& linear_acceleration) {
00610   boost::shared_ptr<const ImuInput>  input     = boost::shared_dynamic_cast<const ImuInput>(getInput("imu"));
00611   boost::shared_ptr<const Accelerometer> accel = boost::shared_dynamic_cast<const Accelerometer>(getSystem("accelerometer"));
00612   boost::shared_ptr<const Gyro> gyro           = boost::shared_dynamic_cast<const Gyro>(getSystem("gyro"));
00613 
00614   if (gyro) {
00615     angular_velocity.x = gyro->getModel()->getBias().x();
00616     angular_velocity.y = gyro->getModel()->getBias().y();
00617     angular_velocity.z = gyro->getModel()->getBias().z();
00618   } else {
00619     angular_velocity.x = 0.0;
00620     angular_velocity.y = 0.0;
00621     angular_velocity.z = 0.0;
00622   }
00623 
00624   if (accel) {
00625     linear_acceleration.x = accel->getModel()->getBias().x();
00626     linear_acceleration.y = accel->getModel()->getBias().y();
00627     linear_acceleration.z = accel->getModel()->getBias().z();
00628   } else {
00629     linear_acceleration.x = 0.0;
00630     linear_acceleration.y = 0.0;
00631     linear_acceleration.z = 0.0;
00632   }
00633 }
00634 
00635 void PoseEstimation::getBias(geometry_msgs::Vector3Stamped& angular_velocity, geometry_msgs::Vector3Stamped& linear_acceleration) {
00636   getBias(angular_velocity.vector, linear_acceleration.vector);
00637   angular_velocity.header.stamp = getTimestamp();
00638   angular_velocity.header.frame_id = base_frame_;
00639   linear_acceleration.header.stamp = getTimestamp();
00640   linear_acceleration.header.frame_id = base_frame_;
00641 }
00642 
00643 void PoseEstimation::getTransforms(std::vector<tf::StampedTransform>& transforms) {
00644   tf::Quaternion orientation;
00645   tf::Point position;
00646   getOrientation(orientation);
00647   getPosition(position);
00648 
00649   tf::Transform transform(orientation, position);
00650   double y,p,r;
00651   transform.getBasis().getEulerYPR(y,p,r);
00652 
00653   std::string parent_frame = nav_frame_;
00654 
00655   if(!position_frame_.empty()) {
00656     tf::Transform position_transform;
00657     position_transform.getBasis().setIdentity();
00658     position_transform.setOrigin(tf::Point(position.x(), position.y(), position.z()));
00659     transforms.push_back(tf::StampedTransform(position_transform, getTimestamp(), parent_frame, position_frame_ ));
00660   }
00661 
00662   if (!footprint_frame_.empty()) {
00663     tf::Transform footprint_transform;
00664     footprint_transform.getBasis().setEulerYPR(y, 0.0, 0.0);
00665     footprint_transform.setOrigin(tf::Point(position.x(), position.y(), 0.0));
00666     transforms.push_back(tf::StampedTransform(footprint_transform, getTimestamp(), parent_frame, footprint_frame_));
00667 
00668     parent_frame = footprint_frame_;
00669     transform = footprint_transform.inverseTimes(transform);
00670   }
00671 
00672   if (!stabilized_frame_.empty()) {
00673     tf::Transform stabilized_transform(transform);
00674 #ifdef TF_MATRIX3x3_H
00675     tf::Matrix3x3 rollpitch_rotation; rollpitch_rotation.setEulerYPR(0.0, p, r);
00676 #else
00677     btMatrix3x3 rollpitch_rotation; rollpitch_rotation.setEulerYPR(0.0, p, r);
00678 #endif
00679     stabilized_transform = stabilized_transform * tf::Transform(rollpitch_rotation.inverse());
00680     transforms.push_back(tf::StampedTransform(stabilized_transform, getTimestamp(), parent_frame, stabilized_frame_));
00681 
00682     parent_frame = stabilized_frame_;
00683     transform = stabilized_transform.inverseTimes(transform);
00684   }
00685 
00686   transforms.push_back(tf::StampedTransform(transform, getTimestamp(), parent_frame, base_frame_));
00687 
00688 //  transforms.resize(3);
00689 
00690 //  transforms[0].stamp_ = getTimestamp();
00691 //  transforms[0].frame_id_ = nav_frame_;
00692 //  transforms[0].child_frame_id_ = footprint_frame_;
00693 //  transforms[0].setOrigin(tf::Point(position.x(), position.y(), 0.0));
00694 //  rotation.setEulerYPR(y,0.0,0.0);
00695 //  transforms[0].setBasis(rotation);
00696 
00697 //  transforms[1].stamp_ = getTimestamp();
00698 //  transforms[1].frame_id_ = footprint_frame_;
00699 //  transforms[1].child_frame_id_ = stabilized_frame_;
00700 //  transforms[1].setIdentity();
00701 //  transforms[1].setOrigin(tf::Point(0.0, 0.0, position.z()));
00702 
00703 //  transforms[2].stamp_ = getTimestamp();
00704 //  transforms[2].frame_id_ = stabilized_frame_;
00705 //  transforms[2].child_frame_id_ = base_frame_;
00706 //  transforms[2].setIdentity();
00707 //  rotation.setEulerYPR(0.0,p,r);
00708 //  transforms[2].setBasis(rotation);
00709 }
00710 
00711 void PoseEstimation::updateWorldToOtherTransform(tf::StampedTransform& world_to_other_transform) {
00712   world_to_other_transform.frame_id_ = world_frame_;
00713 
00714   double y,p,r;
00715   world_to_other_transform.getBasis().getEulerYPR(y,p,r);
00716   if (!(getSystemStatus() & (STATE_ROLLPITCH   | STATE_PSEUDO_ROLLPITCH)))   { r = p = 0.0; }
00717   if (!(getSystemStatus() & (STATE_YAW         | STATE_PSEUDO_YAW)))         { y = 0.0; }
00718   if (!(getSystemStatus() & (STATE_POSITION_XY | STATE_PSEUDO_POSITION_XY))) { world_to_other_transform.getOrigin().setX(0.0); world_to_other_transform.getOrigin().setY(0.0); }
00719   if (!(getSystemStatus() & (STATE_POSITION_Z  | STATE_PSEUDO_POSITION_Z)))  { world_to_other_transform.getOrigin().setZ(0.0); }
00720   world_to_other_transform.getBasis().setEulerYPR(y, p, r);
00721 }
00722 
00723 const GlobalReferencePtr &PoseEstimation::globalReference() {
00724   return GlobalReference::Instance();
00725 }
00726 
00727 } // namespace hector_pose_estimation


hector_pose_estimation_core
Author(s): Johannes Meyer
autogenerated on Mon Oct 6 2014 00:24:16