From 937e7ac564b01ef151b6c961a088d87c489fba3a Mon Sep 17 00:00:00 2001 From: jorgecardleitao <149073281+jorgecardleitao@users.noreply.github.com> Date: Sun, 28 Jan 2024 11:25:05 +0100 Subject: [PATCH] Improved computation of the leg (#22) --- methodology.md | 16 ++++++++-------- src/legs.rs | 24 ++++++++++++++++-------- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/methodology.md b/methodology.md index 66b177c..fb3dc36 100644 --- a/methodology.md +++ b/methodology.md @@ -55,16 +55,16 @@ Source code is available at [src/icao_to_trace.rs](./src/icao_to_trace.rs). ### M-4: Identify legs of a route -This is performed automatically by the computer program. A leg is defined in this methodology has: +This is performed automatically by the computer program. A leg is defined in this methodology +has a continuous sequence of ADS-B positions in time where the aircraft is flying. -> a continuous sequence of ADS-B positions split by landings whose distance is higher than 3km and duration longer than 5 minutes +The aircraft at a given segment between two ADS-B positions is considered grounded (not flying) when either: +* both positions are on the ground +* the time between these positions is > 5m and the aircraft is below 10.000 feet -where a landing is identified by either: -* The previous ADS-B position was flying, and the current is grounded -* Both the previous and current position is flying, and are separated by more than 5 minutes apart. - -The latter condition is used to mitigate the risk that ADS-B radars do not always pick up signals -too close from the ground, resulting the leg to not be identified. +The latter condition is used to mitigate the risk that ADS-B receivers sometimes +do not receive an aircraft's signal when the aircraft is at low altitude. +When this happens for more than 5m, we consider that the aircraft approached and landed. Source code is available at [src/legs.rs](./src/legs.rs). diff --git a/src/legs.rs b/src/legs.rs index 9dc91cd..b7c18dd 100644 --- a/src/legs.rs +++ b/src/legs.rs @@ -50,7 +50,19 @@ fn landed(prev_position: &Position, position: &Position) -> bool { ) || (matches!( (&prev_position, &position), (Position::Flying { .. }, Position::Flying { .. }) - ) && position.datetime() - prev_position.datetime() > time::Duration::minutes(5)) + ) && position.datetime() - prev_position.datetime() > time::Duration::minutes(5) + && position.altitude() < 10000.0) +} + +fn is_grounded(prev_position: &Position, position: &Position) -> bool { + matches!( + (&prev_position, &position), + (Position::Grounded { .. }, Position::Grounded { .. }) + ) || (matches!( + (&prev_position, &position), + (Position::Flying { .. }, Position::Flying { .. }) + ) && position.datetime() - prev_position.datetime() > time::Duration::minutes(5) + && position.altitude() < 10000.0) } /// Returns a set of [`Leg`]s from a sequence of [`Position`]s. @@ -62,13 +74,9 @@ pub fn all_legs(mut positions: impl Iterator) -> Vec { let mut sequence: Vec = vec![]; let mut legs: Vec = vec![]; positions.for_each(|position| { - if let (Position::Grounded { .. }, Position::Grounded { .. }) = (&prev_position, &position) - { - // legs are by definition the minimum length on ground - prev_position = position; - return; - }; - sequence.push(position.clone()); + if !is_grounded(&prev_position, &position) { + sequence.push(position.clone()); + } if landed(&prev_position, &position) { legs.push(Leg { positions: std::mem::take(&mut sequence),