Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
256a121
Add controlling topic expected frequencies and tolerances through ROS…
bmchalenv Jan 2, 2026
596cc53
Add tests for nested YAML and don't specify the topics parameter ever…
bmchalenv Jan 2, 2026
2f31969
More common functions and use rclpy instead of subprocess for interfa…
bmchalenv Jan 2, 2026
e78aca3
Fix cpplint
bmchalenv Jan 2, 2026
b891a6b
Fix lint
bmchalenv Jan 2, 2026
eb488e3
Fix tests
bmchalenv Jan 2, 2026
4fdc70c
Don't maintain pending_topic_configs_
bmchalenv Jan 2, 2026
f715325
Use same base class for RosNodeTestCase
bmchalenv Jan 2, 2026
31e9148
Update copyrights
bmchalenv Jan 2, 2026
88ddcd2
More tests and linting
bmchalenv Jan 3, 2026
ad2aacb
Cover when topics is specified alongside its subfields
bmchalenv Jan 3, 2026
61c898f
Move code inline and add param delete
bmchalenv Jan 5, 2026
99f2981
Catch exceptions with declare
bmchalenv Jan 5, 2026
de7b899
Fix typo
bmchalenv Jan 5, 2026
4ef8db8
Reject non-numeric parameters and allow both int and double
bmchalenv Jan 5, 2026
6fa7976
Add tests for deleting and setting invalid parameters
bmchalenv Jan 5, 2026
53b052a
Fix lint
bmchalenv Jan 5, 2026
82971d7
Move parameters to greenwave_diagnostics.hpp
bmchalenv Jan 7, 2026
cc67a22
Add parameter tests to test_greenwave_diagnostics
bmchalenv Jan 7, 2026
154d35e
More tests. One consolidated test no deletions.
bmchalenv Jan 8, 2026
b9292b3
Remove old test files
bmchalenv Jan 8, 2026
e0327dd
Refactor UI adaptor
bmchalenv Jan 8, 2026
e4d02af
Use parameters instead of ManageTopic
bmchalenv Jan 9, 2026
b8e6141
Fix CI tests
bmchalenv Jan 9, 2026
37aee84
Fix CI issues
bmchalenv Jan 9, 2026
136f3a7
Remove last monitor-interfaces reference
bmchalenv Jan 9, 2026
658dc50
Test no destructor
bmchalenv Jan 9, 2026
01c3f09
Try to fix CI
bmchalenv Jan 9, 2026
c4273fd
Small fixes to improve destructor safety
bmchalenv Jan 9, 2026
c78675c
Fix ROS race conditions during initialization
bmchalenv Jan 9, 2026
7308ae0
Fix lint
bmchalenv Jan 9, 2026
7f1c64f
Small greptile fixups
bmchalenv Jan 9, 2026
97a8f80
Fix lint
bmchalenv Jan 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/debian-packages.yml
Original file line number Diff line number Diff line change
Expand Up @@ -151,10 +151,10 @@ jobs:
ls -la debian_packages/${{ matrix.ros_distro }}/

# Install the debian packages on top of ros-core
apt-get install -y ./debian_packages/${{ matrix.ros_distro }}/ros-${{ matrix.ros_distro }}-greenwave-monitor-interfaces_*.deb ./debian_packages/${{ matrix.ros_distro }}/ros-${{ matrix.ros_distro }}-greenwave-monitor_*.deb
apt-get install -y ./debian_packages/${{ matrix.ros_distro }}/ros-${{ matrix.ros_distro }}-greenwave-monitor_*.deb

# Verify packages are installed
dpkg -s ros-${{ matrix.ros_distro }}-greenwave-monitor ros-${{ matrix.ros_distro }}-greenwave-monitor-interfaces
dpkg -s ros-${{ matrix.ros_distro }}-greenwave-monitor
shell: bash
env:
DEBIAN_FRONTEND: noninteractive
Expand Down
40 changes: 27 additions & 13 deletions docs/images/SERVICES.md
Original file line number Diff line number Diff line change
@@ -1,37 +1,51 @@
# Services
# Parameters

The Greenwave Monitor provides two services. The `ManageTopic` service dynamically adds or removes topics from monitoring. The `SetExpectedFrequency` service dynamically sets or clears expected frequencies for a specified topic, which enables additional diagnostic values and statuses.
The Greenwave Monitor uses ROS parameters for all topic configuration, including enabling/disabling monitoring and setting expected frequencies.

## Manage Topic
## Topic Monitoring Control

The monitor node exposes a `/greenwave_monitor/manage_topic` service that follows the `greenwave_monitor_interfaces/srv/ManageTopic` service definition.
Topics can be enabled or disabled via the `greenwave_diagnostics.<topic>.enabled` parameter.

**Usage Examples**

To add a topic to the monitoring list:
To enable monitoring for a topic:
```bash
ros2 service call /greenwave_monitor/manage_topic greenwave_monitor_interfaces/srv/ManageTopic "{topic_name: '/topic2', add_topic: true}"
ros2 param set /greenwave_monitor greenwave_diagnostics./topic2.enabled true
```

To remove a topic from the monitoring list:
To disable monitoring for a topic:
```bash
ros2 service call /greenwave_monitor/manage_topic greenwave_monitor_interfaces/srv/ManageTopic "{topic_name: '/topic2', add_topic: false}"
ros2 param set /greenwave_monitor greenwave_diagnostics./topic2.enabled false
```

## Set Expected Frequency
## Expected Frequency Parameters

The monitor node exposes a `/greenwave_monitor/set_expected_frequency` service that follows the `greenwave_monitor_interfaces/srv/SetExpectedFrequency` service definition.
Expected frequencies are configured via ROS parameters with the following naming convention:
- `greenwave_diagnostics.<topic>.expected_frequency` - Expected publish rate in Hz
- `greenwave_diagnostics.<topic>.tolerance` - Tolerance percentage (default: 5.0%)

**Usage Examples**

To set the expected frequency for a topic:
```bash
ros2 service call /greenwave_monitor/set_expected_frequency greenwave_monitor_interfaces/srv/SetExpectedFrequency "{topic_name: '/topic2', expected_hz: <float>, tolerance_percent: <float>, add_topic_if_missing: true}"
ros2 param set /greenwave_monitor greenwave_diagnostics./topic2.expected_frequency 30.0
ros2 param set /greenwave_monitor greenwave_diagnostics./topic2.tolerance 10.0
```

To clear the expected frequency for a topic:
Parameters can also be set at launch time via YAML:
```yaml
greenwave_monitor:
ros__parameters:
greenwave_diagnostics./topic2.expected_frequency: 30.0
greenwave_diagnostics./topic2.tolerance: 10.0
greenwave_diagnostics./topic2.enabled: true
```

Or via command line:
```bash
ros2 service call /greenwave_monitor/set_expected_frequency greenwave_monitor_interfaces/srv/SetExpectedFrequency "{topic_name: '/topic2', clear_expected: true}"
ros2 run greenwave_monitor greenwave_monitor --ros-args \
-p greenwave_diagnostics./topic2.expected_frequency:=30.0 \
-p greenwave_diagnostics./topic2.tolerance:=10.0
```

Note: The topic name must include the leading slash (e.g., '/topic2' not 'topic2').
31 changes: 18 additions & 13 deletions greenwave_monitor/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ endif()
find_package(ament_cmake_auto REQUIRED)
ament_auto_find_build_dependencies()

# Add message_diagnostics.hpp as a header-only library
add_library(message_diagnostics INTERFACE)
target_include_directories(message_diagnostics INTERFACE
# Add greenwave_diagnostics.hpp as a header-only library
add_library(greenwave_diagnostics INTERFACE)
target_include_directories(greenwave_diagnostics INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>)

Expand All @@ -34,9 +34,8 @@ ament_target_dependencies(greenwave_monitor
rclcpp
std_msgs
diagnostic_msgs
greenwave_monitor_interfaces
)
target_link_libraries(greenwave_monitor message_diagnostics)
target_link_libraries(greenwave_monitor greenwave_diagnostics)

target_include_directories(greenwave_monitor PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
Expand All @@ -51,7 +50,7 @@ add_executable(minimal_publisher_node
src/minimal_publisher_node.cpp
src/minimal_publisher_main.cpp)
ament_target_dependencies(minimal_publisher_node rclcpp std_msgs sensor_msgs diagnostic_msgs)
target_link_libraries(minimal_publisher_node message_diagnostics)
target_link_libraries(minimal_publisher_node greenwave_diagnostics)
target_include_directories(minimal_publisher_node PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>)
Expand All @@ -60,7 +59,7 @@ install(TARGETS minimal_publisher_node
DESTINATION lib/${PROJECT_NAME})

install(
DIRECTORY launch examples
DIRECTORY launch examples config
DESTINATION share/${PROJECT_NAME}
)

Expand Down Expand Up @@ -116,22 +115,28 @@ if(BUILD_TESTING)
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
)

# Add parameter-based topic configuration tests
ament_add_pytest_test(test_parameters test/test_parameters.py
TIMEOUT 120
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
)

# Add gtests
ament_add_gtest(test_message_diagnostics test/test_message_diagnostics.cpp
ament_add_gtest(test_greenwave_diagnostics test/test_greenwave_diagnostics.cpp
TIMEOUT 60
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
)
ament_target_dependencies(test_message_diagnostics
ament_target_dependencies(test_greenwave_diagnostics
rclcpp
std_msgs
diagnostic_msgs
)
target_link_libraries(test_message_diagnostics message_diagnostics)
target_include_directories(test_message_diagnostics PUBLIC
target_link_libraries(test_greenwave_diagnostics greenwave_diagnostics)
target_include_directories(test_greenwave_diagnostics PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)
target_compile_features(test_message_diagnostics PUBLIC c_std_99 cxx_std_17)
target_compile_features(test_greenwave_diagnostics PUBLIC c_std_99 cxx_std_17)

ament_add_gtest(test_minimal_publisher
test/test_minimal_publisher.cpp
Expand All @@ -144,7 +149,7 @@ if(BUILD_TESTING)
sensor_msgs
diagnostic_msgs
)
target_link_libraries(test_minimal_publisher message_diagnostics)
target_link_libraries(test_minimal_publisher greenwave_diagnostics)
target_include_directories(test_minimal_publisher PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
Expand Down
9 changes: 9 additions & 0 deletions greenwave_monitor/config/greenwave_monitor.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**:
ros__parameters:
# All topics declared in greenwave_diagnostics will be automatically monitored
# if detected at startup.
greenwave_diagnostics:
/params_from_yaml_topic:
enabled: true
expected_frequency: 10.0
tolerance: 5.0
70 changes: 58 additions & 12 deletions greenwave_monitor/examples/example.launch.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (c) 2025, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
# Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand All @@ -12,51 +12,97 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import os

from ament_index_python.packages import get_package_share_directory
from launch import LaunchDescription
from launch.actions import LogInfo
from launch_ros.actions import Node


def generate_launch_description():
config_file = os.path.join(
get_package_share_directory('greenwave_monitor'),
'config',
'greenwave_monitor.yaml'
)
return LaunchDescription([
Node(
package='greenwave_monitor',
executable='minimal_publisher_node',
name='minimal_publisher1',
name='minimal_publisher_imu',
output='log',
parameters=[
{'topic': 'imu_topic', 'frequency_hz': 100.0}
{
'topic': '/imu_topic', 'frequency_hz': 100.0,
'greenwave_diagnostics': {
'/imu_topic': {'expected_frequency': 100.0, 'tolerance': 5.0}
}
}
],
),
Node(
package='greenwave_monitor',
executable='minimal_publisher_node',
name='minimal_publisher2',
name='minimal_publisher_image',
output='log',
parameters=[
{'topic': 'image_topic', 'message_type': 'image', 'frequency_hz': 30.0}
{
'topic': '/image_topic', 'message_type': 'image', 'frequency_hz': 30.0,
'greenwave_diagnostics': {
'/image_topic': {'expected_frequency': 30.0, 'tolerance': 5.0}
}
}
],
),
Node(
package='greenwave_monitor',
executable='minimal_publisher_node',
name='minimal_publisher3',
name='minimal_publisher_string',
output='log',
parameters=[
{'topic': 'string_topic', 'message_type': 'string', 'frequency_hz': 1000.0}
{
'topic': '/string_topic', 'message_type': 'string', 'frequency_hz': 1000.0,
'greenwave_diagnostics': {
'/string_topic': {'expected_frequency': 1000.0, 'tolerance': 10.0}
}
}
],
),
Node(
package='greenwave_monitor',
executable='greenwave_monitor',
name='greenwave_monitor',
executable='minimal_publisher_node',
name='minimal_publisher_params_from_yaml',
output='log',
parameters=[
{
'topic': '/params_from_yaml_topic', 'message_type': 'imu',
'frequency_hz': 10.0, 'enable_greenwave_diagnostics': False
}
],
),
Node(
package='greenwave_monitor',
executable='minimal_publisher_node',
name='minimal_publisher_no_startup_monitor',
output='log',
parameters=[
{'topics': ['/imu_topic', '/image_topic', '/string_topic']}
{
'topic': '/no_startup_monitor_topic', 'message_type': 'imu',
'frequency_hz': 1.0, 'enable_greenwave_diagnostics': False
}
],
),
Node(
package='greenwave_monitor',
executable='greenwave_monitor',
name='greenwave_monitor',
output='log',
parameters=[config_file]
),
LogInfo(
msg='Run `ros2 run r2s_gw r2s_gw` in another terminal to see the demo output '
msg='Follow the instructions to setup r2s_gw in the README.md, then run '
'`ros2 run r2s_gw r2s_gw` in another terminal to see the demo output '
'with the r2s dashboard.'
),
)
])
8 changes: 4 additions & 4 deletions greenwave_monitor/greenwave_monitor/ncurses_frontend.py
Original file line number Diff line number Diff line change
Expand Up @@ -335,10 +335,10 @@ def curses_main(stdscr, node):
diag.latency.ljust(REALTIME_DELAY_WIDTH)
if diag.latency != '-' else 'N/A'.ljust(REALTIME_DELAY_WIDTH))

# Get expected frequency
expected_hz, tolerance = node.ui_adaptor.get_expected_frequency(topic_name)
if expected_hz > 0:
expected_freq_display = f'{expected_hz:.1f}Hz'.ljust(12)
# Get expected frequency with tolerance
expected_freq_str = node.ui_adaptor.get_expected_frequency_str(topic_name)
if expected_freq_str != '-':
expected_freq_display = expected_freq_str.ljust(14)

# Color coding based on status
if is_monitored:
Expand Down
Loading