From 6d5173bfa9a8ce5f92a9eb333e746cecf58eb736 Mon Sep 17 00:00:00 2001 From: Emily Qi Date: Wed, 1 Jan 2025 13:08:26 -0500 Subject: [PATCH 1/3] tasks 1, 2, 3, 4 --- modules/bootcamp/decision_simple_waypoint.py | 28 ++++++++- .../decision_waypoint_landing_pads.py | 59 ++++++++++++++++++- modules/bootcamp/detect_landing_pad.py | 26 ++++---- .../bootcamp/tests/run_decision_example.py | 2 +- .../run_decision_waypoint_landing_pads.py | 2 +- 5 files changed, 102 insertions(+), 15 deletions(-) diff --git a/modules/bootcamp/decision_simple_waypoint.py b/modules/bootcamp/decision_simple_waypoint.py index 26098c2e..db80f8f9 100644 --- a/modules/bootcamp/decision_simple_waypoint.py +++ b/modules/bootcamp/decision_simple_waypoint.py @@ -37,7 +37,9 @@ def __init__(self, waypoint: location.Location, acceptance_radius: float) -> Non # ↓ BOOTCAMPERS MODIFY BELOW THIS COMMENT ↓ # ============ - # Add your own + self.has_sent_landing_command = False + self.min_flight_boundary = -60 + self.max_flight_boundary = 60 # ============ # ↑ BOOTCAMPERS MODIFY ABOVE THIS COMMENT ↑ @@ -70,6 +72,30 @@ def run( # Do something based on the report and the state of this class... + if ( + self.waypoint.location_x >= self.min_flight_boundary + and self.waypoint.location_x <= self.max_flight_boundary + and self.waypoint.location_y >= self.min_flight_boundary + and self.waypoint.location_y <= self.max_flight_boundary + ): + distance_from_waypoint = ( + self.waypoint.location_x - report.position.location_x + ) ** 2 + (self.waypoint.location_y - report.position.location_y) ** 2 + + if ( + report.status == drone_status.DroneStatus.HALTED + and not self.has_sent_landing_command + ): + + if distance_from_waypoint <= self.acceptance_radius**2: + command = commands.Command.create_land_command() + self.has_sent_landing_command = True + + elif distance_from_waypoint > self.acceptance_radius**2: + command = commands.Command.create_set_relative_destination_command( + self.waypoint.location_x, self.waypoint.location_y + ) + # ============ # ↑ BOOTCAMPERS MODIFY ABOVE THIS COMMENT ↑ # ============ diff --git a/modules/bootcamp/decision_waypoint_landing_pads.py b/modules/bootcamp/decision_waypoint_landing_pads.py index ade6f118..6a783a25 100644 --- a/modules/bootcamp/decision_waypoint_landing_pads.py +++ b/modules/bootcamp/decision_waypoint_landing_pads.py @@ -37,12 +37,25 @@ def __init__(self, waypoint: location.Location, acceptance_radius: float) -> Non # ↓ BOOTCAMPERS MODIFY BELOW THIS COMMENT ↓ # ============ - # Add your own + self.has_sent_landing_command = False + self.min_flight_boundary = -60 + self.max_flight_boundary = 60 + + self.ready_to_land = False # ============ # ↑ BOOTCAMPERS MODIFY ABOVE THIS COMMENT ↑ # ============ + def distance_between_locations(self, other_location: location.Location) -> float: + """ + Calculate the squared distance between two Location objects + """ + + return (self.waypoint.location_x - other_location.location_x) ** 2 + ( + self.waypoint.location_y - other_location.location_y + ) ** 2 + def run( self, report: drone_report.DroneReport, landing_pad_locations: "list[location.Location]" ) -> commands.Command: @@ -70,6 +83,50 @@ def run( # Do something based on the report and the state of this class... + if ( + self.waypoint.location_x >= self.min_flight_boundary + and self.waypoint.location_x <= self.max_flight_boundary + and self.waypoint.location_y >= self.min_flight_boundary + and self.waypoint.location_y <= self.max_flight_boundary + ): + distance_from_waypoint = ( + self.waypoint.location_x - report.position.location_x + ) ** 2 + (self.waypoint.location_y - report.position.location_y) ** 2 + + if report.status == drone_status.DroneStatus.HALTED: + + if self.ready_to_land: + command = commands.Command.create_land_command() + self.has_sent_landing_command = True + + elif ( + distance_from_waypoint <= self.acceptance_radius**2 + and not self.has_sent_landing_command + ): + smallest_distance = 999999999 + smallest_distance_x = 0 + smallest_distance_y = 0 + + for landing_pad in landing_pad_locations: + if self.distance_between_locations(landing_pad) < smallest_distance: + smallest_distance = self.distance_between_locations(landing_pad) + smallest_distance_x = landing_pad.location_x - self.waypoint.location_x + smallest_distance_y = landing_pad.location_y - self.waypoint.location_y + + command = commands.Command.create_set_relative_destination_command( + smallest_distance_x, smallest_distance_y + ) + + self.ready_to_land = True + + elif ( + distance_from_waypoint > self.acceptance_radius**2 + and not self.has_sent_landing_command + ): + command = commands.Command.create_set_relative_destination_command( + self.waypoint.location_x, self.waypoint.location_y + ) + # ============ # ↑ BOOTCAMPERS MODIFY ABOVE THIS COMMENT ↑ # ============ diff --git a/modules/bootcamp/detect_landing_pad.py b/modules/bootcamp/detect_landing_pad.py index f17aa677..397e6537 100644 --- a/modules/bootcamp/detect_landing_pad.py +++ b/modules/bootcamp/detect_landing_pad.py @@ -17,9 +17,7 @@ # ↓ BOOTCAMPERS MODIFY BELOW THIS COMMENT ↓ # ============ # Bootcampers remove the following lines: -# Allow linters and formatters to pass for bootcamp maintainers -# No enable -# pylint: disable=unused-argument,unused-private-member,unused-variable + # ============ # ↑ BOOTCAMPERS MODIFY ABOVE THIS COMMENT ↑ # ============ @@ -98,31 +96,37 @@ def run(self, image: np.ndarray) -> "tuple[list[bounding_box.BoundingBox], np.nd # * conf # * device # * verbose - predictions = ... + predictions = self.__model.predict(image, conf=0.7, device=self.__DEVICE, verbose=False) # Get the Result object - prediction = ... + prediction = predictions[0] # Plot the annotated image from the Result object # Include the confidence value - image_annotated = ... + image_annotated = prediction.plot() # Get the xyxy boxes list from the Boxes object in the Result object - boxes_xyxy = ... + boxes_xyxy = prediction.boxes.xyxy # Detach the xyxy boxes to make a copy, # move the copy into CPU space, # and convert to a numpy array - boxes_cpu = ... + boxes_cpu = boxes_xyxy.detach().cpu().numpy() # Loop over the boxes list and create a list of bounding boxes bounding_boxes = [] + # Hint: .shape gets the dimensions of the numpy array # for i in range(0, ...): - # # Create BoundingBox object and append to list - # result, box = ... + for i in range(0, np.shape(boxes_cpu)[0]): + + # Create BoundingBox object and append to list + (result, box) = bounding_box.BoundingBox.create(boxes_cpu[i]) + + if result: + bounding_boxes.append(box) - return [], image_annotated + return bounding_boxes, image_annotated # ============ # ↑ BOOTCAMPERS MODIFY ABOVE THIS COMMENT ↑ # ============ diff --git a/modules/bootcamp/tests/run_decision_example.py b/modules/bootcamp/tests/run_decision_example.py index 7bf681ba..7a9d425e 100644 --- a/modules/bootcamp/tests/run_decision_example.py +++ b/modules/bootcamp/tests/run_decision_example.py @@ -21,7 +21,7 @@ # to reach the 1st command # Increase the step size if your computer is lagging # Larger step size is smaller FPS -TIME_STEP_SIZE = 0.1 # seconds +TIME_STEP_SIZE = 0.4 # seconds # OpenCV ignores your display settings, # so if the window is too small or too large, diff --git a/modules/bootcamp/tests/run_decision_waypoint_landing_pads.py b/modules/bootcamp/tests/run_decision_waypoint_landing_pads.py index c08a2877..d871cbb5 100644 --- a/modules/bootcamp/tests/run_decision_waypoint_landing_pads.py +++ b/modules/bootcamp/tests/run_decision_waypoint_landing_pads.py @@ -21,7 +21,7 @@ # to reach the 1st command # Increase the step size if your computer is lagging # Larger step size is smaller FPS -TIME_STEP_SIZE = 0.1 # seconds +TIME_STEP_SIZE = 0.4 # seconds # OpenCV ignores your display settings, # so if the window is too small or too large, From 2ff5bddbd7cfcb7c98f28fa67680c048f4462601 Mon Sep 17 00:00:00 2001 From: Emily Qi Date: Mon, 6 Jan 2025 14:58:31 -0500 Subject: [PATCH 2/3] task fixes --- modules/bootcamp/decision_simple_waypoint.py | 11 ++----- .../decision_waypoint_landing_pads.py | 29 +++++++------------ modules/bootcamp/detect_landing_pad.py | 3 ++ 3 files changed, 16 insertions(+), 27 deletions(-) diff --git a/modules/bootcamp/decision_simple_waypoint.py b/modules/bootcamp/decision_simple_waypoint.py index db80f8f9..9b747838 100644 --- a/modules/bootcamp/decision_simple_waypoint.py +++ b/modules/bootcamp/decision_simple_waypoint.py @@ -37,7 +37,6 @@ def __init__(self, waypoint: location.Location, acceptance_radius: float) -> Non # ↓ BOOTCAMPERS MODIFY BELOW THIS COMMENT ↓ # ============ - self.has_sent_landing_command = False self.min_flight_boundary = -60 self.max_flight_boundary = 60 @@ -82,16 +81,12 @@ def run( self.waypoint.location_x - report.position.location_x ) ** 2 + (self.waypoint.location_y - report.position.location_y) ** 2 - if ( - report.status == drone_status.DroneStatus.HALTED - and not self.has_sent_landing_command - ): + if report.status == drone_status.DroneStatus.HALTED: - if distance_from_waypoint <= self.acceptance_radius**2: + if distance_from_waypoint < self.acceptance_radius**2: command = commands.Command.create_land_command() - self.has_sent_landing_command = True - elif distance_from_waypoint > self.acceptance_radius**2: + else: command = commands.Command.create_set_relative_destination_command( self.waypoint.location_x, self.waypoint.location_y ) diff --git a/modules/bootcamp/decision_waypoint_landing_pads.py b/modules/bootcamp/decision_waypoint_landing_pads.py index 6a783a25..5ed7a3b7 100644 --- a/modules/bootcamp/decision_waypoint_landing_pads.py +++ b/modules/bootcamp/decision_waypoint_landing_pads.py @@ -37,7 +37,6 @@ def __init__(self, waypoint: location.Location, acceptance_radius: float) -> Non # ↓ BOOTCAMPERS MODIFY BELOW THIS COMMENT ↓ # ============ - self.has_sent_landing_command = False self.min_flight_boundary = -60 self.max_flight_boundary = 60 @@ -47,7 +46,7 @@ def __init__(self, waypoint: location.Location, acceptance_radius: float) -> Non # ↑ BOOTCAMPERS MODIFY ABOVE THIS COMMENT ↑ # ============ - def distance_between_locations(self, other_location: location.Location) -> float: + def squared_distance(self, other_location: location.Location) -> float: """ Calculate the squared distance between two Location objects """ @@ -97,32 +96,24 @@ def run( if self.ready_to_land: command = commands.Command.create_land_command() - self.has_sent_landing_command = True - elif ( - distance_from_waypoint <= self.acceptance_radius**2 - and not self.has_sent_landing_command - ): - smallest_distance = 999999999 - smallest_distance_x = 0 - smallest_distance_y = 0 + elif distance_from_waypoint < self.acceptance_radius**2: + smallest_distance = float("inf") + smallest_distance_pad = None for landing_pad in landing_pad_locations: - if self.distance_between_locations(landing_pad) < smallest_distance: - smallest_distance = self.distance_between_locations(landing_pad) - smallest_distance_x = landing_pad.location_x - self.waypoint.location_x - smallest_distance_y = landing_pad.location_y - self.waypoint.location_y + if self.squared_distance(landing_pad) < smallest_distance: + smallest_distance = self.squared_distance(landing_pad) + smallest_distance_pad = landing_pad command = commands.Command.create_set_relative_destination_command( - smallest_distance_x, smallest_distance_y + (smallest_distance_pad.location_x - self.waypoint.location_x), + (smallest_distance_pad.location_y - self.waypoint.location_y), ) self.ready_to_land = True - elif ( - distance_from_waypoint > self.acceptance_radius**2 - and not self.has_sent_landing_command - ): + else: command = commands.Command.create_set_relative_destination_command( self.waypoint.location_x, self.waypoint.location_y ) diff --git a/modules/bootcamp/detect_landing_pad.py b/modules/bootcamp/detect_landing_pad.py index 397e6537..416e6b87 100644 --- a/modules/bootcamp/detect_landing_pad.py +++ b/modules/bootcamp/detect_landing_pad.py @@ -125,8 +125,11 @@ def run(self, image: np.ndarray) -> "tuple[list[bounding_box.BoundingBox], np.nd if result: bounding_boxes.append(box) + else: + return [], image_annotated return bounding_boxes, image_annotated + # ============ # ↑ BOOTCAMPERS MODIFY ABOVE THIS COMMENT ↑ # ============ From 3a10adf36aa7d4a7ecf5e6889d6ea619b07378fe Mon Sep 17 00:00:00 2001 From: Emily Qi Date: Mon, 6 Jan 2025 15:58:59 -0500 Subject: [PATCH 3/3] task4 --- .../bootcamp/decision_waypoint_landing_pads.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/modules/bootcamp/decision_waypoint_landing_pads.py b/modules/bootcamp/decision_waypoint_landing_pads.py index 5ed7a3b7..d8d9f8fa 100644 --- a/modules/bootcamp/decision_waypoint_landing_pads.py +++ b/modules/bootcamp/decision_waypoint_landing_pads.py @@ -88,9 +88,7 @@ def run( and self.waypoint.location_y >= self.min_flight_boundary and self.waypoint.location_y <= self.max_flight_boundary ): - distance_from_waypoint = ( - self.waypoint.location_x - report.position.location_x - ) ** 2 + (self.waypoint.location_y - report.position.location_y) ** 2 + distance_from_waypoint = self.squared_distance(report.position) if report.status == drone_status.DroneStatus.HALTED: @@ -106,10 +104,13 @@ def run( smallest_distance = self.squared_distance(landing_pad) smallest_distance_pad = landing_pad - command = commands.Command.create_set_relative_destination_command( - (smallest_distance_pad.location_x - self.waypoint.location_x), - (smallest_distance_pad.location_y - self.waypoint.location_y), - ) + if smallest_distance_pad is None: + command = commands.Command.create_null_command() + else: + command = commands.Command.create_set_relative_destination_command( + (smallest_distance_pad.location_x - self.waypoint.location_x), + (smallest_distance_pad.location_y - self.waypoint.location_y), + ) self.ready_to_land = True