Skip to content

Commit

Permalink
Add files via upload
Browse files Browse the repository at this point in the history
  • Loading branch information
SohamD1 authored Sep 24, 2024
1 parent 96bc51a commit baa426f
Show file tree
Hide file tree
Showing 3 changed files with 328 additions and 0 deletions.
94 changes: 94 additions & 0 deletions decision_simple_waypoint.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
"""
BOOTCAMPERS TO COMPLETE.
Travel to designated waypoint.
"""

from .. import commands
from .. import drone_report

# Disable for bootcamp use
# pylint: disable-next=unused-import
from .. import drone_status
from .. import location
from ..private.decision import base_decision


# Disable for bootcamp use
# No enable
# pylint: disable=duplicate-code,unused-argument


class DecisionSimpleWaypoint(base_decision.BaseDecision):
"""
Travel to the designed waypoint.
"""

def __init__(self, waypoint: location.Location, acceptance_radius: float) -> None:
"""
Initialize all persistent variables here with self.
"""
self.waypoint = waypoint
print(f"Waypoint: {waypoint}")

self.acceptance_radius = acceptance_radius

# ============
# ↓ BOOTCAMPERS MODIFY BELOW THIS COMMENT ↓
# ============

self.waypoint_found =False
self.landing_pad_found = False


# ============
# ↑ BOOTCAMPERS MODIFY ABOVE THIS COMMENT ↑
# ============

def run(
self, report: drone_report.DroneReport, landing_pad_locations: "list[location.Location]"
) -> commands.Command:
"""
Make the drone fly to the waypoint.
You are allowed to create as many helper methods as you want,
as long as you do not change the __init__() and run() signatures.
This method will be called in an infinite loop, something like this:
```py
while True:
report, landing_pad_locations = get_input()
command = Decision.run(report, landing_pad_locations)
put_output(command)
```
"""
# Default command
command = commands.Command.create_null_command()

# ============
# ↓ BOOTCAMPERS MODIFY BELOW THIS COMMENT ↓
# ============

status = report.status
current_position = report.position
waypoint = self.waypoint

destination_x = waypoint.location_x - current_position.location_x
destination_y = waypoint.location_y - current_position.location_y
distance_squared = destination_x**2 + destination_y**2

if status == drone_status.DroneStatus.HALTED:
if distance_squared < self.acceptance_radius**2:
command = commands.Command.create_land_command()
print("The drone is within the accepted range")
else: command = commands.Command.create_set_relative_destination_command(
destination_x, destination_y
)
print(f"Moving to waypoint{waypoint.location_x},{waypoint.location_y}")

# ============
# ↑ BOOTCAMPERS MODIFY ABOVE THIS COMMENT ↑
# ============

return command
97 changes: 97 additions & 0 deletions decision_waypoint_landing_pads.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
"""
BOOTCAMPERS TO COMPLETE.
Travel to designated waypoint and then land at a nearby landing pad.
"""

from .. import commands
from .. import drone_report

# Disable for bootcamp use
# pylint: disable-next=unused-import
from .. import drone_status
from .. import location
from ..private.decision import base_decision


# Disable for bootcamp use
# No enable
# pylint: disable=duplicate-code,unused-argument


class DecisionWaypointLandingPads(base_decision.BaseDecision):
"""
Travel to the designed waypoint and then land at the nearest landing pad.
"""

def __init__(self, waypoint: location.Location, acceptance_radius: float) -> None:
"""
Initialize all persistent variables here with self.
"""
self.waypoint = waypoint
print(f"Waypoint: {waypoint}")

self.acceptance_radius = acceptance_radius

# ============
# ↓ BOOTCAMPERS MODIFY BELOW THIS COMMENT ↓
# ============

print(str(waypoint.location_x)+str(waypoint.location_y))

self.has_sent_landing_command = False

self.find_nearest_landing_pad = False

self.reached_waypoint = False

self.moving_to_landing_pad = False

self.counter = 0

def at_point(self, current_x: float, current_y: float):


distance_squared = (self.waypoint.location_x - current_x) ** 2 + (
self.waypoint.location_y - current_y
) ** 2
return distance_squared <= self.acceptance_radius ** 2



# ============
# ↑ BOOTCAMPERS MODIFY ABOVE THIS COMMENT ↑
# ============

def run(
self, report: drone_report.DroneReport, landing_pad_locations: "list[location.Location]"
) -> commands.Command:
"""
Make the drone fly to the waypoint and then land at the nearest landing pad.
You are allowed to create as many helper methods as you want,
as long as you do not change the __init__() and run() signatures.
This method will be called in an infinite loop, something like this:
```py
while True:
report, landing_pad_locations = get_input()
command = Decision.run(report, landing_pad_locations)
put_output(command)
```
"""
# Default command
command = commands.Command.create_null_command()

# ============
# ↓ BOOTCAMPERS MODIFY BELOW THIS COMMENT ↓
# ============

# Do something based on the report and the state of this class...

# ============
# ↑ BOOTCAMPERS MODIFY ABOVE THIS COMMENT ↑
# ============

return command
137 changes: 137 additions & 0 deletions detect_landing_pad.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
"""
BOOTCAMPERS TO COMPLETE.
Detects landing pads.
"""

import pathlib

import numpy as np
import torch
import ultralytics

from .. import bounding_box


# ============
# ↓ 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 ↑
# ============


class DetectLandingPad:
"""
Contains the YOLOv8 model for prediction.
"""

__create_key = object()

# ============
# ↓ BOOTCAMPERS MODIFY BELOW THIS COMMENT ↓
# ============

# Chooses the GPU if it exists, otherwise runs on the CPU
# If you have a CUDA capable GPU but want to force it to
# run on the CPU instead, replace the right side with "cpu"
__DEVICE = 0 if torch.cuda.is_available() else "cpu"

# ============
# ↑ BOOTCAMPERS MODIFY ABOVE THIS COMMENT ↑
# ============

__MODEL_NAME = "best-2n.pt"

@classmethod
def create(cls, model_directory: pathlib.Path) -> "tuple[bool, DetectLandingPad | None]":
"""
model_directory: Directory to models.
"""
if not model_directory.is_dir():
return False, None

model_path = pathlib.PurePosixPath(
model_directory,
cls.__MODEL_NAME,
)

try:
model = ultralytics.YOLO(str(model_path))
# Library can throw any exception
# pylint: disable-next=broad-exception-caught
except Exception:
return False, None

return True, DetectLandingPad(cls.__create_key, model)

def __init__(self, class_private_create_key: object, model: ultralytics.YOLO) -> None:
"""
Private constructor, use create() method.
"""
assert class_private_create_key is DetectLandingPad.__create_key, "Use create() method"

self.__model = model

def run(self, image: np.ndarray) -> "tuple[list[bounding_box.BoundingBox], np.ndarray]":
"""
Converts an image into a list of bounding boxes.
image: The image to run on.
Return: A tuple of (list of bounding boxes, annotated image) .
The list of bounding boxes can be empty.
"""
# ============
# ↓ BOOTCAMPERS MODIFY BELOW THIS COMMENT ↓
# ============

# Ultralytics has documentation and examples

# Use the model's predict() method to run inference
# Parameters of interest:
# * source
# * conf
# * device
# * verbose
# conf threshold is around 0.7
predictions = self.__model.predict(
source=image, conf=0.7, device=self.__DEVICE, verbose =False
)

# Get the Result object
prediction = predictions[0]

# Plot the annotated image from the Result object
# Include the confidence value
image_annotated = prediction.plot(boxes=True, conf=True)

# Get the xyxy boxes list from the Boxes object in the Result object
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_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 boxes_xyxy in boxes_cpu:
success, box = bounding_box.BoundingBox.create(boxes_xyxy)
if not success:
continue

return [], image_annotated


# ============
# ↑ BOOTCAMPERS MODIFY ABOVE THIS COMMENT ↑
# ============

0 comments on commit baa426f

Please sign in to comment.