feat(routing): low-regime fallback when the upper route is FRA-blocked
If discovery's upper-airspace route can't be made no-error because of RAD restrictions we don't yet model (PROF204 forbidden / PROF205 mandatory routing common in Free Route Airspace), retry the whole discovery in the conventional airway regime below the FRA floor (~FL195), where those restrictions are far sparser. Adopt the low route only if it is fully valid — the bar is no-error, and flying needlessly low isn't the answer when neither passes, so the natural-FL route is kept otherwise. Measured on the batch: no regression, and the fallback collapses the FRA-blocked pairs from ~7-9 errors to 1-2 (near-miss). It delivers a no-error plan for any pair that has a valid low-level alternative; the remaining near-misses need the phase-2 mandatory-routing engine to close. 49 tests green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+30
-1
@@ -464,10 +464,39 @@ pub fn discover_route(
|
|||||||
_ => start_fl,
|
_ => start_fl,
|
||||||
};
|
};
|
||||||
|
|
||||||
let result = routing::discover::find_valid_route(
|
let mut result = routing::discover::find_valid_route(
|
||||||
&conn, &from, &to, &dep_sid, &dest_star, start_fl, rad, validator,
|
&conn, &from, &to, &dep_sid, &dest_star, start_fl, rad, validator,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
// Low-regime fallback: if the upper route is blocked by RAD/FRA restrictions
|
||||||
|
// (PROF204 forbidden / PROF205 mandatory routing) we can't model, retry in the
|
||||||
|
// conventional airway regime *below* the FRA floor (~FL195). The low network
|
||||||
|
// has far fewer such restrictions (validated: EGLL–EDDM 9→1 err), so this
|
||||||
|
// trades cruise altitude for a valid plan. Keep whichever result is better.
|
||||||
|
const FRA_FLOOR: i32 = 195;
|
||||||
|
let fra_blocked = !result.accepted
|
||||||
|
&& result.errors.iter().any(|e| e.code == "PROF204" || e.code == "PROF205");
|
||||||
|
if fra_blocked && start_fl >= FRA_FLOOR {
|
||||||
|
let low_target = full
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|r| routing::route_fl_ceiling(&conn, r).ok().flatten())
|
||||||
|
.map_or(FRA_FLOOR - 15, |c| c.min(FRA_FLOOR - 15))
|
||||||
|
/ 10
|
||||||
|
* 10;
|
||||||
|
if low_target >= 60 && low_target < start_fl {
|
||||||
|
let low = routing::discover::find_valid_route(
|
||||||
|
&conn, &from, &to, &dep_sid, &dest_star, low_target, rad, validator,
|
||||||
|
)?;
|
||||||
|
// Only adopt the low route if it is *fully valid* — the bar is no-error.
|
||||||
|
// A low route with fewer-but-nonzero errors is no more deliverable than
|
||||||
|
// the natural-FL one, and flying needlessly low isn't the right answer,
|
||||||
|
// so keep the natural route in that case.
|
||||||
|
if low.accepted {
|
||||||
|
result = low;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Only store routes the oracle actually accepted (no-error) — the DB is the
|
// Only store routes the oracle actually accepted (no-error) — the DB is the
|
||||||
// set of IFPS-valid routes, nothing else.
|
// set of IFPS-valid routes, nothing else.
|
||||||
if result.accepted {
|
if result.accepted {
|
||||||
|
|||||||
Reference in New Issue
Block a user