trackingIMM
ФильтрВ этом примере показано, как сглаживать оценки состояния цели с помощью smooth
объектная функция. Сглаживание является методом, чтобы совершенствовать предыдущие оценки состояния с помощью актуальных измерений и информации об оценке состояния. В этом примере вы изучите, как улучшить ранее откорректированные оценки от фильтра Взаимодействующей мультимодели (IMM) путем выполнения обратной рекурсии, которая производит сглаживавшие и более точные оценки состояния. В первом разделе вы реализуете сглаженный алгоритм, чтобы сглаживать траекторию поворачивающегося автомобиля. В оставшейся части этого примера вы выполняете сглаживание на нескольких высоко маневрирующих траекториях самолета, взятых из Траекторий Сравнительного теста для примера Отслеживания Мультиобъекта.
В этом разделе вы сглаживаете оценку траектории поворачивающегося автомобиля. Во-первых, вы используете helperGenerateCarMeasurements
функция, чтобы сгенерировать измерения положения автомобиля и соответствующей истины.
rng(2021); % For repeatable results % Generate measurements for a car taking a turn [measPositionCar, trueStateCar, timeCar] = helperGenerateCarMeasurements(); % Define the initial detection in the format of objectDetection detection = objectDetection(0, [0;0;0], 'MeasurementNoise', eye(3,3));
Используя initekfimm
функция инициализации, вы создаете фильтр IMM на основе постоянной скорости, постоянного ускорения и постоянных моделей движения поворота. Чтобы установить фильтр для обратного сглаживания, вы устанавливаете EnableSmoothing
свойство фильтра к true
. Поскольку вы хотите выполнить фиксированный интервал, сглаживая (оффлайн сглаживающий) на оценках состояния, который использует все откорректированные и предсказанные шаги, вы устанавливаете MaxNumSmoothingSteps
свойство к количеству шагов измерения.
defaultIMMCar = initekfimm(detection); % Enable Smoothing defaultIMMCar.EnableSmoothing = true; defaultIMMCar.MaxNumSmoothingSteps = size(measPositionCar,1); % Initilaize IMM positionSelector = [1 0 0 0 0 0;0 0 1 0 0 0;0 0 0 0 1 0]; % Select position from state initialState = positionSelector' * measPositionCar(1,:)'; initialCovariance = diag([1,1e4,1,1e4,1,1e4]); initialize(defaultIMMCar, initialState, initialCovariance);
Чтобы получить прямые оценки автомобиля, вы запускаете фильтр путем итеративного предсказания и исправления оценок состояния.
% Initialize the corrected states numSteps = numel(timeCar); correctState = zeros(6,numSteps); correctStateCovariance = zeros(6,6,numSteps); correcState(:,1) = defaultIMMCar.State; correctStateCovariance(:,:,1) = defaultIMMCar.StateCovariance; % Forward tracking with prediction and correction for i = 2:numSteps dt = timeCar(i) - timeCar(i-1); predict(defaultIMMCar, dt); [correctState(:,i), correctStateCovariance(:,:,i)] = correct(defaultIMMCar, measPositionCar(i,:)); end
Чтобы выполнить сглаживание, просто вызовите smooth
объектная функция фильтра. Функция возвращает сглаживавшие состояния, ковариацию состояния и вероятности модели.
[smoothState, smoothStateCovariance, modelProbabilities] = smooth(defaultIMMCar);
Затем используйте helperTrajectoryViewer
функция, чтобы визуализировать сглаженные результаты и ошибки RMS. Результаты показывают, что использование оффлайнового сглаживания фильтра IMM позволяет вам уменьшать ошибки в оценках.
trajNum = 0; helperTrajectoryViewer(trajNum,timeCar,correctState, smoothState, trueStateCar, measPositionCar);
В этом разделе вы сглаживаете траектории шести высоко маневрирующих самолетов. Траектории, используемые в этом разделе, совпадают с теми в Траекториях Сравнительного теста для примера Отслеживания Мультиобъекта. В примере ускорение самолета изменяет целых 35 во время некоторых маневров. Вы используете helperGenerateAircraftTrajMeasurements
функция, чтобы сгенерировать данные об измерении и истину.
[measPosition, trueState, time] = helperGenerateAircraftTrajMeasurements;
Конфигурируйте фильтр IMM, подобный как предыдущий раздел.
% Define initial detection detection = objectDetection(0, [0;0;0], 'MeasurementNoise', eye(3,3)); defaultIMMAircraft = initekfimm(detection); % Enable Smoothing defaultIMMAircraft.EnableSmoothing = true; defaultIMMAircraft.MaxNumSmoothingSteps = size(measPosition,1);
Используя helperGenerateSmoothData
функция, вы запускаете созданный фильтр IMM, получаете откорректированные оценки состояния и генерируете сглаживавшие оценки состояния для первой траектории.
% Only estimate the first trajectory trajNum = 1; % Extract measurement data measPosTraj = measPosition(:,:,trajNum); % Estimate and smooth the trajectory using the helperGenerateSmoothData function [correctState, correctStateCovariance, smoothState, smoothStateCovariance] = helperGenerateSmoothData(defaultIMMAircraft,measPosTraj,time);
Визуализируйте прямую оценку и сглаживающие результаты с помощью helperTrajectoryViewer
funciton.
helperTrajectoryViewer(trajNum,time,correctState, smoothState, trueState(:,:,trajNum), measPosTraj);
Как замечено по результатам, процесс сглаживания выполняет плохо и становится нестабильными близкими 120 секундами. Это происходит в основном из-за недостаточного шума процесса в фильтре IMM. Быстрые изменения на ускорении самолета и крутые повороты в коротких интервалах требуют более высокого шума процесса для постоянного ускорения и постоянных моделей движения поворота фильтра IMM.
В этом разделе вы настраиваете шум процесса фильтра для лучшей оценки и сглаживающих результатов. Во-первых, создайте постоянную скорость, постоянное ускорение и постоянную модель угловой скорости вращения, которая будет использоваться в фильтре IMM.
constVelocityEKF = initcvekf(detection); constantAccelerationEKF = initcaekf(detection); constantTurnEKF = initctekf(detection);
Чтобы компенсировать скоростную неопределенность, увеличьте шум процесса постоянной скоростной модели во всех трех осях на основе оценок изменения в скоростных значениях маневрирующей цели. Точно так же, чтобы компенсировать ускоряющую неопределенность, увеличьте шум процесса для постоянной ускоряющей модели во всех трех осях на основе оценки изменения в ускоряющих значениях цели manuvering. Чтобы компенсировать поворачивающуюся неопределенность уровня, увеличьте шум процесса для угловой скорости вращения модели постоянного поворота.
constantVelocityEKF.ProcessNoise = 36*eye(3,3); constantAccelerationEKF.ProcessNoise = 100*eye(3,3); constantTurnEKF.ProcessNoise = 36*eye(4,4);
Создайте фильтр IMM с помощью трех заданных фильтров оценки и включите возможность сглаживания.
filters = {constVelocityEKF;constantAccelerationEKF;constantTurnEKF};
imm = trackingIMM(filters,'TransitionProbabilities', 0.99);
imm.EnableSmoothing = true;
imm.MaxNumSmoothingSteps = size(measPosition,1);
Используйте фильтр, чтобы оценить траектории шести самолетов один за другим и получить сглаживавшие оценки. Визуализируйте результаты для каждой траектории.
for i = 1:6 trajNum = i; measPosTraj = measPosition(:,:,trajNum); [correctState, correctStateCovariance, smoothState, smoothStateCovariance] = helperGenerateSmoothData(clone(imm),measPosTraj,time); % Visualize the results for each trajectory helperTrajectoryViewer(trajNum, time, correctState, smoothState, trueState(:,:,trajNum), measPosTraj) end
От результатов использование настроенного шума процесса значительно уменьшает ошибки расчета по сравнению с предыдущими результатами сглаживания, не настраивая шум процесса.
В этом примере вы изучили, как сглаживать результаты фильтра получить лучшие оценки состояния. Вы также изучаете важность настраивающего шума фильтра правильно для ваших определенных приложений.
helperGenerateCarMeasurements
Сгенерируйте входные параметры измерения для траектории поворачивающегося автомобиля
function [measPosition, trueState, time] = helperGenerateCarMeasurements() % Create a trajectory of a car taking a turn. carWayPoints = [6 2 0; 18 4 0; 25 7 0; 28 10 0; 31 15 0; 33 22 0]; timeSteps = [0 2 4 6 8 10]; % Scenario Generation. scene = trackingScenario('UpdateRate',20); plat = platform(scene); plat.Trajectory = waypointTrajectory(carWayPoints, timeSteps); % Create trajectory using waypoints from the scenario. numSteps = 0; truePosition = []; trueVelocity = []; trueAcceleration = []; time = []; while advance(scene) poses = platformPoses(scene); t = scene.SimulationTime; numSteps = numSteps + 1; truePosition(numSteps,1:3) = poses.Position; trueVelocity(numSteps,1:3) = poses.Velocity; trueAcceleration(numSteps,1:3) = poses.Acceleration; time(numSteps) = t; end trueState = [truePosition(:,1,:),trueVelocity(:,1,:),truePosition(:,2,:),trueVelocity(:,2,:),truePosition(:,3,:),trueVelocity(:,3,:)]; % Add measurement noise to true position. measNoise = 1* randn(size(truePosition)); measPosition = truePosition + [measNoise(:,1:2), zeros(numSteps,1)]; end
Сгенерируйте входные параметры измерения для траекторий нескольких самолетов
function [measPosition, trueState, time] = helperGenerateAircraftTrajMeasurements() % Load trajectory waypoints and velocities. The file contains tables of waypoints and % velocities (in units of meters and meters per second) that are used to reconstruct six aircraft trajectories. load('benchmarkTrajectoryTables.mat', 'trajTable'); % Scenario generation. scene = trackingScenario('UpdateRate',10); % Assign each platform with a trajectory for n=1:6 plat = platform(scene); traj = trajTable{n}; plat.Trajectory = waypointTrajectory(traj.Waypoints, traj.Time, 'Velocities', traj.Velocities); end % Create trajectory using waypoints from the scenario. numSteps = 0; truePosition = []; trueVelocity = []; trueAcceleration = []; time = []; while advance(scene) poses = platformPoses(scene); t = scene.SimulationTime; numSteps = numSteps + 1; position = vertcat(poses.Position); velocity = vertcat(poses.Velocity); acceleration = vertcat(poses.Acceleration); truePosition(numSteps,1:3,1:6) = permute(position,[3 2 1]); trueVelocity(numSteps,1:3,1:6) = permute(velocity,[3 2 1]); trueAcceleration(numSteps,1:3,1:6) = permute(acceleration,[3 2 1]); time(numSteps) = t; end trueState = [truePosition(:,1,:),trueVelocity(:,1,:),truePosition(:,2,:),trueVelocity(:,2,:),truePosition(:,3,:),trueVelocity(:,3,:)]; % Define the measurements to be the position and add normal random noise with a standard deviation of 0.1 to the measurements. measNoise = 0.1* randn(size(truePosition)); measPosition = truePosition + measNoise; end
Сгенерируйте откорректированные и сглаживавшие состояния
function [correctState, correctStateCovariance, smoothState, smoothStateCovariance] = helperGenerateSmoothData(imm, measPosTraj, time) % Output correct and smooth states numSteps = numel(time); positionSelector = [1 0 0 0 0 0;0 0 1 0 0 0;0 0 0 0 1 0]; initialState = positionSelector' * measPosTraj(1,:)'; initialCovariance = diag([1,16e4,1,16e4,1,16e4]); % Velocity is not measured initialize(imm, initialState, initialCovariance); correctState = zeros(6,numSteps); correctStateCovariance = zeros(6,6,numSteps); correctModelProb = zeros(3,numSteps); correctState(1,1) = measPosTraj(1,1); correctState(3,1) = measPosTraj(1,2); correctState(5,1) = measPosTraj(1,3); correctStateCovariance(:,:,1) = imm.StateCovariance; correctModelProb(:,1) = imm.ModelProbabilities; for i = 2:numSteps dt = time(i) - time(i-1); predict(imm, dt); [correctState(:,i), correctStateCovariance(:,:,i)] = correct(imm, measPosTraj(i,:)); correctModelProb(:,i) = imm.ModelProbabilities; end [smoothState, smoothStateCovariance, smoothModelProb] = smooth(imm); end
helperTrajectoryViewer
Визуализируйте результаты сглаживания и сравните ошибку RMS
function helperTrajectoryViewer(n, time, correctState, smoothState, trueStateTraj, measPosTraj) % Create figure and two panels, first panel for position and second panel % for error visualization truePosition = trueStateTraj(:,[1 3 5])'; correctPosition = correctState([1 3 5],:); smoothPosition = smoothState([1 3 5],:); correctPosError = correctState([1,3,5],1:end-1) - trueStateTraj(1:end-1,[1,3,5])'; smoothPosError = smoothState([1,3,5],:) - trueStateTraj(1:end-1,[1,3,5])'; correctVelError = correctState([2,4,6],1:end-1) - trueStateTraj(1:end-1,[2,4,6])'; smoothVelError = smoothState([2,4,6],:) - trueStateTraj(1:end-1,[2,4,6])'; numSteps = numel(time); correctPosRMS = zeros(1,numSteps-1); smoothPosRMS = zeros(1,numSteps - 1); correctVelRMS = zeros(1,numSteps-1); smoothVelRMS = zeros(1,numSteps - 1); for i = 1:numSteps -1 deltaPc = correctPosError(:,i); correctPosRMS(:,i) = sqrt((deltaPc')*deltaPc); deltaPs = smoothPosError(:,i); smoothPosRMS(:,i) = sqrt((deltaPs')*deltaPs); deltaVc = correctVelError(:,i); correctVelRMS(:,i) = sqrt((deltaVc')*deltaVc); deltaVs = smoothVelError(:,i); smoothVelRMS(:,i) = sqrt((deltaVs')*deltaVs); end hfig = figure('Name',"Trajectory " + n,'NumberTitle','off','Units','normalized','Position',[0.1 0.1 0.8 0.8]); hLeftPanel = uipanel(hfig,'Position',[0 0 1/2 1]); hRightPanel = uipanel(hfig,'Position',[1/2 0 1/2 1]); xMin = 10*floor(min(truePosition(:,1))/10e3)-5; xMax = 10*ceil(max(truePosition(:,1))/10e3)+5; yMin = 10*floor(min(truePosition(:,2))/10e3)-5; yMax = 10*ceil(max(truePosition(:,2))/10e3)+5; zMin = 10*floor(min(truePosition(:,3))/10e3)-5; zMax = 10*ceil(max(truePosition(:,3))/10e3)+5; % Place x-y plot in left panel for plotting true trajectory, corrected % trajectory, and smoothed trajectory hAx1 = axes('Parent',hLeftPanel); axis(hAx1,[xMin xMax yMin yMax zMin zMax]); plot3(hAx1,truePosition(1,:),truePosition(2,:),truePosition(3,:),'-','lineWidth',2); hold on plot3(hAx1,measPosTraj(:,1),measPosTraj(:,2),measPosTraj(:,3),'.','MarkerSize',3,'lineWidth',2); plot3(hAx1,correctPosition(1,:),correctPosition(2,:),correctPosition(3,:),'-','lineWidth',.05); plot3(hAx1,smoothPosition(1,:),smoothPosition(2,:),smoothPosition(3,:),'-','lineWidth',2); title("Trajectory " + n); xlabel('X (m)'); ylabel('Y (m)'); zlabel('Z (m)'); lObj = legend('True Position', 'Measured Position', 'Corrected Position', 'smoothed Position','location',"northeast"); axis(hAx1,'square'); grid(hAx1,'minor'); % Switch view to X-Y if Z 0 viewSwitch = mean(truePosition(3,:)); if viewSwitch == 0 view(90,90); else view(60,10); end % Set legend position legendPos = lObj.Position; set(lObj,'Position',[legendPos(1)*1.1 legendPos(2) legendPos(3) legendPos(4)]) set(gca,'ZDir','reverse'); % Position RMS plot hAx2 = subplot(2,1,1,'Parent',hRightPanel); line(hAx2, time(20:end-1),correctPosRMS(20:end),'color','m'); hold on; line(hAx2, time(20:end-1),smoothPosRMS(20:end),'color','b'); grid(hAx2,'on'); grid(hAx2,'minor'); xlim([1 inf]); xlabel('time (s)'); ylabel('Position Error'); legend('Correct Error', 'Smooth Error'); % Velocity RMS plot hAx3 = subplot(2,1,2,'Parent',hRightPanel); line(hAx3, time(20:end-1),correctVelRMS(20:end),'color','m'); hold on; line(hAx3, time(20:end-1),smoothVelRMS(20:end),'color','b'); grid(hAx3,'on'); grid(hAx3,'minor'); xlim([1 inf]); xlabel('time (s)'); ylabel('Velocity Error'); legend('Correct Error', 'Smooth Error'); end