Zero config telemetry tap for any ROS 1 or ROS 2 robot on your network. Discover, subscribe, stream. No ROS install required.
Project description
ros_tap
Zero config telemetry tap for any ROS robot on your network.
██████╗ ██████╗ ███████╗ ████████╗ █████╗ ██████╗
██╔══██╗██╔═══██╗██╔════╝ ╚══██╔══╝██╔══██╗██╔══██╗
██████╔╝██║ ██║███████╗ ██║ ███████║██████╔╝
██╔══██╗██║ ██║╚════██║ ██║ ██╔══██║██╔═══╝
██║ ██║╚██████╔╝███████║ ██║ ██║ ██║██║
╚═╝ ╚═╝ ╚═════╝ ╚══════╝ ╚═╝ ╚═╝ ╚═╝╚═╝
ros_tap discovers ROS 1 and ROS 2 robots on your network, subscribes to their topics, and streams telemetry wherever you want. No ROS install required. It's just a tap. You decide where the data goes.
Install
pip install ros_tap # ROS 2 support (via CycloneDDS)
pip install 'ros_tap[s3]' # + S3 output
pip install 'ros_tap[all]' # everything
Usage
Scan: see what's on the network
ros_tap scan # rich terminal dashboard
ros_tap scan --json # machine readable output
ros_tap scan --domain 42 # specific ROS 2 domain
ros_tap scan --ros1-uri http://robot:11311 # specific ROS 1 master
Record: stream telemetry
ros_tap record # stream to stdout as JSONL
ros_tap record -o ./data # write NPZ to local dir (default)
ros_tap record -o ./data -f jsonl # write JSONL instead
ros_tap record -o s3://my-bucket/robots # upload to S3
ros_tap record -c power,actuators # filter by category
ros_tap record -t /battery,/joint_states # filter by topic name
ros_tap record | jq '.data' # pipe to anything
ros_tap record -o ./data -c power,imu,lidar # local, filtered
Info: check your setup
ros_tap info # shows installed backends, env vars, version
Storage formats
NPZ (default for local recording)
When recording to a local directory, ros_tap defaults to compressed NumPy archives. Each recording session creates a run directory with per topic .npz files and a manifest.json:
ros_tap_data/
run_20260608_193000_a1b2c3d4e5f6/
manifest.json
battery_state_0000.npz
joint_states_0000.npz
imu_data_0000.npz
The manifest tracks every topic in the run with its type, sample count, and file list. NPZ files store numeric data as compressed arrays, which is dramatically smaller than JSONL for high frequency sensors.
Load a run in Python:
from ros_tap.loader import Run, list_runs
runs = list_runs("./ros_tap_data")
run = runs[-1] # latest run
print(run.topics)
imu = run.load("/imu")
print(imu["timestamps"].shape)
print(imu["linear_acceleration.x"])
JSONL
Use --format jsonl or pipe to stdout for human readable output:
{"ts": 1718000000.0, "node": "/turtlebot", "topic": "/battery_state", "type": "sensor_msgs/BatteryState", "ros": 2, "data": {...}}
Output sinks
| Sink | Flag | Format | Notes |
|---|---|---|---|
| stdout | -o - (default) |
JSONL | Pipe to jq, grep, curl, whatever |
| Local | -o ./path |
NPZ | Compressed arrays + manifest per run |
| Local | -o ./path -f jsonl |
JSONL | Auto rotating files (50 MB default) |
| S3 | -o s3://bucket/prefix |
JSONL | Buffered uploads, NDJSON content type |
How it works
ROS 2: Joins the DDS network as a passive participant using CycloneDDS. Discovers all nodes, topics, and types via DDS multicast. No ROS 2 install needed.
ROS 1: Queries the ROS Master's XML RPC API at ROS_MASTER_URI. Gets the full node/topic graph in one call.
Auto detect: ros_tap tries both and merges results. Works in mixed ROS 1 + ROS 2 environments with ros1_bridge.
Adding a subscriber does not interfere with any existing software on the robot. DDS pub/sub is like tuning into a radio station. Other listeners and the broadcaster are unaffected.
Auto detected categories
ros_tap classifies topics into categories for filtering:
| Category | Example topics |
|---|---|
power |
/battery_state, /battery |
actuators |
/joint_states, /motor_states |
diagnostics |
/diagnostics |
odometry |
/odom |
imu |
/imu |
lidar |
/scan |
camera |
/camera/image_raw |
command |
/cmd_vel |
thermal |
/temperature |
system |
/cpu_monitor, /memory_monitor |
Why not ros2 doctor?
ros2 doctor checks if your ROS 2 installation is healthy. ros_tap checks if your robot is healthy. Different things entirely.
ros2 doctor |
ros_tap |
|
|---|---|---|
| Checks | ROS 2 install, DDS config, QoS | Live robot telemetry |
| Requires ROS 2 | Yes | No |
| ROS 1 support | No | Yes |
| Output | Text report | NPZ / JSONL stream |
| Use case | "Is my dev env broken?" | "Is my robot alive?" |
License
Apache 2.0
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ros_tap-0.2.0.tar.gz.
File metadata
- Download URL: ros_tap-0.2.0.tar.gz
- Upload date:
- Size: 19.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
19b06596334f894c9a21523b00aca9e7ca06aeb332058f696876a17c16c4d575
|
|
| MD5 |
0b0c6283e728a45ee020bb0933115fc6
|
|
| BLAKE2b-256 |
3fad72279b8cb850770c91a744e6555b9952cdb845ce4b6f481b5d35dff1f9ae
|
File details
Details for the file ros_tap-0.2.0-py3-none-any.whl.
File metadata
- Download URL: ros_tap-0.2.0-py3-none-any.whl
- Upload date:
- Size: 22.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
56686479a099058ee419d7315bb3b668dd616b10a15abcf21722bfee9c6a09d7
|
|
| MD5 |
f873b736ad4f7b6d15806275cc695558
|
|
| BLAKE2b-256 |
44c2ffecbafce2cf535d5eef0c15d757fcb461a3e36eabcc58209159955d22e5
|