Attach to an Existing ROS 2 Stack
ros2_medkit discovers a running ROS 2 graph at runtime and builds the SOVD entity tree with no manifest and no changes to your nodes. This guide covers the common case of pointing the gateway at a stack you did not launch yourself (for example Nav2, MoveIt, or Autoware), including the cross-process ROS 2 setup that any external node needs.
The short version
If you install ros2_medkit from a binary release into the same ROS 2 environment as your stack, it already shares the RMW, domain and distro. Source it and run the gateway; it discovers the live graph:
source /opt/ros/jazzy/setup.bash
ros2 run ros2_medkit_gateway gateway_node
# SOVD entity tree + faults at http://localhost:8080/api/v1/
Everything below is for the case where medkit runs in a different environment than your stack (a separate container, image, or install).
Match the ROS 2 environment
medkit talks to your stack over DDS like any other ROS 2 process. Four things must line up, or the gateway sees an empty graph:
Distro. ROS 2 distros do not interoperate over DDS. Run the gateway on the same distro as the target stack (Humble with Humble, Jazzy with Jazzy).
RMW implementation. Both sides must use the same RMW. If your stack runs CycloneDDS, set it for the gateway too:
export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp
The RMW you select must be installed in the gateway’s environment. A binary install pulls in the default RMW; install the matching
ros-<distro>-rmw-*package for any other implementation.Domain ID.
ROS_DOMAIN_IDmust match the stack (default is 0).Discovery reachability. The processes must reach each other’s DDS discovery: same host, a shared network, or - for containers - a shared network namespace (see Containers).
Run the gateway against the graph
Runtime discovery is the default; no manifest is required. The gateway builds the SOVD tree from whatever is on the graph:
ros2 run ros2_medkit_gateway gateway_node
# nodes -> SOVD Apps
curl -s http://localhost:8080/api/v1/apps | jq '.items | length'
# whole-system faults (from /diagnostics, /rosout, aborted actions via the bridges)
curl -s http://localhost:8080/api/v1/faults | jq
Containers
When the gateway runs as a container attaching to a stack on the host, give it access to the host’s DDS traffic and match the environment:
# With --network host the gateway shares the host's ports directly
# (no -p needed); reach the API at http://localhost:8080.
docker run --rm \
--network host \
-e ROS_DOMAIN_ID=0 \
-e RMW_IMPLEMENTATION=rmw_cyclonedds_cpp \
ghcr.io/selfpatch/ros2_medkit-jazzy:latest
If the stack itself runs in a container, share its network namespace instead of the host network:
docker run --rm --network container:<stack_container> \
-e ROS_DOMAIN_ID=0 \
-e RMW_IMPLEMENTATION=rmw_cyclonedds_cpp \
ghcr.io/selfpatch/ros2_medkit-jazzy:latest
Note
On hosts with a small net.core.rmem_max, CycloneDDS may warn about the
socket receive buffer. Basic operation is unaffected; if a large-throughput
stack needs it, raise net.core.rmem_max or point CYCLONEDDS_URI at a
tuned cyclonedds.xml.
Web UI
The web UI is a separate service served from its own origin, so the gateway
must allow that origin via CORS. Set cors.allowed_origins to your UI
origin(s) in the gateway params. See Web UI (ros2_medkit_web_ui) and Docker Deployment. Restrict
origins and enable authentication (Configuring Authentication) for production.
Verify
curl -s http://localhost:8080/api/v1/health # -> healthy
curl -s http://localhost:8080/api/v1/apps | jq '.items | length' # your nodes
curl -s http://localhost:8080/api/v1/faults | jq '.items | length' # active faults
Troubleshooting
Symptom |
Likely cause |
|---|---|
Empty entity tree / no apps discovered |
RMW, |
Gateway loads but the stack uses CycloneDDS |
|
Web UI shows “Failed to fetch” |
CORS: the gateway is not allowing the UI’s origin. |
Cannot reach the gateway from another host |
Bind host is loopback; set |