Skip to content

Commit

Permalink
[uss_qualifier/utm/off_nominal_planning] Add 'down USS with equal pri…
Browse files Browse the repository at this point in the history
…ority conflicts not permitted' scenario validating SCD0010
  • Loading branch information
mickmis committed Dec 1, 2023
1 parent 7f1217e commit 2371e98
Show file tree
Hide file tree
Showing 10 changed files with 540 additions and 91 deletions.
3 changes: 3 additions & 0 deletions monitoring/uss_qualifier/scenarios/astm/utm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,6 @@
from .aggregate_checks import AggregateChecks
from .prep_planners import PrepareFlightPlanners
from .off_nominal_planning.down_uss import DownUSS
from .off_nominal_planning.down_uss_equal_priority_not_permitted import (
DownUSSEqualPriorityNotPermitted,
)
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
# Off-Nominal planning: down USS test scenario

## Description
This test aims to test the strategic coordination requirements that relate to the down USS mechanism:
This test aims to test the strategic coordination requirements that relate to the down USS mechanism in the general case:
- **[astm.f3548.v21.SCD0005](../../../../requirements/astm/f3548/v21.md)**
- **[astm.f3548.v21.SCD0010](../../../../requirements/astm/f3548/v21.md)**

It involves a single tested USS. The USS qualifier acts as a virtual USS that may have its availability set to down.

Expand All @@ -17,24 +16,12 @@ FlightIntentsResource that provides the following flight intents:
<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_vol_A</code></td>
<td rowspan="2">Flight 1</td>
<td rowspan="5">Any</td>
<td>Accepted</td>
<td rowspan="2">Flight 2</td>
<td rowspan="2">Flight 2m</td>
</tr>
<tr>
<td><code>flight_2_planned_vol_A</code></td>
<td rowspan="2">Flight 2</td>
<td rowspan="3">Higher than Flight 1*</td>
<td>Accepted</td>
<td rowspan="2">Flight 1</td>
<td rowspan="2">N/A</td>
</tr>
</table>

Expand Down Expand Up @@ -62,11 +49,12 @@ Delete any leftover operational intents created at DSS by virtual USS.
#### Successful operational intents cleanup check
If the search for own operational intents or their deletion fail, this check fails per **[astm.f3548.v21.DSS0005](../../../../requirements/astm/f3548/v21.md)**.


## Plan flight in conflict with planned flight managed by down USS test case
This test case aims at testing requirement **[astm.f3548.v21.SCD0005](../../../../requirements/astm/f3548/v21.md)**.

### Virtual USS plans high-priority flight 2 test step
The USS qualifier, acting as a virtual USS, creates an operational intent at the DSS with a high priority and a non-working base URL.
### Virtual USS creates conflicting operational intent test step
The USS qualifier, acting as a virtual USS, creates an operational intent at the DSS with a non-working base URL.
The objective is to make the later request by the tested USS to retrieve operational intent details to fail.

#### Operational intent successfully created check
Expand All @@ -75,15 +63,15 @@ If the creation of the operational intent reference at the DSS fails, this check
### [Declare virtual USS as down at DSS test step](../set_uss_down.md)

### Tested USS attempts to plan low-priority flight 1 test step
The low-priority flight 1 of the tested USS conflicts with high-priority flight 2 of the virtual USS.
The low-priority flight 1 of the tested USS conflicts with the operational intent of the virtual USS.
However, since:
- the virtual USS is declared as down at the DSS,
- it does not respond for operational intent details, and
- the operational intent for flight 2 is in 'Planned' state,
The tested USS should evaluate the operational intent of flight 2 as having the lowest bound priority status, i.e. a priority strictly lower than the lowest priority allowed by the local regulation.
- the conflicting operational intent is in the 'Accepted' state,
The tested USS should evaluate the conflicting operational intent as having the lowest bound priority status, i.e. a priority strictly lower than the lowest priority allowed by the local regulation.

As such, the tested USS may either:
- Successfully plan flight 1 over the higher-priority flight 2, or
- Successfully plan flight 1 over the conflicting operational intent, or
- Decide to be more conservative and reject the planning of flight 1.

#### Successful planning check
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
from typing import Optional, List
from typing import Dict, Optional

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
from uas_standards.astm.f3548.v21.api import (
OperationalIntentState,
OperationalIntentReference,
)
from uas_standards.interuss.automated_testing.scd.v1.api import (
InjectFlightResponseResult,
)
Expand Down Expand Up @@ -37,11 +40,8 @@


class DownUSS(TestScenario):
flight_1_id: Optional[str] = None
flight_1_planned_vol_A: FlightIntent

flight_2_planned_vol_A: FlightIntent

uss_qualifier_sub: str

tested_uss: FlightPlanner
Expand All @@ -57,7 +57,7 @@ def __init__(
self.tested_uss = tested_uss.flight_planner
self.dss = dss.dss

_flight_intents = {
_flight_intents: Dict[str, FlightIntent] = {
k: FlightIntent.from_flight_info_template(v)
for k, v in flight_intents.get_flight_intents().items()
}
Expand All @@ -70,47 +70,31 @@ def __init__(
extents
).bounding_volume.to_f3548v21()

try:
(self.flight_1_planned_vol_A, self.flight_2_planned_vol_A,) = (
_flight_intents["flight_1_planned_vol_A"],
_flight_intents["flight_2_planned_vol_A"],
)
now = arrow.utcnow().datetime
for intent_name, intent in _flight_intents.items():
if (
intent.request.operational_intent.state
== OperationalIntentState.Activated
):
if not Volume4DCollection.from_interuss_scd_api(
intent.request.operational_intent.volumes
+ intent.request.operational_intent.off_nominal_volumes
).has_active_volume(now):
err_msg = f"at least one volume of activated intent {intent_name} must be active now (now is {now})"
raise ValueError(
f"`{self.me()}` TestScenario requirements for flight_intents not met: {err_msg}"
)

now = arrow.utcnow().datetime
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
).has_active_volume(
now
), f"at least one volume of activated intent {intent_name} must be active now (now is {now})"
self._parse_flight_intents(_flight_intents)

def _parse_flight_intents(self, flight_intents: Dict[str, FlightIntent]) -> None:
try:
self.flight_1_planned_vol_A = flight_intents["flight_1_planned_vol_A"]

assert (
self.flight_1_planned_vol_A.request.operational_intent.state
== OperationalIntentState.Accepted
), "flight_1_planned_vol_A must have state Accepted"
assert (
self.flight_2_planned_vol_A.request.operational_intent.state
== OperationalIntentState.Accepted
), "flight_2_planned_vol_A must have state Accepted"

# TODO: check that flight data is the same across the different versions of the flight

assert (
self.flight_2_planned_vol_A.request.operational_intent.priority
> self.flight_1_planned_vol_A.request.operational_intent.priority
), "flight_2 must have higher priority than flight_1"
assert Volume4DCollection.from_interuss_scd_api(
self.flight_1_planned_vol_A.request.operational_intent.volumes
).intersects_vol4s(
Volume4DCollection.from_interuss_scd_api(
self.flight_2_planned_vol_A.request.operational_intent.volumes
)
), "flight_1_planned_vol_A and flight_2_planned_vol_A must intersect"

except KeyError as e:
raise ValueError(
Expand Down Expand Up @@ -168,30 +152,68 @@ def _setup(self):
self._clear_op_intents()
self.end_test_step()

def _plan_flight_conflict_planned(self):

# Virtual USS plans high-priority flight 2 test step
self.begin_test_step("Virtual USS plans high-priority flight 2")
def _put_conflicting_op_intent_step(
self,
conflicting_intent: FlightIntent,
target_state: OperationalIntentState,
old_op_intent: Optional[OperationalIntentReference] = None,
) -> OperationalIntentReference:
if old_op_intent is not None:
key = [old_op_intent.ovn]
oi_id = old_op_intent.id
oi_ovn = old_op_intent.ovn
else:
key = None
oi_id = None
oi_ovn = None

if target_state == OperationalIntentState.Accepted:
msg_action = "creates"
msg_action_past = "created"
elif target_state == OperationalIntentState.Activated:
msg_action = "activates"
msg_action_past = "activated"
elif target_state == OperationalIntentState.Nonconforming:
msg_action = "transitions to Nonconforming"
msg_action_past = "transitioned to Nonconforming"
elif target_state == OperationalIntentState.Contingent:
msg_action = "transitions to Contingent"
msg_action_past = "transitioned to Contingent"
else:
raise ValueError(f"Invalid state {target_state}")

self.begin_test_step(f"Virtual USS {msg_action} conflicting operational intent")
oi_ref, _, query = self.dss.put_op_intent(
Volume4DCollection.from_interuss_scd_api(
self.flight_2_planned_vol_A.request.operational_intent.volumes
conflicting_intent.request.operational_intent.volumes
).to_f3548v21(),
[], # we assume there is no other operational intent in that area
OperationalIntentState.Accepted,
key,
target_state,
"https://fake.uss/down",
oi_id,
oi_ovn,
)
self.record_query(query)
with self.check(
"Operational intent successfully created", [self.dss.participant_id]
f"Operational intent successfully {msg_action_past}",
[self.dss.participant_id],
) as check:
if oi_ref is None:
check.record_failed(
"Operational intent not successfully created",
f"Operational intent not successfully {msg_action_past}",
Severity.High,
f"DSS responded code {query.status_code}; error message: {query.error_message}",
query_timestamps=[query.request.timestamp],
)
self.end_test_step()
return oi_ref

def _plan_flight_conflict_planned(self):

# Virtual USS creates conflicting operational intent test step
self._put_conflicting_op_intent_step(
self.flight_1_planned_vol_A, OperationalIntentState.Accepted
)

# Declare virtual USS as down at DSS test step
set_uss_down(
Expand Down
Loading

0 comments on commit 2371e98

Please sign in to comment.