What does the contents of PointCloud2 means in ROS?

  1. fields.offset?
  2. fields.datatype?
  3. fields.count?
  4. point_step?
  5. row_step?

Its documentation is poor

Here is a published PointCloud2 message by Velodyne LiDAR:

  seq: 1071
    secs: 1521699326
    nsecs: 676390000
  frame_id: "velodyne"
height: 1
width: 66811
    name: "x"
    offset: 0
    datatype: 7
    count: 1
    name: "y"
    offset: 4
    datatype: 7
    count: 1
    name: "z"
    offset: 8
    datatype: 7
    count: 1
    name: "intensity"
    offset: 16
    datatype: 7
    count: 1
    name: "ring"
    offset: 20
    datatype: 4
    count: 1
is_bigendian: False
point_step: 32
row_step: 2137952
data: [235, 171, 54, 190, 53, 107, 250, ...

  1. Why height in Velodyne-HDL64e LiDAR is equal to one? I expected it to be 64.

  2. Finally, for example, what is 171 value in data? is Y or is a range (for which one of the beams)?


3 Answers 3


I get why you are confused.

Looking at the definition of PointCloud2, you see that the field that holds the "actual" point cloud data is a 1-dimensional array. Now, you might think, wait: why aren't there 3 dimensions, one for X, Y, and Z? Well, this is why we have PointCloud2: so we can have a single array in memory contain all the info we need, regardless of data associated with the point. The offset is simply where the definition of that part of the first and next point starts in that honkin' huge array. This array not only contains XYZ data, but it also contains other data, like, as the documentation for the message says, normals, intensity, etc.. The PointField message simply tells ROS how the data is formatted (kind of like how you might add a message header to the data being sent through a socket, but that is outside the scope of the question).

I suggest you read the overview on pcl on the ROS website as well as on this link.

The other questions specific to Velodyne I would not be able to answer since I don't know anything about your configuration.


I totally agree that the documentation is poor and it took me quite some time to understand what is going on.

I recorded a rosbag for "velodyne_points" topic using a Velodyne VLP-16. The recorded message is PointCloud2 type. Since the recorded file was really large it gave me a lot of trouble even when only trying to take a look at it(initially I had it converted to .csv and used -010 Editor- to read but csv format turned out useless for me).

What worked was that when I converted this bag file to .pcd format. Take a look at this link for that:


Then I took a look at one of the .pcd files and used the info in the following link to understand what is in it:


After these steps I understood what the PointCloud2 message is about...

So the incoming data in that array you asked about is a 1-D array. That is the reason the height is 1. It is called an unordered or unorganized point cloud data. The ring field tells which one of the 16 lasers in VLP-16 is used (though it is different than the laser numbers in the hardware manual), for your case it should be between 0-63.

The datatype tells whether the fields are float, uint16, int8 etc. After taking a look at the .pcd file I understand that the x,y,z,intensity fields are 4 bytes representation of a floating point number (little endian in your message). The ring value is a uint16(unsigned short).

The count is how many of that datatype is there. So you have 4 byte long 1 x, 4 byte long 1 y, 4 byte long 1 z, 4 byte long 1 intensity and 2 byte long 1 ring fields.

Offset tells at which byte the related field starts. For example offset x is 0 so x is 235 171 54 190 in little endian. Then y starts at 4, which is 53 107 ...

Here is the header of my .pcd file:

.PCD v0.7 - Point Cloud Data file format


FIELDS x y z _ intensity ring _

SIZE 4 4 4 1 4 2 1


COUNT 1 1 1 4 1 1 10

WIDTH 26326


VIEWPOINT 0 0 0 1 0 0 0

POINTS 26326

DATA binary

It tells that there are empty bytes after z and ring fields. After z field there are 4 empty bytes (that is why intensity has an offset of 16, not 12), and after ring there are 10 empty bytes.

point_step is the length of a point in bytes says the PointCloud2 document. It is as follows:

4 bytes (x) + 4 (y) + 4 (z) + 4 (empty) + 4 (intensity) + 2 (ring) + 10 (empty) = 32

row_step is the length of a row in bytes, which is 66811 points (width) * 32 bytes = 2137952

  • $\begingroup$ Why are there empty bytes befor intensity and after ring? $\endgroup$
    – desmond13
    Feb 28, 2022 at 17:18

The height for the Velodyne-HDL64e LiDAR is one because it is an unorganized datasets. This is because pointclouds won't have the same amount of points in dynamic scenarios (if nothing is "seen" by the LiDAR the entry is just left out) while a pointcloud from a camera might have a fixed size (height x width) which helps to speedup some algorithms.
In your Pointcloud2 data example you have an unorganized datasets (indicated by height of 1) with a total of 66811 points (indicated by the width). The following message might have more or less points depending on the objects in the scene.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.