-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add hotspot search path generation #77
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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 |
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 | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Gonna be tedious... but could you hard code the test numbers? So like actual values that are expected of the path. Doesn't have to be extremely complicated, but enough to gauge performance. You can take a look at |
||
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would go with ceil for this to play it safer. Maybe also add a multiplier, like 1.2 to allow for more wiggle room.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also to error on the side of caution, also check if with
camera_horizontal_size
would yield a higher value.