Пример показывает, как автоматически обнаружить отклонения и аномалии в самолетах, совершающих окончательные подходы к взлетно-посадочной полосе аэропорта. В этом примере вы смоделируете идеальную траекторию захода на посадку и сгенерируете из нее варианты, симулируете радарные дорожки и выдаете предупреждения, как только пути отклоняются от правил безопасной посадки.
Посадка - это безопасный критический этап рейса. Самолет при окончательном заходе на посадку должен выровняться по отношению к взлетно-посадочной полосе, постепенно снижаться на землю, и снижать свою наземную скорость при сохранении безопасно выше скорости застоя. Все эти шаги сделаны для того, чтобы самолет тихо касался земли, чтобы уменьшить риск для пассажиров и избежать физического повреждения самолета или взлетно-посадочной полосы. Эти правила могут быть легко определены авиационным профессионалом или они могут быть выведены из отслеживания данных с помощью машинного обучения [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
Системный объект.
Raj Deshmukh and Inseok Hwang, «Anomaly Detection Using Temporal Logic Based Learning for Terminal Airspace Operations», AIAA SciTech Forum, 2019.
Федеральное управление авиации, «Информационный бюллетень - Оборудование для обнаружения поверхности аэропорта, модель 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