Ground drive activity
Remote-side activity for any robot exposing intent:ground-drive-2d
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.
Manifest
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.
UI layout
- Top region — a
CarSteeringControlAdapter-derived widget (joystick or steering-wheel surface). Writes the vertical axis tointent:ground-drive-2d.forwardand the horizontal axis tointent:ground-drive-2d.yaw. - Middle region — bound keys (P for parking brake, Space for horn). When the active stanza exposes the bound port kind, the indicator lights up; pressing the key writes to the port.
- Bottom region —
OptionalPortBankmounted with the manifest'sabsorbspatterns, 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). - Bottom-anchored — the standard Done button per the project's button-placement rule.
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.
Lobe-side counterparts
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.
Class hierarchy
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.
Phase history
- Phase CIV-2 —
ActivityManifest,OptionalPortBank,PortBoundActivityhost. - Phase CIV-3 —
differential_drive+legged_gait_2dlobes shipped. - Phase CIV-4a —
RemoteSteeringActivityrenamed toGroundDriveActivity; manifest declaration added; cross-lobe testing. - Phase CIV-4b — load-time tolerance: personalities that still reference the legacy
RemoteSteeringActivityid rewrite toGroundDriveActivityon read.
Related
- Channels reference — the channel/stanza model the activity binds against.
- Configure Fixo Controller — how the upstream preset declares a ground-drive-capable stanza.
- Author scenes — combine ground-drive with multi-channel scenes.
- Pilot CNC-shield rig — a worked example of driving a real rig with Ground Drive.