Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

**ros2_medkit** is a ROS 2 diagnostics gateway that exposes ROS 2 system information via a RESTful HTTP API aligned with the **SOVD (Service-Oriented Vehicle Diagnostics)** specification. It models robots as a diagnostic entity tree: **Area -> Component -> App**, with optional **Function** groupings.

**Tech Stack**: C++17, ROS 2 Jazzy/Humble/Rolling, Ubuntu 24.04/22.04
**Tech Stack**: C++17, ROS 2 Jazzy/Humble/Lyrical, Ubuntu 26.04/24.04/22.04

## Package Structure

Expand Down Expand Up @@ -294,7 +294,7 @@ Every code change must include corresponding tests. A feature without tests is n
- **Flag** new `.cpp` source files under `src/core/` that aren't picked up by `gateway_core`'s `GLOB_RECURSE` source list, or new ROS-adapter `.cpp` files that aren't added to the `gateway_ros2` STATIC library target in CMakeLists.txt.
- **Flag** any `#include <rclcpp/...>` or message-package include in a file under `core/` - the layer must stay middleware-neutral. The `gateway_core_purity` linter and `test_gateway_core_smoke` link test enforce this; do not paper over their failures.
- **Flag** new test targets that don't link to `gateway_ros2` (the default), unless the test is intentionally a core-only smoke test linking `gateway_core` directly.
- **Flag** use of `ament_target_dependencies()` - use `medkit_target_dependencies()` instead (removed in Rolling).
- **Flag** use of `ament_target_dependencies()` - use `medkit_target_dependencies()` instead (deprecated in Kilted, removed in ament_cmake 2.8.5+ which Lyrical ships).
- **Flag** direct `find_package(yaml-cpp)` or `find_package(httplib)` - use `medkit_find_yaml_cpp()` / `medkit_find_cpp_httplib()` for multi-distro compatibility.

### Documentation
Expand Down
24 changes: 13 additions & 11 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ jobs:
include:
- ros_distro: humble
os_image: ubuntu:jammy
- ros_distro: rolling
os_image: ubuntu:noble
- ros_distro: lyrical
os_image: ubuntu:resolute
container:
image: ${{ matrix.os_image }}
timeout-minutes: 60
Expand Down Expand Up @@ -58,11 +58,12 @@ jobs:
fi
source /opt/ros/${{ matrix.ros_distro }}/setup.bash
rosdep update
# Linters (clang-tidy / clang-format) are gated to the Jazzy lint job
# in quality.yml, but multiple package.xml files still list them as
# <test_depend>. Their rosdep keys are not registered for noble
# (Rolling), which breaks rosdep install on that runner. Skip them
# on every distro this workflow targets - the linters never run here.
# Linters (clang-tidy / clang-format) only run in the Jazzy quality
# job (quality.yml). Multiple package.xml files still list them as
# <test_depend>, so we skip the rosdep keys here to keep build-and-
# test runners from pulling in linter packages they never use. Also
# defensive against transient binary-deb gaps on newly-released
# distros.
rosdep install --from-paths src --ignore-src -y \
--skip-keys "ament_cmake_clang_tidy ament_cmake_clang_format"

Expand All @@ -85,10 +86,11 @@ jobs:
# FastRTPS 2.6 on Humble has a known use-after-free in the
# discovery-teardown path (EDP::unpairWriterProxy) that segfaults
# peer nodes when the gateway shuts down, so we force CycloneDDS
# there. Rolling + Jazzy ship a newer FastRTPS without that bug
# and hit a separate iceoryx-shared-memory crash under CycloneDDS
# during shutdown ("string capacity was zero for allocated data"),
# so on those distros we keep the default FastRTPS.
# there. Lyrical ships a newer FastRTPS without that bug and hits
# a separate iceoryx-shared-memory crash under CycloneDDS during
# shutdown ("string capacity was zero for allocated data"), so on
# Lyrical we keep the default FastRTPS. (Jazzy still uses
# CycloneDDS - see jazzy-test job below for its rationale.)
RMW_IMPLEMENTATION: ${{ matrix.ros_distro == 'humble' && 'rmw_cyclonedds_cpp' || '' }}
run: |
source /opt/ros/${{ matrix.ros_distro }}/setup.bash
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/docker-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
strategy:
fail-fast: false
matrix:
ros_distro: [jazzy, humble, rolling]
ros_distro: [jazzy, humble, lyrical]

steps:
- name: Checkout repository
Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/opcua-plugin.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ jobs:
os_image: ubuntu:jammy
- ros_distro: jazzy
os_image: ubuntu:noble
- ros_distro: rolling
os_image: ubuntu:noble
continue-on-error: ${{ matrix.ros_distro == 'rolling' }}
- ros_distro: lyrical
os_image: ubuntu:resolute
continue-on-error: ${{ matrix.ros_distro == 'lyrical' }}
container:
image: ${{ matrix.os_image }}
timeout-minutes: 60
Expand Down Expand Up @@ -84,8 +84,8 @@ jobs:
source /opt/ros/${{ matrix.ros_distro }}/setup.bash
rosdep update
# Skip nav2_msgs (vda5050_agent declares it; not available on all
# distros) and the linter rosdep keys. The clang_format / clang_tidy
# keys are not registered for noble (Rolling), and the upstream
# distros) and the linter rosdep keys. Linters only run in the Jazzy
# quality job, so we don't need them installed here. The upstream
# medkit packages have already been switched to QUIET + FOUND for
# those find_package calls so the build degrades gracefully without
# the linter packages installed.
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ Open `coverage_html/index.html` in your browser.

#### CI/CD

All PRs are tested on Ubuntu 24.04 (Jazzy) with parallel lint + test jobs, plus Humble and Rolling (allowed to fail). Coverage is uploaded to Codecov on push to main. All CI jobs use ccache.
All PRs are tested on Ubuntu 24.04 (Jazzy) with parallel lint + test jobs, plus Humble and Lyrical. Coverage is uploaded to Codecov on push to main. All CI jobs use ccache.

### Pull Request Checklist

Expand Down
8 changes: 4 additions & 4 deletions QUALITY_DECLARATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ GitHub Copilot code review is used in addition to human review.

All pull requests must pass CI before merging:

- **Build & Test job:** Full build + unit/integration tests on Ubuntu Noble / ROS 2 Jazzy, Ubuntu Jammy / ROS 2 Humble, and Ubuntu Noble / ROS 2 Rolling (best-effort, allow-failure). Linter tests on Jazzy only
- **Build & Test job:** Full build + unit/integration tests on Ubuntu Noble / ROS 2 Jazzy, Ubuntu Jammy / ROS 2 Humble, and Ubuntu Resolute / ROS 2 Lyrical. Linter tests on Jazzy only
- **Coverage job:** Debug build with coverage. Reports are generated for all PRs as artifacts and uploaded to [Codecov](https://codecov.io/gh/selfpatch/ros2_medkit) on pushes to `main`
- Linting enforced: `clang-format`, `clang-tidy` via `ament_lint_auto`

Expand Down Expand Up @@ -203,9 +203,9 @@ Linter tests are enforced in CI on every pull request.

- **Ubuntu 24.04 (Noble)** with **ROS 2 Jazzy** (primary)
- **Ubuntu 22.04 (Jammy)** with **ROS 2 Humble**
- **Ubuntu 24.04 (Noble)** with **ROS 2 Rolling** (experimental, best-effort)
- **Ubuntu 26.04 (Resolute)** with **ROS 2 Lyrical** (newest LTS, released May 2026)

Jazzy and Humble are the Tier 1 platforms per [REP-2000](https://www.ros.org/reps/rep-2000.html) and are tested in CI. Rolling is tested as best-effort (allow-failure) for forward-compatibility.
Jazzy and Humble are Tier 1 LTS platforms per [REP-2000](https://www.ros.org/reps/rep-2000.html); Lyrical is the newest LTS (May 2026) and is also tested in CI.

---

Expand Down Expand Up @@ -234,7 +234,7 @@ Security issues can be reported via GitHub Security Advisories on the
| Feature tests | Met | 65 tests across unit + integration |
| Coverage | Met | 75% line coverage |
| Linting | Met | clang-format, clang-tidy, ament_lint |
| Platform support | Met | Ubuntu Noble / ROS 2 Jazzy + Ubuntu Jammy / ROS 2 Humble + Rolling (best-effort) |
| Platform support | Met | Ubuntu Noble / ROS 2 Jazzy + Ubuntu Jammy / ROS 2 Humble + Ubuntu Resolute / ROS 2 Lyrical |
| Security policy | Met | REP-2006 compliant |

**Caveat:** Version is 0.3.0 (pre-1.0.0, requirement 1.ii). The REST API is versioned (`/api/v1/`)
Expand Down
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](LICENSE)
[![ROS 2 Jazzy](https://img.shields.io/badge/ROS%202-Jazzy-blue)](https://docs.ros.org/en/jazzy/)
[![ROS 2 Humble](https://img.shields.io/badge/ROS%202-Humble-blue)](https://docs.ros.org/en/humble/)
[![ROS 2 Rolling](https://img.shields.io/badge/ROS%202-Rolling-orange)](https://docs.ros.org/en/rolling/)
[![ROS 2 Lyrical](https://img.shields.io/badge/ROS%202-Lyrical-blue)](https://docs.ros.org/en/lyrical/)
[![Discord](https://img.shields.io/badge/Discord-Join%20Us-7289DA?logo=discord&logoColor=white)](https://discord.gg/6CXPMApAyq)
[![Quality Level 3](https://img.shields.io/badge/Quality-Level%203-yellow)](QUALITY_DECLARATION.md)

Expand Down Expand Up @@ -42,7 +42,7 @@ cd selfpatch_demos/demos/turtlebot3_integration

Open `http://localhost:3000` in your browser. You will see a TurtleBot3 with Nav2, organized into a browsable entity tree with live faults, topic data, and parameter access.

**Build from source** (ROS 2 Jazzy, Humble, or Rolling):
**Build from source** (ROS 2 Jazzy, Humble, or Lyrical):

```bash
source /opt/ros/jazzy/setup.bash # or humble - adjust for your distro
Expand Down Expand Up @@ -148,8 +148,8 @@ This entity model follows the **SOVD (Service-Oriented Vehicle Diagnostics)** st

## 📋 Requirements

- **OS:** Ubuntu 24.04 LTS (Jazzy / Rolling) or Ubuntu 22.04 LTS (Humble)
- **ROS 2:** Jazzy Jalisco, Humble Hawksbill, or Rolling (experimental)
- **OS:** Ubuntu 26.04 LTS (Resolute, for Lyrical), Ubuntu 24.04 LTS (Noble, for Jazzy), or Ubuntu 22.04 LTS (Jammy, for Humble)
- **ROS 2:** Jazzy Jalisco, Humble Hawksbill, or Lyrical Luth (LTS, released May 2026)
- **Compiler:** GCC 11+ (C++17 support)
- **Build System:** colcon + ament_cmake

Expand Down
16 changes: 8 additions & 8 deletions docs/installation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Installation
============

This guide covers installation of ros2_medkit on Ubuntu 24.04 with ROS 2 Jazzy,
Ubuntu 22.04 with ROS 2 Humble, or Ubuntu 24.04 with ROS 2 Rolling.
Ubuntu 22.04 with ROS 2 Humble, or Ubuntu 26.04 with ROS 2 Lyrical.

System Requirements
-------------------
Expand All @@ -14,25 +14,25 @@ System Requirements
* - Requirement
- Version
* - Operating System
- Ubuntu 24.04 LTS (Noble) or Ubuntu 22.04 LTS (Jammy)
- Ubuntu 26.04 LTS (Resolute), Ubuntu 24.04 LTS (Noble), or Ubuntu 22.04 LTS (Jammy)
* - ROS 2 Distribution
- Jazzy, Humble, or Rolling
- Jazzy, Humble, or Lyrical
* - C++ Compiler
- GCC 11+ (C++17 support required)
* - CMake
- 3.22+
* - Python
- 3.10+ (Humble) / 3.12+ (Jazzy / Rolling)
- 3.10+ (Humble) / 3.12+ (Jazzy) / 3.14+ (Lyrical)

Prerequisites
-------------

**ROS 2 Jazzy, Humble, or Rolling** must be installed and sourced. Follow the official installation guide
**ROS 2 Jazzy, Humble, or Lyrical** must be installed and sourced. Follow the official installation guide
for your distribution:

- Jazzy: https://docs.ros.org/en/jazzy/Installation/Ubuntu-Install-Debs.html
- Humble: https://docs.ros.org/en/humble/Installation/Ubuntu-Install-Debs.html
- Rolling: https://docs.ros.org/en/rolling/Installation/Ubuntu-Install-Debs.html
- Lyrical: https://docs.ros.org/en/lyrical/Installation/Ubuntu-Install-Debs.html

.. note::

Expand Down Expand Up @@ -136,8 +136,8 @@ ROS 2 distributions:
# Humble
docker run -p 8080:8080 ghcr.io/selfpatch/ros2_medkit-humble:latest

# Rolling
docker run -p 8080:8080 ghcr.io/selfpatch/ros2_medkit-rolling:latest
# Lyrical
docker run -p 8080:8080 ghcr.io/selfpatch/ros2_medkit-lyrical:latest

The gateway will be available at http://localhost:8080/api/v1/health.

Expand Down
2 changes: 1 addition & 1 deletion docs/troubleshooting.rst
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ parameter changes) only happen when explicitly requested via the API.

**Q: Can I use ros2_medkit with ROS 1?**

No. ros2_medkit requires ROS 2 (Jazzy, Humble, or Rolling). For ROS 1 systems, consider using
No. ros2_medkit requires ROS 2 (Jazzy, Humble, or Lyrical). For ROS 1 systems, consider using
the ``ros1_bridge`` and running ros2_medkit on the ROS 2 side.

**Q: Is ros2_medkit production-ready?**
Expand Down
4 changes: 2 additions & 2 deletions docs/tutorials/docker.rst
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ Images are available for all supported ROS 2 distributions:
- ``ghcr.io/selfpatch/ros2_medkit-jazzy:latest``
* - Humble
- ``ghcr.io/selfpatch/ros2_medkit-humble:latest``
* - Rolling
- ``ghcr.io/selfpatch/ros2_medkit-rolling:latest``
* - Lyrical
- ``ghcr.io/selfpatch/ros2_medkit-lyrical:latest``

Each image includes the gateway and all open-core packages:

Expand Down
2 changes: 1 addition & 1 deletion docs/tutorials/plugin-system.rst
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ providing access to gateway data and utilities:
``create_generic_subscription()``, or ``create_callback_group()``
directly on this node. Issue #375 showed that concurrent rcl
mutations on the gateway node race its internal hash map and
SIGSEGV under load on Rolling. The regression gate in
SIGSEGV under load on Rolling/Lyrical. The regression gate in
``scripts/check_no_naked_subscriptions.sh`` is run in CI and will
fail PRs that add such calls outside the allowlist. Use
``ros2_medkit_gateway::ros2_common::Ros2SubscriptionSlot::create_typed``
Expand Down
3 changes: 2 additions & 1 deletion scripts/check_no_naked_subscriptions.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
# callback-group creation APIs from gateway and fault_manager code outside
# `ros2_common/` is forbidden because it bypasses Ros2SubscriptionExecutor's
# serial worker (or fault_manager's LockedSubscriptionGuard) and reintroduces
# the rcl hash-map race that triggered SIGSEGV on Rolling.
# the rcl hash-map race that triggered SIGSEGV on Rolling (still applicable
# on Lyrical and any future distro that ships the same rcl hash-map code).
#
# Callers in the gateway must go through:
# ros2_medkit_gateway::ros2_common::Ros2SubscriptionSlot::create_typed / create_generic
Expand Down
4 changes: 2 additions & 2 deletions src/ros2_medkit_cmake/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ build acceleration, and centralized linting configuration across all packages.
|--------|-------------|
| `ROS2MedkitCcache.cmake` | Auto-detect and configure ccache with PCH-aware sloppiness settings |
| `ROS2MedkitLinting.cmake` | Centralized clang-tidy configuration (opt-in locally, mandatory in CI) |
| `ROS2MedkitCompat.cmake` | Multi-distro compatibility shims for ROS 2 Humble, Jazzy, and Rolling |
| `ROS2MedkitCompat.cmake` | Multi-distro compatibility shims for ROS 2 Humble, Jazzy, and Lyrical |

### ROS2MedkitCompat

Resolves dependency differences across ROS 2 distributions:

- `medkit_find_yaml_cpp()` - Finds yaml-cpp (namespaced targets on Jazzy, manual fallback on Humble)
- `medkit_find_cpp_httplib()` - Finds cpp-httplib >= 0.14 via pkg-config, CMake config, or vendored fallback (`VENDORED_DIR` param)
- `medkit_target_dependencies()` - Drop-in replacement for `ament_target_dependencies` (removed on Rolling)
- `medkit_target_dependencies()` - Drop-in replacement for `ament_target_dependencies` (removed on Lyrical)
- `medkit_detect_compat_defs()` / `medkit_apply_compat_defs()` - Compile definitions for version-specific APIs

## Usage
Expand Down
25 changes: 15 additions & 10 deletions src/ros2_medkit_cmake/cmake/ROS2MedkitCompat.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
# =============================================================================
#
# Centralizes all dependency resolution workarounds for supporting multiple
# ROS 2 distributions (Humble, Jazzy, Rolling) in a single place.
# ROS 2 distributions (Humble, Jazzy, Lyrical) in a single place.
#
# Usage (in each package's CMakeLists.txt):
# find_package(ros2_medkit_cmake REQUIRED)
Expand All @@ -31,7 +31,7 @@
# medkit_target_dependencies(target ...) - Drop-in ament_target_dependencies replacement
#
# Variables set by medkit_detect_compat_defs():
# MEDKIT_RCLCPP_VERSION_MAJOR — integer (e.g., 16 for Humble, 28 for Jazzy)
# MEDKIT_RCLCPP_VERSION_MAJOR — integer (16=Humble, 28=Jazzy, 32+=Lyrical)
# MEDKIT_ROSBAG2_OLD_TIMESTAMP — ON if rosbag2_storage < 0.22.0 (Humble)
#

Expand All @@ -40,9 +40,11 @@ include_guard(GLOBAL)
# ---------------------------------------------------------------------------
# medkit_find_yaml_cpp()
# ---------------------------------------------------------------------------
# Jazzy's yaml_cpp_vendor exports a namespaced yaml-cpp::yaml-cpp cmake target.
# Humble's yaml_cpp_vendor bundles yaml-cpp but does NOT export the cmake target.
# This macro creates an IMPORTED INTERFACE target when find_package doesn't.
# Jazzy's and Lyrical's yaml_cpp_vendor export a namespaced yaml-cpp::yaml-cpp
# cmake target (Jazzy directly; Lyrical via its Findyaml-cpp.cmake module that
# aliases the upstream yaml-cpp 0.8+ target). Humble's yaml_cpp_vendor bundles
# yaml-cpp but does NOT export the cmake target. This macro creates an IMPORTED
# INTERFACE target when find_package doesn't.
#
# Prerequisite: find_package(yaml_cpp_vendor REQUIRED) must be called before.
# ---------------------------------------------------------------------------
Expand Down Expand Up @@ -120,7 +122,7 @@ endmacro()
# Call AFTER find_package(rclcpp) and optionally find_package(rosbag2_storage).
#
# Sets:
# MEDKIT_RCLCPP_VERSION_MAJOR — integer (16=Humble, 21+=Iron, 28+=Jazzy)
# MEDKIT_RCLCPP_VERSION_MAJOR — integer (16=Humble, 21+=Iron, 28+=Jazzy, 32+=Lyrical)
# MEDKIT_ROSBAG2_OLD_TIMESTAMP — ON if rosbag2_storage < 0.22.0 (Humble)
# ---------------------------------------------------------------------------
macro(medkit_detect_compat_defs)
Expand Down Expand Up @@ -166,11 +168,14 @@ endfunction()
# ---------------------------------------------------------------------------
# medkit_target_dependencies(target [PUBLIC|PRIVATE|INTERFACE] dep1 dep2 ...)
# ---------------------------------------------------------------------------
# Drop-in replacement for ament_target_dependencies that works on Rolling
# (where ament_target_dependencies was removed from ament_cmake).
# Drop-in replacement for ament_target_dependencies that works on Lyrical
# (ament_target_dependencies was deprecated in Kilted / ament_cmake 2.7.3
# and removed in ament_cmake 2.8.5+, which Lyrical ships).
#
# On Humble/Jazzy: delegates to ament_target_dependencies (available).
# On Rolling: uses target_link_libraries with ${dep_TARGETS}.
# On Lyrical: uses target_link_libraries with ${dep_TARGETS}.
# The branch is selected at runtime via if(COMMAND ament_target_dependencies)
# so any future distro keeps working regardless of where the removal lands.
#
# When no visibility keyword (PUBLIC/PRIVATE/INTERFACE) is passed, the macro
# uses the plain target_link_libraries signature. This avoids conflicts with
Expand All @@ -185,7 +190,7 @@ macro(medkit_target_dependencies target)
if(COMMAND ament_target_dependencies)
ament_target_dependencies(${target} ${ARGN})
else()
# Rolling fallback: resolve dependency targets explicitly.
# Lyrical fallback: resolve dependency targets explicitly.
#
# CMake forbids mixing the "plain" and "keyword" (PUBLIC/PRIVATE/INTERFACE)
# signatures of target_link_libraries on the same target.
Expand Down
4 changes: 2 additions & 2 deletions src/ros2_medkit_cmake/design/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ The package provides four CMake modules installed to the ament index:
- ``medkit_find_cpp_httplib()`` - Finds cpp-httplib >= 0.14 via pkg-config, cmake config, or vendored fallback (``VENDORED_DIR`` param)
- ``medkit_detect_compat_defs()`` - Detects rclcpp and rosbag2 versions, sets ``MEDKIT_RCLCPP_VERSION_MAJOR`` and ``MEDKIT_ROSBAG2_OLD_TIMESTAMP``
- ``medkit_apply_compat_defs(target)`` - Applies compile definitions based on detected versions
- ``medkit_target_dependencies(target ...)`` - Drop-in replacement for ``ament_target_dependencies`` that also works on Rolling (where ``ament_target_dependencies`` was removed)
- ``medkit_target_dependencies(target ...)`` - Drop-in replacement for ``ament_target_dependencies`` that also works on Lyrical (where ``ament_target_dependencies`` was removed)

Design Decisions
----------------
Expand All @@ -60,5 +60,5 @@ Multi-Distro Strategy

Rather than maintaining separate branches per ROS 2 distribution, the compat
module detects version numbers at configure time and adapts. This keeps a single
source tree building on Humble, Jazzy, and Rolling without ``#ifdef`` proliferation
source tree building on Humble, Jazzy, and Lyrical without ``#ifdef`` proliferation
in application code.
Loading
Loading