ros / common_msgs

Commonly used messages in ROS. Includes messages for actions (actionlib_msgs), diagnostics (diagnostic_msgs), geometric primitives (geometry_msgs), robot navigation (nav_msgs), and common sensors (sensor_msgs), such as laser range finders, cameras, point clouds.
http://wiki.ros.org/common_msgs
179 stars 191 forks source link

Add function to convert sensor_msgs/PointCloud2 to list of named tuples #111

Closed 2scholz closed 6 years ago

2scholz commented 7 years ago

Add new function read_points_list. In contrast to read_points it returns a list of named tuples, instead of a generator. Using lists one can access the points via index, which is not possible using a generator. The named tuples are indexed by the field name.

We use this package in an undergraduate course at our university. Many students struggled using the generator and lists are more intuitive for beginners. For a previous discussion regarding this issue see this pull request.

We would like to see this change in indigo-devel branch as well. This should not be a problem because API did not change.

We used the code below to test on our turtlebots:

projector = LaserProjection()

def scanCallback(scan_in):
    cloud = projector.projectLaser(scan_in)

    # create a list of namedtuples containing the values of the point cloud for easier usage
    point_list = read_points_list(cloud)

    # access the values
    print point_list[0]
    print point_list[0].x

@vrabaud Please have a look.

2scholz commented 7 years ago

@vrabaud was concerned about the performance of the previous approach that created a PointCloud1 directly. If we create namedtuples from the results returned by the generator wouldn't this affect the performance in the same way? Apart from this it clearly makes sense not to duplicate the logic.

How should we proceed?

tfoote commented 7 years ago

I'm not worried about performance as this is explicitly a lower performance approach than the generator. I just want that to be clearly documented for the users so they don't use the lower performance one without knowing the difference.

And since this code block and the one above are line for line identical except for appending vs yielding they should be collapsed.

2scholz commented 7 years ago

I completely agree on the documentation.

It is not true though that both code blocks are identical except for the appending vs yielding. The new function uses named tuples, while the other function yields a list.

For comparison, this is the line in read_points: p = unpack_from(data, (row_step * v) + (point_step * u))

And this is the line in read_points_list: point = Point._make(unpack_from(data, (row_step * v) + (point_step * u)

I just want to clear any misconceptions, so if you still think the generator is the way to go I will make the necessary changes.

2scholz commented 7 years ago

I made a new pull request for the alternative approach you suggested.

tfoote commented 6 years ago

Replaced by #112