GithubHelp home page GithubHelp logo

ros-drivers / ros2_ouster_drivers Goto Github PK

View Code? Open in Web Editor NEW
134.0 9.0 78.0 239 KB

ROS2 Drivers for the Ouster OS-0, OS-1, and OS-2 Lidars

Home Page: https://ouster.com/

License: Apache License 2.0

CMake 1.30% C++ 95.70% Python 2.99%
ros ros2 ouster-sensor ouster drivers

ros2_ouster_drivers's Introduction

ROS2 Ouster Drivers

These are an implementation of ROS2 drivers for the Ouster lidar. This includes all models of the OS-x from 16 to 128 beams running the firmware 2.2-2.4. This is a legacy driver for those deploying within their applications. For new applications, we recommend checking out Ouster's newly supported ROS 2 driver which we have also validated works well.

You can find a few videos looking over the sensor below. They both introduce the ROS1 driver but are extremely useful references regardless:

OS-1 Networking Setup OS-1 Data Overview
IMAGE ALT TEXT HERE IMAGE ALT TEXT HERE

Documentation

Documentation can be generated using Doxygen.

Run doxygen in the root of this repository. It will generate a /doc/* directory containing the documentation. Entrypoint in a browser is index.html.

Design

See design doc in design/* directory here.

ROS Interfaces

Topic Type Description
scan sensor_msgs/LaserScan 2D laser scan of the 0-angle ring
range_image sensor_msgs/Image Image of the range values from the sensor
intensity_image sensor_msgs/Image Image of the Intensity values from the sensor
noise_image sensor_msgs/Image Image of the noise values from the sensor
reflectivity_image sensor_msgs/Image Image of the reflectivity values from the sensor
points sensor_msgs/PointCloud2 3D Pointcloud generated from a 360 rotation
imu sensor_msgs/Imu IMU values at transmission rate
Service Type Description
reset std_srvs/Empty Reset the sensor's connection
GetMetadata ouster_msgs/GetMetadata Get information about the sensor. A optional filepath can be specified to save the metadata to a local file.
Parameter Type Description
lidar_ip String IP or hostname of lidar (ex. 10.5.5.87, os1-serialno.local)
computer_ip String IP or hostname of computer to get data (ex. 10.5.5.1) or broadcast (ex. 255.255.255.255) or if using the default driver, "" for automatic detection
lidar_mode String Mode of data capture, default 512x10
imu_port int Port of IMU data, default 7503
lidar_port int Port of laser data, default 7502
sensor_frame String TF frame of sensor, default laser_sensor_frame
laser_frame String TF frame of laser data, default laser_data_frame
imu_frame String TF frame of imu data, default imu_data_frame
ethernet_device String An ethernet device (e.g. eth0 or eno1) on which the Tins driver will listen for packets. Note that this is only a parameter for the Tins driver, and is only specified in the config file for that driver.
use_system_default_qos bool Publish data with default QoS for rosbag2 recording, default False
timestamp_mode String Method used to timestamp measurements, default TIME_FROM_INTERNAL_OSC
os1_proc_mask String Mask encoding data processors to activate, default IMG | PCL | IMU | SCAN
pointcloud_filter_zero_points bool Reduce pointcloud size by omitting (0, 0, 0) points, default False. If used, will make the PC2 unstructured.

Note: TF will provide you the transformations from the sensor frame to each of the data frames.

Timestamp Modes

Referring to the parameter table above, the timestamp_mode parameter has four allowable options (as of this writing). They are: TIME_FROM_INTERNAL_OSC, TIME_FROM_SYNC_PULSE_IN, TIME_FROM_PTP_1588, TIME_FROM_ROS_RECEPTION. A description of each now follows.

TIME_FROM_INTERNAL_OSC

Use the LiDAR internal clock. Measurements are time stamped with ns since power-on. Free running counter based on the sensor’s internal oscillator. Counts seconds and nanoseconds since sensor turn on, reported at ns resolution (both a second and nanosecond register in every UDP packet), but min increment is on the order of 10 ns. Accuracy is +/- 90 ppm.

TIME_FROM_SYNC_PULSE_IN

A free running counter synced to the SYNC_PULSE_IN input counts seconds (# of pulses) and nanoseconds since sensor turn on. If multipurpose_io_mode is set to INPUT_NMEA_UART then the seconds register jumps to time extracted from a NMEA $GPRMC message read on the multipurpose_io port. Reported at ns resolution (both a second and nanosecond register in every UDP packet), but min increment is on the order of 10 ns. Accuracy is +/- 1 s from a perfect SYNC_PULSE_IN source.

TIME_FROM_PTP_1588

Synchronize with an external PTP master. A monotonically increasing counter that will begin counting seconds and nanoseconds since startup. As soon as a 1588 sync event happens, the time will be updated to seconds and nanoseconds since 1970. The counter must always count forward in time. If another 1588 sync event happens the counter will either jump forward to match the new time, or slow itself down. It is reported at ns resolution (there is both a second and nanosecond register in every UDP packet), but the minimum increment varies. Accuracy is +/- <50 us from the 1588 master.

TIME_FROM_ROS_RECEPTION

The sensor will run in TIME_FROM_INTERNAL_OSC time mode but data are stamped with the ROS time when they are received. The inherent latency between when the data were sampled by the LiDAR and when the data were received by this ROS node is not modelled. This approach may be acceptable to get up and running quickly or for static applications. However, for mobile robots, particularly those traveling at higher speeds, it is not recommended to use this timestamp_mode. When running in this mode, the on-LiDAR timestamp_mode will not be set by this driver.

Parameterizing the Active Data Processors

The os1_proc_mask parameter is set to a mask-like-string used to define the data processors that should be activated upon startup of the driver. This will determine the topics that are available for client applications to consume. The de facto reference for these values are defined in processor_factories.hpp. It is recommended to only use the processors that you require for your application.

The available data processors are:

  • IMG Provides 8-bit image topics encoding the noise, range, intensity, and reflectivitiy from a scan.
  • PCL Provides a point cloud encoding of a LiDAR scan
  • IMU Provides a data stream from the LiDAR's integral IMU
  • SCAN Provides a 2D LaserScan from the closest to 0-degree azimuth ring

To construct a valid string for the os1_proc_mask parameter, join the tokens from above (in any combination) with the pipe character (|). For example, valid strings include but are not limited to: IMG|PCL, IMG|PCL|IMU, PCL, etc. The default value is IMG|PCL|IMU|SCAN.

More details about data processors in the driver is provided in the Additional Lidar Processing section below.

Extensions

This package was intentionally designed for new capabilities to be added. Whether that being supporting new classes of Ouster lidars (sensor-custom, OS2, ...) or supporting new ways of processing the data packets.

Additional Lidar Processing

It can be imagined that if you have a stream of lidar or IMU packets, you may want to process them differently. If you're working with a high speed vehicle, you may want the packets projected into a pointcloud and published with little batching inside the driver. If you're working with pointclouds for machine learning, you may only want the pointcloud to include the XYZ information and not the intensity, reflectivity, and noise information to reduce dimensionality.

In any case, I provide a set of logical default processing implementations on the lidar and IMU packets. These are implementations of the ros2_ouster::DataProcessorInterface class in the interfaces directory. To create your own processor to change the pointcloud type, buffering methodology, or some new cool thing, you must create an implementation of a data processor.

After creating your implementation, that will take in a uint8_t * of a data packet and accomplish your task, you will need to create a factory method for it in processor_factories.hpp and add it to the list of processors to be created in the createProcessors method.

I encourage you to contribute back any new processor methods to this project! The default processors will buffer 1 full rotation of data of the pointcloud and publish the pointcloud with the X, Y, Z, range, intensity, reflectivity, ring, and noise information. It will also buffer a full rotation and publish the noise, intensity, and reflectivity images. Finally, it will publish the IMU data at transmission frequency.

Some examples:

  • If you wanted the points at transmission frequency to reduce aliasing
  • Different types of pointclouds published containing a subset or additional information.
  • If you wanted the information in another format (ei 1 data image with 3 channels of the range, intensity, and noise)
  • Downsample the data at a driver level to only take every Nth ring.

Additional Lidar Units

To create a new lidar for this driver, you only need to make an implementation of the ros2_ouster::SensorInterface class and include any required SDKs. Then, in the driver_types.hpp file, add your new interface as a template of the OusterDriver and you're good to go.

You may need to add an additional main method for the new templated program, depending if you're using components. If it uses another underlying SDK other than sensor you will also need to create new processors for it as the processors are bound to a specific unit as the data formatting may be different. If they are the same, you can reuse the sensor processors.

Lifecycle

This ROS2 driver makes use of Lifecycle nodes. If you're not familiar with lifecycle, or managed nodes, please familiarize yourself with the ROS2 design document on it.

The lifecycle node allow for the driver to have a deterministic setup and tear down and is a new feature in ROS2. The launch script will need to use a lifecycle node launcher to transition into the active state to start processing data.

Component

This ROS2 driver makes use of Component nodes. If you're not familiar with component nodes please familiarize yourself with the ROS2 design document on it.

The component node allow for the driver and its processing nodes to be launched into the same process and is a new feature in ROS2. This allows the sensor and its data clients to operate without serialization or copying between nodes sharing a memory pool.

There's a little work in ROS2 Eloquent to launch a component-lifecycle node using only the roslaunch API. It may be necessary to include the Ouster driver in your lifecycle manager to transition into the active state when loading the driver into a process as a component. Example using the ROS2 component manager:

# component manager for dynamic loading (also may be done through launch)
ros2 run rclcpp_components component_container
# load this component
ros2 component load /ComponentManager ros2_ouster ros2_ouster::OS1Driver
# Set parameters
ros2 param set OusterDriver lidar_ip 10.5.5.86
ros2 param set OusterDriver computer_ip 10.5.5.1
# transition to configuring lifecycle stage
ros2 lifecycle set OusterDriver 1
# transition to active lifecycle stage (will now stream data)
ros2 lifecycle set OusterDriver 3

Ouster Messages

A message Metadata was created to describe the metadata of the lidars. In addition the GetMetadata service type will be used to get the metadata from a running driver.

Setup and Networking

Ouster gives you some tools to set up a direct connection to the sensor from you computer. I'd argue these are a bit obtuse and they should really provide a set of scripts to set this up automatically as a daemon. However, since I am also using this as a development tool, I don't want this always running in the background on my machines so I provide the directions below to setup the network connection.

One time setup with IPv4

These are bash commands in Linux to setup the connection. These steps only need to happen the first time you set up the laser. After the first time, when you establish the network connection to the sensor, you can just select this created network profile. Ensure the sensor is powered off and disconnected at this point.

The [eth name] is the nework interface you're connecting to. On older Linux systems, that's eth0 or similar. In newer versions, its enp... or enx... when you look at the output of ifconfig.

 ip addr flush dev [eth name]
 ip addr show dev [eth name]

The output you see from show should look something like [eth name] ... state DOWN .... Its only important that you see DOWN and not UP. Next, lets setup a static IP address for your machine so you can rely on this in the future. Ouster uses the 10.5.5.* range, and I don't see a compelling reason to argue with it.

sudo ip addr add 10.5.5.1/24 dev [eth name]

Now, lets setup the connection. At this point you may now plug in and power on your sensor.

sudo ip link set [eth name] up
sudo addr show dev [eth name]

The output you see from show should look something like [eth name] ... state UP .... Its only important that you see UP now and not DOWN. At this point, you've setup the networking needed for the one time setup.

Connection with IPv4

We can setup the network connection to the sensor now with the proper settings. Note: This command could take up to 30 seconds to setup, be patient. If after a minute you see no results, then you probably have an issue. Start the instructions above over. Lets set up the network

sudo dnsmasq -C /dev/null -kd -F 10.5.5.50,10.5.5.100 -i [eth name] --bind-dynamic

Instantly you should see something similar to:

dnsmasq: started, version 2.75 cachesize 150
dnsmasq: compile time options: IPv6 GNU-getopt DBus i18n IDN DHCP DHCPv6 no-Lua TFTP conntrack ipset auth DNSSEC loop-detect inotify
dnsmasq-dhcp: DHCP, IP range 10.5.5.50 -- 10.5.5.100, lease time 1h
dnsmasq-dhcp: DHCP, sockets bound exclusively to interface enxa0cec8c012f8
dnsmasq: reading /etc/resolv.conf
dnsmasq: using nameserver 127.0.1.1#53
dnsmasq: read /etc/hosts - 10 addresses

You need to wait until you see something like:

dnsmasq-dhcp: DHCPDISCOVER(enxa0cec8c012f8) [HWaddr]
dnsmasq-dhcp: DHCPOFFER(enxa0cec8c012f8) 10.5.5.87 [HWaddr]
dnsmasq-dhcp: DHCPREQUEST(enxa0cec8c012f8) 10.5.5.87 [HWaddr]
dnsmasq-dhcp: DHCPACK(enxa0cec8c012f8) 10.5.5.87 [HWaddr] os1-SerialNumXX

Now you're ready for business. Lets see what IP address it's on (10.5.5.87). Lets ping it

ping 10.5.5.87

and we're good to go!

Using IPv6 with link local

Instead of having to configure dnsmasq and static addresses in the previous section, you can use link local IPv6 addresses.

  1. Find the link local address of the Ouster. With avahi-browse, we can find the address of the ouster by browsing all non-local services and resolving them.
$ avahi-browse -arlt
+   eth2 IPv6 Ouster Sensor 992109000xxx                    _roger._tcp          local
+   eth2 IPv4 Ouster Sensor 992109000xxx                    _roger._tcp          local
=   eth2 IPv6 Ouster Sensor 992109000xxx                    _roger._tcp          local
   hostname = [os-992109000xxx.local]
   address = [fe80::be0f:a7ff:fe00:2861]
   port = [7501]
   txt = ["fw=ousteros-image-prod-aries-v2.0.0+20201124065024" "sn=992109000xxx" "pn=840-102144-D"]
=   eth2 IPv4 Ouster Sensor 992109000xxx                    _roger._tcp          local
   hostname = [os-992109000xxx.local]
   address = [192.168.90.2]
   port = [7501]
   txt = ["fw=ousteros-image-prod-aries-v2.0.0+20201124065024" "sn=992109000xxx" "pn=840-102144-D"]

As shown above, on interface eth2, the ouster has an IPv6 link local address of fe80::be0f:a7ff:fe00:2861.

To use link local addressing with IPv6, the standard way to add a scope ID is appended with a % character like so in sensor.yaml. Automatic detection for computer IP address can be used with an empty string.

lidar_ip: "fe80::be0f:a7ff:fe00:2861%eth2"
computer_ip: ""

Note that this feature is only available with the default driver version, configured by driver_config.yaml. When running the Tins-based driver (see the following sections), both the LiDAR and computer IP address must be specified in tins_driver_config.yaml.

Usage with the default driver

Now that we have a connection over the network, lets view some data. After building your colcon workspace with this package, source the install space, then run:

ros2 launch ros2_ouster driver_launch.py

Make sure to update your parameters file if you don't use the default IPs (10.5.5.1, 10.5.5.87). You may also use the .local version of your ouster lidar. To find your IPs, see the dnsmasq output or check with nmap -SP 10.5.5.*/24. An alternative tool is avahi-browse:

avahi-browse -arlt

Now that your connection is up, you can view this information in RViz. Open an RViz session and subscribe to the points, images, and IMU topics in the laser frame. When trying to visualize the point clouds, be sure to change the Fixed Frame under Global Options to "laser_data_frame" as this is the default parent frame of the point cloud headers.

When the driver configures itself, it will automatically read the metadata parameters from the Ouster. If you wish to save these parameters and use them with captured data (see the next section) then you can save the data to a specific location using the getMetadata service that the driver offers. To use it, run the driver with a real Ouster LiDAR and then make the following service call:

ros2 service call /ouster_driver/get_metadata ouster_msgs/srv/GetMetadata "{metadata_filepath: "/path/to/your/metadata.json"}"

The driver will then save all the required metadata to the specified file and dump the same metadata as a JSON string to the terminal. Alternatively, the service can be called without specifying a filepath (see below) in which case no file will be saved, and the metadata will still be printed to terminal. Copying this string and manually saving it to a .json file is also a valid way to generate a metadata file.

ros2 service call /ouster_driver/get_metadata ouster_msgs/srv/GetMetadata

Have fun!

Usage with Tins-based driver

If you want to use the driver to read data from a pcap file, you can use the Tins-based driver. To do this, open the tins_driver_config.yaml file and edit the following parameter:

  • ethernet_device: Change this to a working ethernet device on your computer that you plan to replay data through (e.g. "eth1").

You can run the Tins driver with the command below. This will use the default ouster_os0128_1024_metadata.json file:

ros2 launch ros2_ouster tins_driver_launch.py

Alternatively, you can change the metadata being used by specifying the metadata filepath as shown below. You can generate a metadata file using the getMetadata service as shown in the previous section. Or you can use one of the example metadata files provided, which come from an Ouster OS0-128 in either 1024x10 or 2048x10 mode.

ros2 launch ros2_ouster tins_driver_launch.py metadata_filepath:=/path/to/metadata.json

After launching the driver, in a new terminal, you can replay a pcap file of recorded ouster data using the following command (as an example):

sudo tcpreplay --intf1=eth1 saved_ouster_data.pcap

You may need to run this command with sudo. Note that this driver version will also work with a live Ouster sensor, provided the data is coming into the correct ethernet device, and the parameters in the metadata file match those of the sensor. However it is recommended that you run the default drive with a real sensor, as this will guarantee that the metadata settings are correct.

ros2_ouster_drivers's People

Contributors

ahcorde avatar bertaveira avatar clalancette avatar cottsay avatar jlbicho avatar jonbakerfish avatar luhuadong avatar mattsyoung avatar maxandreogeret avatar rfriedm-trimble avatar rotu avatar simonwaterer avatar splatter96 avatar stevemacenski avatar tpanzarella avatar vinnnyr avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

ros2_ouster_drivers's Issues

Don't use IP addresses in params file

Right now, the default addresses are hardcoded unicast IPV4 addresses. It would be nice to change this for usability:

  1. The lidar advertises itself as os1-############.local, where the # are the serial number printed on the device. It would be nice to use this hostname instead of the IP address, which may change with a particular hardware setup.

  2. The lidar supports more robust destination addresses: multicast with address 255.255.255.255, ff02::01 or unicast with set_udp_dest_auto.

https://github.com/SteveMacenski/ros2_ouster_drivers/blob/ed188b388e09c9fab54aed21855ba04fcf6c3c08/ros2_ouster/params/os1.yaml#L3-L4

OS1 lidar outputs a single points packet instead of full PointCloud2

Hello,
My team and I have been using 3 OS1 lidars without much issues in ROS1, until we recently decided to migrate to ROS2. We are using ROS2 Eloquent, on Ubuntu 18.04, with the default DDS implementation (Fast RTPS).
When we launch the ouster node, it publishes the full point cloud for a few seconds, but afterwards it publishes what seems to be only a part of the full point cloud at a time. We suspect it to be publishing only a single packet (about 300 points), but we are not sure about this. We tried using CycloneDDS, but we have the same results.
We used ros2 topic hz to get the publish rate, it was between 180 Hz and 400 Hz, when it should be 10 Hz.

Here is a gif with what we see on Rviz :
VID_20201203_113527

Unable to connect with firmware 2.0

Hello,

I use ros dashing. and my Lidar has the firmware 2.0 and a static ip.
I have installed the driver using apt.
I have configured the yaml file correctly :

ouster_driver:
  ros__parameters:
    lidar_ip: 192.168.3.200
    computer_ip: 192.168.3.100
    lidar_mode: "512x10"
    imu_port: 7503
    lidar_port: 7502
    sensor_frame: laser_sensor_frame
    laser_frame: laser_data_frame
    imu_frame: imu_data_frame

But when I try to run the launch file I get this error :

[INFO] [launch]: All log files can be found below /home/student/.ros/log/2021-01-06-15-50-00-467613-HPZ1-17665
[INFO] [launch]: Default logging verbosity is set to INFO
[INFO] [ouster_driver-1]: process started with pid [17675]
[ouster_driver-1] [INFO] [ouster_driver]: Configuring Ouster driver node.
[ouster_driver-1] [INFO] [ouster_driver]: Connecting to sensor at 192.168.3.200.
[ouster_driver-1] [INFO] [ouster_driver]: Broadcasting data from sensor to 192.168.3.100.
[ouster_driver-1] [ERROR] []: Caught exception in callback for transition 10
[ERROR] [launch_ros.actions.lifecycle_node]: Failed to make transition 'TRANSITION_CONFIGURE' for LifecycleNode '/ouster_driver'
[ouster_driver-1] [ERROR] []: Original error: vector::_M_range_check: __n (which is 0) >= this->size() (which is 0)
[ouster_driver-1] [WARN] []: Error occurred while doing error handling.
[ouster_driver-1] [ERROR] [ouster_driver]: Handing error in Ouster driver node.

Any idea what could be the problem ? It works perfectly with ROS1.

Thanks !

In-memory data layout

In #46 I outlined some puzzling issues as it relates to how the driver organizes its in-memory data buffers. I created this notebook to more clearly articulate the issue and its downstream effects.

I'd like to use this issue to discuss this topic and come to a consensus on a path forward. I am happy to take on the work to play with some potential implementations and see how it affects, among other things, the performance of the system.

As is more completely articulated in the notebook linked to above, the current in-memory data layout has implications for performance, usability, and correctness. Per the latter, given how the data are laid out in memory an argument could be made that the meta-data on the point cloud is inconsistent with these data and could be considered a bug. I think as it stands today, users who simply use the PointCloud2 and/or PCL interfaces to these data may be insulated from those issues. However, users developing deeper perception algorithms that access the array data directly, and assume it is modeled consistent with the LiDAR physically, will certainly be affected.

Let's discuss openly and come to consensus.

Rviz2 show 0 messages of topic /points

Hi,

I can see the data on ros2 topic echo /points but in Rviz2 I can't see it. Rviz notified that 0 messages arrived.
I tried to reinstall rviz2 but hadn't solved.
If I opened it with rviz of ROS1 (by the bridge pkg) I can see the point clouds.
Do you know what is the reason for that problem?

Aviad

TCP configuration can hang with no warning

The ouster does not handle simultaneous TCP connections to the same driver well. It queues responses and only serves one connection at a time.
If a user accidentally has a TCP connection already open to an ouster, say from doing manual configuration, or running two drivers, the ouster accepts both TCP connection but doesn't respond to any commands in do_tcp_cmd to the ROS2 driver.

Thus, the driver hangs and doesn't start up the rest of the topics. No warning is given to the user of this condition. The timeout should still apply if the TCP connection is accepted but no data is returned.

To reproduce: Start a netcat session with the ouster and leave that running. Then, start the ROS2 driver.

Can't launch by the source code

Hey,

ros-distro : eloquent

I clone the code and made colcon build.
I set inside the yaml file the right IPs.
When I tried to launch the driver by ros2 launch ros2_ouster os1_launch.py I got this error:

[INFO] [launch]: Default logging verbosity is set to INFO
[ERROR] [launch]: Caught exception in launch (see debug for traceback): Caught exception when trying to load file of format [py]: init() missing 1 required keyword-only argument: 'node_name

Thanks for your help,
Aviad

Unable to connect to the lidar - Address already in use

Hello,

I use ros dashing. and my Lidar has the firmware 2.0 and a static ip.
I have configured the yaml file correctly :

ouster_driver:
  ros__parameters:
    lidar_ip: 192.168.3.200
    computer_ip: 192.168.3.100
    lidar_mode: "512x10"
    imu_port: 7503
    lidar_port: 7502
    sensor_frame: laser_sensor_frame
    laser_frame: laser_data_frame
    imu_frame: imu_data_frame

But when I try to run the launch file I get this error :

[INFO] [launch]: All log files can be found below /home/student/.ros/log/2021-01-06-15-25-28-707071-HPZ1-14468
[INFO] [launch]: Default logging verbosity is set to INFO
[INFO] [ouster_driver-1]: process started with pid [14478]
[ouster_driver-1] [INFO] [ouster_driver]: Configuring Ouster driver node.
[ouster_driver-1] [INFO] [ouster_driver]: Connecting to sensor at 192.168.3.200.
[ouster_driver-1] [INFO] [ouster_driver]: Broadcasting data from sensor to 192.168.3.100.
[ouster_driver-1] udp bind(): Address already in use
[ouster_driver-1] udp bind(): Address already in use
[ERROR] [launch_ros.actions.lifecycle_node]: Failed to make transition 'TRANSITION_CONFIGURE' for LifecycleNode '/ouster_driver'
[ouster_driver-1] [ERROR] []: Caught exception in callback for transition 10
[ouster_driver-1] [ERROR] []: Original error: vector::_M_range_check: __n (which is 0) >= this->size() (which is 0)
[ouster_driver-1] [WARN] []: Error occurred while doing error handling.
[ouster_driver-1] [ERROR] [ouster_driver]: Handing error in Ouster driver node.

Any idae what could be the problem ? It works perfectly with ROS1.

Thanks !

/scan topic always has 0 values for range and intensity

Issue: /scan(Laser Scan) topic always has zero values in range and intensity.
OS: Ubuntu 20.04
ROS2: Foxy
Sensor: OS-32
Steps to reproduce:

  1. Clone the repository inside src of a ROS2 workspace
    git clone -b foxy-devel https://github.com/ros-drivers/ros2_ouster_drivers.git
  2. Follow the steps mentioned in the readme file to set up the sensor
  3. The Mode that was tried where 1024x10 or 512x10. These were set in the os1.yaml file.
  4. Ensure that SCAN is present in os1_proc_mask os1_proc_mask: IMG|PCL|IMU|SCAN
  5. Run ros2 launch ros2_ouster os1_launch.py
  6. Open RVIZ and add set the frame to laser_sensor_frame
  7. Add Pointcloud and Laser scan topic to the display panel.
    See PointCloud in /points topic.
    image

See No Laserscan in /scan topic.
image

Sample ROS topic echo of /scan

header:
  stamp:
    sec: 1812
    nanosec: 946384100
  frame_id: laser_data_frame
angle_min: -3.1415927410125732
angle_max: 3.1415927410125732
angle_increment: 0.006135923322290182
time_increment: 9.765625145519152e-05
scan_time: 0.10000000149011612
range_min: 0.10000000149011612
range_max: 120.0
ranges:
- 0.0
- 0.0
- 0.0
- 0.0
- 0.0
- 0.0
- 0.0
- 0.0
- 0.0
- 0.0
- 0.0
- 0.0
<More zeros>
intensities:
- 0.0
- 0.0
- 0.0
- 0.0
- 0.0
- 0.0
- 0.0
- 0.0
- 0.0
- 0.0
- 0.0
- 0.0
- 0.0
- 0.0
- 0.0
- 0.0
- 0.0
- 0.0
- 0.0
- 0.0
- 0.0
<More zeros>

Ethernet device throughput limits driver output

As discussed in Issue #74, the depending on what mode (512x10, 1024x10, 2048x10 etc) the Ouster is in, the data rate is different. This can cause problems on systems that have an ethernet connection limited to 100 Mbit/s, as in some higher resolution modes, the packet data from the Ouster can exceed this Mbit/s limit. Specific examples include:

  • An Ouster OS0-128 in 1024x10 mode will generate ~124 Mbit/s
  • An Ouster OS0-128 in 2048x10 mode will generate ~248 Mbit/s

When this issue occurs, the output rate of the /points topic will not reach the target 10 or 20 Hz, and (at present) the driver will provide no warning to the user.

I would like to add code to:

  • Calculate the expected packet rate, from the given LiDAR mode
  • Calculate the actual incoming packet rate
  • Compare expected vs actual packet rates and warn the user if the target rate is not being met

Use of diagnostic aggregator package

Use the ROS diagnostics to give info about the sensor on the diagnostics topic for debug. This is common for drivers to use to report issues for later debugging and error handling.

The original ROS1 drivers and the CPFL fork didnt implement them, but this would be a good feature for someone to add.

When using Cyclone DDS topics aren’t being subscribed

Hi ,

I recently attached an Ouster lidar to a robot running on an Intel NUC.
With the default rmw of ros foxy, I am able to capture the cloud and view it in RVIZ. I want however process the cloud on another machine, the machine and intel NUC are on same network, all topics and nodes are discoverable mutually between these two.

When I view the cloud on rviz on remote machine, the cloud reaches partially(maybe due to size ).

I changed default DDS to Cyclone DDS to see if it can deal with the problem. However when rmw is set to Cyclone DDS, none of the topics published by the driver are subscribe-able, I checked all Qos compatibilities, ros2 topic echo to any topic by driver hangs without printing anything

I test demo talker and listener nodes and some other nodes when in Cyclone DDS they all work as intended.

Any recommendations ?
Has someone run this driver in a similar setup or non-default DDS ?

Document working with OS-0 and OS-2 (non-128 beam models) in readme

May be worth removing "OS1" across code naming. It appears that the OS0 and OS2 use the same interfaces and data formatting. There's no special changes needed for supporting all the sensors.

There's an open question on the 128 beam model. We need to think about how to support that, but first need code samples from Ouster themselves

Register driver node as component

This would ordinarily be easy, however because the driver is templated to allow for multiple future implementations of Ouster sensors (or new variants, or even other vendors with a similar interface) the class loader that deals with the components under the hood yields the following warning:

[ouster_driver-1] Warning: class_loader.impl: SEVERE WARNING!!! A namespace collision has occured with plugin factory for class rclcpp_components::NodeFactoryTemplate<ros2_ouster::OS1Driver>. New factory will OVERWRITE existing one. This situation occurs when libraries containing plugins are directly linked against an executable (the one running right now generating this message). Please separate plugins out into their own library or just don't link against the library and use either class_loader::ClassLoader/MultiLibraryClassLoader to open.
[ouster_driver-1]          at line 238 in /opt/ros/eloquent/include/class_loader/class_loader_core.hpp

Given its a warning, and the collision I'm not sure tangibly impacts performance as long as each component is loaded into another process, I don't think its a show-stopper if you need it. However it is ugly and should be resolved.

I've commented out the registration macros in the driver_types.hpp and CMakeLists.txt files for now until this is resolved or looked at further.

Request to give ROS2 Master branch support.

Currently, I see that the last code commit for the driver is a few months old and I believe it is not much of an effort to maintain a ROS2 Master branch that can compile with the latest ROS2. I would have helped but I am not very good at writing C++ drivers for ROS2.

OS: Ubuntu 20.04
ROS2: Master Branch
Sensor: OS-32

Steps to reproduce:

  • Build ROS2 from source selecting the Master branch.
    https://index.ros.org/doc/ros2/Installation/Foxy/Linux-Development-Setup/
  • git clone https://github.com/ros-drivers/ros2_ouster_drivers.git
  • Ouster_msgs compiles successfully colcon build --symlink-install --packages-select ouster_msgs
  • ros2_ouster throws errors colcon build --symlink-install --packages-select ros2_ouster

It is a long trace but just posting a part of it.

In file included from /home/bautomation/ros_ws_foxy/ros2_ws/install/geometry_msgs/include/geometry_msgs/msg/detail/pose_with_covariance_stamped__traits.hpp:19,
                 from /home/bautomation/ros_ws_foxy/ros2_ws/install/geometry_msgs/include/geometry_msgs/msg/pose_with_covariance_stamped.hpp:9,
                 from /home/bautomation/ros_ws_foxy/ros2_ws/install/tf2_geometry_msgs/include/tf2_geometry_msgs/tf2_geometry_msgs.h:45,
                 from /home/bautomation/ba_pontoon_ros2/src/ros2_ouster_drivers/ros2_ouster/include/ros2_ouster/conversions.hpp:33,
                 from /home/bautomation/ba_pontoon_ros2/src/ros2_ouster_drivers/ros2_ouster/include/ros2_ouster/ouster_driver.hpp:21,
                 from /home/bautomation/ba_pontoon_ros2/src/ros2_ouster_drivers/ros2_ouster/include/ros2_ouster/driver_types.hpp:17,
                 from /home/bautomation/ba_pontoon_ros2/src/ros2_ouster_drivers/ros2_ouster/src/driver_types.cpp:18:
/home/bautomation/ros_ws_foxy/ros2_ws/install/geometry_msgs/include/geometry_msgs/msg/detail/pose_with_covariance__traits.hpp: In function ‘void rosidl_generator_traits::to_yaml(const PoseWithCovariance&, std::ostream&, size_t)’:
/home/bautomation/ros_ws_foxy/ros2_ws/install/geometry_msgs/include/geometry_msgs/msg/detail/pose_with_covariance__traits.hpp:49:9: error: ‘value_to_yaml’ was not declared in this scope
   49 |         value_to_yaml(item, out);
      |         ^~~~~~~~~~~~~
/home/bautomation/ba_pontoon_ros2/install/ouster_msgs/include/ouster_msgs/msg/detail/metadata__traits.hpp:148:5: error: ‘value_to_yaml’ was not declared in this scope
  148 |     value_to_yaml(msg.firmware_rev, out);
      |     ^~~~~~~~~~~~~
/home/bautomation/ba_pontoon_ros2/install/ouster_msgs/include/ouster_msgs/msg/detail/metadata__traits.hpp:158:5: error: ‘value_to_yaml’ was not declared in this scope
  158 |     value_to_yaml(msg.imu_port, out);
      |     ^~~~~~~~~~~~~
/home/bautomation/ba_pontoon_ros2/install/ouster_msgs/include/ouster_msgs/msg/detail/metadata__traits.hpp:168:5: error: ‘value_to_yaml’ was not declared in this scope
  168 |     value_to_yaml(msg.lidar_port, out);
      |     ^~~~~~~~~~~~~
In file included from /home/bautomation/ba_pontoon_ros2/install/ouster_msgs/include/ouster_msgs/msg/metadata.hpp:9,
                 from /home/bautomation/ba_pontoon_ros2/src/ros2_ouster_drivers/ros2_ouster/include/ros2_ouster/conversions.hpp:34,
                 from /home/bautomation/ba_pontoon_ros2/src/ros2_ouster_drivers/ros2_ouster/include/ros2_ouster/ouster_driver.hpp:21,
                 from /home/bautomation/ba_pontoon_ros2/src/ros2_ouster_drivers/ros2_ouster/include/ros2_ouster/driver_types.hpp:17,
                 from /home/bautomation/ba_pontoon_ros2/src/ros2_ouster_drivers/ros2_ouster/src/driver_types.cpp:18:
/home/bautomation/ba_pontoon_ros2/install/ouster_msgs/include/ouster_msgs/msg/detail/metadata__traits.hpp: In function ‘void rosidl_generator_traits::to_yaml(const Metadata&, std::ostream&, size_t)’:
/home/bautomation/ba_pontoon_ros2/install/ouster_msgs/include/ouster_msgs/msg/detail/metadata__traits.hpp:28:5: error: ‘value_to_yaml’ was not declared in this scope
   28 |     value_to_yaml(msg.hostname, out);
      |     ^~~~~~~~~~~~~
/home/bautomation/ba_pontoon_ros2/install/ouster_msgs/include/ouster_msgs/msg/detail/metadata__traits.hpp:38:5: error: ‘value_to_yaml’ was not declared in this scope
   38 |     value_to_yaml(msg.lidar_mode, out);
      |     ^~~~~~~~~~~~~
/home/bautomation/ba_pontoon_ros2/install/ouster_msgs/include/ouster_msgs/msg/detail/metadata__traits.hpp:48:5: error: ‘value_to_yaml’ was not declared in this scope
   48 |     value_to_yaml(msg.timestamp_mode, out);
      |     ^~~~~~~~~~~~~
/home/bautomation/ba_pontoon_ros2/install/ouster_msgs/include/ouster_msgs/msg/detail/metadata__traits.hpp:66:9: error: ‘value_to_yaml’ was not declared in this scope
   66 |         value_to_yaml(item, out);
      |         ^~~~~~~~~~~~~
/home/bautomation/ba_pontoon_ros2/install/ouster_msgs/include/ouster_msgs/msg/detail/metadata__traits.hpp:86:9: error: ‘value_to_yaml’ was not declared in this scope
   86 |         value_to_yaml(item, out);
      |         ^~~~~~~~~~~~~
/home/bautomation/ba_pontoon_ros2/install/ouster_msgs/include/ouster_msgs/msg/detail/metadata__traits.hpp:106:9: error: ‘value_to_yaml’ was not declared in this scope
  106 |         value_to_yaml(item, out);
      |         ^~~~~~~~~~~~~
/home/bautomation/ba_pontoon_ros2/install/ouster_msgs/include/ouster_msgs/msg/detail/metadata__traits.hpp:126:9: error: ‘value_to_yaml’ was not declared in this scope
  126 |         value_to_yaml(item, out);
      |         ^~~~~~~~~~~~~
/home/bautomation/ba_pontoon_ros2/install/ouster_msgs/include/ouster_msgs/msg/detail/metadata__traits.hpp:138:5: error: ‘value_to_yaml’ was not declared in this scope
  138 |     value_to_yaml(msg.serial_no, out);
      |     ^~~~~~~~~~~~~
/home/bautomation/ba_pontoon_ros2/install/ouster_msgs/include/ouster_msgs/msg/detail/metadata__traits.hpp:148:5: error: ‘value_to_yaml’ was not declared in this scope
  148 |     value_to_yaml(msg.firmware_rev, out);
      |     ^~~~~~~~~~~~~
/home/bautomation/ba_pontoon_ros2/install/ouster_msgs/include/ouster_msgs/msg/detail/metadata__traits.hpp:158:5: error: ‘value_to_yaml’ was not declared in this scope
  158 |     value_to_yaml(msg.imu_port, out);
      |     ^~~~~~~~~~~~~
/home/bautomation/ba_pontoon_ros2/install/ouster_msgs/include/ouster_msgs/msg/detail/metadata__traits.hpp:168:5: error: ‘value_to_yaml’ was not declared in this scope
  168 |     value_to_yaml(msg.lidar_port, out);
      |     ^~~~~~~~~~~~~
make[2]: *** [CMakeFiles/ouster_driver_core.dir/build.make:102: CMakeFiles/ouster_driver_core.dir/src/OS1/OS1_sensor.cpp.o] Error 1
make[2]: *** [CMakeFiles/ouster_driver_core.dir/build.make:63: CMakeFiles/ouster_driver_core.dir/src/driver_types.cpp.o] Error 1
make[2]: *** [CMakeFiles/ouster_driver_core.dir/build.make:76: CMakeFiles/ouster_driver_core.dir/src/ouster_driver.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:134: CMakeFiles/ouster_driver_core.dir/all] Error 2
make: *** [Makefile:141: all] Error 2

Lifecycle publishers with FastRTPS crashing

I've validated the object exists and is allocated, the messages have been printed and are complete, but a bunch of the time, especially with the PCL-used image / pointcloud publishers it crashes when it tries to publish a message. See traceback below.

I cant tell if its a RMW, ROS, PCL, or my software problem. But its stopping me from being able to publish data other than IMU.

Occasionally I get it to work and I can see in rviz the data is good, so I really don't think its related to the data handling from the lidar.

Thread 1 "ouster_driver" received signal SIGSEGV, Segmentation fault.
do_lookup_x (
    undef_name=undef_name@entry=0x7fffd77cef0a "_ZN11sensor_msgs3msg24typesupport_fastrtps_cpp19get_serialized_sizeERKNS0_4Imu_ISaIvEEEm", 
    new_hash=new_hash@entry=1679295439, old_hash=old_hash@entry=0x7fffffffaa40, 
    ref=0x7fffd77cc208, result=result@entry=0x7fffffffaa50, scope=<optimized out>, 
    i=63, version=0x0, flags=5, skip=0x0, type_class=1, undef_map=0x555555a92450)
    at dl-lookup.c:360
360 dl-lookup.c: No such file or directory.
(gdb) traceback
Undefined command: "traceback".  Try "help".
(gdb) backtrace
#0  do_lookup_x (
    undef_name=undef_name@entry=0x7fffd77cef0a "_ZN11sensor_msgs3msg24typesupport_fastrtps_cpp19get_serialized_sizeERKNS0_4Imu_ISaIvEEEm", 
    new_hash=new_hash@entry=1679295439, old_hash=old_hash@entry=0x7fffffffaa40, 
    ref=0x7fffd77cc208, result=result@entry=0x7fffffffaa50, scope=<optimized out>, 
    i=63, version=0x0, flags=5, skip=0x0, type_class=1, undef_map=0x555555a92450)
    at dl-lookup.c:360
#1  0x00007ffff7de01ef in _dl_lookup_symbol_x (
    undef_name=0x7fffd77cef0a "_ZN11sensor_msgs3msg24typesupport_fastrtps_cpp19get_serialized_sizeERKNS0_4Imu_ISaIvEEEm", undef_map=0x555555a92450, 
    ref=ref@entry=0x7fffffffaae8, symbol_scope=0x555555a927a8, version=0x0, 
    type_class=type_class@entry=1, flags=5, skip_map=<optimized out>)
    at dl-lookup.c:813
#2  0x00007ffff7de4ec3 in _dl_fixup (l=<optimized out>, reloc_arg=<optimized out>)
    at ../elf/dl-runtime.c:112
#3  0x00007ffff7dec7ca in _dl_runtime_resolve_xsavec ()
    at ../sysdeps/x86_64/dl-trampoline.h:125
#4  0x00007fffd77da22b in ?? ()
   from /opt/ros/eloquent/lib/libsensor_msgs__rosidl_typesupport_fastrtps_cpp.so
#5  0x00007ffff0ebb077 in ?? () from /opt/ros/eloquent/lib/librmw_fastrtps_cpp.so
#6  0x00007ffff0a885ad in ?? ()
   from /opt/ros/eloquent/lib/librmw_fastrtps_shared_cpp.so
#7  0x00007ffff0420401 in eprosima::fastrtps::rtps::CacheChangePool::reserve_Cache(eprosima::fastrtps::rtps::CacheChange_t**, std::function<unsigned int ()> const&) ()
   from /opt/ros/eloquent/lib/libfastrtps.so.1
#8  0x00007ffff03ffd82 in eprosima::fastrtps::rtps::RTPSWriter::new_change(std::function<unsigned int ()> const&, eprosima::fastrtps::rtps::ChangeKind_t, eprosima::fastrtps::rtps::InstanceHandle_t) () from /opt/ros/eloquent/lib/libfastrtps.so.1
#9  0x00007ffff0488c3d in eprosima::fastrtps::PublisherImpl::create_new_change_with_params(eprosima::fastrtps::rtps::ChangeKind_t, void*, eprosima::fastrtps::rtps::WriteParams&) () from /opt/ros/eloquent/lib/libfastrtps.so.1
#10 0x00007ffff048b370 in eprosima::fastrtps::PublisherImpl::create_new_change(eprosima::fastrtps::rtps::ChangeKind_t, void*) ()
   from /opt/ros/eloquent/lib/libfastrtps.so.1
#11 0x00007ffff0a8304d in rmw_fastrtps_shared_cpp::__rmw_publish(char const*, rmw_publisher_t const*, void const*, rmw_publisher_allocation_t*) ()
   from /opt/ros/eloquent/lib/librmw_fastrtps_shared_cpp.so
#12 0x00007ffff5a3ae3f in rcl_publish () from /opt/ros/eloquent/lib/librcl.so
#13 0x00007ffff7b4d608 in rclcpp::Publisher<sensor_msgs::msg::Imu_<std::allocator<void> >, std::allocator<void> >::do_inter_process_publish(sensor_msgs::msg::Imu_<std::allocator<void> > const&) ()
   from /home/steve/Documents/ouster_ws2/install/ros2_ouster/lib/libouster_driver_core.so
#14 0x00007ffff7b48120 in rclcpp::Publisher<sensor_msgs::msg::Imu_<std::allocator<void> >, std::allocator<void> >::publish(sensor_msgs::msg::Imu_<std::allocator<void> > const&) ()
   from /home/steve/Documents/ouster_ws2/install/ros2_ouster/lib/libouster_driver_core.so
#15 0x00007ffff7b4346a in rclcpp_lifecycle::LifecyclePublisher<sensor_msgs::msg::Imu_<std::allocator<void> >, std::allocator<void> >::publish(sensor_msgs::msg::Imu_<std::allocator<void> > const&) ()
   from /home/steve/Documents/ouster_ws2/install/ros2_ouster/lib/libouster_driver_co---Type <return> to continue, or q <return> to quit---
re.so
#16 0x00007ffff7b3b6d5 in OS1::IMUProcessor::process(unsigned char*) ()
   from /home/steve/Documents/ouster_ws2/install/ros2_ouster/lib/libouster_driver_core.so
#17 0x00007ffff7b3ec0d in ros2_ouster::OusterDriver<OS1::OS1Sensor>::processData()
    ()
   from /home/steve/Documents/ouster_ws2/install/ros2_ouster/lib/libouster_driver_core.so
#18 0x00007ffff7b85a61 in void std::__invoke_impl<void, void (ros2_ouster::OusterDriver<OS1::OS1Sensor>::*&)(), ros2_ouster::OusterDriver<OS1::OS1Sensor>*&>(std::__invoke_memfun_deref, void (ros2_ouster::OusterDriver<OS1::OS1Sensor>::*&)(), ros2_ouster::OusterDriver<OS1::OS1Sensor>*&) ()
   from /home/steve/Documents/ouster_ws2/install/ros2_ouster/lib/libouster_driver_core.so
#19 0x00007ffff7b8504a in std::__invoke_result<void (ros2_ouster::OusterDriver<OS1::OS1Sensor>::*&)(), ros2_ouster::OusterDriver<OS1::OS1Sensor>*&>::type std::__invoke<void (ros2_ouster::OusterDriver<OS1::OS1Sensor>::*&)(), ros2_ouster::OusterDriver<OS1::OS1Sensor>*&>(void (ros2_ouster::OusterDriver<OS1::OS1Sensor>::*&)(), ros2_ouster::OusterDriver<OS1::OS1Sensor>*&) ()
   from /home/steve/Documents/ouster_ws2/install/ros2_ouster/lib/libouster_driver_core.so
#20 0x00007ffff7b8447b in void std::_Bind<void (ros2_ouster::OusterDriver<OS1::OS1Sensor>::*(ros2_ouster::OusterDriver<OS1::OS1Sensor>*))()>::__call<void, , 0ul>(std::tuple<>&&, std::_Index_tuple<0ul>) ()
   from /home/steve/Documents/ouster_ws2/install/ros2_ouster/lib/libouster_driver_core.so
#21 0x00007ffff7b82b41 in void std::_Bind<void (ros2_ouster::OusterDriver<OS1::OS1Sensor>::*(ros2_ouster::OusterDriver<OS1::OS1Sensor>*))()>::operator()<, void>() ()
   from /home/steve/Documents/ouster_ws2/install/ros2_ouster/lib/libouster_driver_core.so
#22 0x00007ffff7b81508 in void rclcpp::GenericTimer<std::_Bind<void (ros2_ouster::OusterDriver<OS1::OS1Sensor>::*(ros2_ouster::OusterDriver<OS1::OS1Sensor>*))()>, (void*)0>::execute_callback_delegate<std::_Bind<void (ros2_ouster::OusterDriver<OS1::OS1Sensor>::*(ros2_ouster::OusterDriver<OS1::OS1Sensor>*))()>, (void*)0>() ()
   from /home/steve/Documents/ouster_ws2/install/ros2_ouster/lib/libouster_driver_core.so
#23 0x00007ffff7b7f4b4 in rclcpp::GenericTimer<std::_Bind<void (ros2_ouster::OusterDriver<OS1::OS1Sensor>::*(ros2_ouster::OusterDriver<OS1::OS1Sensor>*))()>, (void*)0>::execute_callback() ()
   from /home/steve/Documents/ouster_ws2/install/ros2_ouster/lib/libouster_driver_core.so
#24 0x00007ffff72fdfb5 in rclcpp::executor::Executor::execute_any_executable(rclcpp::executor::AnyExecutable&) () from /opt/ros/eloquent/lib/librclcpp.so
#25 0x00007ffff73046ef in rclcpp::executors::SingleThreadedExecutor::spin() ()
   from /opt/ros/eloquent/lib/librclcpp.so
#26 0x00007ffff73013e2 in rclcpp::spin(std::shared_ptr<rclcpp::node_interfaces::NodeBaseInterface>) () from /opt/ros/eloquent/lib/librclcpp.so
#27 0x00005555555616da in main ()

colcon build fails - No module named 'catkin_pkg'

Hi, there seems to be a problem with ROS2 and colcon. I'm working on Ubuntu 20.04 and ROS2 Foxy. Any idea how to get this to run? I really needs this sensor to run with ROS2.

Here is what I did:

mkdir -p ros2_ws/src
cd ros2_ws/src/
git clone https://github.com/ros-drivers/ros2_ouster_drivers.git
cd ..
colcon build

And here is the error:

Starting >>> ouster_msgs
--- stderr: ouster_msgs
Traceback (most recent call last):
File "/opt/ros/foxy/share/ament_cmake_core/cmake/core/package_xml_2_cmake.py", line 21, in
from catkin_pkg.package import parse_package_string
ModuleNotFoundError: No module named 'catkin_pkg'
CMake Error at /opt/ros/foxy/share/ament_cmake_core/cmake/core/ament_package_xml.cmake:94 (message):
execute_process(/home/invoke7/anaconda3/bin/python3
/opt/ros/foxy/share/ament_cmake_core/cmake/core/package_xml_2_cmake.py
/home/invoke7/Development/ros2_ws/src/ros2_ouster_drivers/ouster_msgs/package.xml
/home/invoke7/Development/ros2_ws/build/ouster_msgs/ament_cmake_core/package.cmake)
returned error code 1
Call Stack (most recent call first):
/opt/ros/foxy/share/ament_cmake_core/cmake/core/ament_package_xml.cmake:49 (_ament_package_xml)
/opt/ros/foxy/share/rosidl_cmake/cmake/rosidl_generate_interfaces.cmake:226 (ament_package_xml)
CMakeLists.txt:9 (rosidl_generate_interfaces)


Failed <<< ouster_msgs [0.86s, exited with code 1]

Summary: 0 packages finished [0.96s]
1 package failed: ouster_msgs
1 package had stderr output: ouster_msgs
1 package not processed

Recommended networking setup does not assign addresses robustly

The current recommendation on dnsmasq setup results in a fragile system since it doesn't result in stable IP addresses.

  1. Without hardware changes, if the DHCP lease expires (e.g. the network connection is down for an hour), the configured address is no longer correct.

  2. If the hardware is swapped out, the lidar will not be reachable at its configured address without additional action.

Here are some mutually exclusive suggestions for ways to fix this:

  • Assign static IP addresses (solves 1, 2 requires additional per-LIDAR setup, Ouster dissuades this)
  • Set up dnsmasq so leases are infinite (solves 1, not 2)
  • Assign an IP address for the device based on MAC address (solves 1, not 2)
  • Constrain the DHCP to assign addresses in a predictable way, emulating static assignment. A description of one such implementation that also requires restricting the physical network. It may be possible to lift some of these restrictions by making dnsmasq use, e.g. a certain pool for certain vendor types. (solves 1 and 2)

`lidar_ip` and `computer_ip` need better naming and/or documentation

lidar_ip and computer_ip have similar names and are documented analogously to each other. This makes the following caveats unexpected:

  • lidar_ip can be a IP address or a hostname. The name suggests it is an IP address.
  • computer_ip must be an IP address. It may be a UDP multicast address.

No IMU data with OS0-64 at 1024x20 or 2048x10

When running the OS0-64 at either 1024x20 or 2048x10 modes, IMU data is not properly published. At lidar startup there is a burst of about 20 IMU messages published, then no more. Changing the os1_proc_mask parameter to only 'IMU' does not change the behavior.

When running in 1024x10, 512x20 and 512x10 modes, IMU data is published at the correct rate (100 Hz).

When using the Ouster provided ROS1 driver, IMU data is correctly published in 1024x20 and 2048x10 modes which suggests this is not an issue on the lidar side, but on the host side.

Additional information:

  • Lidar is connected directly to the PC, no switches or other devices on the network.
  • Lidar model: OS0-64-U with v1.14.0-beta.10 firmware.
  • Using eloquent-devel branch of ros2_ouster_drivers

Tests

  • create test sensor interface and make test to cover reset and configure services in active and inactive state
  • create lifecycle activate / deactivate / activate / reset script to make sure we transition ok
  • create test sensor interface to give back pre-determined packet infos (or bag?) and verify output PC/images/imu are correct
  • test for conversion functions

That should cover the ros interfaces, the abstract interfaces, process loop, lifecycle

  • how to test OS1 sensor implementation without sensor in loop? Or maybe have test that is just sensor in the loop? Run launch file and have a watcher for the rate and dimensions of information/rates

Create center ring data processor to create a 2D lidar scan

Because I made the data processors modular this should be pretty easy:

  • create scan_os.hpp class for storing just the range and intensity information, for all scan columns not the center, set -1, else actual range / intensity value
  • create a new processor to create a scan publisher and batch iterator, for all non-negative-1 push into a scan message and publish after a full rotation
  • create a processor factory and add to the data processors multimap under the lidar data key

Adding Libtins support

Hello

I'd like to add a feature to the driver that allows it to use the open-source Libtins library to read packets on an ethernet device. This is primarily so that I can use the driver to parse packets being replayed from a pcap file using tcpreplay. The changes I would like to propose making are:

  • Add/expose functions for saving metadata to, and reading from, a JSON file
  • Add a replay parameter that allows the user to specify the source of metadata (real sensor or JSON file)
  • Rename the Driver class to DefaultDriver
  • Add a class called sensor::SensorTins that uses libtins to read LiDAR and IMU packets
  • Add a parameter to allow the user to specify the sensor driver type (default or Tins)

The question I have is: I have seen in other threads that there is a desire to maintain as much compatibility as possible between this driver, and the official ROS1 equivalent: ouster-lidar/ouster_example. A recent PR (#239) adds some pcap parsing functions. Should I try and use these? Or am I free to add libtins support as I see fit?

As a note: the pcap functions introduces in PR (#239) use Tins to read directly from a pcap file, whereas I want to read from an ethernet device (and have tcpreplay play the file through the same device).

Port FW 2.0 and 2.1 changes

Based on my discussion with Steve in #74, there are features in ouster-lidar/ouster_example that have yet to be ported to this repo. I believe (and correct me if I'm wrong) that the last set of changes ported were made with #67. It looks like this PR includes all changes prior to ouster_example/#239.

The goal of this issue is to port across the minimal number of changes to maintain compatibility between the contents of ouster_example/ouster_client and the equivalent files here.

List of features/items to port include:

From ouster_example/#239

  • Addition of optional-lite code
  • Addition of the sensor_config struct amongst others to types.h
  • Addition of new functions to types.h/cpp
  • Function changes in lidar_scan.h/cpp
  • Addition of new functions to client.h/cpp
  • Misc Cmake, readme changes

From ouster_example/#246

  • Bugfixes

From ouster_example/#259

  • Addition of signal_multiplier parameter to config, across multiple files
  • Misc other bug fixes and code changes across ouster_client/ folder

Frame transformations different from Ouster Software Manual

Hello
I just checked that the frame transformations on the tf_static topic are different from the transformations given in the Ouster Software Manual. This is the output if the /tf_static topic which is published just once when we start this driver -

transforms:

  • header:
    stamp:
    sec: 1632922020
    nanosec: 663394972
    frame_id: laser_sensor_frame
    child_frame_id: imu_data_frame
    transform:
    translation:
    x: 0.0
    y: 0.0
    z: 0.0
    rotation:
    x: 0.0
    y: 0.0
    z: 0.0
    w: 1.0
  • header:
    stamp:
    sec: 1632922020
    nanosec: 663400150
    frame_id: laser_sensor_frame
    child_frame_id: laser_data_frame
    transform:
    translation:
    x: 0.0
    y: 0.0
    z: 0.0
    rotation:
    x: 0.0
    y: 0.0
    z: 1.0
    w: 0.0

When I visualized the data in RViz I saw that the laser_sensor frame is rotated by 180 degrees from the RViz axes. The laser_data_frame in RViz with respect to the real Ouster 0S1-128 Sensor was like this -
IMG_20210929_160351
Which is completely different from the frame transformations given in the manual. So I want to know the correct transformations of the laser_data_frame and imu_data_frame with respect to the laser_sensor_frame and also the correct position and orientation of the laser_sensor_frame with respect to the real Ouster Sensor.

Thanks.

Best regards
Gaurav

Document components use / test

e.g.

component manager for dynamic loading (also may be done through launch)
$ros2 run rclcpp_components component_container
load this component
$ros2 component load /ComponentManager ros2_ouster ros2_ouster::OS1Driver
transition to configuring
ros2 lifecycle set OusterDriver 1
transition to active
ros2 lifecycle set OusterDriver 3

** parameters

Publish TF

Params for tf frames? Will a namespace push the frame names into it?

black strip on Ouster Lidar

image
image

I'm facing the black strips problem on ouster lidar, as shown in the first figure. But it is ought to be the form in the second figure, where no black strips inside.
If someone faced similar problems or have some ideas about how to solve it, please leave messages here.

[open question] Moving repo over to ros-drivers organization

Hi,

This has been a bit coming. I think this would get alot more notoriety and community contributions if it lived in the ros-drivers organization. I'd like to open this for general folks to give their feedback on that transition, keep it here, or put it somewhere else.

colcon build fails on Foxy

Hi all, I've been working with this library on ROS2 Dashing/Ubuntu 18 and today updated to Ubuntu 20 with a fresh install of ROS2 Foxy. I cloned this repo and have been unable to get colcon build to succeed. Here are the steps I've been taking to reproduce the build failure. Please let me know if there's anything else I can provide or do to get this issue fixed.

Cheers,
Luke

Failed to create connection to lidar.

Hi,

I get such an error when I want to run driver_launch.py after completing the installation steps.

[INFO] [launch]: Default logging verbosity is set to INFO
[INFO] [ouster_driver-1]: process started with pid [129885]
[ouster_driver-1] [INFO] [1632326990.557586247] [ouster_driver]: Configuring Ouster driver node.
[ouster_driver-1] [INFO] [1632326990.557844659] [ouster_driver]: Connecting to sensor at 192.168.1.8.
[ouster_driver-1] [INFO] [1632326990.557915325] [ouster_driver]: Sending data from sensor to 192.168.1.102.
[ouster_driver-1] [FATAL] [1632326991.581233097] [ouster_driver]: Exception thrown: (Failed to create connection to lidar.)

Implement Advanced settings (from CPFL's fork and user feedback)

CPFL has a fork with some updates compared to the ouster example driver in ROS1 that this is feature parity to. CPFL was the ROS1 org holding Autoware so those features are probably needed by them for Autoware. These are the features they created that should be ported here.

  • pulse mode - not sure, didnt read that indepth
  • window rejection - not sure, didnt read that indepth
  • pointcloud mode (probably need them to do) - different point encodings of the pointcloud (PointXYZ, PointXYZI, PointXYZR, ...)
  • scan buffer duration - how long to buffer scans for before publishing, if not wanting to just do full scans.
  • using optionally ROS time for data rather than sensor time on packet reception
  • implement set_udp_dest_auto from firmware 1.13.0 SDK

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.