Link Search Menu Expand Document

Pipe Interface

voxl-open-vins-server communicates exclusively through ModalAI’s MPA pipe architecture: sensors stream in through client pipes, estimates stream out through server pipes, and a control pipe accepts runtime commands. This page is the complete communications reference — what each pipe carries, when it publishes, and how to interpret states, quality, and error codes.

Table of contents

  1. The pipe map
  2. Input pipes
  3. Output pipes
    1. /run/mpa/ov — primary VIO output
    2. /run/mpa/ov_extended — extended output
    3. /run/mpa/ov_status — health and diagnostics
  4. Control pipe
  5. States
  6. Quality
  7. Error codes
  8. Frame conventions
  9. Client tools

The pipe map

MPA pipe map

Publishing happens on the VIO thread, immediately after every estimator update — there is no separate publish timer. The output rate therefore tracks the camera update rate (e.g. ~60 Hz on a rig whose reference camera runs 60 fps), with IMU-rate pose propagation available to consumers that extrapolate between updates.


Input pipes

PipeSourceContents
imu_apps_bodyvoxl-imu-serverCalibrated IMU samples (~1 kHz), already rotated into the body frame. Used when imu_body_frame_mode is enabled (default)
imu_appsvoxl-imu-serverRaw-orientation IMU pipe, used when imu_body_frame_mode is disabled
camera pipesvoxl-camera-serverOne image pipe per camera enabled in vio_cams.conf (e.g. tracking_front, tracking_down, hires_misp_grey). Cameras may be synchronized or fully unsynchronized — see Asynchronous & Mixed-Shutter Cameras

All cameras must reference the same IMU in vio_cams.conf. The IMU clock is the common timebase against which every camera’s time offset is estimated.

Camera frames are pushed into the estimator’s lock-free per-camera ingest directly from the camera pipe callbacks — nothing blocks a camera thread, and a stalled camera cannot stall the pipeline. The IMU callback drives estimation: each IMU batch advances the filter and releases any camera frames whose global time order is now decided.


Output pipes

/run/mpa/ov — primary VIO output

Publishes vio_data_t (defined in modal_pipe_interfaces.h), the packet consumed by voxl-px4 for position control:

Field groupMeaning
timestamp_nsTimestamp of the state estimate (monotonic clock, nanoseconds)
T_imu_wrt_vio, R_imu_to_vioPosition and rotation of the IMU/body frame with respect to VIO local frame (FRD conventions)
vel_imu_wrt_vioVelocity in the VIO frame
imu_angular_velBody-rate estimate (from quaternion differentiation of consecutive states)
qualityEstimation quality score — see Quality below
stateVIO_STATE_INITIALIZING, VIO_STATE_OK, or VIO_STATE_FAILED
error_codeBitmask of active error codes — see Error codes
n_feature_pointsNumber of SLAM landmarks currently in the state vector

/run/mpa/ov_extended — extended output

Publishes ext_vio_data_t: everything in vio_data_t plus pose/velocity covariance diagonals, gyro/accel bias estimates, camera extrinsics in use, and the list of currently tracked feature locations (consumed by voxl-portal for the VIO overlay). Only written when at least one client is connected, so it costs nothing in normal flight.

/run/mpa/ov_status — health and diagnostics

Publishes ov_status_t at the health-check cadence: hysteresis state, counters, and operational diagnostics for logging and fleet monitoring (voxl-log-vins consumes this alongside ov).


Control pipe

The server listens on /run/mpa/ov/control (also reachable through the ov_extended channel):

CommandEffect
RESET_VIO_SOFTWarm reset. Rebuilds the filter state while preserving feature tracks, IMU history, calibration values, and the live gyro/accel bias estimates (carried into re-initialization as priors). Recovers in seconds, in motion, at any attitude
RESET_VIO_HARDCold reset. Destroys and recreates the whole estimator; all queued frames are released safely and every error code is cleared. Re-initializes from scratch
voxl-reset-vins        # hard reset
voxl-reset-vins -s     # soft reset

See Initialization & Resets for what each reset preserves and when the server triggers them autonomously.


States

StateMeaning
VIO_STATE_INITIALIZINGWaiting for motion/gravity gates, or actively initializing (static or dynamic). Also reported during a reset and re-initialization. Quality is capped low in this state so a freshly built covariance cannot masquerade as confidence
VIO_STATE_OKEstimator initialized and updating normally
VIO_STATE_FAILEDAuto-reset conditions met — the estimate should not be trusted; a reset is in progress or imminent

Quality

quality is a 0–100 score computed from the tracked-feature population: per-camera image coverage (a 5×5 occupancy grid), SLAM landmark uncertainty, and MSCKF track quality, pooled over a short window so that asynchronous per-camera updates score exactly like synchronized batch updates. The published value is smoothed with a short time constant; -1 means failed, 0 means resetting.

A hysteresis state machine (INITIAL → GOOD/BAD) sits on top of the raw score to prevent rapid quality flapping; its thresholds are configurable in voxl-open-vins-server.conf (see the main page). The full design and the exact formulas — the windowed feature union, per-camera grid scoring, and the published-value EMA — are documented on the async page: Estimation quality on asynchronous rigs and Appendix A.5.


Error codes

error_code is a bitmask; multiple codes can be active simultaneously. The health monitor (30 Hz) classifies codes into two severities:

Only estimator-health codes can trigger an automatic reset. Transport hiccups — a dropped frame or IMU sample — are expected events on a busy system (the asynchronous ingest disposes frames deliberately for ordering and staleness) and must never take down a healthy filter. Warning-class codes self-clear after 10 s without a new occurrence.

CodeClassMeaning
ERROR_CODE_COVARIANCEauto-resetCovariance no longer positive definite — filter is corrupt
ERROR_CODE_IMU_OOBauto-resetIMU measurement exceeded sensor range
ERROR_CODE_IMU_BWauto-resetIMU bandwidth/rate too low to propagate safely
ERROR_CODE_NOT_STATIONARYauto-resetEstimation quality below threshold for too long (bit name is historical)
ERROR_CODE_NO_FEATURESauto-resetNo usable features for an extended period
ERROR_CODE_CONSTRAINTauto-resetInsufficient geometric constraints from current features
ERROR_CODE_FEATURE_ADDauto-resetFailed to add new features to the map
ERROR_CODE_VEL_INST_CERT / ERROR_CODE_VEL_WINDOW_CERTauto-resetVelocity estimate uncertainty exceeded bounds
ERROR_CODE_DROPPED_CAMwarningA camera frame was dropped (ring full, stale, or out of order)
ERROR_CODE_DROPPED_IMUwarningIMU samples dropped
ERROR_CODE_BAD_TIMESTAMPwarningA sensor timestamp regressed or jumped
ERROR_CODE_LOW_FEATURESwarningNot enough good features to (re)initialize yet
ERROR_CODE_BAD_CAM_CALwarningCamera intrinsic calibration looks questionable
ERROR_CODE_CAM_MISSING / ERROR_CODE_IMU_MISSINGreconnectSensor pipe not delivering — handled by reconnect logic, not by reset
ERROR_CODE_CAM_BAD_RES / ERROR_CODE_CAM_BAD_FORMATconfigCamera stream resolution/format unsupported — fix the camera configuration

Frame conventions

Internally the estimator runs in the OpenVINS world frame (gravity-aligned, z-up). The publisher transforms every output into ModalAI’s FRD (front-right-down) local frame convention before writing to the pipes, using the body → imu extrinsic from /etc/modalai/extrinsics.conf when imu_body_frame_mode is enabled. Heading is re-zeroed at every (re)initialization: the local frame’s x-axis is the vehicle’s heading at init, which is what position controllers expect.


Client tools

ToolPurpose
voxl-inspect-vinsLive terminal view of the ov stream (-v velocity, -b body frame, -z everything)
voxl-log-vinsCSV logging of VIO output and features for offline analysis
voxl-reset-vinsSends RESET_VIO_HARD / RESET_VIO_SOFT (-s) on the control pipe
voxl-benchmark-vioReplay-based benchmarking harness — see voxl-benchmark-vio