01
Landmark Tour
Schedule → Service Call → Action, sending a goal and waiting on its feedback.
7 nodes
- rosTopicNextMessage
- rosServiceCall
- rosAction
Demo · live · read-only
A self-contained showcase for the ROS 2 node package: a simulated rover that offers real ROS 2 topics, services and actions, eleven n8n workflows that drive it, and a read-only live view on the public web. Everything the workflows do shows up on screen.
Read-only at the protocol level, not by convention: x11vnc runs with
-viewonly, so the server never applies pointer or keyboard events
whatever a client sends. Rosbridge itself is bound to localhost and is not on the
internet. Open the viewer on its own.
Telemetry
connecting
The watchdog fires below 25 %: it turns the LED red, preempts whatever mission is running and sends the rover to the dock.
Your turn
Both of these command the same robot you are watching above. Send it somewhere and the landmark tour is preempted; the trail it draws is the evidence.
Workflow 03. The dropdown is built from /rover/landmarks, a latched
topic, so the places come from the robot rather than from the form.
Workflow 07. The agent is given plain tools and fills in every ROS name, type and payload itself, so nothing about this robot is hardcoded in the workflow. Try “what interfaces does the rover have, and send it to the tree”.
The chat is public and every message spends model tokens, so it starts only when you ask it to.
Watch the robot. Read-only at the protocol level — x11vnc runs with -viewonly, so the server never applies pointer or keyboard events no matter what a client sends.
Every workflow that drives the rover, on the canvas that runs them. Viewing is behind the n8n owner login.
A public form with a dropdown of places on the map — lake, tree, house, mountain, dock. Works from a phone.
A webhook that captures the robot camera topic and returns it as a JPEG.
Written from the live ROS graph on request, not from a file. Whatever the robot exposes right now is what it documents.
The n8n node package, the demo compose stack, the rover node and all eleven workflows.
The robot is turtlesim wrapped in a rover-shaped interface: a battery that drains while driving, a dock that recharges it, an e-stop, and a map with landmarks drawn on it so a demo can talk about places rather than coordinates. n8n reaches it over a rosbridge WebSocket on the internal Docker network.
Two things are worth pointing at. The custom message types are discovered at runtime —
rover_interfaces is a real ROS 2 interface package with nested messages, and nothing
about them is hardcoded in n8n. And every interface documents itself: each one publishes a
latched <name>/desc topic saying what it is for, which is how an agent
that has never seen this robot can still work out what to call.
Three choices keep it safe to leave on the internet: rosbridge is bound to localhost and never exposed, the live view is read-only at the protocol level rather than by convention, and the workflows that only observe use a credential that is refused at the node level if it tries to publish or call a service.
┌─ n8n editor (owner login)
Internet ─ Caddy ─┤
(TLS) └─ live view (read-only, public)
internal network
n8n ──ws──▶ ros2 container
├─ rosbridge + rosapi (not exposed)
├─ turtlesim on Xvfb
├─ x11vnc -viewonly ─▶ noVNC
├─ rover_node.py
└─ camera_node.py Actions
/rover/navigate_to Drives to one point. Feedback carries distance remaining; cancellable. /rover/patrol Visits named waypoints in order, feedback per waypoint, optional looping. Services
/rover/set_led Sets the status LED, which is also the trail colour. /rover/dock Drives home and starts charging. Preempts a running mission. /rover/emergency_stop Engages or releases the e-stop. /rover/reset_demo Full reset: battery, e-stop, trail, back to the centre. Topics
/rover/status Rover state at 2 Hz. Embeds the battery and the current waypoint. /rover/battery Charge and charging state at 1 Hz. /rover/events One JSON message per event — this is what the watchdog triggers on. /rover/camera/compressed The screen, published as a camera topic at 2 Hz. Eleven workflows
These are the running workflows, on a real n8n canvas — pan and zoom them, open a node to see its parameters, or copy the JSON and import it into your own n8n. Click a canvas once before it takes the scroll wheel. The same workflows are live in the editor, behind the owner login.
01
Schedule → Service Call → Action, sending a goal and waiting on its feedback.
7 nodes
02
Topic Trigger with a conditions filter, so the workflow only wakes for messages that matter.
4 nodes
03
An n8n Form with a dropdown of places, driving an Action with live feedback.
3 nodes
04
Service Trigger — n8n advertises a ROS service that ROS can call.
3 nodes
05
Action Trigger and Respond — n8n advertises an action server, sends feedback, then succeeds.
6 nodes
06
Webhook → Capture Image, returning a JPEG from a camera topic.
3 nodes
07
An AI agent with vision: it discovers the graph, drives the rover, and looks through its camera.
15 nodes
08
Housekeeping — calls /rover/reset_demo every hour so the demo stays clean.
3 nodes
09
The model plans, n8n executes: plain language in, a JSON plan out, executed step by step.
8 nodes
10
Runtime discovery turned into an operator manual, written from the live ROS graph.
9 nodes
11
The same trigger as 02, but an agent decides whether to dock, finish, or e-stop.
9 nodes · inactive
Ships inactive on purpose: it listens to the same battery_low event as workflow 02, so running both means two things racing to command the rover. Turn 02 off before turning this on — the pair is meant to be shown as a before/after, fixed logic against a reasoned decision.
From the real rover
The eleven above were written to show what a node does. These five came off the n8n instance that drives the physical rover, and were written to get work done — swapping an end effector, running a sampling campaign, walking a maintenance checklist. They are longer, they retry, and they call each other. Shown here read-only: identifiers have been pseudonymised, and the hardware they name is not on the simulated rover.
Drill a core, weigh it, file the result
The full sampling run as one operator-driven sequence: drive to the sampling site, photograph it, drill out a core, drop it in the onboard container, weigh it and photograph the result. The drill is driven entirely through its own ROS service surface — man_lower_drill, man_up, man_unload, target speed up and down — while max_depth and the load cell are read back from topics between steps. Depth and mass end up on an Asana task, so the science record writes itself.
52 nodes · 24 ROS
Drilling · Unload · Tare · Weigh Sample · Set Parameters · Take Photo · Put drilling values into Asana task · Initialize
A manipulator working a switch panel
The largest workflow here, and the one that looks least like a script: an operator walks a panel of switches, sockets and rods, and at each step n8n moves the arm, hands control to a learned policy, and checks whether it worked. Failures fall through to a retry or a manual skip that re-enables the spacemouse, so a stuck switch stalls one step instead of the run. Vision comes from /detect_board_objects; the arm is posed through ROS parameters and actions.
80 nodes · 24 ROS
Set the main Switch to On · Set four switches to on position · Three rotary switches · Insert plug into socket · Turn rotary power switches · Place plate on electromagnet · Change Tool
Pick up and drop off end effectors
Swapping the arm's end effector, which is the kind of job that is all edge cases. The coupler is locked and unlocked by publishing to /wecant/TCC/Lock/Set, the gripper is homed over a service, and /joint_states plus the gripper's own absolute-position topic are read back to confirm the tool actually seated. /shake_gripper is exactly what it sounds like — a deliberate wiggle to prove the tool is latched before the arm trusts it.
25 nodes · 8 ROS
Named joint positions, three ways in
The small one, and the one most worth copying. A named position goes in, /move_to_joint_positions gets called, and that is the whole workflow — but it exposes itself three ways at once: a form for a human, a webhook for a script, and an execute-workflow trigger so every other workflow here can reuse it. The position names come from an n8n data table rather than being hardcoded, so the vocabulary is editable without touching the graph.
7 nodes · 1 ROS
A chat agent with the robot as its tool belt
The production sibling of the demo's workflow 07. Nothing about the robot is hardcoded: the agent lists nodes, expands services and topics into concrete field definitions, reads messages, calls services and looks through the camera, filling in every ROS name and payload itself. It can also search, create and update Asana tasks, so "check the gripper and open a ticket if it is sticking" is one sentence rather than two systems.
18 nodes · 10 ROS