00001 #include "trajectory_3Dscans_2_pointcloud_alg_node.h"
00002
00003 Trajectory3DScans2PointcloudAlgNode::Trajectory3DScans2PointcloudAlgNode(void) :
00004 algorithm_base::IriBaseAlgorithm<Trajectory3DScans2PointcloudAlgorithm>()
00005 {
00006
00007 emptyPointCloud_ = true;
00008 started_ = false;
00009
00010
00011
00012
00013 this->slices3D_pointcloud_publisher_ = this->public_node_handle_.advertise<sensor_msgs::PointCloud2>("slices3D_pointcloud", 10);
00014
00015
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
00020
00021
00022
00023
00024
00025
00026 }
00027
00028 Trajectory3DScans2PointcloudAlgNode::~Trajectory3DScans2PointcloudAlgNode(void)
00029 {
00030
00031 }
00032
00033 void Trajectory3DScans2PointcloudAlgNode::mainNodeThread(void)
00034 {
00035
00036
00037
00038
00039
00040
00041
00042 }
00043
00044
00045 void Trajectory3DScans2PointcloudAlgNode::slices3D_callback(const sensor_msgs::PointCloud2::ConstPtr& msg)
00046 {
00047
00048
00049
00050
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
00061
00062
00063
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
00074
00075
00076
00077
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
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
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
00109 if (LoopClosed)
00110 {
00111 clear_PointCloud_msg();
00112
00113
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
00124 while (slice_buffer_.size() > 0 && slice_buffer_.front().header.stamp < trajectory.poses.back().header.stamp)
00125 {
00126
00127
00128
00129 trajectory_slice_buffer_.push_back(slice_buffer_.front());
00130 interpolation_buffer_.push_back(search_interpolation(slice_buffer_.front(), trajectory));
00131
00132
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
00137 slice_buffer_.erase(slice_buffer_.begin());
00138 }
00139
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
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
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;
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
00193 uint id_pre = interpolation_buffer_.at(id).first;
00194 double alpha = interpolation_buffer_.at(id).second;
00195
00196
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
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
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
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
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
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 }