Skip to content

Commit dfbc9e4

Browse files
committed
update readme and fix tests
1 parent 113802a commit dfbc9e4

File tree

4 files changed

+37
-18
lines changed

4 files changed

+37
-18
lines changed

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,21 @@ The diagnostics messages published by greenwave monitor are valid ROS 2 Diagnost
2121

2222
In particular, the messages follow conventions from [Isaac ROS NITROS](https://github.com/NVIDIA-ISAAC-ROS/isaac_ros_nitros), which means configured NITROS nodes can be monitored by greenwave monitor frontends without any additional subscriber overhead. For example the drivers from [Isaac ROS NOVA](https://github.com/NVIDIA-ISAAC-ROS/isaac_ros_nova) can be monitored out of the box. Furthermore, you can set `ENABLE_GLOBAL_NITROS_DIAGNOSTICS=1` to configure all NITROS nodes to publish diagnostics (more info [here](https://nvidia-isaac-ros.github.io/repositories_and_packages/isaac_ros_nitros/isaac_ros_nitros/index.html)).
2323

24+
## Latency Measurements
25+
26+
Latency is calculated as the difference between the current system time and the timestamp in the message header. For this calculation to work correctly:
27+
28+
- The message type must have a `std_msgs/Header` field
29+
- The message type must be in the recognized types list (see `has_header_from_type()` in `greenwave_monitor.cpp`)
30+
- The header timestamp must be in epoch time (not boottime)
31+
32+
If any of these conditions are not met, the latency will be reported as **"N/A"** in the dashboard. This typically occurs when:
33+
- The message type doesn't have a header (e.g., `std_msgs/String`, `geometry_msgs/Twist`)
34+
- The message type is not recognized by greenwave monitor
35+
- The header timestamp is in boottime format instead of epoch time
36+
37+
Currently, message types with headers must be manually registered in the `known_header_types` map in `greenwave_monitor.cpp`. Support for automatic detection of arbitrary message types may be added in the future. In the meantime, if you need support for a commonly used message type, please submit an issue or pull request to add it to the registry.
38+
2439
## Compatibility
2540

2641
Greenwave monitor is a standalone package tested on Humble, Iron, Jazzy, Kilted, and Rolling ROS 2 releases, under Ubuntu 22.04 and Ubuntu 24.04. It does not depend on Isaac ROS.

greenwave_monitor/greenwave_monitor/test_utils.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#
1818
# SPDX-License-Identifier: Apache-2.0
1919

20+
import math
2021
import time
2122
from typing import List, Optional, Tuple
2223

@@ -41,7 +42,6 @@
4142
MANAGE_TOPIC_TEST_CONFIG = TEST_CONFIGURATIONS[2]
4243
MONITOR_NODE_NAME = 'test_greenwave_monitor'
4344
MONITOR_NODE_NAMESPACE = 'test_namespace'
44-
ONE_YEAR_IN_MS = 365 * 24 * 60 * 60 * 1000
4545

4646

4747
def create_minimal_publisher(
@@ -178,7 +178,7 @@ def find_best_diagnostic(
178178
"""Find the diagnostic message with frequency closest to expected."""
179179
best_status = None
180180
best_values = None
181-
best_diff = float('inf')
181+
best_diff = None
182182

183183
for status in diagnostics:
184184
node_str = None
@@ -192,6 +192,8 @@ def find_best_diagnostic(
192192
msg_str = kv.value
193193
elif kv.key == 'current_delay_from_realtime_ms':
194194
latency_str = kv.value
195+
if latency_str == 'N/A':
196+
latency_str = 'nan'
195197

196198
try:
197199
node_val = float(node_str) if node_str is not None else None
@@ -242,9 +244,9 @@ def verify_diagnostic_values(status: DiagnosticStatus,
242244
if message_type == 'string':
243245
if reported_frequency_msg != 0.0:
244246
errors.append(f'String message frequency should be 0.0, got {reported_frequency_msg}')
245-
if reported_latency_ms < ONE_YEAR_IN_MS:
247+
if not math.isnan(reported_latency_ms):
246248
errors.append(
247-
f'String latency should be >= {ONE_YEAR_IN_MS} ms, '
249+
f'String latency should be {math.nan}, '
248250
f'got {reported_latency_ms}')
249251
else:
250252
if abs(reported_frequency_msg - expected_frequency) > tolerance_hz:

greenwave_monitor/include/message_diagnostics.hpp

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include <algorithm>
2121
#include <limits>
2222
#include <cinttypes>
23+
#include <cmath>
2324
#include <mutex>
2425
#include <queue>
2526
#include <string>
@@ -99,7 +100,7 @@ class MessageDiagnostics
99100
prev_timestamp_node_us_ = std::numeric_limits<uint64_t>::min();
100101
prev_timestamp_msg_us_ = std::numeric_limits<uint64_t>::min();
101102
num_non_increasing_msg_ = 0;
102-
message_latency_msg_ms_ = -1;
103+
message_latency_msg_ms_ = std::numeric_limits<double>::quiet_NaN();
103104
outdated_msg_ = true;
104105

105106
diagnostic_publisher_ =
@@ -161,7 +162,7 @@ class MessageDiagnostics
161162
// calculate key values for diagnostics status (computed on publish/getters)
162163
message_latency_msg_ms_ = latency_wrt_current_timestamp_node_ms;
163164
if (message_latency_msg_ms_ > message_diagnostics::constants::kNonsenseLatencyMs) {
164-
message_latency_msg_ms_ = -1;
165+
message_latency_msg_ms_ = std::numeric_limits<double>::quiet_NaN();
165166
}
166167

167168
// frame dropping warnings
@@ -220,7 +221,7 @@ class MessageDiagnostics
220221
values.push_back(
221222
diagnostic_msgs::build<diagnostic_msgs::msg::KeyValue>()
222223
.key("current_delay_from_realtime_ms")
223-
.value(message_latency_msg_ms_ == -1 ?
224+
.value(std::isnan(message_latency_msg_ms_) ?
224225
"N/A" : std::to_string(message_latency_msg_ms_)));
225226
values.push_back(
226227
diagnostic_msgs::build<diagnostic_msgs::msg::KeyValue>()
@@ -280,7 +281,8 @@ class MessageDiagnostics
280281
RCLCPP_ERROR(
281282
node_.get_logger(),
282283
"expected_hz is 0.0. It should be set to a value greater than 0."
283-
" Keeping previous values: expected_dt_us = %" PRId64 ", jitter_tolerance_us = %" PRId64 ".",
284+
" Keeping previous values: expected_dt_us = %" PRId64 ","
285+
" jitter_tolerance_us = %" PRId64 ".",
284286
static_cast<int64_t>(diagnostics_config_.expected_dt_us),
285287
diagnostics_config_.jitter_tolerance_us);
286288
return;
@@ -290,8 +292,8 @@ class MessageDiagnostics
290292
static_cast<int64_t>(message_diagnostics::constants::kSecondsToMicroseconds / expected_hz);
291293
diagnostics_config_.expected_dt_us = expected_dt_us;
292294

293-
const int64_t tolerance_us =
294-
static_cast<int64_t>((message_diagnostics::constants::kSecondsToMicroseconds / expected_hz) *
295+
const int tolerance_us =
296+
static_cast<int>((message_diagnostics::constants::kSecondsToMicroseconds / expected_hz) *
295297
(tolerance_percent / 100.0));
296298
diagnostics_config_.jitter_tolerance_us = tolerance_us;
297299
}
@@ -302,18 +304,18 @@ class MessageDiagnostics
302304
diagnostics_config_.enable_node_time_diagnostics = false;
303305
diagnostics_config_.enable_msg_time_diagnostics = false;
304306

305-
diagnostics_config_.expected_dt_us = 0LL;
306-
diagnostics_config_.jitter_tolerance_us = 0LL;
307+
diagnostics_config_.expected_dt_us = 0;
308+
diagnostics_config_.jitter_tolerance_us = 0;
307309
}
308310

309311
private:
310312
struct RollingWindow
311313
{
312314
int window_size{0};
313315
std::queue<int64_t> interarrival_us;
314-
int64_t sum_interarrival_us{0LL};
316+
int64_t sum_interarrival_us{0};
315317
std::queue<int64_t> jitter_abs_us;
316-
int64_t sum_jitter_abs_us{0LL};
318+
int64_t sum_jitter_abs_us{0};
317319
int64_t max_abs_jitter_us{0};
318320
uint64_t outlier_count{0};
319321

@@ -357,7 +359,7 @@ class MessageDiagnostics
357359
int64_t meanAbsJitterUs() const
358360
{
359361
if (jitter_abs_us.empty()) {
360-
return 0LL;
362+
return 0;
361363
}
362364
return sum_jitter_abs_us / static_cast<int64_t>(jitter_abs_us.size());
363365
}

scripts/docker-test.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ echo "Starting Docker container for ROS 2 $DISTRO..."
5353
echo "Image: $IMAGE"
5454

5555
# Get current directory (should be the greenwave_monitor root)
56-
WORKSPACE_DIR=$(pwd)/../
56+
WORKSPACE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/../"
5757

5858
# Run container with interactive shell, mounting current directory
5959
docker run -it --rm \
@@ -73,9 +73,9 @@ docker run -it --rm \
7373
7474
# Install Python requirements based on ROS distro
7575
if [[ '${DISTRO}' == 'jazzy' || '${DISTRO}' == 'kilted' || '${DISTRO}' == 'rolling' ]]; then
76-
pip3 install --break-system-packages -I pygments -r src/greenwave_monitor/requirements.txt
76+
pip3 install --break-system-packages -I pygments -r /workspace/src/greenwave_monitor/r2s_gw/requirements.txt
7777
else
78-
pip3 install -r src/greenwave_monitor/requirements.txt
78+
pip3 install -r /workspace/src/greenwave_monitor/r2s_gw/requirements.txt
7979
fi
8080
8181
echo '=== Building packages ==='

0 commit comments

Comments
 (0)