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

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

Введение

Посадка - это безопасный критический этап рейса. Самолет при окончательном заходе на посадку должен выровняться по отношению к взлетно-посадочной полосе, постепенно снижаться на землю, и снижать свою наземную скорость при сохранении безопасно выше скорости застоя. Все эти шаги сделаны для того, чтобы самолет тихо касался земли, чтобы уменьшить риск для пассажиров и избежать физического повреждения самолета или взлетно-посадочной полосы. Эти правила могут быть легко определены авиационным профессионалом или они могут быть выведены из отслеживания данных с помощью машинного обучения [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. Каждая путевая точка в траектории возмущается нулевым нормальным распределением и стандартным отклонением, которое становится меньше от первой путевой точки до последней (точки посадки). При первой путевой точке стандартное отклонение составляет 5e-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

Чтобы увидеть, какие возмущенные траектории удовлетворяют правилам безопасного подхода к посадке, вы используете функцию helper 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);

Как и другие крупные аэропорты США, Логан использует Оборудование Обнаружения Поверхности Аэропорта - Модель 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 Функция helper, чтобы сгенерировать предупреждения аномалии для треков. Код функции отображается в нижней части этой страницы.

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

% 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.

Следующий гиф был взят, когда в течение минуты симуляции с 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. Raj Deshmukh and Inseok Hwang, «Anomaly Detection Using Temporal Logic Based Learning for Terminal Airspace Operations», AIAA SciTech Forum, 2019.

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

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

defineTrajectoryRules Задайте правила траектории

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 Валидация треков и правила аномалии

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

анализируйте - анализируйте историю аномалии трека и сравнивайте ее с процентом аномалии истинности

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
Для просмотра документации необходимо авторизоваться на сайте