Production-grade ROS 2 Jazzy driver for YDLIDAR sensors
Model-agnostic YDLIDAR driver with health monitoring, auto-reconnect, and zero-config Nav2 compatibility.
Built for the Porter Robot by VirtusCo.
- Model-agnostic -- supports X4 Pro, S2 Pro, G4, G2, Tmini, TG series, and more. Change LIDAR model via YAML config only -- zero code changes.
- Production-grade health monitoring -- sliding-window diagnostics on
/diagnosticswith scan frequency, invalid point ratio, and failure tracking. - Auto-reconnect -- exponential backoff retry on init failure, automatic reconnection on sustained scan failures.
- Sensor Data QoS -- uses
rclcpp::SensorDataQoS()for/scanpublisher, compatible with Nav2 and slam_toolbox out of the box. - Clean shutdown -- graceful stop of scan motor and serial disconnect.
| Model | Type | Baudrate | Tested |
|---|---|---|---|
| YDLIDAR X4 Pro 360 | Triangle | 128000 | Primary target |
| YDLIDAR S2 Pro | Triangle | 115200 | Config only |
| YDLIDAR G4 | Triangle | 230400 | Config only |
| YDLIDAR X2/X2L | Triangle | 115200 | Config only |
| YDLIDAR TG series | ToF | 512000 | Config only |
- ROS 2 Jazzy (Ubuntu 24.04)
- YDLidar SDK installed system-wide:
git clone https://github.com/YDLIDAR/YDLidar-SDK.git
cd YDLidar-SDK && mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
make -j$(nproc)
sudo make install
sudo ldconfig# Clone into your colcon workspace
cd ~/ros2_ws/src
git clone https://github.com/VirtusCo/ydlidar-ros2-driver.git
# Install dependencies
cd ~/ros2_ws
rosdep install --from-paths src --ignore-src -r -y
# Build
source /opt/ros/jazzy/setup.bash
colcon build --packages-select ydlidar_driver --symlink-install
source install/setup.bashdocker pull ghcr.io/virtusco/ydlidar-ros2-driver:latest
# Run with device access
docker run --rm -it \
--device=/dev/ttyUSB0 \
--net=host \
ghcr.io/virtusco/ydlidar-ros2-driver:latest# Launch with default config (X4 Pro on /dev/ttyUSB0)
ros2 launch ydlidar_driver ydlidar_launch.py
# Override port
ros2 launch ydlidar_driver ydlidar_launch.py port:=/dev/ttyUSB1
# Launch with RViz2 visualization
ros2 launch ydlidar_driver ydlidar_rviz_launch.py
# Direct run with parameter overrides
ros2 run ydlidar_driver ydlidar_node --ros-args \
-p port:=/dev/ttyUSB0 \
-p baudrate:=128000 \
-p frame_id:=laser_frameros2 topic echo /scan # View scan data
ros2 topic hz /scan # Check scan rate (~10 Hz)
ros2 topic echo /diagnostics # View health status
ros2 param dump /ydlidar_node # Dump all parametersAll parameters are configurable via config/ydlidar_params.yaml:
| Parameter | Type | Default | Description |
|---|---|---|---|
port |
string | /dev/ttyUSB0 |
Serial device path |
baudrate |
int | 128000 |
Serial baudrate |
frame_id |
string | laser_frame |
TF frame ID |
frequency |
double | 10.0 |
Target scan frequency (Hz) |
angle_min |
double | -180.0 |
Minimum scan angle (degrees) |
angle_max |
double | 180.0 |
Maximum scan angle (degrees) |
min_range |
double | 0.01 |
Minimum valid range (metres) |
max_range |
double | 12.0 |
Maximum valid range (metres) |
lidar_type |
int | 1 |
0=ToF, 1=Triangle, 3=GS |
singleChannel |
bool | true |
True for X4/X4Pro/X2/S2/S4 |
intensity |
bool | false |
Enable intensity data |
auto_reconnect |
bool | true |
Auto-reconnect on failure |
health_window_size |
int | 20 |
Diagnostic sliding window |
max_consecutive_failures |
int | 5 |
Failures before reconnect |
| Topic | Type | QoS | Description |
|---|---|---|---|
/scan |
sensor_msgs/LaserScan |
SensorData (RELIABLE) | 360 laser scan |
/diagnostics |
diagnostic_msgs/DiagnosticArray |
Default | Health status (1 Hz) |
ydlidar_node
┌──────────────────────────────────────────┐
│ │
│ ┌──────────────┐ ┌───────────────┐ │
│ │ SdkAdapter │ │ HealthMonitor │ │
│ │ │ │ │ │
│ │ initialize() │ │ record_scan │───>│ /diagnostics
│ │ start_scan() │ │ record_fail │ │
│ │ read_scan() │ │ get_health │ │
│ │ disconnect() │ │ should_ │ │
│ │ │ │ reconnect │ │
│ └──────┬───────┘ └───────────────┘ │
│ │ │
│ v │
│ ┌──────────────┐ │
│ │ CYdLidar │ YDLidar SDK │
│ └──────┬───────┘ │
│ │ serial │
│ /dev/ttyUSB0 ────────────────────────>│ /scan
└──────────────────────────────────────────┘
To switch from X4 Pro to another model, edit config/ydlidar_params.yaml:
# Example: Switch to YDLIDAR G4
ydlidar_node:
ros__parameters:
baudrate: 230400
lidar_type: 1 # Still TYPE_TRIANGLE
intensity: true # G4 supports intensity
max_range: 16.0 # G4 range is 16m
samp_rate: 9 # G4 sample rateNo recompilation needed -- just change the YAML and relaunch.
# Build with tests
colcon build --packages-select ydlidar_driver --symlink-install
# Run tests
colcon test --packages-select ydlidar_driver --event-handlers console_direct+
colcon test-result --verbose| Issue | Detail | Mitigation |
|---|---|---|
| Missing baseplate info | Some units don't report baseplate reliably | Treated as non-fatal |
SDK health code ffffffff |
Occurs with some firmware versions | 3-retry with exponential backoff |
| DTR motor control | Some OS/USB adapters don't support DTR | Set support_motor_dtr_ctrl: false |
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch (
git checkout -b feat/my-feature) - Commit with conventional commits (
feat:,fix:,docs:) - Open a Pull Request
Apache License 2.0 -- see LICENSE.