Skip to content

Latest commit

 

History

History
259 lines (187 loc) · 14.3 KB

File metadata and controls

259 lines (187 loc) · 14.3 KB

ROS2 Executer Plugin (avlite-executer-ROS2)

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.

Comparison with other executers and bridges

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.

Prerequisites

  • ROS 2 (Humble or newer recommended)
  • Optional: autoware_auto_msgs for 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: ROSExecuter

Install full dependencies: pip install -r requirements-full.txt.

Multiprocess architecture

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
Loading

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:

  1. World — steps BasicSim, publishes ego pose, optional ground truth and LiDAR
  2. Planner — runs the configured local planner (compute_planner), publishes trajectories
  3. Controller — runs the configured controller (compute_controller), publishes control commands
  4. 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).

Components

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.

ROS topic reference

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

Message types

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).

Configuration

Enable ROSExecuter

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: StanleyController

Shipped profiles using ROSExecuter include SAN, Carla_Town10, and ros.

Plugin settings (plugin_avlite-executer-ROS2.yaml)

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).

Sensor and visualization toggles

Execution flags (see Settings naming for c41_* keys):

  • c41_provide_lidar — world worker publishes LiDAR when true at bootstrap
  • c41_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 to c41_provide_lidar)
  • bridge_provide_ground_truth_detection — request GT bridge (maps to c41_provide_ground_truth)
  • show_occupancy_flow — draw perception occupancy heatmap from exec.pm
  • show_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.

Visualization sync

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.

Logging

Worker processes log through a standard AVLite → ROS → GUI pipeline:

  1. Forward — attach_worker_logging() attaches a handler on the avlite logger tree; records are published to /rosout from each worker node.
  2. Collect — CollectorNode subscribes to /rosout with compatible QoS and routes messages to layer loggers (avlite.c20_planning, avlite.c30_control, etc.).
  3. Display — LogView polls 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_file hides 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.

Usage

GUI

  1. Select a profile with c40_executer_type: ROSExecuter (e.g. SAN).
  2. Click Start/Stop Stack.
  3. 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.

Headless

The same YAML profiles apply:

python -m avlite headless -p SAN

ROS 2 must be sourced in the environment. The headless dashboard shows FPS and ego state; worker logs go to stderr unless configured otherwise.

External Autoware (advanced)

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.

Troubleshooting

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

Related code and tests

  • 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/sync
  • test/plugins/test_ros_executer_sensor_gating.py — GT/LiDAR sync gating
  • test/plugins/test_rosout_log_routing.py — rosout → layer logger routing

See also