В примере показано, как автоматически обнаруживать отклонения и аномалии в самолетах, выполняющих окончательные подступы к взлетно-посадочной полосе аэропорта. В этом примере вы смоделируете идеальную траекторию захода на посадку и создадите из нее варианты, смоделируете радиолокационные трассы и выдадите предупреждения, как только трассы отклонятся от правил безопасной посадки.
Посадка является критическим этапом полета. Самолет при конечном заходе на посадку должен совмещаться со взлетно-посадочной полосой, постепенно опускаться на землю и снижать свою наземную скорость, надежно удерживая ее выше скорости остановки. Все эти шаги выполняются для обеспечения того, чтобы самолет мягко касался земли, чтобы уменьшить риск для пассажиров и избежать физического повреждения самолета или взлетно-посадочной полосы. Эти правила могут быть легко определены авиационным специалистом или выведены из данных отслеживания с помощью машинного обучения [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 Системный объект.
Радж Дешмух и Инсеок Хванг, «Обнаружение аномалий с использованием обучения на основе временной логики для операций в воздушном пространстве терминала», AIAA SciTech Forum, 2019.
Федеральное управление гражданской авиации, «Фактологический бюллетень - Оборудование для обнаружения поверхности в аэропорту, модель 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