artefacts-route-recorder
A CLI tool that allows users to set their navigation routes by clicking in RViz, storing to YAML, which can then be later loaded into simulation tests through
artefacts-toolkit-navigation. (artefacts-route-recorder is included in artefacts-toolkit-navigation)
A route is an optional start pose plus an ordered list of waypoints, each
{x, y, yaw} in metres/radians in a named frame (map by default).
Works on ROS 2 Humble (Python 3.10) and Jazzy (Python 3.12), and needs only
rclpy, the standard message packages and PyYAML.
Quick start
# source python environment if using a venv
source venv/bin/activate
# source ros
source /opt/ros/<ros-distro>/setup.bash # setup.zsh under zsh
# Record a route on Turtlebot3 demo
artefacts-route record routes/lab.yaml --map /opt/ros/jazzy/share/nav2_bringup/maps/tb3_sandbox.yaml
# /opt/ros/humble/share/nav2_bringup/maps/turtlebot3_world.yaml
Click 2D Pose Estimate once where the robot should start, then Publish
Point for each waypoint. Close RViz or press enter in the terminal to save
routes/lab.yaml. artefacts-route replay draws it back.
Installation
Pre-requisites
If using record --map (i.e with a preexisting map) you will need to install nav2_map_server
sudo apt install ros-<distro>-nav2-map-server
Install
source /opt/ros/<ros-distro>/setup.bash
python3 -m venv --system-site-packages venv # if using a virtual environment
source venv/bin/activate # if using
pip install artefacts-route-recorder
Recording
There are two ways to record, depending on whether you already have RViz up.
1. RViz (and a map) already running
artefacts-route record [routes/<name>.yaml]
The recorder just subscribes to the topics the RViz tools publish on. Add
--map-ref maps/<map-name>.yaml if you want the route file to remember which map it
was recorded against (path plus a sha256 of the yaml and image); this does not
launch anything.
2. Nothing is running and you only have a saved map
artefacts-route record [routes/<name>.yaml] --map maps/<map-name>.yaml
This starts nav2_map_server on that map, drives it through configure/activate,
and opens RViz with the bundled config (rviz/record.rviz) already pointed at
/map and /route_markers. Closing RViz saves the route and quits.
Use Publish Point for waypoints when Nav2 is running: a 2D Goal Pose click is recorded too, but Nav2 also drives the robot there.
Terminal commands while recording
[enter] or s save and quit u undo the last waypoint
q quit without saving c clear all waypoints (keeps start pose)
l list what is recorded h help
Ctrl-C also saves and quits.
The route is saved to the file you give, or to routes/<date>_<time>.yaml if not provided.
The filename is also the route's name. --force overwrites an existing file.
Inspecting and replaying
artefacts-route list # all routes in routes/, * marks the most recent
artefacts-route show # print the latest route's YAML + any problems
artefacts-route show routes/lab_loop.yaml
artefacts-route replay # publish the latest route as RViz markers
artefacts-route replay routes/lab_loop.yaml
replay publishes a visualization_msgs/MarkerArray on /route_markers with
transient local durability, so RViz picks it up whenever it connects: a
blue line through the waypoints, a green arrow and an index label at each one,
and an orange arrow for the start pose. The bundled RViz config already has a
matching MarkerArray display.
routes/.latest remembers the last route saved into routes/, which is what
the commands above default to. Give show, replay or list a directory
instead of a file for the latest route in it.
YAML format
format_version: 1
name: lab_loop
recorded_at: "2026-09-17T14:55:00+00:00"
ros_distro: jazzy
frame_id: map
map: # null unless --map/--map-ref was used
file: maps/lab.yaml
sha256: "abc123..."
initial_pose: {x: 1.2, y: 0.45, yaw: 0.0} # null if never set
waypoints:
- {x: 3.1, y: 0.5, yaw: 0.0}
- {x: 3.1, y: 2.8, yaw: 1.5708}
Loading routes from Python
from artefacts_route_recorder.schema import Route, RoutesDir
route, path = RoutesDir("routes").find("lab_loop") # None = the latest route
route = Route.load("routes/lab_loop.yaml")
print(route.initial_pose, route.waypoints)
Release
Releases go to PyPI (sdist and wheel), built and uploaded by bin/release:
- Move the
[Unreleased]notes inCHANGELOG.mdunder the new version and commit. - Tag that commit with the bare version:
git tag 0.1.0. The package version comes from this tag (setuptools-scm). pip install -e ".[dev]"once, forbuild,setuptools-scmandtwine.bin/releaseuploads to TestPyPI;bin/release productionto PyPI.
Metadata
Release files for artefacts-route-recorder 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| artefacts_route_recorder-0.2.0.tar.gz | 37.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| artefacts_route_recorder-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 64.0 kB
Release files / artefacts_route_recorder-0.2.0.tar.gz
| Download URL | artefacts_route_recorder-0.2.0.tar.gz |
|---|---|
| Size | 37.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
90f1b7d183c7509501fac55ff94d7351f8403f99d58bb15efbf0a05f8e1c0e30
|
|
BLAKE2b-256 checksum How to use checksums |
2dc80ecb79214d09304101ecf017ff71c36d4b2acd361f271d30f932767ddf80
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.3
|
Release files / artefacts_route_recorder-0.2.0-py3-none-any.whl
| Download URL | artefacts_route_recorder-0.2.0-py3-none-any.whl |
|---|---|
| Size | 26.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
dc644d0e59cd6c9c274350e6363f2180f4aa029864dc2e9023b2dc620b2f8a63
|
|
BLAKE2b-256 checksum How to use checksums |
70e17b3ebf6333d5a28a78731029a34bb25812c93ae4fda19320ac2f69d13115
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.12.3
|