-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* FOV for vertical frustum * Variable frustum * Fixed trig errors * Parameter for degrees or radians * Fixed factor bug; decimal default values * Search area dimensions unit tests * Fixed linter * Removed dots * Deleted init.py * Deleted more init files * Search area dimensions (#71) * FOV for vertical frustum * Variable frustum * Fixed trig errors * Parameter for degrees or radians * Fixed factor bug; decimal default values * Added back the init files I wasn't supposed to delete * Deleted duplicate
- Loading branch information
1 parent
1e0fb79
commit e51b6d1
Showing
2 changed files
with
163 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
""" | ||
Converts field of view to display dimensions in metres. | ||
""" | ||
|
||
from math import tan, pi | ||
|
||
|
||
# Measurements from https://uwarg-docs.atlassian.net/wiki/spaces/CV/pages/2236613655/200+CV+Camera | ||
FIELD_OF_VISION_X = 0.64889 | ||
FIELD_OF_VISION_Y = 0.41438 | ||
|
||
|
||
def search_area_dimensions( | ||
height: int, | ||
frustum_angle_x: float, | ||
frustum_angle_y: float, | ||
frustum_radians: bool = True, | ||
field_of_vision_x: float = FIELD_OF_VISION_X, | ||
field_of_vision_y: float = FIELD_OF_VISION_Y, | ||
field_of_vision_radians: bool = True, | ||
) -> "tuple[float, float]": | ||
""" | ||
Parameters: | ||
- height: height of the drone, in metres | ||
- frustum_angle_x: the left-right camera direction angle w/ respect to vertical | ||
- frustum_angle_y: the up-down camera direction angle w/ respect to vertical | ||
- frustum_radians: Boolean for whether frustum input is in radians or not | ||
- field_of_vision_x: the horizontal field of vision of the camera, in radians (default to measured constant) | ||
- field_of_vision_y: the vertical field of vision of the camera, in radians (default to measured constant) | ||
- field_of_vision_radians: Boolean for whether field of vision input is in radians or not | ||
Return: | ||
- tuple containing the rectangular dimensions of the field of view of the camera, in metres | ||
""" | ||
frustum_factor = 1 | ||
if not frustum_radians: | ||
frustum_factor = pi / 180 | ||
field_of_vision_factor = 1 | ||
if not field_of_vision_radians: | ||
field_of_vision_factor = pi / 180 | ||
|
||
left_distance = ( | ||
tan((field_of_vision_x * field_of_vision_factor) / 2 - frustum_angle_x * frustum_factor) | ||
* height | ||
) | ||
right_distance = ( | ||
tan((field_of_vision_x * field_of_vision_factor) / 2 + frustum_angle_x * frustum_factor) | ||
* height | ||
) | ||
horizontal_distance = left_distance + right_distance | ||
up_distance = ( | ||
tan((field_of_vision_y * field_of_vision_factor) / 2 - frustum_angle_y * frustum_factor) | ||
* height | ||
) | ||
down_distance = ( | ||
tan((field_of_vision_y * field_of_vision_factor) / 2 + frustum_angle_y * frustum_factor) | ||
* height | ||
) | ||
vertical_distance = up_distance + down_distance | ||
return horizontal_distance, vertical_distance |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
""" | ||
Test cases for the search_area_dimensions module. | ||
""" | ||
|
||
from math import pi, sqrt | ||
|
||
from modules import search_area_dimensions | ||
|
||
# Test functions use test fixture signature names and access class privates | ||
# No enable | ||
# pylint: disable=duplicate-code,protected-access,redefined-outer-name | ||
|
||
THRESHOLD = 1e-6 | ||
|
||
|
||
def test_no_field_of_view() -> None: | ||
""" | ||
Testing 0 degree field of view. | ||
""" | ||
height = 10 | ||
frustum_angle_x = 10 | ||
frustum_angle_y = 20 | ||
field_of_vision_x = 0 | ||
field_of_vision_y = 0 | ||
|
||
x, y = search_area_dimensions.search_area_dimensions( | ||
height, frustum_angle_x, frustum_angle_y, True, field_of_vision_x, field_of_vision_y, True | ||
) | ||
|
||
assert abs(x - 0) < THRESHOLD | ||
assert abs(y - 0) < THRESHOLD | ||
|
||
|
||
def test_vertical_field_of_view() -> None: | ||
""" | ||
Testing straight-down camera angle. | ||
""" | ||
height = 20 | ||
frustum_angle_x = 0 | ||
frustum_angle_y = 0 | ||
field_of_vision_x = pi / 2 | ||
field_of_vision_y = 2 * pi / 3 | ||
|
||
x, y = search_area_dimensions.search_area_dimensions( | ||
height, frustum_angle_x, frustum_angle_y, True, field_of_vision_x, field_of_vision_y, True | ||
) | ||
|
||
assert abs(x - 40) < THRESHOLD | ||
assert abs(y - 40 * sqrt(3)) < THRESHOLD | ||
|
||
|
||
def test_side_vertical_field_of_view() -> None: | ||
""" | ||
Test for when one side of the field of view is vertical. | ||
""" | ||
height = 30 | ||
frustum_angle_x = pi / 8 | ||
frustum_angle_y = pi / 6 | ||
field_of_vision_x = pi / 4 | ||
field_of_vision_y = pi / 3 | ||
|
||
x, y = search_area_dimensions.search_area_dimensions( | ||
height, frustum_angle_x, frustum_angle_y, True, field_of_vision_x, field_of_vision_y, True | ||
) | ||
|
||
assert abs(x - 30) < THRESHOLD | ||
assert abs(y - 30 * sqrt(3)) < THRESHOLD | ||
|
||
|
||
def test_askew_acute_field_of_view() -> None: | ||
""" | ||
Test for when field of view spreads outwards on both sides. | ||
""" | ||
height = 40 | ||
frustum_angle_x = pi / 12 | ||
frustum_angle_y = pi / 24 | ||
field_of_vision_x = pi / 2 | ||
field_of_vision_y = 7 * pi / 12 | ||
|
||
x, y = search_area_dimensions.search_area_dimensions( | ||
height, frustum_angle_x, frustum_angle_y, True, field_of_vision_x, field_of_vision_y, True | ||
) | ||
|
||
assert abs(x - (40 * sqrt(3) + 40 / sqrt(3))) < THRESHOLD | ||
assert abs(y - (40 + 40 * sqrt(3))) < THRESHOLD | ||
|
||
|
||
def test_askew_obtuse_field_of_view() -> None: | ||
""" | ||
Test for when field of view spreads to one side from both directions. | ||
""" | ||
height = 50 | ||
frustum_angle_x = pi / 4 | ||
frustum_angle_y = 7 * pi / 24 | ||
field_of_vision_x = pi / 6 | ||
field_of_vision_y = pi / 12 | ||
|
||
x, y = search_area_dimensions.search_area_dimensions( | ||
height, frustum_angle_x, frustum_angle_y, True, field_of_vision_x, field_of_vision_y, True | ||
) | ||
|
||
assert abs(x - (50 * sqrt(3) - 50 / sqrt(3))) < THRESHOLD | ||
assert abs(y - (50 * sqrt(3) - 50)) < THRESHOLD |