Architecture
The safety island hosts the Autoware trajectory follower and talks to the
main compute over DDS. This page describes how the pieces fit together at
runtime on the supported runtime targets. The controller logic is shared
across backends via a platform abstraction layer
(actuation_module/include/platform/); Zephyr and FreeRTOS targets provide
different backend implementations under that layer.
Two-domain DDS topology
The main compute and the safety island live on separate CycloneDDS domains:
Domain 1 — Autoware main compute (full ROS 2 graph).
Domain 2 — Safety island runtime target (CycloneDDS, no ROS 2 runtime).
A ros2 domain_bridge instance running on the main compute forwards
exactly the topics the safety island needs between the two domains. The
list is fixed in demo/bridge/bridge-config.yaml.
Full topic list with message types: DDS topics.
The SI’s authoritative supervised output,
/control/safety_island/approved_request, and the re-enable input,
/control/safety_island/reenable, stay on domain 2; the E2E rig’s single
CARLA actuator consumes the former and the rig tools publish the latter
there. The demo bridge above carries the legacy control_cmd topic only.
See DDS topics and VisionPilot–Safety Island control contract.
The default AVH / Zephyr FVP TAP demo domains are configured through
demo/cyclonedds.xml. S32Z hardware (Zephyr or FreeRTOS) uses
demo/cyclonedds-s32z2.xml so Domain 2 binds the host NIC on the board LAN
rather than tap0. The FreeRTOS POSIX local validation flow uses
demo/cyclonedds.posix.xml to pin Domain 2 to a multicast-capable host
interface. The key tunables are shared across the domains:
MaxMessageSize = 1400B— matches the safety-island MTU.AllowMulticast = spdp— SPDP discovery over multicast, application traffic unicast.In
demo/cyclonedds.xml, Domain 2 pins its interface totap0for the AVH VPN or Zephyr FVP TAP path.In
demo/cyclonedds-s32z2.xml, Domain 2 pins its interface to the host LAN address (default192.168.0.1) for S32Z hardware.In
demo/cyclonedds.posix.xml, Domain 2 pins its interface toSAFETY_ISLAND_DDS_INTERFACEfor the FreeRTOS POSIX local path.If discovery stalls, verify the selected interface — see Troubleshooting.
Controller node
The entry point is actuation_module/src/main.cpp. It brings up DHCP,
optionally syncs time via SNTP (CONFIG_ENABLE_SNTP), and instantiates
a single Controller node. The controller is defined in
actuation_module/src/autoware/autoware_trajectory_follower_node/src/controller_node.cpp.
At construction the controller:
Declares a control period. Default 150 ms. Upstream Autoware uses 30 ms; the safety island runs slower because the MPC solve is the dominant cost on a Cortex-R class core.
Declares a stale-output timeout of 0.5 s. The
isTimeOuthelper still exists incontroller_node.cpp, but the call is currently disabled in the timer callback. Input readiness is handled byprocessDataand the supervisor: before an input has ever arrived the tick publishesHOLD; once a source has been seen, its own arrival watchdog governs, and a stale selected candidate or vehicle feedback latchesSI_STOPuntil the explicit re-enable (see VisionPilot–Safety Island control contract).Instantiates the lateral controller (
mpc— only mode currently supported) and the longitudinal controller (pid).Creates the subscriptions and publishers listed in DDS topics; the set depends on the startup mode/source.
Starts a periodic timer that runs
callbackTimerControleveryctrl_period.
RTOS primitives
The common abstraction layer under actuation_module/include/common/
hides runtime-specific primitives behind small interfaces:
node/node.hpp— thread and timer wrappers. The common code uses a POSIX-style API; the platform layer supplies compatible stack and threading definitions for Zephyr and FreeRTOS.dds/— CycloneDDS publisher/subscriber templates with ROS 2 topic-name translation.clock/clock.hpp— monotonic clock, optional SNTP-backed wall clock.logger/logger.hpp— throttled logging.
This layering means replacing the RTOS backend is a question of swapping
these four headers, not rewriting the controller. The FreeRTOS backend
under include/platform/freertos/ demonstrates this in practice.
Build pipeline
build.sh drives the selected runtime target pipeline.
For Zephyr targets (zephyr-fvp and zephyr-s32z):
Compiles the CycloneDDS host tools (IDLC) under
build/cyclonedds_host.Invokes
west buildwith the selected target (fvp_baser_aemv8r_smpors32z270dc2_rtu0_r52@D).Produces
build/zephyr-fvp/zephyr/zephyr.elforbuild/zephyr-s32z/zephyr/zephyr.elfunless-dselects another directory.
For freertos-posix:
Builds the CycloneDDS host tools.
Builds a static CycloneDDS target library for the POSIX runtime.
Configures and builds
actuation_module/freertos.Produces
build/freertos-posix/actuation_freertosunless-dselects a different directory.
For freertos-s32z2:
Builds the CycloneDDS host tools.
Cross-builds CycloneDDS for Cortex-R52 using the S32Z2 toolchain file.
Configures and builds
actuation_module/freertos_s32z2with NXP SDK and S32 Config Tools inputs.Produces
build/freertos-s32z2/actuation_freertos_s32z2.elfunless-dselects a different directory.
IDL messages under
actuation_module/src/autoware/autoware_msgs/ are compiled to C by
IDLC and linked into the firmware. The Autoware C++ packages
(autoware_mpc_lateral_controller, etc.) are compiled directly against
the selected runtime backend; there is no ROS 2 runtime on the safety island.