← All skills

Skill

Lidar

Laser range sensors for mapping and localization. Two RPLIDAR A1s merged on OpenDubs, the Odin1 lidar-inertial sensor and the LD19 2D lidar characterized for ARUW.

3 log entries2 projects

OpenDubsBest example

Two 2D lidars, merged into one scan

Also shows: State estimationROS 2Hardware bring-upPython

For localization and a map, the base carries two RPLIDAR A1 2D lidars, one at the front and one at the back. Bringing them up, with the team, was mostly fighting USB: the two units have identical USB IDs, so udev rules name each by the hub port it's plugged into, and they power up a few seconds apart so neither times out.

Mapping and Nav2 expect one scan, so I wrote a node that merges the two. The two scans never line up on their own: nothing guarantees the lidars spin at exactly the same rate or finish a revolution at the same moment, and each reaches the Thor with its own latency. So the node pairs scans by their timestamps (any two within 0.1 s), looks up each scan's transform into the robot's frame at that scan's own timestamp, resamples both to the finer of the two angular resolutions, and keeps the nearest return in each direction of one 360° scan, stamped halfway between the two and dropping hits on the robot itself. On top of it, I set up slam_toolbox and Nav2, which drove the robot point to point in simulation.

A CAD render of a round 2D lidar sitting in a bright green 3D-printed mount
One of the two lidar mounts. CAD render from the lab's build guide.
A replay in Gazebo: the robot's URDF, my lidar merger and our slam_toolbox settings, unmodified, mapping a made-up lab room while Nav2 drives. 6× speed.

Advanced Robotics at UW

The same check for a 2D lidar

Code

Also shows: ROS 2State estimation

I ran the same characterization on a WayPonDEV LD19 2D lidar, for obstacle mapping, with the Odin providing the pose. It scans at a steady 10 Hz with 8–14 ms of jitter, about 503 points per scan 0.72° apart, and skips 1–2% of scans. Range noise is 3–6 mm at 1–2 m, 6–11 mm at 2–3 m and 7–28 mm at 3–5 m: well under a 5 cm map cell, even at 5 m. At most 0.2% of returns are isolated false points and 1–2.4% are outliers, mostly at object edges where a beam half-hits the edge and half the background, which a filter removes easily. It never dropped off USB in the 40 minutes it ran, and the longest gap between scans was one skipped scan. The LD19 was good enough for our use, but we bought a 3D lidar anyway: the Odin's field of view is small, and a 3D lidar sees much more of the area around the robot.

Occupancy map of a cluttered room, about 7 by 12 meters, with the robot's pushed path drawn in red as two loops
The room mapped with the LD19's scans, placed by the Odin's poses (5 cm cells), with the 24.5 m path the robot was pushed along in red.
Top-down diagram of the sentry's sensor coverage: the Odin's lidar covers a 126 degree wedge to the front, the LD19 a 196 degree arc behind, and a 39 degree wedge between them is covered by neither
What the two sensors see on the sentry, from the measured mounting: a 39° wedge is covered by neither.

Advanced Robotics at UW

A test platform against motion capture

Code

Also shows: Experiment designPython

The sentry localizes with an Odin1, a lidar-inertial sensor that relocalizes into a prebuilt map. Before the team decided whether the whole localization system could rely on it alone, we wanted to know how accurate it is and where it is weak. So I built a test platform that measures it against the motion capture room, whose OptiTrack tracks the robot to a fraction of a millimeter. It starts and stops the sensor, records every run, guides whoever is driving with live mocap feedback, and can also drive the robot itself through the Jetson and the robot's controller, with a watchdog and speed caps. A campaign day runs a fixed protocol: calibration spins, a mapping drive, figure-8 laps at set speeds, ten-minute holds, back-and-forth motion to measure latency, cold starts, and outages where someone covers the sensor.

Diagram of the system: motion capture and the Odin1 sensor feed the characterization scripts, which record every run and write a report; in autonomous mode they send chassis velocities over UDP to the Jetson, which forwards them over UART to the sentry's motor control board
The three parts, and the default human-driven mode.
Bar timeline of day 1: preflight 8 minutes, calibration 3, mapping 5, figure-8 laps 6, holds 41, latency 3, cold starts 16, outages 11; 93 minutes in all
Day 1, step by step, from the campaign's time estimate.