segway_rmp400_odom_fused_alg_node.cpp
Go to the documentation of this file.
00001 #include "segway_rmp400_odom_fused_alg_node.h"
00002 #include <algorithm>
00003 
00004 using namespace Eigen;
00005 
00006 SegwayRmp400OdomAlgNode::SegwayRmp400OdomAlgNode(void) :
00007   algorithm_base::IriBaseAlgorithm<SegwayRmp400OdomAlgorithm>(),
00008   r_(0),
00009   p_(0),
00010   th_(0),
00011   dth_(0),
00012   sigma2_dth_(0),
00013   first_segway_status_(true),
00014   first_imu_(true)
00015 {
00016   //init class attributes if necessary
00017   loop_rate_ = 10;//in [Hz]
00018 
00019   public_node_handle_.param<std::string>("tf_prefix",        tf_prefix_,        "");
00020   public_node_handle_.param<std::string>("odom_id",          odom_id_,          "odom" );
00021   public_node_handle_.param<std::string>("base_link_id",     base_link_id_,     "base_footprint" );
00022   public_node_handle_.param<bool>       ("six_d",            six_d_,            true );
00023   public_node_handle_.param<bool>       ("publish_tf",       publish_tf_,       true );
00024   public_node_handle_.param<bool>       ("publish_odom_rel", publish_odom_rel_, true );
00025   public_node_handle_.param<double>     ("sigma_dx_fwd",     sigma_dx_fwd_,     0.00425 ); //teo_apps error_icp_mp.py
00026   public_node_handle_.param<double>     ("sigma_dx_turn",    sigma_dx_turn_,    0.00425 ); //teo_apps error_icp_mp.py
00027   public_node_handle_.param<double>     ("sigma_thimu",      sigma_thimu_,      0.00453 ); //teo_apps error_imu.py
00028   public_node_handle_.param<double>     ("offset_fwd",       offset_fwd_,       0.06758 ); //teo_apps error_icp_mp.py
00029   public_node_handle_.param<double>     ("offset_turn",      offset_turn_,      0.06758 ); //teo_apps error_icp_mp.py
00030 
00031   cov_ = MatrixXf::Zero(3,3);
00032   Q_   = MatrixXf::Zero(3,3);
00033   Jp_  = MatrixXf::Identity(3,3);
00034   Jd_  = MatrixXf::Identity(3,3);
00035 
00036   // push down frame ids if necessary
00037   if( tf_prefix_.size()!=0 )
00038   {
00039     odom_id_      = tf_prefix_ + "/" + odom_id_;
00040     base_link_id_ = tf_prefix_ + "/" + base_link_id_;
00041   }
00042 
00043   // [init publishers]
00044   odom_publisher_ = public_node_handle_.advertise<nav_msgs::Odometry>("odom", 100);
00045   odom_rel_publisher_ = public_node_handle_.advertise<nav_msgs::Odometry>("odom_rel", 100);
00046 
00047   // [init subscribers]
00048   segway_status_subscriber_ = public_node_handle_.subscribe("segway_status", 100, &SegwayRmp400OdomAlgNode::segway_status_callback, this);
00049   imu_subscriber_ = public_node_handle_.subscribe("imu", 100, &SegwayRmp400OdomAlgNode::imu_callback, this);
00050 
00051 }
00052 
00053 SegwayRmp400OdomAlgNode::~SegwayRmp400OdomAlgNode(void)
00054 {
00055   // [free dynamic memory]
00056 }
00057 
00058 void SegwayRmp400OdomAlgNode::mainNodeThread(void)
00059 {
00060   // Initialize Time
00061   if(first_segway_status_)
00062   {
00063       last_time_ = ros::Time::now();
00064       first_segway_status_=false;
00065   }
00066   ros::Time current_time = ros::Time::now();
00067 
00068   // compute delta time
00069   double dt = (current_time - last_time_).toSec();
00070   last_time_ = current_time;
00071 
00072   // Get translational velocity and last theta angle
00073   segway_status_mutex_.enter();
00074     double vT = vT_;
00075   segway_status_mutex_.exit();
00076   // Get IMU variance2, delta yaw, angular velocities, reset delta theta and sigma^2
00077   imu_mutex_.enter();
00078     double sigma2_dth = sigma2_dth_;
00079     sigma2_dth_ = 0;
00080     double dth = dth_;
00081     dth_ = 0;
00082     double r = r_;
00083     double p = p_;
00084     double vrimu  = vrimu_;
00085     double vpimu  = vpimu_;
00086     double vthimu = vthimu_;
00087   imu_mutex_.exit();
00088 
00089   // Kinematic Model = translation + rotation
00090   // Propagate covariance using the previous angle
00091   double dx_local,sigma_dx;
00092   if (fabs(vthimu)>0.05)
00093   {
00094     dx_local  = vT*dt*(1+ offset_turn_);
00095     sigma_dx = sigma_dx_turn_;
00096   }else{
00097     dx_local  = vT*dt*(1+offset_fwd_);
00098     sigma_dx = sigma_dx_fwd_;
00099   }
00100   double dy_local = 0;
00101   // Reference Point Jacobian
00102   Jp_(0,2) =-sin(th_)*dx_local - cos(th_)*dy_local;
00103   Jp_(1,2) = cos(th_)*dx_local - sin(th_)*dy_local;
00104   // Displacement Jacobian
00105   Jd_(0,0) = cos(th_);
00106   Jd_(0,1) =-sin(th_);
00107   Jd_(1,0) = sin(th_);
00108   Jd_(1,1) = cos(th_);
00109   // Sensor noise
00110   Q_(0,0) = sigma_dx*sigma_dx;
00111   Q_(1,1) = 1e-10;
00112   Q_(2,2) = sigma2_dth;
00113   // Covariance propagation
00114   cov_ = Jp_ * cov_ * Jp_.transpose() + Jd_ * Q_ * Jd_.transpose();
00115   // Relative Covariance (Local coordinates)
00116   Eigen::Matrix3f cov_rel = Q_;
00117 
00118 
00119   // Get x,y,z displacements (Global coordinates)
00120   // displacements          TODO 3D (6D)               2D (3D)
00121   double dx  = six_d_ ? dx_local*cos(th_)*cos(p) : dx_local*cos(th_)-dy_local*sin(th_);
00122   double dy  = six_d_ ? dx_local*sin(th_)*cos(r) : dx_local*sin(th_)+dy_local*cos(th_);
00123   double dz  = six_d_ ? dx_local*cos(r)*sin(p)   : 0.0;
00124   // update and accumulate yaw angle theta
00125   th_ += dth;
00126 
00127   // Update message
00128   geometry_msgs::TransformStamped odom_trans_msg;
00129   Odometry_msg_.header.stamp    = odom_trans_msg.header.stamp    = current_time;
00130   Odometry_msg_.header.frame_id = odom_trans_msg.header.frame_id = odom_id_;
00131   Odometry_msg_.child_frame_id  = odom_trans_msg.child_frame_id  = base_link_id_;
00132 
00133   odom_trans_msg.transform.translation.x = Odometry_msg_.pose.pose.position.x  += dx;
00134   odom_trans_msg.transform.translation.y = Odometry_msg_.pose.pose.position.y  += dy;
00135   odom_trans_msg.transform.translation.z = Odometry_msg_.pose.pose.position.z  += dz;
00136   // Calculate rotation quaternion
00137   geometry_msgs::Quaternion rot,rot_rel;
00138   if(six_d_) rot = tf::createQuaternionMsgFromRollPitchYaw(r,-p,th_);
00139   else rot = tf::createQuaternionMsgFromYaw (th_);
00140   odom_trans_msg.transform.rotation      = Odometry_msg_.pose.pose.orientation  = rot;
00141 
00142   Odometry_msg_.pose.covariance[0]  = cov_(0,0);
00143   Odometry_msg_.pose.covariance[1]  = cov_(0,1);
00144   Odometry_msg_.pose.covariance[5]  = cov_(0,2);
00145   Odometry_msg_.pose.covariance[6]  = cov_(1,0);
00146   Odometry_msg_.pose.covariance[7]  = cov_(1,1);
00147   Odometry_msg_.pose.covariance[11] = cov_(1,2);
00148   Odometry_msg_.pose.covariance[30] = cov_(2,0);
00149   Odometry_msg_.pose.covariance[31] = cov_(2,1);
00150   Odometry_msg_.pose.covariance[35] = cov_(2,2);
00151 
00152   Odometry_msg_.twist.twist.linear.x  = vT;
00153   Odometry_msg_.twist.twist.linear.y  = 0.0;
00154   Odometry_msg_.twist.twist.linear.z  = 0.0;
00155   Odometry_msg_.twist.twist.angular.x = vrimu;
00156   Odometry_msg_.twist.twist.angular.y = vpimu;
00157   Odometry_msg_.twist.twist.angular.z = vthimu;
00158 
00159   Odometry_msg_.twist.covariance[0]  = sigma_dx*sigma_dx;
00160   Odometry_msg_.twist.covariance[35] = sigma2_dth_/(dt*dt);
00161 
00162   // Relative Odometry TODO assure which covariance use
00163   Odometry_rel_msg_ = Odometry_msg_;
00164   Odometry_rel_msg_.pose.pose.position.x  = dx_local;
00165   Odometry_rel_msg_.pose.pose.position.y  = dy_local;
00166   // Relative rotation TODO 6D rotation
00167   //if(six_d_) rot_rel = tf::createQuaternionMsgFromRollPitchYaw(dr,-dp,dth);
00168   //else 
00169   rot_rel = tf::createQuaternionMsgFromYaw (dth);
00170   Odometry_rel_msg_.pose.pose.orientation = rot_rel;
00171   Odometry_rel_msg_.pose.covariance[0]    = cov_rel(0,0);
00172   Odometry_rel_msg_.pose.covariance[1]    = cov_rel(0,1);
00173   Odometry_rel_msg_.pose.covariance[5]    = cov_rel(0,2);
00174   Odometry_rel_msg_.pose.covariance[6]    = cov_rel(1,0);
00175   Odometry_rel_msg_.pose.covariance[7]    = cov_rel(1,1);
00176   Odometry_rel_msg_.pose.covariance[11]   = cov_rel(1,2);
00177   Odometry_rel_msg_.pose.covariance[30]   = cov_rel(2,0);
00178   Odometry_rel_msg_.pose.covariance[31]   = cov_rel(2,1);
00179   Odometry_rel_msg_.pose.covariance[35]   = cov_rel(2,2);
00180 
00181   // Publish Odometry Message
00182   odom_publisher_.publish(Odometry_msg_);
00183   if(publish_odom_rel_)
00184     odom_rel_publisher_.publish(Odometry_rel_msg_);
00185   if(publish_tf_)
00186     odom_broadcaster_.sendTransform(odom_trans_msg);
00187 }
00188 
00189 void SegwayRmp400OdomAlgNode::segway_status_callback(const iri_segway_rmp_msgs::SegwayRMP400Status::ConstPtr& msg) 
00190 {
00191   // Get Segway's Translational Velocity
00192   segway_status_mutex_.enter();
00193     vT_ = (msg->rmp200[0].left_wheel_velocity + msg->rmp200[0].right_wheel_velocity +
00194            msg->rmp200[1].left_wheel_velocity + msg->rmp200[1].right_wheel_velocity)/4;
00195   segway_status_mutex_.exit();
00196 }
00197 
00198 void SegwayRmp400OdomAlgNode::imu_callback(const sensor_msgs::Imu::ConstPtr& msg)
00199 {
00200   //use appropiate mutex to shared variables if necessary
00201   //alg_.lock();
00202   imu_mutex_.enter();
00203 
00204   if(first_imu_)
00205   {
00206     last_time_imu_ = msg->header.stamp;
00207     first_imu_ = false;
00208   }
00209 
00210   // get time stamp
00211   ros::Time current_time_imu = msg->header.stamp;
00212   // get yaw velocity
00213   vrimu_ = msg->angular_velocity.x;
00214   vpimu_ = msg->angular_velocity.y;
00215   vthimu_ = -msg->angular_velocity.z;
00216 
00217   // TODO get roll and pitch angles straight from the imu
00218   tf::Quaternion q;
00219   tf::quaternionMsgToTF(msg->orientation,q);
00220   tf::Matrix3x3(q).getRPY(rimu_, pimu_, thimu_);
00221 
00222   // Fix roll angle
00223   rimu_ = rimu_<0 ? rimu_+M_PI : rimu_-M_PI;
00224 
00225   r_ = rimu_;
00226   p_ = -pimu_;
00227 
00228   double dt_imu = (current_time_imu - last_time_imu_).toSec();
00229   last_time_imu_ = current_time_imu;
00230 
00231   // delta theta accum
00232   dth_ += vthimu_ * dt_imu;
00233   // covariance accum
00234   sigma2_dth_ += sigma_thimu_ * sigma_thimu_;
00235 
00236 
00237   //unlock previously blocked shared variables 
00238   //alg_.unlock(); 
00239   imu_mutex_.exit(); 
00240 }
00241 
00242 /*  [service callbacks] */
00243 
00244 /*  [action callbacks] */
00245 
00246 /*  [action requests] */
00247 
00248 void SegwayRmp400OdomAlgNode::node_config_update(Config &config, uint32_t level)
00249 {
00250   alg_.lock();
00251 
00252   alg_.unlock();
00253 }
00254 
00255 void SegwayRmp400OdomAlgNode::addNodeDiagnostics(void)
00256 {
00257 }
00258 
00259 /* main function */
00260 int main(int argc,char *argv[])
00261 {
00262   return algorithm_base::main<SegwayRmp400OdomAlgNode>(argc, argv, "segway_rmp400_odom_alg_node");
00263 }


iri_segway_rmp400_odom
Author(s): mmorta
autogenerated on Fri Dec 6 2013 23:10:58