Skip to content

Commit b2d5fe3

Browse files
authored
Max Elevation Scan Angle Config (#11)
Add max elevation scan angle to LOS parameters. Restrict to [0,90]. In LOS Validator simple checks, add back same x,y coordinate check separate from elevation scan angle check. Allow elevation scan angle to be 90 degrees. Because of x,y coordinate check, 90 degrees technically is not allowed, but this enables the user to allow all elevation scan angles < 90 degrees (even if that is not advisable).
1 parent 181e840 commit b2d5fe3

File tree

14 files changed

+115
-21
lines changed

14 files changed

+115
-21
lines changed
Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
# Easy Negative Cases
22

3-
Regardless of the model, there are four situations which immediately return
3+
Regardless of the model, there are five situations which immediately return
44
invalid LOS that has nothing to do with obstructions.
55

6-
1. The elevation angle between the two sites is too large (i.e., it should be
7-
much less than 90 degrees).
8-
2. Both sites are on the same building (generally, such sites can be connected
6+
1. Sites have the same latitude and longitude.
7+
2. The elevation angle between the two sites is larger than a user-specified
8+
maximum elevation scan angle. While this would seemingly make #1 redundant,
9+
a user can effectively disable this check by setting it to 90 degrees (even
10+
if that is not advisable).
11+
3. Both sites are on the same building (generally, such sites can be connected
912
by wire).
10-
3. The distance between the sites exceeds the maximum distance (i.e., the
13+
4. The distance between the sites exceeds the maximum distance (i.e., the
1114
signal is not sufficiently strong to merit valid LOS).
12-
4. The LOS intersects with exclusion zones.
15+
5. The LOS intersects with exclusion zones.

terragraph_planner/common/configuration/configs.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,7 @@ def __init__(
424424
link_availability_percentage: float = 99.9,
425425
maximum_los_distance: Optional[int] = 200,
426426
minimum_los_distance: int = 50,
427+
maximum_elevation_scan_angle: float = 25,
427428
carrier_frequency: float = DEFAULT_CARRIER_FREQUENCY,
428429
thermal_noise_power: float = -81.0,
429430
noise_figure: float = 7.0,
@@ -464,6 +465,11 @@ def __init__(
464465
"and maximum LOS distance must be larger than minimum LOS distance",
465466
ConfigException,
466467
)
468+
planner_assert(
469+
0 <= maximum_elevation_scan_angle <= 90,
470+
"Maximum elevation scan angle must be in [0, 90]",
471+
ConfigException,
472+
)
467473
planner_assert(
468474
mounting_height_above_rooftop >= 0,
469475
"Mounting height above rooftop cannot be negative",
@@ -494,6 +500,7 @@ def __init__(
494500
self.rain_rate = rain_rate
495501
self.maximum_los_distance = maximum_los_distance
496502
self.minimum_los_distance = minimum_los_distance
503+
self.maximum_elevation_scan_angle = maximum_elevation_scan_angle
497504
self.carrier_frequency = carrier_frequency
498505
self.thermal_noise_power = thermal_noise_power
499506
self.noise_figure = noise_figure

terragraph_planner/common/configuration/test/test_data/exhausted_configs_with_non_default.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ LINE_OF_SIGHT:
2323
DEFAULT_CN_HEIGHT_ON_POLE: 8
2424
MAXIMUM_LOS_DISTANCE: 500
2525
MINIMUM_LOS_DISTANCE: 5
26+
MAXIMUM_ELEVATION_SCAN_ANGLE: 30
2627
MINIMUM_MCS_OF_BACKHAUL_LINKS: 2
2728
MINIMUM_MCS_OF_ACCESS_LINKS: 3
2829
USE_ELLIPSOIDAL_LOS_MODEL: True

terragraph_planner/common/configuration/test/test_utils.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,7 @@ def test_struct_object_from_non_default_file(self) -> None:
284284
link_availability_percentage=78.9,
285285
maximum_los_distance=500,
286286
minimum_los_distance=5,
287+
maximum_elevation_scan_angle=30,
287288
carrier_frequency=50000.0,
288289
thermal_noise_power=-78.0,
289290
noise_figure=6.6,

terragraph_planner/common/constants.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@
1111
3 # precision used in placement of equidistance sectors
1212
)
1313
EARTH_RADIUS: float = 6371000.0 # the radius of the earth, in meters
14-
# The upper bound for elevation deviation for valid los
15-
ELE_SCAN_ANGLE_LIMIT = 25
1614
FSPL_MARGIN = 92.45 # free-space path loss constant
1715
FULL_ROTATION_ANGLE = 360.0
1816
# WGS 84, aka EPSG 4326, latitude/longitude coordinate system based on the Earth's

terragraph_planner/data/template.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,10 @@ LINE_OF_SIGHT:
103103
# viable communication between two sites
104104
MINIMUM_LOS_DISTANCE: 50
105105

106+
# [Float] Maximum elevation scan angle with respect to the xy-plane for
107+
# viable communication between two sites.
108+
MAXIMUM_ELEVATION_SCAN_ANGLE: 25
109+
106110
# [Optional][Int] Minimum MCS used to determine the maximum line-of-sight
107111
# distance for backhaul/access links in the LOS candidate graph. This
108112
# distance is computed to be the point at which the link capacity goes to 0

terragraph_planner/los/base_los_validator.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ def __init__(
3838
LOSException,
3939
)
4040
planner_assert(
41-
0 < max_el_dev < 90,
41+
0 <= max_el_dev <= 90,
4242
"Invalid max elevation deviation",
4343
LOSException,
4444
)
@@ -74,11 +74,15 @@ def _comp_los_distance(site1: LOSSite, site2: LOSSite) -> float:
7474
def _passes_simple_checks(self, site1: LOSSite, site2: LOSSite) -> bool:
7575
"""
7676
Performs these simple checks
77-
Check 1: on the same building
78-
Check 2: out of distance range
79-
Check 3: exceeds max elevation deviation
80-
Check 4: intersects with the exclusion zones
77+
Check 1: same xy location
78+
Check 2: on the same building
79+
Check 3: out of distance range
80+
Check 4: exceeds max elevation deviation
81+
Check 5: intersects with the exclusion zones
8182
"""
83+
if self._same_xy(site1, site2):
84+
return False
85+
8286
if self._on_the_same_building(site1, site2):
8387
return False
8488

@@ -96,6 +100,9 @@ def _passes_simple_checks(self, site1: LOSSite, site2: LOSSite) -> bool:
96100

97101
return True
98102

103+
def _same_xy(self, site1: LOSSite, site2: LOSSite) -> bool:
104+
return site1.utm_x == site2.utm_x and site1.utm_y == site2.utm_y
105+
99106
def _on_the_same_building(self, site1: LOSSite, site2: LOSSite) -> bool:
100107
return (
101108
site1.location_type

terragraph_planner/los/core.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ def generate_candidate_topology(
150150
exclusion_zones,
151151
max_los_distance,
152152
los_params.minimum_los_distance,
153+
los_params.maximum_elevation_scan_angle,
153154
los_params.los_confidence_threshold,
154155
los_params.use_ellipsoidal_los_model,
155156
los_params.fresnel_radius,
@@ -255,6 +256,7 @@ def compute_los(
255256
exclusion_zones: List[Polygon],
256257
max_los_distance: int,
257258
min_los_distance: int,
259+
max_el_scan_angle: float,
258260
los_confidence_threshold: float,
259261
use_ellipsoidal_los_model: bool,
260262
fresnel_radius: float,
@@ -276,7 +278,8 @@ def compute_los(
276278
@params exlcusion_zones
277279
A list of Polygons where a LOS is prohibited.
278280
279-
@params max_los_distance, min_los_distance, los_confidence_threshold, fresnel_radius, carrier_frequency
281+
@params max_los_distance, min_los_distance, max_el_scan_angle, los_confidence_threshold,
282+
fresnel_radius, carrier_frequency
280283
A set of params to construct the LOS validator to validate the LOS
281284
282285
@params use_ellipsoidal_los_model
@@ -338,6 +341,7 @@ def compute_los(
338341
else None,
339342
max_los_distance=max_los_distance,
340343
min_los_distance=min_los_distance,
344+
max_el_scan_angle=max_el_scan_angle,
341345
los_confidence_threshold=los_confidence_threshold,
342346
use_ellipsoidal_los_model=use_ellipsoidal_los_model,
343347
fresnel_radius=fresnel_radius,
@@ -415,6 +419,7 @@ def build_candidate_topology(
415419
los_params.device_list,
416420
device_pair_to_max_los_dist,
417421
los_params.minimum_los_distance,
422+
los_params.maximum_elevation_scan_angle,
418423
)
419424
logger.info("Completed constructing the topology.")
420425
return topology

terragraph_planner/los/helper.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
StatusType,
3131
)
3232
from terragraph_planner.common.constants import (
33-
ELE_SCAN_ANGLE_LIMIT,
3433
LOWER_BOUND_FOR_LOS_DISTANCE,
3534
UPPER_BOUND_FOR_LOS_DISTANCE,
3635
)
@@ -515,6 +514,7 @@ def compute_los_batch(
515514
left_top_y: Optional[float],
516515
max_los_distance: int,
517516
min_los_distance: int,
517+
max_el_scan_angle: float,
518518
los_confidence_threshold: float,
519519
use_ellipsoidal_los_model: bool,
520520
fresnel_radius: float,
@@ -549,7 +549,7 @@ def compute_los_batch(
549549
surface_elevation,
550550
max_los_distance * (1 + DISTANCE_TOLERANCE_PERCENT),
551551
min_los_distance * (1 - DISTANCE_TOLERANCE_PERCENT),
552-
ELE_SCAN_ANGLE_LIMIT + ELE_SCAN_ANGLE_TOLERANCE,
552+
min(max_el_scan_angle + ELE_SCAN_ANGLE_TOLERANCE, 90),
553553
carrier_frequency,
554554
exclusion_zones,
555555
los_confidence_threshold,
@@ -559,7 +559,7 @@ def compute_los_batch(
559559
surface_elevation,
560560
max_los_distance * (1 + DISTANCE_TOLERANCE_PERCENT),
561561
min_los_distance * (1 - DISTANCE_TOLERANCE_PERCENT),
562-
ELE_SCAN_ANGLE_LIMIT + ELE_SCAN_ANGLE_TOLERANCE,
562+
min(max_el_scan_angle + ELE_SCAN_ANGLE_TOLERANCE, 90),
563563
fresnel_radius,
564564
exclusion_zones,
565565
los_confidence_threshold,
@@ -831,6 +831,7 @@ def construct_topology_from_los_result(
831831
device_list: List[DeviceData],
832832
device_pair_to_max_los_dist: Dict[Tuple[str, str], int],
833833
min_los_dist: int,
834+
max_el_scan_angle: float,
834835
) -> Topology:
835836
"""
836837
Construct a Topology instance for candidate graph from LOS result.
@@ -849,6 +850,8 @@ def construct_topology_from_los_result(
849850
A dict mapping a pair of device SKUs to the max los distance.
850851
@param min_los_dist
851852
An int for the min los distance.
853+
@param max_el_scan_angle
854+
An float for the max elevation scan angle.
852855
@return
853856
A Topology representing the candidate graph.
854857
"""
@@ -868,6 +871,7 @@ def construct_topology_from_los_result(
868871
confidence_dict,
869872
device_pair_to_max_los_dist,
870873
min_los_dist,
874+
max_el_scan_angle,
871875
)
872876

873877

@@ -928,6 +932,7 @@ def add_links_to_topology(
928932
confidence_dict: Dict[Tuple[int, int], float],
929933
device_pair_to_max_los_dist: Dict[Tuple[str, str], int],
930934
min_los_dist: int,
935+
max_el_scan_angle: float,
931936
) -> Topology:
932937
"""
933938
Called by construct_topology_from_los_result, this function is to add links to
@@ -961,7 +966,7 @@ def add_links_to_topology(
961966
rx_site.device.device_sku,
962967
)
963968
]
964-
and link.el_dev <= ELE_SCAN_ANGLE_LIMIT
969+
and link.el_dev <= max_el_scan_angle
965970
):
966971
topology.add_link(link)
967972
return topology

terragraph_planner/los/test/test_base_los_validator.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,10 @@ def setUp(self) -> None:
4343

4444
def test_same_x_y_coordinate(self) -> None:
4545
base_los_validator = MockBaseLOSValidator(
46-
self.elevation, 5, 1, 89, [], 1
46+
self.elevation, 5, 1, 90, [], 1
4747
)
4848
self.assertEqual(
49-
base_los_validator._passes_simple_checks(
49+
base_los_validator._same_xy(
5050
build_los_site_for_los_test(
5151
2.5,
5252
2.5,
@@ -62,7 +62,7 @@ def test_same_x_y_coordinate(self) -> None:
6262
building_id=1,
6363
),
6464
),
65-
False,
65+
True,
6666
)
6767

6868
def test_on_the_same_building(self) -> None:

0 commit comments

Comments
 (0)