diff --git a/modules/bootcamp/decision_simple_waypoint.py b/modules/bootcamp/decision_simple_waypoint.py index 26098c2e..6776989d 100644 --- a/modules/bootcamp/decision_simple_waypoint.py +++ b/modules/bootcamp/decision_simple_waypoint.py @@ -37,7 +37,8 @@ def __init__(self, waypoint: location.Location, acceptance_radius: float) -> Non # ↓ BOOTCAMPERS MODIFY BELOW THIS COMMENT ↓ # ============ - # Add your own + # Boolean to check for completion + self.waypoint_reached = False # ============ # ↑ BOOTCAMPERS MODIFY ABOVE THIS COMMENT ↑ @@ -68,7 +69,23 @@ def run( # ↓ BOOTCAMPERS MODIFY BELOW THIS COMMENT ↓ # ============ - # Do something based on the report and the state of this class... + # Check the report to see what the status of the drone is + if report.status == drone_status.DroneStatus.HALTED: + + # First check whether it has gotten to the waypoint + if not self.waypoint_reached: + # Moves towards the waypoint + x_dist = self.waypoint.location_x - report.position.location_x + y_dist = self.waypoint.location_y - report.position.location_y + command = commands.Command.create_set_relative_destination_command(x_dist, y_dist) + + self.waypoint_reached = True + + # Once it has gotten to waypoint, land it + else: + command = commands.Command.create_land_command() + + # raise NotImplementedError # ============ # ↑ 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..49bac0c3 100644 --- a/modules/bootcamp/decision_waypoint_landing_pads.py +++ b/modules/bootcamp/decision_waypoint_landing_pads.py @@ -36,9 +36,8 @@ def __init__(self, waypoint: location.Location, acceptance_radius: float) -> Non # ============ # ↓ BOOTCAMPERS MODIFY BELOW THIS COMMENT ↓ # ============ - - # Add your own - + self.landpad_reached = False + self.waypoint_reached = False # ============ # ↑ BOOTCAMPERS MODIFY ABOVE THIS COMMENT ↑ # ============ @@ -68,10 +67,54 @@ def run( # ↓ BOOTCAMPERS MODIFY BELOW THIS COMMENT ↓ # ============ - # Do something based on the report and the state of this class... + if report.status == drone_status.DroneStatus.HALTED: + + if not self.waypoint_reached: + # Moves towards the waypoint + x_dist = self.waypoint.location_x - report.position.location_x + y_dist = self.waypoint.location_y - report.position.location_y + command = commands.Command.create_set_relative_destination_command(x_dist, y_dist) + + self.waypoint_reached = True + + # Once you get to the waypoint, you have to go to the nearest landpad + elif not self.landpad_reached: + # Find the closest pad and store it in closest_landpad + # This is using the min() method to iterate through each pad, get the distance to it and compare it with others + closest_pad = min( + landing_pad_locations, key=lambda pad: self.get_distance(report.position, pad) + ) + print(f"Closest Landpad: {closest_pad.location_x}, {closest_pad.location_y}") + + # Move to the closest landpad + x_dist = closest_pad.location_x - report.position.location_x + y_dist = closest_pad.location_y - report.position.location_y + # print(f"{x_dist}, {y_dist}") + command = commands.Command.create_set_relative_destination_command(x_dist, y_dist) + + self.landpad_reached = True + + else: + command = commands.Command.create_land_command() + + # raise NotImplementedError + + return command + + # Method used to check distance sqaured between two locations + # We don't need the square root since this is for comparison only + def get_distance(self, loc_1: location.Location, loc_2: location.Location) -> float: + """ + This method is used to get the distance squared between any two locations + + """ + x = loc_1.location_x - loc_2.location_x + y = loc_1.location_y - loc_2.location_y + + # Don't need to square root when comparing between squares + hypotenuse_squared = (x**2) + (y**2) + return hypotenuse_squared # ============ # ↑ BOOTCAMPERS MODIFY ABOVE THIS COMMENT ↑ # ============ - - return command diff --git a/modules/bootcamp/detect_landing_pad.py b/modules/bootcamp/detect_landing_pad.py index f17aa677..098b2de6 100644 --- a/modules/bootcamp/detect_landing_pad.py +++ b/modules/bootcamp/detect_landing_pad.py @@ -16,10 +16,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 +95,41 @@ def run(self, image: np.ndarray) -> "tuple[list[bounding_box.BoundingBox], np.nd # * conf # * device # * verbose - predictions = ... + predictions = self.__model.predict( + source=image, conf=0.7, device=self.__DEVICE, verbose=False + ) # Get the Result object - prediction = ... - + # Only 1 image was used therefore we access the first result in the list + prediction = predictions[0] # Plot the annotated image from the Result object # Include the confidence value - image_annotated = ... + image_annotated = prediction.plot(conf=True, boxes=True) # 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 = [] + # .shape returns a tuple with the 0th index being the number of lists in the numpy array + for i in range(0, boxes_cpu.shape[0]): + # This func returns a tuple, with whether the operation was a sucess (bool) & the bounding box itself + successful, box = bounding_box.BoundingBox.create(bounds=boxes_cpu[i]) + + if successful: + bounding_boxes.append(box) + # Hint: .shape gets the dimensions of the numpy array # for i in range(0, ...): # # Create BoundingBox object and append to list # result, 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..1cab3f7c 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.15 # seconds # OpenCV ignores your display settings, # so if the window is too small or too large, diff --git a/requirements.txt b/requirements.txt index fa1ed662..b89d4e75 100644 --- a/requirements.txt +++ b/requirements.txt @@ -17,7 +17,7 @@ pytest # If you are on MacOS, don't have a CUDA capable GPU, # or if things don't work and you just want to use the CPU, # comment out the "--extra-index-url" option ---extra-index-url https://download.pytorch.org/whl/cu124 +# --extra-index-url https://download.pytorch.org/whl/cu124 # ============ # ↑ BOOTCAMPERS MODIFY ABOVE THIS COMMENT ↑