Skip to content

Commit 8bb238e

Browse files
committed
factor out r2s
1 parent f013b8e commit 8bb238e

40 files changed

+161
-4563
lines changed

.github/workflows/ros-tests.yml

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -74,22 +74,11 @@ jobs:
7474
env:
7575
DEBIAN_FRONTEND: noninteractive
7676

77-
- name: Install Python dependencies
78-
run: |
79-
if [[ "${{ matrix.ros_distro }}" == "jazzy" || \
80-
"${{ matrix.ros_distro }}" == "kilted" || \
81-
"${{ matrix.ros_distro }}" == "rolling" ]]; then
82-
pip3 install --break-system-packages -I pygments textual
83-
else
84-
pip3 install textual
85-
fi
86-
shell: bash
87-
8877
- name: Build packages
8978
run: |
9079
source /opt/ros/${{ matrix.ros_distro }}/setup.bash
9180
echo "Building and testing on ROS2 ${{ matrix.ros_distro }}"
92-
colcon build --packages-up-to r2s_gw
81+
colcon build --packages-up-to greenwave_monitor
9382
shell: bash
9483

9584
- name: Smoke test README commands
@@ -98,14 +87,13 @@ jobs:
9887
source install/setup.bash
9988
set -e
10089
timeout 10s bash -lc "script -qfec 'ros2 run greenwave_monitor ncurses_dashboard' /dev/null <<< \$'q'" || true
101-
timeout 10s bash -lc "script -qfec 'ros2 run greenwave_monitor r2s_gw_dashboard' /dev/null <<< \$'q'" || true
10290
timeout 5s ros2 launch greenwave_monitor hz.launch.py topics:='["/topic1"]' || true
10391
shell: bash
10492

10593
- name: Run tests
10694
run: |
10795
source /opt/ros/${{ matrix.ros_distro }}/setup.bash
108-
colcon test --event-handlers console_direct+ --return-code-on-test-failure --packages-up-to r2s_gw
96+
colcon test --event-handlers console_direct+ --return-code-on-test-failure --packages-up-to greenwave_monitor
10997
shell: bash
11098

11199
- name: Upload test results

CLAUDE.md

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Overview
6+
7+
Greenwave Monitor is a ROS 2 diagnostic tool for runtime monitoring of topic frame rates and latency. The project consists of two packages:
8+
9+
1. **greenwave_monitor** - Core C++ monitoring node, ncurses dashboard frontend, and header-only library
10+
2. **greenwave_monitor_interfaces** - ROS service definitions (ManageTopic, SetExpectedFrequency)
11+
12+
## Build Commands
13+
14+
```bash
15+
# Build all packages
16+
cd <ros_workspace>
17+
colcon build --packages-up-to greenwave_monitor
18+
19+
# Build individual packages
20+
colcon build --packages-select greenwave_monitor
21+
colcon build --packages-select greenwave_monitor_interfaces
22+
```
23+
24+
## Testing
25+
26+
```bash
27+
# Run all tests for greenwave_monitor
28+
colcon test --packages-select greenwave_monitor
29+
colcon test-result --verbose
30+
31+
# Run specific test types
32+
colcon test --packages-select greenwave_monitor --pytest-args -k test_greenwave_monitor
33+
colcon test --packages-select greenwave_monitor --pytest-args -k test_topic_monitoring_integration
34+
35+
# C++ unit tests (gtest) are run automatically with colcon test
36+
# - test_message_diagnostics.cpp - Tests MessageDiagnostics header-only library
37+
# - test_minimal_publisher.cpp - Tests example publisher node
38+
39+
# Python linting tests
40+
colcon test --packages-select greenwave_monitor --pytest-args -k test_flake8
41+
colcon test --packages-select greenwave_monitor --pytest-args -k test_pep257
42+
colcon test --packages-select greenwave_monitor --pytest-args -k test_copyright
43+
```
44+
45+
## Architecture
46+
47+
### Core Components
48+
49+
**GreenwaveMonitor Node** (`greenwave_monitor.cpp`):
50+
- Subscribes to topics using generic subscriptions (rclcpp::GenericSubscription)
51+
- Extracts timestamps from serialized messages for latency calculation
52+
- Uses MessageDiagnostics to track frame rates and latency per topic
53+
- Publishes diagnostics to `/diagnostics` topic (diagnostic_msgs/DiagnosticArray)
54+
- Exposes services at `~/manage_topic` and `~/set_expected_frequency`
55+
- Timer callback (1Hz) triggers diagnostics publishing for all monitored topics
56+
57+
**MessageDiagnostics Library** (`message_diagnostics.hpp`):
58+
- Header-only C++ library for calculating and publishing diagnostics
59+
- Tracks frame rate using both node clock and message timestamps
60+
- Uses rolling window filtering (default 300 messages) for smoothing
61+
- Calculates jitter, dropped frames, and latency metrics
62+
- Can be integrated directly into custom nodes to avoid subscription overhead
63+
- Thread-safe with mutex protection for updateDiagnostics() and publishDiagnostics()
64+
65+
**UI Adaptor**:
66+
- `ncurses_frontend.py` - Lightweight terminal dashboard
67+
- Subscribes to `/diagnostics` topic and calls services to manage monitoring
68+
- `ui_adaptor.py` provides GreenwaveUiAdaptor class for building custom UIs
69+
70+
Third-party UIs (like r2s_gw, available as a separate package) can integrate by subscribing to the `/diagnostics` topic and using the ManageTopic and SetExpectedFrequency services.
71+
72+
### Diagnostics Message Format
73+
74+
Greenwave follows Isaac ROS NITROS diagnostic conventions with these KeyValue fields:
75+
- `frame_rate_node` - Hz calculated from node clock
76+
- `frame_rate_msg` - Hz calculated from message timestamps
77+
- `current_delay_from_realtime_ms` - Latency (or "N/A" if unavailable)
78+
- `num_jitter_outliers_node/msg` - Count of deadline misses
79+
- `max_abs_jitter_node/msg` - Maximum jitter observed (µs)
80+
- `mean_abs_jitter_node/msg` - Average jitter (µs)
81+
- `total_dropped_frames` - Total frames dropped
82+
83+
This format allows NITROS-enabled nodes to be monitored without greenwave_monitor subscribing (when `ENABLE_GLOBAL_NITROS_DIAGNOSTICS=1` is set).
84+
85+
### Latency Calculation
86+
87+
Latency is computed as: `current_time - message.header.stamp`
88+
89+
**Important constraints:**
90+
- Message type must have a `std_msgs/Header` field
91+
- Message type must be registered in `known_header_types` map in greenwave_monitor.cpp:has_header_from_type()
92+
- Header timestamp must use epoch time (not boottime)
93+
94+
If conditions aren't met, latency shows as "N/A". Commonly supported types include sensor_msgs/Image, sensor_msgs/CameraInfo, etc.
95+
96+
**To add support for new message types:**
97+
1. Edit `greenwave_monitor.cpp::has_header_from_type()`
98+
2. Add entry to `known_header_types` map with type name and header offset
99+
3. Example: `{"sensor_msgs/msg/Image", {0, true}}`
100+
101+
## Service API
102+
103+
**ManageTopic.srv** - Add/remove topics from monitoring:
104+
```
105+
string topic_name
106+
bool add_topic # true=add, false=remove
107+
---
108+
bool success
109+
string message
110+
```
111+
112+
**SetExpectedFrequency.srv** - Configure expected rate and tolerances:
113+
```
114+
string topic_name
115+
float64 expected_hz
116+
float64 tolerance_percent # e.g., 5.0 = 5%
117+
bool clear_expected # reset to no expectation
118+
bool add_topic_if_missing # auto-add topic if not monitored
119+
---
120+
bool success
121+
string message
122+
```
123+
124+
## Contributing
125+
126+
All commits must be signed off using `git commit -s` to certify the Developer Certificate of Origin (DCO). This indicates you have rights to submit the contribution under the Apache 2.0 license.
127+
128+
CI automatically runs on PRs. For local testing across ROS distributions, use:
129+
```bash
130+
scripts/docker-test.sh
131+
```
132+
133+
## Code Style
134+
135+
- C++17 standard (enforced in CMakeLists.txt)
136+
- Python code must pass flake8, pep257, and copyright tests
137+
- Use ament_lint_auto for automatic style checking
138+
- Copyright header required: Apache 2.0 license with NVIDIA CORPORATION & AFFILIATES

README.md

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,9 @@ source install/setup.bash
5353

5454
## Usage
5555

56-
Greenwave monitor provides two dashboard frontends, a lightweight ncurses interface and a rich terminal interface (a fork of [r2s](https://github.com/mjcarroll/r2s)). Note we rename the fork r2s_gw to avoid conflicts with the original r2s package.
56+
Greenwave monitor provides a lightweight ncurses dashboard for monitoring topics. An optional rich TUI (r2s integration) with additional features is also available as a separate package.
5757

58-
We have found that the r2s dashboard gets sluggish when there are many topics, so we recommend using the ncurses dashboard for large deployments.
59-
60-
### ncurses Dashboard (Lightweight)
58+
### ncurses Dashboard
6159

6260
After installing, you can launch the ncurses dashboard with:
6361

@@ -71,27 +69,36 @@ You can also launch the dashboard with some demo publishers to see everything in
7169
ros2 run greenwave_monitor ncurses_dashboard --demo
7270
```
7371

74-
### r2s_gw Dashboard (Rich TUI)
72+
### Rich TUI (r2s integration) - Optional
73+
74+
For users who want a more feature-rich terminal interface, **r2s_gw** is available as a separate package. This is a fork of [r2s](https://github.com/mjcarroll/r2s) designed to integrate with Greenwave Monitor.
75+
76+
**Note:** The r2s integration requires additional dependencies (specifically the `textual` Python package) and can slow down when monitoring many topics. For large deployments or minimal dependencies, we recommend using the ncurses dashboard above.
7577

76-
First you need to build the r2s_gw package and some additional dependencies, r2s_gw is included in the greenwave_monitor package.
78+
To use r2s_gw:
7779

80+
1. Clone the r2s_gw repository into your workspace:
7881
```bash
79-
cd ros_ws/
82+
cd ros_ws/src
83+
git clone https://github.com/NVIDIA-ISAAC-ROS/r2s_gw.git
84+
cd ../..
85+
```
86+
87+
2. Install dependencies and build:
88+
```bash
89+
pip install textual
8090
colcon build --packages-up-to r2s_gw
81-
pip install -I textual # There is a requirements.txt file in the r2s_gw package, but in case you installed from debian and that's not handy ...
8291
source install/setup.bash
8392
```
8493

85-
Then you can launch the dashboard with the following. Use tab to navigate between different UI elements.
86-
94+
3. Launch the dashboard (use tab to navigate between UI elements):
8795
```bash
88-
ros2 run greenwave_monitor r2s_gw_dashboard
96+
ros2 run r2s_gw r2s_gw_dashboard
8997
```
9098

91-
Just like before, you can also launch the dashboard with some demo publishers to see everything in action.
92-
99+
4. Or launch with demo publishers:
93100
```bash
94-
ros2 run greenwave_monitor r2s_gw_dashboard -- --demo
101+
ros2 run r2s_gw r2s_gw_dashboard -- --demo
95102
```
96103

97104
### Manual Launch (ros2 topic hz mode)

greenwave_monitor/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ install(
6767
# Install Python scripts
6868
install(
6969
PROGRAMS
70-
scripts/r2s_gw_dashboard
7170
scripts/ncurses_dashboard
7271
DESTINATION lib/${PROJECT_NAME}
7372
)

greenwave_monitor/package.xml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,6 @@
5050
<test_depend>launch_testing</test_depend>
5151
<test_depend>launch_testing_ros</test_depend>
5252

53-
<!-- TODO add textual as dependency (need to host rosdep)-->
54-
5553
<build_depend>rosidl_default_generators</build_depend>
5654
<exec_depend>rosidl_default_runtime</exec_depend>
5755
<member_of_group>rosidl_interface_packages</member_of_group>

r2s_gw/.github/workflows/black_format.yml

Lines changed: 0 additions & 22 deletions
This file was deleted.

r2s_gw/.pre-commit-config.yaml

Lines changed: 0 additions & 35 deletions
This file was deleted.

0 commit comments

Comments
 (0)