DroneTracker
Aims AXIS Q-8615E PTZ cameras at AERPAW UAVs from Kafka GPS/velocity and records the flight over VAPIX.
Built
Dockerized field service: Kafka position/velocity in, VAPIX pan/tilt/zoom out, recordings to the camera SD card as Matroska. Stock sensecam-control had PTZ but not record, so I forked sensecam-control-record for start/stop/export. YAML holds site pose, FOV scale, and drone size; dry-run works without a camera.
Hard parts
- Pan is a spherical bearing; tilt is elevation; zoom maps a Q-8615E FOV model into 0–9999 steps.
- Camera north-offset has to wrap into AXIS ±180° pan.
- Optional velocity lead: NEU vs a possible NED convention (sign-flip on vz).
- Minimum pan/zoom steps so the PTZ is not spammed; stale telemetry parks the camera.
Learned
Closing a telemetry bus onto a physical PTZ is as much field ops as math: Digest-auth CGI, host-network Docker, and a library that can actually start a recording.
Also
- Geodetic → pan/tilt/zoom for AXIS Q-8615E, including FOV calibration
- Kafka data, command, and output topics; packet-timeout deactivate
- VAPIX recording start/stop/export via a forked sensecam-control
- Docker Compose, host networking, recordings volume, dry-run mode
The job
DroneTracker keeps an AXIS Q-8615E pointed at an AERPAW UAV and records the pass. Positions and velocities arrive on Kafka. Commands leave over VAPIX. Recordings land on the camera SD card as Matroska. The repo is quantumbagel/DroneTracker.
This is the featured project that actually uses Kafka. PyAerial does not. I keep saying that because the AERPAW-adjacent repos share a vocabulary and not a stack.
Geometry before CGI
Pan is a spherical bearing from the camera to the aircraft. Tilt is elevation. Zoom is a Q-8615E field-of-view model mapped into 0–9999 steps, using slant range and a configured drone size. YAML holds site pose, FOV scale, and that size. If those numbers are wrong, VAPIX will faithfully stare at the wrong sky.
Camera north-offset has to wrap into AXIS ±180° pan. Optional velocity lead is NEU; a NED source will look fine until vz is the wrong sign. I forked sensecam-control-record because stock sensecam-control could PTZ and could not start a recording.
Field ops is the other half
Kafka lag looks like a tracking bug. A stale packet is a confident wrong pan, so a timeout parks the camera instead of chasing history. Minimum pan/zoom steps exist because command spam does not slew the head faster — it makes it hunt. Digest-auth CGI, host-network Docker, and a dry-run mode without a camera are how this survives a field day.
Closing a telemetry bus onto a physical PTZ is as much ops as math. The library either starts a recording or it does not. There is no dashboard that makes a bad bearing look good.