color_laser.cpp
Go to the documentation of this file.
1 
34 #include <functional>
35 
38 
39 //
40 // Anonymous namespace for locally scoped symbols
41 namespace {
42 
43  const uint32_t laser_cloud_step = 16;
44 
45 } // namespace
46 
47 namespace multisense_ros {
48 
49 ColorLaser::ColorLaser(ros::NodeHandle& nh, const std::string &tf_prefix):
50  node_handle_(nh),
51  image_channels_(3),
52  tf_prefix_(tf_prefix)
53 {
54  //
55  // Initialize point cloud structure
56 
57  color_laser_publisher_ = nh.advertise<sensor_msgs::PointCloud2>("lidar_points2_color",
58  10,
59  std::bind(&ColorLaser::startStreaming, this),
60  std::bind(&ColorLaser::stopStreaming, this));
61 
62 }
63 
65  const sensor_msgs::Image::ConstPtr& message
66 )
67 {
68  std::lock_guard<std::mutex> lock(data_lock_);
69 
70  //
71  // Images are assumed to be 8 bit.
72 
73  image_channels_ = message->data.size() / (message->height * message->width);
74 
75  if (image_channels_ > 3)
76  {
77  ROS_ERROR("Unsupported number of color channels: %d", image_channels_);
78  }
79 
80  color_image_ = *message;
81 }
82 
84  const sensor_msgs::CameraInfo::ConstPtr& message
85 )
86 {
87  std::lock_guard<std::mutex> lock(data_lock_);
88 
89  camera_info_ = *message;
90 }
91 
93  sensor_msgs::PointCloud2::Ptr message
94 )
95 {
96  std::lock_guard<std::mutex> lock(data_lock_);
97 
98  //
99  // Make sure the associated camera_info/color image is within 2 seconds
100  // of the current point cloud message
101 
102  if (message->header.stamp - color_image_.header.stamp > ros::Duration(2) ||
103  message->header.stamp - camera_info_.header.stamp > ros::Duration(2))
104  {
105  return;
106  }
107 
108  initializePointcloud<float, uint32_t>(color_laser_pointcloud_,
109  message->header.stamp,
110  message->width,
111  message->height,
112  true,
113  message->header.frame_id,
114  "rgb");
115 
116  //
117  // Here we assume that our the sizeof our intensity field is the same as
118  // the sizeof our new rgb color field.
119 
120  float* colorPointCloudDataP = reinterpret_cast<float*>(&(color_laser_pointcloud_.data[0]));
121 
122  //
123  // Iterate over all the points in the point cloud, Use the camera projection
124  // matrix to project each point into the left camera image,
125  // colorize the point with the corresponding image point in the left
126  // camera. If the point does not project into the camera image
127  // do not add it to the point cloud.
128 
129  float* pointCloudDataP = reinterpret_cast<float*>(&(message->data[0]));
130 
131  const uint32_t height = message->height;
132  const uint32_t width = message->width;
133  const uint32_t cloudStep = message->point_step / message->fields.size();
134 
135  uint32_t validPoints = 0;
136  for( uint32_t index = 0 ; index < height * width ; ++index, pointCloudDataP += cloudStep)
137  {
138  float x = pointCloudDataP[0];
139  float y = pointCloudDataP[1];
140  float z = pointCloudDataP[2];
141 
142  //
143  // Invalid points from the laser will have a distance of 60m.
144  // Since these points have the laser calibration applied to them
145  // add in a 2m buffer for filtering out invalid points
146 
147  if (sqrt(x * x + y * y * z * z) > 58.0)
148  {
149  continue;
150  }
151 
152  //
153  // Compute the (u,v) camera coordinates corresponding to our laser
154  // point
155 
156  //
157  // (fx*x + cx*z)/z
158  const double u = (camera_info_.P[0] * x + camera_info_.P[2] * z) / z;
159  //
160  // (fy*y + cy*z)/z
161  const double v = (camera_info_.P[5] * y + camera_info_.P[6] * z) / z;
162 
163  //
164  // If our computed (u, v) point projects into the image use its
165  // color value and add it to the color pointcloud message
166 
167  if (u < color_image_.width && v < color_image_.height && u >= 0.0 && v >= 0.0)
168  {
169 
170  colorPointCloudDataP[0] = x;
171  colorPointCloudDataP[1] = y;
172  colorPointCloudDataP[2] = z;
173 
174  uint8_t* colorChannelP = reinterpret_cast<uint8_t*>(&colorPointCloudDataP[3]);
175 
176  //
177  // Image data is assumed to be BRG and stored continuously in memory
178  // both of which are the case for color images from the MultiSense
179 
180  uint8_t* imageDataP = &color_image_.data[(image_channels_ * static_cast<size_t>(v) * color_image_.width) +
181  (image_channels_ * static_cast<size_t>(u))];
182 
183  switch(image_channels_)
184  {
185  case 3:
186  colorChannelP[2] = imageDataP[2];
187  colorChannelP[1] = imageDataP[1];
188  colorChannelP[0] = imageDataP[0];
189  break;
190  case 2:
191  colorChannelP[1] = imageDataP[1];
192  colorChannelP[0] = imageDataP[0];
193  break;
194  case 1:
195  colorChannelP[0] = imageDataP[0];
196  colorChannelP[2] = imageDataP[0];
197  colorChannelP[1] = imageDataP[0];
198  break;
199  }
200 
201  colorPointCloudDataP += cloudStep;
202  ++validPoints;
203  }
204 
205  }
206 
207  color_laser_pointcloud_.data.resize(validPoints * laser_cloud_step);
208  color_laser_pointcloud_.width = validPoints;
209  color_laser_pointcloud_.row_step = validPoints * laser_cloud_step;
210 
212 }
213 
215 {
216  if (color_image_sub_.getNumPublishers() == 0 &&
219  {
220  color_image_sub_ = node_handle_.subscribe("image_rect_color",
221  10,
223  this);
224 
225  camera_info_sub_ = node_handle_.subscribe("camera_info",
226  10,
228  this);
229 
230  laser_pointcloud_sub_ = node_handle_.subscribe("lidar_points2",
231  10,
233  this);
234  }
235 
236 }
237 
239 {
241  {
245  }
246 }
247 
248 } // namespace
249 
250 int main(int argc, char** argv)
251 {
252  try
253  {
254  ros::init(argc, argv, "color_laser_publisher");
255 
256  ros::NodeHandle nh;
257  ros::NodeHandle nh_private("~");
258 
259  std::string tf_prefix;
260  nh_private.param<std::string>("tf_prefix", tf_prefix, "multisense");
261 
262  multisense_ros::ColorLaser colorLaserPublisher(nh, tf_prefix);
263 
264  ros::spin();
265  }
266  catch(std::exception& e)
267  {
268  ROS_ERROR("%s", e.what());
269  return 1;
270  }
271 
272  return 0;
273 }
ros::init
ROSCPP_DECL void init(const M_string &remappings, const std::string &name, uint32_t options=0)
color_laser.h
multisense_ros::ColorLaser::camera_info_sub_
ros::Subscriber camera_info_sub_
Definition: color_laser.h:93
multisense_ros::ColorLaser::startStreaming
void startStreaming()
Definition: color_laser.cpp:214
ros::Subscriber::shutdown
void shutdown()
ros::Publisher::publish
void publish(const boost::shared_ptr< M > &message) const
ros::NodeHandle::advertise
Publisher advertise(AdvertiseOptions &ops)
ros::Subscriber::getNumPublishers
uint32_t getNumPublishers() const
multisense_ros::ColorLaser::image_channels_
uint8_t image_channels_
Definition: color_laser.h:108
point_cloud_utilities.h
multisense_ros::ColorLaser::color_laser_publisher_
ros::Publisher color_laser_publisher_
Definition: color_laser.h:86
multisense_ros
Definition: camera.h:58
multisense_ros::ColorLaser::cameraInfoCallback
void cameraInfoCallback(const sensor_msgs::CameraInfo::ConstPtr &message)
Definition: color_laser.cpp:83
multisense_ros::ColorLaser::color_image_sub_
ros::Subscriber color_image_sub_
Definition: color_laser.h:91
ros::NodeHandle::subscribe
Subscriber subscribe(const std::string &topic, uint32_t queue_size, const boost::function< void(C)> &callback, const VoidConstPtr &tracked_object=VoidConstPtr(), const TransportHints &transport_hints=TransportHints())
multisense_ros::ColorLaser::data_lock_
std::mutex data_lock_
Definition: color_laser.h:103
multisense_ros::ColorLaser::laser_pointcloud_sub_
ros::Subscriber laser_pointcloud_sub_
Definition: color_laser.h:92
main
int main(int argc, char **argv)
Definition: color_laser.cpp:250
multisense_ros::ColorLaser::laserPointCloudCallback
void laserPointCloudCallback(sensor_msgs::PointCloud2::Ptr message)
Definition: color_laser.cpp:92
multisense_ros::ColorLaser::ColorLaser
ColorLaser(ros::NodeHandle &nh, const std::string &tf_prefix)
Definition: color_laser.cpp:49
multisense_ros::ColorLaser::color_image_
sensor_msgs::Image color_image_
Definition: color_laser.h:78
ROS_ERROR
#define ROS_ERROR(...)
multisense_ros::ColorLaser::color_laser_pointcloud_
sensor_msgs::PointCloud2 color_laser_pointcloud_
Definition: color_laser.h:81
ros::NodeHandle::param
T param(const std::string &param_name, const T &default_val) const
multisense_ros::ColorLaser::stopStreaming
void stopStreaming()
Definition: color_laser.cpp:238
ros::spin
ROSCPP_DECL void spin()
multisense_ros::ColorLaser::camera_info_
sensor_msgs::CameraInfo camera_info_
Definition: color_laser.h:79
multisense_ros::ColorLaser
Definition: color_laser.h:48
ros::Publisher::getNumSubscribers
uint32_t getNumSubscribers() const
ros::Duration
ros::NodeHandle
multisense_ros::ColorLaser::colorImageCallback
void colorImageCallback(const sensor_msgs::Image::ConstPtr &message)
Definition: color_laser.cpp:64
multisense_ros::ColorLaser::node_handle_
ros::NodeHandle node_handle_
Definition: color_laser.h:98


multisense_ros
Author(s):
autogenerated on Thu Apr 17 2025 02:49:24