exponenta event banner

Управление воздушным движением

В этом примере показано, как создать сценарий управления воздушным движением, смоделировать радиолокационные обнаружения с радара наблюдения аэропорта (ASR) и настроить глобальный трекер ближайшего соседа (GNN) для отслеживания моделируемых целей с помощью радиолокационных обнаружений. Это позволяет оценить различные целевые сценарии, требования к радарам и конфигурации трекеров без необходимости доступа к дорогостоящему самолету или оборудованию. В этом примере рассматривается весь поток операций с синтетическими данными.

Сценарий управления воздушным движением

Моделирование башни управления воздушным движением (УВД) и движущихся целей в сценарии в качестве платформ. Моделирование движения платформ в сценарии управляется trackingScenario.

Создать trackingScenario и добавьте башню УВД в сценарий.

% Create tracking scenario
scenario = trackingScenario;

% Add a stationary platform to model the ATC tower
tower = platform(scenario);

Радар наблюдения аэропорта

Добавить радар наблюдения аэропорта (ASR) в башню УВД. Типовая башня УВД имеет радар, установленный в 15 метрах над землей. Этот радар сканирует механически по азимуту с фиксированной скоростью для обеспечения 360-градусного покрытия вблизи башни УВД. Перечислены общие спецификации для ASR:

  • Чувствительность: 0 дБсм @ 111 км

  • Механическое сканирование: только азимут

  • Скорость механического сканирования: 12,5 об/мин

  • Электронное сканирование: нет

  • Поле зрения: азимут 1,4 град., отметка 10 град.

  • Разрешение по азимуту: 1,4 град.

  • Разрешение по дальности: 135 м

Моделирование ASR с использованием вышеуказанных спецификаций monostaticRadarSensor.

rpm = 12.5;
fov = [1.4;10];
scanrate = rpm*360/60;  % deg/s
updaterate = scanrate/fov(1); % Hz

radar = monostaticRadarSensor(1, 'Rotator', ...
    'UpdateRate', updaterate, ...           % Hz
    'FieldOfView', fov, ...                 % [az;el] deg
    'MaxMechanicalScanRate', scanrate, ...  % deg/sec
    'AzimuthResolution', fov(1), ...        % deg
    'ReferenceRange', 111e3, ...            % m
    'ReferenceRCS', 0, ...                  % dBsm
    'RangeResolution', 135, ...             % m
    'HasINS', true, ...
    'DetectionCoordinates', 'Scenario');

% Mount radar at the top of the tower
radar.MountingLocation = [0 0 -15];
tower.Sensors = radar;

Наклоните радар так, чтобы он обследовал область, начинающуюся на 2 градуса над горизонтом. Для этого включить отметку и установить пределы механического обзора для охвата поля зрения РЛС, начиная с 2 градусов над горизонтом. Поскольку trackingScenario использует фрейм координат «Север-Восток-Вниз» (NED), отрицательные отметки соответствуют точкам над горизонтом.

% Enable elevation scanning
radar.HasElevation = true;

% Set mechanical elevation scan to begin at 2 degrees above the horizon
elFov = fov(2);
tilt = 2; % deg
radar.MechanicalScanLimits(2,:) = [-fov(2) 0]-tilt; % deg

Установите поле зрения фасада немного большим, чем отметка, охватываемая пределами сканирования. Это предотвращает растровое сканирование на высоте и наклоняет радар к точке в середине пределов сканирования на высоте.

radar.FieldOfView(2) = elFov+1e-3;

monostaticRadarSensor диапазон моделей и смещение возвышения из-за атмосферной рефракции. Эти отклонения становятся более выраженными на меньших высотах и для целей на больших дальностях. Поскольку показатель преломления изменяется (уменьшается) с изменением высоты, радиолокационные сигналы распространяются по криволинейной траектории. Это приводит к тому, что РЛС наблюдает за целями на высотах, превышающих их истинную высоту, и на дальностях, выходящих за пределы их дальности визирования.

Добавить три лайнера в секторе управления УВД. Один авиалайнер подходит к УВД с большой дальности, другой отходит, а третий летит по касательной к башне. Смоделировать движение этих лайнеров на 60-секундном интервале.

trackingScenario использует координатную рамку «Север-Восток-Вниз» (NED). При определении ППМ для авиалайнеров ниже координата z соответствует нисходящей, поэтому высоты над землей устанавливаются на отрицательные значения.

% Duration of scenario
sceneDuration = 60; % s

% Inbound airliner
ht = 3e3;
spd = 900*1e3/3600; % m/s
wp = [-5e3 -40e3 -ht;-5e3 -40e3+spd*sceneDuration -ht];
traj = waypointTrajectory('Waypoints',wp,'TimeOfArrival',[0 sceneDuration]);
platform(scenario,'Trajectory', traj);

% Outbound airliner
ht = 4e3;
spd = 700*1e3/3600; % m/s
wp = [20e3 10e3 -ht;20e3+spd*sceneDuration 10e3 -ht];
traj = waypointTrajectory('Waypoints',wp,'TimeOfArrival',[0 sceneDuration]);
platform(scenario,'Trajectory', traj);

% Tangential airliner
ht = 4e3;
spd = 300*1e3/3600; % m/s
wp = [-20e3 -spd*sceneDuration/2 -ht;-20e3 spd*sceneDuration/2 -ht];
traj = waypointTrajectory('Waypoints',wp,'TimeOfArrival',[0 sceneDuration]);
platform(scenario,'Trajectory', traj);

Отслеживание GNN

Создать trackerGNN для формирования трасс из радиолокационных обнаружений, генерируемых тремя авиалайнерами. Обновите трекер с обнаружениями, сгенерированными после завершения полного сканирования на 360 градусов по азимуту.

Трекер использует initFilter поддерживающая функция для инициализации расширенного фильтра Калмана с постоянной скоростью для каждой новой дорожки. initFilter изменяет фильтр, возвращенный initcvekf для соответствия целевым скоростям и интервалу обновления трекера.

tracker = trackerGNN( ...
    'Assignment', 'Auction', ...
    'AssignmentThreshold',50, ...
    'FilterInitializationFcn',@initFilter);

Визуализация на карте

Вы используете helperATCMap для визуализации результатов поверх отображения карты. Вы позиционируете происхождение местной системы координат Северо-Восток-Даун (NED), используемой башенным радаром и трекером на позиции аэропорта Логан в Бостоне. Начало координат расположено на 42.36306 широте и -71.00639 долготе и 50 метрах над уровнем моря. Помощник предоставляет необходимые утилиты для преобразования координат из NED в координатную рамку с центром Земли, используемую картой.

origin = [42.366978, -71.022362, 50];
mapViewer = helperATCMap('ReferenceLocation',origin);
setCamera(mapViewer, origin + [0 0 1e5]);
showScenario(mapViewer,scenario);
snap(mapViewer);

Имитация и отслеживание авиалайнеров

Следующий цикл продвигает позиции платформы до тех пор, пока не будет достигнут конец сценария. Для каждого шага вперед в сценарии РЛС генерирует обнаружения по целям в поле своего зрения. Трекер обновляется этими обнаружениями после того, как радар завершил сканирование на 360 градусов по азимуту.

% Set simulation to advance at the update rate of the radar
scenario.UpdateRate = radar.UpdateRate;

% Create a buffer to collect the detections from a full scan of the radar
scanBuffer = {};

% Initialize the track array
tracks = [];

% Save visualization snapshots for each scan
allsnaps = {};
scanCount = 0;

% Set random seed for repeatable results
s = rng;
rng(2020)

while advance(scenario)
    
    % Update airliner positions
    plotTarget(mapViewer, scenario.Platforms([2 3 4]));
    
    % Generate detections on targets in the radar's current field of view
    [dets,config] = detect(scenario);
    scanBuffer = [scanBuffer;dets]; %#ok<AGROW>
    % Plot beam and detections
    plotCoverage(mapViewer,coverageConfig(scenario))
    plotDetection(mapViewer,scanBuffer);
    
    
    % Update tracks when a 360 degree scan is complete
    simTime = scenario.SimulationTime;
    isScanDone = config.IsScanDone;
    if isScanDone
        scanCount = scanCount+1;
        % Update tracker
        [tracks,~,~,info] = tracker(scanBuffer,simTime);
        % Clear scan buffer for next scan
        scanBuffer = {};
    elseif isLocked(tracker)
        % Predict tracks to the current simulation time
        tracks = predictTracksToTime(tracker,'confirmed',simTime);
    end
    
    % Update map and take snapshots
    allsnaps = snapPlotTrack(mapViewer,tracks,isScanDone, scanCount, allsnaps);

end
allsnaps = [allsnaps, {snap(mapViewer)}];

Отображение первого снимка, сделанного по завершении второго сканирования радара.

figure
imshow(allsnaps{1});

На предыдущем рисунке показан сценарий в конце второго обзора радара на 360 градусов. Радиолокационные детекторы, показанные как светло-синие точки, присутствуют для каждого из имитируемых авиалайнеров. К этому моменту трекер уже был обновлен одним полным сканированием радара. Внутри трекер инициализировал трассы для каждого из лайнеров. Эти дорожки будут показаны после обновления после этого сканирования, когда дорожки будут повышены до подтвержденных, что соответствует требованию трекера о подтверждении 2 попаданий из 3 обновлений.

Следующие два снимка показывают отслеживание исходящего авиалайнера.

figure
imshow(allsnaps{2});

figure
imshow(allsnaps{3});

Предыдущие рисунки показывают изображение дорожки до и сразу после обновления трекера после второго сканирования радара. Обнаружение на рисунке перед обновлением трекера используется для обновления и подтверждения инициализированной дорожки из предыдущего обнаружения сканирования для данного авиалайнера. На следующем рисунке показано положение и скорость подтвержденной дорожки. Неопределенность оценки положения дорожки показана как серый эллипс. После только двух обнаружений трекер установил точную оценку положения и скорости исходящего авиалайнера. Истинная высота полета авиалайнера составляет 4 км, и он движется на восток со скоростью 700 км/ч.

figure
imshow(allsnaps{4});

figure
imshow(allsnaps{5});

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

figure
imshow(allsnaps{6});

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

truthTrackTable = tabulateData(scenario, tracks) %#ok<NOPTS>
truthTrackTable=3×4 table
    TrackID        Altitude              Heading               Speed      
               True    Estimated    True    Estimated    True    Estimated
    _______    _________________    _________________    _________________

     "T1"      4000      3874        90         89       700        710   
     "T2"      4000      3977         0        358       300        293   
     "T3"      3000      3077         0          0       900        899   

Визуализация дорожек в 3D, чтобы лучше понять предполагаемые высоты.

% Reposition and orient the camera to show the 3-D nature of the map
camPosition = origin + [0.367, 0.495, 1.5e4];
camOrientation = [0, -17, 235]; %Looking south west, 17 degrees below the horizon
setCamera(mapViewer, camPosition, camOrientation);

На рисунке ниже показана 3-D карта сценария. Вы можете видеть смоделированные струи в белых треугольниках с их траекториями, изображенными в виде белых линий. Луч радара показан синим конусом с синими точками, представляющими радиолокационные обнаружения. Дорожки показаны желтым, оранжевым и синим цветом, а их информация указана в соответствующих цветах. Из-за характера 3-D дисплея некоторые маркеры могут быть скрыты за другими.

Для получения различных видов сцены можно использовать следующие элементы управления на карте:

  • Для панорамирования карты щелкните левой кнопкой мыши и перетащите карту.

  • Чтобы повернуть карту, удерживая нажатой кнопку Ctrl, щелкните мышью и перетащите карту.

  • Для увеличения и уменьшения масштаба карты используется колесо прокрутки мыши.

snap(mapViewer);

Резюме

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

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

initFilter

Эта функция изменяет функцию initcvekf для обработки целей с более высокой скоростью, таких как авиалайнеры в сценарии УВД.

function filter = initFilter(detection)
filter = initcvekf(detection);
classToUse = class(filter.StateCovariance);

% Airliners can move at speeds around 900 km/h. The velocity is
% initialized to 0, but will need to be able to quickly adapt to
% aircraft moving at these speeds. Use 900 km/h as 1 standard deviation
% for the initialized track's velocity noise.
spd = 900*1e3/3600; % m/s
velCov = cast(spd^2,classToUse);
cov = filter.StateCovariance;
cov(2,2) = velCov;
cov(4,4) = velCov;
filter.StateCovariance = cov;

% Set filter's process noise to match filter's update rate
scaleAccelHorz = cast(1,classToUse);
scaleAccelVert = cast(1,classToUse);
Q = blkdiag(scaleAccelHorz^2, scaleAccelHorz^2, scaleAccelVert^2);
filter.ProcessNoise = Q;
end

tabulateData

Эта функция возвращает таблицу, сравнивающую истинность земли и дорожки

function truthTrackTable = tabulateData(scenario, tracks)
% Process truth data
platforms = scenario.Platforms(2:end); % Platform 1 is the radar
numPlats = numel(platforms);
trueAlt = zeros(numPlats,1);
trueSpd = zeros(numPlats,1);
trueHea = zeros(numPlats,1);
for i = 1:numPlats
    traj = platforms{i}.Trajectory;
    waypoints = traj.Waypoints;
    times = traj.TimeOfArrival;
    trueAlt(i) = -waypoints(end,3);
    trueVel = (waypoints(end,:) - waypoints(end-1,:)) / (times(end)-times(end-1));
    trueSpd(i) = norm(trueVel) * 3600 / 1000; % Convert to km/h
    trueHea(i) = atan2d(trueVel(1),trueVel(2));
end
trueHea = mod(trueHea,360);

% Associate tracks with targets
atts = [tracks.ObjectAttributes];
tgtInds = [atts.TargetIndex];

% Process tracks assuming a constant velocity model
numTrks = numel(tracks);
estAlt = zeros(numTrks,1);
estSpd = zeros(numTrks,1);
estHea = zeros(numTrks,1);
truthTrack = zeros(numTrks,7);
for i = 1:numTrks
    estAlt(i) = -round(tracks(i).State(5));
    estSpd(i) = round(norm(tracks(i).State(2:2:6)) * 3600 / 1000); % Convert to km/h;
    estHea(i) = round(atan2d(tracks(i).State(2),tracks(i).State(4)));
    estHea(i) = mod(estHea(i),360);
    platID = tgtInds(i);
    platInd = platID - 1;
    truthTrack(i,:) = [tracks(i).TrackID, trueAlt(platInd), estAlt(i), trueHea(platInd), estHea(i), ...
        trueSpd(platInd), estSpd(i)];
end

% Organize the data in a table
names = {'TrackID','TrueAlt','EstimatedAlt','TrueHea','EstimatedHea','TrueSpd','EstimatedSpd'};
truthTrackTable = array2table(truthTrack,'VariableNames',names);
truthTrackTable = mergevars(truthTrackTable, (6:7), 'NewVariableName', 'Speed', 'MergeAsTable', true);
truthTrackTable.(6).Properties.VariableNames = {'True','Estimated'};
truthTrackTable = mergevars(truthTrackTable, (4:5), 'NewVariableName', 'Heading', 'MergeAsTable', true);
truthTrackTable.(4).Properties.VariableNames = {'True','Estimated'};
truthTrackTable = mergevars(truthTrackTable, (2:3), 'NewVariableName', 'Altitude', 'MergeAsTable', true);
truthTrackTable.(2).Properties.VariableNames = {'True','Estimated'};
truthTrackTable.TrackID = "T" + string(truthTrackTable.TrackID);
end

snapPlotTrack

Эта функция управляет перемещением mapViewer камера, создание соответствующих снимков и обновление визуальных объектов дорожки.

function allsnaps = snapPlotTrack(mapViewer,tracks,isScanDone, scanCount,allsnaps)
% Save snapshots during first 4 scans
if isScanDone && any(scanCount == [2 3])
    allsnaps = [allsnaps, {snap(mapViewer)}];
    %move camera
    if scanCount == 2
        % Show the outbound airliner
        setCamera(mapViewer, [42.5650  -70.8990 7e3]);
        allsnaps = [allsnaps, {snap(mapViewer)}];
    end
    
end

% Update display with current track positions
plotTrack(mapViewer,tracks);

if isScanDone && any(scanCount == [2 3])
    % Take a snapshot of confirmed track
    allsnaps = [allsnaps, {snap(mapViewer)}];
    % Reset Camera view to full scene
    if scanCount == 3
        origin = [42.366978, -71.022362, 50];
        setCamera(mapViewer, origin + [0 0 1e5]);
    end
end
end