Package for handling execution of RobBDD models using ROS 2 communication. A GUI tool is also available for visualizing test results.
- Python DSL/model packages:
- Other Python dependencies include RDFLib, textX, Trinary, PyYAML, NumPy, and SciPy.
- ROS dependencies include
rclpy,ament_index_python,rosidl_runtime_py,simulation_interfaces,bdd_ros2_interfaces,builtin_interfaces,geometry_msgs,std_msgs, andunique_identifier_msgs. - The desktop visualizer requires PySide6, while the web visualizer requires aiohttp.
A mockup setup is available for testing communication between the test coordinator node and
a mockup behaviour action server, which cycles through a pick-and-place state machine and publishes
the expected events and trinary messages. A more detailed tutorial on the interactions of these
components, including observation providers and simulation-backed execution, is available in the
bdd-dsl execution tutorial.
To run the mockup setup:
-
Run the mockup launch file:
ros2 launch bdd_exec_ros2 launch_mockup.yaml
-
(Optional) Run the web visualizer and open http://127.0.0.1:8080:
ros2 run bdd_exec_ros2 web_visualizer
The existing desktop visualizer remains available with:
ros2 run bdd_exec_ros2 visualizer
When status timestamps use the simulated
/clock, run the visualizer with ROS time enabled:ros2 run bdd_exec_ros2 web_visualizer --ros-args -p use_sim_time:=true
-
Trigger test execution:
ros2 topic pub /bdd/start std_msgs/msg/Empty "{}" -1
bdd_coordination_node.py loads BDD models
from RDF graphs or RobBDD sources and, when triggered, sends a goal for each scenario variation to a
behaviour action server.
user_story optionally selects one full UserStory URI from the loaded graph.
Leave it empty to run all stories; use it when imported contracts also contain
reference scenarios that should not run in this execution setup.
By default, scene_setup_mode is none and variations retain their concurrent execution behavior.
Set it to simulation to prepare variations sequentially through SimInterface: the coordinator
loads or resets the exact scene instance, spawns its invariant and variable-selected elements, and
starts the behaviour only after setup succeeds. simulation_service_namespace defaults to /, and
world_entity_name defaults to world.
The complete observation-provider contract, ObservationManager API, evaluator forms, and
simulation polling lifecycle are documented in the
bdd-dsl execution tutorial.
For example, with a working simulator exposing ROS 2 simulation_interfaces services:
ros2 launch bdd_exec_ros2 launch_mockup_robbdd.yaml \
scene_setup_mode:=simulation \
simulation_service_namespace:=/ \
world_entity_name:=worldrecord_execution.py records the configured topic set,
waits for the configured trigger-topic subscriber, and publishes one empty trigger message to start the
coordinator. The configuration contains a trigger_topic and named topic_sets, for example:
trigger_topic: "/bdd/start"
topic_sets:
icra-sim:
- "/bdd/status"
- "/bdd/events"Run it with the config file and topic-set name. For the RobBDD mockup launch:
ros2 launch bdd_exec_ros2 launch_mockup_robbdd.yaml
ros2 run bdd_exec_ros2 record_execution \
"$(ros2 pkg prefix bdd_exec_ros2)/share/bdd_exec_ros2/config/mockup_recording.yaml" \
mockupThe bag is written under the current directory by default, in a timestamped directory named after the
selected topic set, such as icra-sim-20260902T143012123456Z/. Use --output-dir to choose another
parent directory. --startup-delay controls rosbag discovery startup, and --listener-timeout
bounds waiting for the coordinator. If no subscriber appears, recording is stopped
and the command exits with an error.
sim_interface_test.py is an interactive
reference client that showcases the main SimInterface APIs:
| Command | SimInterface API |
Purpose |
|---|---|---|
list-features |
get_sim_features() |
Display the simulator's advertised capabilities and spawn formats. |
load-scene |
setup_scene() |
Load or reset a world, spawn the selected SceneX instance, and start simulation. |
get-pose |
get_element_pose() |
Query the current stamped pose of a scene element. |
reset |
reset_simulation() |
Perform a basic simulation reset. |
The tool assumes a running simulator with a working ROS 2 simulation_interfaces setup, such as
one provided by Gazebo or Isaac Sim. It does not start or configure the simulator itself.
After a successful load-scene, the simulation is left playing.
Set the installed example path and inspect the simulator:
MODEL="$(ros2 pkg prefix bdd_exec_ros2)/share/bdd_exec_ros2/models/robbdd/lab.scenex"
ros2 run bdd_exec_ros2 sim_interface_test list-features
ros2 run bdd_exec_ros2 sim_interface_test load-scene --scene-model "$MODEL"
ros2 run bdd_exec_ros2 sim_interface_test get-pose \
--scene-model "$MODEL" --element-id lab_env:dex_cube
ros2 run bdd_exec_ros2 sim_interface_test resetget-pose expands --element-id as a CURIE using the SceneX graph namespaces and queries an
already-loaded entity; it does not load or reset the scene. Use --service-namespace when the
simulation services are namespaced, and --world-entity-name when the simulator's world entity is
not named world.
The web_visualizer.py script serves a seekable
timeline at http://127.0.0.1:8080. It groups events, scenarios, behaviours, and observation-policy
trinaries into lanes and exposes their details without a JavaScript framework. It subscribes only
to coordinator status; the event lane is reconstructed from each scenario's embedded event history.
Available options are:
-t, --topic(default:/bdd/status)--host(default:127.0.0.1)--port(default:8080)
The original visualizer.py desktop UI remains
available.
The RobBDD
mockup model includes a no-collision policy. Run it with simulate_collision:=true to see the
policy fail and its affected bodies reported in the visualizer:
ros2 launch bdd_exec_ros2 launch_mockup_robbdd.yaml simulate_collision:=true
ros2 run bdd_exec_ros2 web_visualizer
ros2 topic pub /bdd/start std_msgs/msg/Empty "{}" -1Without collision messages, the policy defaults to a successful no collision recorded result.
Custom RobBDD observation policies now reference evaluator classes, for example
bdd_exec_ros2.observation.TargetsDoNotCollideEvaluator, which own their result and reason.
mockup_behaviour_node.py cycles through states of a finite-state machine (FSM) for a pick-and-place behaviour while sending events and trinary messages expected by the BDD coordinator node. The FSM Python implementation is generated from the FSM model using coord-dsl.
To set up a ROS 2 Python virtual environment,
allow the environment to use the system ROS 2 Python packages, for example with
uv in zsh:
source /opt/ros/jazzy/setup.zsh
cd $ROS_WS_HOME # where the 'src' folder is located
uv venv --system-site-packages venv
touch ./venv/COLCON_IGNORE
colcon buildThe included setup.cfg installs Python entry points in the location expected by ROS 2.
Now you can activate both environments with:
source "$ROS_WS_HOME/venv/bin/activate"
source "$ROS_WS_HOME/install/setup.zsh"