Turret
Command-line tool for STorM32 gimbal controllers. Uses the RC Commands protocol.
Features
- CLI Mode: Direct command-line control
- Daemon Mode: Background service with Unix socket IPC and MAVLink
- Auto-detects STorM32 devices
- Set gimbal angles, pan modes, standby
- Query status and firmware info
- Structured logging with verbosity levels
- Priority-based command arbitration
Installation
Download Binary
Download the latest release from Releases for your platform.
OR:
From source
With a recent Rust installed:
Usage
CLI Mode (Direct Control)
# Basic commands (auto-detects device)
# Manual device specification
# Verbose output for debugging
# Individual axis control
# Pan mode and standby
Daemon Mode (Background Service)
# Start daemon (auto-detects device)
# Or with custom config
# Connect via Unix socket (JSON commands)
|
|
|
|
|
|
# MAVLink on UDP:14550 - use pymavlink or QGroundControl
# Implements Gimbal Manager protocol
The IPC wire format uses snake_case for both the cmd discriminator
and field names — matches the response shape (firmware_version,
pan_mode, ...) and standard JSON conventions. Send {"cmd":"help"}
for the full machine-readable schema.
Yaw calibration
If your gimbal's IMU yaw reading is biased relative to its commanded
zero (typical symptom: set yaw=0 then status returns yaw≠0 by a
fixed amount), calibrate from the daemon — no GUI required:
# Auto-calibrate: daemon centers the gimbal, samples raw IMU yaw,
# stores the bias as the new offset.
|
# → {"status":"ok","data":{"yaw_offset_deg": -4.48, "prior_yaw_offset_deg": 0.0}}
# Or set an explicit value (e.g. from a measurement you took elsewhere):
|
# 0.0 disables the offset:
|
The offset persists to $XDG_STATE_HOME/turret/calibration.toml (default
~/.local/state/turret/calibration.toml) and is auto-loaded on daemon
start. The current offset is included in every status response as
"yaw_offset_deg".
Read-side correction model: commands hit the device exactly as you wrote
them (the gimbal physically goes to the asked-for angle), and the
calibration offset is subtracted from the IMU's report before it reaches
any consumer (IPC status, MAVLink GIMBAL_DEVICE_ATTITUDE_STATUS).
Self-test
Verify SP→PV agreement across the gimbal's working range without leaving the daemon — useful both as a post-calibration check and as a quick-and-dirty health probe before a mission:
|
The daemon sweeps (0,0,0) → (15,0,0) → (-15,0,0) → (0,0,15) → (0,0,-15) → (0,0,0), waits 2.5 s after each step, samples
operator-frame attitude, and returns per-sample SP/PV/error plus per-axis
max error and a pass/fail against a 1° tolerance. The whole run takes
~16 s. Refuses with an error if standby is engaged. The original pose is
restored at the end.
A clean run on a calibrated gimbal looks like:
If the gimbal hasn't been calibrated yet, the failing samples make the
bias obvious — that's a good cue to run {"cmd":"calibrate_yaw"}.
Configuration (turret.yaml):
device:
path: auto
ipc:
socket_path: /tmp/turret.sock
mavlink:
enabled: true
udp_port: 14550
sysid: 1
compid: 154
Priority System: MAVLink autopilot (highest) > GCS > Unix socket > CLI (lowest)
Daemon behavior:
- 1 Hz
HEARTBEAT(advertisesMAV_TYPE_GIMBALonMAV_COMP_ID_GIMBAL) - 5 Hz
GIMBAL_MANAGER_STATUS, broadcast to every recorded peer - 4 Hz attitude poll →
GIMBAL_DEVICE_ATTITUDE_STATUSbroadcast.COMMS_ERRORflag is set for ~1 s after any failed poll. - 8 consecutive poll failures → automatic reconnect (scan + reopen, exponential backoff to 10 s).
SIGTERM/SIGINTstart a 2 s grace shutdown; in-flight tasks are drained, then aborted; the IPC socket file is removed.- A critical task exiting unexpectedly (IPC, MAVLink, reconnect) tears the daemon down instead of leaving it half-running.
Use as a library
Two consumption modes:
-
Lean driver (
default-features = false): just theStorm32RCdriver and theGimbalDevicetrait. Pulls 4 direct deps (serde / serialport / thiserror / tracing) and no tokio.[] = { = "0.1", = false }let mut g = detect_gimbal?; g.set_attitude?; # Ok:: -
Embedded MAVLink manager: bring your own
dyn GimbalDevice(different protocol, simulator, network-attached gimbal) and let Turret handle MAVLink discovery, primary-control arbitration, hot attitude broadcast, IPC, and bounded shutdown. The default features pull tokio + the daemon stack.See
turret::daemonmodule-level docs for the full embedding example.
Develop
With a recent Rust installed:
# Clone and build
Protocol
Uses STorM32 RC Commands protocol over serial (115200 baud).
Message format: [0xFA][len][cmd][payload][crc16]
Supports: version query, angle setting, status reading, pan modes.
Device Detection
Auto-detects STM32 Virtual COM Port (VID:0x0483, PID:0x5740).
Falls back to common patterns: /dev/ttyACM*, /dev/ttyUSB*, COM*
Troubleshooting
- No device found: Check USB connection and power
- Permission denied: Add user to
dialoutgroup or usesudo - Communication errors: Verify 115200 baud rate and cable quality