Skip to content
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

[uss_qualifier/utm] Use active volumes for activated op intents; [mock_uss/scdsc] Enforce active volume for activated op intent; Fix #217 #237

Merged
merged 12 commits into from
Oct 18, 2023
Merged
21 changes: 21 additions & 0 deletions monitoring/mock_uss/scdsc/routes_injection.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from typing import List, Tuple
import uuid

import arrow
import flask
from loguru import logger
import requests.exceptions
Expand Down Expand Up @@ -245,6 +246,26 @@ def inject_flight(flight_id: str, req_body: InjectFlightRequest) -> Tuple[dict,
200,
)

# Validate intent is currently active if in Activated state
# I.e. at least one volume has start time in the past and end time in the future
now = arrow.utcnow()
if req_body.operational_intent.state == OperationalIntentState.Activated:
active_volume = False
for vol in (
req_body.operational_intent.volumes
+ req_body.operational_intent.off_nominal_volumes
):
if vol.time_start.value.datetime <= now <= vol.time_end.value.datetime:
active_volume = True
mickmis marked this conversation as resolved.
Show resolved Hide resolved
if not active_volume:
return (
InjectFlightResponse(
result=InjectFlightResponseResult.Rejected,
notes=f"Operational intent is activated but has no volume currently active (now: {now})",
),
200,
)

# Check if this is an existing flight being modified
deadline = datetime.utcnow() + DEADLOCK_TIMEOUT
while True:
Expand Down
7 changes: 7 additions & 0 deletions monitoring/monitorlib/geotemporal.py
Original file line number Diff line number Diff line change
Expand Up @@ -547,3 +547,10 @@ def from_interuss_scd_api(

def to_f3548v21(self) -> List[f3548v21.Volume4D]:
return [v.to_f3548v21() for v in self.volumes]

def has_active_volume(self, time_ref: datetime) -> bool:
active_volume = False
for vol in self.volumes:
if vol.time_start.datetime <= time_ref <= vol.time_end.datetime:
active_volume = True
return active_volume
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ FlightIntentsResource that provides the following flight intents:
- `invalid_too_far_away`: reference time mutation: reference time pulled back so that it is like the operational intent is attempted to be planned more than OiMaxPlanHorizon = 30 days ahead of time
- `valid_conflict_tiny_overlap`: volumes mutation: has a volume that overlaps with `valid_op_intent` just above IntersectionMinimumPrecision = 1cm in a way that must result as a conflict

Because the scenario involves activation of intents, all activated intents must be active during the execution of the
test scenario, i.e. they must start before the reference time plus planning time duration. Additionally, their end time
must leave sufficient time for the execution of the test scenario. For the sake of simplicity, it is recommended to set
the start and end times of all the intents to the same range.

### tested_uss
FlightPlannerResource that will be tested for its validation of operational intents.

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import arrow

from monitoring.monitorlib.geotemporal import Volume4DCollection
from monitoring.uss_qualifier.common_data_definitions import Severity
from uas_standards.astm.f3548.v21.api import OperationalIntentState
Expand Down Expand Up @@ -59,10 +61,10 @@ def __init__(
self.tested_uss = tested_uss.flight_planner
self.dss = dss.dss

flight_intents = flight_intents.get_flight_intents()
_flight_intents = flight_intents.get_flight_intents()

extents = []
for intent in flight_intents.values():
for intent in _flight_intents.values():
extents.extend(intent.request.operational_intent.volumes)
extents.extend(intent.request.operational_intent.off_nominal_volumes)
self._intents_extent = Volume4DCollection.from_interuss_scd_api(
Expand All @@ -78,14 +80,25 @@ def __init__(
self.invalid_activated_offnominal,
self.valid_conflict_tiny_overlap,
) = (
flight_intents["valid_flight"],
flight_intents["valid_activated"],
flight_intents["invalid_too_far_away"],
flight_intents["invalid_accepted_offnominal"],
flight_intents["invalid_activated_offnominal"],
flight_intents["valid_conflict_tiny_overlap"],
_flight_intents["valid_flight"],
_flight_intents["valid_activated"],
_flight_intents["invalid_too_far_away"],
_flight_intents["invalid_accepted_offnominal"],
_flight_intents["invalid_activated_offnominal"],
_flight_intents["valid_conflict_tiny_overlap"],
)

now = arrow.utcnow()
for intent_name, intent in _flight_intents.items():
if (
intent.request.operational_intent.state
== OperationalIntentState.Activated
):
assert Volume4DCollection.from_interuss_scd_api(
intent.request.operational_intent.volumes
+ intent.request.operational_intent.off_nominal_volumes
), f"at least one volume of activated intent {intent_name} must be active now (now is {now})"

assert (
self.valid_flight.request.operational_intent.state
== OperationalIntentState.Accepted
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,60 +21,65 @@ Otherwise, the FlightIntentsResource must provide the following flight intents:

<table>
<tr>
<th>Flight intent ID</th><!-- TODO: remove mention of time ranges -->
<th>Flight intent ID</th><
<th>Flight name</th>
<th>Priority</th>
<th>State</th><!-- TODO: Update with usage_state and uas_state when new flight planning API is adopted -->
<th>Must conflict with</th>
<th>Must not conflict with</th>
</tr>
<tr>
<td><code>flight_1_planned_time_range_A</code></td>
<td><code>flight_1_planned_vol_A</code></td>
<td rowspan="2">Flight 1</td>
<td rowspan="8">Any (but all the same)</td>
<td>Accepted</td>
<td rowspan="2">Flight 2</td>
<td rowspan="2">N/A</td>
</tr>
<tr>
<td><code>flight_1_activated_time_range_A</code></td>
<td><code>flight_1_activated_vol_A</code></td>
<td>Activated</td>
</tr>
<tr>
<td><code>flight_1_activated_time_range_A_extended</code></td>
<td><code>flight_1_activated_vol_A_extended</code></td>
<td>Flight 1m</td>
<td>Activated</td>
<td>Flight 2</td>
<td>N/A</td>
</tr>
<tr>
<td><code>flight_1_planned_time_range_B</code></td>
<td><code>flight_1_planned_vol_B</code></td>
<td rowspan="2">Flight 1c</td>
<td>Planned</td>
<td rowspan="2">N/A</td>
<td rowspan="2">Flight 2</td>
</tr>
<tr>
<td><code>flight_1_activated_time_range_B</code></td>
<td><code>flight_1_activated_vol_B</code></td>
<td>Activated</td>
</tr>
<tr>
<td><code>flight_2_equal_prio_planned_time_range_B</code></td>
<td><code>flight_2_equal_prio_planned_vol_B</code></td>
<td rowspan="3">Flight 2</td>
<td>Planned</td>
<td rowspan="3">Flight 1, Flight 1m</td>
<td rowspan="3">Flight 1c</td>
</tr>
<tr>
<td><code>flight_2_equal_prio_activated_time_range_B</code></td>
<td><code>flight_2_equal_prio_activated_vol_B</code></td>
<td>Activated</td>
</tr>
<tr>
<td><code>flight_2_equal_prio_nonconforming_time_range_A</code></td>
<td><code>flight_2_equal_prio_nonconforming_vol_A</code></td>
<td>Nonconforming</td>
</tr>
</table>

Because the scenario involves activation of intents, all activated intents must be active during the execution of the
test scenario, i.e. they must start before the reference time plus planning time duration. Additionally, their end time
must leave sufficient time for the execution of the test scenario. For the sake of simplicity, it is recommended to set
the start and end times of all the intents to the same range.

### tested_uss
FlightPlannerResource that is under test and will manage flight 1.

Expand Down
Loading
Loading