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}:

Accepted is the start, not the outcome

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.

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 --> S

Read 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.

Generated from spec/10-camera-and-payload-control.md.