From 3990e347a5fbbc740a97ea9b772e166fd30003d2 Mon Sep 17 00:00:00 2001 From: Vincent Grafe Date: Thu, 25 Jun 2026 13:08:06 -0400 Subject: [PATCH] Configure generated NetRID flight data --- .../configurations/dev/library/resources.yaml | 15 ++++++ .../configurations/dev/netrid_v19.yaml | 4 +- .../configurations/dev/netrid_v22a.yaml | 4 +- .../resources/netrid/flight_data.py | 6 +++ .../netrid/flight_data_resources_test.py | 52 ++++++++++++++++++- .../adjacent_circular_flights_simulator.py | 25 ++++++--- ...CircularFlightsSimulatorConfiguration.json | 8 +++ 7 files changed, 101 insertions(+), 13 deletions(-) diff --git a/monitoring/uss_qualifier/configurations/dev/library/resources.yaml b/monitoring/uss_qualifier/configurations/dev/library/resources.yaml index 06e42eec7a..e0bfbdcfb8 100644 --- a/monitoring/uss_qualifier/configurations/dev/library/resources.yaml +++ b/monitoring/uss_qualifier/configurations/dev/library/resources.yaml @@ -236,6 +236,21 @@ che_adjacent_circular_flights_data: specification: adjacent_circular_flights_simulation_source: { } +kentland_generated_flights_data: + $content_schema: monitoring/uss_qualifier/resources/definitions/ResourceDeclaration.json + resource_type: resources.netrid.FlightDataResource + specification: + adjacent_circular_flights_simulation_source: + minx: -80.579 + miny: 37.196 + maxx: -80.574 + maxy: 37.199 + utm_zone: 17 + altitude_of_ground_level_wgs_84: 526 + num_flights: 10 + duration: 61 + flight_start_delay: 5s + dc_flights_data: $content_schema: monitoring/uss_qualifier/resources/definitions/ResourceDeclaration.json resource_type: resources.netrid.FlightDataResource diff --git a/monitoring/uss_qualifier/configurations/dev/netrid_v19.yaml b/monitoring/uss_qualifier/configurations/dev/netrid_v19.yaml index 198b9eb1f2..3b536794e9 100644 --- a/monitoring/uss_qualifier/configurations/dev/netrid_v19.yaml +++ b/monitoring/uss_qualifier/configurations/dev/netrid_v19.yaml @@ -3,7 +3,7 @@ v1: test_run: resources: resource_declarations: - kentland_flights_data: {$ref: 'library/resources.yaml#/kentland_flights_data'} + kentland_generated_flights_data: {$ref: 'library/resources.yaml#/kentland_generated_flights_data'} netrid_observation_evaluation_configuration: {$ref: 'library/resources.yaml#/netrid_observation_evaluation_configuration'} utm_client_identity: {$ref: 'library/resources.yaml#/utm_client_identity'} id_generator: {$ref: 'library/resources.yaml#/id_generator'} @@ -32,7 +32,7 @@ v1: test_suite: suite_type: suites.astm.netrid.f3411_19 resources: - flights_data: kentland_flights_data + flights_data: kentland_generated_flights_data service_providers: netrid_service_providers_v19 observers: netrid_observers_v19 mock_uss_dp: mock_uss_instance_dp_v19 diff --git a/monitoring/uss_qualifier/configurations/dev/netrid_v22a.yaml b/monitoring/uss_qualifier/configurations/dev/netrid_v22a.yaml index b4ce563c71..fdc586293c 100644 --- a/monitoring/uss_qualifier/configurations/dev/netrid_v22a.yaml +++ b/monitoring/uss_qualifier/configurations/dev/netrid_v22a.yaml @@ -3,7 +3,7 @@ v1: test_run: resources: resource_declarations: - kentland_flights_data: {$ref: 'library/resources.yaml#/kentland_flights_data'} + kentland_generated_flights_data: {$ref: 'library/resources.yaml#/kentland_generated_flights_data'} netrid_observation_evaluation_configuration: {$ref: 'library/resources.yaml#/netrid_observation_evaluation_configuration'} utm_client_identity: {$ref: 'library/resources.yaml#/utm_client_identity'} id_generator: {$ref: 'library/resources.yaml#/id_generator'} @@ -32,7 +32,7 @@ v1: test_suite: suite_type: suites.astm.netrid.f3411_22a resources: - flights_data: kentland_flights_data + flights_data: kentland_generated_flights_data service_providers: netrid_service_providers_v22a observers: netrid_observers_v22a mock_uss_dp: mock_uss_instance_dp_v22a diff --git a/monitoring/uss_qualifier/resources/netrid/flight_data.py b/monitoring/uss_qualifier/resources/netrid/flight_data.py index 6c73f321ae..09613c8937 100644 --- a/monitoring/uss_qualifier/resources/netrid/flight_data.py +++ b/monitoring/uss_qualifier/resources/netrid/flight_data.py @@ -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") diff --git a/monitoring/uss_qualifier/resources/netrid/flight_data_resources_test.py b/monitoring/uss_qualifier/resources/netrid/flight_data_resources_test.py index 1511c8d01e..98a4a8fef0 100644 --- a/monitoring/uss_qualifier/resources/netrid/flight_data_resources_test.py +++ b/monitoring/uss_qualifier/resources/netrid/flight_data_resources_test.py @@ -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") diff --git a/monitoring/uss_qualifier/resources/netrid/simulation/adjacent_circular_flights_simulator.py b/monitoring/uss_qualifier/resources/netrid/simulation/adjacent_circular_flights_simulator.py index 76c7b72a86..63c36d9e9c 100644 --- a/monitoring/uss_qualifier/resources/netrid/simulation/adjacent_circular_flights_simulator.py +++ b/monitoring/uss_qualifier/resources/netrid/simulation/adjacent_circular_flights_simulator.py @@ -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 @@ -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 @@ -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) diff --git a/schemas/monitoring/uss_qualifier/resources/netrid/flight_data/AdjacentCircularFlightsSimulatorConfiguration.json b/schemas/monitoring/uss_qualifier/resources/netrid/flight_data/AdjacentCircularFlightsSimulatorConfiguration.json index 94ad03e5e7..1e400220d1 100644 --- a/schemas/monitoring/uss_qualifier/resources/netrid/flight_data/AdjacentCircularFlightsSimulatorConfiguration.json +++ b/schemas/monitoring/uss_qualifier/resources/netrid/flight_data/AdjacentCircularFlightsSimulatorConfiguration.json @@ -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" @@ -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": [