sensors_2_link_alg_node.cpp
Go to the documentation of this file.
00001 #include "sensors_2_link_alg_node.h"
00002 
00003 Sensors2LinkAlgNode::Sensors2LinkAlgNode(void) :
00004 algorithm_base::IriBaseAlgorithm<Sensors2LinkAlgorithm>()
00005 {
00006   //init class attributes if necessary
00007   //this->loop_rate_ = 2;//in [Hz]
00008   
00009   // [init publishers]
00010   
00011   // [init subscribers]
00012   this->scan_subscriber_ = this->public_node_handle_.subscribe("scan", 100, &Sensors2LinkAlgNode::scan_callback, this);
00013   this->odom_relative_subscriber_ = this->public_node_handle_.subscribe("odom_relative", 100, &Sensors2LinkAlgNode::odom_relative_callback, this);
00014   this->cmd_vel_subscriber_ = this->public_node_handle_.subscribe("cmd_vel", 100, &Sensors2LinkAlgNode::cmd_vel_callback, this);
00015   
00016   // [init services]
00017   this->get_link_server_ = this->public_node_handle_.advertiseService("get_link", &Sensors2LinkAlgNode::get_linkCallback, this);
00018   
00019   // [init clients]
00020   get_relative_pose_client_ = this->public_node_handle_.serviceClient<iri_laser_icp::GetRelativePose>("get_relative_pose");
00021   
00022   // [init action servers]
00023   
00024   // [init action clients]
00025   
00026   // init variables
00027   odom_rel_       = MatrixXd::Zero(3,1);                              
00028   odom_rel_cov_   = MatrixXd::Zero(3,3);                              
00029   Jp              = MatrixXd::Identity(3,3);                             
00030   Jd              = MatrixXd::Identity(3,3);                             
00031   fusion_ready_   = false;                              
00032   new_laser_scan_ = false;                              
00033   prev_seq        = 0;                             
00034 }
00035 
00036 Sensors2LinkAlgNode::~Sensors2LinkAlgNode(void)
00037 {
00038   // [free dynamic memory]
00039 }
00040 
00041 void Sensors2LinkAlgNode::mainNodeThread(void)
00042 {
00043   // [fill msg structures]
00044   
00045   // [fill srv structure and make request to the server]
00046 
00047   // [fill action structure and make request to the action server]
00048 
00049   // [publish messages]
00050 }
00051 
00052 /*  [subscriber callbacks] */
00053 void Sensors2LinkAlgNode::scan_callback(const sensor_msgs::LaserScan::ConstPtr& msg)
00054 {
00055   //ROS_INFO("SENSORS 2 LINK: New laser scan received! time = %f", msg->header.stamp.toSec());
00056 
00057   // LOAD THE LASER SCAN
00058   last_laser_scan_ = (*msg);
00059   new_laser_scan_ = true;
00060 
00061   // ADD FIRST SCAN DIRECTLY TO laser_scan_buffer_
00062   if (laser_scan_buffer_.empty())
00063   {
00064     laser_scan_buffer_.push_back(*msg);
00065     new_laser_scan_ = false; // avoid self pose odometry
00066   }
00067 }
00068 
00069 void Sensors2LinkAlgNode::odom_relative_callback(const nav_msgs::Odometry::ConstPtr& msg)
00070 {
00071   if (prev_seq + 1 < msg->header.seq)
00072     ROS_WARN("SENSORS 2 LINK: Any odom relative lost! prev_seq = %i current_seq = %i", prev_seq, msg->header.seq);
00073 
00074   prev_seq = msg->header.seq;
00075 
00076   Q = MatrixXd::Zero(3,3);
00077   d_local = MatrixXd::Zero(3,1);
00078 
00079   // stopped?
00080   if (!stopped_since_last_odom)
00081   {
00082     // Odometry
00083     d_local = pose_2_vector(msg->pose.pose);
00084 
00085     // Odometry noise
00086     Q = covariance_2_matrix(msg->pose);
00087   }
00088   else
00089     ROS_DEBUG("SENSORS 2 LINK: Zero motion relative odometry");
00090 
00091   // if now is stopped, update the boolean
00092   if (currently_stopped)
00093     stopped_since_last_odom = true;
00094   
00095   // accumulate odometry
00096   // TIME
00097   odom_rel_time_ = msg->header.stamp;
00098 
00099   // COVARIANCE PROPAGATION
00100   // Reference Point Jacobian (previous orientation)
00101   Jp(0,2) =-sin(odom_rel_(2)) * d_local(0) - cos(odom_rel_(2)) * d_local(1);
00102   Jp(1,2) = cos(odom_rel_(2)) * d_local(0) - sin(odom_rel_(2)) * d_local(1);
00103 
00104   // Displacement Jacobian
00105   Jd = rotation_matrix(odom_rel_(2));
00106 
00107   // Covariance propagation
00108   odom_rel_cov_ = Jp * odom_rel_cov_ * Jp.transpose() + Jd * Q * Jd.transpose();
00109 
00110   // POSE
00111   odom_rel_ += rotation_matrix(odom_rel_(2)) * d_local;
00112 
00113   // ADD IN THE BUFFER
00114   // reserve space if needed
00115   if (odom_rel_buffer_.size() == odom_rel_buffer_.capacity())
00116   {
00117     odom_rel_time_buffer_.reserve(int(odom_rel_time_buffer_.size()) + 1000);
00118     odom_rel_cov_buffer_.reserve(int(odom_rel_cov_buffer_.size()) + 1000);
00119     odom_rel_buffer_.reserve(int(odom_rel_buffer_.size()) + 1000);
00120   }
00121   odom_rel_time_buffer_.push_back(odom_rel_time_);
00122   odom_rel_cov_buffer_.push_back(odom_rel_cov_);
00123   odom_rel_buffer_.push_back(odom_rel_);
00124 
00125   
00126   // ODOMETRY FUSION ISSUES
00127 
00128   // OFFLINE MODE
00129   if (!online_mode && odom_rel_buffer_.size() > 1 && new_laser_scan_ && last_laser_scan_.header.stamp < msg->header.stamp)
00130   {
00131     // reserve space if needed
00132     if (odom_buffer_.size() == odom_buffer_.capacity())
00133       odom_buffer_.reserve(int(odom_buffer_.size()) + 1000);
00134 
00135     // ODOMETRY FUSION (LASER & ODOMETRY_RELATIVE)
00136     geometry_msgs::PoseWithCovarianceStamped new_odometry = odometry_fusion(last_laser_scan_, odom_rel_buffer_.size() - 1);
00137     odom_buffer_.push_back(new_odometry);
00138     new_laser_scan_ = false;
00139 
00140     //ROS_INFO("SENSORS 2 LINK: New precomputed odometry stored!");
00141   }
00142 
00143   // ONLINE MODE
00144   else
00145   {
00146     if (odom_rel_buffer_.size() > 1 && new_laser_scan_ && last_laser_scan_.header.stamp < msg->header.stamp)
00147     {
00148       fusion_ready_ = true;
00149       new_laser_scan_ = false;
00150       ready_laser_scan_ = last_laser_scan_;
00151       ready_odom_id_ = odom_rel_buffer_.size() - 1;
00152     }
00153   }
00154 }
00155 
00156 void Sensors2LinkAlgNode::cmd_vel_callback(const geometry_msgs::Twist::ConstPtr& msg)
00157 {
00158   currently_stopped = (msg->linear.x == 0 && msg->linear.y == 0 && msg->linear.z == 0 && msg->angular.x == 0 && msg->angular.y == 0 && msg->angular.z == 0);
00159 
00160   if (stopped_since_last_odom)
00161     stopped_since_last_odom = currently_stopped;
00162 }
00163 
00164 /*  [service callbacks] */
00165 bool Sensors2LinkAlgNode::get_linkCallback(iri_poseslam::GetLink::Request &req, iri_poseslam::GetLink::Response &res)
00166 {
00167   //ROS_INFO("SENSORS 2 LINK: New GetLink Request Received!");
00168 
00169   res.success = false;
00170   res.end = false;
00171 
00172   // FIRST CALLBACK (ask for first laser scan header)
00173   if (req.current_step == 0 && req.with_step == 0)
00174   {
00175     if (!laser_scan_buffer_.empty())
00176     {
00177       // give the first laser scan
00178       res.odom.header = laser_scan_buffer_.front().header;
00179       res.success = true;
00180 
00181       ROS_INFO("SENSORS 2 LINK: first laser scan header given");
00182     }
00183   }
00184 
00185   // NORMAL CALLBACK
00186   else
00187   {
00188     // ODOMETRY LINK
00189     if (req.current_step < req.with_step)
00190     {
00191       // OFFLINE MODE
00192       if (!online_mode)
00193         res = offline_odometry();
00194       
00195       // ONLINE MODE
00196       else
00197         res = online_odometry();
00198     }
00199 
00200     // LOOP CLOSURE LINK
00201     else
00202     { 
00203       if (req.current_step != laser_scan_buffer_.size() - 1)
00204         ROS_WARN("SENSORS 2 LINK: current_scan is not last_scan in LOOP CLOSURE");
00205         
00206       get_relative_pose_srv_.request.scan_ref = laser_scan_buffer_.at(req.with_step);
00207       get_relative_pose_srv_.request.scan_sens = laser_scan_buffer_.at(req.current_step);
00208       
00209       Vector3d prior_d = pose_2_vector(get_relative_pose_srv_.response.pose_rel.pose.pose);
00210       base_2_laser_frame(prior_d);
00211       get_relative_pose_srv_.request.prior_d = vector_2_pose(prior_d);
00212 
00213       // call ICP
00214       if (get_relative_pose_client_.call(get_relative_pose_srv_))
00215       {
00216         if (get_relative_pose_srv_.response.success)
00217         {
00218           Vector3d link_ICP = pose_2_vector(get_relative_pose_srv_.response.pose_rel.pose.pose);
00219           Matrix3d link_ICP_cov = covariance_2_matrix(get_relative_pose_srv_.response.pose_rel.pose);
00220           
00221           // CHANGE FRAME TO BASE FOOTPRINT
00222           laser_2_base_frame(link_ICP, link_ICP_cov);
00223 
00224           // COVARIANCE CORRECTION
00225           link_ICP_cov = link_ICP_cov * ICP_covariance_correction_factor;
00226 
00227           res.odom.header = get_relative_pose_srv_.request.scan_sens.header;
00228           res.odom.pose = eigen_2_posewithcovariance(link_ICP, link_ICP_cov);
00229           
00230           res.success = true;
00231           //ROS_INFO("SENSORS 2 LINK: ICP in LC prior = %f, %f, %f", req.prior_d.position.x, req.prior_d.position.y, tf::getYaw(req.prior_d.orientation));
00232           //ROS_INFO("SENSORS 2 LINK: ICP in LC result = %f, %f, %f - seq: %i - %i", res.odom.pose.pose.position.x, res.odom.pose.pose.position.y, tf::getYaw(res.odom.pose.pose.orientation), laser_scan_buffer_.at(req.with_step).header.seq, laser_scan_buffer_.at(req.current_step).header.seq);
00233           //ROS_INFO("SENSORS 2 LINK: ICP covariance:");
00234           //ROS_INFO_STREAM(link_ICP_cov);
00235         }
00236         else
00237         {
00238           ROS_WARN("SENSORS 2 LINK: ICP didn't found a match in loop closure");
00239           res.success = false;
00240         }
00241       }
00242       else
00243       {
00244         ROS_ERROR("SENSORS 2 LINK: ICP communication failed in loop closure");
00245         res.success = false;
00246       }
00247     }
00248   }
00249 
00250   return true;
00251 }
00252 
00253 /*  [action callbacks] */
00254 
00255 /*  [action requests] */
00256 
00257 void Sensors2LinkAlgNode::node_config_update(Config &config, uint32_t level)
00258 {
00259   this->alg_.lock();
00260 
00261   stopped_since_last_odom = config.cmd_vel_available;
00262   currently_stopped = config.cmd_vel_available;
00263   online_mode = config.online_mode;
00264   d_base_2_laser(0) = config.dx_base_2_laser;
00265   d_base_2_laser(1) = config.dy_base_2_laser;
00266   d_base_2_laser(2) = config.dth_base_2_laser;
00267   ICP_covariance_correction_factor = config.ICP_covariance_correction_factor;
00268   
00269   ROS_WARN("SENSORS 2 LINK: Config updated");
00270 
00271   this->alg_.unlock();
00272 }
00273 
00274 void Sensors2LinkAlgNode::addNodeDiagnostics(void)
00275 {
00276 }
00277 
00278 geometry_msgs::PoseWithCovarianceStamped Sensors2LinkAlgNode::odometry_fusion(const sensor_msgs::LaserScan &laser_scan, const int &odom_rel_idx)
00279 {
00280   Vector3d odom, odom_fused, odom_ICP;
00281   Matrix3d odom_cov, odom_fused_cov, odom_ICP_cov;
00282   geometry_msgs::PoseWithCovarianceStamped fused_odom;
00283   
00284   // RELATIVE ODOMETRY INTERPOLATION
00285   std::pair<Vector3d, Matrix3d> int_odom = interpolate_odom_rel(odom_rel_idx, laser_scan.header.stamp);
00286 
00287   Vector3d int_odom_rel = int_odom.first;
00288   Matrix3d int_odom_rel_cov = int_odom.second;
00289 
00290   // LASER SCANS ICP
00291   get_relative_pose_srv_.request.scan_sens = laser_scan;  // next laser scan
00292   get_relative_pose_srv_.request.scan_ref = laser_scan_buffer_.back(); // current laser scan
00293   
00294   base_2_laser_frame(int_odom_rel);
00295   get_relative_pose_srv_.request.prior_d = vector_2_pose(int_odom_rel);
00296 
00297   // call ICP
00298   if (get_relative_pose_client_.call(get_relative_pose_srv_))
00299   {
00300     if (get_relative_pose_srv_.response.success)
00301     {
00302       ROS_DEBUG("SENSORS 2 LINK: ICP in odometry success!");
00303       odom_ICP = pose_2_vector(get_relative_pose_srv_.response.pose_rel.pose.pose);
00304       odom_ICP_cov = covariance_2_matrix(get_relative_pose_srv_.response.pose_rel.pose);
00305 
00306       // CHANGE FRAME TO BASE FOOTPRINT
00307       laser_2_base_frame(odom_ICP, odom_ICP_cov);
00308       
00309       // COVARIANCE CORRECTION
00310       odom_ICP_cov = odom_ICP_cov * ICP_covariance_correction_factor;
00311       
00312       //ROS_INFO("SENSORS 2 LINK: ICP in odometry prior = %f, %f, %f", get_relative_pose_srv_.request.prior_d.position.x, get_relative_pose_srv_.request.prior_d.position.y, tf::getYaw(get_relative_pose_srv_.request.prior_d.orientation));
00313       //ROS_INFO("SENSORS 2 LINK: ICP in odometry result = %f, %f, %f", get_relative_pose_srv_.response.pose_rel.pose.pose.position.x, get_relative_pose_srv_.response.pose_rel.pose.pose.position.y, tf::getYaw(get_relative_pose_srv_.response.pose_rel.pose.pose.orientation));
00314 
00315       // BEST ODOMETRY ELECTION
00316       // Motion zero
00317       if (int_odom_rel_cov.isZero())
00318       {
00319         //ROS_INFO("SENSORS 2 LINK: Zero motion odometry");
00320         odom_cov = int_odom_rel_cov;
00321         odom = int_odom_rel;
00322       }
00323       else
00324       {
00325         // // FUSION
00326         // // covariance
00327         // odom_fused_cov = (int_odom_rel_cov.inverse() + odom_ICP_cov.inverse()).inverse();
00328         // // mean 
00329         // odom_fused = odom_fused_cov * (int_odom_rel_cov.inverse() * int_odom_rel + odom_ICP_cov.inverse() * odom_ICP);
00330         
00331         // Best is interpolated odom
00332         if (int_odom_rel_cov.trace() < odom_ICP_cov.trace())
00333         {
00334           odom = int_odom_rel;
00335           odom_cov = int_odom_rel_cov;
00336         }
00337         // Best is ICP odom
00338         else
00339         {
00340           odom = odom_ICP;
00341           odom_cov = odom_ICP_cov;
00342         }
00343         
00344         //ROS_INFO("odom_ICP_cov:");
00345         //ROS_INFO_STREAM(odom_ICP_cov);
00346         //ROS_INFO("int_odom_rel_cov:");
00347         //ROS_INFO_STREAM(int_odom_rel_cov);
00348         //ROS_INFO("odom_cov:");
00349         //ROS_INFO_STREAM(odom_cov);
00350         //ROS_INFO("SENSORS 2 LINK: Fused odometry %f %f %f", odom(0), odom(1), odom(2));
00351       }
00352     }
00353     else
00354     {
00355       ROS_WARN("SENSORS 2 LINK: ICP didn't found a match in odometry fusion");
00356       odom_cov = int_odom_rel_cov;
00357       odom = int_odom_rel;
00358     }
00359   }
00360   else
00361   {
00362     ROS_WARN("SENSORS 2 LINK: ICP communication failed in odometry fusion");
00363     odom_cov = int_odom_rel_cov;
00364     odom = int_odom_rel;
00365   }
00366 
00367   // reserve space if needed
00368   if (laser_scan_buffer_.size() == laser_scan_buffer_.capacity())
00369     laser_scan_buffer_.reserve(int(laser_scan_buffer_.size()) + 1000);
00370   
00371   // Add laser scan in the laser_scan_buffer_
00372   laser_scan_buffer_.push_back(laser_scan);
00373   
00374   // TRANSLATING to a PoseWithCovariancestamped
00375   fused_odom.header = laser_scan.header;
00376   fused_odom.pose = eigen_2_posewithcovariance(odom, odom_cov);
00377   
00378   return fused_odom;
00379 }
00380 
00381 Matrix3d Sensors2LinkAlgNode::rotation_matrix(const double &alpha) const
00382 {
00383   Matrix3d rot = MatrixXd::Identity(3,3);
00384   
00385   rot(0,0) = cos(alpha);
00386   rot(0,1) = -sin(alpha);
00387   rot(1,0) = sin(alpha);
00388   rot(1,1) = cos(alpha);
00389 
00390   return rot;
00391 }
00392 
00393 Matrix3d Sensors2LinkAlgNode::covariance_2_matrix(const geometry_msgs::PoseWithCovariance &pose) const
00394 {
00395   Matrix3d cov;
00396   
00397   cov(0,0) = pose.covariance[0];
00398   cov(0,1) = pose.covariance[1];
00399   cov(0,2) = pose.covariance[5];
00400   cov(1,0) = pose.covariance[6];
00401   cov(1,1) = pose.covariance[7];
00402   cov(1,2) = pose.covariance[11];
00403   cov(2,0) = pose.covariance[30];
00404   cov(2,1) = pose.covariance[31];
00405   cov(2,2) = pose.covariance[35];
00406 
00407   return cov;
00408 }
00409 
00410 Vector3d Sensors2LinkAlgNode::pose_2_vector(const geometry_msgs::Pose &pose) const
00411 {
00412   Vector3d p;
00413   
00414   p(0) = pose.position.x;
00415   p(1) = pose.position.y;
00416   p(2) = tf::getYaw(pose.orientation);
00417   
00418   return p;
00419 }
00420 
00421 geometry_msgs::PoseWithCovariance Sensors2LinkAlgNode::eigen_2_posewithcovariance(const Vector3d &p, const Matrix3d &cov) const
00422 {
00423   geometry_msgs::PoseWithCovariance pose;
00424 
00425   pose.pose = vector_2_pose(p);
00426   
00427   pose.covariance[0]  = cov(0,0);
00428   pose.covariance[1]  = cov(0,1);
00429   pose.covariance[5]  = cov(0,2);
00430   pose.covariance[6]  = cov(1,0);
00431   pose.covariance[7]  = cov(1,1);
00432   pose.covariance[11] = cov(1,2);
00433   pose.covariance[30] = cov(2,0);
00434   pose.covariance[31] = cov(2,1);
00435   pose.covariance[35] = cov(2,2);
00436   
00437   return pose;
00438 }
00439 
00440 geometry_msgs::Pose Sensors2LinkAlgNode::vector_2_pose(const Vector3d &p) const
00441 {
00442   geometry_msgs::Pose pose;
00443 
00444   pose.position.x = p(0);
00445   pose.position.y = p(1);
00446   pose.position.z = 0;
00447   pose.orientation = tf::createQuaternionMsgFromYaw(p(2));
00448   
00449   return pose;
00450 }
00451 
00452 iri_poseslam::GetLink::Response Sensors2LinkAlgNode::offline_odometry()
00453 {
00454   iri_poseslam::GetLink::Response result;
00455  
00456   // Return the pre-computed odometry
00457   if (!odom_buffer_.empty())
00458   {
00459     result.odom = odom_buffer_.front();
00460     result.success = true;
00461     result.end = false;
00462 
00463     // Erase from the buffer
00464     odom_buffer_.erase(odom_buffer_.begin());
00465   }
00466   else
00467   {
00468     ROS_DEBUG("SENSORS 2 LINK: There is no more precomputed odometries");
00469     result.success = false;
00470     result.end = true;
00471   }
00472   
00473   return result;
00474 }
00475 
00476 iri_poseslam::GetLink::Response Sensors2LinkAlgNode::online_odometry()
00477 {
00478   iri_poseslam::GetLink::Response result;
00479   
00480   if (fusion_ready_)
00481   {
00482     // Call sensor fusion
00483     result.odom = odometry_fusion(ready_laser_scan_, ready_odom_id_);
00484     result.success = true;
00485     result.end = false;
00486     fusion_ready_ = false;
00487   }
00488   else
00489   {
00490     ROS_DEBUG("SENSORS 2 LINK: There is not enough sensor data");
00491     result.success = false;
00492     result.end = true;
00493   }
00494   
00495   return result;
00496 }
00497 
00498 std::pair<Vector3d, Matrix3d> Sensors2LinkAlgNode::interpolate_odom_rel(const int &odom_rel_idx, const ros::Time scan_stamp)
00499 {
00500   Vector3d pre_odom_rel  = odom_rel_buffer_.at(odom_rel_idx - 1);
00501   Vector3d post_odom_rel = odom_rel_buffer_.at(odom_rel_idx);
00502   Matrix3d pre_odom_rel_cov  = odom_rel_cov_buffer_.at(odom_rel_idx - 1);
00503   Matrix3d post_odom_rel_cov = odom_rel_cov_buffer_.at(odom_rel_idx);
00504   ros::Time pre_odom_rel_time  = odom_rel_time_buffer_.at(odom_rel_idx - 1);
00505   ros::Time post_odom_rel_time = odom_rel_time_buffer_.at(odom_rel_idx);
00506 
00507   // Interpolation
00508   double alpha = (scan_stamp - pre_odom_rel_time).toSec() / (post_odom_rel_time - pre_odom_rel_time).toSec();
00509   alpha = 1; // NOT INTERPOLE: posterior odometry message
00510   //alpha = 0; // NOT INTERPOLE: previous odometry message
00511   VectorXd int_odom_rel = (1 - alpha) * pre_odom_rel + alpha * post_odom_rel;
00512   MatrixXd int_odom_rel_cov = (1 - alpha) * pre_odom_rel_cov + alpha * post_odom_rel_cov;
00513 
00514   // Update relative odometries buffers
00515   MatrixXd rot = rotation_matrix(int_odom_rel(2));
00516   VectorXd rest_odom_rel = rot * (post_odom_rel - int_odom_rel);
00517 
00518   rot = rotation_matrix(-int_odom_rel(2));
00519   MatrixXd rest_odom_rel_cov = rot * (post_odom_rel_cov - int_odom_rel_cov) * rot.transpose();
00520 
00521   odom_rel_buffer_.clear();
00522   odom_rel_cov_buffer_.clear();
00523   odom_rel_time_buffer_.clear();
00524 
00525   odom_rel_buffer_.push_back(rest_odom_rel);
00526   odom_rel_cov_buffer_.push_back(rest_odom_rel_cov);
00527   odom_rel_time_buffer_.push_back(pre_odom_rel_time + (post_odom_rel_time - pre_odom_rel_time) * alpha);
00528 
00529   // initialize odom relative
00530   odom_rel_ = rest_odom_rel; //MatrixXd::Zero(3,1);
00531   odom_rel_cov_ = rest_odom_rel_cov; //MatrixXd::Zero(3,3);
00532 
00533   std::pair<Vector3d, Matrix3d> result;
00534   result.first = int_odom_rel;
00535   result.second = int_odom_rel_cov;
00536 
00537   return result;
00538 }
00539 
00540 void Sensors2LinkAlgNode::base_2_laser_frame(Vector3d &prior_d)
00541 {
00542   Matrix3d rot_frame = rotation_matrix(-d_base_2_laser(2));
00543   Matrix3d rot_d = rotation_matrix(prior_d(2));
00544   
00545   prior_d = rot_d * rot_frame * d_base_2_laser + rot_frame * prior_d - rot_frame * d_base_2_laser;
00546 
00547 }
00548 
00549 void Sensors2LinkAlgNode::laser_2_base_frame(Vector3d &odom_ICP, Matrix3d &odom_ICP_cov)
00550 {
00551   Matrix3d rot_frame = rotation_matrix(d_base_2_laser(2));
00552   Matrix3d rot_d = rotation_matrix(odom_ICP(2));
00553   odom_ICP = d_base_2_laser + rot_frame * odom_ICP - rot_d * d_base_2_laser;
00554 
00555   Matrix3d J = rotation_matrix(d_base_2_laser(2));
00556   odom_ICP_cov = J * odom_ICP_cov * J.transpose();
00557 }
00558 
00559 /* main function */
00560 int main(int argc,char *argv[])
00561 {
00562   return algorithm_base::main<Sensors2LinkAlgNode>(argc, argv, "sensors_2_link_node");
00563 }


iri_poseslam
Author(s): Joan Vallvé
autogenerated on Fri Dec 6 2013 21:21:14