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

Revision history [back]

click to hide/show revision 1
initial version

Are you asking how to construct a sensor_msgs::PointCloud2 message from scratch? If this is the case: you construct it like any other ros message by first looking up the structure and documentation of that message in the .msg file.

Depending on the ros implementation you are using, most probably roscpp or rospy, you then need to construct an initialize its members. In c++ something like the following and in python also not too different.

#include <sensor_msgs/PointCloud2.h>

...

sensor_msgs::PointCloud2 msg; // construct message
msg.header = laserMsg.header; // perhaps something different, but often this is what you want
msg.height = 1; // or whatever you need
msg.widht  = 10000; // or whatever your width is
msg.fields = ... // this is more complicated but just is just more of the same
// and so on

Admittedly the sensor_msgs::PointCloud2 message is one of the more complicated messages you may use (at least for me that's true). You need to read the .msg file very carefully, which should be enough to build your own message. It could help to inspect existing PointCloud2 messages that you know to be correct and/or look into the implementation of convertPointCloudToPointCloud2 .

Please note the most important part to understand about the message: in the PointField[] fields you define the format in which your points are stored in the uint8[] data member.

I just realized myself, that PointCloud2 allows for a lot of flexibility, because of PointField[] fields, so I'm not sure what needs to be done to not break interoperability with other code. I'd assume that many nodes expect you define at least "x", "y" and "z" fields.

Are you asking how to construct a sensor_msgs::PointCloud2 message from scratch? If this is the case: you construct it like any other ros message by first looking up the structure and documentation of that message in the .msg file.

Depending on the ros implementation you are using, most probably roscpp or rospy, you then need to construct an initialize its members. In c++ something like the following and in python also not too different.

#include <sensor_msgs/PointCloud2.h>

...

sensor_msgs::PointCloud2 msg; // construct message
msg.header = laserMsg.header; // perhaps something different, but often this is what you want
msg.height = 1; // or whatever you need
msg.widht  = 10000; // or whatever your width is
msg.fields = ... // this is more complicated but just is just more of the same
// and so on

Admittedly the sensor_msgs::PointCloud2 message is one of the more complicated messages you may use (at least for me that's true). You need to read the .msg file very carefully, which should be enough to build your own message. It could help to inspect existing PointCloud2 messages that you know to be correct and/or look into the implementation of convertPointCloudToPointCloud2 .

Please note the most important part to understand about the message: in the PointField[] fields you define the format in which your points are stored in the uint8[] data member.

I just realized myself, that PointCloud2 allows for a lot of flexibility, because of PointField[] fields, so I'm not sure what needs to be done to not break interoperability with other code. I'd assume that many nodes expect you define at least "x", "y" and "z" fields.

Edit answering the comment From what I read in the documentation

  • point_step is the size of one point in bytes, which you need to manually calculate for your particular format as specified in msg.fields. (with pen & paper). For example if msg.fields[0] has datatype uint16 (2 bytes) and count 3, then your write down 23=6 bytes for that field. Plus the rest of msg.fields. A common use case would be for you to have 3 entries in msg.fields (for x, y and z) where each has datatype = FLOAT32, which is 4 bytes. So point_step would be 34=12.
  • row_step is should be just width*point_step. Seems rather odd me, because that is redundant.
  • data then contains your actual data as specified in fields. So in the simple use case from above it would just be x1, y1,z1, x2, y2, z3, x3, y3, z3, ....
  • What "is_dense = true" means is: this dataset has _no_ invalid points (e.g., NaN, Inf). (Source is about PCL but it sure is equivalent)