Verb Authoring¶
A verb is the unit of robot behaviour in Defined Robotics. Each verb has two files: a YAML metadata file and a Jinja2 template that renders to BehaviorTree.CPP XML. Together they define what a verb requires from the robot, what parameters it accepts, and what BT nodes it produces.
Verb YAML structure¶
name: go_to
description: "Navigate the robot to a specified position"
# Capability gate — compilation fails if any of these are missing from the RDF
required_capabilities:
- differential_drive
- lidar_2d
# Jinja2 template file (in the same directory as this YAML)
template: go_to.xml.j2
# BT primitives this verb relies on (informational)
primitives:
- navigate_to_pose
# Parameters passed to the Jinja2 template
parameters:
x:
type: float
required: true
description: "Target X coordinate (meters)"
y:
type: float
required: true
description: "Target Y coordinate (meters)"
theta:
type: float
required: false
default: 0.0
description: "Target orientation (radians)"
timeout:
type: float
required: false
default: 60.0
description: "Navigation timeout in seconds"
# Output parameters emitted by the BT node (informational)
output_parameters:
error_code:
type: int
description: "Navigation error code"
# ROS dependencies needed at runtime
dependencies:
apt:
- ros-jazzy-nav2-bringup
source:
- repo: https://github.com/Defined-Robotics/defined-platform
ref: trunk
packages: [defined_runtime]
# Runtime node configuration
runtime:
nodes:
- package: nav2_bringup
executable: navigation_launch.py
parameters:
use_sim_time: true
# ROS interface contract
interface:
actions:
- name: /navigate_to_pose
topics:
subscribes: []
publishes: []
Parameter fields¶
| Field | Type | Required | Description |
|---|---|---|---|
type |
string | yes | float, int, string, or bool |
required |
bool | yes | Whether the caller must supply this parameter |
default |
any | no | Default value when parameter is omitted (required if required: false) |
description |
string | no | Human-readable description |
Jinja2 template format¶
The template file renders to one or more BT XML nodes. Parameters are available as Jinja2 variables.
{# go_to.xml.j2 #}
<RetryUntilSuccessful num_attempts="{{ retries | default('3') }}">
<Action ID="GoTo" name="go_to_{{ x }}_{{ y }}"
x="{{ x }}" y="{{ y }}" theta="{{ theta | default('0.0') }}"
frame_id="{{ frame_id | default('map') }}"
server_name="{{ server_name | default('/navigate_to_pose') }}"
timeout="{{ timeout | default('60.0') }}" />
</RetryUntilSuccessful>
Standard Jinja2 filters work — | default(...), | upper, | int, etc. The template receives all parameters from the task step's params dict, with missing optional parameters substituted by their defaults before rendering.
Built-in verbs¶
| Verb | Required capabilities | Parameters | Notes |
|---|---|---|---|
go_to |
differential_drive, lidar_2d |
x (req), y (req), theta (0.0), timeout (60.0), frame_id ("map"), server_name ("/navigate_to_pose"), retries (3) |
Wraps in RetryUntilSuccessful |
explore |
differential_drive, lidar_2d |
timeout (300.0) |
Runs frontier exploration |
report |
— | message ("checkpoint"), topic ("/task_reports"), level ("info") |
Publishes to ROS topic |
wait |
— | duration (req) |
Pauses execution |
capture_image |
rgb_camera |
topic ("/camera/image_raw"), save_path ("/tmp/capture"), timeout (5.0) |
Saves image to disk |
Adding a new verb¶
Step 1. Create the verb directory (or use an existing verbs/ directory):
Step 2. Write the verb YAML (verbs/take_photo.yaml):
name: take_photo
description: "Capture a photo and save to disk"
required_capabilities:
- rgb_camera
template: take_photo.xml.j2
primitives:
- capture_image
parameters:
save_path:
type: string
required: false
default: "/tmp/photos"
description: "Directory to save images"
topic:
type: string
required: false
default: "/camera/image_raw"
description: "Camera topic"
output_parameters:
image_path:
type: string
description: "Path to saved image"
dependencies:
apt:
- ros-jazzy-cv-bridge
source:
- repo: https://github.com/Defined-Robotics/defined-platform
ref: trunk
packages: [defined_runtime]
runtime: {}
interface:
topics:
subscribes:
- /camera/image_raw
Step 3. Write the Jinja2 template (verbs/take_photo.xml.j2):
<Action ID="CaptureImage"
topic="{{ topic | default('/camera/image_raw') }}"
save_path="{{ save_path | default('/tmp/photos') }}" />
Step 4. Use the verb in a task:
name: PhotoPatrol
steps:
- verb: go_to
params:
x: 2.0
y: 1.0
- verb: take_photo
params:
save_path: "/data/patrol_photos"
- verb: report
params:
message: "photo_captured"
Step 5. Compile with your verbs directory:
defined compile tasks/photo_patrol.task.yaml \
--rdf robot.rdf.yaml \
--verbs-dir verbs/ \
-o photo_patrol.bt.xml
Capability validation¶
At compile time, each verb's required_capabilities list is checked against the capabilities declared in the robot's RDF. If any capability is missing, compilation aborts:
To add the capability to your robot, add a module with that capability type to your RDF:
modules:
- name: camera_module
type: camera
capabilities:
- name: vision
type: rgb_camera
parameters:
resolution: [640, 480]
fps: 30
Any string is a valid capability type. Custom verbs can require any type you define — the compiler does a simple string match.