trajectory_scans_2_pointcloud_alg_node.cpp
Go to the documentation of this file.
00001 #include "trajectory_scans_2_pointcloud_alg_node.h"
00002 
00003 TrajectoryScans2PointcloudAlgNode::TrajectoryScans2PointcloudAlgNode(void) :
00004   algorithm_base::IriBaseAlgorithm<TrajectoryScans2PointcloudAlgorithm>()
00005 {
00006   //init class attributes if necessary
00007   emptyPointCloud_ = true;
00008   
00009   //this->loop_rate_ = 2;//in [Hz]
00010 
00011   // [init publishers]
00012   this->laser_pointcloud_publisher_ = this->public_node_handle_.advertise<sensor_msgs::PointCloud2>("laser_pointcloud", 100);
00013   
00014   // [init subscribers]
00015   this->scan_subscriber_ = this->public_node_handle_.subscribe("scan", 1000, &TrajectoryScans2PointcloudAlgNode::scan_callback, this);
00016   this->trajectory_subscriber_ = this->public_node_handle_.subscribe("trajectory", 100, &TrajectoryScans2PointcloudAlgNode::trajectory_callback, this);
00017   
00018   // [init services]
00019   
00020   // [init clients]
00021   
00022   // [init action servers]
00023   
00024   // [init action clients]
00025 }
00026 
00027 TrajectoryScans2PointcloudAlgNode::~TrajectoryScans2PointcloudAlgNode(void)
00028 {
00029   // [free dynamic memory]
00030 }
00031 
00032 void TrajectoryScans2PointcloudAlgNode::mainNodeThread(void)
00033 {
00034   // [fill msg structures]
00035   
00036   // [fill srv structure and make request to the server]
00037   
00038   // [fill action structure and make request to the action server]
00039 
00040   // [publish messages]
00041 }
00042 
00043 /*  [subscriber callbacks] */
00044 void TrajectoryScans2PointcloudAlgNode::scan_callback(const sensor_msgs::LaserScan::ConstPtr& msg)
00045 {  
00046   //ROS_INFO("TR 2 PC New LaserScan Message Received"); 
00047   //ROS_INFO_STREAM(msg->header.covariance);
00048   
00049   // reserve space if needed
00050   if (laser_scan_buffer_.size() == laser_scan_buffer_.capacity())
00051     laser_scan_buffer_.reserve(laser_scan_buffer_.size() + 1000);
00052 
00053   laser_scan_buffer_.push_back(*msg);
00054 }
00055 
00056 void TrajectoryScans2PointcloudAlgNode::trajectory_callback(const iri_poseslam::Trajectory::ConstPtr& msg)
00057 { 
00058   //ROS_INFO("TR 2 PC: New Trajectory Message Received");
00059   //ROS_INFO_STREAM(*msg);
00060   
00061   iri_poseslam::Trajectory new_trajectory = *msg;
00062   
00063   // RECOMPUTE trajectory_laser_scan_buffer_
00064   if (new_trajectory.steps_2_states.back() != -1 || publish_redundant_)
00065   {
00066     //ROS_INFO("TR 2 PC: \n\tRecompute trajectory_laser_scan_buffer_ size = %u \n\t laser_scan_buffer_.size = %u", trajectory_laser_scan_buffer_.size(), laser_scan_buffer_.size());
00067     
00068     bool added = false;
00069     while (!added)
00070     {
00071       if (laser_scan_buffer_.front().header.seq == new_trajectory.poses.back().header.seq)
00072       {
00073         trajectory_laser_scan_buffer_.push_back(laser_scan_buffer_.front());
00074         laser_scan_buffer_.erase(laser_scan_buffer_.begin());
00075         added = true;
00076         //ROS_INFO("TR 2 PC: laser scan added! \n\tnSteps = %i \n\tnStates = %i \n\ttrajectory_laser_scan_buffer_.size = %i", new_trajectory.steps_2_states.size(), new_trajectory.states_2_steps.size(), trajectory_laser_scan_buffer_.size());
00077       }
00078       else if (laser_scan_buffer_.front().header.seq < new_trajectory.poses.back().header.seq)
00079         laser_scan_buffer_.erase(laser_scan_buffer_.begin());
00080       else
00081       {
00082         ROS_ERROR("TR 2 PC: Last trajectory pose laser scan not found!");
00083         sensor_msgs::LaserScan empty_LaserScan;
00084         empty_LaserScan.header = new_trajectory.poses.back().header;
00085         trajectory_laser_scan_buffer_.push_back(empty_LaserScan);
00086         added = true;
00087       }
00088       
00089     }
00090   }
00091   
00092   // RECOMPUTE PointCloud
00093   if (recompute_PointCloud_msg(new_trajectory))
00094   {
00095     // PUBLISH if pointCloud has changed
00096     this->laser_pointcloud_publisher_.publish(this->PointCloud_msg_);
00097     ROS_DEBUG("TR 2 PC: PointCloud_msg_ published! size = %u", PointCloud_msg_.height * PointCloud_msg_.width);
00098   }
00099 }
00100 
00101 /*  [service callbacks] */
00102 
00103 /*  [action callbacks] */
00104 
00105 /*  [action requests] */
00106 
00107 void TrajectoryScans2PointcloudAlgNode::node_config_update(Config &config, uint32_t level)
00108 {
00109   this->alg_.lock();
00110 
00111   T_laser_frame = transformation_matrix(config.dx_base_2_laser, config.dy_base_2_laser, config.dz_base_2_laser, config.dth_base_2_laser);
00112   publish_redundant_ = config.publish_redundant;
00113 
00114   ROS_WARN("TR 2 PC: Config updated");
00115   
00116   this->alg_.unlock();
00117 }
00118 
00119 void TrajectoryScans2PointcloudAlgNode::addNodeDiagnostics(void)
00120 {
00121 }
00122 
00123 /* main function */
00124 int main(int argc,char *argv[])
00125 {
00126   return algorithm_base::main<TrajectoryScans2PointcloudAlgNode>(argc, argv, "trajectory_scans_2_pointcloud_alg_node");
00127 }
00128 
00129 bool TrajectoryScans2PointcloudAlgNode::recompute_PointCloud_msg(const iri_poseslam::Trajectory& trajectory)
00130 {
00131   bool cloud_changed;
00132   bool LoopClosed = false;
00133   if (trajectory.loops.size() > 0)
00134     LoopClosed = (trajectory.loops.back() == trajectory.states_2_steps.back() && trajectory.steps_2_states.back() != -1);
00135   
00136   // LOOP CLOSED: Recompute all scans
00137   if (LoopClosed)
00138   {
00139     clear_PointCloud_msg();
00140     
00141     ROS_DEBUG("TR 2 PC: Loop Closed! Recompute all %u poses of the trajectory with %u laser scans", uint(trajectory.poses.size()), uint(trajectory_laser_scan_buffer_.size()));
00142     
00143     for (uint i = 0; i < trajectory.poses.size(); i++)
00144     {
00145       sensor_msgs::LaserScan laser_scan;
00146 
00147       if (publish_redundant_)
00148         laser_scan = trajectory_laser_scan_buffer_.at(i);
00149       
00150       else if (trajectory.steps_2_states.at(i) != -1)
00151         laser_scan = trajectory_laser_scan_buffer_.at(trajectory.steps_2_states.at(i));
00152       
00153       if (publish_redundant_ || trajectory.steps_2_states.at(i) != -1)
00154       {
00155         if (laser_scan.header.seq != trajectory.poses.at(i).header.seq)
00156           ROS_ERROR("TR 2 PC: headers don't match! step %i", i);
00157 
00158         add_to_PointCloud_msg(laser_scan_to_point_cloud(laser_scan, trajectory.poses.at(i).pose.pose));
00159         cloud_changed = true;
00160       }  
00161     }
00162     //ROS_INFO("TR 2 PC: Loop Closed - nLoops = %i - nStates = %i", trajectory.loops.size(), trajectory.poses.size());
00163   }
00164 
00165   // NOT LOOP: ADD CURRENT SCAN
00166   else if (trajectory.steps_2_states.back() != -1 || publish_redundant_) //NO LOOP CLOSED AND NO REDUNDANT POSE --> Compute last laserscan pointcloud
00167   {
00168     //ROS_INFO("TR 2 PC: New state: %i step %i \ntrajectory.steps_2_states.size() = %i\ntrajectory.poses.size() = %i\nlaser_scan_buffer_.size() = %i", trajectory.steps_2_states.back(), trajectory.states_2_steps.back(), trajectory.steps_2_states.size(), trajectory.poses.size(),laser_scan_buffer_.size());
00169     add_to_PointCloud_msg(laser_scan_to_point_cloud(trajectory_laser_scan_buffer_.back(), trajectory.poses.back().pose.pose));
00170     cloud_changed = true;
00171   }
00172 
00173   return cloud_changed;
00174 }
00175 
00176 sensor_msgs::PointCloud2 TrajectoryScans2PointcloudAlgNode::laser_scan_to_point_cloud(const sensor_msgs::LaserScan& LScan, const geometry_msgs::Pose& pose) 
00177 {
00178   sensor_msgs::PointCloud2 pcloud;
00179   sensor_msgs::PointCloud2 transformed_pcloud;
00180   
00181   laser_projector_.projectLaser(LScan, pcloud, LScan.range_max - 0.0001);
00182   
00183   Matrix4f T_pose = transformation_matrix(pose.position.x, pose.position.y, pose.position.z, tf::getYaw(pose.orientation));
00184   
00185   pcl_ros::transformPointCloud(T_pose * T_laser_frame, pcloud, transformed_pcloud);
00186 
00187   return transformed_pcloud;
00188 }
00189 
00190 void TrajectoryScans2PointcloudAlgNode::add_to_PointCloud_msg(const sensor_msgs::PointCloud2& newPointCloud)
00191 {
00192   //ROS_INFO("ADD to pointcloud");
00193   pcl::PointCloud<pcl::PointXYZ> newcloud;
00194   
00195   pcl::PointCloud<pcl::PointXYZ>::Ptr cloud2 (new pcl::PointCloud<pcl::PointXYZ>);
00196   pcl::fromROSMsg(newPointCloud, *cloud2);
00197   
00198   if (emptyPointCloud_)
00199   {
00200     newcloud = *cloud2;
00201     emptyPointCloud_ = false;
00202   
00203   }
00204   else
00205   {
00206     pcl::PointCloud<pcl::PointXYZ>::Ptr cloud1 (new pcl::PointCloud<pcl::PointXYZ>);
00207     pcl::fromROSMsg(PointCloud_msg_, *cloud1);
00208     
00209     newcloud = *cloud1 + *cloud2;
00210   }
00211   
00212   pcl::toROSMsg(newcloud, PointCloud_msg_);
00213   PointCloud_msg_.header.frame_id = "/map";
00214 }
00215 
00216 void TrajectoryScans2PointcloudAlgNode::clear_PointCloud_msg()
00217 {
00218   pcl::PointCloud<pcl::PointXYZ> cloud;
00219   pcl::fromROSMsg(PointCloud_msg_, cloud);
00220   
00221   cloud.clear();
00222   
00223   pcl::toROSMsg(cloud, PointCloud_msg_);
00224 }
00225 
00226 Matrix4f TrajectoryScans2PointcloudAlgNode::transformation_matrix(const float x, const float y, const float z, const float alpha) const
00227 {
00228   Matrix4f T = MatrixXf::Identity(4,4);
00229 
00230   // Rotation
00231   T(0,0) =  cos(alpha);
00232   T(0,1) = -sin(alpha);
00233   T(1,0) =  sin(alpha);
00234   T(1,1) =  cos(alpha);
00235 
00236   // Translation
00237   T(0,3) = x;
00238   T(1,3) = y;
00239   T(2,3) = z;
00240 
00241   return T;
00242 }


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