Этот пример показывает, как можно сплавить датчики с различными скоростями для оценки положения. Акселерометр, гироскоп, магнитометр и GPS предназначены для определения ориентации и положения транспортного средства, перемещающегося по круговому пути. Можно использовать элементы управления в окне рисунка, чтобы варьировать скорости датчика и экспериментировать с выпадением датчика, видя эффект на предполагаемое положение.
Загрузите предварительно записанные данные о датчике. Данные о датчике основаны на круговой траектории, созданной с помощью waypointTrajectory
класс. Значения датчиков были созданы с помощью gpsSensor
и imuSensor
классы. The CircularTrajectorySensorData.mat
файл, используемый здесь, может быть сгенерирован с помощью generateCircularTrajSensorData
функция.
ld = load('CircularTrajectorySensorData.mat'); Fs = ld.Fs; % maximum MARG rate gpsFs = ld.gpsFs; % maximum GPS rate ratio = Fs./gpsFs; refloc = ld.refloc; trajOrient = ld.trajData.Orientation; trajVel = ld.trajData.Velocity; trajPos = ld.trajData.Position; trajAcc = ld.trajData.Acceleration; trajAngVel = ld.trajData.AngularVelocity; accel = ld.accel; gyro = ld.gyro; mag = ld.mag; lla = ld.lla; gpsvel = ld.gpsvel;
Создайте insfilterAsync
предохранить измерения БИНС + GPS. Этот фильтр слияния использует непрерывно-дискретный расширенный фильтр Калмана (EKF) для отслеживания ориентации (в качестве кватерниона), скорости вращения, положения, скорости, ускорения, смещений датчика и геомагнитного вектора.
Этот insfilterAsync
имеет несколько методов обработки данных о датчике: fuseaccel
, fusegyro
, fusemag
и fusegps
. Потому что insfilterAsync
использует непрерывно-дискретный EKF, predict
способ может переместить фильтр вперед на произвольное количество времени.
fusionfilt = insfilterAsync('ReferenceLocation', refloc);
insfilterAsync
The insfilterAsync
отслеживает состояния положения в векторе с 28 элементами. Состояниями являются:
States Units Index Orientation (quaternion parts) 1:4 Angular Velocity (XYZ) rad/s 5:7 Position (NED) m 8:10 Velocity (NED) m/s 11:13 Acceleration (NED) m/s^2 14:16 Accelerometer Bias (XYZ) m/s^2 17:19 Gyroscope Bias (XYZ) rad/s 20:22 Geomagnetic Field Vector (NED) uT 23:25 Magnetometer Bias (XYZ) uT 26:28
Основная истина используется, чтобы помочь инициализировать состояния фильтра, поэтому фильтр быстро сходится к хорошим ответам.
Nav = 100; initstate = zeros(28,1); initstate(1:4) = compact( meanrot(trajOrient(1:Nav))); initstate(5:7) = mean( trajAngVel(10:Nav,:), 1); initstate(8:10) = mean( trajPos(1:Nav,:), 1); initstate(11:13) = mean( trajVel(1:Nav,:), 1); initstate(14:16) = mean( trajAcc(1:Nav,:), 1); initstate(23:25) = ld.magField; % The gyroscope bias initial value estimate is low for the Z-axis. This is % done to illustrate the effects of fusing the magnetometer in the % simulation. initstate(20:22) = deg2rad([3.125 3.125 3.125]); fusionfilt.State = initstate;
insfilterAsync
Отклонение шума процесса описывает неопределенность модели движения, которую использует фильтр.
fusionfilt.QuaternionNoise = 1e-2; fusionfilt.AngularVelocityNoise = 100; fusionfilt.AccelerationNoise = 100; fusionfilt.MagnetometerBiasNoise = 1e-7; fusionfilt.AccelerometerBiasNoise = 1e-7; fusionfilt.GyroscopeBiasNoise = 1e-7;
Каждый датчик имеет некоторый шум в измерениях. Эти значения обычно можно найти в таблице данных датчика.
Rmag = 0.4; Rvel = 0.01; Racc = 610; Rgyro = 0.76e-5; Rpos = 3.4; fusionfilt.StateCovariance = diag(1e-3*ones(28,1));
The HelperScrollingPlotter
возможности включает построение графиков переменных с течением времени. Он используется здесь, чтобы отслеживать ошибки в положении. The PoseViewerWithSwitches
Возможности позволяют 3D визуализацию оценки фильтра и основной истины положения. Возможности могут замедлить симуляцию. Чтобы отключить возможности, установите соответствующую логическую переменную false.
useErrScope = true; % Turn on the streaming error plot. usePoseView = true; % Turn on the 3D pose viewer. if usePoseView posescope = PoseViewerWithSwitches(... 'XPositionLimits', [-30 30], ... 'YPositionLimits', [-30, 30], ... 'ZPositionLimits', [-10 10]); end f = gcf; if useErrScope errscope = HelperScrollingPlotter(... 'NumInputs', 4, ... 'TimeSpan', 10, ... 'SampleRate', Fs, ... 'YLabel', {'degrees', ... 'meters', ... 'meters', ... 'meters'}, ... 'Title', {'Quaternion Distance', ... 'Position X Error', ... 'Position Y Error', ... 'Position Z Error'}, ... 'YLimits', ... [ -1, 30 -2, 2 -2 2 -2 2]); end
Симуляция алгоритма слияния позволяет вам проверить эффекты изменения скоростей выборки датчика. Кроме того, слияние отдельных датчиков можно предотвратить, сняв соответствующий флажок. Это может использоваться, чтобы имитировать выпадение датчика.
Некоторые строения дают драматические результаты. Для примера отключение GPS-датчика приводит к быстрому дрейфу оценки положения. Выключение датчика магнитометра приведет к медленному отклонению оценки ориентации от основной истины, когда оценка вращается слишком быстро. И наоборот, если гироскоп выключен и магнитометр включен, оцененная ориентация показывает колебание и отсутствие плавности сглаживания, если используются оба датчика.
Включение всех датчиков, но установка их на наименьшую скорость, приводит к оценке, которая заметно отклоняется от основной истины, а затем защелкивается к более правильному результату, когда датчики сплавляются. Это легче всего увидеть в HelperScrollingPlotter
текущих ошибок оценки.
Основная симуляция работает на частоте 100 Гц. Каждая итерация просматривает флажки в окне рисунка и, если датчик включен, запирает данные для этого датчика с соответствующей скоростью.
for ii=1:size(accel,1) fusionfilt.predict(1./Fs); % Fuse Accelerometer if (f.UserData.Accelerometer) && ... mod(ii, fix(Fs/f.UserData.AccelerometerSampleRate)) == 0 fusionfilt.fuseaccel(accel(ii,:), Racc); end % Fuse Gyroscope if (f.UserData.Gyroscope) && ... mod(ii, fix(Fs/f.UserData.GyroscopeSampleRate)) == 0 fusionfilt.fusegyro(gyro(ii,:), Rgyro); end % Fuse Magnetometer if (f.UserData.Magnetometer) && ... mod(ii, fix(Fs/f.UserData.MagnetometerSampleRate)) == 0 fusionfilt.fusemag(mag(ii,:), Rmag); end % Fuse GPS if (f.UserData.GPS) && mod(ii, fix(Fs/f.UserData.GPSSampleRate)) == 0 fusionfilt.fusegps(lla(ii,:), Rpos, gpsvel(ii,:), Rvel); end % Plot the pose error [p,q] = pose(fusionfilt); posescope(p, q, trajPos(ii,:), trajOrient(ii)); orientErr = rad2deg(dist(q, trajOrient(ii) )); posErr = p - trajPos(ii,:); errscope(orientErr, posErr(1), posErr(2), posErr(3)); end
The insfilterAsync
позволяет для различных и меняющихся частот дискретизации. Качество предполагаемых выходов в большой степени зависит от отдельных скоростей слияния датчиков. Любое выпадение датчика окажет глубокий эффект на выход.