OpenDroneKit

The whole drone inspection, on your own laptop.

OpenDroneKit is an open-source Windows app that plans the mission, flies it over MAVLink, reconstructs the site, finds defects, measures them in metres and writes the report. No cloud account, no upload. Outputs land in a real coordinate reference system and open directly in QGIS.

There is no Windows installer yet. When one is published it will appear here with its version, size and SHA-256. Until then, OpenDroneKit runs from source in a Python 3.11 environment.

Launch reel · 1:30 · sound onAukerman Park sample survey · OpenDroneMap
The reel shows real OpenDroneKit output: the public Aukerman Park survey (77 photos) for maps and measurements, held-out test images for the models. Fleet records in the reel are demo records.

Plan → fly → reconstruct → detect → measure → report

One desktop app for the whole inspection, run end to end on the public OpenDroneMap Aukerman survey. The figures below are drawn from that run’s output files, in UTM 17N.

01Plan

Missions with real constraint geometry

Sixteen templates, laid out inside your geofence: ray-cast containment, no-fly polygons with detours inserted per segment, altitude bands, standoff and return-to-home rules. Terrain-aware AGL/AMSL following from a GeoTIFF, ESRI ASCII grid, CSV samples or a fitted plane.

griddouble gridcorridorfacadetowersolarorbitpanorama360 bubblewaypointsrooflinearlateralmagneticlinkedadaptive
Template
grid
Waypoints
152
Flight length
1,853.3 m
Estimated time
5.1 min
Altitude
55 m rel. home
Ground sample distance
1.29 cm
Grid plan for Aukerman Park. 152 waypoints inside the site boundary (dashed: the 13-vertex hull of the survey’s camera positions, 40,818 m²). Green ring: first waypoint.

02Fly

MAVLink upload, live telemetry

Missions upload with yaw, gimbal pitch, dwell and camera triggers, plus geofence and rally points, each through the MAVLink request/ack transfer protocol into the right mission slot. Live telemetry; arm, start, pause, RTL and abort from the app.

Autopilot
ArduPilot (MAVLink 2)
Simulation testing
ArduPilot Copter 4.5.7 (SITL)
Mission · fence · rally
checked against a MAVLink peer
Mock driver
always labelled SIMULATED

Flight code is tested against real ArduPilot Copter 4.5.7 firmware running in simulation. That testing caught missions putting NAV_TAKEOFF at sequence 0, which MAVLink reserves for home, after every mock-based test had passed.

77 camera stations, recovered from the photos. The 2016 Aukerman survey was flown by an eBee, not by OpenDroneKit; these are the positions the reconstruction solved, joined in capture order (10:47 to 11:04).

03Reconstruct

Georeferenced products, solved locally

COLMAP structure-from-motion with bundle adjustment, intrinsics from an EXIF sensor database, and georeferencing solved as a RANSAC Helmert similarity between camera centres and image geotags. Outputs a Cloud-Optimized GeoTIFF orthomosaic, DSM, DTM and hillshade in the automatically chosen UTM zone, plus a point cloud, Poisson mesh and camera-track GeoJSON.

Images registered
77 / 77
Mean reprojection error
1.255 px
Georeference RMSE
1.12 m (77 inliers)
Orthomosaic
0.033 m/px · 8192 × 6406
DSM
1.23 m/px · 230.3–264.1 m
CRS
EPSG:32617 · UTM 17N
DSM from the full-quality run, shown at its true 1.23 m/px. Dense stereo needs a CUDA COLMAP build that this machine’s driver could not load, so the surface comes from the sparse cloud and the run said so in its warnings. With dense MVS, a 20-frame run reached 0.32 m/px.

04Detect

Findings that carry their evidence

Trained ONNX models for cracks, corrosion severity, structural damage and solar faults. Every finding stores the model key, the SHA-256 of the weights file that produced it, and its confidence. The installed file is hashed at load and compared with the registry; a mismatch is reported, not used.

Refusal · actual response

corrosion_severity_segmentation cannot run: Its weights are not installed on this machine.

Api.grade_corrosion with no model present. Colour rules can find rust, but nothing outside the training corpus separates poor from severe, so the app answers with a reason instead of a grade.

Concrete surface with a long crack; the model's crack mask is drawn over it in red
crack_segmentationSegFormer-B5 · threshold 0.85sha256 3391eca1…0c23IoU 0.853 on this image
Electroluminescence image of a solar cell with three detector boxes on defects
solar_cell_defect_detectorYOLO11l · EL imagerysha256 a57676a7…783b3 boxes · scores 0.38–0.39

Both images are from held-out test splits. The crack image is the best of 18 sampled (median IoU of those with cracks: 0.701; whole split: 0.637). Each solar box sits on an annotated defect, but on all three the finger/crack class disagrees with the annotation: the boxes are found, the label is not to be trusted here.

05Measure

Metres, not pixels

Area, perimeter, volume and change against the real DSM and DTM. Defects are back-projected from 2-D images onto the reconstructed surface to become georeferenced polygons with square-metre areas. Volume is verified to 0.00 m³ error against an analytic test surface.

Area (planimetric)
23,591.8 m²
Perimeter
609.72 m
Volume above terrain
10,182 m³
Max height above DTM
13.09 m

The volume covers the 17,137 m² of the polygon where the 1.23 m/px DSM has data. Without georeferenced rasters, the report says measurements are absent rather than printing zeros.

Orthomosaic, 0.033 m/px, with the measured polygon. Pixel colours are measured; relief between sparse points is interpolated, so trees and roofs can lean.

06Report

A report a client can read

Built from the open project: site information, missions, datasets, reviewed findings and measurements. A finding rejected in review leaves the report. The PDF is drawn from the same sections as the HTML.

.htmlbrowser
.pdfreportlab
.docxWord, editable
.mdMarkdown
First page of the generated Aukerman Park inspection report: site information, executive summary and missions table

Aukerman Park survey

Pages7
Findings0
CRSEPSG:32617
Page 1 of the generated report. No findings were recorded for this project, and the report says so, adding that this is not evidence the asset is free of defects.

Measured, not promised

Each number is the registry’s own figure for the installed weights, with the split it was measured on and the weakness its entry names.

0.637IoU · held-out test split

Crack segmentation

SegFormer-B5 at 1024 px, threshold 0.85. Precision 0.811, recall 0.748.

Thin, faint cracks are missed, so an empty mask is not evidence of a sound surface. Crack width is not measured.

crack_segmentation
0.788severe-pixel recall

Corrosion severity

SegFormer-B2 grading every pixel good / fair / poor / severe. Mean IoU 0.577.

Errors are almost all one grade, so a reported grade can be one step optimistic. 440 images from a single source.

corrosion_severity_segmentation
0.884mAP50 · validation

Solar cell defects

YOLO11l on electroluminescence images of individual cells (PVEL-AD).

EL imagery only. There is no model for RGB photographs of panels; a photo is refused with that reason.

solar_cell_defect_detector
0.724balanced accuracy · validation

Thermal anomalies

ResNet18 classifying aerial infrared modules across 12 classes; all 12 are recalled.

Soiling is the weak class at 0.367 recall: about two soiled modules in three are missed.

solar_thermal_anomaly_classifier

Three further models were trained and rejected rather than shipped, with the reasons kept in the registry. Weights are not stored in the Git repository; the registry records the SHA-256 of each file whose metrics were measured. Full detail in docs/FEATURES.md.

Refuses rather than guesses

A missing model or dependency produces a refusal with a reason, never a quietly worse answer. A heuristic is labelled as a heuristic and is never reported as AI.

Every finding is attributable

Model key, weights digest and confidence travel with each result. The API refuses a model-sourced defect that is missing any of them.

A person signs off

Findings go to review first. Accept, reject and flag append to a history instead of overwriting it, and a rejected finding leaves the report.

Your survey never leaves the laptop

Built for sites with no signal and clients who do not want their imagery on someone else’s server.

Nothing calls home

Processing, detection, measurement and reporting run on your machine. Cloud reconstruction is not implemented: requesting it runs locally and the run says so.

Offline basemaps

Frame the site before you leave and press Cache view: satellite tiles for that view and three zoom levels deeper are stored on disk. Areas never cached stay visibly empty.

Local data root

Projects, mission versions and the audit log live in SQLite under one data folder you choose. PostGIS is there for multi-user deployments, not required.

No GPU required

A GPU only matters for dense reconstruction (a CUDA COLMAP build) and for training your own models. Environment Capabilities shows what this machine can do before you start a long job.

Works with the tools you already fly and map with

Mission export

.planQGroundControl
.waypointsQGC WPL; round-trips through pymavlink
.kmzDJI WPML
.csvLitchi (split when long)
.kml / .geojsonGoogle Earth, QGIS, any GIS

Flight

ArduPilotDirect control over MAVLink 2; tested in simulation (SITL)
MAVLinkMission, geofence and rally upload; telemetry
DJI · LitchiExport only: fly the file with their apps

Products

COG GeoTIFFOrthomosaic, DSM, DTM, hillshade
.ply / .objPoint cloud, Poisson mesh
.geojsonCamera track, defect polygons
CRSAuto-selected UTM zone or your EPSG; opens in QGIS

Run it today, from source

The Windows installer is not out yet. These are the steps from docs/INSTALLATION.md.

  1. Clone the repository.

    git clone https://github.com/00PrabalK00/OpenDroneKit.git
    cd OpenDroneKit
    
  2. Create a Python 3.11 environment (conda shown; any Python 3.11+ environment works) and install the packages.

    conda create -n odk python=3.11 -y
    conda activate odk
    pip install -r requirements.txt
    
  3. Check the install with the test suite. Several hundred passes and a handful of skips is a clean run: a skip marks an optional dependency that is absent, not a failure.

    python -m pytest
    
  4. Start the desktop app. On Windows you can also double-click OpenDroneKit.bat in the repository folder.

    python main.py
    

System requirements

OSWindows, using its built-in Edge WebView2. Also developed and tested on Linux.
Python3.11 or newer, plus the packages in requirements.txt
GitAny version, for cloning
GPUOptional. NVIDIA + CUDA COLMAP for dense reconstruction; training
NetworkOnly to install, and to cache basemap tiles

What a missing piece costs you

open3dNo mesh; cloud, DSM and ortho unaffected
rasterioFlat-earth planning, with a warning on every plan
onnxruntimeDetection refuses instead of returning empty results
pymavlinkNo flight control; planning and processing unaffected