Skip to content

Wrapping flight gap identification in UI #738

Draft
allisonsibrian wants to merge 7 commits intohotosm:devfrom
allisonsibrian:feat/flight-gap-ui
Draft

Wrapping flight gap identification in UI #738
allisonsibrian wants to merge 7 commits intohotosm:devfrom
allisonsibrian:feat/flight-gap-ui

Conversation

@allisonsibrian
Copy link
Collaborator

@allisonsibrian allisonsibrian commented Mar 16, 2026

What type of PR is this? (check all applicable)

  • 🍕 Feature
  • 🐛 Bug Fix
  • 📝 Documentation
  • 🧑‍💻 Refactor
  • ✅ Test
  • 🤖 Build or CI
  • ❓ Other (please specify)

Related Issue

Fixes #512

Describe this PR

Draft PR that wraps flight gap identification into a UI accessible to users.

Updates on the flight gap identification function:

  • Now returns a dictionary rather than bytes that contains a successful message, the task aoi, the gap polygons, drone type, file bytes, and image points to be utilized by the frontend.
  • Optional manual gaps added (still needs to be implemented in frontend) that skips the analysis and goes straight to reconstruction if the user manually adds their own gaps.
  • Important tracking variables set in the very beginning with safety constraints around flight drone type, altitude, and side overlap medians that still runs if values are None.
    - Note: For drone type, a hard variable is not set if an image does not have drone type metadata. I am not sure if this is an issue for users.
  • Testing for flight gaps now considers these changes.

For Routes:

  • POST and GET routes created for posting the result of the gap identification function and getting a download flightplan.

For Frontend:

  • I created a 'Find Flight Gaps' button right next to the 'Verify Tasks Button' in red.
  • I followed the same structure as the TaskVerificationModal, where a user can see all of the gaps for their specific task, in addition to their image points (easier to track gaps by where they occurred by images taken).
  • Still Needs to Be Added: Users can manually delete and add gaps
  • User can finalize gaps through 'Finalize Gaps' button that -> creates a 'Download Flight Plan' button for the user.

Screenshots

Screenshot 2026-03-14 at 11 23 11 PM Screenshot 2026-03-15 at 3 53 44 PM Screenshot 2026-03-15 at 3 54 01 PM 63b54ee" /> Screenshot 2026-03-15 at 3 54 25 PM

Alternative Approaches Considered

  • I considered adding Flight Gaps in the Task Verification Modal; however, to make it visible to the user, I opted for making it a separate button and modal.

Review Guide

  1. Create a test project
  2. Run the image processing workflow and upload imagery
  3. Test out 'Find Flight Gap' buttons and modal during the Image Review phase.

My next steps consist of:

  • Allowing manual changes to be added by the user in the frontend:
    • Adding and deleting gaps
  • Allowing the flight plan to be downloaded once finalized.

A few things to note on the screenshots provided:

  • I lowered the threshold and hardcoded a drone type since I utilized the Aukerman dataset from ODM, and it had missing metadata (such as drone type).
    • Lowering the threshold resulted in the gaps observed in the screenshot. I tried omitting images from the dataset to trigger the original threshold, but it still would not find gaps.
  • Images were not loading for me in the frontend, but the process still worked.
  • After pressing the 'Download Flight Plan', the url is redirected to the download URL, but nothing happens. (Last image)

Please let me know if these changes would make sense for users structurally. I personally thought separating the buttons during the ImageReview Process made sense, but I am open to overall feedback, especially on how this aspect/feature should look for users (e.g, button colors, if sidebar is needed, etc.).

Sorry this took a while. I've been busy, and this was my first time making frontend changes, so I wanted to make sure I understood all of these different pieces and how they played together!

Checklist before requesting a review

  • 📖 Read the HOT Code of Conduct: https://docs.hotosm.org/code-of-conduct
  • 👷‍♀️ Create small PRs. In most cases, this will be possible.
  • ✅ Provide tests for your changes.
  • 📝 Use descriptive commit messages.
  • 📗 Update any related documentation and include any relevant screenshots.

[optional] What gif best describes this PR or how it makes you feel?

@github-actions github-actions bot added enhancement New feature or request backend Related to backend code frontend labels Mar 16, 2026
@spwoodcock
Copy link
Member

I rebased this on the latest photo uploader changes on dev & moved things around a little - it's looking great!

Had to force push though for the rebase, sorry - it might mean you need to git reset you branch to this git fetch feat/flight-gap-ui && git reset --hard origin feat/flight-gap-ui

@spwoodcock
Copy link
Member

Oh also, I had to add a dropdown for the user to select their drone model.

I think the flight gap identification does belong as part of this workflow, but the problem with the project details page is that the user doesn't select a drone type (that's only on the task details page, where they generate flightplans). So we need to also ask the user which drone it's a flightplan for =)

@spwoodcock
Copy link
Member

image image image image

Currently the identify gaps dialog is a bit redundant - it could simply download the flightplan immediately from the button, instead of opening the dialog. But I think the idea was that if there are two clear 'gaps' that are not connected, the user can select for which one they wish to generate the flightplan? It could probably be refined a bit, but for now it's great work!

Example response (it says 'no gaps detected' for a task where there are only two images inside - from agung-2 dataset).
So maybe a little bit of refinement is needed, but we are mostly there =)

{"task_id":"2dcf8bf9-2654-4631-a9f3-550a106311ef","message":"No gaps detected","task_geometry":{"type":"Feature","properties":{},"geometry":{"type":"Polygon","coordinates":[[[115.507831,-8.241272],[115.506027,-8.246768],[115.50327,-8.246768],[115.494287,-8.246768],[115.494287,-8.237878],[115.494287,-8.237058],[115.496921,-8.237878],[115.50327,-8.239853],[115.507831,-8.241272]]]}},"gap_polygons":{"type":"FeatureCollection","features":[]},"drone_type":"DJI_MINI_5_PRO","images":{"type":"FeatureCollection","features":[{"type":"Feature","geometry":{"type":"Point","coordinates":[115.494488139,-8.241717917]},"properties":{"id":"d1952622-7fec-46ea-b8e8-c6ef52d3eb35","filename":"DJI_20251027143608_0008_D.JPG","status":"assigned","thumbnail_url":"http://localhost:9000/dtm-bucket/projects/5b9dd85e-baca-47a9-b528-e080e630aa53/user-uploads/thumb_DJI_20251027143608_0008_D.JPG?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=admin%2F20260317%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260317T052203Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=1146463081636f888589ea630780753434f9f72ea6a6671bf68df8607305732d","url":"http://localhost:9000/dtm-bucket/projects/5b9dd85e-baca-47a9-b528-e080e630aa53/user-uploads/DJI_20251027143608_0008_D.JPG?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=admin%2F20260317%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260317T052203Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=8f755caad7be5410f607d12b67954d089368fa461412d2195432356ed8972728"}},{"type":"Feature","geometry":{"type":"Point","coordinates":[115.4946985,-8.241717444]},"properties":{"id":"805ee1b7-140d-4916-b9f0-b7e50c8459f9","filename":"DJI_20251027143610_0009_D.JPG","status":"assigned","thumbnail_url":"http://localhost:9000/dtm-bucket/projects/5b9dd85e-baca-47a9-b528-e080e630aa53/user-uploads/thumb_DJI_20251027143610_0009_D.JPG?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=admin%2F20260317%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260317T052203Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=b0747be0595d28513182d66e8e2ddc15f2f1b49eb6801110eb6cff991d1b4654","url":"http://localhost:9000/dtm-bucket/projects/5b9dd85e-baca-47a9-b528-e080e630aa53/user-uploads/DJI_20251027143610_0009_D.JPG?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=admin%2F20260317%2Fus-east-1%2Fs3%2Faws4_request&X-Amz-Date=20260317T052203Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=53338e14b4f0d349e14a4e95a42ab6e0d2817846f1a8d1406bc6052932b8d074"}}]},"flightplan_url":null}

@spwoodcock
Copy link
Member

spwoodcock commented Mar 17, 2026

The main detector is built for trajectory analysis: it skips any segment with fewer than 20 images, hence:

image

MIN_SEGMENT_SIZE = 20

There is a sparse-coverage fallback, that should trigger when there are 5 images or fewer in the segment (SPARSE_SEGMENT_MAX_IMAGES = 5), but this doesn't seem to work as expected:

image

I need to test this with the generate-flight-gaps script in https://github.com/spwoodcock/drone-testdata-freetown-1 (which is much more applicable and a valid test)

Ideal scenario:

  1. User clicks to identify gaps.
  2. A map displays highlighting the areas with gaps.
  3. User clicks to generate flightplan
  4. A flightplan in waypoint mode is generated that captures all of the missing points (and the photos are captured automatically in waypoint mode too).
  5. User flies this one flight and it should cover all the remaining 'gaps' - it's unlikely they will need to do two 'gap' re-flights, else the task area would have been way to big to start with.

@allisonsibrian
Copy link
Collaborator Author

Thanks Sam! I appreciate you revising and adding these changes, as well as testing thoroughly!
I unfortunately have my hands a bit full right now, but hoping to sync and review these changes towards the end of the week. I can take a look at sparse coverage fallback and current min segment size closely, and finalize the revised changes for the ideal scenario.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend Related to backend code enhancement New feature or request frontend

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Web UI to allow user to select areas from the first pass ortho that were missed by flights & create a second pass flight

2 participants