Skip to content

Commit

Permalink
Add hotspot search path generation
Browse files Browse the repository at this point in the history
  • Loading branch information
siddhp1 committed Nov 22, 2024
1 parent 0868f4f commit 79be8ad
Show file tree
Hide file tree
Showing 2 changed files with 150 additions and 0 deletions.
55 changes: 55 additions & 0 deletions modules/generate_hotspot_search_path.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
"""
Generates search path for hotspots.
"""

import math

from . import plot_circular_path
from .common.modules import position_global_relative_altitude


MINIMUM_POINTS = 3


def generate_search_path(
center: position_global_relative_altitude.PositionGlobalRelativeAltitude,
search_radius: float,
search_area_dimensions: "tuple[float, float]",
) -> "tuple[bool, list[position_global_relative_altitude.PositionGlobalRelativeAltitude] | None]":
"""
Generates list of spline waypoints representing concentric rings for drone search path.
center: waypoint for center of circle.
search_radius: drone search radius.
search_area_dimensions: search area width, height
Returns: Success, list of waypoints.
"""
camera_horizontal_size, camera_vertical_size = search_area_dimensions

if camera_horizontal_size <= 0 or camera_vertical_size <= 0:
print(f"ERROR: Camera dimensions must be greater than 0: {search_area_dimensions}")
return False, None

if search_radius < 0:
print(f"ERROR: Search radius must be greater than or equal to 0: {search_radius}")
return False, None

current_radius = camera_horizontal_size / 2

all_waypoints = []

while current_radius <= search_radius:
circumference = 2 * math.pi * current_radius
num_points = max(MINIMUM_POINTS, int(circumference / camera_vertical_size))

result, waypoints = plot_circular_path.generate_circular_path(
center, current_radius, num_points
)
if not result or waypoints is None:
return False, None
all_waypoints.extend(waypoints)

current_radius += camera_horizontal_size

return True, all_waypoints
95 changes: 95 additions & 0 deletions tests/unit/test_generate_hotspot_search_path.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
"""
Hotspot search path generation unit tests.
"""

import math

from modules import generate_hotspot_search_path
from modules.common.modules import position_global_relative_altitude


class TestGenerateSearchPath:
"""
Test suite for generate_search_path.
"""

def test_generate_search_path(self) -> None:
"""
Test successful generation of search path.
"""
result, center = position_global_relative_altitude.PositionGlobalRelativeAltitude.create(
0.0, 0.0, 100.0
)
search_radius = 100.0
search_area_dimensions = (20.0, 10.0)

result, waypoints = generate_hotspot_search_path.generate_search_path(
center, search_radius, search_area_dimensions
)

assert result
assert waypoints

camera_width, camera_height = search_area_dimensions
current_radius = camera_width / 2
waypoint_index = 0

while current_radius <= search_radius:
circumference = 2 * math.pi * current_radius
num_points = max(3, int(circumference / camera_height))

assert len(waypoints[waypoint_index : waypoint_index + num_points]) == num_points

waypoint_index += num_points
current_radius += camera_width

def test_generate_search_path_zero_radius(self) -> None:
"""
Test generate_search_path with a zero search radius.
"""
result, center = position_global_relative_altitude.PositionGlobalRelativeAltitude.create(
0.0, 0.0, 100.0
)
search_radius = 0.0
search_area_dimensions = (3.0, 3.0)

result, waypoints = generate_hotspot_search_path.generate_search_path(
center, search_radius, search_area_dimensions
)

assert result
assert waypoints == []

def test_generate_search_path_negative_radius(self) -> None:
"""
Test generate_search_path with a negative search radius.
"""
result, center = position_global_relative_altitude.PositionGlobalRelativeAltitude.create(
0.0, 0.0, 100.0
)
search_radius = -10.0
search_area_dimensions = (3.0, 3.0)

result, waypoints = generate_hotspot_search_path.generate_search_path(
center, search_radius, search_area_dimensions
)

assert result is False
assert waypoints is None

def test_generate_search_path_invalid_dimensions(self) -> None:
"""
Test generate_search_path with invalid search area dimensions.
"""
result, center = position_global_relative_altitude.PositionGlobalRelativeAltitude.create(
0.0, 0.0, 100.0
)
search_radius = 10.0
search_area_dimensions = (-3, 3.0)

result, waypoints = generate_hotspot_search_path.generate_search_path(
center, search_radius, search_area_dimensions
)

assert result is False
assert waypoints is None

0 comments on commit 79be8ad

Please sign in to comment.