exponenta event banner

Моделирование, обнаружение и отслеживание аномалий при заходе на посадку

В примере показано, как автоматически обнаруживать отклонения и аномалии в самолетах, выполняющих окончательные подступы к взлетно-посадочной полосе аэропорта. В этом примере вы смоделируете идеальную траекторию захода на посадку и создадите из нее варианты, смоделируете радиолокационные трассы и выдадите предупреждения, как только трассы отклонятся от правил безопасной посадки.

Введение

Посадка является критическим этапом полета. Самолет при конечном заходе на посадку должен совмещаться со взлетно-посадочной полосой, постепенно опускаться на землю и снижать свою наземную скорость, надежно удерживая ее выше скорости остановки. Все эти шаги выполняются для обеспечения того, чтобы самолет мягко касался земли, чтобы уменьшить риск для пассажиров и избежать физического повреждения самолета или взлетно-посадочной полосы. Эти правила могут быть легко определены авиационным специалистом или выведены из данных отслеживания с помощью машинного обучения [1]. В этом примере предполагается, что правила уже определены.

Основные аэропорты обычно имеют несколько взлетно-посадочных полос, ориентированных в разных направлениях. Приближающиеся самолеты направляются авиадиспетчерами в башне аэропорта для посадки на одну из взлетно-посадочных полос, которая лучше всего выравнивается по направлению ветра в это время. При заходе на посадку контролеры осуществляют контроль самолета на основе систем слежения. За последние десятилетия объем перевозок в аэропортах увеличился, а также возросла нагрузка на авиадиспетчеров. В результате возникает необходимость в автоматическом и надёжном оповещении авиадиспетчеров о самолётах, которые приближаются к точке посадки небезопасным образом: плохо выровнены с ВПП, слишком быстро или слишком медленно снижаются или слишком быстро или слишком медленно приближаются.

Генерировать и маркировать истины

Вы определяете траекторию захода на посадку в международный аэропорт Логан в Бостоне, Массачусетс с помощью geoTrajectory объект. Путевые точки траектории выровнены с 22L ВПП, которая проходит с северо-востока на юго-запад, и глиссадой 3 градуса. Время прибытия и скорость набора высоты определяются для замедления приближающегося самолета до безопасной скорости и плавного приземления. При этом положительное значение скорости набора высоты используется для нисходящей траектории. Вы используете helperPertScenarioGlobeViewer (см. вспомогательный файл) для визуализации траектории на карте.

baselineApproachTrajectory = geoTrajectory([42.7069 -70.8395 1500; 42.5403 -70.9203 950; 42.3736 -71.001 0],[0;180;400],...
    'ClimbRate', [6; 3.75; 3.75]);

viewer = helperPertScenarioGlobeViewer;
viewer.TargetHistoryLength = 0;
viewer.TrackHistoryLength = 0;
viewer.TrackLabelScale = 0.75;
positionCamera(viewer, [42.3072 -70.8463 12455], [0 -34 335]);
plotTrajectory(viewer, baselineApproachTrajectory, 'Color', [15 255 255]/255, "Width", 1);

Чтобы траектория, поступающая на посадку в аэропорту Логан на ВПП 22L была безопасной, траектория должна удовлетворять следующим правилам:

  • Траектория должна быть тесно совмещена с направлением взлетно-посадочной полосы.

  • Наклон глиссады должен быть между 2,5 и 4 градусами в последние 20963 метра. На расстояниях выше 20963 метров высота должна быть не менее 3000 фт.

  • Скорость должна быть между 120 узлами и 180 узлами в точке посадки. Верхняя граница скорости может увеличиваться линейно с расстоянием от точки посадки.

Эти правила определяются с помощью helperTrajectoryValidationRule (см. вспомогательный файл) и визуализируйте правила на карте.

% Define and show trajectory rules.
trajRules = defineTrajectoryRules();
showRules(viewer, trajRules)
snap(viewer)

Вы используете perturbations функция объекта для определения нормального распределения вокруг базовой траектории, approachTrajectory. Каждый ППМ на траектории возмущается нулевым средним нормальным распределением и стандартным отклонением, которое становится меньше от первого ППМ к последнему (точка посадки). В первом ППМ стандартное отклонение составляет 5е-3 градуса по долготе и 300 метров по высоте. Стандартное отклонение уменьшается до 1e-3 градусов по долготе и 150 метров по высоте в средней точке и затем до 1e-4 градусов по долготе и 0 по высоте в конечной точке на земле.

% Define perturbation to the approach trajectory
perturbations(baselineApproachTrajectory, 'Waypoints', 'Normal', zeros(3,3), [0 5e-3 300; 0 1e-3 150; 0 1e-4 0]);

Чтобы создать 20 траекторий, возмущенных от базовой траектории, сначала clone траектория, а затем perturb это.

% Generate perturbed trajectories
s = rng(2021, 'twister'); % Set random noise generator for repeatable results
numTrajectories = 20;
trajectories = cell(1,numTrajectories);
for i = 1:numTrajectories
    trajectories{i} = clone(baselineApproachTrajectory);
    perturb(trajectories{i});
end

Чтобы увидеть, какие возмущенные траектории удовлетворяют правилам безопасного подхода к посадке, используйте функцию помощника validateTrajectory, в нижней части этой страницы. Функция объявляет траекторию аномальной, если хотя бы 1% точек, выбранных из нее, нарушают правило траектории.

[truthAnomalyFlags, truthPercentAnomalousSteps] = validateTrajectory(trajectories, trajRules);

Постройте график траекторий желтым для аномальных траекторий и голубым для безопасных подходов. В целом, существует 7 аномальных траекторий из 20 сгенерированных траекторий.

plotTrajectory(viewer, trajectories(truthAnomalyFlags), 'Color', [255 255 17]/255, "Width", 1);
plotTrajectory(viewer, trajectories(~truthAnomalyFlags), 'Color', [15 255 255]/255, "Width", 1);
positionCamera(viewer, [42.4808 -70.916 1136], [0 0 340]);
snap(viewer)

Определение сценария

Обнаружение аномалий в реальном времени на основе данных отслеживания является проблемой по нескольким причинам. Во-первых, поскольку данные отслеживания несовершенны с шумом, результаты отслеживания неопределенны. В результате необходимо предусмотреть некоторые допуски, чтобы избежать выдачи ложных предупреждений. Во-вторых, датчики сообщают о ложных обнаружениях, и система слежения должна быть осторожна, чтобы не подтверждать следы на основе этих ложных обнаружений. Тщательное подтверждение требует, чтобы системе отслеживания требовалось больше времени для подтверждения дорожек. Во избежание чрезмерных предупреждений на ложных дорожках предупреждения выдаются только после подтверждения дорожки.

Определяется сценарий отслеживания, ориентированный на Землю.

% Create an Earth-centered tracking scenario
scenario = trackingScenario('UpdateRate', 1, 'IsEarthCentered', true, 'InitialAdvance', 'UpdateInterval');

Самолёты, приближающиеся к посадке в аэропорту, планируются для избежания аэродинамического удара от одного самолёта на следующий по его следу. Минимальная безопасная разница во времени между двумя самолетами составляет одну минуту.

Вы используете perturbations и perturb снова функции объекта для возмущения TimeOfArrival каждой траектории и убедиться в отсутствии дополнительных возмущений Waypoints. Затем вы прикрепляете каждую траекторию к новой платформе. Для возмущения всего сценария используется perturb объектная функция.

% Schedule the trajectories and attach each to a platform.
for i = 1:numTrajectories
    perturbations(trajectories{i}, 'TimeOfArrival', 'Uniform',(i-1)*60, (i-1)*60+10);
    perturbations(trajectories{i}, 'Waypoints', 'None');
    platform(scenario, 'Trajectory', trajectories{i});
end
perturb(scenario);

Как и другие крупные аэропорты США, Logan использует оборудование для обнаружения поверхности в аэропорту - Model X (ASDE-X) для отслеживания самолетов во время окончательного захода на посадку и на земле [2]. ASDE-X опирается на радар наблюдения аэропорта, автоматические зависимые отчеты наблюдения-вещания (ADS-B) с приближающегося самолета и другие методы обеспечения точного слежения, которые обновляются каждую секунду (подробнее см. [1]).

Для упрощения модели этой системы слежения используется статистическая радиолокационная модель, monostaticRadarSensor, прикрепленный к башне аэропорта и соединяющий датчик с trackerGNN объект. Вы настраиваете трекер консервативно относительно подтверждения треков, установив ConfirmationThreshold чтобы подтвердить, получает ли трек обновления 4 из 5.

asdex = monostaticRadarSensor(1, ...
    'ScanMode', 'No Scanning', ...
    'MountingAngles', [0 0 0], ...
    'FieldOfView', [360;20], ...
    'UpdateRate', 1, ...
    'ReferenceRange', 40000,...
    'RangeResolution', 100, ...
    'HasElevation', true, ...
    'HasINS', true, ...
    'DetectionCoordinates', 'Scenario', ...
    'FalseAlarmRate', 1e-7, ...
    'ElevationResolution', 0.4, ...
    'AzimuthResolution', 0.4);
p = platform(scenario, 'Position', [42.3606 -71.011 0], 'Sensors', asdex);
tracker = trackerGNN("AssignmentThreshold", [100 2000], "ConfirmationThreshold", [4 5]);
tam = trackAssignmentMetrics('AssignmentThreshold', 100, 'DivergenceThreshold', 200);

Выполнение сценария и обнаружение аномальных дорожек

В следующих строках моделируется сценарий и отслеживается приближающийся самолет. Вы используете validateTracks вспомогательная функция для генерации предупреждений об аномалии для дорожек. Код функции можно просмотреть в нижней части этой страницы.

Дорожки, нарушающие правила безопасного подхода, отображаются желтым цветом, а дорожки, соответствующие этим правилам, - голубым. Обратите внимание, что предупреждение выдается немедленно, когда дорожка нарушает любое правило и удаляется, когда она удовлетворяет всем правилам.

% Clean the display and prepare it for the simulation.
clear(viewer)
positionCamera(viewer, [42.3072 -70.8463 12455], [0 -34 335]);
showRules(viewer, trajRules)
snaptime = 930;
clear validateTracks

% Main loop
while advance(scenario)
    % Collect detections
    dets = detect(scenario);
    
    % Update the tracker and output tracks.
    if ~isempty(dets) || isLocked(tracker)
        tracks = tracker(dets, scenario.SimulationTime);
    else
        tracks = objectTrack.empty;
    end
    
    % Get platform poses and assignment between tracks and truths.
    poses = platformPoses(scenario,"Quaternion","CoordinateSystem","Cartesian");
    tam(tracks,poses);
    [assignedTrackIDs, assignedTruthIDs] = currentAssignment(tam);
    
    % Validate the tracks with rules to find anomalous tracks.
    [tracks, trackAnomalyHistory] = validateTracks(tracks, trajRules, assignedTrackIDs, assignedTruthIDs);
    
    % Visualize
    updateDisplay(viewer,scenario.SimulationTime,[scenario.Platforms{:}],dets,[],tracks);
end
rng(s); % Reset the random number generator to its value before running the example.

Следующий gif был принят в течение минуты моделирования от 900 секунд до 960 секунд. Он показывает дорожки, идентифицированные как безопасные в голубом, и дорожки, идентифицированные как аномальные в желтом. Эта идентификация выполняется на каждом этапе моделирования, как можно видеть для дорожки 3661.

Сравнить отчеты об аномалиях с правдой

Чтобы убедиться, что предупреждения об аномалиях были выданы для правильных дорожек, используйте analyze вспомогательная функция, показанная в нижней части этой страницы.

Функция использует trackAnomalyHistory собранный во время моделирования и сравнивает его с truthPercentAnomalousSteps рассчитано для каждой траектории. Подобно истине, трекам присваиваются флаги аномалии, если они были объявлены аномальными не менее 1% временных шагов. Вы можете видеть, что аномалии выданы правильно для семи траекторий, которые были признаны аномальными.

comparisonTable = analyze(trackAnomalyHistory ,truthPercentAnomalousSteps);
disp(comparisonTable)
    TruthID    Truth Anomaly Flag    Track Anomaly Flag
    _______    __________________    __________________

       1             false                 false       
       2             false                 false       
       3             false                 false       
       4             false                 false       
       5             false                 false       
       6             false                 false       
       7             true                  true        
       8             true                  true        
       9             false                 false       
      10             true                  true        
      11             false                 false       
      12             false                 false       
      13             true                  true        
      14             true                  true        
      15             false                 false       
      16             false                 false       
      17             false                 false       
      18             false                 false       
      19             true                  true        
      20             true                  true        

Резюме

В этом примере показано, как использовать данные отслеживания для генерации предупреждений в реальном времени о таких аномалиях, как небезопасный подход к посадке.

Вы использовали geoTrajectory определение идеальной траектории захода на посадку в географических координатах. Затем вы использовали perturbations и perturb для создания 20 траекторий, которые отклоняются от идеальной траектории захода на посадку, и для планирования траекторий одна за другой в trackingScenario. Чтобы смоделировать систему слежения за аэропортом, вы упростили модель системы, используя модель статистического радара, с помощью monostaticRadarSensor Системный объект и трекер по trackerGNN Системный объект.

Ссылки

  1. Радж Дешмух и Инсеок Хванг, «Обнаружение аномалий с использованием обучения на основе временной логики для операций в воздушном пространстве терминала», AIAA SciTech Forum, 2019.

  2. Федеральное управление гражданской авиации, «Фактологический бюллетень - Оборудование для обнаружения поверхности в аэропорту, модель X (ASDE-X)». https://www.faa.gov/news/fact_sheets/news_story.cfm?newsId=17095 получен в мае 2020 года.

Вспомогательные функции

defineTrajectiveRules Определение правил траектории

function trajRules = defineTrajectoryRules
% This function defines rules for safe approach to landing on runway 22L at
% Logan International Airport in Boston, MA.

% The function uses the helperTrajectoryValidationRule attached as a
% supporting file to this example

% The trajectory must be closely aligned with the runway direction.
longitudeRule = helperTrajectoryValidationRule([42.37 42.71], [0.4587, -90.4379], [0.5128, -92.730]);

% The glide slope must be between 2.5 and 4 degrees in the last 20963
% meters. At distances above 20963 meters, the altitude must be at least
% 3000 ft. The rules are relative to range from the runway landing point.
altitudeRule1 = helperTrajectoryValidationRule([100 20963], [sind(2.5) 0], [sind(4) 0]); 
altitudeRule2 = helperTrajectoryValidationRule([20963 40000], 3000 * 0.3048, [sind(4) 0]); 

% The speed must be between 120 knots and 180 knots at the landing point.
% The upper speed bound can increase linearly with distance from the
% landing point.
speedRule = helperTrajectoryValidationRule([0 40000], 61.733, [1e-3 100]);

% Collect all the rules.
trajRules = [longitudeRule;altitudeRule1;altitudeRule2;speedRule];
end

validateTrajectory Проверка каждой траектории

function [truthAnomalyFlags, percentAnomalousSteps] = validateTrajectory(trajectories, rules)
numTrajectories = numel(trajectories);
numAnomalousSteps = zeros(1, numTrajectories);
for tr = 1:numTrajectories
    if iscell(trajectories)
        traj = trajectories{tr};
    elseif numTrajectories == 1
        traj = trajectories;
    else
        traj = trajectories(tr);
    end
    timesamples = (traj.TimeOfArrival(1):traj.TimeOfArrival(end));
    [pos,~,vel] = lookupPose(traj, timesamples);
    posECEF = lookupPose(traj, timesamples, 'ECEF');
    landingPoint = [1.536321  -4.462053   4.276352]*1e6;
    
    for i = 1:numel(timesamples)
        distance = norm(posECEF(i,:) - landingPoint);
        isLongitudeValid = validate(rules(1),pos(i,1),pos(i,2));
        isAltitudeValid = (validate(rules(2),distance,pos(i,3)) && validate(rules(3),distance,pos(i,3)));
        isSpeedValid = validate(rules(4),distance,norm(vel(i,:)));
        isValid = isLongitudeValid && isAltitudeValid && isSpeedValid;
        numAnomalousSteps(tr) = numAnomalousSteps(tr) + ~isValid;
    end
end
percentAnomalousSteps = numAnomalousSteps ./ numel(timesamples) * 100;
truthAnomalyFlags = (percentAnomalousSteps > 1);
end

validateTrack Validate tracks vs правила аномалии

function [tracks, history] = validateTracks(tracks, rules, assignedTrackIDs, assignedTruthIDs)
persistent trackAnomalyHistory
if isempty(trackAnomalyHistory)
    trackAnomalyHistory = repmat(struct('TrackID', 0, 'AssignedTruthID', 0, 'NumSteps', 0, 'NumAnomalousSteps', 0),30,1);
end

posECEF = getTrackPositions(tracks, [1 0 0 0 0 0; 0 0 1 0 0 0; 0 0 0 0  1 0]);
pos = fusion.internal.frames.ecef2lla(posECEF);
vel = getTrackVelocities(tracks, [0 1 0 0 0 0; 0 0 0 1 0 0; 0 0 0 0 0 1]);
numTracks = numel(tracks);
landingPoint = [1.536321  -4.462053   4.276352]*1e6;

trackIDs = [trackAnomalyHistory.TrackID];

for tr = 1:numTracks
    % Only validate tracks if altitude is greater than 0
    if pos(tr,3) > 15
        distance = norm(posECEF(tr,:) - landingPoint);
        isLongitudeValid = validate(rules(1),pos(tr,1),pos(tr,2));
        isAltitudeValid = (validate(rules(2),distance,pos(tr,3)) && validate(rules(3),distance,pos(tr,3)));
        isSpeedValid = validate(rules(4),distance,norm(vel(tr,:)));
        isValid = isLongitudeValid && isAltitudeValid && isSpeedValid;
    else
        isValid = true;
    end
    
    tracks(tr).ObjectClassID = uint8(~isValid) + uint8(isValid)*6; % To get the right color for tracks
    
    % Update anomlay history
    inHistory = (tracks(tr).TrackID == trackIDs);
    if any(inHistory)
        trackAnomalyHistory(inHistory).NumSteps = trackAnomalyHistory(inHistory).NumSteps + 1;
        trackAnomalyHistory(inHistory).NumAnomalousSteps = trackAnomalyHistory(inHistory).NumAnomalousSteps + ~isValid;
    else
        ind = find(trackIDs == 0, 1, 'first');
        trackAnomalyHistory(ind).AssignedTruthID = assignedTruthIDs(tracks(tr).TrackID == assignedTrackIDs);
        trackAnomalyHistory(ind).TrackID = tracks(tr).TrackID;
        trackAnomalyHistory(ind).NumSteps = 1;
        trackAnomalyHistory(ind).NumAnomalousSteps = ~isValid;
    end
end
history = trackAnomalyHistory;
end

analyze - анализ истории аномалий отслеживания и сравнение ее с процентом аномалий истинности;

function comparisonTable = analyze(trackAnomalyHistory, percentTruthAnomalous)
trackAnomalyHistory = trackAnomalyHistory([trackAnomalyHistory.TrackID] > 0);
anomalousSteps = [trackAnomalyHistory.NumAnomalousSteps];
numSteps = [trackAnomalyHistory.NumSteps];
trackAssignedTruths = [trackAnomalyHistory.AssignedTruthID];
assignedTruths = unique(trackAssignedTruths);
numTrackAnomalousSteps = zeros(numel(assignedTruths),1);
numTrackSteps = zeros(numel(assignedTruths),1);

for i = 1:numel(assignedTruths)
    inds = (assignedTruths(i) == trackAssignedTruths);
    numTrackAnomalousSteps(i) = sum(anomalousSteps(inds));
    numTrackSteps(i) = sum(numSteps(inds));
end
percentTrackAnomalous = numTrackAnomalousSteps ./ numTrackSteps * 100;
trueAnomaly = (percentTruthAnomalous > 1)';
anomalyFlags = (percentTrackAnomalous > 1);
comparisonTable = table((1:20)',trueAnomaly, anomalyFlags,...
    'VariableNames', {'TruthID', 'Truth Anomaly Flag', 'Track Anomaly Flag'});
end