Skip to content

Commit

Permalink
Fix behavior
Browse files Browse the repository at this point in the history
  • Loading branch information
BenjaminPelletier committed Oct 10, 2023
1 parent 6984112 commit e257ae4
Show file tree
Hide file tree
Showing 7 changed files with 125 additions and 85 deletions.
129 changes: 69 additions & 60 deletions monitoring/mock_uss/scdsc/routes_injection.py
Original file line number Diff line number Diff line change
Expand Up @@ -216,9 +216,11 @@ def inject_flight(flight_id: str, req_body: InjectFlightRequest) -> Tuple[dict,
)

# Validate max planning horizon for creation
start_time = Volume4DCollection.from_interuss_scd_api(
v4c = Volume4DCollection.from_interuss_scd_api(
req_body.operational_intent.volumes
).time_start.datetime
+ req_body.operational_intent.off_nominal_volumes
)
start_time = v4c.time_start.datetime
time_delta = start_time - datetime.now(tz=start_time.tzinfo)
if (
time_delta.days > OiMaxPlanHorizonDays
Expand Down Expand Up @@ -297,72 +299,79 @@ def inject_flight(flight_id: str, req_body: InjectFlightRequest) -> Tuple[dict,
logger.debug(
f"[inject_flight/{pid}:{flight_id}] Obtaining latest operational intent information"
)
vol4 = Volume4DCollection.from_interuss_scd_api(
req_body.operational_intent.volumes
).bounding_volume.to_f3548v21()
op_intents = query_operational_intents(vol4)

# Check for intersections
step_name = "checking for intersections"
logger.debug(
f"[inject_flight/{pid}:{flight_id}] Checking for intersections with {', '.join(op_intent.reference.id for op_intent in op_intents)}"
)
v1 = Volume4DCollection.from_interuss_scd_api(
req_body.operational_intent.volumes
+ req_body.operational_intent.off_nominal_volumes
)
for op_intent in op_intents:
if (
existing_flight
and existing_flight.op_intent_reference.id == op_intent.reference.id
):
logger.debug(
f"[inject_flight/{pid}:{flight_id}] intersection with {op_intent.reference.id} not considered: intersection with a past version of this flight"
)
continue
if req_body.operational_intent.priority > op_intent.details.priority:
logger.debug(
f"[inject_flight/{pid}:{flight_id}] intersection with {op_intent.reference.id} not considered: intersection with lower-priority operational intents"
)
continue
if (
req_body.operational_intent.priority == op_intent.details.priority
and locality.allows_same_priority_intersections(
req_body.operational_intent.priority
)
):
logger.debug(
f"[inject_flight/{pid}:{flight_id}] intersection with {op_intent.reference.id} not considered: intersection with same-priority operational intents (if allowed)"
)
continue
vol4 = v1.bounding_volume.to_f3548v21()
op_intents = query_operational_intents(vol4)

v2 = Volume4DCollection.from_interuss_scd_api(
op_intent.details.volumes + op_intent.details.off_nominal_volumes
if req_body.operational_intent.state in (
OperationalIntentState.Nonconforming,
OperationalIntentState.Contingent,
):
logger.debug(
f"[inject_flight/{pid}:{flight_id}] Skipping intersection check because flight is {req_body.operational_intent.state}"
)
else:
# Check for intersections
step_name = "checking for intersections"
logger.debug(
f"[inject_flight/{pid}:{flight_id}] Checking for intersections with {', '.join(op_intent.reference.id for op_intent in op_intents)}"
)
for op_intent in op_intents:
if (
existing_flight
and existing_flight.op_intent_reference.id == op_intent.reference.id
):
logger.debug(
f"[inject_flight/{pid}:{flight_id}] intersection with {op_intent.reference.id} not considered: intersection with a past version of this flight"
)
continue
if req_body.operational_intent.priority > op_intent.details.priority:
logger.debug(
f"[inject_flight/{pid}:{flight_id}] intersection with {op_intent.reference.id} not considered: intersection with lower-priority operational intents"
)
continue
if (
req_body.operational_intent.priority == op_intent.details.priority
and locality.allows_same_priority_intersections(
req_body.operational_intent.priority
)
):
logger.debug(
f"[inject_flight/{pid}:{flight_id}] intersection with {op_intent.reference.id} not considered: intersection with same-priority operational intents (if allowed)"
)
continue

if (
existing_flight
and existing_flight.op_intent_reference.state
== OperationalIntentState.Activated
and req_body.operational_intent.state
== OperationalIntentState.Activated
and Volume4DCollection.from_f3548v21(
existing_flight.op_intent_injection.volumes
).intersects_vol4s(v2)
):
logger.debug(
f"[inject_flight/{pid}:{flight_id}] intersection with {op_intent.reference.id} not considered: modification of Activated operational intent with a pre-existing conflict"
v2 = Volume4DCollection.from_interuss_scd_api(
op_intent.details.volumes + op_intent.details.off_nominal_volumes
)
continue

if v1.intersects_vol4s(v2):
notes = f"Requested flight (priority {req_body.operational_intent.priority}) intersected {op_intent.reference.manager}'s operational intent {op_intent.reference.id} (priority {op_intent.details.priority})"
return (
InjectFlightResponse(
result=InjectFlightResponseResult.ConflictWithFlight,
notes=notes,
),
200,
)
if (
existing_flight
and existing_flight.op_intent_reference.state
== OperationalIntentState.Activated
and req_body.operational_intent.state
== OperationalIntentState.Activated
and Volume4DCollection.from_f3548v21(
existing_flight.op_intent_injection.volumes
).intersects_vol4s(v2)
):
logger.debug(
f"[inject_flight/{pid}:{flight_id}] intersection with {op_intent.reference.id} not considered: modification of Activated operational intent with a pre-existing conflict"
)
continue

if v1.intersects_vol4s(v2):
notes = f"Requested flight (priority {req_body.operational_intent.priority}) intersected {op_intent.reference.manager}'s operational intent {op_intent.reference.id} (priority {op_intent.details.priority})"
return (
InjectFlightResponse(
result=InjectFlightResponseResult.ConflictWithFlight,
notes=notes,
),
200,
)

# Create operational intent in DSS
step_name = "sharing operational intent in DSS"
Expand Down
6 changes: 2 additions & 4 deletions monitoring/monitorlib/clients/flight_planning/client_scd.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,15 +77,13 @@ def _inject(

if uas_state == UasState.Nominal:
volumes = [
v.to_interuss_scd_api()
for v in flight_info.basic_information.area
v.to_interuss_scd_api() for v in flight_info.basic_information.area
]
off_nominal_volumes = []
else:
volumes = []
off_nominal_volumes = [
v.to_scd_automated_testing_api()
for v in flight_info.basic_information.area
v.to_interuss_scd_api() for v in flight_info.basic_information.area
]

if "astm_f3548_21" in flight_info and flight_info.astm_f3548_21:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,9 +112,15 @@ def request_flight(
OperationalIntentState.Nonconforming: UasState.OffNominal,
OperationalIntentState.Contingent: UasState.Contingent,
}
if request.operational_intent.state in (OperationalIntentState.Accepted, OperationalIntentState.Activated) and request.operational_intent.off_nominal_volumes:
if (
request.operational_intent.state
in (OperationalIntentState.Accepted, OperationalIntentState.Activated)
and request.operational_intent.off_nominal_volumes
):
# This invalid request can no longer be represented with a standard flight planning request; reject it at the client level instead
raise ValueError(f"Request for nominal {request.operational_intent.state} operational intent is invalid because it contains off-nominal volumes")
raise ValueError(
f"Request for nominal {request.operational_intent.state} operational intent is invalid because it contains off-nominal volumes"
)
v4c = Volume4DCollection.from_interuss_scd_api(
request.operational_intent.volumes
) + Volume4DCollection.from_interuss_scd_api(
Expand All @@ -138,13 +144,13 @@ def request_flight(
)

if not flight_id:
flight_id = str(uuid.uuid4())
try:
resp = self.scd_client.try_plan_flight(
flight_info, ExecutionStyle.IfAllowed
)
except PlanningActivityError as e:
raise QueryError(str(e), e.queries)
flight_id = resp.flight_id
else:
try:
resp = self.scd_client.try_update_flight(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,10 @@ def _validate_precision_intersection(self):
self,
"Attempt to plan flight conflicting by a tiny overlap",
"Incorrectly planned",
{InjectFlightResponseResult.ConflictWithFlight},
{
InjectFlightResponseResult.ConflictWithFlight,
InjectFlightResponseResult.Rejected,
},
{InjectFlightResponseResult.Failed: "Failure"},
self.tested_uss,
self.valid_conflict_tiny_overlap.request,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -455,10 +455,6 @@ def _modify_activated_flight_preexisting_conflict(
self.flight_1_activated_time_range_A.request
)

# TODO: the following call requires the control USS to support CMSA role,
# but as there is currently no explicit way of knowing if it is the case
# or not, we assume that a Rejected result means the USS does not
# support the CMSA role, in which case we interrupt the scenario.
with OpIntentValidator(
self,
self.control_uss,
Expand All @@ -473,15 +469,15 @@ def _modify_activated_flight_preexisting_conflict(
"Successful transition to non-conforming state",
{
InjectFlightResponseResult.Planned,
InjectFlightResponseResult.Rejected,
InjectFlightResponseResult.NotSupported,
},
{InjectFlightResponseResult.Failed: "Failure"},
self.control_uss,
self.flight_2_equal_prio_nonconforming_time_range_A.request,
self.flight_2_id,
)
if resp_flight_2.result == InjectFlightResponseResult.Rejected:
msg = f"{self.control_uss.config.participant_id} rejected transition to a Nonconforming state because it does not support CMSA role, execution of the scenario was stopped without failure"
if resp_flight_2.result == InjectFlightResponseResult.NotSupported:
msg = f"{self.control_uss.config.participant_id} does not support the transition to a Nonconforming state; execution of the scenario was stopped without failure"
self.record_note("Control USS does not support CMSA role", msg)
raise ScenarioCannotContinueError(msg)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,10 @@ def plan_priority_conflict_flight_intent(
scenario,
test_step,
"Incorrectly planned",
{InjectFlightResponseResult.ConflictWithFlight},
{
InjectFlightResponseResult.ConflictWithFlight,
InjectFlightResponseResult.Rejected,
},
{InjectFlightResponseResult.Failed: "Failure"},
flight_planner,
flight_intent,
Expand Down Expand Up @@ -67,7 +70,10 @@ def modify_planned_priority_conflict_flight_intent(
scenario,
test_step,
"Incorrectly modified",
{InjectFlightResponseResult.ConflictWithFlight},
{
InjectFlightResponseResult.ConflictWithFlight,
InjectFlightResponseResult.Rejected,
},
{InjectFlightResponseResult.Failed: "Failure"},
flight_planner,
flight_intent,
Expand Down Expand Up @@ -97,7 +103,10 @@ def activate_priority_conflict_flight_intent(
scenario,
test_step,
"Incorrectly activated",
{InjectFlightResponseResult.ConflictWithFlight},
{
InjectFlightResponseResult.ConflictWithFlight,
InjectFlightResponseResult.Rejected,
},
{InjectFlightResponseResult.Failed: "Failure"},
flight_planner,
flight_intent,
Expand Down Expand Up @@ -127,7 +136,10 @@ def modify_activated_priority_conflict_flight_intent(
scenario,
test_step,
"Incorrectly modified",
{InjectFlightResponseResult.ConflictWithFlight},
{
InjectFlightResponseResult.ConflictWithFlight,
InjectFlightResponseResult.Rejected,
},
{InjectFlightResponseResult.Failed: "Failure"},
flight_planner,
flight_intent,
Expand Down Expand Up @@ -156,7 +168,10 @@ def plan_conflict_flight_intent(
scenario,
test_step,
"Incorrectly planned",
{InjectFlightResponseResult.ConflictWithFlight},
{
InjectFlightResponseResult.ConflictWithFlight,
InjectFlightResponseResult.Rejected,
},
{InjectFlightResponseResult.Failed: "Failure"},
flight_planner,
flight_intent,
Expand Down Expand Up @@ -185,7 +200,10 @@ def modify_planned_conflict_flight_intent(
scenario,
test_step,
"Incorrectly modified",
{InjectFlightResponseResult.ConflictWithFlight},
{
InjectFlightResponseResult.ConflictWithFlight,
InjectFlightResponseResult.Rejected,
},
{InjectFlightResponseResult.Failed: "Failure"},
flight_planner,
flight_intent,
Expand Down Expand Up @@ -215,7 +233,10 @@ def activate_conflict_flight_intent(
scenario,
test_step,
"Incorrectly activated",
{InjectFlightResponseResult.ConflictWithFlight},
{
InjectFlightResponseResult.ConflictWithFlight,
InjectFlightResponseResult.Rejected,
},
{InjectFlightResponseResult.Failed: "Failure"},
flight_planner,
flight_intent,
Expand Down Expand Up @@ -245,7 +266,10 @@ def modify_activated_conflict_flight_intent(
scenario,
test_step,
"Incorrectly modified",
{InjectFlightResponseResult.ConflictWithFlight},
{
InjectFlightResponseResult.ConflictWithFlight,
InjectFlightResponseResult.Rejected,
},
{InjectFlightResponseResult.Failed: "Failure"},
flight_planner,
flight_intent,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@ def clear_area(
check.record_failed(
summary="Area could not be cleared",
severity=Severity.High,
details=f'Participant indicated "{resp.outcome.message}"' if "message" in resp.outcome else "See query",
details=f'Participant indicated "{resp.outcome.message}"'
if "message" in resp.outcome
else "See query",
query_timestamps=[query.request.timestamp],
)

Expand Down Expand Up @@ -385,7 +387,9 @@ def cleanup_flights(
else:
check.record_failed(
summary="Failed to delete flight",
details=f"USS indicated: {resp.notes}" if "notes" in resp else "See query",
details=f"USS indicated: {resp.notes}"
if "notes" in resp
else "See query",
severity=Severity.Medium,
query_timestamps=[query.request.timestamp],
)

0 comments on commit e257ae4

Please sign in to comment.