Go to the documentation of this file.00001
00034 #include <arpa/inet.h>
00035
00036 #include <multisense_ros/color_laser.h>
00037
00038
00039
00040 namespace {
00041
00042 const uint32_t laser_cloud_step = 16;
00043
00044 }
00045
00046 namespace multisense_ros {
00047
00048 ColorLaser::ColorLaser(
00049 ros::NodeHandle& nh
00050 ):
00051 color_image_(),
00052 camera_info_(),
00053 color_laser_pointcloud_(),
00054 color_laser_publisher_(),
00055 color_image_sub_(),
00056 laser_pointcloud_sub_(),
00057 camera_info_sub_(),
00058 node_handle_(nh),
00059 data_lock_(),
00060 image_channels_(3)
00061 {
00062
00063
00064
00065 color_laser_pointcloud_.is_bigendian = (htonl(1) == 1);
00066 color_laser_pointcloud_.is_dense = true;
00067 color_laser_pointcloud_.height = 1;
00068 color_laser_pointcloud_.point_step = laser_cloud_step;
00069
00070 color_laser_pointcloud_.fields.resize(4);
00071 color_laser_pointcloud_.fields[0].name = "x";
00072 color_laser_pointcloud_.fields[0].offset = 0;
00073 color_laser_pointcloud_.fields[0].count = 1;
00074 color_laser_pointcloud_.fields[0].datatype = sensor_msgs::PointField::FLOAT32;
00075 color_laser_pointcloud_.fields[1].name = "y";
00076 color_laser_pointcloud_.fields[1].offset = 4;
00077 color_laser_pointcloud_.fields[1].count = 1;
00078 color_laser_pointcloud_.fields[1].datatype = sensor_msgs::PointField::FLOAT32;
00079 color_laser_pointcloud_.fields[2].name = "z";
00080 color_laser_pointcloud_.fields[2].offset = 8;
00081 color_laser_pointcloud_.fields[2].count = 1;
00082 color_laser_pointcloud_.fields[2].datatype = sensor_msgs::PointField::FLOAT32;
00083 color_laser_pointcloud_.fields[3].name = "rgb";
00084 color_laser_pointcloud_.fields[3].offset = 12;
00085 color_laser_pointcloud_.fields[3].count = 1;
00086 color_laser_pointcloud_.fields[3].datatype = sensor_msgs::PointField::FLOAT32;
00087
00088 color_laser_publisher_ = nh.advertise<sensor_msgs::PointCloud2>("lidar_points2_color",
00089 10,
00090 boost::bind(&ColorLaser::startStreaming, this),
00091 boost::bind(&ColorLaser::stopStreaming, this));
00092
00093 }
00094
00095 ColorLaser::~ColorLaser()
00096 {
00097 }
00098
00099 void ColorLaser::colorImageCallback(
00100 const sensor_msgs::Image::ConstPtr& message
00101 )
00102 {
00103 boost::mutex::scoped_lock lock(data_lock_);
00104
00105
00106
00107
00108 image_channels_ = message->data.size() / (message->height * message->width);
00109
00110 if (image_channels_ > 3)
00111 {
00112 ROS_ERROR("Unsupported number of color channels: %d", image_channels_);
00113 }
00114
00115 color_image_ = *message;
00116 }
00117
00118 void ColorLaser::cameraInfoCallback(
00119 const sensor_msgs::CameraInfo::ConstPtr& message
00120 )
00121 {
00122 boost::mutex::scoped_lock lock(data_lock_);
00123
00124 camera_info_ = *message;
00125 }
00126
00127 void ColorLaser::laserPointCloudCallback(
00128 sensor_msgs::PointCloud2::Ptr message
00129 )
00130 {
00131 boost::mutex::scoped_lock lock(data_lock_);
00132
00133
00134
00135
00136
00137 if (message->header.stamp - color_image_.header.stamp > ros::Duration(2) ||
00138 message->header.stamp - camera_info_.header.stamp > ros::Duration(2))
00139 {
00140 return;
00141 }
00142
00143 color_laser_pointcloud_.header = message->header;
00144
00145
00146
00147
00148
00149 color_laser_pointcloud_.data.resize(message->data.size());
00150 float* colorPointCloudDataP = reinterpret_cast<float*>(&(color_laser_pointcloud_.data[0]));
00151
00152
00153
00154
00155
00156
00157
00158
00159 float* pointCloudDataP = reinterpret_cast<float*>(&(message->data[0]));
00160
00161 uint32_t height = message->height;
00162 uint32_t width = message->width;
00163 uint32_t cloudStep = message->point_step / message->fields.size();
00164
00165 uint32_t validPoints = 0;
00166 for( uint32_t index = 0 ; index < height * width ;
00167 ++index, pointCloudDataP += cloudStep)
00168 {
00169 float x = pointCloudDataP[0];
00170 float y = pointCloudDataP[1];
00171 float z = pointCloudDataP[2];
00172
00173
00174
00175
00176
00177
00178 if (sqrt(pow(x,2) + pow(y,2) + pow(z,2)) > 58.0)
00179 {
00180 continue;
00181 }
00182
00183
00184
00185
00186
00187
00188
00189
00190 uint32_t u = (camera_info_.P[0] * x + camera_info_.P[2] * z) / z;
00191
00192
00193 uint32_t v = (camera_info_.P[5] * y + camera_info_.P[6] * z) / z;
00194
00195
00196
00197
00198
00199
00200
00201 if (u < color_image_.width && v < color_image_.height && u >= 0 && v >= 0)
00202 {
00203
00204 colorPointCloudDataP[0] = x;
00205 colorPointCloudDataP[1] = y;
00206 colorPointCloudDataP[2] = z;
00207
00208 uint8_t* colorChannelP = reinterpret_cast<uint8_t*>(&colorPointCloudDataP[3]);
00209
00210
00211
00212
00213
00214 uint8_t* imageDataP = &color_image_.data[(image_channels_ * v * color_image_.width) + (image_channels_ * u)];
00215
00216 switch(image_channels_)
00217 {
00218 case 3:
00219 colorChannelP[2] = imageDataP[2];
00220 case 2:
00221 colorChannelP[1] = imageDataP[1];
00222 case 1:
00223 colorChannelP[0] = imageDataP[0];
00224 }
00225
00226
00227
00228
00229
00230 if (image_channels_ == 1)
00231 {
00232 colorChannelP[2] = imageDataP[0];
00233 colorChannelP[1] = imageDataP[0];
00234 }
00235
00236 colorPointCloudDataP += cloudStep;
00237 ++validPoints;
00238 }
00239
00240 }
00241
00242 color_laser_pointcloud_.data.resize(validPoints * laser_cloud_step);
00243 color_laser_pointcloud_.width = validPoints;
00244 color_laser_pointcloud_.row_step = validPoints * laser_cloud_step;
00245
00246 color_laser_publisher_.publish(color_laser_pointcloud_);
00247 }
00248
00249 void ColorLaser::startStreaming()
00250 {
00251 if (color_image_sub_.getNumPublishers() == 0 &&
00252 camera_info_sub_.getNumPublishers() == 0 &&
00253 laser_pointcloud_sub_.getNumPublishers() == 0)
00254 {
00255 color_image_sub_ = node_handle_.subscribe("image_rect_color",
00256 10,
00257 &multisense_ros::ColorLaser::colorImageCallback,
00258 this);
00259
00260 camera_info_sub_ = node_handle_.subscribe("camera_info",
00261 10,
00262 &multisense_ros::ColorLaser::cameraInfoCallback,
00263 this);
00264
00265 laser_pointcloud_sub_ = node_handle_.subscribe("lidar_points2",
00266 10,
00267 &multisense_ros::ColorLaser::laserPointCloudCallback,
00268 this);
00269 }
00270
00271 }
00272
00273 void ColorLaser::stopStreaming()
00274 {
00275 if (color_laser_publisher_.getNumSubscribers() == 0)
00276 {
00277 color_image_sub_.shutdown();
00278 camera_info_sub_.shutdown();
00279 laser_pointcloud_sub_.shutdown();
00280 }
00281 }
00282
00283 }
00284
00285 int main(int argc, char** argv)
00286 {
00287
00288 try
00289 {
00290 ros::init(argc, argv, "color_laser_publisher");
00291
00292 ros::NodeHandle nh;
00293
00294 multisense_ros::ColorLaser colorLaserPublisher(nh);
00295
00296 ros::spin();
00297 }
00298 catch(std::exception& e)
00299 {
00300 ROS_ERROR("%s", e.what());
00301 return 1;
00302 }
00303
00304 return 0;
00305 }
00306
00307