Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implementing Terrain Following in the waypoint generation API plus GSD #123

Merged
merged 3 commits into from
Aug 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 67 additions & 27 deletions src/backend/app/waypoints/waypoint_routes.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import uuid
import geojson
import shutil
from fastapi import APIRouter, UploadFile, File, Form, HTTPException
from fastapi.responses import FileResponse
from app.config import settings
from drone_flightplan import flightplan, waypoints
from app.models.enums import HTTPStatus

# Constant to convert gsd to Altitude above ground level
GSD_to_AGL_CONST = 29.7 # For DJI Mini 4 Pro

router = APIRouter(
prefix=f"{settings.API_PREFIX}/waypoint",
Expand All @@ -20,9 +24,13 @@ async def generate_kmz(
description="The GeoJSON file representing the project area. This file will be used to define the boundaries and paths for the flight plan.",
),
altitude: float = Form(
80,
None,
description="The altitude at which the drone should fly during the mission, in meters.",
),
gsd: float = Form(
None,
description="Excepted gsd value",
),
download: bool = Form(
True,
description="A flag indicating weather you want to download the kmz file or view the waypoint coordinates first. If True, file will be downloaded directly",
Expand All @@ -43,35 +51,67 @@ async def generate_kmz(
False,
description="A flag indicating weather you want to generate 3D imageries or not (To generate 3D imagery, we need to click images at 3 different angles -90, -45 and lateral 45 degree angle)",
),
terrain_follow: bool = Form(
False,
description="A flag indicating weather you want to generate flight plan with terrain follow.",
),
dem: UploadFile = File(
None,
description="The Digital Elevation Model (DEM) file that will be used to generate the terrain follow flight plan. This file should be in GeoTIFF format",
),
):
try:
boundary = geojson.loads(await project_geojson.read())

features = boundary["features"][0]
if not (altitude or gsd):
raise HTTPException(
status_code=HTTPStatus.BAD_REQUEST,
detail="Either altitude or gsd is required",
)

if not download:
return waypoints.create_waypoint(
features,
altitude,
forward_overlap,
side_overlap,
generate_each_points,
generate_3d,
if terrain_follow:
if not dem:
raise HTTPException(
status_code=400,
detail="DEM file is required for terrain follow",
)
else:
output_file = flightplan.generate_flightplan(
features,
altitude,
forward_overlap,
side_overlap,
generate_each_points,
generate_3d,
f"/tmp/{uuid.uuid4()}",
if dem.content_type != "image/tiff":
raise HTTPException(
status_code=400,
detail="DEM file should be in GeoTIFF format",
)

return FileResponse(
output_file, media_type="application/zip", filename="output.kmz"
)
dem_path = f"/tmp/{dem.filename}"
with open(dem_path, "wb") as buffer:
shutil.copyfileobj(dem.file, buffer)

boundary = geojson.loads(await project_geojson.read())
features = boundary["features"][0]

if not download:
# TODO This should be fixed within the drone_flightplan
if gsd:
altitude = gsd * GSD_to_AGL_CONST

return waypoints.create_waypoint(
features,
altitude,
forward_overlap,
side_overlap,
generate_each_points,
generate_3d,
)
else:
output_file = flightplan.generate_flightplan(
features,
altitude,
gsd,
forward_overlap,
side_overlap,
generate_each_points,
generate_3d,
terrain_follow,
dem_path if dem else None,
f"/tmp/{uuid.uuid4()}",
)

except Exception as e:
raise HTTPException(status_code=500, detail=str(e))
return FileResponse(
output_file, media_type="application/zip", filename="output.kmz"
)
30 changes: 11 additions & 19 deletions src/backend/pdm.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/backend/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ dependencies = [
"GDAL==3.6.2",
"aiosmtplib>=3.0.1",
"python-slugify>=8.0.4",
"drone-flightplan>=0.1.2",
"drone-flightplan>=0.2.1",
]
requires-python = ">=3.11"
license = {text = "GPL-3.0-only"}
Expand Down
Loading