Problem
fly_footprint() sizes a digital frame through R/fly_camera_format.R, keyed on
camera_calibration_url / calib_file — the calibration reports the BC Data Catalogue links
for its survey aircraft. A UAV frame has no entry in that catalogue, so today it falls to
inferred_format (sized from focal_length) or unknown_format (empty geometry).
But a UAV's sensor geometry is not unknown — it is published by the manufacturer and is more
precise than anything recoverable from a scanned calibration PDF. There is no route that says
"this frame came from a Mini 4 Pro at 48 MP" and sizes it exactly.
This blocks planning UAV coverage over an AOI, which is the sibling work in stac_uav_bc.
fly_coverage() and fly_select() already do what that needs; only the footprint sizing is
missing.
What is known
DJI Mini 4 Pro, from the published specs:
1/1.3" CMOS, 2.4 µm 4-in-1 pixels (so 1.2 µm native), 48 MP = 8064 × 6048,
6.72 mm actual focal length. Derived sensor 9.68 × 7.26 mm, diagonal 12.10 mm against a
1/1.3" nominal ~12.1 mm — consistent.
At 300 m AGL that gives a 432 × 324 m footprint and 5.36 cm/px.
This is validated against real flight plans, not just arithmetic. Five DJI WPML missions
flown over the Morice (MORR) floodplain in 2026 carry measured transect spacing of 86.0 m and
along-track photo spacing of 65.0 m. Against a 432 × 324 m footprint those are 80.1% side
and 79.9% forward overlap — i.e. the published sensor geometry reproduces the spacings an
independent planner computed, to within a tenth of a percent.
Binning is a mode, not a camera. The same sensor at 12 MP binned (4032 × 3024, 2.4 µm)
gives an identical 432 × 324 m footprint and 10.71 cm/px. Footprint is set by field of view and
height; megapixels only move GSD. So the format table needs a resolution mode alongside the
camera, or a single "Mini 4 Pro" row silently halves or doubles the GSD it implies.
Proposed work
- Add a UAV sizing route to
fly_camera_format.R: sensor dimensions and focal length keyed on
camera and resolution mode, sourced from manufacturer specs rather than calibration PDFs.
Mini 4 Pro at 48 MP and at 12 MP as the first two entries.
- Decide where those rows live — extending
inst/extdata/camera_formats.csv versus a sibling
table. The existing file's columns (width_mm, height_mm, px_cross, px_along,
pitch_um, focal_mm) already carry everything needed, but its key_type and provenance
columns (report_serial, source_pdf, retrieved) describe a calibration report and do not
apply. Whichever way, camera_formats_manifest.csv's drift guard should still cover it.
- Record the route in
footprint_basis so a UAV-sized frame is distinguishable from a film or
calibration-sized one, consistent with the v0.4.0 decision to refuse rather than estimate.
- Tests from the measured numbers above: footprint dimensions at 300 m, GSD at both resolution
modes, and the 80/80 spacings the five real missions imply.
Acceptance
fly_footprint() on a Mini 4 Pro frame at 300 m AGL returns a 432 × 324 m rectangle
- GSD resolves to 5.36 cm/px at 48 MP and 10.71 cm/px at 12 MP, from the same footprint
footprint_basis names the UAV route explicitly
- An unknown UAV camera still returns empty geometry rather than a guess
Scope note
This is a remit question as well as a code change. fly is described as a historic airphoto
toolkit — README, acronym and CLAUDE.md all say legacy — and fly_georef/fly_bearing already
handle digital frames, so the digital path is live rather than hypothetical. Sizing a UAV frame
widens that to "aerial image footprints, whatever produced them", which is a small and
defensible step.
What is explicitly out of scope here, and belongs in the stac_uav_bc sibling issue:
battery endurance budgets, launch-point placement, transect ordering, DJI WPML/KMZ writing.
fly carries no notion of a battery, a home point, a waypoint or a gimbal today (measured: zero
files under R/, tests/ or inst/ mention any of them) and this issue does not add one.
Problem
fly_footprint()sizes a digital frame throughR/fly_camera_format.R, keyed oncamera_calibration_url/calib_file— the calibration reports the BC Data Catalogue linksfor its survey aircraft. A UAV frame has no entry in that catalogue, so today it falls to
inferred_format(sized fromfocal_length) orunknown_format(empty geometry).But a UAV's sensor geometry is not unknown — it is published by the manufacturer and is more
precise than anything recoverable from a scanned calibration PDF. There is no route that says
"this frame came from a Mini 4 Pro at 48 MP" and sizes it exactly.
This blocks planning UAV coverage over an AOI, which is the sibling work in
stac_uav_bc.fly_coverage()andfly_select()already do what that needs; only the footprint sizing ismissing.
What is known
DJI Mini 4 Pro, from the published specs:
1/1.3" CMOS, 2.4 µm 4-in-1 pixels (so 1.2 µm native), 48 MP = 8064 × 6048,
6.72 mm actual focal length. Derived sensor 9.68 × 7.26 mm, diagonal 12.10 mm against a
1/1.3" nominal ~12.1 mm — consistent.
At 300 m AGL that gives a 432 × 324 m footprint and 5.36 cm/px.
This is validated against real flight plans, not just arithmetic. Five DJI WPML missions
flown over the Morice (MORR) floodplain in 2026 carry measured transect spacing of 86.0 m and
along-track photo spacing of 65.0 m. Against a 432 × 324 m footprint those are 80.1% side
and 79.9% forward overlap — i.e. the published sensor geometry reproduces the spacings an
independent planner computed, to within a tenth of a percent.
Binning is a mode, not a camera. The same sensor at 12 MP binned (4032 × 3024, 2.4 µm)
gives an identical 432 × 324 m footprint and 10.71 cm/px. Footprint is set by field of view and
height; megapixels only move GSD. So the format table needs a resolution mode alongside the
camera, or a single "Mini 4 Pro" row silently halves or doubles the GSD it implies.
Proposed work
fly_camera_format.R: sensor dimensions and focal length keyed oncamera and resolution mode, sourced from manufacturer specs rather than calibration PDFs.
Mini 4 Pro at 48 MP and at 12 MP as the first two entries.
inst/extdata/camera_formats.csvversus a siblingtable. The existing file's columns (
width_mm,height_mm,px_cross,px_along,pitch_um,focal_mm) already carry everything needed, but itskey_typeand provenancecolumns (
report_serial,source_pdf,retrieved) describe a calibration report and do notapply. Whichever way,
camera_formats_manifest.csv's drift guard should still cover it.footprint_basisso a UAV-sized frame is distinguishable from a film orcalibration-sized one, consistent with the v0.4.0 decision to refuse rather than estimate.
modes, and the 80/80 spacings the five real missions imply.
Acceptance
fly_footprint()on a Mini 4 Pro frame at 300 m AGL returns a 432 × 324 m rectanglefootprint_basisnames the UAV route explicitlyScope note
This is a remit question as well as a code change. fly is described as a historic airphoto
toolkit — README, acronym and CLAUDE.md all say legacy — and
fly_georef/fly_bearingalreadyhandle digital frames, so the digital path is live rather than hypothetical. Sizing a UAV frame
widens that to "aerial image footprints, whatever produced them", which is a small and
defensible step.
What is explicitly out of scope here, and belongs in the
stac_uav_bcsibling issue:battery endurance budgets, launch-point placement, transect ordering, DJI WPML/KMZ writing.
fly carries no notion of a battery, a home point, a waypoint or a gimbal today (measured: zero
files under
R/,tests/orinst/mention any of them) and this issue does not add one.