Estimar la posición y orientación de un vehículo terrestre
Este ejemplo muestra cómo estimar la posición y orientación de vehículos terrestres fusionando datos de una unidad de medición inercial (IMU) y un receptor del sistema de posicionamiento global (GPS).
Configuración de simulación
Establezca las tasas de muestreo. En un sistema típico, el acelerómetro y el giroscopio de la IMU funcionan a velocidades de muestreo relativamente altas. La complejidad de procesar datos de esos sensores en el algoritmo de fusión es relativamente baja. Por el contrario, el GPS funciona a una frecuencia de muestreo relativamente baja y la complejidad asociada con su procesamiento es alta. En este algoritmo de fusión, las muestras de GPS se procesan a una velocidad baja y las muestras del acelerómetro y el giroscopio se procesan juntas a la misma velocidad alta.
Para simular esta configuración, la IMU (acelerómetro y giroscopio) se muestrea a 100 Hz y el GPS a 10 Hz.
imuFs = 100; gpsFs = 10; % Define where on the Earth this simulation takes place using latitude, % longitude, and altitude (LLA) coordinates. localOrigin = [42.2825 -71.343 53.0352]; % Validate that the |gpsFs| divides |imuFs|. This allows the sensor sample % rates to be simulated using a nested for loop without complex sample rate % matching. imuSamplesPerGPS = (imuFs/gpsFs); assert(imuSamplesPerGPS == fix(imuSamplesPerGPS), ... 'GPS sampling rate must be an integer factor of IMU sampling rate.');
Filtro de fusión
Cree el filtro para fusionar las mediciones de IMU + GPS. El filtro de fusión utiliza un filtro de Kalman extendido para rastrear la orientación (como un cuaternión), la posición, la velocidad y los sesgos del sensor.
El objeto insfilterNonholonomic
tiene dos métodos principales: predict
y fusegps
. El método predict
toma las muestras del acelerómetro y giroscopio de la IMU como entrada. Llame al método predict
cada vez que se muestreen el acelerómetro y el giroscopio. Este método predice los estados hacia adelante en un paso de tiempo basándose en el acelerómetro y el giroscopio. En este paso se actualiza la covarianza de error del filtro de Kalman extendido.
El método fusegps
toma las muestras de GPS como entrada. Este método actualiza los estados del filtro según la muestra de GPS calculando una ganancia de Kalman que pondera las distintas entradas del sensor según su incertidumbre. En este paso también se actualiza una covarianza de error, esta vez utilizando también la ganancia de Kalman.
El objeto insfilterNonholonomic
tiene dos propiedades principales: IMUSampleRate
y DecimationFactor
. El vehículo terrestre tiene dos restricciones de velocidad que suponen que no rebota ni se desliza sobre el suelo. Estas restricciones se aplican utilizando las ecuaciones de actualización del filtro de Kalman extendidas. Estas actualizaciones se aplican a los estados del filtro a una velocidad de IMUSampleRate/DecimationFactor
Hz.
gndFusion = insfilterNonholonomic('ReferenceFrame', 'ENU', ... 'IMUSampleRate', imuFs, ... 'ReferenceLocation', localOrigin, ... 'DecimationFactor', 2);
Crear trayectoria de vehículo terrestre
El objeto waypointTrajectory
calcula la pose en función de la frecuencia de muestreo, los puntos de referencia, los tiempos de llegada y la orientación especificados. Especifique los parámetros de una trayectoria circular para el vehículo terrestre.
% Trajectory parameters r = 8.42; % (m) speed = 2.50; % (m/s) center = [0, 0]; % (m) initialYaw = 90; % (degrees) numRevs = 2; % Define angles theta and corresponding times of arrival t. revTime = 2*pi*r / speed; theta = (0:pi/2:2*pi*numRevs).'; t = linspace(0, revTime*numRevs, numel(theta)).'; % Define position. x = r .* cos(theta) + center(1); y = r .* sin(theta) + center(2); z = zeros(size(x)); position = [x, y, z]; % Define orientation. yaw = theta + deg2rad(initialYaw); yaw = mod(yaw, 2*pi); pitch = zeros(size(yaw)); roll = zeros(size(yaw)); orientation = quaternion([yaw, pitch, roll], 'euler', ... 'ZYX', 'frame'); % Generate trajectory. groundTruth = waypointTrajectory('SampleRate', imuFs, ... 'Waypoints', position, ... 'TimeOfArrival', t, ... 'Orientation', orientation); % Initialize the random number generator used to simulate sensor noise. rng('default');
Receptor GPS
Configure el GPS a la frecuencia de muestreo y ubicación de referencia especificadas. Los otros parámetros controlan la naturaleza del ruido en la señal de salida.
gps = gpsSensor('UpdateRate', gpsFs, 'ReferenceFrame', 'ENU'); gps.ReferenceLocation = localOrigin; gps.DecayFactor = 0.5; % Random walk noise parameter gps.HorizontalPositionAccuracy = 1.0; gps.VerticalPositionAccuracy = 1.0; gps.VelocityAccuracy = 0.1;
Sensores IMU
Normalmente, los vehículos terrestres utilizan un sensor IMU de 6 ejes para estimar la pose. Para modelar un sensor IMU, defina un modelo de sensor IMU que contenga un acelerómetro y un giroscopio. En una aplicación del mundo real, los dos sensores podrían provenir de un único circuito integrado o de circuitos separados. Los valores de propiedad establecidos aquí son típicos de sensores MEMS de bajo coste.
imu = imuSensor('accel-gyro', ... 'ReferenceFrame', 'ENU', 'SampleRate', imuFs); % Accelerometer imu.Accelerometer.MeasurementRange = 19.6133; imu.Accelerometer.Resolution = 0.0023928; imu.Accelerometer.NoiseDensity = 0.0012356; % Gyroscope imu.Gyroscope.MeasurementRange = deg2rad(250); imu.Gyroscope.Resolution = deg2rad(0.0625); imu.Gyroscope.NoiseDensity = deg2rad(0.025);
Inicializar los Estados del insfilterNonholonomic
Los estados son:
States Units Index Orientation (quaternion parts) 1:4 Gyroscope Bias (XYZ) rad/s 5:7 Position (NED) m 8:10 Velocity (NED) m/s 11:13 Accelerometer Bias (XYZ) m/s^2 14:16
La ground-truth se utiliza para ayudar a inicializar los estados del filtro, de modo que el filtro converja rápidamente hacia buenas respuestas.
% Get the initial ground truth pose from the first sample of the trajectory % and release the ground truth trajectory to ensure the first sample is not % skipped during simulation. [initialPos, initialAtt, initialVel] = groundTruth(); reset(groundTruth); % Initialize the states of the filter gndFusion.State(1:4) = compact(initialAtt).'; gndFusion.State(5:7) = imu.Gyroscope.ConstantBias; gndFusion.State(8:10) = initialPos.'; gndFusion.State(11:13) = initialVel.'; gndFusion.State(14:16) = imu.Accelerometer.ConstantBias;
Inicializar las variaciones del insfilterNonholonomic
Los ruidos de medición describen cuánto ruido está corrompiendo la lectura del GPS según los parámetros gpsSensor
y cuánta incertidumbre hay en el modelo dinámico del vehículo.
Los ruidos del proceso describen qué tan bien las ecuaciones de filtro describen la evolución del estado. Los ruidos del proceso se determinan empíricamente mediante barrido de parámetros para optimizar conjuntamente las estimaciones de posición y orientación del filtro.
% Measurement noises Rvel = gps.VelocityAccuracy.^2; Rpos = gps.HorizontalPositionAccuracy.^2; % The dynamic model of the ground vehicle for this filter assumes there is % no side slip or skid during movement. This means that the velocity is % constrained to only the forward body axis. The other two velocity axis % readings are corrected with a zero measurement weighted by the % |ZeroVelocityConstraintNoise| parameter. gndFusion.ZeroVelocityConstraintNoise = 1e-2; % Process noises gndFusion.GyroscopeNoise = 4e-6; gndFusion.GyroscopeBiasNoise = 4e-14; gndFusion.AccelerometerNoise = 4.8e-2; gndFusion.AccelerometerBiasNoise = 4e-14; % Initial error covariance gndFusion.StateCovariance = 1e-9*eye(16);
Inicializar ámbitos
El alcance HelperScrollingPlotter
permite trazar variables a lo largo del tiempo. Se utiliza aquí para rastrear errores en la pose. El alcance HelperPoseViewer
permite la visualización tridimensional de la estimación del filtro y la pose de ground-truth. Los alcances pueden ralentizar la simulación. Para deshabilitar un alcance, establezca la variable lógica correspondiente en false
.
useErrScope = true; % Turn on the streaming error plot usePoseView = true; % Turn on the 3D pose viewer if useErrScope errscope = HelperScrollingPlotter( ... 'NumInputs', 4, ... 'TimeSpan', 10, ... 'SampleRate', imuFs, ... 'YLabel', {'degrees', ... 'meters', ... 'meters', ... 'meters'}, ... 'Title', {'Quaternion Distance', ... 'Position X Error', ... 'Position Y Error', ... 'Position Z Error'}, ... 'YLimits', ... [-1, 1 -1, 1 -1, 1 -1, 1]); end if usePoseView viewer = HelperPoseViewer( ... 'XPositionLimits', [-15, 15], ... 'YPositionLimits', [-15, 15], ... 'ZPositionLimits', [-5, 5], ... 'ReferenceFrame', 'ENU'); end
Bucle de simulación
El bucle de simulación principal es un bucle while con un bucle for anidado. El bucle while se ejecuta en gpsFs
, que es la velocidad de medición del GPS. El bucle for anidado se ejecuta en imuFs
, que es la frecuencia de muestreo de IMU. Los alcances se actualizan a la frecuencia de muestreo de IMU.
totalSimTime = 30; % seconds % Log data for final metric computation. numsamples = floor(min(t(end), totalSimTime) * gpsFs); truePosition = zeros(numsamples,3); trueOrientation = quaternion.zeros(numsamples,1); estPosition = zeros(numsamples,3); estOrientation = quaternion.zeros(numsamples,1); idx = 0; for sampleIdx = 1:numsamples % Predict loop at IMU update frequency. for i = 1:imuSamplesPerGPS if ~isDone(groundTruth) idx = idx + 1; % Simulate the IMU data from the current pose. [truePosition(idx,:), trueOrientation(idx,:), ... trueVel, trueAcc, trueAngVel] = groundTruth(); [accelData, gyroData] = imu(trueAcc, trueAngVel, ... trueOrientation(idx,:)); % Use the predict method to estimate the filter state based % on the accelData and gyroData arrays. predict(gndFusion, accelData, gyroData); % Log the estimated orientation and position. [estPosition(idx,:), estOrientation(idx,:)] = pose(gndFusion); % Compute the errors and plot. if useErrScope orientErr = rad2deg( ... dist(estOrientation(idx,:), trueOrientation(idx,:))); posErr = estPosition(idx,:) - truePosition(idx,:); errscope(orientErr, posErr(1), posErr(2), posErr(3)); end % Update the pose viewer. if usePoseView viewer(estPosition(idx,:), estOrientation(idx,:), ... truePosition(idx,:), estOrientation(idx,:)); end end end if ~isDone(groundTruth) % This next step happens at the GPS sample rate. % Simulate the GPS output based on the current pose. [lla, gpsVel] = gps(truePosition(idx,:), trueVel); % Update the filter states based on the GPS data. fusegps(gndFusion, lla, Rpos, gpsVel, Rvel); end end
Cálculo de métricas de error
La posición y la orientación se registraron durante toda la simulación. Ahora calcule un error cuadrático medio de extremo a extremo para la posición y la orientación.
posd = estPosition - truePosition; % For orientation, quaternion distance is a much better alternative to % subtracting Euler angles, which have discontinuities. The quaternion % distance can be computed with the |dist| function, which gives the % angular difference in orientation in radians. Convert to degrees for % display in the command window. quatd = rad2deg(dist(estOrientation, trueOrientation)); % Display RMS errors in the command window. fprintf('\n\nEnd-to-End Simulation Position RMS Error\n');
End-to-End Simulation Position RMS Error
msep = sqrt(mean(posd.^2)); fprintf('\tX: %.2f , Y: %.2f, Z: %.2f (meters)\n\n', msep(1), ... msep(2), msep(3));
X: 1.16 , Y: 0.98, Z: 0.03 (meters)
fprintf('End-to-End Quaternion Distance RMS Error (degrees) \n');
End-to-End Quaternion Distance RMS Error (degrees)
fprintf('\t%.2f (degrees)\n\n', sqrt(mean(quatd.^2)));
0.11 (degrees)