Skip to main content
The Cerulion lion wiring a camera input to a monitor output, building a two-node pipeline

What you’ll build

In this tutorial you build a complete two-node graph:
  • A periodic publisher (sensor) that emits a sensor_msgs/Image on a fixed interval.
  • A data-triggered consumer (detector) that fires each time a new image arrives and publishes a geometry_msgs/PoseArray of detections.
You will wire them into a graph, run it, and watch the messages flow with cerulion topic echo in a second terminal. Figure: The two-node graph you build. The periodic sensor node publishes a sensor_msgs/Image; the data-triggered detector fires on each image and publishes a geometry_msgs/PoseArray.
This guide assumes the cerulion CLI is installed and cargo is on your PATH. If not, follow Installation first.

Build it step by step

Create and enter a workspace

A workspace is the project container that holds your nodes, graphs, and schemas.
Expected output:

Create the publisher node

Create a sensor node with one output port named image carrying a sensor_msgs/Image. Because it has no inputs, a source-only node must declare a non-data trigger policy; here, a 33 ms period.
Expected output:
The period is set with --policy period_ms=33. Note the underscore and the =.

Create the consumer node

Create a detector node whose image input is a trigger (-T), so the node fires whenever an image arrives. Give it an output named detections carrying a geometry_msgs/PoseArray.
Expected output:
-T and -o each take two values in the order SCHEMA NAME. The trigger input also sets the node’s policy to fire on that input’s data.

Fill in the publisher's tick

Open nodes/sensor/src/lib.rs and replace its contents with the node below. Each tick stamps the image dimensions and bumps a frame counter.
height and width are fixed fields, written straight to shared memory. encoding is a variable-length field, so it is listed in #[output(data, encoding)] — once listed, plain assignment works for it too.

Fill in the consumer's tick

Open nodes/detector/src/lib.rs and replace its contents with the node below. Each tick reads the latest image dimensions and counts a detection.
The #[input(trigger)] attribute on image is what makes detector fire on each incoming image. The node-level macro has no policy attribute because the trigger comes from the field.

Build both node crates

Compile each node into a loadable library. These commands shell out to cargo.
Expected output:

Create a graph

Create an empty graph named perception with an explicit topic prefix of perception. The -n/--prefix flag fixes the prefix so the topic names are predictable; without it, the prefix would default to your machine’s hostname.
Expected output:
Cerulion composes each topic name as {prefix}/{node_id}/{output_name}. With the prefix perception, the sensor instance’s image output publishes to perception/sensor/image.

Stage the nodes and wire them

Add an instance of each node to the graph. For detector, wire its image input to the sensor instance’s image output with -I.
Expected output:
-I takes the input port name followed by its source. The [sensor,image] form means “the image output of the node instance sensor.”

Run the graph

Run the graph. The default is live mode — the graph wakes and processes messages as they arrive. The run continues until you stop it with Ctrl+C.
Leave this terminal running.

Watch the topics in a second terminal

Open a new terminal. Topic discovery needs no workspace. List the active topics, then echo the one carrying images:
topic echo pretty-prints sensor_msgs/Image, so you will see the image dimensions and encoding update as frames arrive. Stop echoing with Ctrl+C.
Because you set the prefix to perception, the topic is perception/sensor/image. Always run cerulion topic list first to confirm the exact names before echoing.
You should see image messages streaming in the echo terminal while the graph runs. Your two-node graph is live: sensor publishes images on a 33 ms period and detector fires on each one. Press Ctrl+C in the run terminal to stop the graph.
The Cerulion lion on a podium with a gold medal celebrating a first successful graph run

Next steps

Concepts

The mental model behind workspaces, nodes, graphs, topics, and schemas.

Guides

Task-focused walkthroughs for defining nodes and wiring graphs.

CLI reference

Every command and flag, with synopses and examples.