Skip to content
This repository was archived by the owner on Sep 21, 2025. It is now read-only.
Open
Show file tree
Hide file tree
Changes from 5 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
29 changes: 26 additions & 3 deletions modules/bootcamp/decision_simple_waypoint.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,12 @@
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):
Expand All @@ -39,6 +36,10 @@ def __init__(self, waypoint: location.Location, acceptance_radius: float) -> Non

# Add your own

self.has_sent_landing_command = False
self.min_bounds = -60
self.max_bounds = 60

# ============
# ↑ BOOTCAMPERS MODIFY ABOVE THIS COMMENT ↑
# ============
Expand Down Expand Up @@ -69,6 +70,28 @@ def run(
# ============

# Do something based on the report and the state of this class...
# ensuring drone is within bounds
if (
self.waypoint.location_x >= self.min_bounds
and self.waypoint.location_x <= self.max_bounds
and self.waypoint.location_y >= self.min_bounds
and self.waypoint.location_y <= self.max_bounds
):
# when the drone is halted but not at the destination
if (
report.status == drone_status.DroneStatus.HALTED
and report.destination != self.waypoint
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than using direct equality comparison of floating point numbers (which are not very accurate and may not give you the result you want), you should use the self.acceptance_radius as a guide.

):
command = commands.Command.create_set_relative_destination_command(
self.waypoint.location_x, self.waypoint.location_y
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a relative distance command, so your own position matters

)
# when the drone is at the destination and is halted
if (
report.status == drone_status.DroneStatus.HALTED
and report.destination == self.waypoint
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, use acceptance radius rather than equality

):
command = commands.Command.create_land_command()
self.has_sent_landing_command = True

# ============
# ↑ BOOTCAMPERS MODIFY ABOVE THIS COMMENT ↑
Expand Down
50 changes: 47 additions & 3 deletions modules/bootcamp/decision_waypoint_landing_pads.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,12 @@
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):
Expand All @@ -38,11 +35,21 @@ def __init__(self, waypoint: location.Location, acceptance_radius: float) -> Non
# ============

# Add your own
self.has_sent_landing_command = False
self.min_bounds = -60
self.max_bounds = 60

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

def min_dist_squared(self, landing_pads: location.Location) -> float:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should rename your function and its parameters to match the description better. But good job including a doc string!

"""returns distance squared"""
dist = (self.waypoint.location_x - landing_pads.location_x) ** 2 + (
self.waypoint.location_y - landing_pads.location_y
) ** 2
return dist

def run(
self, report: drone_report.DroneReport, landing_pad_locations: "list[location.Location]"
) -> commands.Command:
Expand All @@ -69,6 +76,43 @@ def run(
# ============

# Do something based on the report and the state of this class...
if (
self.waypoint.location_x >= self.min_bounds
and self.waypoint.location_x <= self.max_bounds
and self.waypoint.location_y >= self.min_bounds
and self.waypoint.location_y <= self.max_bounds
):
proximity = (self.waypoint.location_x - report.position.location_x) ** 2 + (
self.waypoint.location_y - report.position.location_y
) ** 2
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You have a function for calculating distances, you can use it!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, you are constantly calculating the distance to the waypoint, which is probably not necessary all the time, such as after you reached the waypoint

new_pad = location.Location(0, 0)
# checking if the drone is halted
if report.status == drone_status.DroneStatus.HALTED:

# when drone is at the nearest landing pad
if self.has_sent_landing_command:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename this variable to something else, as it feels awkward to send a land command after "has_sent_landing_command" is true. Code readability and communication is also important!

command = commands.Command.create_land_command()

# finding nearest landing pad and setting relative destination
elif not self.has_sent_landing_command and proximity < self.acceptance_radius**2:
smallest_dist = float("inf")
for landing_pads in landing_pad_locations:
new_dist = self.min_dist_squared(landing_pads)
if new_dist < smallest_dist:
smallest_dist = new_dist
new_pad = landing_pads

command = commands.Command.create_set_relative_destination_command(
new_pad.location_x - self.waypoint.location_x,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be your own position: if your drone stopped midway to the waypoint, it would overshoot the landing pad by a lot

new_pad.location_y - self.waypoint.location_y,
)
self.has_sent_landing_command = True

# setting relative destination to designated waypoint
elif proximity > self.acceptance_radius and not self.has_sent_landing_command:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

distance squared

command = commands.Command.create_set_relative_destination_command(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do you know that you should go to the waypoint and not the landing pad? What if you were en route towards the landing pad?

self.waypoint.location_x, self.waypoint.location_y
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Relative distance command, your own position matters

)

# ============
# ↑ BOOTCAMPERS MODIFY ABOVE THIS COMMENT ↑
Expand Down
29 changes: 19 additions & 10 deletions modules/bootcamp/detect_landing_pad.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 ↑
# ============
Expand Down Expand Up @@ -98,31 +96,42 @@ def run(self, image: np.ndarray) -> "tuple[list[bounding_box.BoundingBox], np.nd
# * conf
# * device
# * verbose
predictions = ...
# model = ultralytics.YOLO("yolov8n.pt")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can delete commented out code since that's what git is for, it keeps track of history for you

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()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please include the confidence value in the image as indicated above, set it using a kwarg like in the predict() method


# 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 = ...
# result, box = ...
# result=0

for i in range(0, np.shape(boxes_cpu)[0]):

(result, box) = bounding_box.BoundingBox.create(boxes_cpu[i])

if result:
bounding_boxes.append(box)
else:
return [], image_annotated

return [], image_annotated
return bounding_boxes, image_annotated
# ============
# ↑ BOOTCAMPERS MODIFY ABOVE THIS COMMENT ↑
# ============
2 changes: 1 addition & 1 deletion modules/bootcamp/tests/run_decision_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 = 4 # seconds

# OpenCV ignores your display settings,
# so if the window is too small or too large,
Expand Down
Binary file added yolov8n.pt
Binary file not shown.
Loading