Part 10 — Camera and Payload ControlLink to the section Part 10 — Camera and Payload Control
On this page
Maturity: Draft · Profiles: C · Schemas: univip.command.v0.2, univip.command_status.v0.2
10.1 Command model (shared with Part 11)Link to the section 10.1 Command model (shared with Part 11)
Cancellation MUST NOT be reported as CANCELLED when the underlying adapter refuses or cannot confirm the stop. DELETE /commands/{command_id} then returns 409 command-not-cancellable with a rejection reason and leaves the original command active. A rejected vehicle.cancel similarly leaves the original movement active. Failure to stop after lease loss is reported as FAILED, with the reason and an explicit indication that stopping was not confirmed; the lease still ends. Dock launch preparation is one example of an operation whose cancellation may be unavailable.
A command is submitted with POST /univip/v1/devices/{device_id}/commands:
{
"schema": "univip.command.v0.2",
"command_id": "01J9ZC5R2M8K4T1V7W9X3Y5Z0A",
"type": "camera.gimbal.set_orientation",
"issued_at": "2026-10-15T10:33:00.000Z",
"expires_at": "2026-10-15T10:33:05.000Z",
"lease_id": "lease-7f3a",
"payload_id": "cam-1",
"params": { "frame": "EARTH", "pitch_deg": -45, "yaw_deg": 90 }
}The synchronous response (HTTP 202 or 200) is:
{ "schema": "univip.command_status.v0.2", "command_id": "...", "type": "...", "state": "ACCEPTED", "timestamp": "..." }or, with HTTP 422, state: "REJECTED", reason and message. A command refused for a lease, limit, state or safety reason is always a 422 rejection, never a 403 (403 means only a missing scope, Part 05 §5.5). ACCEPTED means the device will attempt the command; it never means completion.
Where the vehicle or payload controller acknowledges commands (for example MAVLink COMMAND_ACK), the synchronous answer reflects that acknowledgment: the device dispatches the command and waits for it, up to 10 s, before answering. A refusal by the controller is answered REJECTED with the mapped reason (Annex A); an acknowledgment that reports failure is answered ACCEPTED and followed at once by FAILED; no acknowledgment within the wait is answered ACCEPTED, and the outcome follows as status messages. Subsequent states arrive as command_status envelopes on the session channel and via GET /commands/{command_id}:
An accepted command may be queued and then execute. Later status messages report completion, failure, cancellation or supersession. A rejected command is refused before entering this lifecycle.
Scroll horizontally to see the whole diagram.
View Mermaid source
flowchart TB
accTitle: Accepted is the start, not the outcome
accDescr: An accepted command may be queued and then execute. Later status messages report completion, failure, cancellation or supersession. A rejected command is refused before entering this lifecycle.
A["ACCEPTED: the device will try"] --> Q["QUEUED"]
Q --> E["EXECUTING"]
E --> C["COMPLETED"]
Q --> F["FAILED"]
E --> F
Q --> X["CANCELLED"]
E --> X
Q --> S["SUPERSEDED"]
E --> SRead ACCEPTED as an acknowledgment, then follow command_status for the outcome. Cancellation can follow a client request or lease loss; a newer command on the same axis or target can supersede the earlier one.
Standard rejection and failure reasons: UNSUPPORTED_COMMAND, INVALID_PARAMETERS, NO_LEASE, LEASE_SCOPE, LEASE_EXPIRED, OUT_OF_LIMITS, PAYLOAD_UNAVAILABLE, BUSY, FLIGHT_STATE, PILOT_OVERRIDE, GEOFENCE, SAFETY, FLIGHT_CONTROL_DISABLED, LINK_LOST, EXPIRED, INTERNAL.
expires_at is RECOMMENDED for all commands and REQUIRED for continuous moves. It bounds the start of execution, not its completion: the device MUST NOT start a command after its expiry (reason EXPIRED), and a command already executing at expires_at continues, except that a continuous move stops.
10.2 Separation from vehicle controlLink to the section 10.2 Separation from vehicle control
Every camera.* command MUST be executable without moving the vehicle. If a payload's pointing is coupled to the aircraft (for example a fixed forward camera where "pan" would require yawing the aircraft), the device MUST NOT advertise the gimbal axis and MUST NOT translate a camera.* command into aircraft motion. A client MAY offer the user an explicit vehicle.* alternative under Profile N permissions.
10.3 Gimbal commandsLink to the section 10.3 Gimbal commands
| Type | Params | Notes |
|---|---|---|
camera.gimbal.set_orientation |
frame (BODY/EARTH), any of roll_deg, pitch_deg, yaw_deg, optional rate_degps |
Absolute. Omitted axes unchanged. Equivalent to ONVIF AbsoluteMove. rate_degps is a slew-rate limit; a device that cannot limit slew rate ignores it and says so in result.applied. |
camera.gimbal.move_relative |
frame, any of roll_deg, pitch_deg, yaw_deg deltas |
Equivalent to ONVIF RelativeMove. The deltas apply to the current orientation expressed in the requested frame: if telemetry reports the gimbal in the other frame, the device converts the current orientation using the vehicle heading before adding the deltas. |
camera.gimbal.move_continuous |
any of roll_rate_degps, pitch_rate_degps, yaw_rate_degps; REQUIRED expires_at ≤ issued_at + 2 s |
Client re-issues while the user holds the control. Equivalent to ONVIF ContinuousMove with timeout. |
camera.gimbal.stop |
— | Stops motion; supersedes continuous commands. |
camera.gimbal.recenter |
— | Returns to forward-level. |
camera.gimbal.point_at |
latitude_deg, longitude_deg, one altitude member |
Geospatial extension; device computes orientation from its own position. |
Gimbal frames: in EARTH, yaw_deg is the true azimuth of the optical axis ([0, 360) or (−180, 180]), and pitch_deg and roll_deg are relative to the local horizontal plane (pitch_deg negative looking down). In BODY, yaw_deg is relative to the vehicle's forward axis (positive to the right), and pitch_deg and roll_deg are still relative to the local horizontal, as a stabilized gimbal holds them; they are not relative to the vehicle's own pitch and roll. (MAVLink's "vehicle frame" is this BODY frame; ST 0601's sensor-relative angles are relative to the full platform attitude, see Annex A.3.)
10.4 Zoom and focusLink to the section 10.4 Zoom and focus
| Type | Params |
|---|---|
camera.zoom.set |
zoom_ratio (absolute) |
camera.zoom.move_continuous |
rate in ratio/s (negative = out); REQUIRED expires_at |
camera.zoom.stop |
— |
camera.focus.set_mode |
mode: AUTO, MANUAL, ONE_SHOT |
camera.focus.set |
distance_m or position_pct (manual) |
camera.focus.trigger |
— (one-shot autofocus) |
10.5 Recording, snapshot, modeLink to the section 10.5 Recording, snapshot, mode
| Type | Params |
|---|---|
camera.recording.start |
optional profile |
camera.recording.stop |
— |
camera.snapshot |
— ; result in command_status.result.media_id |
camera.mode.set |
mode: VIDEO, PHOTO, THERMAL, SPLIT, vendor strings allowed |
camera.stream.set |
stream_id, optional width, height, fps, bitrate_kbps |
10.6 ImagingLink to the section 10.6 Imaging
camera.imaging.set with params.settings as an object of standard parameter names:
| Parameter | Values |
|---|---|
EXPOSURE_MODE |
AUTO, MANUAL, SHUTTER_PRIORITY, APERTURE_PRIORITY |
EV_COMPENSATION |
number, stops |
ISO |
integer |
SHUTTER_S |
number |
WHITE_BALANCE |
AUTO, SUNNY, CLOUDY, INCANDESCENT, FLUORESCENT, CUSTOM_K with white_balance_k |
IR_CUT_FILTER |
ON, OFF, AUTO |
BRIGHTNESS, CONTRAST, SATURATION, SHARPNESS |
0–100 |
WDR |
ON, OFF, AUTO |
DEFOG |
ON, OFF, AUTO |
Thermal payloads additionally accept camera.thermal.set with palette, gain_mode, isotherm ({ "enabled", "min_c", "max_c" }), spot_meter ({ "x_pct", "y_pct" }).
10.7 Other payloadsLink to the section 10.7 Other payloads
| Type | Params |
|---|---|
payload.spotlight.set |
enabled, intensity_pct |
payload.speaker.play |
media_id or text (TTS), volume_pct |
payload.speaker.stop |
— |
10.8 Leases for camera controlLink to the section 10.8 Leases for camera control
If a payload declares lease_required: true, camera.* and payload.* commands for it MUST carry a valid lease with scope camera:<payload_id> or camera:*. Lease mechanics are in Part 11 §11.3. A device MAY allow multiple concurrent camera leases on different payloads. Pilot gimbal input MUST take precedence and MUST generate vehicle.control.pilot_override scoped to the camera lease.
10.9 Capability-gated behaviorLink to the section 10.9 Capability-gated behavior
A client MUST NOT send a command type, axis, frame, parameter or value outside the ranges advertised in the capability document. A device MUST reject such commands with UNSUPPORTED_COMMAND, INVALID_PARAMETERS or OUT_OF_LIMITS, never silently clamp, except for continuous-move rates which it MAY clamp and report in the EXECUTING status result.applied.