Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
6 changes: 6 additions & 0 deletions monitoring/uss_qualifier/resources/netrid/flight_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ class AdjacentCircularFlightsSimulatorConfiguration(ImplicitDict):
flight_start_shift: int = 0
"""Delay generated flight starts from the reference time to spread flights over time. Expressed in seconds. Use 0 to disable."""

num_flights: int = 6
"""Number of adjacent circular flights to generate."""

duration: int = 30
"""Number of seconds of telemetry to generate for each flight."""


class FlightDataKMLFileConfiguration(ImplicitDict):
reference_time: StringBasedDateTime = StringBasedDateTime("2022-01-01T00:00:00Z")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,54 @@ def test_adjacent_circular_flights_simuation_source():
specs = FlightDataSpecification(
adjacent_circular_flights_simulation_source=AdjacentCircularFlightsSimulatorConfiguration()
)
FlightDataResource(specs, "test")
resource = FlightDataResource(specs, "test")

assert len(resource.flight_collection.flights) == 6
assert [len(f.states) for f in resource.flight_collection.flights] == [
30,
30,
30,
30,
30,
30,
]


def test_adjacent_circular_flights_simulation_source_configuration():
specs = FlightDataSpecification(
adjacent_circular_flights_simulation_source=AdjacentCircularFlightsSimulatorConfiguration(
num_flights=4,
duration=61,
)
)

resource = FlightDataResource(specs, "test")

assert len(resource.flight_collection.flights) == 4
assert [len(f.states) for f in resource.flight_collection.flights] == [
61,
61,
61,
61,
]


@pytest.mark.parametrize(
"num_flights,duration",
[
(0, 61),
(4, 0),
],
)
def test_adjacent_circular_flights_simulation_source_invalid_configuration(
num_flights, duration
):
specs = FlightDataSpecification(
adjacent_circular_flights_simulation_source=AdjacentCircularFlightsSimulatorConfiguration(
num_flights=num_flights,
duration=duration,
)
)

with pytest.raises(ValueError):
FlightDataResource(specs, "test")
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ def __init__(self, config: AdjacentCircularFlightsSimulatorConfiguration) -> Non
self.maxx = config.maxx
self.maxy = config.maxy
self.utm_zone = config.utm_zone
if config.num_flights < 1:
raise ValueError("num_flights must be at least 1")
if config.duration < 1:
raise ValueError("duration must be at least 1 second")
self.num_flights = config.num_flights
self.duration = config.duration

self.altitude_agl = 50.0

Expand Down Expand Up @@ -182,15 +188,18 @@ def generate_flight_grid_and_path_points(
self, altitude_of_ground_level_wgs_84: float
):
"""Generate a series of boxes (grid) within the given bounding box to have areas for different flight tracks within each box"""
# Compute the box where the flights will be created. For a the sample bounds given, over Bern, Switzerland, a division by 2 produces a cell_size of 0.0025212764739985793, a division of 3 is 0.0016808509826657196 and division by 4 0.0012606382369992897. As the cell size goes smaller more number of flights can be accomodated within the grid. For the study area bounds we build a 3x2 box for six flights by creating 3 column 2 row grid.
N_COLS = 3
N_ROWS = 2
cell_size_x = (self.maxx - self.minx) / (N_COLS) # create three columns
cell_size_y = (self.maxy - self.miny) / (N_ROWS) # create two rows
# Arrange cells into a compact grid. The default 6 flights preserves the
# previous 3-column by 2-row layout.
n_rows = round(self.num_flights**0.5)
n_cols = -(-self.num_flights // n_rows)
cell_size_x = (self.maxx - self.minx) / n_cols
cell_size_y = (self.maxy - self.miny) / n_rows
grid_cells = []
for u0 in range(0, N_COLS): # 3 columns
for u0 in range(0, n_cols):
x0 = self.minx + (u0 * cell_size_x)
for v0 in range(0, N_ROWS): # 2 rows
for v0 in range(0, n_rows):
if len(grid_cells) >= self.num_flights:
break
y0 = self.miny + (v0 * cell_size_y)
x1 = x0 + cell_size_x
y1 = y0 + cell_size_y
Expand Down Expand Up @@ -356,7 +365,7 @@ def generate_aircraft_states(
)
my_path_generator.generate_query_bboxes()

my_path_generator.generate_rid_state(duration=30)
my_path_generator.generate_rid_state(duration=my_path_generator.duration)
flights = my_path_generator.flights

result = FlightRecordCollection(flights=flights)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
"altitude_of_ground_level_wgs_84": {
"type": "integer"
},
"duration": {
"description": "Number of seconds of telemetry to generate for each flight.",
"type": "integer"
},
"flight_start_shift": {
"description": "Delay generated flight starts from the reference time to spread flights over time. Expressed in seconds. Use 0 to disable.",
"type": "integer"
Expand All @@ -30,6 +34,10 @@
"description": "Southern edge of bounding box (degrees latitude)",
"type": "number"
},
"num_flights": {
"description": "Number of adjacent circular flights to generate.",
"type": "integer"
},
"random_seed": {
"description": "Pseudorandom seed that should be used, or specify None to use default Random.",
"type": [
Expand Down
Loading