Write Device Bridge Drivers¶
The Device Bridge runs on a small computer next to the sensors and serves their data to Stellar X. It connects any RGB-D camera, IMU or wheel board for which it has a driver: one Python class on the sensor computer. The drivers that come with the bridge, for Intel RealSense D400 cameras, the TurtleBot3 OpenCR board and simulated devices, are examples; write a driver of the same kind for your own device. Nothing on the controller is rebuilt or modified.
This page is for developers. To install the bridge and connect it to the Station, see Device Bridge.
1. Driver Classes¶
A driver is one Python class for one piece of hardware. It subclasses Device and each capability the hardware has: Camera, Imu or Wheels. One class may provide several, as the OpenCR driver provides both Imu and Wheels. The interfaces are documented in device_bridge/devices/base.py, and device_bridge/devices/simulated.py is the smallest complete example.
| Class | You implement |
|---|---|
Device |
open(): connect, or raise an exception with a clear message. close(): stop and release the hardware; safe to call twice. self.options holds the device's configuration block. |
Camera |
camera_info() returns CameraInfo(width, height, fx, fy, cx, cy) of the aligned output; read_frame(timeout_s) returns RgbdFrame(rgb, depth_mm, capture_unix_ns) or None |
Imu |
read_imu() returns ImuSample(gyro, accel, orientation_xyzw, source_time_ns), or None when nothing is new |
Wheels |
joint_count; read_joints() returns JointState(positions, velocities, efforts, source_time_ns) or None; set_velocities(rad_per_s); stop() sets zero speed and releases the motors |
A minimal IMU driver:
# device_bridge/devices/my_imu.py
from device_bridge.devices.base import Device, Imu, ImuSample
import vendor_sdk # placeholder: your IMU's SDK
class MyImu(Device, Imu):
def open(self):
self.sensor = vendor_sdk.open(self.options.get("port", "/dev/ttyUSB0"))
self.last_ns = 0
def close(self):
if getattr(self, "sensor", None) is not None:
self.sensor.close()
self.sensor = None
def read_imu(self):
raw = self.sensor.latest() # newest sample; never wait for one
if raw is None or raw.timestamp_ns <= self.last_ns:
return None # nothing new since the last call
self.last_ns = raw.timestamp_ns
return ImuSample(gyro=raw.gyro_rad_s, # rad/s, sensor axes
accel=raw.accel_m_s2, # m/s², gravity included
orientation_xyzw=raw.quaternion_xyzw,
source_time_ns=raw.timestamp_ns) # must increase
Select it in the configuration as driver: device_bridge.devices.my_imu:MyImu, or register a short name in DRIVERS in device_bridge/devices/__init__.py. Keep your drivers in device_bridge/devices/ so that install.sh copies them, and add your SDK's Python package to requirements.txt. python -m unittest discover -s tests checks the bridge end to end with the simulated devices.
Rules every driver follows:
- Units: radians, rad/s, m/s² with gravity included (+9.81 m/s² upward at rest), depth in millimeters as 16-bit integers (0 = no measurement), times in nanoseconds. Wheel positions are continuous and do not wrap at 2π.
- Frames: IMU data in the sensor's own axes, with
orientation_xyzwthe sensor's attitude in the world. Camera images in the optical frame (x right, y down, z forward), depth aligned to the RGB image, both rectified without distortion. Do not rotate data into the robot's frame; the mounting belongs in the map bundle. - Time:
source_time_nsmust increase; a monotonic clock is fine. A camera'scapture_unix_nsis the capture time on the wall clock. - Timing:
read_imuandread_jointsreturn at once;read_frameblocks for at most its timeout. Copy images out of buffers that the SDK reuses. - Safety:
stop()must stop and release the motors. The bridge calls it when the controller switches its drive off and when commands pause forcommand_timeout_s.
2. Protocol¶
The Device Bridge and Isaac Bridge send the same messages over ZeroMQ on TCP. The bridge listens; the Station's gateways connect.
| Port | Direction | Contents | Station node |
|---|---|---|---|
| 53335 | bridge → controller | RGB-D frames (16-bit depth in millimeters and 8-bit RGB) and the camera intrinsics | Camera gateway |
| 53334 | bridge → controller | IMU samples and wheel states | IMU gateway, Actuator gateway |
| 53333 | controller → bridge | Wheel commands: velocity while the drive is on, limp when it is off | Actuator gateway |
Every message carries the robot name, and each gateway takes only the messages of its own name. A slow link drops old frames instead of queuing them. The byte layouts are documented in docs/protocol.md in the repository.