ROS Resources: Documentation | Support | Discussion Forum | Index | Service Status | ros @ Robotics Stack Exchange
Ask Your Question
1

confusion about constructing pointcloud2 messages

asked 2020-11-10 10:21:37 -0500

ecarrig gravatar image

updated 2020-11-13 10:32:08 -0500

foxy on ubuntu 20.04, C++, new to ROS2 and ROS generally

I would like to publish a pointcloud2 message based on periodic laser profiles (a rudimentary driver if you will).

I considered using a laser scan message, but since the data come as Cartesian co-ordinates (not polar), going right to point cloud seemed more appropriate. My data consist of X co-ordinates and Z co-ordinates.

from the PointCloud2.msg file:

The point cloud data may be organized 2d (image-like) or 1d (unordered). Point clouds organized as 2d images may be produced by camera depth sensors such as stereo or time-of-flight... 2D structure of the point cloud. If the cloud is unordered, height is 1 and width is the length of the point cloud.

I am not clear on how to choose these dimensions. My data is not exactly image-like, but it is not unordered (or at least need not be) either.

Are the height and width defined in terms of bytes, co-ordinates, or points (sets of two co-ordinates)?

From the PointField.msg file:

Common PointField names are x, y, z, intensity, rgb, rgba

So... if the field name is RGB, does that imply a "point" is an amalgamation of 3 values? Why would one choose to do that? Why wouldn't one do that with xyz? Is a "point" a single co-ordinate or a set of co-ordinates whose number of elements is equal to the dimensionality of the space (in my case two)?

No idea what offset means here... (first reference to "struct"?)

The actual values (in real units) are real numbers (some negative) with 2 degrees of precision. I have already unpacked the data from the sensor into arrays of floats (it arrived as two byte values). Is FLOAT32 therefore the right choice?

how many elements are there in the field? One X one Z - so two? Or one X in one field and one Z in another field?

point_step? same irreconcilability...

row_step? When did we start talking about rows?

I understand the actual co-ordinates need to be stored in a binary blob (technically a std::vector<unsigned char="">). How should I do that starting from floats? Or should I not even bother with trans-coding into floats in the first place? If not, how should I handle scaling the values to real units? Where are the units specified?

Any reference on this subject is welcomed. Any examples of anything similar?

Thanks in advance!

[UPDATE]

I am grateful (and still clueless and frustrated). I am now able to build a pcl::PointCloud<pcl::pointxyz>

object (I think).

I believe I have the recommended package installed:

$ apt-cache policy ros-foxy-pcl-conversions

ros-foxy-pcl-conversions: Installed: 2.2.0-1focal.20201103.153038

I've updated my CMakeLists.txt file to:

cmake_minimum_required(VERSION 3.5)

project(leuze_lps_36_driver)

find_package(ament_cmake REQUIRED)

find_package(rclcpp REQUIRED)

find_package(std_msgs REQUIRED)

find_package(sensor_msgs REQUIRED)

find_package(PCL 1.3 REQUIRED COMPONENTS common io conversions)

include_directories(${PCL_INCLUDE_DIRS})

link_directories(${PCL_LIBRARY_DIRS}) add_definitions(${PCL_DEFINITIONS})

add_executable(profile_publisher src/profile_publisher.cpp)

ament_target_dependencies(profile_publisher rclcpp std_msgs sensor_msgs)

target_include_directories(profile_publisher PUBLIC $<build_interface:${cmake_current_source_dir ...

(more)
edit retag flag offensive close merge delete

Comments

1

Taking a step back:

  1. have you made sure there is not already a driver for your laser scanner? If you could tell us the make and model nr, it should not be too hard to find one if it has been shared before.
  2. you normally don't create sensor_msgs/PointCloud2 messages by hand, but create a PCL cloud object and then convert that using pcl_ros et al. The conversion takes care of almost all the details you now have questions about.

    Don't confuse a message (ie: the serialised form of a data structure) with the object (in this case the PCL cloud object). You create objects, then convert them to messages and publish those.

gvdhoorn gravatar image gvdhoorn  ( 2020-11-10 11:31:58 -0500 )edit

The sensor is a Leuze LPS 36HI/EN.10. I did look, but could not find anything. Thanks for the tip about object/message confusion - no doubt I have it. I did come across pcl_ros, but did not investigate deeply b/c it has not been ported to ROS2 (AFAIK).

ecarrig gravatar image ecarrig  ( 2020-11-10 12:20:43 -0500 )edit

The pcl_conversions package has been ported to ROS2, and that's the specific one you'll need to convert between PCL cloud objects and ROS2 sensor_msgs/PointCloud2 messages. You should be able to install it through ros-foxy-pcl-conversions. I would definitely recommend using the functions in that package (in particular, pcl::toROSMsg()) instead of manually populating the fields in the PointCloud2 message.

jschornak gravatar image jschornak  ( 2020-11-10 23:12:00 -0500 )edit

the compiler is not complaining about: #include <pcl conversions.h="">

and yet when I call pcl::toROSMsg(cloud, &profile);

I get

error: ‘toROSMsg’ is not a member of ‘pcl’

152 | pcl::toROSMsg(cloud, &profile);

where do you actually find_package(pcl_conversions REQUIRED) and pass pcl_conversions to ament_target_dependencies?

I don't see that in the CMakeLists.txt you show.

You also shouldn't need to manually find_package(PCL ..), as I believe pcl_conversions already brings in that dependency, but it probably doesn't hurt. I wouldn't use link_directories(..) any more though.

gvdhoorn gravatar image gvdhoorn  ( 2020-11-13 10:35:31 -0500 )edit

That certainly helped :) I did still have to pull in PCL independently... Thanks ton! Now to see if I can actually get toROSMsg() to work! Will update with a synopsis when I get it.

ecarrig gravatar image ecarrig  ( 2020-11-13 11:11:53 -0500 )edit

1 Answer

Sort by » oldest newest most voted
3

answered 2020-11-13 16:24:52 -0500

ecarrig gravatar image

updated 2020-11-13 16:29:20 -0500

So... I don't quite know if this qualifies as an "answer" (I certainly don't want to steal anybody's karma - all credit due to gvdhoorn and jschornak), but yes, unsurprisingly to many I'm sure, creating a

pcl::PointCloud<pcl::pointxyz> cloud

then converting that to a pointcloud 2 sensor message

pcl::toROSMsg(cloud, profile);

and publishing that

publisher_->publish(profile);

worked for me. I still need to figure out how to use tf2 to locate the sensor, and I think there may be some funny business around negative values, but at least there are tutorials for that. Thanks again!

edit flag offensive delete link more

Comments

1

also this would have been helpful https://pcl.readthedocs.io/en/latest/...

ecarrig gravatar image ecarrig  ( 2020-11-13 17:11:22 -0500 )edit

Question Tools

2 followers

Stats

Asked: 2020-11-10 10:21:37 -0500

Seen: 1,926 times

Last updated: Nov 13 '20