From ef82d3d6dce71f6c2fd864e6bb6bfd02273973a2 Mon Sep 17 00:00:00 2001 From: Pradip-p Date: Tue, 24 Dec 2024 14:00:38 +0545 Subject: [PATCH 1/5] feat: update constants values for DJJ air 3 --- drone_flightplan/add_elevation_from_dem.py | 9 ++++++-- drone_flightplan/calculate_parameters.py | 21 +++++++++-------- drone_flightplan/create_flightplan.py | 8 ++++++- drone_flightplan/drone_type.py | 27 ++++++++++++++++++++++ drone_flightplan/waypoints.py | 5 +++- 5 files changed, 57 insertions(+), 13 deletions(-) create mode 100644 drone_flightplan/drone_type.py diff --git a/drone_flightplan/add_elevation_from_dem.py b/drone_flightplan/add_elevation_from_dem.py index 83e790c..612cc40 100755 --- a/drone_flightplan/add_elevation_from_dem.py +++ b/drone_flightplan/add_elevation_from_dem.py @@ -19,6 +19,7 @@ log = logging.getLogger(__name__) + def raster_data_format_string(input_datatype: str): """ Returns a format string for unpacking a c-style Struct object based @@ -126,11 +127,15 @@ def add_elevation_from_dem(raster_file, points, outfile): # It's almost certainly a nodata value, possibly over water elevation = 0 except Exception as e: - log.error(f"Error reading elevation at point ({geom.GetX()}, {geom.GetY()}): {e}") + log.error( + f"Error reading elevation at point ({geom.GetX()}, {geom.GetY()}): {e}" + ) elevation = 0 else: # Point is outside the raster bounds, set elevation to 0 or another fallback value - log.info(f"Point ({geom.GetX()}, {geom.GetY()}) is outside the raster bounds.") + log.info( + f"Point ({geom.GetX()}, {geom.GetY()}) is outside the raster bounds." + ) elevation = 0 # Create a new point with elevation diff --git a/drone_flightplan/calculate_parameters.py b/drone_flightplan/calculate_parameters.py index 4140cf9..f3b244c 100644 --- a/drone_flightplan/calculate_parameters.py +++ b/drone_flightplan/calculate_parameters.py @@ -1,5 +1,6 @@ import logging import argparse +from drone_flightplan.drone_type import DroneType # Configure logging logging.basicConfig(level=logging.INFO, format="%(message)s") @@ -12,6 +13,7 @@ def calculate_parameters( agl: float, gsd: float = None, image_interval: int = 2, + drone_type: DroneType = DroneType.DJI_MINI_4_PRO, ): """ Parameters @@ -34,11 +36,11 @@ def calculate_parameters( ground speed = forward spacing / image interval = 10 """ - - # Constants ( For DJI Mini 4 Pro) - VERTICAL_FOV = 0.71 - HORIZONTAL_FOV = 1.26 - GSD_to_AGL_CONST = 29.7 + # Get the drone specifications from the Enum + drone_specs = drone_type.value + VERTICAL_FOV = drone_specs["VERTICAL_FOV"] + HORIZONTAL_FOV = drone_specs["HORIZONTAL_FOV"] + GSD_to_AGL_CONST = drone_specs["GSD_to_AGL_CONST"] if gsd: agl = gsd * GSD_to_AGL_CONST @@ -52,13 +54,13 @@ def calculate_parameters( side_spacing = side_photo_width - side_overlap_distance ground_speed = forward_spacing / image_interval - # Cap ground speed at 11.5 m/s to avoid problems with the DJI Mini 4 Pro controller. - # Speeds over 12 m/s cause the controller to change the speed to 2.5 m/s, which is too slow. + # Cap ground speed at 11.5 m/s to avoid problems with the DJI Mini 4 Pro controller. + # Speeds over 12 m/s cause the controller to change the speed to 2.5 m/s, which is too slow. # Keeping it below 12 m/s ensures the flight plan works correctly. - + if ground_speed > 12: ground_speed = 11.5 - + return { "forward_photo_height": round(forward_photo_height, 0), "side_photo_width": round(side_photo_width, 0), @@ -114,6 +116,7 @@ def main(): args.altitude_above_ground_level, args.gsd, args.image_interval, + args.drone_type, ) for key, value in results.items(): diff --git a/drone_flightplan/create_flightplan.py b/drone_flightplan/create_flightplan.py index 6f59ad9..3b69b65 100644 --- a/drone_flightplan/create_flightplan.py +++ b/drone_flightplan/create_flightplan.py @@ -8,6 +8,7 @@ from drone_flightplan.add_elevation_from_dem import add_elevation_from_dem from drone_flightplan.create_placemarks import create_placemarks from drone_flightplan.wpml import create_wpml +from drone_flightplan.drone_type import DroneType # Instantiate logger log = logging.getLogger(__name__) @@ -40,7 +41,12 @@ def create_flightplan( """ parameters = calculate_parameters( - forward_overlap, side_overlap, agl, gsd, image_interval + forward_overlap, + side_overlap, + agl, + gsd, + image_interval, + drone_type=DroneType.DJI_MINI_4_PRO, ) waypoints = create_waypoint( diff --git a/drone_flightplan/drone_type.py b/drone_flightplan/drone_type.py new file mode 100644 index 0000000..c26cbc8 --- /dev/null +++ b/drone_flightplan/drone_type.py @@ -0,0 +1,27 @@ +from enum import Enum + +class DroneType(int, Enum): + DJI_MINI_4_PRO = { + # Constants (For DJI Mini 4 Pro) + "VERTICAL_FOV": 0.71, + "HORIZONTAL_FOV": 1.26, + "GSD_to_AGL_CONST": 29.7, + } + + DJI_AIR_3 = { + # Constants (For DJI Air 3) + # Vertical Field of View (FOV): + # Formula: Vertical FOV = 2 * tan^(-1)(sensor height / 2 * focal length) + # The vertical FOV for DJI Air 3 is calculated as: 2 * tan^(-1)(6.3 / (2 * 19.4)) ≈ 0.3224 radians + "VERTICAL_FOV": 0.3224, + + # Horizontal Field of View (FOV): + # Formula: Horizontal FOV = 2 * tan^(-1)(sensor width / 2 * focal length) + # The horizontal FOV for DJI Air 3 is calculated as: 2 * tan^(-1)(8.4 / (2 * 19.4)) ≈ 0.4269 radians + "HORIZONTAL_FOV": 0.4269, + + # Ground Sampling Distance constant (GSD to AGL constant): + # GSD = (sensor height / focal length) * AGL + # This constant helps in determining the ground resolution per pixel at a given altitude (AGL). + "GSD_to_AGL_CONST": 30.5, + } diff --git a/drone_flightplan/waypoints.py b/drone_flightplan/waypoints.py index d02ddb8..fae12e8 100644 --- a/drone_flightplan/waypoints.py +++ b/drone_flightplan/waypoints.py @@ -1,6 +1,7 @@ import logging import argparse from math import sqrt +from drone_flightplan.drone_type import DroneType import pyproj import geojson from shapely.geometry import Point, shape, Polygon @@ -297,7 +298,9 @@ def create_waypoint( } """ - parameters = cp(forward_overlap, side_overlap, agl, gsd) + parameters = cp( + forward_overlap, side_overlap, agl, gsd, drone_type=DroneType.DJI_MINI_4_PRO + ) side_spacing = parameters["side_spacing"] forward_spacing = parameters["forward_spacing"] From 6696a5d907ad843533ac2c6d5f519938c114116d Mon Sep 17 00:00:00 2001 From: Niraj Adhikari Date: Tue, 24 Dec 2024 10:32:17 +0545 Subject: [PATCH 2/5] code formatted --- drone_flightplan/terrain_following_waylines.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drone_flightplan/terrain_following_waylines.py b/drone_flightplan/terrain_following_waylines.py index 16c37c3..59825ec 100755 --- a/drone_flightplan/terrain_following_waylines.py +++ b/drone_flightplan/terrain_following_waylines.py @@ -319,4 +319,4 @@ def waypoints2waylines(injson, threshold): outgeojson = waypoints2waylines(injson, a.threshold) with open(a.outfile, "w") as output_file: - json.dump(outgeojson, output_file) + json.dump(outgeojson, output_file) \ No newline at end of file From 7c09b0499c49c41646366cf3680e9b90cfea2985 Mon Sep 17 00:00:00 2001 From: Pradip-p Date: Tue, 24 Dec 2024 15:17:24 +0545 Subject: [PATCH 3/5] fix: update the argparse arguments to get the drone type --- drone_flightplan/create_flightplan.py | 16 +++++++++++++--- drone_flightplan/waypoints.py | 1 + 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/drone_flightplan/create_flightplan.py b/drone_flightplan/create_flightplan.py index 3b69b65..69c4c2f 100644 --- a/drone_flightplan/create_flightplan.py +++ b/drone_flightplan/create_flightplan.py @@ -25,7 +25,9 @@ def create_flightplan( outfile: str = None, generate_each_points: bool = False, rotation_angle: float = 0.0, - take_off_point: list[float] = None, + take_off_point: list[float] = None, + drone_type: DroneType = DroneType.DJI_MINI_4_PRO, + ): """ Arguments: @@ -46,7 +48,7 @@ def create_flightplan( agl, gsd, image_interval, - drone_type=DroneType.DJI_MINI_4_PRO, + drone_type=drone_type, ) waypoints = create_waypoint( @@ -58,6 +60,7 @@ def create_flightplan( rotation_angle, generate_each_points, take_off_point=take_off_point, + drone_type=drone_type, ) # Add elevation data to the waypoints @@ -115,7 +118,14 @@ def main(): type=float, help="The ground sampling distance in cm/px.", ) - + + parser.add_argument( + "--drone_type", + type=lambda dt: DroneType[dt.upper()], + default=DroneType.DJI_MINI_4_PRO, + help="The type of drone to use, e.g., DJI_MINI_4_PRO.", + ) + parser.add_argument( "--forward_overlap", type=float, diff --git a/drone_flightplan/waypoints.py b/drone_flightplan/waypoints.py index fae12e8..20737a9 100644 --- a/drone_flightplan/waypoints.py +++ b/drone_flightplan/waypoints.py @@ -257,6 +257,7 @@ def create_waypoint( no_fly_zones: dict = None, take_off_point: list[float] = None, mode: str = "waylines", + drone_type= DroneType.DJI_MINI_4_PRO, ) -> str: """ Create waypoints or waylines for a given project area based on specified parameters. From 3a2c626511d7944344f21117602d49b89a30e229 Mon Sep 17 00:00:00 2001 From: Pradip-p Date: Tue, 24 Dec 2024 15:18:56 +0545 Subject: [PATCH 4/5] fix: added missing drone type as arg --- drone_flightplan/create_flightplan.py | 1 + 1 file changed, 1 insertion(+) diff --git a/drone_flightplan/create_flightplan.py b/drone_flightplan/create_flightplan.py index 69c4c2f..e4a21f9 100644 --- a/drone_flightplan/create_flightplan.py +++ b/drone_flightplan/create_flightplan.py @@ -182,6 +182,7 @@ def main(): args.generate_each_points, args.rotation_angle, args.take_off_point, + args.drone_type, ) From 6e181c31ceaa1453b6fc0f796a3a3887552fa9c2 Mon Sep 17 00:00:00 2001 From: Pradip-p Date: Tue, 24 Dec 2024 15:53:16 +0545 Subject: [PATCH 5/5] fix: changes drone_types dynamically in create waypoints --- drone_flightplan/waypoints.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drone_flightplan/waypoints.py b/drone_flightplan/waypoints.py index 20737a9..193c906 100644 --- a/drone_flightplan/waypoints.py +++ b/drone_flightplan/waypoints.py @@ -300,7 +300,7 @@ def create_waypoint( """ parameters = cp( - forward_overlap, side_overlap, agl, gsd, drone_type=DroneType.DJI_MINI_4_PRO + forward_overlap, side_overlap, agl, gsd, drone_type=drone_type ) side_spacing = parameters["side_spacing"] forward_spacing = parameters["forward_spacing"]