Расширенное отслеживание объектов с помощью радара для морского наблюдения

Этот пример показывает, как сгенерировать морской сценарий, моделировать радиолокационные обнаружения с морского радара наблюдения и сконфигурировать многоцелевой трекер Hypothesis Density (PHD), чтобы оценить местоположение и размер моделируемых кораблей, используя радиолокационные обнаружения.

Сценарий морского наблюдения

Симулируйте морской радар наблюдения, установленный на верхней части башни с видом на корабли в гавани. Симуляция местоположения башни и движения кораблей в сценарии управляется trackingScenario.

% Create tracking scenario.
scenario = trackingScenario('StopTime',30);

% Define unit conversions.
nmi2m = 1852;           % nautical miles to meters
hr2s = 3600;            % hours to seconds
kts2mps = nmi2m/hr2s;   % knots to meters per second

Радар морского наблюдения

Добавьте морской радар наблюдения на башню. Радар установлен на высоте 20 метров над уровнем моря (ASL). Радар смотрит в гавань, исследуя 30 степени азимутальный сектор. Общие спецификации для морского радара наблюдения перечислены:

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

  • Поле зрения: 30 град азимут, 10 град повышение

  • Азимут Разрешение: 2 град

  • Разрешение в области значений: 5 м

Моделируйте морской радар с вышеуказанными спецификациями, используя fusionRadarSensor.

% Create surveillance radar.
sensor = fusionRadarSensor(1,'No scanning', ...
    'MountingLocation',[0 0 -20], ...      % 20 meters (ASL)
    'MountingAngles',[45 0 0], ...         % [yaw pitch roll] deg
    'FieldOfView',[30 10], ...             % [az el] deg
    'ReferenceRange',5e3, ...              % m
    'AzimuthResolution',2, ...             % deg
    'RangeResolution',5, ...               % m
    'HasINS',true,...                      % Report INS information
    'TargetReportFormat','Detections',...  % Detections without clustering
    'DetectionCoordinates','Sensor spherical');

Добавьте башню в сценарий как стационарную платформу с установленным на верхнюю часть радаром.

platform(scenario,'Sensors',sensor);
tower = scenario.Platforms{1}
tower = 

  Platform with properties:

       PlatformID: 1
          ClassID: 0
         Position: [0 0 0]
      Orientation: [0 0 0]
       Dimensions: [1x1 struct]
             Mesh: [1x1 extendedObjectMesh]
       Trajectory: [1x1 kinematicTrajectory]
    PoseEstimator: [1x1 insSensor]
         Emitters: {}
          Sensors: {[1x1 fusionRadarSensor]}
       Signatures: {[1x1 rcsSignature]  [1x1 irSignature]  [1x1 tsSignature]}

Добавьте три корабля в гавань в секторе наблюдения радара. Два меньших корабля разворачиваются на 20 и 30 узлах, большой корабль движется по постоянному курсу на 10 узлах.

% Define the dimensions for the two small ships.
dim = struct( ...
    'Length',80, ... % m
    'Width',15, ...  % m
    'Height',5, ...  % m
    'OriginOffset', [0 0 5/2]); % [x y z] m

% Model the radar cross section (RCS) of the small ships as 30 dBsm.
rcs = rcsSignature('Pattern',30);

% Create a turning trajectory.
speed = 20;     % knots
initYaw = 130;  % deg
initPos = [1050 790 0];
radius = 200;   % m

initOrient = quaternion([initYaw 0 0], 'eulerd', 'ZYX', 'frame');
initVel = speed*kts2mps*rotatepoint(initOrient,[1 0 0])';
accBody = [0 (speed*kts2mps)^2/radius 0];
angVelBody = [0 0 speed*kts2mps/radius];
traj = kinematicTrajectory('Position',initPos,'Velocity',initVel,'Orientation',initOrient, ...
    'AccelerationSource','Property','Acceleration',accBody, ...
    'AngularVelocitySource','Property','AngularVelocity', angVelBody);

% Add the first small ship, traveling at 20 knots to the scenario. This is
% the closest ship to the radar tower.
platform(scenario,'Dimensions',dim,'Signatures',rcs,'Trajectory',traj);

% Create the other small ship, traveling at 30 knots. This is the ship
% which is farthest from the radar tower.
speed = 30;     % knots
initYaw = 120;  % deg
initPos = [1410 1180 0];
radius = 400;   % m

initOrient = quaternion([initYaw 0 0],'eulerd','ZYX','frame');
initVel = speed*kts2mps*rotatepoint(initOrient,[1 0 0])';
accBody = [0 (speed*kts2mps)^2/radius 0];
angVelBody = [0 0 speed*kts2mps/radius];
traj = kinematicTrajectory('Position',initPos,'Velocity',initVel,'Orientation',initOrient, ...
    'AccelerationSource','Property','Acceleration',accBody, ...
    'AngularVelocitySource','Property','AngularVelocity', angVelBody);

platform(scenario,'Dimensions',dim,'Signatures',rcs,'Trajectory',traj);

% Define the dimensions for the large ship.
dim = struct( ...
    'Length',400, ... % m
    'Width',60, ...   % m
    'Height',15, ...  % m
    'OriginOffset', [0 0 15/2]); % [x y z] m

% Model the radar cross section (RCS) of the large ship as 75 dBsm.
rcs = rcsSignature('Pattern',75);

% Create the large ship's trajectory, traveling at a constant heading at 10 knots.
speed = 10;     % knots
initYaw = -135; % deg
initPos = [1150 1100 0];

initOrient = quaternion([initYaw 0 0],'eulerd','ZYX','frame');
initVel = speed*kts2mps*rotatepoint(initOrient,[1 0 0])';
traj = kinematicTrajectory('Position',initPos,'Velocity',initVel,'Orientation',initOrient, ...
    'AccelerationSource','Property','AngularVelocitySource','Property');

% Add the large ship to the scenario.
platform(scenario,'Dimensions',dim,'Signatures',rcs,'Trajectory',traj);

% Create a display to show the true, measured, and tracked positions of the ships.
theaterDisplay = helperMarineSurveillanceDisplay(scenario, ...
    'IsSea',true,'DistanceUnits','m', ...
    'XLim',450*[-1 1]+1e3,'YLim',450*[-1 1]+1e3,'ZLim',[-1000 10], ...
    'Movie','MarineSurveillanceExample.gif');
slctTrkPos = zeros(3,7); slctTrkPos(1,1) = 1; slctTrkPos(2,3) = 1; slctTrkPos(3,6) = 1;
slctTrkVel = circshift(slctTrkPos,[0 1]);
theaterDisplay.TrackPositionSelector = slctTrkPos;
theaterDisplay.TrackVelocitySelector = slctTrkVel;
theaterDisplay();
snapnow(theaterDisplay);

Multi-Target GGIW-PHD Tracker

Создайте trackerPHD для формирования треков от радиолокационных обнаружений, сгенерированных тремя кораблями в гавани. PHD-трекер позволяет оценивать размер кораблей, позволяя связывать несколько обнаружений с одним объектом. Это важно в таких ситуациях, как морское наблюдение, где размер объектов, обнаруженных датчиком, больше разрешения датчика, что приводит к множественным обнаружениям, сгенерированным вдоль поверхностей кораблей.

Трекер использует filterInitFcn поддерживающая функция для инициализации постоянного фильтра Гамма-Гауссова обратного желания (GGIW) PHD. filterInitFcn добавляет компоненты рождения к интенсивности PHD на каждом временном шаге. Эти компоненты рождения складываются равномерно внутри поля зрения датчика. Их размеры и ожидаемое количество обнаружений определяются с помощью предварительной информации о типах судов, ожидаемых в гавани.

Трекер использует гамма- распределение компонентов GGIW-PHD, чтобы оценить, сколько обнаружений должно быть сгенерировано от объекта. Трекер также вычисляет обнаруживаемость каждого компонента в плотности, используя пределы датчика. Использование trackingSensorConfiguration для моделирования строения датчика для trackerPHD.

% Define radar's measurement limits and resolution.
azLimits = sensor.FieldOfView(1)/2*[-1 1]; % deg
rangeLimits = [0 15e3];                    % m
sensorLimits = [azLimits;rangeLimits];
sensorResolution = [sensor.AzimuthResolution;sensor.RangeResolution];

% Define the sensor's mounting location and orientation on the tower.
params(1) = struct('Frame','Spherical', ...
    'OriginPosition',sensor.MountingLocation(:), ...
    'OriginVelocity',[0;0;0], ...
    'Orientation',rotmat(quaternion(sensor.MountingAngles,'eulerd','zyx','frame'),'frame'),...
    'IsParentToChild', true, ...
    'HasRange',true,'HasElevation',sensor.HasElevation,'HasVelocity',false);

% Define the tower's location, velocity, and orientation in the scenario.
params(2) = struct('Frame','Rectangular', ...
    'OriginPosition',tower.Trajectory.Position(:), ...
    'OriginVelocity',tower.Trajectory.Velocity(:), ...
    'Orientation',rotmat(tower.Trajectory.Orientation,'frame'), ...
    'IsParentToChild', true, ...
    'HasRange',true,'HasElevation',false,'HasVelocity',false);

% Create a trackingSensorConfiguration to model the detectability of the
% tracks by the sensor. The detection probability defines the probability
% of generating at least 1 detection from the extended object.
sensorConfig = trackingSensorConfiguration('SensorIndex',sensor.SensorIndex, ...
    'SensorLimits',sensorLimits,...
    'SensorResolution',sensorResolution,...
    'DetectionProbability',0.99,...
    'SensorTransformParameters',params);

% Fields on the sensor configuration used to update trackingSensorConfiguration.
configFlds = {'SensorIndex','IsValidTime'};

% Noise covariance corresponding to a resolution cell of the radar.
resolutionNoise = diag((sensorResolution/2).^2);

sensorConfig.FilterInitializationFcn = @(varargin)filterInitFcn(varargin{:},params);
sensorConfig.SensorTransformFcn = @ctmeas;
sensorConfig.ClutterDensity = sensor.FalseAlarmRate/(sensor.AzimuthResolution*sensor.RangeResolution);

% Create a PHD tracker using the trackingSensorConfiguration.
tracker = trackerPHD('SensorConfigurations',sensorConfig, ...
    'HasSensorConfigurationsInput',true, ...
    'PartitioningFcn',@(x)partitionDetections(x,1.5,6), ...
    'DeletionThreshold',1e-6,...
    'BirthRate',1e-5);

Моделирование и отслеживание кораблей

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

% Initialize scenario and tracker.
restart(scenario);
reset(tracker);

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

% Set random seed for repeatable results.
rng(2019);

% Run simulation.
snapTimes = [2 7 scenario.StopTime]; % seconds
while advance(scenario)
    % Get current simulation time.
    time = scenario.SimulationTime;

    % Generate detections from the tower's radar.
    [dets,~,config] = detect(tower,time);
    config.SensorIndex = sensor.SensorIndex;

    % Update measurement noise of detections to match radar's resolution.
    dets = updateMeasurementNoise(dets,resolutionNoise);

    % Update tracker.
    trackSensorConfig = computeTrackingSensorConfig(config,configFlds);
    tracks = tracker(dets,trackSensorConfig,time);

    % Update display with current beam position, detections, and track positions.
    theaterDisplay(dets,config,tracks);

    % Take snapshot.
    snapFigure(theaterDisplay,any(time==snapTimes));
end
writeMovie(theaterDisplay);

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

showSnapshot(theaterDisplay,1)

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

showSnapshot(theaterDisplay,2)
axis([1250 1450 1150 1350]); view([-90 90]);

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

showSnapshot(theaterDisplay,3)
axis([650 850 700 900]); view([-90 90]);

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

showSnapshot(theaterDisplay,3)
axis([900 1100 1250 1450]); view([-90 90]);

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

numTrks = numel(tracks);
TrackID = [tracks.TrackID]';
Length = zeros(numTrks,1);
Width = zeros(numTrks,1);
Height = zeros(numTrks,1);
for iTrk = 1:numTrks
    ext = tracks(iTrk).Extent;
    [Q,D] = eig(ext);
    d = 2*sqrt(diag(D));
    iDims = 1:3;

    up = [0 0 -1];
    [~,iUp] = max(abs(up*Q));
    Height(iTrk) = d(iDims(iUp));
    iDims(iUp) = [];

    Length(iTrk) = max(d(iDims));
    Width(iTrk) = min(d(iDims));
end

% Display a table of the estimated dimensions of the ships.
dims = table(TrackID,Length,Width,Height)
dims =

  3x4 table

    TrackID    Length    Width     Height
    _______    ______    ______    ______

       1        102.7    18.213    16.543
       2       472.05     55.85     8.953
       3       97.196     18.57    17.626

Напомним, истинные размерности кораблей даются:

Большой корабль

  • Длина: 400 м

  • Ширина: 60 м

  • Высота: 15 м

Малый Корабль

  • Длина: 80 м

  • Ширина: 15 м

  • Высота: 5 м

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

Сводные данные

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

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

computeTrackingSensorConfig

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

function config = computeTrackingSensorConfig(configIn,flds)
config = struct();
for iFld = 1:numel(flds)
    thisFld = flds{iFld};
    config.(thisFld) = configIn.(thisFld);
end
end

updateMeasurementNoise

Устанавливает шум измерения обнаружений на основе заданной шумовой ковариации.

function dets = updateMeasurementNoise(dets,noise)
    for iDet = 1:numel(dets)
        dets{iDet}.MeasurementNoise(:) = noise(:);
    end
end

filterInitFcn

Изменяет фильтр, возвращенный initctggiwphd для соответствия скоростям и ожидаемому количеству обнаружений для отслеживаемых кораблей.

function phd = filterInitFcn(measParam,varargin)
% This function uses the predictive birth density only to simulate birth in
% the scenario.

if nargin == 1 % Set predictive birth uniformly inside the FOV.
    phdDefault = initctggiwphd;
    % 1. Create uniformly distributed states using Azimuth and Range.
    az = 0; % All components at azimuth.
    ranges = linspace(1000,10000,5); % 5 components for range
    [Az,R] = meshgrid(az,ranges);

    % create a PHD filter to allocate memory.
    phd = ggiwphd(zeros(7,numel(Az)),repmat(eye(7),[1 1 numel(Az)]),...
        'ScaleMatrices',repmat(eye(3),[1 1 numel(Az)]),...
        'StateTransitionFcn',@constturn,'StateTransitionJacobianFcn',@constturnjac,...
        'MeasurementFcn',@ctmeas,'MeasurementJacobianFcn',@ctmeasjac,...
        'PositionIndex',[1 3 6],'ExtentRotationFcn',phdDefault.ExtentRotationFcn,...
        'HasAdditiveProcessNoise',false,'ProcessNoise',2*eye(4),...
        'TemporalDecay',1e3,'GammaForgettingFactors',1.1*ones(1,numel(Az)),...
        'MaxNumComponents',10000);

    for i = 1:numel(Az)
        [sensorX,sensorY,sensorZ] = sph2cart(deg2rad(Az(i)),0,R(i));
        globalPos = measParam(1).Orientation'*[sensorX;sensorY;sensorZ] + measParam(1).OriginPosition(:);
        phd.States([1 3 6],i) = globalPos;
        phd.StateCovariances([1 3 6],[1 3 6],i) = diag([1e5 1e5 1000]); % Cover gaps between components using position covariance
    end

    % 2. You have described the "kinematic" states of each of the ships
    % inside the field of view. Next, add information about their sizes and
    % expected number of detections.
    %
    % It is expected that there are 2 types of ships in the sea, small and
    % large. You create components for each size.
    phdSmall = phd;

    % Clone the PHD filter for large ships.
    phdLarge = clone(phd);

    % Set initial number of components.
    numComps = phdSmall.NumComponents;

    % For small ships, the expected size is about 100 meters in length and
    % 20 meters in width. As the orientation is unknown, we will create 4
    % orientations for each size. First, you must add components to the
    % density at same states. This can be done by simply appending it
    % Setup values for small boats
    append(phdSmall,phdSmall);
    append(phdSmall,phdSmall);

    % Degrees of freedom for defining shape. A large number represents
    % higher certainty in dimensions.
    dof = 1000;

    % Covariance in vx, vy and omega.
    smallStateCov = diag([300 300 50]);

    % Scale matrix for small boats
    smallShape = (dof - 4)*diag([100/2 20/2 10].^2); % l, w and h

    % Create 4 orientations at 45 degrees from each other.
    for i = 1:4
        thisIndex = (i-1)*numComps + (1:numComps);
        R = rotmat(quaternion([45*(i-1) 0 0],'eulerd','ZYX','frame'),'frame');
        phdSmall.ScaleMatrices(:,:,thisIndex) = repmat(R*smallShape*R',[1 1 numComps]);
        phdSmall.StateCovariances([2 4 5],[2 4 5],thisIndex) = repmat(R*smallStateCov*R',[1 1 numComps]);
        phdSmall.StateCovariances([6 7],[6 7],thisIndex) = repmat(diag([100 100]),[1 1 numComps]);
    end

    % Small ships generate approximately 10-20 detections.
    expNumDets = 15;
    uncertainty = 5^2;
    phdSmall.Rates(:) = expNumDets/uncertainty;
    phdSmall.Shapes(:) = expNumDets^2/uncertainty;
    phdSmall.DegreesOfFreedom(:) = dof;

    % Follow similar process for large ships.
    append(phdLarge,phdLarge);
    append(phdLarge,phdLarge);
    largeStateCov = diag([100 5 10]);
    largeShape = (dof - 4)*diag([500/2 100/2 10].^2);
    for i = 1:4
        thisIndex = (i-1)*numComps + (1:numComps);
        R = rotmat(quaternion([45*(i-1) 0 0],'eulerd','ZYX','frame'),'frame');
        phdLarge.ScaleMatrices(:,:,thisIndex) = repmat(R*largeShape*R',[1 1 numComps]);
        phdLarge.StateCovariances([2 4 5],[2 4 5],thisIndex) = repmat(R*largeStateCov*R',[1 1 numComps]);
        phdLarge.StateCovariances([6 7],[6 7],thisIndex) = repmat(diag([100 100]),[1 1 numComps]);
    end

    % Generate approximately 100-200 detections.
    expNumDets = 150;
    uncertainty = 50^2;
    phdLarge.Rates(:) = expNumDets/uncertainty;
    phdLarge.Shapes(:) = expNumDets^2/uncertainty;
    phdLarge.DegreesOfFreedom(:) = dof;

    % Add large ships to small ships to create total density. This density
    % is added to the total density every step.
    phd = phdSmall;
    append(phd,phdLarge);
end

% When called with detection input i.e. the adaptive birth density, do not
% add any new components.
if nargin > 1
    % This creates 0 components in the density.
    phd = initctggiwphd;
end

end