The canonical Remote-side control surface for any robot whose active stanza exposes intent:ground-drive-2d. Replaces the pre-CIV RemoteSteeringActivity. Drives ground vehicles (wheeled, tracked, legged-via-legged_gait_2d) interchangeably — the activity doesn't know about robot morphology; that lives entirely on the Agent side.
Ground Drive declares the canonical CIV manifest:
| Field | Value |
|---|---|
name |
"Ground Drive" |
requiredIntents |
{ "intent:ground-drive-2d" } |
channelScope |
"*" (matches any channel) |
binds |
switch:parking_brake → P, momentary:horn → Space |
absorbs |
switch:*, momentary:*, axis:*, event:* |
A channel is eligible whenever its active stanza exposes both intent:ground-drive-2d.forward and .yaw. Multiple eligible channels = the activity binds to the first one in channel declaration order.
CarSteeringControlAdapter-derived widget (joystick or steering-wheel surface). Writes the vertical axis to intent:ground-drive-2d.forward and the horizontal axis to intent:ground-drive-2d.yaw.OptionalPortBank mounted with the manifest's absorbs patterns, with the bound port kinds excluded so they don't double-render. Renders one strip per kind family (switch toggles, momentary press-and-hold, axis sliders, event buttons).The activity is enabled iff manifestMatches() returns true for at least one channel's active stanza. When disabled, the widget remains visible but greyed; switching the Agent to a non-eligible stanza (e.g. a turret-aiming stanza) greys the activity in real time.
The activity is morphology-agnostic. The lobe consuming the intent values is the one currently active on the matching channel:
| Lobe | Source | Behaviour |
|---|---|---|
differential_drive |
Phase CIV-3 canonical | Two-side accumulating step targets; drives wheels or tracks based on the preset's actuator semantic tags |
legged_gait_2d |
Phase CIV-3 intent face | Thin wrapper over the 6-input LeggedGaitLobe, mapping forward → velocity, yaw → turn, others zero |
A custom lobe declaring intent:ground-drive-2d on its input ports also Just Works — the activity doesn't know or care about the implementation.
Activity (libwidgets/components/navigation)
└── PortBoundActivity (libfixo/fixo/widget)
└── GroundDriveActivity (libremote/remote)
PortBoundActivity provides manifest gating + OptionalPortBank mounting. GroundDriveActivity adds the joystick / steering-wheel widget on top.
ActivityManifest, OptionalPortBank, PortBoundActivity host.differential_drive + legged_gait_2d lobes shipped.RemoteSteeringActivity renamed to GroundDriveActivity; manifest declaration added; cross-lobe testing.RemoteSteeringActivity id rewrite to GroundDriveActivity on read.