The ROS2 Executer plugin runs AVLite's perception, planning, control, and simulation stack across parallel ROS 2 worker processes while keeping the visualizer in the main process. Workers communicate only through ROS topics—there are no shared planner objects or locks across process boundaries.
!!! tip "When to use"
Use ROSExecuter when you want Autoware-compatible topics, a realistic ROS deployment shape, or to stress-test the stack with process isolation. For single-process prototyping, use SyncExecuter or AsyncThreadedExecuter instead.
| Mode | Class / plugin | Sim runs in | Typical use |
|---|---|---|---|
| Single-process sync | SyncExecuter |
Main process | Fast iteration, debugging |
| Single-process async | AsyncThreadedExecuter |
Main process threads | Overlapped perceive/plan/control |
| Multiprocess ROS | ROSExecuter (avlite-executer-ROS2) |
World worker + planner/controller/perception workers | ROS-shaped stack, GUI mirrors via topics |
| External ROS world | ROS2WorldBridge (avlite-bridge-ROS2) |
External ROS nodes | Live Autoware/CARLA stack as the world only |
ROSExecuter replaces the in-process world with BasicSim inside a WorldNode subprocess. The main process uses TopicMirrorBridge so plots, spawn, and teleport still work through the familiar AVLite interfaces.
- ROS 2 (Humble or newer recommended)
- Optional:
autoware_auto_msgsfor native Autoware message types (use_autoware_msgs: true) - Plugin registered in the execution profile:
c40_community_plugins:
avlite-executer-ROS2: related-repos/avlite-executer-ROS2
c40_executer_type: ROSExecuterInstall full dependencies: pip install -r requirements-full.txt.
flowchart TB
subgraph main [Main process - GUI]
RE[ROSExecuter]
Coll[CollectorNode]
Bridge[TopicMirrorBridge]
ProxyP[ProxyLocalPlanner]
ProxyC[ProxyController]
RE --> Coll
RE --> Bridge
RE --> ProxyP
RE --> ProxyC
end
subgraph workers [Worker subprocesses]
W[WorldNode - BasicSim]
P[PlannerNode]
C[ControllerNode]
Perc[PerceptionNode]
end
Coll <-->|ROS topics| W
Coll <-->|ROS topics| P
Coll <-->|ROS topics| C
Coll <-->|ROS topics| Perc
W -->|control_out| C
W -->|localization| P
W -->|localization| Perc
W -->|world_gt / lidar| Perc
P -->|trajectory_out| C
Perc -->|perception_topic| P
On Start Stack, the main process creates a CollectorNode and spins it on a background thread. The first step() starts four worker subprocesses via ROSProcessSupervisor:
- World — steps
BasicSim, publishes ego pose, optional ground truth and LiDAR - Planner — runs the configured local planner (
compute_planner), publishes trajectories - Controller — runs the configured controller (
compute_controller), publishes control commands - Perception — runs the configured perception strategy, publishes tracked objects and a PM snapshot for the GUI
The main process holds mirrors only: ProxyLocalPlanner and ProxyController for plots, TopicMirrorBridge for world/LiDAR/spawn, and exec.pm for stack perception overlays.
!!! note "Parallel workers"
Each worker has its own timer and ROS node. Workers do not wait on each other synchronously; coupling is entirely through topic publish/subscribe at configured rates (sim_dt, replan_dt, control_dt, perception_dt).
| Component | Module | Role |
|---|---|---|
ROSExecuter |
p41_ros_launcher.py |
Orchestrates collector + workers; step() syncs ROS data into AVLite state |
CollectorNode |
p41_ros_launcher.py |
Subscribes to worker outputs; publishes spawn, teleport, global plan, exec flags |
WorldNode |
p45_world_node.py |
Runs BasicSim; publishes localization, optional GT and LiDAR |
PlannerNode |
p43_planner_node.py |
Runs local planner; publishes local trajectory |
ControllerNode |
p44_controller_node.py |
Runs controller; publishes control command to world |
PerceptionNode |
p42_perception_node.py |
Runs perception; publishes tracked objects + full PM snapshot |
TopicMirrorBridge |
topic_mirror_bridge.py |
Main-process world facade for visualization and spawn forwarding |
ProxyLocalPlanner / ProxyController |
p47_proxy_strategies.py |
Display-only mirrors of worker planner/controller output |
ROSLocalPlanner and ROSController are internal aliases used during factory bootstrap—they do not appear in strategy dropdowns. Select real planner/controller names (e.g. GreedyLatticePlanner, StanleyController) in execution settings; the plugin maps them to worker subprocesses.
Topics are configured in plugin_avlite-executer-ROS2.yaml (repo defaults under configs/, user overrides under ~/.config/avlite/). Defaults below match the default profile.
| Setting | Default topic | Publisher | Subscriber(s) | Purpose |
|---|---|---|---|---|
localization_topic |
/localization/kinematic_state |
World | Planner, Perception, Collector | Ego pose |
trajectory_out_topic |
/avlite/planning/trajectory |
Planner | Controller, Collector | Local plan |
control_out_topic |
/avlite/control/control_cmd |
Controller | World | Vehicle command |
perception_topic |
/perception/object_recognition/tracking/objects |
Perception | Planner, Collector | Tracked agents (planner input) |
perception_viz_topic |
/avlite/perception/pm_snapshot |
Perception | Collector | Full PM for GUI (occupancy, trajectories, clusters) |
world_gt_topic |
/avlite/world/ground_truth |
World | Perception | Ground-truth agents when enabled |
lidar_topic |
/avlite/world/lidar |
World | Perception, Collector | Simulated LiDAR (JSON) |
global_plan_topic |
/avlite/planning/global_plan |
Collector | Planner | Global plan updates from GUI |
call_replan_topic |
/avlite/exec/call_replan |
Collector | Planner | Enable/disable replan loop |
call_control_topic |
/avlite/exec/call_control |
Collector | Controller | Enable/disable control loop |
spawn_agent_topic |
/avlite/world/spawn_agent |
Collector | World | Spawn NPC from GUI |
teleport_ego_topic |
/avlite/world/teleport_ego |
Collector | World | Teleport ego from GUI |
reset_agents_topic |
/avlite/world/reset_agents |
Collector | World | Clear agents |
/rosout |
— | All nodes | Collector | Worker logs forwarded to GUI |
When use_autoware_msgs: true (default in most profiles), worker topics use Autoware types where applicable (VehicleKinematicState, Trajectory, VehicleControlCommand, BoundingBoxArray). LiDAR, PM snapshot, global plan, spawn, and teleport use JSON std_msgs/String payloads.
Set use_autoware_msgs: false to use JSON strings on all worker topics (useful without Autoware installed).
In c40_execution.yaml (profile section):
c40_executer_type: ROSExecuter
c40_community_plugins:
avlite-executer-ROS2: related-repos/avlite-executer-ROS2
c40_default_plugins:
- p50_headless_mode
c40_bridge: BasicSim # world runs in WorldNode; bridge is TopicMirrorBridge in main
c40_perception: PerceptionPipeline
c40_local_planner: GreedyLatticePlanner
c40_controller: StanleyControllerShipped profiles using ROSExecuter include SAN, Carla_Town10, and ros.
| Field | Description |
|---|---|
sim_dt |
Fixed world integration step when pace_sim is true; max-step cap when wall-time sim is on |
replan_dt |
Planner tick period when pace_replan is true |
control_dt |
Controller tick period when pace_control is true |
perception_dt |
Perception tick period when pace_perception is true |
pace_sim / pace_control / pace_replan / pace_perception |
If true, throttle to the matching Δt; if false, best-effort (WorldNode uses wall-clock Δt when pace_sim is false). Apply on next worker launch. |
compute_planner |
Planner class name for the planner worker |
compute_controller |
Controller class name for the controller worker |
use_autoware_msgs |
Autoware message types vs JSON strings |
WorldNode._sim_tick is the simulate step (ZOH on last control command); ControllerNode only recomputes and publishes. This matches Sync/Async _simulate_step / _control_step.
Topic names can be retargeted per profile to match an external stack (e.g. Autoware topic layout).
Execution flags (see Settings naming for c41_* keys):
c41_provide_lidar— world worker publishes LiDAR when true at bootstrapc41_provide_ground_truth— world worker publishes GT agents to perception
Visualization flags in c50_visualization.yaml:
bridge_provide_lidar_data— request LiDAR in the GUI (maps toc41_provide_lidar)bridge_provide_ground_truth_detection— request GT bridge (maps toc41_provide_ground_truth)show_occupancy_flow— draw perception occupancy heatmap fromexec.pmshow_lidar_global/show_lidar_frenet— LiDAR scatter visibility
!!! note "LiDAR visibility"
LiDAR must be enabled in both execution settings (c41_provide_lidar) and visualization (bridge_provide_lidar_data, show_lidar_global). Profile YAML often sets bridge_provide_lidar_data: false by default—check your active profile if LiDAR does not appear.
The GUI never runs BasicSim directly when ROSExecuter is active. Data flows:
Ego, plan, control — CollectorNode receives worker topics → _sync_ros_to_avlite() updates ego_state, ProxyLocalPlanner, and ProxyController.
!!! note "ROS pose authority (vs Sync GT / localize)"
SyncExecuter fills stack pose (pm.ego_vehicle / exec.ego_state) from GT world ego or a localization strategy. ROSExecuter does not use that Sync pose-update path: worker localization → apply_worker_ego_state → PM / TopicMirrorBridge / display ego is the ROS equivalent. Do not gate _sync_ros_to_avlite on GT LOCALIZATION; keep field writes in place so the PM ego alias stays mutable.
Stack perception (GT off) — Perception worker publishes /avlite/perception/pm_snapshot each tick. Collector fills exec.pm with agents, occupancy flow, trajectories, and detection clusters. The local plot uses exec.pm when the Ground Truth bridge checkbox is off.
Ground truth overlay (GT on) — World publishes world_gt_topic → perception worker → tracked objects on perception_topic. When GT bridge is enabled, agent boxes can also mirror onto TopicMirrorBridge.perception_model for the GT overlay path in the plot.
LiDAR — World publishes lidar_topic → Collector copies into TopicMirrorBridge._lidar_buffer when c41_provide_lidar is true.
Race boundaries — TopicMirrorBridge reloads boundary segments when map settings change; the executer detects map setting changes each step() and refreshes the bridge.
Spawn / teleport — GUI calls on TopicMirrorBridge forward JSON commands through the collector to the world worker.
Worker processes log through a standard AVLite → ROS → GUI pipeline:
- Forward —
attach_worker_logging()attaches a handler on theavlitelogger tree; records are published to/rosoutfrom each worker node. - Collect —
CollectorNodesubscribes to/rosoutwith compatible QoS and routes messages to layer loggers (avlite.c20_planning,avlite.c30_control, etc.). - Display —
LogViewpolls the root handler queue and renders lines in the log panel.
To see worker output in the GUI:
- Enable Core and the relevant layer checkboxes (Planning, Control, Perception, Execution)
- Keep File logging off if you want on-screen output (
log_to_filehides the panel) - Set log level to INFO or DEBUG as needed
Worker node names (avlite_planner, avlite_world, avlite_perception, avlite_controller) map to the corresponding AVLite layer loggers.
- Select a profile with
c40_executer_type: ROSExecuter(e.g.SAN). - Click Start/Stop Stack.
- Workers start automatically on the first simulation step; ego, plan, and perception data appear as topics flow.
Right-click spawn, global plan export, and map selection work as with SyncExecuter; commands are forwarded over ROS topics.
The same YAML profiles apply:
python -m avlite headless -p SANROS 2 must be sourced in the environment. The headless dashboard shows FPS and ego state; worker logs go to stderr unless configured otherwise.
You can point collector subscriptions at external Autoware topics and disable internal workers for integration testing. The primary path documented here is internal workers with BasicSim in the world subprocess.
| Symptom | Things to check |
|---|---|
| No worker logs in GUI | Log layer toggles (Planning/Execution/etc.); log level INFO+; log_to_file off; same ROS_DOMAIN_ID for all processes |
| Empty agent boxes, GT off | Perception enabled in profile; perception worker running; PM snapshot topic in plugin YAML |
| No occupancy heatmap | show_occupancy_flow on; perception produces occupancy_flow |
| No LiDAR in plot | c41_provide_lidar and bridge_provide_lidar_data + show_lidar_global; check profile defaults |
| Stale global plan in planner | Global plan published on map change; planner subscribes to global_plan_topic |
- Plugin source:
avlite/plugins/avlite-executer-ROS2/ - Plugin settings schema:
avlite/plugins/avlite-executer-ROS2/settings.py - Default YAML:
configs/plugin_avlite-executer-ROS2.yaml
Tests:
test/plugins/test_pm_snapshot_commands.py— PM snapshot encode/synctest/plugins/test_ros_executer_sensor_gating.py— GT/LiDAR sync gatingtest/plugins/test_rosout_log_routing.py— rosout → layer logger routing
- Architecture — overall stack design
- Plugin Development — creating custom plugins
- Settings naming — YAML key prefixes and validation