ModalAI VOXL 2 Mini research notes
Scope: what the VOXL 2 Mini provides out of the box, what it cannot do, and where an indoor autonomous-capture stack has to attach.
Core take: the Mini is a 42 x 42 mm, 11 g board that is both the companion computer and the flight controller, and it already ships a working indoor autonomy stack:
- visual-inertial odometry (VIO),
- stereo and time-of-flight (ToF) depth,
- truncated / Euclidean signed distance field (TSDF / ESDF) mapping,
- rapidly-exploring random tree (RRT*) planning with trajectory optimization,
- PX4 collision prevention.
What it does not ship is any notion of where to go next: no exploration policy, no next-best-view, no coverage or photo-quality metric. That gap is the subject of the GLEAM / Next-Best-Path (NBP) line of work, and it sits off-board.
Prices as of 2026-07:
- $1,249.99 board only,
- $1,349.99 with power module,
- $1,449.99 with VOXL electronic speed controller (ESC) Mini,
- product page, docs.
Assembled in USA, which is most of why the price looks the way it does — see the bill-of-materials estimate below.
Hardware at a glance
| Item | VOXL 2 Mini |
|---|---|
| Size / weight | 42 x 42 mm, 11 g, 30.5 mm mount pattern |
| SoC | Qualcomm QRB5165, 8 cores to 3.091 GHz |
| RAM / flash | 8 GB LPDDR5 / 128 GB |
| GPU | Adreno 650, 1024 ALUs |
| NPU | Hexagon, ~15 TOPS |
| Cameras | 4 concurrent MIPI-CSI2 lanes |
| Video | 8K30 h.264/h.265 encode, up to 108 MP stills |
| IMU / baro | 2x TDK ICM-42688-P / ICP-10111 |
| Flight controller | PX4 1.14 or ArduPilot 4.6+, on the sensor DSP |
| Power | 3.8 VDC in, 0.5-8 W |
| Radio | none onboard; WiFi / 5G / LTE / Microhard as add-ons |
Terms: SoC = system on chip, ALU = arithmetic logic unit, NPU = neural processing unit, TOPS = tera-operations per second, MIPI-CSI2 = camera serial interface, IMU = inertial measurement unit, DSP = digital signal processor.
Mini vs full-size VOXL 2
The QRB5165 is the robotics variant of the Snapdragon 865; Qualcomm’s Robotics RB5 platform is the reference design it comes from. The flight controller runs on one of its DSP subsystems, not on a separate microcontroller — the next section unpacks that.
Differences vs the full-size VOXL 2:
- 42 x 42 mm / 11 g vs 70 x 36 mm / 16 g.
- 4 concurrent camera lanes vs 6.
- 3.8 V input vs 5 V.
- ArduPilot documented alongside PX4.
Everything else — SoC, RAM, flash, GPU, NPU, encode, IMUs — is identical. The Mini is not cut-down compute; the differences are mechanical and I/O.
The flight controller is a DSP core, not a chip
The QRB5165 is a heterogeneous SoC: eight ARM (Kryo 585) cores running Ubuntu, the Adreno GPU, a compute DSP (cDSP — the “NPU” in the spec table), and the SLPI (sensor low-power island) — a Hexagon DSP subsystem that phones use for always-on sensor fusion. ModalAI runs the entire flight controller there (their docs call it the sensors DSP, SDSP). PX4 executes under QuRT, Qualcomm’s real-time OS for Hexagon, with its own scheduler and memory space; the board’s IMUs and barometer are wired to SLPI-owned SPI/I2C buses, so the control loop never crosses into Linux. PX4 itself is deliberately split: everything flight-critical runs on the DSP, while its support tasks — logging, MAVLink processing — run as a companion process on the ARM cores.
What this buys and costs, versus a separate flight-controller MCU:
- Real isolation, shared package. The DSP keeps stabilizing through Linux-side CPU load, service crashes, even a userspace lockup — the practical failure containment a separate STM32 gives. What it does not survive is what a separate chip would: whole-SoC events (power, thermal shutdown, kernel-triggered subsystem resets) take the autopilot down with the computer.
- The bridge is muORB: PX4’s internal uORB pub/sub, extended across the DSP↔︎Linux boundary over Qualcomm’s FastRPC shared-memory transport. Linux-side services (
voxl-px4companion process,voxl-mavlink-server, and through it qVIO and the rest of the SDK) see the autopilot’s topics without a serial link — the same role a UART+MAVLink hop plays on a Pixhawk-style split stack, at shared-memory latency. - Toolchain lock-in. Code on the SLPI is built with Qualcomm’s proprietary Hexagon SDK, so
voxl-px4is ModalAI’s fork built in their docker environment — you cannot flash an upstream PX4 release, and the shipped version trails upstream (1.14 in SDK 1.6). ArduPilot took the same path but upstream: its QuRT HAL is mainlined, which is why current ArduPilot is documented on the Mini. - I/O follows the SoC. No timer-driven PWM pads — hence UART/serial ESCs only — and no SWD-style debug probe into the DSP: flight-side debugging is logs, the PX4 shell over adb, and muORB topic inspection.
- History note: this replaced a real two-chip design — VOXL 1 paired with the STM32F7-based Flight Core (“VOXL Flight” when combined on one PCB). VOXL 2 moved the autopilot on-die and dropped the MCU.
Cameras and sensors
Concurrency caps on the Mini: 4 tracking, or 2 ToF, or 2 hires (high-resolution) sensors across the 4 camera ports, mixed via interposer boards M0076 / M0084 / M0135.
| Role | Sensor | Shutter | Modules |
|---|---|---|---|
| Tracking (VIO) | OV7251, AR0144 | global | M0014, M0072, M0166, M0149 |
| Stereo | OV7251, OV9782 | global | M0015, M0073, M0113 |
| Hires | Sony IMX214/412/678/664 | rolling | M0024, M0025, M0107, M0161, M0143, M0186 |
| ToF | PMD IRS1645, IRS2975C | - | M0040, M0169, M0178 |
| Thermal | FLIR Lepton 3.5 / Boson | - | I2C + SPI adapter |
| Rangefinder | VL53L1X / VL53L1CX | - | I2C |
Every module above except M0143 has a datasheet page at docs.modalai.com/<part number>/; the interposers and flexes below follow the same pattern. The PCB catalog is the index, though it lags the per-board pages.
What each role is for:
- Tracking: mono fisheye (~167 deg) — the VIO input.
- Stereo: mono pairs — depth-from-stereo.
- Hires: the photogrammetry path.
- ToF: primary depth input to
voxl-mapper. - Rangefinder: altitude only.
Buses: I2C = inter-integrated circuit, SPI = serial peripheral interface.

ToF vs lidar
Same physics family, different engineering, different data product:
- The PMD modules are indirect ToF flash cameras. A flood illuminator lights the whole scene and every pixel measures the phase shift of the modulated return, giving a dense but low-resolution depth image. Short range (a few metres indoors), weak in sunlight, poor on dark or specular surfaces, and prone to multipath error in corners.
- Lidar normally means direct ToF: a pulsed laser timed against a single-photon detector, scanned or flash-illuminated. Sparse returns, but tens to hundreds of metres, sunlight-robust, cm-accurate.
- The VL53L1X rangefinder is direct ToF as well — effectively a single-pixel lidar.
For indoor mapping the ToF camera is the better data product: dense depth, cheap, small. For large or sunlit spaces it degrades badly, and that is where lidar would be wanted — which the Mini does not natively support.
Two consequences for capture
Every high-resolution sensor is rolling shutter. Global shutter exists only on the low-resolution mono computer-vision (CV) cameras. For photogrammetry that means motion blur and rolling-shutter skew unless the vehicle flies slowly or stops to shoot at capture poses. A capture-policy constraint, not a software one.
Per camera, QRB5165 can configure only three image outputs at once. HAL3 is Android’s camera hardware abstraction layer: the interface between Qualcomm’s sensor/ISP stack and
voxl-camera-server. We use it indirectly whenever a MIPI camera is used, but applications normally consume Modal Pipe Architecture (MPA) pipes rather than call HAL3 themselves.preview,small_video,large_video, andsnapshotare ModalAI’s four camera-server profiles, not four stream types defined by HAL3:Profile Intended output previewLow-latency RAW8/NV12 frames for CV small_videoLower-resolution H.264/H.265 for FPV/RTSP large_videoHigh-resolution H.264/H.265 for recording snapshotOn-demand, ISP-processed JPEG A hires camera normally spends its three slots on small video, large video, and snapshots; adding an uncompressed CV preview requires disabling one. This is usually acceptable here because qVIO consumes preview frames from a separate tracking camera while the hires camera handles capture. Multiple programs can also subscribe to the same MPA output without consuming another HAL3 slot. The hard limitation is therefore four distinct native outputs from one sensor, not necessarily four downstream uses if an output can be shared or derived.
I/O and connectors

| Connector | Function |
|---|---|
| J1 | 3.8 V DC power in + I2C battery monitoring (6 A inrush) |
| J2 | 5 V fan output, PWM controlled |
| J3 | USB3 SuperSpeed, 900 mA VBUS |
| J4 | serial debug console (debug kernel builds only) |
| J6 / J7 | camera group 0 / 1: 2x 4-lane MIPI CSI, CCI, 8 power rails |
| J9 | USB-C: ADB, OTG / host |
| J10 | UART or SPI expansion (2 chip selects), 3.3 V |
| J19 | 2x UART + 2x I2C: RC receiver, ESC, GNSS, magnetometer |
Terms: PWM = pulse-width modulation, CCI = camera control interface, ADB = Android Debug Bridge, OTG = USB on-the-go, UART = universal asynchronous receiver/transmitter, RC = radio control, GNSS = global navigation satellite system.
Power and motors
Power is the integration gotcha: the Mini wants 3.8 V, not 5 V. Two supported sources:
MDK-M0041-4-00Power Module v3 — 2S-6S LiPo in on XT60, fixed 3.8 V out, two INA231 current monitors on I2C.- M0129 VOXL Mini 4-in-1 ESC — use the fixed-3.8 V
M0129-63(current 2S-6S hardware), sold asMDK-M0129-63-00without accessory cables or-01with them. It reports battery telemetry over UART on J19 instead.
M0041 is the correct board-family number, not M00041. ModalAI’s Mini guide shortens the required variant to MDK-M0041-4; the full current orderable SKU is MDK-M0041-4-00. The generic Power Module v3 datasheet is stale: its part-number table lists only older 5 V assemblies, while the Mini guide and store listing confirm this 3.8 V variant.
There is also no PWM output for motors: the QRB5165 has none, so ESCs talk UART, or you add the VOXL 2 IO board. See the ecosystem section below.
Offboard sensors
Documented on the Mini:
- GNSS — UART on J19 (SSC_QUP6).
- Magnetometer — I2C on J19 (SSC_QUP0).
- Power monitoring — I2C on J1.
- Rangefinder — I2C.
Notably no documented UART lidar support. A spinning or solid-state lidar would mean USB3 or a custom UART bring-up, not a supported path.
The ecosystem around the board
The Mini is one stock-keeping unit in a vertically integrated catalogue. ModalAI sells the compute, the sensors, the flexes that connect them, the ESCs, the power modules, the radios, and finished drones — and the software assumes their parts. Buying a bare board is rarely what you actually want.

Compute boards
| Board | What it is |
|---|---|
| M0054 / M0154 | VOXL 2, full size, 6 camera lanes, from $1,299.99 |
| M0104 | VOXL 2 Mini, 4 camera lanes, from $1,249.99 |
| M0204 | VOXL 2 Mini refresh (no doc page yet) |
| M0087 | Flight Core v2 — standalone STM32 autopilot, no compute |
| M0006 / M0019 | VOXL 1 and VOXL Flight, previous generation |
SDK 1.6 also lists MVX-* boards (MM0204-1, M0205-1, M0206-1) and QCS6490 support as supported platforms — the next hardware generation is already in the tree.
Image sensors and the flex chain

A sensor never plugs straight into the board. The chain is sensor module -> flex cable -> interposer -> J6/J7:
- Interposers: M0076 (DF40C to AXT), M0084 (Y-AXT, two sensors per port), M0135 (dual image sensor adapter), M0195 (Mini / Stinger).
- Thermal adapters: M0187 (Lepton), M0153 (Boson).
- ToF adapters: M0172, M0178 (high power), M0189 (Mini-specific).
- Extension flexes in fixed lengths (M0036, M0074), stereo flexes with fixed baselines (M0010, M0039).
The mechanical layout of a build is largely decided by which flexes exist. Custom baselines or camera placements mean custom flex, not just a config file.
Full part-number lookup with weights and datasheet links: ModalAI module reference.
ESCs and the missing PWM
The QRB5165 has no PWM output. This shapes every build:
- UART ESCs are the native path: M0129 (Mini 4-in-1, pairs with the Mini over J19), M0049 / M0117 / M0134 (4-in-1, up to 32 A), M0138 (FPV 4-in-1). See the Mini ESC configs.
- For PWM ESCs you add the VOXL 2 IO board, which speaks the PX4IO protocol — and therefore does not support DShot.
- The M0129 also feeds the Mini its 3.8 V and reports battery telemetry over the same UART.

Power, radios, breakouts
- Power modules: M0041 family — the Mini needs the 3.8 V
MDK-M0041-4-00, not a 5 V-1/-5variant. - Cellular: M0130 LTE add-on with I/O breakout and USB hub (from $249.99), M0067 / M0090 5G carriers.
- Mesh/datalink: M0048 / M0059 Microhard ($199.99), Doodle Labs options.
- WiFi: M0136 modules, M0141 WiFi add-on with I/O.
- Video transmit: M0185 dual-band VTX; MSP DisplayPort OSD works with third-party HDZero / Walksnail units.
- Debug and expansion: M0017 / M0078 USB debug, M0125 / M0151 USB3-UART expansion (from $49.99), M0062 and M0144 breakouts, M0022 PWM breakout.
Full part-number lookup — 85 boards, weights, and verified datasheet links, plus which ones the official catalog is missing — is in ModalAI module reference.
Full part list: the PCB catalog and the add-ons store page.
Finished vehicles and kits
| Product | Notes |
|---|---|
| Starling 2 | 220 mm, 280 g, >40 min flight, from $2,949.99 |
| Starling 2 Max | 322 mm, 500 g takeoff + 500 g payload, 55+ min, from $3,199.99 |
| Sentinel | ModalAI’s reference drone; also sold as flight deck or bare PCB |
| VOXL 2 Flight Deck | pre-assembled, calibrated compute + sensor kit |
| MDK-M0104-1-C4 / -C6 | Mini sensor development kits |
| D0013 | Mini reference architecture |
Sensor fits, for reference:
- Starling 2: 3x AR0144 tracking + 1x IMX412 hires.
- Starling 2 Max: 2x AR0144 + 2x IMX412, optional FLIR Lepton, up to $5,799.99 fully equipped.
- MDK-M0104-1-C4: tracking + hires. MDK-M0104-1-C6: ToF + hires + tracking.
- D0013: Mini + M0129 ESC + IMX664 + 2x AR0144 + Lepton + ELRS receiver.

Note the Starlings carry the full VOXL 2, not the Mini. There is no ModalAI turnkey drone built on the Mini, so any Mini-based vehicle is an integration job.
What it costs to build
Nobody publishes QRB5165 pricing, so the following is inference from teardown-era Snapdragon 865 numbers and distributor kit prices — call it +/-40%. Short version: the Mini plausibly costs ~$350-575 to manufacture, so $1,249.99 is roughly 2.5-3.5x cost, 60-70% gross margin. Normal for niche US-assembled robotics hardware, and most of the price is not on the bill of materials.
Bill-of-materials estimate, anchors, and what the margin buys
Estimated unit cost at ModalAI volume (low thousands per year):
| Item | Est. unit cost |
|---|---|
| QRB5165 SoC | $120-180 |
| 8 GB LPDDR5 | $45-70 |
| 128 GB UFS | $25-40 |
| PMICs + power tree | $30-50 |
| 2x ICM-42688-P + ICP-10111 | $15-25 |
| Passives, crystals, inductors | $20-35 |
| Connectors (2x DF40C-60, USB-C, 4x JST) | $15-25 |
| PCB (42 x 42 mm, ~12-layer HDI, stacked microvias) | $25-50 |
| Shields, thermal, mech | $5-10 |
| SMT assembly, test, IMU/baro calibration, yield | $50-90 |
| Total | ~$350-575, midpoint ~$450 |
At 10k+/year this would fall to roughly $280-350.
Anchors behind the range:
- Snapdragon 865 was ~$85 die-only and ~$150 packaged at phone volumes in 2020. QRB5165 is the industrial SKU with 10+ year longevity at a fraction of the volume, so a premium over $85 is expected.
- Thundercomm’s RB5 Core Kit — QRB5165 SOM (8 GB / 128 GB) plus a full carrier board — retails $795 at qty 1, $764 at 100+. A finished product with margin at $795 caps how expensive the silicon can plausibly be.
- Memory is abnormally expensive in 2026: LPDDR5X contract prices rose ~90% quarter-on-quarter in Q1, so the memory lines are maybe $40 above their 2024 level.
What the margin actually buys:
- US assembly in small runs, to defense-procurement standards — a trusted supply chain costs real money.
- The software: VOXL SDK, the PX4-on-DSP port, camera and ISP bring-up. That engineering is amortized over a few thousand boards a year and dwarfs the silicon.
- Qualcomm licensee access — ModalAI builds the sensor-DSP images. That is the moat, and it is not on the BOM.
- Long support life, export paperwork, reseller margin.
What the ecosystem implies
- Buy a configured kit, not a bare board. The catalogue is the real product; a board on its own needs an airframe, ESC, flexes, sensors, and a radio before it does anything.
- Sensor choice is catalogue-bounded. Anything outside the list means camera driver work against a Qualcomm ISP on a 4.19 kernel — expensive, and exactly the kind of task that consumes a research sprint on its own.
- The lock-in is real but honest. PX4, ArduPilot, ROS 2, and MAVLink are all upstream open standards, so the autonomy work is portable even if the hardware is not.
- Volume pricing exists but will not halve it. For a deployment that needs compute under ~$500 per vehicle, this platform is the wrong shape — but the obvious alternative got worse in July 2026: NVIDIA raised Jetson prices by 33-101% (Orin Nano Super devkit $249 -> $399, AGX Orin 32 GB module $899 -> $1,799) on memory cost pressure, so a Jetson plus a separate flight controller no longer undercuts an integrated VOXL by much once the FMU, carrier and wiring are counted.
- For a demonstration, the cheapest credible path is a Starling 2 — same SDK, flying, no integration — with the Mini reserved for a later size- or weight-driven build.
Software: VOXL SDK
Current release SDK 1.6.3 (2026-02-06), system image 1.8.06, Ubuntu 18.04 / kernel 4.19 (the store page says “Debian Buster” instead — ModalAI’s own materials disagree; the SDK build targets are qrb5165 = Ubuntu 18.04 and qrb5165-2 = Ubuntu 20.04). Services talk over ModalAI’s Modal Pipe Architecture (MPA) — named pipes under /run/mpa/. Source is on GitLab — but see the licensing note below: it is source-available, not open source.
| Service | Does |
|---|---|
voxl-camera-server |
HAL3 access to the Qualcomm ISP, OpenMAX encode |
voxl-qvio-server |
MPA wrapper around Qualcomm mvVISLAM: fisheye + IMU -> 6-DoF pose |
voxl-open-vins-server |
Open-VINS, the open alternative to qVIO |
voxl-dfs-server |
depth from stereo: disparity + point cloud pipes |
voxl-mapper |
voxblox TSDF -> ESDF, RRT*, loco trajectory, mesh export |
voxl-vision-hub |
VIO -> PX4 bridge, MAVLink, VOA, AprilTag, offboard modes |
voxl-tflite-server |
LiteRT inference on CPU / GPU / NNAPI / NPU delegates |
voxl-portal |
web UI: video, 2D costmap, 3D mesh, planning overlays |
voxl-streamer |
RTSP video out |
voxl-logger / voxl-replay |
record and replay MPA pipes |
voxl-mavlink-server |
MAVLink routing to autopilot and ground station |
voxl-tag-detector |
AprilTag detection |
voxl-lepton-server, voxl-rangefinder-server |
thermal, rangefinder drivers |
Terms: ISP = image signal processor, 6-DoF = six degrees of freedom, VOA = visual obstacle avoidance (PX4 collision prevention), LiteRT = formerly TensorFlow Lite, NNAPI = Android neural networks API, RTSP = real-time streaming protocol.
Details worth keeping in mind
voxl-qvio-serveris an open MPA wrapper; the VIO itself is Qualcomm’s proprietarylibmvVISLAMfrom the MV SDK. How it is fed and read is open to change; how it estimates is not.voxl-mapperis beta; needs qVIO + vision-hub; ToF input by default.voxl-camera-serverdoes NV12/RAW8 preview, h264/h265, JPG snapshot, with either ISP or mean-sample-value (MSV) auto-exposure.voxl-tflite-serverships YOLOv5, MobileNet-SSD, DeepLabV3, MoveNet, FastDepth.voxl-vision-hubopens MAVLink UDP ports for MAVROS/MAVSDK — the entry point for an off-board planner.
ROS and cross-development
ROS (Robot Operating System) support:
- ROS 2 Foxy as native Debian packages (
voxl-ros2-foxy, on disk since SDK 1.1), see the install guide. voxl-mpa-to-ros2bridges images, IMU, point clouds, VIO pose.- Anything newer than Foxy runs in Docker.
- The bridge only publishes topics that have subscribers.
Cross-development uses the voxl-cross Docker image; targets are qrb5165 (Ubuntu 18.04) and qrb5165-2 (Ubuntu 20.04). CPU, OpenCL GPU, and Hexagon SDK DSP paths are all available.
What the source tree shows
The SDK was cloned locally under voxl/ (40 repos, shallow, 2026-07-31; commit manifest in voxl/README.md). Reading it corrects several things the marketing pages imply.
Licensing is source-available, not open source. 28 of 33 LICENSE files are BSD-3 with a fourth clause: “The Software is used solely in conjunction with devices provided by ModalAI Inc.” Exceptions: libmodal-pipe and libmodal-json are LGPL-3.0, voxl-voxblox keeps ETH-ASL’s BSD, voxl-open-vins-server is an Open-VINS redistribution. Practical effect: the code can be read, patched and extended for a ModalAI-based product, but not lifted onto other hardware.
voxl-qvio-server is a thin wrapper, not the algorithm. Its README: “MPA service for Qualcomm MV SDK VIO (MVVISLAM)”. The estimator is Qualcomm’s libmvVISLAM; the repo is the pipe plumbing, config, and quality reporting. A quirk worth knowing: on the 18.04 image the MV SDK is 32-bit only, so this is the only 32-bit package on the platform — the 20.04 (qrb5165-2) build is 64-bit.
voxl-mapper vendors the ETH-ASL planning stack. Under server/ sit loco_planner, mav_local_planner, mav_path_smoothing, mav_planning_common, mav_trajectory_generation, voxblox_planning_common — i.e. mav_voxblox_planning de-ROSed onto MPA. Familiar research code, which also means its known limits (2.5D-ish assumptions, replanning cost) are inherited wholesale.
voxl-vision-hub has more offboard modes than the docs advertise. Source files include offboard_figure_eight, offboard_follow_tag, offboard_trajectory, offboard_wps (waypoints), offboard_backtrack (retrace the flown path), plus voa_manager, obs_pc_filter, pose_filter, fixed_pose_input, horizon_cal. Waypoint mode is likely a simpler integration target for an external planner than trajectory mode.
Tooling worth knowing about early. voxl-mpa-tools ships voxl-inspect-* for every pipe type (cam, imu, vio, pose, points, tof, gps, mavlink, detections) — that is the debugging surface. voxl-logger records and replays MPA data and includes voxl-logger-to-rosbag, so real flight data can be pulled into ROS-side tooling.
SDK 1.7 is in progress: voxl-suite on dev reads version 1.7.0, ahead of the 1.6.3 release the docs describe.
Bridging the board to simulation
Three separate seams, in increasing order of custom work.
1. PX4 HITL — documented, works today
voxl-px4-hitl is a shipped target (voxl-px4/make_package.sh installs voxl-px4-hitl, voxl-px4-hitl-start, and a HITL parameter config). The host runs Gazebo Classic — in ModalAI’s voxl-gazebo-docker image, since Gazebo Classic has no Ubuntu 22.04 build — sends HIL_SENSOR / HIL_GPS over an FTDI serial link, and PX4 on the sensor DSP returns actuator commands. Real RC still works.
Setup notes from the docs and the community write-up: SDK >= 1.1.2, systemctl disable voxl-px4, disable voxl-qvio-server (real VIO fights the simulated sensors), drop the FTDI latency_timer to 1, start Gazebo before QGroundControl. The docs wire it to J18, which is a VOXL 2 connector — on the Mini that has to move to a J10/J19 UART, so verify before ordering cables.
2. Simulated VIO into the real stack — also shipped
The useful find in the source tree. voxl-hitl-vio-server listens for MAVLink ODOMETRY messages on UDP port 14560, converts them into a vio_data_t, and publishes them on the qvio pipe that voxl-vision-hub already consumes — pose, quaternion, linear and angular velocity, covariances, and a quality field. voxl-hitl-rangefinder-server does the same for height.
The README says “from a gazebo instance”, but nothing in the code is Gazebo-specific: any simulator that can emit MAVLink ODOMETRY over UDP can drive the onboard autonomy stack, and Pegasus already speaks MAVLink. So Isaac Sim can feed pose to the real board with no new protocol — an Isaac-side publisher plus a config file, not a porting project.
3. Simulated imagery into the perception stack — custom
Neither of the above exercises cameras, qVIO, DFS, or voxl-mapper’s depth input. Doing that means publishing frames into MPA ourselves. The camera interface is documented and extensible — camera_image_metadata_t plus raw bytes, a JSON info file for discovery — and voxl-camera-server, voxl-lepton-server, and voxl-uvc-server are all implementations of it, so a “sim camera server” is the intended shape.
Verify before committing: whether qVIO’s IMU arrives over MPA or straight from the DSP; timestamp discipline (metadata wants apps-proc CLOCK_MONOTONIC at exposure start, so sim frames must be stamped in the board’s clock); and matching intrinsics, distortion, and exposure metadata to a real module, otherwise the VIO tuning is meaningless. Bandwidth is a non-issue for tracking cameras (640x480 mono at 30 Hz is about 9 MB/s); 4K hires would need encoding.
Cheaper substitute: voxl-logger records MPA pipes on a real flight and voxl-replay plays them back on the bench, with voxl-logger-to-rosbag feeding ROS-side tooling. Real data, no bridge to write.
Recommended ladder
- First: Isaac/Pegasus + PX4 SITL, planner on MAVSDK/MAVROS. The interface is identical to the real board, so this already is the bridge that matters.
- Once hardware is in hand: HITL with Gazebo Classic exactly as documented, to establish that offboard commands drive the real flight stack. Then swap in Isaac as the odometry source through
voxl-hitl-vio-server— cheap, and it puts simulated scenes in front of the realvoxl-mapper/ VOA / PX4 loop. - Only if perception-on-hardware becomes a milestone: MPA image injection. Budget a week; verify the qVIO IMU path first, because that single unknown decides feasibility.
One constraint applies throughout: HITL cannot use lockstep, so the simulator must hold real time. Isaac with RTX rendering and several cameras on a laptop GPU may not, and when it slips the flight dynamics are wrong rather than merely slow.
Running the stack on the host (software in the loop)
22 of the 40 cloned repos have a native platform in build.sh — “Build with the native gcc/g++ compilers for testing code locally on a desktop computer”. The chain below was built on Ubuntu 24.04 / gcc 13, without sudo, with /usr and /run read-only. Full log and reproduction steps in voxl/NATIVE_BUILD.md.
| Component | Result |
|---|---|
| libmodal-json, libmodal-pipe, librc-math, libmodal-journal, libvoxl-cutils | build clean |
| MPA transport on x86 | works — server/client exchanged live data |
voxl-hitl-vio-server |
builds, runs, sim bridge verified end to end |
voxl-mapper |
builds and runs (2 include-path patches, no source changes) |
voxl-vision-hub |
builds and runs with a ~90-line libmodal-cv stub |
voxl-mavlink-server |
builds with patch; upstream native target is broken |
voxl-mpa-tools |
builds, 18 voxl-inspect-* binaries |
voxl-logger |
needs libturbojpeg0-dev, libopencv-dev; source compiles clean |
The autonomy layer runs on a desktop. No emulation, no cross-compiler, no board.
Expectation vs reality
Three expectations formed before the build turned out to be wrong, all in a useful direction.
libmodal-cv is a soft blocker, not a hard one. It is 8 functions, 1 struct, 1 macro, used from three files. Six are container plumbing; the only real computer vision is mcv_pc_downsample2, a voxel-grid decimator with depth/FOV/count/confidence filtering. A ~90-line pass-through stub gives a clean build of voxl-vision-hub, and the binary starts, brings up geometry, MAVLink IO, VIO manager, tag manager, VOA manager and IMU manager, and creates its MPA pipes. A faithful version is ~150 lines, half a day. Caveat: the ABI is inferred from call sites, so a stub is source-compatible only — every consumer must then be built from source, never mixed with a real ModalAI .deb.
libmodal-cv was not even the first thing to break. voxl_common_config.h failed earlier, and it is open source, sitting in voxl-mpa-tools/lib/.
The dependency cost, not the code, is what makes this a day of work. Nothing usable came from the system — no Eigen, Ceres, NLopt or OpenCV dev headers — so voxl-mapper required building Eigen 3.4, NLopt, Ceres 2.0 (~7 min) and voxblox first. Worse, ModalAI’s voxl-ceres-solver and voxl-nlopt repos contain no source at all, only submodule pointers to upstream GitHub. An offline host cannot build voxl-mapper.
The bridge, verified
voxl-hitl-vio-server built natively, and a purpose-written probe then sent mavlink_odometry_t{x=1.5, y=2.5, z=-3.5, q=identity, v=(.1,.2,.3), quality=77} to 127.0.0.1:14560 and read back vio_data_t{state=OK, quality=77, T=[1.50 2.50 -3.50], vel=[0.10 0.20 0.30]} on the qvio pipe. Isaac to MPA works today, on a laptop, with no board present.
Wiring facts that matter:
- Port 14560 is hardcoded (
receiver_udp.c:52). The config exposesreceiver_portbut nothing reads it. - It publishes
qvioandqvio_extended, deliberately squatting the real qVIO pipe names — which is why mapper and vision-hub accept it transparently. - It ignores
time_usecand stamps with localCLOCK_MONOTONIC, so sim time and board time have to be reconciled externally. voxl-mappersubscribes tovvhub_body_wrt_fixed(its only hardcoded input) plustof_pipe_0..3anddepth_pipe_0..3, and publishesplan_msgswhose control pipe acceptsplan_home,plan_to,follow_path,stop_following. That control pipe is the attachment point for an external exploration planner. Depth inputs are fully config-driven, but note all fourdepth_pipe_*_enabledefault to 0 whiletof_0_enabledefaults to 1, and extrinsics are stored as a name resolved againstextrinsics.conf, not an inline transform.
Practical gotchas when reproducing this
voxl-mavlinkis a submodule wrapper; a--depth 1clone leavesc_library_v2empty and libmodal-pipe fails onmavlink.h.- gcc 13 needs
-Wno-error=foraddress-of-packed-member,sign-compareand astringop-overflowfalse positive. These work as envCFLAGSbecause their CMakeLists append${CMAKE_C_FLAGS}last. make installwrites to/usr/includeand/usr/bindirectly. Copy into a prefix instead.- The MPA base dir is a compile-time
#define(/run/mpa/) with no env override; either make/run/mpawritable or patch the define. - Raise the inotify limit before a multi-service session.
libmodal-pipecallsinotify_init()per server pipe and exits on failure. With the default 128 instances mostly eaten by a desktop, services die seemingly at random —voxl-mavlink-servernever survived.sudo sysctl -w fs.inotify.max_user_instances=1024.
Bugs worth reporting upstream
Found while getting this to run, all with file:line in voxl/NATIVE_BUILD.md:
voxl-hitl-vio-serverassignss.qualityafter thememcpy, soqvio_extendedalways publishes quality 0.- The same file fills
velocity_covariancefrompose_covarianceand never readsodom.velocity_covariance. - Its “reject localhost” guard compares host-order against network-order, so it never fires on little-endian.
voxl-mavlink-server’s ownbuild.sh nativeomits-DPLATFORM, so CMake hard-fails: their native target is broken out of the box.voxl-vision-hub/utils/voxl-inspect-vfcnever links-lmand only builds by luck on their toolchain.voxl-mpa-toolsuses${OpenCV_LIBS}with nofind_package(OpenCV)anywhere, and itsbuild.shreturns exit 0 even whenmakefails.
What the autonomy stack already does
Chained together, the shipped stack is a complete indoor GPS-denied loop:
- Tracking fisheye + IMU ->
voxl-qvio-server-> 6-DoF pose. - ToF and/or stereo -> point clouds.
voxl-mapperintegrates them into a TSDF, derives an ESDF collision cost field (0.2 m voxels by default), plans with RRT* (1 s budget by default), and smooths withloco.voxl-vision-hubtransforms the trajectory into the autopilot frame and feeds PX4 in trajectory offboard mode.- VOA fuses stereo/ToF/rangefinder points into a buffer driving PX4 collision prevention, independent of the planner.
So the standing question of whether local navigation is already solved by the hardware vendor has, for indoor, slow, GPS-denied flight, a largely affirmative answer. Research effort is better spent on the exploration and capture layers than on re-deriving local navigation.
The honest caveats:
voxl-mapperis labelled beta and authorized for beta use only.- qVIO is a closed-source DSP blob that cannot be debugged or extended.
- Everything is tuned for ModalAI’s own Starling airframes.
Onboard AI compute, realistically
15 TOPS sounds like a lot. The constraint is not throughput, it is the toolchain:
- No CUDA. Nothing from the Isaac / PyTorch side runs on this board as-is. Anything learned must be exported to LiteRT with a GPU/NNAPI/NPU delegate, or converted for the Qualcomm Neural Processing SDK (SNPE). Invalid delegate choices silently fall back to CPU.
- Custom models are not drop-in for
voxl-tflite-server: each needs a C++ class implementingpost_process()andworker(). - Published VOXL 2 GPU-delegate numbers: MobileNetV1 ~125 fps, YOLOv5 ~36 fps. Comfortable for a detector alongside VIO; not a budget for a large policy network at high rate.
So a learned exploration policy of the GLEAM/NBP kind is portable to this hardware, but porting is real engineering: model conversion, quantization, a serving class, and a latency budget shared with VIO, mapping, and encode. For a research milestone the policy is better kept on a PC, streaming decisions to the drone.
What is provided, and what is missing
Provided out of the box — effectively the entire onboard column of an indoor autonomy system:
- pose, depth, a volumetric map,
- obstacle avoidance,
- a web visualization surface,
- log/replay and video streaming,
- a flight controller that already consumes external trajectories.
Missing, and therefore the research surface — goal selection. voxl-mapper plans a path to a goal someone else chose. There is no:
- frontier selection,
- information gain,
- next-best-view,
- photo-coverage metric,
- notion of whether the pictures taken were any good.
Integration surface
For a PC-side planner there are two clean options, neither needing a custom protocol:
- MAVLink/MAVSDK over the UDP ports
voxl-vision-hubopens, sending setpoints or trajectories. - ROS 2 topics via
voxl-mpa-to-ros2(pose, images, point clouds up; goals down), which matches how the simulation-side tooling is structured.
For the photogrammetry stream:
- Hires stills go through the ISP as JPG snapshots, stored on the 128 GB onboard.
- Offload over USB3 or an add-on modem — there is no built-in radio.
- Rolling shutter plus the 3-stream cap means capture has to be deliberate — pose, stop, shoot — not continuous high-rate video harvesting.
Simulation link: QRB5165 is not an Isaac target. The bridge between Isaac Sim / Pegasus and this hardware is PX4 — software-in-the-loop (SITL) first, MAVLink message compatibility later.
Risks and caveats
- Stack age. Ubuntu 18.04, kernel 4.19, ROS 2 Foxy (end of life 2023), PX4 1.14. Anything modern lives in Docker. Expect friction with current Python/CV packages.
- Flight controller shares the SoC. Excellent for SWaP (size, weight and power) and latency, but a Linux-side fault and the autopilot are on the same die. J10/J19 support an external flight controller where that separation is required.
- Closed components and a field-of-use licence. The VIO algorithm (
libmvVISLAM) and the sensor DSP images are Qualcomm builds; if VIO misbehaves in a given environment the available responses are configuration and Open-VINS, not a fix. Separately, most SDK repos are BSD-3 plus a clause restricting use to ModalAI hardware — source-available, not open source, so the code cannot be lifted onto another board. - No documented UART lidar path on the Mini. If the sensor plan drifts toward lidar SLAM (simultaneous localization and mapping), bring-up needs verifying before committing.
- Roadmap risk is the strongest argument against this board. VOXL 3 (QCS8550, 45 TOPS) is SBIR-funded development, not a product —
modalai.com/products/voxl-3404s. Meanwhile the signals point away from QRB5165: SDK 1.6 carries QCS6490 support and new MVX-* boards, the SDK 1.7 betas exist only for a QCS6490 next-gen board rather than voxl2/voxl2-mini, and a ModalAI engineer stated on their forum (17 Jul 2026) that “we are not going to be officially supporting Ubuntu2.0 Kernel on VOXL2, as we are working on enabling next gen hardware”. Forum-sourced, so confirm with sales — but if accurate, the Ubuntu 18.04 userland is where VOXL 2 stops, and a product roadmap should not assume otherwise. - Their own support has limits on the closed parts. In a February 2026 forum thread about violently unstable qVIO flight, a ModalAI engineer replied that “the underlying QVIO source code is not available” to them either. That is the practical meaning of the
libmvVISLAMdependency. - Lead time is the practical killer. The product page states “Expected to ship within 60 business days from San Diego, CA” for the Mini (30 for the full VOXL 2). That is roughly three months. Any schedule that depends on having one of these boards in hand starts with an order placed up front.
- Cost of hands-on work. $1.25-1.45k for a board that still needs an airframe, ESC, radio, and cameras. The Starling 2 / Starling 2 Max dev drones run the same SDK flying and are the cheaper path to validating the software, though they carry full VOXL 2 rather than the Mini.
References
Product and board:
- VOXL 2 Mini product page
- Docs overview
- Feature matrix
- Connectors
- Power
- Image sensors
- Offboard sensors
- D0013 architecture
Software:
- VOXL SDK overview
- SDK 1.6 release notes
- voxl-camera-server
- voxl-dfs-server
- voxl-tflite-server
- voxl-vision-hub
- voxl-mapper source
- ROS 2 on VOXL 2
Flight stack and accessories: