pulse-top
Live terminal dashboard over a ros2_pulse probe log. A pure log consumer:
no ROS dependency, no node, no subscriptions; it tails the jsonl file the probe
already writes, so watching costs the robot nothing and works over plain ssh or on
a dead log after the incident.
That is the difference from graph-joining monitors (ros2top, ornis,
ros2_topic_monitor, ...): they join the graph to measure it; pulse-top reads
what the in-process probe measured, including the intra-process traffic no
graph-side tool can see.
Run
pip install ./tools/pulse-top # or: pipx install ros2-pulse-top (once published)
# probe side: emit jsonl
export ROS_TOPIC_STATS_FORMAT=jsonl
LD_PRELOAD=libros2_pulse.so ros2 launch my_robot bringup.launch.py
# dashboard side (any shell, any machine with the file):
pulse-top # every $TMPDIR/topic_freq.<pid>.log (one per probed process)
pulse-top /path/to/shared.log # one explicit file (e.g. a fleet-wide ROS_TOPIC_STATS_OUTPUT_FILE)
pulse-top '/var/log/topic_freq.*.log' # a quoted glob; new files are picked up as nodes start
pulse-top --demo # self-generated demo graph with a scripted incident
Keys
| Key | Action |
|---|---|
↑/↓ |
select topic (detail sidebar follows) |
tab |
switch view: Topics · Tree · Nodes · Warns |
s |
cycle sort: topic / rate / gap |
w |
toggle warns-only filter |
q |
quit |
What it shows
- Topics: per-topic publish/intra/receive Hz, max inter-arrival gap, 60-window
sparkline. Absence renders as
—; the probe's "not measured" is never shown as 0. - Tree: topic namespace hierarchy with live rates.
- Nodes: liveness from
NODErecords; missing nodes flagged from structured warns. - Warns: the probe's structured
warns[](topic_rate,topic_gap,node_missing), parsed as JSON rather than regex.
Development
cd tools/pulse-top
uv venv .venv && uv pip install -p .venv/bin/python -e ".[dev]"
env -u PYTHONPATH .venv/bin/python -m pytest tests/ # clear ROS's pytest plugins
Reading a live stack (many processes, one view)
Every probed process flushes its own window; a 77-node stack is ~15 windows/s interleaved across files (or within one shared file). The view is built for that:
- Stale is measured in time, from the window timestamps: a topic is
stale 12sonce more than 1.5× its own window period has passed since its last window, regardless of how many other processes' windows landed in between. A 5 Hz topic on a 77-node stack used to readstale 3wfor that reason (Orin, 2026-08-23). - Sides merge. One process publishes
/tf_static, twenty receive it. A receive-only window refreshes theRECVfields and leavesPUBas learned from the publisher's window. - One sparkline sample per period, whichever process's window lands first in it.
- Only changed cells repaint. Textual's
DataTable.update_cellinvalidates and refreshes unconditionally; pulse-top diffs against what it last rendered, so an idle screen costs nothing over ssh.
transition_event, NITROS _supported_types and other one-shot topics going stale minutes
after startup is correct: they fired once.
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 ros2_pulse_top-0.2.0.tar.gz.
File metadata
- Download URL: ros2_pulse_top-0.2.0.tar.gz
- Upload date:
- Size: 25.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
872eb8590bd94ace2bede4fe04eceb0efe6c1fb8e3bdc8f92616f0579f745671
|
|
| MD5 |
dff30675bfba8b22769d336bdb170e76
|
|
| BLAKE2b-256 |
d8ea959bde87c303a73f1eac1abea0418b4210e0e94b54bed4359728e79caa4b
|
Provenance
The following attestation bundles were made for ros2_pulse_top-0.2.0.tar.gz:
Publisher:
publish-pypi.yml on TanayK07/ros2_pulse
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ros2_pulse_top-0.2.0.tar.gz -
Subject digest:
872eb8590bd94ace2bede4fe04eceb0efe6c1fb8e3bdc8f92616f0579f745671 - Sigstore transparency entry: 2573347700
- Sigstore integration time:
-
Permalink:
TanayK07/ros2_pulse@fc052507b1a98e92fd595c37bcbe237b12998226 -
Branch / Tag:
refs/tags/pulse-top-v0.2.0 - Owner: https://github.com/TanayK07
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@fc052507b1a98e92fd595c37bcbe237b12998226 -
Trigger Event:
push
-
Statement type:
File details
Details for the file ros2_pulse_top-0.2.0-py3-none-any.whl.
File metadata
- Download URL: ros2_pulse_top-0.2.0-py3-none-any.whl
- Upload date:
- Size: 20.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c5aee90a0239393da5459d8a3d2d6c7829395815ebce07e79b1be0cf65a468c3
|
|
| MD5 |
2550eae903b8068dfd07861ebab35e8f
|
|
| BLAKE2b-256 |
42bc6241ce48310578194d2fa0087602d1a459bc97e5b7cd7300ef95a341689a
|
Provenance
The following attestation bundles were made for ros2_pulse_top-0.2.0-py3-none-any.whl:
Publisher:
publish-pypi.yml on TanayK07/ros2_pulse
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
ros2_pulse_top-0.2.0-py3-none-any.whl -
Subject digest:
c5aee90a0239393da5459d8a3d2d6c7829395815ebce07e79b1be0cf65a468c3 - Sigstore transparency entry: 2573348378
- Sigstore integration time:
-
Permalink:
TanayK07/ros2_pulse@fc052507b1a98e92fd595c37bcbe237b12998226 -
Branch / Tag:
refs/tags/pulse-top-v0.2.0 - Owner: https://github.com/TanayK07
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-pypi.yml@fc052507b1a98e92fd595c37bcbe237b12998226 -
Trigger Event:
push
-
Statement type: