How each robot builds a map of a building and keeps track of where it is on that map.
M20 Pro
The M20 has two ways to map and localize: DEEP Robotics’ 2D mapping stack, which is the one connected to navigation, and Lightning-LM, which maps and localizes in 3D. Lightning-LM runs beside the 2D stack on AOS, produces its own map and pose, and doesn’t drive the planner.
2D mapping
Provided by DEEP Robotics: a FAST-LIO-style filter for odometry and mapping, and GTSAM plus ICP for localization, fed by the RoboSense LiDAR (/LIDAR/POINTS) and Yesense IMU (/IMU_YESENSE).
| Odometry | Mapping | Localization | |
|---|---|---|---|
| Host | AOS, always running | NOS, on demand | NOS, always running |
| Program | lio_ddsnode (dr_lio) |
slam_ddsnode (dr_lio) |
localization_ddsnode (graph_loc, v3.2.3) |
| Method | IKFoM iterated Kalman filter with a multi-level voxel map | Same filter; README adds pose graph optimization | 3-second GTSAM fixed-lag IMU smoother plus fast_icp |
| Output | /LIO_ODOM, which feeds the height map |
full_cloud.pcd and a 2D occupancy grid |
/ODOM |
- Separate estimates: localization reads raw LiDAR and IMU, not
/LIO_ODOM, so two position estimates run at once.
2D mapping commands
Maps are stored in /var/opt/robot/data/maps, and active points to the one in use.
| Action | Command |
|---|---|
| Start mapping | drmap mapping -n NAME -s (in tmux; -s skips RViz) |
| Stop mapping | drmap stop_mapping |
| Use a map | drmap apply PATH |
| Stop localization | localization_stop.sh |
| Start localization | Probably the localization systemd service; untested |
| Set pose | /initialpose |
Status topics: /LOCATION_STATUS, /ODOM, /ALIGNED_POINTS, plus /SLAM_ODOM and /SLAM_ALIGNED_POINTS while mapping.
3D mapping: Lightning-LM
Lightning-LM (DEEP Robotics’ fork of gaoxiang12/lightning-lm, BSD-3) is another way to map and localize on the M20, this time in 3D. It is built on AOS at /home/user/lightning-lm.
- LiDAR-inertial odometry: a FAST-LIO-style filter fuses the IMU and LiDAR and tracks full 3D motion, with no flat-floor assumption.
- Scan skipping: LiDAR corrections run on every 2nd scan to save CPU, while the IMU still handles every scan.
- Loop closure: revisited places are matched and a pose graph removes accumulated drift.
- Start-anywhere localization: a place-recognition index lets the robot localize from anywhere in a saved map.
- Tiled maps: maps are saved as tiles, and distant tiles are unloaded during localization to save memory.
A Lightning-LM map (global.pcd) of the Levine hallway, viewed in pcl_viewer.
Installing. To install Lightning-LM on the M20, follow the steps in the DEEP Robotics Lightning-LM repository.
Before each session:
- Start the point-cloud relay on NOS. It exists since V1.2.x but isn’t enabled at boot:
ssh -J user@10.21.41.1 user@10.21.31.106 sudo systemctl start multicast-relay.service - Open the AOS root shell.
onboard.pyrefuses to run asuseron the M20:ssh user@10.21.41.1 cd ~/lightning-lm sudo bash export LIGHTNING_DIR=/home/user/lightning-lm && cd "$LIGHTNING_DIR"
Mapping, saving and localizing:
tmux new-session -s lightning -c "$LIGHTNING_DIR"
python3 scripts/onboard.py status # must print SUCCESS
python3 scripts/onboard.py slam # map; add --record-bag to keep its inputs
python3 scripts/onboard.py save run1 # from a 2nd root shell; wait for "response: 0"
python3 scripts/onboard.py localize data/run1 --global-init
- Keep the robot still until it initializes, then walk it around. Revisiting earlier spots gives loop closure a chance.
- A map is saved only by
save; stopping without it loses the map. Use a new name each run, because a non-empty folder won’t be overwritten. --global-initusesplaces.binto start anywhere in the map, confirming over three observations. Without it, start near where mapping began.- Stop with Ctrl+C and wait for the prompt. Localization writes accepted poses to
data/localization_onboard.tum, replaced each run.
Map files
| Map file | Purpose |
|---|---|
global.pcd |
Full point cloud, for viewing |
index.txt + numbered .pcd tiles |
Required for localization |
places.bin |
Place-recognition index for --global-init |
map_view.json |
Display leveling for the onboard map viewer |
Topics
| Output / input | Topic |
|---|---|
| Estimator pose | /lightning/pose |
| Live scan / matching pose | /lightning/current_scan, /lightning/current_pose |
| Trajectory | /lightning/trajectory |
| Transforms | /lightning/tf, /lightning/tf_static |
Manual initial pose (frame map) |
/lightning/initialpose |
Viewing. Copy the map to a laptop and open it with pcl_viewer:
# on your laptop
mkdir -p ~/m20_runs
rsync -aP user@10.21.41.1:/home/user/lightning-lm/data/run1/ ~/m20_runs/map_run1/
pcl_viewer ~/m20_runs/map_run1/global.pcd -ps 2
Files are written by root, so run sudo chown -R user:user /home/user/lightning-lm/data on AOS first if copying fails. To visualize live in RViz, follow the steps in the DEEP Robotics Lightning-LM repository.
Troubleshooting
| Symptom | Cause / fix |
|---|---|
onboard.py: “need the root shell” |
Use the AOS root shell (step 2). |
status says NOT READY |
Check multicast-relay.service on NOS and the firmware sensor services. |
/LIDAR/POINTS has 0 publishers, but /IMU works |
Running as user or with the robot’s DDS profile. See Visualization. |
save returns 3 |
No map data yet, or the destination folder isn’t empty. Use a new name. |
| Wi-Fi dropped | tmux keeps running. Reconnect and tmux attach -t lightning from a root shell. |
| Localization won’t initialize | Keep the robot still; start near the mapping origin or use --global-init. |
X30 Pro
X30 SLAM notes to come. For now, see Mapping and Localization on the X30 Pro page.