trajectory_3Dscans_2_pointcloud_alg_node.cpp
Go to the documentation of this file.
00001 #include "trajectory_3Dscans_2_pointcloud_alg_node.h"
00002 
00003 Trajectory3DScans2PointcloudAlgNode::Trajectory3DScans2PointcloudAlgNode(void) :
00004   algorithm_base::IriBaseAlgorithm<Trajectory3DScans2PointcloudAlgorithm>()
00005 {
00006   //init class attributes if necessary
00007   emptyPointCloud_ = true;
00008   started_ = false;
00009 
00010   //this->loop_rate_ = 2;//in [Hz]
00011 
00012   // [init publishers]
00013   this->slices3D_pointcloud_publisher_ = this->public_node_handle_.advertise<sensor_msgs::PointCloud2>("slices3D_pointcloud", 10);
00014 
00015   // [init subscribers]
00016   this->slices3D_subscriber_ = this->public_node_handle_.subscribe("slices3D", 1000, &Trajectory3DScans2PointcloudAlgNode::slices3D_callback, this);
00017   this->trajectory_subscriber_ = this->public_node_handle_.subscribe("trajectory", 1000, &Trajectory3DScans2PointcloudAlgNode::trajectory_callback, this);
00018   
00019   // [init services]
00020   
00021   // [init clients]
00022   
00023   // [init action servers]
00024   
00025   // [init action clients]
00026 }
00027 
00028 Trajectory3DScans2PointcloudAlgNode::~Trajectory3DScans2PointcloudAlgNode(void)
00029 {
00030   // [free dynamic memory]
00031 }
00032 
00033 void Trajectory3DScans2PointcloudAlgNode::mainNodeThread(void)
00034 {
00035   // [fill msg structures]
00036   
00037   // [fill srv structure and make request to the server]
00038   
00039   // [fill action structure and make request to the action server]
00040 
00041   // [publish messages]
00042 }
00043 
00044 /*  [subscriber callbacks] */
00045 void Trajectory3DScans2PointcloudAlgNode::slices3D_callback(const sensor_msgs::PointCloud2::ConstPtr& msg)
00046 {  
00047   //ROS_INFO("SLICES 2 PC New slice Message Received"); 
00048   //ROS_INFO_STREAM(msg->header.covariance);
00049   
00050   // reserve space if needed
00051   if (slice_buffer_.size() == slice_buffer_.capacity())
00052     slice_buffer_.reserve(slice_buffer_.size() + 1000);
00053 
00054   if (started_)
00055     slice_buffer_.push_back(*msg);
00056 }
00057 
00058 void Trajectory3DScans2PointcloudAlgNode::trajectory_callback(const iri_poseslam::Trajectory::ConstPtr& msg)
00059 { 
00060   //ROS_INFO("SLICES 2 PC: New Trajectory Message Received");
00061   //ROS_INFO_STREAM(*msg);
00062   
00063   // RECOMPUTE PointCloud if have been 2 trajectory messages
00064   if (started_)
00065     recompute_PointCloud_msg(*msg);
00066   else
00067     started_ = true;
00068 
00069   slices3D_pointcloud_publisher_.publish(this->PointCloud_msg_);
00070   ROS_DEBUG("SLICES 2 PC: PointCloud_msg_ published! size = %u", PointCloud_msg_.height * PointCloud_msg_.width);
00071 }
00072 
00073 /*  [service callbacks] */
00074 
00075 /*  [action callbacks] */
00076 
00077 /*  [action requests] */
00078 
00079 void Trajectory3DScans2PointcloudAlgNode::node_config_update(Config &config, uint32_t level)
00080 {
00081   this->alg_.lock();
00082   
00083   T_laser_frame = transformation_matrix(config.dx_base_2_h3d, config.dy_base_2_h3d, config.dz_base_2_h3d, config.dth_base_2_h3d);
00084 
00085   ROS_WARN("SLICES 2 PC: Config updated");
00086 
00087   this->alg_.unlock();
00088 }
00089 
00090 void Trajectory3DScans2PointcloudAlgNode::addNodeDiagnostics(void)
00091 {
00092 }
00093 
00094 /* main function */
00095 int main(int argc,char *argv[])
00096 {
00097   return algorithm_base::main<Trajectory3DScans2PointcloudAlgNode>(argc, argv, "trajectory_3Dscans_2_pointcloud_alg_node");
00098 }
00099 
00100 void Trajectory3DScans2PointcloudAlgNode::recompute_PointCloud_msg(const iri_poseslam::Trajectory& trajectory)
00101 {
00102   // AUX VARIABLES
00103   geometry_msgs::Pose slice_pose;
00104   bool LoopClosed = false;
00105   if (trajectory.loops.size() > 0)
00106     LoopClosed = (trajectory.loops.back() == trajectory.states_2_steps.back() && trajectory.steps_2_states.back() != -1);
00107   
00108   // LOOP CLOSED: Recompute all previous slices
00109   if (LoopClosed) 
00110   {
00111     clear_PointCloud_msg();
00112     
00113     //ROS_INFO("SLICES 2 PC: Recompute all %u slices of the trajectory with %u steps", uint(trajectory_slice_buffer_.size()), uint(trajectory.poses.size()));
00114     
00115     for (uint i = 0; i < trajectory_slice_buffer_.size(); i++)
00116     {
00117       slice_pose = interpole_slice_pose(i, trajectory);
00118       add_to_PointCloud_msg(transform_point_cloud(trajectory_slice_buffer_.at(i), slice_pose));
00119     }
00120     ROS_INFO("SLICES 2 PC: Pointcloud recomputed after a Loop Closure");
00121   }
00122   
00123   // ADD NEW SLICES
00124   while (slice_buffer_.size() > 0 && slice_buffer_.front().header.stamp < trajectory.poses.back().header.stamp)
00125   {
00126     //ROS_INFO("SLICES 2 PC: Add new slices: slice_buffer_.size = %u", uint(slice_buffer_.size()));
00127     
00128     // ADD to trajectory_slice_buffer_ and interpolation index and factor
00129     trajectory_slice_buffer_.push_back(slice_buffer_.front());
00130     interpolation_buffer_.push_back(search_interpolation(slice_buffer_.front(), trajectory));
00131 
00132     // ADD to the PointCloud
00133     slice_pose = interpole_slice_pose(trajectory_slice_buffer_.size() - 1, trajectory);
00134     add_to_PointCloud_msg(transform_point_cloud(slice_buffer_.front(), slice_pose));
00135     
00136     // ERASE from the slice_buffer_
00137     slice_buffer_.erase(slice_buffer_.begin());
00138   }
00139   //ROS_INFO("SLICES 2 PC: New slices added: slice_buffer_.size = %u", uint(slice_buffer_.size()));
00140 }
00141 
00142 sensor_msgs::PointCloud2 Trajectory3DScans2PointcloudAlgNode::transform_point_cloud(const sensor_msgs::PointCloud2& pcloud, const geometry_msgs::Pose& pose) 
00143 {
00144   sensor_msgs::PointCloud2 transformed_pcloud;
00145   
00146   Matrix4f T_pose = transformation_matrix(pose.position.x, pose.position.y, pose.position.z, tf::getYaw(pose.orientation));
00147   
00148   pcl_ros::transformPointCloud(T_pose * T_laser_frame, pcloud, transformed_pcloud);
00149 
00150   return transformed_pcloud;
00151 }
00152 
00153 void Trajectory3DScans2PointcloudAlgNode::add_to_PointCloud_msg(const sensor_msgs::PointCloud2& newPointCloud)
00154 {
00155   //ROS_INFO("ADD to pointcloud");
00156   pcl::PointCloud<pcl::PointXYZ> newcloud;
00157   
00158   pcl::PointCloud<pcl::PointXYZ>::Ptr cloud2 (new pcl::PointCloud<pcl::PointXYZ>);
00159   pcl::fromROSMsg(newPointCloud, *cloud2);
00160   
00161   if (emptyPointCloud_)
00162   {
00163     newcloud = *cloud2;
00164     emptyPointCloud_ = false;
00165     //ROS_INFO("added empty");
00166   
00167   }
00168   else
00169   {
00170     pcl::PointCloud<pcl::PointXYZ>::Ptr cloud1 (new pcl::PointCloud<pcl::PointXYZ>);
00171     pcl::fromROSMsg(PointCloud_msg_, *cloud1);
00172     
00173     newcloud = *cloud1 + *cloud2;
00174   }
00175   
00176   pcl::toROSMsg(newcloud, PointCloud_msg_);
00177   PointCloud_msg_.header.frame_id = "/map";
00178 }
00179 
00180 void Trajectory3DScans2PointcloudAlgNode::clear_PointCloud_msg()
00181 {
00182   pcl::PointCloud<pcl::PointXYZ> cloud; //::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>);
00183   pcl::fromROSMsg(PointCloud_msg_, cloud);
00184   
00185   cloud.clear();
00186   
00187   pcl::toROSMsg(cloud, PointCloud_msg_);
00188 }
00189 
00190 geometry_msgs::Pose Trajectory3DScans2PointcloudAlgNode::interpole_slice_pose(const uint& id, const iri_poseslam::Trajectory& trajectory) const
00191 {
00192   // GET THE INTERPOLATION INDEX AND FACTOR
00193   uint id_pre  = interpolation_buffer_.at(id).first;
00194   double alpha = interpolation_buffer_.at(id).second;
00195 
00196   // GET THE PRE AND POST POSES
00197   geometry_msgs::Point pre_position  = trajectory.poses.at(id_pre).pose.pose.position;
00198   geometry_msgs::Point post_position = trajectory.poses.at(id_pre + 1).pose.pose.position;
00199   double pre_yaw = tf::getYaw(trajectory.poses.at(id_pre).pose.pose.orientation);
00200   double post_yaw = tf::getYaw(trajectory.poses.at(id_pre + 1).pose.pose.orientation);
00201   double d_yaw = pi_2_pi(post_yaw- pre_yaw);
00202 
00203   // INTERPOLE
00204   geometry_msgs::Pose slice_pose;
00205   slice_pose.position.x = (1 - alpha) * pre_position.x + alpha * post_position.x;
00206   slice_pose.position.y = (1 - alpha) * pre_position.y + alpha * post_position.y;
00207   slice_pose.position.z = (1 - alpha) * pre_position.z + alpha * post_position.z;
00208   slice_pose.orientation = tf::createQuaternionMsgFromYaw(pre_yaw + alpha * d_yaw);
00209   
00210   return slice_pose;
00211 }
00212 
00213 std::pair<uint, double> Trajectory3DScans2PointcloudAlgNode::search_interpolation(const sensor_msgs::PointCloud2& slice, const iri_poseslam::Trajectory& trajectory) const
00214 {
00215   // SEARCH THE INTERPOLATION INDEX
00216   bool found = false;
00217   uint i = 1;
00218   uint id = 0;
00219   while (!found && i < trajectory.poses.size())
00220   {
00221     if (slice.header.stamp < trajectory.poses.at(i).header.stamp)
00222     {
00223       id  = i - 1;
00224       found = true;
00225     }
00226     else
00227       i++;
00228   }
00229 
00230   if (!found)
00231     ROS_ERROR("SLICES 2 PC: Interpolation index not found");
00232 
00233   // COMPUTE THE INTERPOLATION FACTOR
00234   ros::Time pre_time  = trajectory.poses.at(id).header.stamp;
00235   ros::Time post_time = trajectory.poses.at(id + 1).header.stamp;
00236   double alpha = (slice.header.stamp - pre_time).toSec() / (post_time - pre_time).toSec();
00237 
00238   std::pair<uint, double> result(id, alpha);
00239 
00240   return result;
00241 }
00242 
00243 Matrix4f Trajectory3DScans2PointcloudAlgNode::transformation_matrix(const float x, const float y, const float z, const float alpha) const
00244 {
00245   Matrix4f T = MatrixXf::Identity(4,4);
00246 
00247   // Rotation
00248   T(0,0) =  cos(alpha);
00249   T(0,1) = -sin(alpha);
00250   T(1,0) =  sin(alpha);
00251   T(1,1) =  cos(alpha);
00252 
00253   // Translation
00254   T(0,3) = x;
00255   T(1,3) = y;
00256   T(2,3) = z;
00257 
00258   return T;
00259 }
00260 
00261 double Trajectory3DScans2PointcloudAlgNode::pi_2_pi(const double& angle) const
00262 {
00263   return angle - 2 * M_PI * floor((angle + M_PI)/(2 * M_PI));
00264 }


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