Sunday, August 23, 2026

nn20vps: Visual Positioning on a $25 device

I have been experimenting with a fairly simple question:

Can a small, low-cost embedded device work out where a drone is from what its camera sees, without GPS?

That experiment became nn20vps, a proof-of-concept visual positioning system running fully locally on an ESP32-P4.

The goal is not to replace GPS. GPS is more accurate, cheaper in terms of compute, and should obviously be used whenever it is available. The interesting case is what happens when GPS is no longer available.

Could a drone still determine its approximate position well enough to return home or continue along a planned route?

Running the complete VPS on the ESP32-P4

The current implementation runs the complete positioning pipeline on a roughly $25 ESP32-P4 board.

A downward-looking camera image is processed into an embedding and compared with a database of reference imagery. Rather than trusting a single image match, nn20vps combines candidates over time and maintains a position estimate while the aircraft moves.

The complete pipeline includes:

  • image conditioning
  • neural-network embedding
  • vector search
  • temporal tracking
  • cold-start localisation
  • position recovery after a lost track

The embedded vector search is powered by nn20db, my vector database designed for resource-constrained devices.

The system uses two search levels. A fast local search runs around the currently estimated position, while a slower full-map search can search the complete reference database.

The local search handles normal tracking. The full-map search is used for a cold start, recovery after losing the position, and periodic checks to catch a track that has drifted.

That makes a genuine cold start possible: the device can begin without being told its location and search the complete map to find itself.

An 81 km² test area

For the demo I built an approximately 9 × 9 km, or 81 km², reference area around Ghent and Merelbeke in Belgium.

The reference maps come from public orthographic imagery published by Digitaal Vlaanderen.

One thing I specifically wanted to avoid was testing against exactly the same imagery used to create the model and reference database. That would produce impressive results, but would tell me much less about actual visual localisation.

The model and reference database were built using winter 2025 and summer 2021 imagery.

The demo flights use held-out epochs such as winter 2022, winter 2023, winter 2024 and summer 2018.

That means the system has to deal with different foliage, lighting, shadows, vehicles and changes in the landscape rather than simply matching against an identical image.

Current results

On a cross-season test flight running on the ESP32-P4, the system achieved:

  • 55 m median positioning error
  • 183 m p90 positioning error
  • 0.94 Hz camera frame rate
  • recovery from a 1,425 m error down to 28 m

That last number is probably the most interesting one.

The local tracker had drifted far enough that the correct position was outside its search window. The full-map search then searched the complete reference area and successfully re-acquired the aircraft, reducing an error of 1,425 m to 28 m.

For GPS, tens of metres would obviously be poor accuracy.

For a low-cost fallback system whose job is to answer "where am I roughly?" after GPS has disappeared, it starts to become useful.

The simulator

I also built a drone simulator around the system.

The simulator runs on a desktop and provides camera images and simulated telemetry, while the actual VPS runs on the ESP32-P4. Nothing about the positioning system itself is simulated.

The simulator knows the real aircraft position, but the VPS does not. Camera frames are generated from the absolute simulated position, never from the VPS estimate. Otherwise the simulation would become circular and positioning drift could not be tested properly.

The interface therefore shows two positions:

  • the real simulated aircraft position
  • the position reported by the ESP32-P4

It also supports waypoint-to-waypoint flights and lets me introduce disturbances such as wind, compass bias, odometry scale error and visual odometry noise.

What is published

I decided to publish the project as an evaluation/demo kit rather than keep tuning it indefinitely.

The repository contains:

  • the Python drone simulator
  • map download and preparation tools
  • prebuilt ESP32-P4 firmware
  • the nn20db reference database
  • instructions for reproducing the demo

The VPS core itself is written in C and is not published as source at this stage.

The idea is to make the proof of concept easy enough for other people to run and experiment with, and to see whether the approach is interesting before taking it much further.

What is still missing

This is very much a proof of concept.

The current testing uses orthographic map imagery in the simulator. The obvious next validation step is real downward-looking drone footage, ideally around 70 metres altitude, together with real telemetry.

That will introduce additional problems that the simulator does not fully reproduce: lens distortion, vibration, motion blur, camera attitude, altitude errors and a much larger visual difference between the live camera and the reference orthophoto.

That is the test that should show whether the current results translate into something genuinely useful outside the simulator.

For now, though, I think it has reached the point where it is more interesting to let other people try it than to keep polishing the same demo.