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
177 stars 190 forks source link

MultiLayerLaserScan #150

Open peci1 opened 4 years ago

peci1 commented 4 years ago

Nowadays, there seem to be lots of multiple-layer lidars on the market. I've noticed there's no datatype that would represent them as laserscans (of course, you can transform them into pointclouds right away, but you can lose some information during the transformation).

The result is that most lidar vendors create their own message types, which are, of course, incompatible. And then, it also means each lidar vendor provides his own version of raw data->pointcloud transformers, although there already is the standard (though single-layer) LaserScanToPointCloud tool provided by ROS.

I think it'd be nice to provide a common defeinition vendors could use to get to the same nice state where single-layered lidars are now in ROS.

However, I'm neither a lidar maker, nor do I feel I could persuade them to switch to a different scan message. Do you see any way to proceed?

E.g. Gazebo has its own multilayered scan definition, although a simplified one which doesn't account for the time it takes to capture the scan: https://bitbucket.org/osrf/gazebo/src/default/gazebo/msgs/laserscan.proto .

tfoote commented 4 years ago

There's certainly an option to propose one. If you wanted to do so conducting a survey of the sensors available, determining their datatypes and then layout out the necessary coverage elements would be what we'd want to do. As well as collecting all the competing implementations for comparison and contrasting.

A few concerns I would have would be to think about what order scans are measured? Are they simultaneous? Do they go in the same direction? Do they have the same start angles? Do they follow a grid or are they interleaved or offset?

There are also several approaches using existing datatypes that can capture the information fully. The simplest is to simply publish N LaserScan messages, one for each row of the scan.

As a multi layer laser scanner starts to get to a non-trivial number of layers it starts to look a lot like a depth camera, and as such the DepthImage datatype starts to look like a good way to encode the data for analysis. (Clearly this would be missing some of the potential timing data, but can be processed quickly in many common pipelines). And of course the laser drivers could also just directly publish the point clouds doing all the internal timing and reprojection internally. Again there's a little bit of timing loss compared to the high precision laser scan to point cloud projections without the timing information available.

One benefit of using N of the basic LaserScan messages is that the standard laser scan to point cloud implementations can continue to work. Also if users want classic behavior they can process just one of the scans. Each scan can be run into all the standard navigation algorithms without andy changes. And the aggregate results can moderately easily be aggregated say using the point cloud aggregator just like we did for the tilting hokuyo on the PR2. N scans can be aggregated, transformed with high precision and then converted into the depth map or point cloud.

So in the end I'd suggest encouraging the laser scanner drivers to publish N of the standard Laser Scans for the N rows. Likely they could be put out on the same topic and they would just want to have different frame_ids for each scan to show the different angular positions. And this would work for ones that are not even coaxial or have a single focal point, or exactly the same timings.

peci1 commented 4 years ago

Thanks for the insights, Tully. I was already thinking about this and many of the problems you pointed out popped up to me, too. But I think it's manageable if it's done proper/thoroughly.

I've two comments now before anyone starts doing the actual job.

  1. The idea to publish multiple LaserScan messages won't work for the majority of multi-layer laser scanners, because the scan rings aren't planes but cones. And I think most (if not all) LaserScan processing algorithms only count with planes. Creating separate frame_ids for every ring would not help with this issue. Therefore, I'm strongly against re-using the existing LaserScan type for this kind of non-planar information.

  2. The reason why I think a LaserScan-like message is needed, is exactly the timing and reprojection information that can get lost during a transformation to a point cloud. Think about faster mobile robots which can go 1 meter per second or faster. If the scan frequency is 10 Hz, the robot drives around 10 cm during capturing the scan. And you really need to account for this motion during the transformation to a point cloud. Most lidars provide nodes that publish point clouds, but they either use some internal IMU for doing this correction, or they don't do the correction at all... And I feel this is just wrong in case you have some better-grade fast odometry available.

peci1 commented 4 years ago

Velodyne HDL-32E

32 rings, all lasers pointing in the same direction horizontally, vertically evenly spaced by 4/3° around -10° direction. Firing sequence is irregular in angles, and regular in time offsets (only 1 laser firing at a time, the 32 rings are collected sequentially). The single firing sequence consists of 32 cycles of 1.152μs followed by 8 dead cycles of 1.152μs. Horizontal angle can be interpolated for higher precision given the time offsets and assuming a constant rotational speed of the lidar.

Possible output channels: X, Y, Z, Intensity, Ring. Supports dual output mode (strongest, latest).

Vertical firing pattern: obrazek

peci1 commented 4 years ago

Robosense RS-Lidar 32

32 rings, lasers pointing into different directions both vertically and horizontally. Vertical rays have irregular angle offsets. Timing is a little bit unclear - I've only found docs for the 16-beam version. in the 16-beam version, there are 3 us per firing (times 16) plus 2 us recharge time, giving 50 us per firing pattern.

Vertical angle distribution: obrazek

Vertical firing pattern: obrazek

Horizontal firing pattern: obrazek

Possible output channels: X, Y, Z, Intensity. Supports dual output mode (strongest, latest).

peci1 commented 4 years ago

Ouster OS1 64-beam

64 rings, lasers pointing to different directions both vertically and horizontally. Vertical rays have regular offsets, horizontal rays have partly-regular periodic offsets. Timing-wise, it should be a solid-state multi-beam lidar in the vertical direction, so all points in a firing sequence should have the same timestamp. Nevertheless, the docs say the minimum length of the firing pattern is 50 us.

What's interesting here is that the 16-beam version publishes a 64-ring pointcloud, where the excess rings are filled with zeros...

Possible output channels: X, Y, Z, ring, intensity, timestamp, reflectivity, noise, range.

Vertical firing pattern: obrazek

Horizontal firing pattern: obrazek

HappySamuel commented 4 years ago

Hi

Is there a way to filter out those zeros points in the pointcloud (64 layers)? As i am using a OS1-16.

Best, Samuel

peci1 commented 4 years ago

@HappySamuel This is not the right place to ask. Please, ask the Ouster lidar support. Generally, a LaserScan message can contain many values, but only those inside its specified range are considered valid.

HappySamuel commented 4 years ago

Hi @peci1

Ok, i will ask for the ouster lidar support.

Best, Samuel

peci1 commented 1 year ago

Here's a working draft of a package implementing the proposed messages: https://github.com/peci1/multilayer_laser_scan .