- Keep control in your controller, designed, tested and, where required, certified for that purpose, and use answers only as one input to it.
- Keep independent safety controls, limits and fallback behaviour that bring and keep the system in a safe state without any answer, including when an answer is late, dropped, unavailable or wrong.
- Test and validate the system together with DecisionNode in the conditions it will be used in, before use and after every change of model, settings or software.
- In practice: subscribe to
decisionfrom your own logic, checkok, readheader.stampto know how old the frame was, and treat a missing or stale answer as no answer. Control loops shows the pattern.
The repository brings DecisionNode to ROS 2 as two packages: decisionnode_ros, an rclpy node that reads frames from an image topic, asks your questions at a rate you set and publishes each set of answers, and decisionnode_msgs, the Decision and Answer messages and the DecideOnce service. Supported: ROS 2 Jazzy (Ubuntu 24.04), Humble (Ubuntu 22.04) and Rolling, on amd64 and arm64.
Install from source#
mkdir -p ~/dn_ws/src && cd ~/dn_ws/src
git clone https://github.com/Bynn-Intelligence/decision-node-ros2.git
cd ~/dn_ws
source /opt/ros/$ROS_DISTRO/setup.bash
rosdep install --from-paths src --ignore-src -yQuickstart (5 minutes)#
You need ROS 2 Jazzy, Humble or Rolling, the packages built as above, and an API key from the console.
- 1
Start a camera#
A USB webcam with
usb_cam, or a recorded bag that has an image topic.sudo apt install ros-$ROS_DISTRO-usb-cam ros2 run usb_cam usb_cam_node_exe - 2
Run the node#
In another terminal, with your API key in the environment:
source ~/dn_ws/install/setup.bash export DECISIONNODE_API_KEY=your-api-key ros2 launch decisionnode_ros decisionnode.launch.py - 3
Read the decisions#
One
decisionnode_msgs/Decisiona second, answering the three example questions (is there a person, what hazard is in view, how many people).ros2 topic echo /decision
Configuration#
Copy config/example.yaml, edit it, and launch with params:=/. Questions live under questions, in the order ids gives, each a truth, choice, score, number, point or box.
decisionnode:
ros__parameters:
image_topic: /image_raw
model: decisionnode-flash
max_rate_hz: 2.0
questions:
ids: [blocked, surface, door]
blocked:
type: truth
instructions: Is the path ahead blocked?
surface:
type: choice
instructions: What is the floor surface ahead?
options: [concrete, carpet, grass, gravel, wet]
door:
type: box
instructions: Where is the nearest door?| Parameter | Default | Meaning |
|---|---|---|
image_topic | image | The image topic to read |
compressed | false | true to read sensor_msgs/CompressedImage, sent as it is |
state_topic | empty | A std_msgs/String topic of JSON sent with every frame as the state |
model | decisionnode-flash | The model to ask |
max_rate_hz | 1.0 | The most decisions a second |
max_in_flight | 1 | Requests running at once |
timeout_s | 10.0 | The time one request may take |
session_mode | false | true to stream frames into one live session instead of one request each |
The node keeps one slot for the newest frame: a newer frame replaces a waiting one and nothing queues, and each Decision says in frames_dropped how many were replaced. A failed request publishes a Decision with ok: false and the API's error_type, so your logic always knows no answer came. The decide_once service answers the configured questions about the image you send, or the latest frame.
The API key#
The key comes from DECISIONNODE_API_KEY, or from the file api_key_file names (keep it at mode 600). It is never a parameter's value, because parameters can be read by anything on the ROS graph, and the node never logs it. Without a key the node refuses to start.
The source, the full README and the issues are in the repository. MIT licence.