sensor.*.register capability
in its manifest.
The driver layer exists in both agent SDKs. Python drivers
subclass the abstract base classes in
ados.sdk.drivers. Rust
drivers implement the matching trait in ados-sdk::drivers. The two
are method-for-method equivalents: the same discover / open /
close / capabilities preamble, the same candidate / capabilities
/ session shapes, the same kind-specific streaming methods. A driver
plugin can be authored in either language. Set agent.runtime in the
manifest to python or rust to pick.Why a driver layer
Hardware-driver plugins are the highest-value class of extensions. A vendor shipping a thermal camera, a LiDAR, a custom GPS, a payload actuator, or a vendor-specific gimbal wants their hardware to “just work” once installed. They do not want to fork the agent. They want a stable interface that says “implement these methods and we will route the rest.”The six driver kinds
All six share the same shape in both languages:
CameraDriver yields
FrameBuffers. A GpsDriver yields GpsFixes. A GimbalDriver
takes attitude commands. The shared four-method preamble lets the
agent’s peripheral manager handle every kind uniformly, whichever
language the driver is written in. In Python the kind-specific stream
methods return an AsyncIterator. In Rust they return a SampleStream
(a boxed Stream), and the opaque *Session base class becomes a
Session associated type the host hands back as a token.
Lifecycle
- The plugin’s
on_starthook constructs the driver and registers it with the peripheral manager. In Python that isperipheral_manager.register_camera_driver(driver); in Rust it isctx.peripheral_manager.register_camera_driver(driver_ref). The manifest must declare the matchingsensor.camera.registercapability or registration is rejected. - The peripheral manager calls
discover()on every registered driver at boot and on USB / serial hotplug events. Each driver reports a list ofXCandidates for devices it claims it can open. - Multiple drivers may claim the same device. The peripheral manager arbitrates among the candidates and opens one of them.
- The winning driver gets
open(candidate, config)called against it.configis the operator-edited config validated againstconfig-schema.json. - The driver yields data through its kind-specific stream method
(
frame_iterator,fix_iterator,state_iterator, etc.). - On unload or hotplug-disappear,
close(session)runs.
Registration capabilities
A driver registers under asensor.*.register capability that the
manifest must declare. Camera, depth, lidar, imu, and payload drivers
each gate on their own capability (sensor.camera.register,
sensor.depth.register, sensor.lidar.register,
sensor.imu.register, sensor.payload.register). Gimbal, GPS, and
ESC drivers do not have dedicated capabilities in the current catalog;
they register under sensor.payload.register. The per-kind pages note
which capability each one uses.
Errors
Python drivers raise fromados.sdk.drivers.errors. Rust drivers
return the DriverError enum from ados-sdk::drivers (every driver
method returns DriverResult<T>).
DriverError is the base. DriverDeviceNotFound says “the
candidate disappeared between discover and open.” DriverPermissionDenied
says “the device exists but the agent process cannot open it”
(missing udev rule, locked USB, etc.). The Rust enum mirrors these:
DeviceNotFound and PermissionDenied carry the same meaning,
InvalidParam is returned for an unknown set_param name or an
unknown actuate action, and NotSupported is returned for an
optional capability a device does not have (a rate command on a
position-only gimbal, RTCM injection on a non-RTK GPS). Other carries
any predictable, recoverable condition that does not fit a named kind.
The host catches these, logs them, and surfaces them in the GCS
plugin event stream. A Python driver that raises bare Exception
(or a Rust driver that panics) is treated as crashed and the plugin is
moved to the circuit-breaker state per the lifecycle rules.
Where to go next
- Camera driver for the worked example, including the FLIR Lepton USB UVC reference plugin.
- Vendor binaries when your driver
needs a closed-source
.soto talk to the device. - Hardware testing for SITL, hardware-in-loop, and rig-on-bench testing patterns.