40 bool preservative,
int mask)
42 boost::numeric::ublas::matrix<double> ranges(2, scan_in.ranges.size());
45 for (
unsigned int index = 0; index < scan_in.ranges.size(); index++)
47 ranges(0,index) = (double) scan_in.ranges[index];
48 ranges(1,index) = (double) scan_in.ranges[index];
53 boost::numeric::ublas::matrix<double> output = element_prod(ranges,
getUnitVectors_(scan_in.angle_min, scan_in.angle_max, scan_in.angle_increment, scan_in.ranges.size()));
56 cloud_out.header = scan_in.header;
57 cloud_out.points.resize (scan_in.ranges.size());
60 int idx_intensity = -1, idx_index = -1, idx_distance = -1, idx_timestamp = -1;
62 cloud_out.channels.resize(0);
67 int chan_size = cloud_out.channels.size();
68 cloud_out.channels.resize (chan_size + 1);
69 cloud_out.channels[0].name =
"intensities";
70 cloud_out.channels[0].values.resize (scan_in.intensities.size());
77 int chan_size = cloud_out.channels.size();
78 cloud_out.channels.resize (chan_size +1);
79 cloud_out.channels[chan_size].name =
"index";
80 cloud_out.channels[chan_size].values.resize (scan_in.ranges.size());
81 idx_index = chan_size;
87 int chan_size = cloud_out.channels.size();
88 cloud_out.channels.resize (chan_size + 1);
89 cloud_out.channels[chan_size].name =
"distances";
90 cloud_out.channels[chan_size].values.resize (scan_in.ranges.size());
91 idx_distance = chan_size;
96 int chan_size = cloud_out.channels.size();
97 cloud_out.channels.resize (chan_size + 1);
98 cloud_out.channels[chan_size].name =
"stamps";
99 cloud_out.channels[chan_size].values.resize (scan_in.ranges.size());
100 idx_timestamp = chan_size;
103 if (range_cutoff < 0)
104 range_cutoff = scan_in.range_max;
106 unsigned int count = 0;
107 for (
unsigned int index = 0; index< scan_in.ranges.size(); index++)
109 const float range = ranges(0, index);
110 if (preservative || ((range < range_cutoff) && (range >= scan_in.range_min)))
112 cloud_out.points[count].x = output(0,index);
113 cloud_out.points[count].y = output(1,index);
114 cloud_out.points[count].z = 0.0;
124 cloud_out.channels[idx_index].values[count] = index;
127 if (idx_distance != -1)
128 cloud_out.channels[idx_distance].values[count] = range;
131 if (scan_in.intensities.size() >= index)
133 if (idx_intensity != -1)
134 cloud_out.channels[idx_intensity].values[count] = scan_in.intensities[index];
138 if( idx_timestamp != -1)
139 cloud_out.channels[idx_timestamp].values[count] = (float)index*scan_in.time_increment;
146 cloud_out.points.resize (count);
147 for (
unsigned int d = 0;
d < cloud_out.channels.size();
d++)
148 cloud_out.channels[
d].values.resize(count);
153 boost::mutex::scoped_lock guv_lock(this->
guv_mutex_);
156 std::stringstream anglestring;
157 anglestring <<angle_min<<
","<<angle_max<<
","<<angle_increment<<
","<<length;
158 std::map<std::string, boost::numeric::ublas::matrix<double>* >::iterator it;
162 return *((*it).second);
164 boost::numeric::ublas::matrix<double> * tempPtr =
new boost::numeric::ublas::matrix<double>(2,length);
165 for (
unsigned int index = 0;index < length; index++)
167 (*tempPtr)(0,index) = cos(angle_min + (
double) index * angle_increment);
168 (*tempPtr)(1,index) = sin(angle_min + (
double) index * angle_increment);
179 std::map<std::string, boost::numeric::ublas::matrix<double>*>::iterator it;
192 cloud_out.header = scan_in.header;
198 bool requested_index =
false;
199 if ((mask & channel_option::Index))
200 requested_index =
true;
206 pointIn.
frame_id_ = scan_in.header.frame_id;
208 projectLaser_ (scan_in, cloud_out, range_cutoff,
false, mask);
210 cloud_out.header.frame_id = target_frame;
213 ros::Time start_time = scan_in.header.stamp ;
214 ros::Time end_time = scan_in.header.stamp ;
215 if(!scan_in.ranges.empty()) end_time +=
ros::Duration().
fromSec( (scan_in.ranges.size()-1) * scan_in.time_increment);
221 tf.
lookupTransform(target_frame, scan_in.header.frame_id, start_time, start_transform) ;
222 tf.
lookupTransform(target_frame, scan_in.header.frame_id, end_time, end_transform) ;
225 int index_channel_idx = -1;
226 for(
unsigned int i = 0; i < cloud_out.channels.size(); ++i)
228 if(cloud_out.channels[i].name ==
"index")
230 index_channel_idx = i;
238 for(
unsigned int i = 0; i < cloud_out.points.size(); ++i)
241 uint32_t pt_index = cloud_out.channels[index_channel_idx].values[i];
244 tfScalar ratio = pt_index / ( (double) scan_in.ranges.size() - 1.0) ;
262 tf::Vector3 pointIn(cloud_out.points[i].x, cloud_out.points[i].y, cloud_out.points[i].z) ;
266 cloud_out.points[i].
x = pointOut.
x();
267 cloud_out.points[i].y = pointOut.
y();
268 cloud_out.points[i].z = pointOut.
z();
273 cloud_out.channels.erase(cloud_out.channels.begin() + index_channel_idx);
277 sensor_msgs::PointCloud2 &cloud_out,
281 size_t n_pts = scan_in.ranges.size ();
282 Eigen::ArrayXXd ranges (n_pts, 2);
283 Eigen::ArrayXXd output (n_pts, 2);
286 for (
size_t i = 0; i < n_pts; ++i)
288 ranges (i, 0) = (double) scan_in.ranges[i];
289 ranges (i, 1) = (double) scan_in.ranges[i];
295 ROS_DEBUG (
"[projectLaser] No precomputed map given. Computing one.");
300 for (
size_t i = 0; i < n_pts; ++i)
302 co_sine_map_ (i, 0) = cos (scan_in.angle_min + (
double) i * scan_in.angle_increment);
303 co_sine_map_ (i, 1) = sin (scan_in.angle_min + (
double) i * scan_in.angle_increment);
310 cloud_out.header = scan_in.header;
311 cloud_out.height = 1;
312 cloud_out.width = scan_in.ranges.size ();
313 cloud_out.fields.resize (3);
314 cloud_out.fields[0].name =
"x";
315 cloud_out.fields[0].offset = 0;
316 cloud_out.fields[0].datatype = sensor_msgs::PointField::FLOAT32;
317 cloud_out.fields[0].count = 1;
318 cloud_out.fields[1].name =
"y";
319 cloud_out.fields[1].offset = 4;
320 cloud_out.fields[1].datatype = sensor_msgs::PointField::FLOAT32;
321 cloud_out.fields[1].count = 1;
322 cloud_out.fields[2].name =
"z";
323 cloud_out.fields[2].offset = 8;
324 cloud_out.fields[2].datatype = sensor_msgs::PointField::FLOAT32;
325 cloud_out.fields[2].count = 1;
328 int idx_intensity = -1, idx_index = -1, idx_distance = -1, idx_timestamp = -1, idx_vpx = -1, idx_vpy = -1, idx_vpz = -1;
332 if ((channel_options & channel_option::Intensity) && scan_in.intensities.size() > 0)
334 int field_size = cloud_out.fields.size();
335 cloud_out.fields.resize(field_size + 1);
336 cloud_out.fields[field_size].name =
"intensity";
337 cloud_out.fields[field_size].datatype = sensor_msgs::PointField::FLOAT32;
338 cloud_out.fields[field_size].offset = offset;
339 cloud_out.fields[field_size].count = 1;
341 idx_intensity = field_size;
344 if ((channel_options & channel_option::Index))
346 int field_size = cloud_out.fields.size();
347 cloud_out.fields.resize(field_size + 1);
348 cloud_out.fields[field_size].name =
"index";
349 cloud_out.fields[field_size].datatype = sensor_msgs::PointField::INT32;
350 cloud_out.fields[field_size].offset = offset;
351 cloud_out.fields[field_size].count = 1;
353 idx_index = field_size;
356 if ((channel_options & channel_option::Distance))
358 int field_size = cloud_out.fields.size();
359 cloud_out.fields.resize(field_size + 1);
360 cloud_out.fields[field_size].name =
"distances";
361 cloud_out.fields[field_size].datatype = sensor_msgs::PointField::FLOAT32;
362 cloud_out.fields[field_size].offset = offset;
363 cloud_out.fields[field_size].count = 1;
365 idx_distance = field_size;
368 if ((channel_options & channel_option::Timestamp))
370 int field_size = cloud_out.fields.size();
371 cloud_out.fields.resize(field_size + 1);
372 cloud_out.fields[field_size].name =
"stamps";
373 cloud_out.fields[field_size].datatype = sensor_msgs::PointField::FLOAT32;
374 cloud_out.fields[field_size].offset = offset;
375 cloud_out.fields[field_size].count = 1;
377 idx_timestamp = field_size;
382 int field_size = cloud_out.fields.size();
383 cloud_out.fields.resize(field_size + 3);
385 cloud_out.fields[field_size].name =
"vp_x";
386 cloud_out.fields[field_size].datatype = sensor_msgs::PointField::FLOAT32;
387 cloud_out.fields[field_size].offset = offset;
388 cloud_out.fields[field_size].count = 1;
391 cloud_out.fields[field_size + 1].name =
"vp_y";
392 cloud_out.fields[field_size + 1].datatype = sensor_msgs::PointField::FLOAT32;
393 cloud_out.fields[field_size + 1].offset = offset;
394 cloud_out.fields[field_size + 1].count = 1;
397 cloud_out.fields[field_size + 2].name =
"vp_z";
398 cloud_out.fields[field_size + 2].datatype = sensor_msgs::PointField::FLOAT32;
399 cloud_out.fields[field_size + 2].offset = offset;
400 cloud_out.fields[field_size + 2].count = 1;
403 idx_vpx = field_size;
404 idx_vpy = field_size + 1;
405 idx_vpz = field_size + 2;
408 cloud_out.point_step = offset;
409 cloud_out.row_step = cloud_out.point_step * cloud_out.width;
410 cloud_out.data.resize (cloud_out.row_step * cloud_out.height);
411 cloud_out.is_dense =
false;
413 if (range_cutoff < 0)
414 range_cutoff = scan_in.range_max;
416 unsigned int count = 0;
417 for (
size_t i = 0; i < n_pts; ++i)
420 const float range = scan_in.ranges[i];
421 if (range < range_cutoff && range >= scan_in.range_min)
423 float *pstep = (
float*)&cloud_out.data[count * cloud_out.point_step];
426 pstep[0] = output (i, 0);
427 pstep[1] = output (i, 1);
431 if(idx_intensity != -1)
432 pstep[idx_intensity] = scan_in.intensities[i];
436 ((
int*)(pstep))[idx_index] = i;
439 if(idx_distance != -1)
440 pstep[idx_distance] = range;
443 if(idx_timestamp != -1)
444 pstep[idx_timestamp] = i * scan_in.time_increment;
447 if(idx_vpx != -1 && idx_vpy != -1 && idx_vpz != -1)
491 cloud_out.width = count;
492 cloud_out.row_step = cloud_out.point_step * cloud_out.width;
493 cloud_out.data.resize (cloud_out.row_step * cloud_out.height);
497 const sensor_msgs::LaserScan &scan_in,
498 sensor_msgs::PointCloud2 &cloud_out,
500 tf2::Vector3 origin_start,
502 tf2::Vector3 origin_end,
507 bool requested_index =
false;
508 if ((channel_options & channel_option::Index))
509 requested_index =
true;
515 projectLaser_(scan_in, cloud_out, range_cutoff, channel_options);
518 bool has_viewpoint =
false;
519 uint32_t vp_x_offset = 0;
526 uint32_t index_offset = 0;
527 for(
unsigned int i = 0; i < cloud_out.fields.size(); ++i)
529 if(cloud_out.fields[i].name ==
"index")
531 index_offset = cloud_out.fields[i].offset;
537 if(cloud_out.fields[i].name ==
"vp_x")
539 has_viewpoint =
true;
540 vp_x_offset = cloud_out.fields[i].offset;
546 cloud_out.header.frame_id = target_frame;
550 double ranges_norm = 1 / ((double) scan_in.ranges.size () - 1.0);
553 for(
size_t i = 0; i < cloud_out.width; ++i)
556 float *pstep = (
float*)&cloud_out.data[i * cloud_out.point_step + 0];
560 memcpy(&pt_index, &cloud_out.data[i * cloud_out.point_step + index_offset],
sizeof(uint32_t));
563 tfScalar ratio = pt_index * ranges_norm;
567 tf2::Vector3 v (0, 0, 0);
568 v.setInterpolate3 (origin_start, origin_end, ratio);
574 tf2::Vector3 point_in (pstep[0], pstep[1], pstep[2]);
575 tf2::Vector3 point_out = cur_transform * point_in;
578 pstep[0] = point_out.x ();
579 pstep[1] = point_out.y ();
580 pstep[2] = point_out.z ();
585 float *vpstep = (
float*)&cloud_out.data[i * cloud_out.point_step + vp_x_offset];
586 point_in = tf2::Vector3 (vpstep[0], vpstep[1], vpstep[2]);
587 point_out = cur_transform * point_in;
590 vpstep[0] = point_out.x ();
591 vpstep[1] = point_out.y ();
592 vpstep[2] = point_out.z ();
599 sensor_msgs::PointCloud2 cloud_without_index;
602 cloud_without_index.header = cloud_out.header;
603 cloud_without_index.width = cloud_out.width;
604 cloud_without_index.height = cloud_out.height;
605 cloud_without_index.is_bigendian = cloud_out.is_bigendian;
606 cloud_without_index.is_dense = cloud_out.is_dense;
609 cloud_without_index.fields.resize(cloud_out.fields.size());
610 unsigned int field_count = 0;
611 unsigned int offset_shift = 0;
612 for(
unsigned int i = 0; i < cloud_out.fields.size(); ++i)
614 if(cloud_out.fields[i].name !=
"index")
616 cloud_without_index.fields[field_count] = cloud_out.fields[i];
617 cloud_without_index.fields[field_count].offset -= offset_shift;
628 cloud_without_index.fields.resize(field_count);
631 cloud_without_index.point_step = cloud_out.point_step - offset_shift;
632 cloud_without_index.row_step = cloud_without_index.point_step * cloud_without_index.width;
633 cloud_without_index.data.resize (cloud_without_index.row_step * cloud_without_index.height);
638 while (i < cloud_out.data.size())
640 if((i % cloud_out.point_step) < index_offset || (i % cloud_out.point_step) >= (index_offset + 4))
642 cloud_without_index.data[j++] = cloud_out.data[i];
648 cloud_out = cloud_without_index;
653 const sensor_msgs::LaserScan &scan_in,
654 sensor_msgs::PointCloud2 &cloud_out,
659 ros::Time start_time = scan_in.header.stamp;
660 ros::Time end_time = scan_in.header.stamp;
661 if(!scan_in.ranges.empty()) end_time +=
ros::Duration ().
fromSec ( (scan_in.ranges.size()-1) * scan_in.time_increment);
665 tf.
lookupTransform (target_frame, scan_in.header.frame_id, start_time, start_transform);
666 tf.
lookupTransform (target_frame, scan_in.header.frame_id, end_time, end_transform);
674 tf2::Vector3 origin_start(start_transform.
getOrigin().
getX(),
681 quat_start, origin_start,
682 quat_end, origin_end,
688 const sensor_msgs::LaserScan &scan_in,
689 sensor_msgs::PointCloud2 &cloud_out,
694 ros::Time start_time = scan_in.header.stamp;
695 ros::Time end_time = scan_in.header.stamp;
696 if(!scan_in.ranges.empty()) end_time +=
ros::Duration ().
fromSec ( (scan_in.ranges.size()-1) * scan_in.time_increment);
698 geometry_msgs::TransformStamped start_transform = tf.
lookupTransform (target_frame, scan_in.header.frame_id, start_time);
699 geometry_msgs::TransformStamped end_transform = tf.
lookupTransform (target_frame, scan_in.header.frame_id, end_time);
702 start_transform.transform.rotation.y,
703 start_transform.transform.rotation.z,
704 start_transform.transform.rotation.w);
706 end_transform.transform.rotation.y,
707 end_transform.transform.rotation.z,
708 end_transform.transform.rotation.w);
710 tf2::Vector3 origin_start(start_transform.transform.translation.x,
711 start_transform.transform.translation.y,
712 start_transform.transform.translation.z);
713 tf2::Vector3 origin_end(end_transform.transform.translation.x,
714 end_transform.transform.translation.y,
715 end_transform.transform.translation.z);
717 quat_start, origin_start,
718 quat_end, origin_end,
void projectLaser_(const sensor_msgs::LaserScan &scan_in, sensor_msgs::PointCloud &cloud_out, double range_cutoff, bool preservative, int channel_options)
Internal hidden representation of projectLaser.
std::map< std::string, boost::numeric::ublas::matrix< double > * > unit_vector_map_
Internal map of pointers to stored values.
TFSIMD_FORCE_INLINE const tfScalar & getY() const
TFSIMD_FORCE_INLINE const tfScalar & getW() const
TFSIMD_FORCE_INLINE const tfScalar & getZ() const
TFSIMD_FORCE_INLINE Quaternion slerp(const Quaternion &q1, const Quaternion &q2, const tfScalar &t)
Eigen::ArrayXXd co_sine_map_
void getRotation(Quaternion &q) const
TFSIMD_FORCE_INLINE const tfScalar & x() const
TFSIMD_FORCE_INLINE const tfScalar & z() const
TFSIMD_FORCE_INLINE void setInterpolate3(const Vector3 &v0, const Vector3 &v1, tfScalar rt)
~LaserProjection()
Destructor to deallocate stored unit vectors.
Duration & fromSec(double t)
TFSIMD_FORCE_INLINE const tfScalar & y() const
const boost::numeric::ublas::matrix< double > & getUnitVectors_(double angle_min, double angle_max, double angle_increment, unsigned int length)
Internal protected representation of getUnitVectors.
void transformLaserScanToPointCloud_(const std::string &target_frame, sensor_msgs::PointCloud &cloud_out, const sensor_msgs::LaserScan &scan_in, tf::Transformer &tf, double range_cutoff, int channel_options)
Internal hidden representation of transformLaserScanToPointCloud.
Enable "viewpoint" channel.
Enable "intensities" channel.
TFSIMD_FORCE_INLINE const tfScalar & getX() const
Enable "distances" channel.
geometry_msgs::TransformStamped lookupTransform(const std::string &target_frame, const std::string &source_frame, const ros::Time &time) const