kinton_odom_alg_node.cpp
Go to the documentation of this file.
00001 #include "kinton_odom_alg_node.h"
00002 
00003 KintonOdomAlgNode::KintonOdomAlgNode(void) :
00004   algorithm_base::IriBaseAlgorithm<KintonOdomAlgorithm>()
00005 {
00006   //init class attributes if necessary
00007   this->loop_rate_ = 100;//in [Hz]
00008 
00009   this->public_node_handle_.param<std::string>("tf_prefix",    this->tf_prefix_,    "");
00010   this->public_node_handle_.param<std::string>("odom_id",      this->odom_id_,      "odom" );
00011   this->public_node_handle_.param<std::string>("base_link_id", this->base_link_id_, "base_link" );
00012   this->public_node_handle_.param<bool>       ("publish_tf",   this->publish_tf_,   true  );
00013   
00014   // push down frame ids if necessary
00015   if( this->tf_prefix_.size()!=0 )
00016   {
00017     this->odom_id_      = this->tf_prefix_ + "/" + this->odom_id_;
00018     this->base_link_id_ = this->tf_prefix_ + "/" + this->base_link_id_;
00019   }
00020 
00021   ini_zeros();
00022 
00023   //wait 1 secs waiting for the other nodes to start
00024   sleep(1.0);
00025 
00026   //Get fixed transforms between the IMU data and the robot frame
00027   tf::TransformListener listener1,listener2,listener3;
00028   tf::StampedTransform tf_accelerometers,tf_gyros,tf_compass;
00029 
00030   try {
00031     listener1.waitForTransform("/base_link","/accelerometers", ros::Time::now(), ros::Duration(1.0));
00032     listener1.lookupTransform("/base_link","/accelerometers", ros::Time::now(), tf_accelerometers);
00033   } 
00034   catch (tf::TransformException ex1) {
00035     ROS_ERROR("Accelerometers Transform error: %s",ex1.what());
00036   }
00037 
00038   try {
00039     listener2.waitForTransform("/base_link","/gyros", ros::Time::now(), ros::Duration(1.0));
00040     listener2.lookupTransform("/base_link","/gyros", ros::Time::now(), tf_gyros);
00041   }
00042   catch (tf::TransformException ex2) {
00043     ROS_ERROR("Gyros Transform error: %s",ex2.what());
00044   }
00045 
00046   try {
00047     listener3.waitForTransform("/base_link","/compass", ros::Time::now(), ros::Duration(1.0));
00048     listener3.lookupTransform("/base_link","/compass", ros::Time::now(), tf_compass);
00049   }
00050   catch (tf::TransformException ex3) {
00051     ROS_ERROR("Compass Transform error: %s",ex3.what());
00052   }
00053 
00054 
00055   //Transform to eigen 4x4 matrix
00056   this->T_acc_ = getTransform(tf_accelerometers);
00057   this->T_gyr_ = getTransform(tf_gyros);
00058   this->T_comp_ = getTransform(tf_compass);
00059 
00060   // [init publishers]
00061   this->odom_publisher_ = this->public_node_handle_.advertise<nav_msgs::Odometry>("odom", 100);
00062   
00063   // [init subscribers]
00064   this->imu_subscriber_ = this->public_node_handle_.subscribe("imu", 100, &KintonOdomAlgNode::imu_callback, this);
00065   this->height_point_subscriber_ = this->public_node_handle_.subscribe("height_point", 100, &KintonOdomAlgNode::height_point_callback, this);
00066 
00067    
00068   // [init services]
00069   
00070   // [init clients]
00071   
00072   // [init action servers]
00073   
00074   // [init action clients]
00075 }
00076 
00077 KintonOdomAlgNode::~KintonOdomAlgNode(void)
00078 {
00079   // [free dynamic memory]
00080 }
00081 
00082 void KintonOdomAlgNode::mainNodeThread(void)
00083 {
00084   geometry_msgs::TransformStamped odom_trans_msg;
00085 
00086   //compute differencial
00087   double dt = (this->current_time_ - this->last_time_).toSec();
00088   if (dt > 10) dt = 0.01;
00089   //ROS_ERROR_STREAM("Times: " << this->last_time_ << " " << this->current_time_ << " dt: " << dt);
00090 
00091   //update the last_time
00092   this->last_time_ = this->current_time_;
00093 
00094   // Sensors data ///////////////////////////////////////////////////////////
00095   //get data from the IMU
00096   Eigen::MatrixXd pos_ang_imu(3,1), vel_ang_imu(3,1), acc_lin_imu(3,1);
00097   this->imu_mutex_.enter();  
00098     pos_ang_imu = this->pos_ang_imu_;
00099     vel_ang_imu = this->vel_ang_imu_;
00100     acc_lin_imu = this->acc_lin_imu_;
00101   this->imu_mutex_.exit();  
00102   //get data from height
00103   double height;
00104   this->height_point_mutex_.enter(); 
00105     height = this->height_;
00106   this->height_point_mutex_.exit(); 
00107 
00108   //ANGLES r.t ODOM frame (Integrated angular velocities) ///////////////////
00109   this->pos_ang_odom_ += vel_ang_imu * dt;
00110   geometry_msgs::Quaternion rot;
00111   rot = tf::createQuaternionMsgFromRollPitchYaw(this->pos_ang_odom_(0,0),this->pos_ang_odom_(1,0),this->pos_ang_odom_(2,0));
00112   //Get rotation matrix
00113   Eigen::Matrix3d R_mov;
00114   R_mov = Eigen::AngleAxisd(this->pos_ang_odom_(0,0), Eigen::Vector3d::UnitX()) \
00115       * Eigen::AngleAxisd(this->pos_ang_odom_(1,0), Eigen::Vector3d::UnitY()) \
00116       * Eigen::AngleAxisd(this->pos_ang_odom_(2,0), Eigen::Vector3d::UnitZ());
00117 
00118   // LINEAR VELOCITY vector (Integrated linear accelerations) ///////////////
00119   Eigen::MatrixXd vel_lin_imu(3,1);
00120   vel_lin_imu = acc_lin_imu * dt;
00121   //r.t. ODOM frame
00122   this->vel_lin_odom_ += R_mov * vel_lin_imu;
00123 
00124   // LINEAR POSITIONS r.t. ODOM (Integrated lineal velocities) ///////////////
00125   this->pos_lin_odom_ += this->vel_lin_odom_ * dt;
00126 
00127 
00128   // [fill msg structures]
00129 
00130   //update transform message
00131   this->transform_.translation.x = this->pos_lin_odom_(0,0);
00132   this->transform_.translation.y = this->pos_lin_odom_(1,0);
00133   //this->transform_.translation.z = this->pos_lin_odom_(2,0);
00134   this->transform_.translation.z = height;
00135   this->transform_.rotation      = rot;
00136 
00137   //update pose
00138   this->pose_.pose.position.x = this->pos_lin_odom_(0,0);
00139   this->pose_.pose.position.y = this->pos_lin_odom_(1,0);
00140   // this->pose_.pose.position.z = this->pos_lin_odom_(2,0);
00141   this->pose_.pose.position.z = height;
00142   this->pose_.pose.orientation = rot;
00143   this->pose_.covariance[0]  = 
00144   this->pose_.covariance[7]  = 
00145   this->pose_.covariance[14] = 
00146   this->pose_.covariance[21] = 
00147   this->pose_.covariance[28] = 
00148   this->pose_.covariance[35] = 0.5;
00149 
00150   //update twist
00151   this->twist_.twist.linear.x  = vel_lin_imu(0,0);
00152   this->twist_.twist.linear.y  = vel_lin_imu(1,0);
00153   this->twist_.twist.linear.z  = vel_lin_imu(2,0);
00154   this->twist_.twist.angular.x = vel_ang_imu(0,0);
00155   this->twist_.twist.angular.y = vel_ang_imu(1,0);
00156   this->twist_.twist.angular.z = vel_ang_imu(2,0);
00157 
00158   this->twist_.covariance[0]  = 
00159   this->twist_.covariance[7]  = 
00160   this->twist_.covariance[14] = 
00161   this->twist_.covariance[21] = 
00162   this->twist_.covariance[28] = 
00163   this->twist_.covariance[35] = 0.01;
00164 
00165   //send the transform
00166   if(this->publish_tf_)
00167   {
00168     //Publish the transform over tf
00169     odom_trans_msg.header.stamp    = this->current_time_;
00170     odom_trans_msg.header.frame_id = this->odom_id_;
00171     odom_trans_msg.child_frame_id  = this->base_link_id_;
00172     odom_trans_msg.transform       = this->transform_;
00173 
00174     this->odom_broadcaster_.sendTransform(odom_trans_msg);
00175   }
00176 
00177   //Publish the odometry message over ROS
00178   this->Odometry_msg_.header.stamp    = this->current_time_;
00179   this->Odometry_msg_.header.frame_id = this->odom_id_;
00180   this->Odometry_msg_.child_frame_id  = this->base_link_id_;
00181   this->Odometry_msg_.pose            = this->pose_;
00182   this->Odometry_msg_.twist           = this->twist_;
00183 
00184   //this->Odometry_msg_.data = my_var;
00185   
00186   // [fill srv structure and make request to the server]
00187   
00188   // [fill action structure and make request to the action server]
00189 
00190   // [publish messages]
00191   this->odom_publisher_.publish(this->Odometry_msg_);
00192 }
00193 
00194 /*  [subscriber callbacks] */
00195 
00196 void KintonOdomAlgNode::imu_callback(const sensor_msgs::Imu::ConstPtr& msg) 
00197 { 
00198 
00199   //Considering the IMU frame with X(Fwd)-Y(Left)-Z(up), but the gravity positive (it should be removed)
00200 
00201 
00202   //ROS_INFO("KintonOdomAlgNode::imu_callback: New Message Received"); 
00203 
00204   //use appropiate mutex to shared variables if necessary 
00205   //this->alg_.lock(); 
00206   this->imu_mutex_.enter(); 
00207 
00208   //get time stamp
00209   this->current_time_ = msg->header.stamp;
00210 
00211   Eigen::MatrixXd pos_ang_imu(4,1), acc_lin_imu(4,1), vel_ang_imu(4,1);
00212 
00213   //Get vectors /////////////////////////////////////////////////////////////
00214   //linear accelerations in base_link (roll change of pi/2)
00215   acc_lin_imu(0,0) = msg->linear_acceleration.x;
00216   acc_lin_imu(1,0) = msg->linear_acceleration.y; 
00217   acc_lin_imu(2,0) = msg->linear_acceleration.z; 
00218   acc_lin_imu(3,0) = 1.0;
00219 
00220   //angular velocities in base_link
00221   vel_ang_imu(0,0) = msg->angular_velocity.x;
00222   vel_ang_imu(1,0) = msg->angular_velocity.y;
00223   vel_ang_imu(2,0) = msg->angular_velocity.z;
00224   vel_ang_imu(3,0) = 1.0;
00225 
00226   //angles base_link r.t. world
00227   tf::Quaternion q;
00228   tf::quaternionMsgToTF(msg->orientation,q);
00229   tf::Matrix3x3(q).getRPY(pos_ang_imu(0,0), pos_ang_imu(1,0), pos_ang_imu(2,0));
00230   pos_ang_imu(3,0) = 1.0;
00231 
00232   //Transform data to base_link frame /////////////////////////////////////////
00233   //To simplify the translation between frames won't be considered
00234   // acc_lin_imu = this->T_acc_ * acc_lin_imu;
00235   // vel_ang_imu = this->T_gyr_ * vel_ang_imu;
00236   // pos_ang_imu = this->T_comp_ * pos_ang_imu;
00237 
00238 
00239   //Gravity extraction from accelerations //////////////////////////////////////
00240   //Quadrotor pitch and roll
00241   this->Rquad_ = Eigen::AngleAxisd(pos_ang_imu(0,0), Eigen::Vector3d::UnitX()) \
00242       * Eigen::AngleAxisd(pos_ang_imu(1,0), Eigen::Vector3d::UnitY()) \
00243       * Eigen::AngleAxisd(pos_ang_imu(2,0), Eigen::Vector3d::UnitZ());
00244 
00245   //gravity vector    
00246   Eigen::MatrixXd g(3,1), new_g(3,1);
00247   g(0) = 0;
00248   g(1) = 0;
00249   g(2) = 9.8;
00250   new_g = this->Rquad_ * g;
00251 
00252   //Quadrotor acceleration
00253   acc_lin_imu(0,0) = (acc_lin_imu(0,0) - new_g(0,0));
00254   acc_lin_imu(1,0) = (acc_lin_imu(1,0) - new_g(1,0)); 
00255   acc_lin_imu(2,0) = (acc_lin_imu(2,0) - new_g(2,0)); 
00256   acc_lin_imu(3,0) = 1.0;
00257 
00259   //TODO: Do not consider IMU values
00260   acc_lin_imu = Eigen::MatrixXd::Zero(3,1);  
00261   //vel_ang_imu = Eigen::MatrixXd::Zero(3,1); 
00262   pos_ang_imu = Eigen::MatrixXd::Zero(3,1);
00264 
00265   this->acc_lin_imu_ = acc_lin_imu.block(0,0,3,1);
00266   this->vel_ang_imu_ = vel_ang_imu.block(0,0,3,1);
00267   this->pos_ang_imu_ = pos_ang_imu.block(0,0,3,1);
00268 
00269   // ROS_DEBUG("ACC_X:%f ACC_Y:%f ACC_Z:%f",this->acc_lin_imu_(0,0),this->acc_lin_imu_(1,0),this->acc_lin_imu_(2,0));
00270   // ROS_DEBUG("VEL_X:%f VEL_Y:%f VEL_Z:%f",this->vel_ang_imu_(0,0),this->vel_ang_imu_(1,0),this->vel_ang_imu_(2,0));
00271   // ROS_DEBUG("POS_X:%f POS_Y:%f POS_Z:%f",this->pos_ang_imu_(0,0),this->pos_ang_imu_(1,0),this->pos_ang_imu_(2,0));
00272 
00273 
00274   //unlock previously blocked shared variables 
00275   //this->alg_.unlock(); 
00276   this->imu_mutex_.exit(); 
00277 }
00278 
00279 void KintonOdomAlgNode::height_point_callback(const geometry_msgs::PointStamped::ConstPtr& msg) 
00280 {
00281   //ROS_INFO("KintonOdomAlgNode::height_point_callback: New Message Received"); 
00282 
00283   //use appropiate mutex to shared variables if necessary 
00284   //this->alg_.lock(); 
00285   this->height_point_mutex_.enter(); 
00286 
00287   this->height_ = msg->point.z;
00288 
00289   if (this->init_) {
00290     this->height_init_ = this->height_;
00291     this->init_ = false;
00292   }
00293   this->height_ = this->height_ - this->height_init_;   
00294         
00295 
00296   //unlock previously blocked shared variables 
00297   //this->alg_.unlock(); 
00298   this->height_point_mutex_.exit(); 
00299 }
00300 /*  [service callbacks] */
00301 
00302 /*  [action callbacks] */
00303 
00304 /*  [action requests] */
00305 
00306 void KintonOdomAlgNode::ini_zeros() 
00307 {
00308   ROS_DEBUG("Initialization to Zeros");
00309 
00310   this->last_time_ = ros::Time::now();
00311   usleep(10);
00312   this->current_time_ = ros::Time::now();
00313 
00314   //Initialization of positions, velocities and accelerations
00315   this->pos_ang_imu_ = Eigen::MatrixXd::Zero(3,1);
00316   this->vel_ang_imu_ = Eigen::MatrixXd::Zero(3,1);
00317   this->acc_lin_imu_ = Eigen::MatrixXd::Zero(3,1);
00318 
00319   //Initialization of linear velocities
00320   this->vel_lin_odom_ = Eigen::MatrixXd::Zero(3,1);
00321 
00322   //Initialization of angles
00323   this->pos_ang_odom_ = Eigen::MatrixXd::Zero(3,1);
00324 
00325   //Initialization of positions
00326   this->pos_lin_odom_ = Eigen::MatrixXd::Zero(3,1);
00327  
00328   //Initial height
00329   this->height_init_ = 0.0;  
00330 
00331   //Init = true
00332   this->init_ = true;           
00333 }
00334 
00335 Eigen::Matrix4d KintonOdomAlgNode::getTransform(const tf::StampedTransform& transform)
00336 {
00337 
00338   double roll,pitch,yaw;
00339   tf::Quaternion q =  transform.getRotation();
00340   tf::Matrix3x3(q).getRPY(roll,pitch,yaw); 
00341 
00342   Eigen::Matrix3d Rot;
00343   Rot = Eigen::AngleAxisd(yaw, Eigen::Vector3d::UnitZ()) \
00344       * Eigen::AngleAxisd(pitch, Eigen::Vector3d::UnitY()) \
00345       * Eigen::AngleAxisd(roll, Eigen::Vector3d::UnitX());
00346   Eigen::Matrix4d T = Eigen::Matrix4d::Zero();
00347 
00348   T.block(0,0,3,3) = Rot;
00349   T(0,3) = transform.getOrigin().x();
00350   T(1,3) = transform.getOrigin().y();
00351   T(2,3) = transform.getOrigin().z();
00352   T(3,3) = 1.0;  
00353 
00354   //ROS_INFO("x: %f y: %f z: %f roll: %f, pitch: %f, yaw: %f",transform.getOrigin().x(),transform.getOrigin().y(),transform.getOrigin().z(),roll,pitch,yaw);
00355 
00356   return T;
00357 }
00358 
00359 void KintonOdomAlgNode::node_config_update(Config &config, uint32_t level)
00360 {
00361   this->alg_.lock();
00362 
00363   this->alg_.unlock();
00364 }
00365 
00366 void KintonOdomAlgNode::addNodeDiagnostics(void)
00367 {
00368 }
00369 
00370 /* main function */
00371 int main(int argc,char *argv[])
00372 {
00373   return algorithm_base::main<KintonOdomAlgNode>(argc, argv, "kinton_odom_alg_node");
00374 }


kinton_odom
Author(s): asantamaria
autogenerated on Fri Dec 6 2013 21:55:13