DroneVision on NXP i.MX93 FRDM¶
Validation record for running DroneVision on the NXP i.MX93 FRDM board available through
the imx SSH host. The measurements in this document were taken on 6 August 2026.
Executive summary¶
DroneVision installs and runs correctly on the board with the NXP-provided Python, OpenCV and ONNX Runtime packages. The complete test suite passes and the bundled FP32 ONNX model produces valid output on the CPU.
The classical colour-marker pipeline processes approximately 33 four-camera frame sets per second. The YOLO FP32 CPU path is far slower: with both Cortex-A55 cores it processes approximately 1.02 frame sets per second, or 4.09 individual camera inferences per second. This makes learned detection—not JPEG decoding or geometry—the dominant optimization opportunity.
The next meaningful optimization is an INT8 Ethos-U65 backend. JPEG decoding and the geometric stages are not significant bottlenecks.
Provenance¶
| Item | Value |
|---|---|
| Source branch | feature/pi5-bench |
| Source commit tested | e9b6088bea8ab801b2a1b3d6f852487d87d47543 |
| Commit subject | Measure multiprocessing against threads: 12% slower on the Pi 4 |
| Remote deployment | /root/dronevision-ai |
| Python environment | /root/dronevision-ai/.venv |
| Corpus samples | 337 four-camera frame sets |
| Corpus content | 30 seconds, four JPEG cameras, synchronized ground truth |
Artifact identity:
| Artifact | Size | SHA-256 |
|---|---|---|
models/drone_yolo26n_v4.onnx |
9,678,386 bytes | 7acd721e718a6fe444b22eb93300d2316ae4413209c2a89789072d4e1a4a3bc9 |
data/corpus/frames.zip |
12,864,307 bytes | 21596ae0161babdd593170378915a4d5b51da9d3adcb96a59b0998dd2e11d885 |
Board inventory¶
Hardware and operating system¶
| Resource | Observed value |
|---|---|
| Board | NXP i.MX93 11x11 FRDM |
| Application CPU | 2x Arm Cortex-A55 |
| Architecture | AArch64 |
| CPU features of interest | NEON, FP16 and Arm dot-product (asimddp) |
| Real-time core | Cortex-M33 available in the platform |
| RAM | 1,879 MiB usable, no swap |
| NPU | Arm Ethos-U65 exposed as /dev/ethosu0 |
| NPU reserved memory | 128 MiB |
| OS | NXP i.MX Release Distro 6.6 Scarthgap |
| Kernel | 6.6.36-lts-next-g34fd186d1571 |
| Root filesystem | 6.7 GiB ext4, approximately 2.5 GiB free during testing |
| Physical eMMC | 28.9 GiB / nominal 32 GB |
The eMMC currently has an 83 MiB boot partition and a 6.9 GiB root partition. Roughly 22 GiB are unpartitioned. Expanding the root partition would be useful before storing larger datasets or multiple model variants.
Connected and exposed devices¶
- HDMI is connected, with 1280x720 and 800x600 modes.
- Weston/Wayland and a terminal are active.
- A Logitech USB keyboard/mouse receiver is connected.
- Three I2C buses, SPI, GPIO, CAN, OP-TEE and the Ethos-U device are exposed.
can0exists but is down.- No
/dev/video*camera device is currently enumerated. - Audio playback is available through
mqs-audio; no capture device was enumerated.
Network state¶
eth0 negotiated at 100 Mbps during inspection and had two IPv4 addresses,
192.168.1.128 and 192.168.1.132. Both ConnMan and systemd-networkd were managing the
interface and requesting DHCP. This should be resolved before live latency measurements.
The system exposes SSH, RPCBind, NTP and Avahi. SSH permits direct root login and password
authentication, while the firewall policies are ACCEPT. This is acceptable only on an
isolated development network and should be hardened for deployment.
Installed development and AI stack¶
| Component | Version / state |
|---|---|
| Python | 3.12.4 |
| NumPy | 1.26.4 |
| OpenCV | 4.10.0 NXP build |
| PyYAML | 6.0.1 |
| ONNX Runtime | 1.17.1 |
| ONNX providers | CPUExecutionProvider only |
| TensorFlow Lite runtime | 2.16.2 |
| NNStreamer | 2.2.0 |
| Ethos-U driver stack and firmware | 24.05 |
| Vela compiler | 3.12.0 |
| GStreamer | 1.24.0 NXP build |
| GCC | 13.3.0 |
| CMake | 3.28.3 |
| Weston | 12.0.4 |
Docker and Podman are not installed. The full Gazebo/PX4 simulator is neither required nor appropriate for these board-side offline benchmarks.
Phase 0: preparation and traceability¶
Status: complete.
The committed source tree was transferred over SSH without requiring Git credentials on
the board. A virtual environment was created with --system-site-packages, and
DroneVision was installed editable with --no-deps. This deliberately preserves the NXP
builds of NumPy, OpenCV and ONNX Runtime instead of replacing them with generic wheels.
The effective module paths were verified as:
numpy /usr/lib/python3.12/site-packages/numpy/__init__.py
opencv /usr/lib/python3.12/site-packages/cv2/__init__.py
onnxruntime /usr/lib/python3.12/site-packages/onnxruntime/__init__.py
dronevision /root/dronevision-ai/dronevision/__init__.py
bench/pi.sh was generalized for Arm SBCs:
- Transfers are gzip-compressed;
THREADS=autotests one thread and the remote core count;SYSTEM_SITE_PACKAGES=1preserves vendor-optimized packages;BOARD_TAGcontrols target-specific output names;- The script is executable.
The setup command for this board is:
HOST=imx \
BRANCH=feature/pi5-bench \
SYSTEM_SITE_PACKAGES=1 \
BOARD_TAG=imx93 \
./bench/pi.sh setup
Phase 1: functional smoke test¶
Status: complete.
Corpus and configuration¶
factory.yaml loaded correctly. The first corpus set contained all four expected cameras:
cam_ne 360x640x3 RGB
cam_nw 360x640x3 RGB
cam_sw 360x640x3 RGB
cam_se 360x640x3 RGB
truth [0.00961, 0.08076, 2.45177]
ONNX smoke inference¶
One direct OnnxRuntime inference was run on cam_ne, without a benchmark sweep or
automatic warm-up passes.
| Property | Result |
|---|---|
| Provider | CPUExecutionProvider |
| Precision | FP32 |
| Input | images[1, 3, 320, 320] |
| Output | output0[1, 300, 6] |
| Output layout | YOLO end-to-end |
| ONNX intra-op threads | 2 |
| Session creation | 703.952 ms |
| Preprocess | 10.262 ms |
| First inference | 252.477 ms |
| Postprocess | 0.533 ms |
| Maximum RSS | 131,648 KiB |
| Temperature | 57.35 to 58.35 degrees C |
The selected first cam_ne image produced no detection above confidence 0.25. This was a
valid empty output, not a runtime error; the complete-corpus tests below measured the real
detection and localization rate.
Test suite¶
pytest 9.1.1 was installed only inside the project virtual environment.
The skipped tests cover optional components. No core test failed.
Phase 2: accuracy and end-to-end timing¶
Status: complete.
The tests were run serially to avoid CPU, memory and thermal interference:
# Classical marker baseline
.venv/bin/python -m bench.accuracy
# YOLO CPU baseline
.venv/bin/python -m bench.accuracy \
--detector yolo --runtime onnx --threads 1
# Use both Cortex-A55 cores
.venv/bin/python -m bench.accuracy \
--detector yolo --runtime onnx --threads 2
# Include JPEG reading and decode
.venv/bin/python -m bench.accuracy \
--detector yolo --runtime onnx --threads 2 --mode encoded
| Configuration | Localized | Misses | Mean 3D error | P95 3D error | Mean total | Frame sets/s |
|---|---|---|---|---|---|---|
| Colour, decoded | 337 | 0 | 6.22 mm | 10.72 mm | 30.225 ms | 33.09 |
| YOLO ONNX FP32, 1 thread | 333 | 4 | 36.42 mm | 77.58 mm | 1,607.158 ms | 0.622 |
| YOLO ONNX FP32, 2 threads | 333 | 4 | 36.42 mm | 77.58 mm | 977.734 ms | 1.023 |
| YOLO ONNX FP32, 2 threads, JPEG | 333 | 4 | 36.42 mm | 77.58 mm | 990.761 ms | 1.009 |
| YOLO INT8 Ethos-U65 NPU (Sequential) | 336 | 1 | 52.39 mm | 95.94 mm | 199.369 ms | 5.02 |
| YOLO INT8 Ethos-U65 NPU (2 Workers) | 336 | 1 | 52.39 mm | 95.94 mm | 167.777 ms | 5.96 |
YOLO localized 98.81% of the corpus frame sets on FP32 and 99.70% (336/337) on Ethos-U NPU. Precision was identical across thread counts and input modes, as expected.
Timing breakdown¶
| Configuration | Acquire | Detect | Triangulate | Total | Wall time |
|---|---|---|---|---|---|
| Colour, decoded | 0.060 ms | 25.841 ms | 4.237 ms | 30.225 ms | 10.31 s |
| YOLO, 1 thread, decoded | 0.060 ms | 1,604.101 ms | 2.918 ms | 1,607.158 ms | 541.71 s |
| YOLO, 2 threads, decoded | 0.060 ms | 974.626 ms | 2.968 ms | 977.734 ms | 329.59 s |
| YOLO, 2 threads, JPEG | 14.385 ms | 973.363 ms | 2.936 ms | 990.761 ms | 333.99 s |
| YOLO Ethos-U NPU (Sequential) | 0.059 ms | 195.899 ms | 3.330 ms | 199.369 ms | 67.30 s |
| YOLO Ethos-U NPU (2 Workers) | 0.060 ms | 164.176 ms | 3.459 ms | 167.777 ms | 56.66 s |
Two threads provide a 1.644x speed-up and reduce total latency by 39.16% relative to one thread. The process consumed approximately 173-175% CPU, showing that ONNX used both cores but did not scale perfectly because of serial work and synchronization.
JPEG adds approximately 13.0 ms per four-camera set, only 1.33% of total latency. The dominant cost is therefore inference, not acquisition, decode, association or geometry.
Memory and thermal observations¶
- Decoded mode retained much of the expanded corpus and reached approximately 54% process memory, leaving about 676 MiB available system-wide.
- Encoded mode used approximately 8% process memory and left about 1.55 GiB available.
- Encoded mode is strongly preferred on this 2 GB board.
- The two-thread runs stabilized around 59-60 degrees C.
- No throttling, OOM, kernel error or failed inference was observed.
- After testing, the board returned to approximately 53 degrees C and 1.6 GiB available.
Workload assessment¶
Observed two-core CPU/YOLO result:
The FP32 CPU implementation is almost an order of magnitude slower than the later NPU implementation and makes learned perception the clear system bottleneck.
The colour detector achieves 33 frame sets/s, but it depends on a visible colour marker and does not replace general drone detection.
Comparison context: Raspberry Pi 5¶
The i.MX93 has two Cortex-A55 cores and 2 GB RAM, while a Raspberry Pi 5 has four newer Cortex-A76 cores and is available with substantially more RAM. The Pi 5 is expected to be much faster for FP32 ONNX CPU inference and general development workloads.
The i.MX93 advantages are different: integrated 0.5-TOPS Ethos-U65, Cortex-M33, CAN-FD, eMMC, EdgeLock and embedded/industrial I/O. The correct comparison for this board is therefore not CPU FP32 alone, but optimized INT8 inference on its integrated NPU.
Limitations of these results¶
- ONNX Runtime exposes only
CPUExecutionProvider; the Ethos-U65 was not used. - The bundled ONNX model is FP32, not INT8.
- The corpus is hover-only, with little horizontal movement. It does not fully exercise tracking, coasting or motion-gated detection.
- Weston and the normal NXP development services remained active. These are results for the board as found, not a stripped headless image.
- The live ZeroMQ path was not tested.
pyzmqis not currently installed on the board. - No physical camera is enumerated, so all completed measurements used the bundled corpus.
- Power draw was not instrumented.
Remaining test plan¶
Phase 3: isolated speed benchmark¶
Run repeated, warmed inference measurements with one and two threads, collecting mean,
median, P95 and thermal context through bench.speed. This separates model execution from
the full localization loop and produces directly comparable JSON rows.
Phase 4: multicamera scheduling¶
Compare sequential execution, two camera workers and oversubscription. Test detect-every-N plus tracking if every-frame inference cannot meet the budget.
Phase 5: sustained thermal test¶
Run the best CPU case for 10-15 minutes, first with the system as found and then with Weston temporarily stopped. Record CPU temperature, frequency, memory and latency drift.
Phase 6: live network test¶
Resolve duplicate network management, install pyzmq in the virtual environment, and
measure camera JPEG transport, decode, inference, stale frames and recovery from one or
two missing cameras.
Phase 7: Ethos-U65 path¶
- Export or convert a TensorFlow Lite INT8 model.
- Quantize with representative images from the corpus.
- Check operator compatibility.
- Compile with Vela for Ethos-U65.
- Measure the delegated portion of the graph.
- Add a TFLite/Ethos-U runtime to DroneVision.
- Repeat accuracy, speed, multicamera and thermal tests.
Success requires accuracy close to the FP32 reference and a substantial reduction in the current 11.7x real-time performance gap.