Skip to main content
cerulion ros2 attach points Cerulion at a robot that is already running ROS 2. It discovers the live DDS topics, generates a bridge graph for the ones whose types resolve, and runs it — so those topics become ordinary Cerulion topics you can echo, record, visualize, and consume from your own nodes. Run it on the robot, or on a machine on the robot’s DDS network.

Look before you write

--dry-run prints the discovery report and stops: it writes nothing and runs nothing.
The report tells you which topics resolved to a known type and which did not. A topic whose type Cerulion cannot resolve is left out of the generated graph — add the message definition to your workspace and re-run if you need it.

Read the migration section

Every attach report ends with a MIGRATION section — no flag, --dry-run included. It groups the discovered processes by whether they could run on Cerulion transport directly instead of being bridged, and prints the commands that would do it:
The restart unit is the process — one DDS participant, which is the granularity the ROS 2 graph gives attach. A process is restartable today when every message type on its endpoints already resolves locally, restartable after the write when a type was resolved during this attach and consent still has to materialize the .msg files, and stays bridged when a type resolves nowhere. Endpoints attach cannot attribute to a node are counted as topics rather than processes, and their line says so: no ros_discovery_info record was seen for them, which is either a vendor or raw-DDS process or a node table the discovery window did not observe. Where such a topic’s type does resolve, the line still tells you what a restart would buy. On a robot that publishes no node table at all, the section says plainly that no restartable process can be named, and prints no command block — there is no process to name in it. Paste the ros2: block into a graph file and fill in each package and executable: DDS discovery sees endpoints, not launch metadata, so attach cannot know which package ships a node. See Or run the ROS 2 nodes on Cerulion transport below.
ROS plumbing endpoints — parameter services, /rosout, /parameter_events, ros_discovery_info — are left out of the judgment. Every ROS 2 node carries them under any RMW, so counting them would mark every stock node unrestartable. A process that exposed nothing else is listed as having no message endpoints seen.
The section is rendered from the discovery data attach already holds. It opens no extra network, never blocks, and changes no outcome or exit code.

Generate and run the bridge

It writes graphs/go2.yaml plus graphs/go2.bridge.yaml, asks you to confirm, and then runs the bridge. Use --yes for scripts and non-interactive shells.
--robot-name is not the network identity. The name that shows up in cerulion topic list and over mDNS comes from the machine’s hostname, or from CERULION_ROBOT_IDENTITY if you set it.

See the data on your desk

The generated graph bridges the robot’s topics and nothing else — no visualization node is staged on the robot, which keeps the robot’s job to shipping raw frames. To look at the data, work from your own machine:
Then connect to the robot in Cerulion Studio and check the topics you want to watch. Your desk demands each topic, the frames are mirrored into desk-local shared memory, and decoding and rendering happen there — see Visualize a running graph. See Reach remote robots.

Consume a bridged topic from your own node

A bridged topic is a normal topic, so wire an input to it by absolute name:
An absolute source with no in-graph producer is an external topic: Cerulion does not own it, and other publishers attach to it freely.

Record a bridged system

A bridge run records like any other run, and a recording of one plays back as a robot substitute when the robot is not available:
Use plain bag play for a bridge recording. A bridge node reads a live device rather than computing from its graph inputs, and --resim all re-executes every node in the bag — including the bridge, against DDS that is no longer there. See Record and replay a run.

Or run the ROS 2 nodes on Cerulion transport

Bridging carries another robot’s DDS traffic across. When the ROS 2 nodes are yours to launch, run them on Cerulion transport instead of bridging to them — swap the command, not the stack:
Everything after run or launch reaches ros2 untouched, and Cerulion stages the child so ROS 2 loads rmw_cerulion — the nodes’ topics land on the same shared-memory transport your native nodes use. This is Unix only. See cerulion ros2. The topics keep their ROS names verbatim: a ROS 2 publisher on /camera/image_raw is the Cerulion topic /camera/image_raw, leading slash included, so you wire an #[input] to it and record it under the name ROS 2 already uses. Each of those publishers also registers its topic with the machine’s network plane, so a ROS 2 node’s output is announced and demandable from your desk exactly like a native node’s — see Reach remote robots. A ROS 2 publisher has no graph YAML to size its payloads in, so each variable-length message type gets the same per-type shared-memory budget Cerulion gives one of its own outputs of that schema — a type Cerulion does not know takes 128 MiB. A message larger than its budget fails to publish, loudly; raise the ceiling for that type with CERULION_RMW_SLICE_CEILING:
To bring both halves of a mixed robot up from one file, declare the ROS 2 processes as ros2: entries beside your native nodes and run cerulion graph run:
graph run spawns and supervises each entry; a ros2: entry declares no ports, so its topics meet native nodes by absolute topic name. See ros2: entries.

Next steps

Message types

The 254 built-in ROS 2 messages that resolve out of the box.

Record and replay a run

Bag a bridged system and play it back without the robot.