Hauptinhalt

Diese Seite wurde mithilfe maschineller Übersetzung übersetzt. Klicken Sie hier, um das englische Original zu sehen.

Position und Ausrichtung eines Bodenfahrzeugs abschätzen

Dieses Beispiel zeigt, wie man die Position und Orientierung von Bodenfahrzeugen durch die Fusion von Daten einer Inertialmesseinheit (IMU) und eines globalen Positionierungssystems (GPS) schätzen kann.

Simulationseinstellungen

Die Abtastraten einstellen. In einem typischen System arbeiten der Beschleunigungsmesser und das Gyroskop in der IMU mit relativ hohen Abtastraten. Die Komplexität der Datenverarbeitung von diesen Sensoren im Fusionsalgorithmus ist relativ gering. Umgekehrt arbeitet das GPS mit einer relativ niedrigen Abtastrate und die damit verbundene Komplexität der Datenverarbeitung ist hoch. Bei diesem Fusionsalgorithmus werden die GPS-Messwerte mit einer niedrigen Rate verarbeitet, während die Beschleunigungsmesser- und Gyroskopmesswerte gleichzeitig mit der gleichen hohen Rate verarbeitet werden.

Um diese Konfiguration zu simulieren, wird die IMU (Beschleunigungsmesser und Gyroskop) mit 100 Hz abgetastet, das GPS hingegen mit 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.');

Fusionsfilter

Erstelle den Filter zur Fusion von IMU- und GPS-Messungen. Der Fusionsfilter verwendet einen erweiterten Kalman-Filter, um Orientierung (als Quaternion), Position, Geschwindigkeit und Sensorabweichungen zu verfolgen.

Das insfilterNonholonomic-Objekt verfügt über zwei Hauptmethoden: predict und fusegps. Die predict-Methode verwendet die Beschleunigungsmesser- und Gyroskop-Messwerte der IMU als Eingabe. Rufen Sie die Methode predict jedes Mal auf, wenn Beschleunigungsmesser und Gyroskop abgetastet werden. Diese Methode sagt die Zustände für einen Zeitschritt in die Zukunft auf Basis des Beschleunigungsmessers und des Gyroskops voraus. In diesem Schritt wird die Fehlerkovarianz des erweiterten Kalman-Filters aktualisiert.

Die fusegps-Methode verwendet die GPS-Messwerte als Eingabe. Bei dieser Methode werden die Filterzustände anhand der GPS-Abtastung aktualisiert, indem eine Kalman-Verstärkung berechnet wird, die die verschiedenen Sensoreingaben entsprechend ihrer Unsicherheit gewichtet. In diesem Schritt wird auch die Fehlerkovarianz aktualisiert, diesmal ebenfalls unter Verwendung des Kalman-Verstärkungsfaktors.

Das insfilterNonholonomic-Objekt hat zwei Haupteigenschaften: IMUSampleRate und DecimationFactor. Für das Bodenfahrzeug gelten zwei Geschwindigkeitsbeschränkungen, die davon ausgehen, dass es nicht vom Boden abprallt oder auf dem Boden rutscht. Diese Nebenbedingungen werden mithilfe der erweiterten Kalman-Filter-Aktualisierungsgleichungen angewendet. Diese Aktualisierungen werden mit einer Rate von IMUSampleRate/DecimationFactor Hz auf die Filterzustände angewendet.

gndFusion = insfilterNonholonomic('ReferenceFrame', 'ENU', ...
    'IMUSampleRate', imuFs, ...
    'ReferenceLocation', localOrigin, ...
    'DecimationFactor', 2);

Bodenfahrzeugtrajektorie erstellen

Das waypointTrajectory-Objekt berechnet die Pose anhand der angegebenen Abtastrate, Wegpunkte, Ankunftszeiten und Orientierung. Legen Sie die Parameter einer Kreisbahn für das Bodenfahrzeug fest.

% 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');

GPS-Empfänger

Stellen Sie das GPS auf die angegebene Abtastrate und den Referenzstandort ein. Die übrigen Parameter steuern die Art des Rauschens im Ausgangssignal.

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;

IMU-Sensoren

Typischerweise verwenden Bodenfahrzeuge einen 6-Achsen-IMU-Sensor zur Lagebestimmung. Um einen IMU-Sensor zu modellieren, definieren Sie ein IMU-Sensormodell, das einen Beschleunigungsmesser und ein Gyroskop enthält. In einer realen Anwendung können die beiden Sensoren von einem einzigen integrierten Schaltkreis oder von separaten Schaltkreisen stammen. Die hier angegebenen Eigenschaftswerte sind typisch für kostengünstige MEMS-Sensoren.

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);

Initialisieren der Zustände von insfilterNonholonomic

Die Zustände sind:

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

Die Ground Truth wird verwendet, um die Filterzustände zu initialisieren, damit der Filter schnell zu guten Ergebnissen konvergiert.

% 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;

Initialisieren der Varianzen von insfilterNonholonomic

Die Messrauschen beschreiben, wie stark das GPS-Messergebnis durch Rauschen verfälscht wird, basierend auf den gpsSensor-Parametern, und wie groß die Unsicherheit im Fahrzeugdynamikmodell ist.

Das Prozessrauschen beschreibt, wie gut die Filtergleichungen die Zustandsentwicklung beschreiben. Prozessrauschen wird empirisch ermittelt, indem Parameter-Sweeps durchgeführt werden, um die Positions- und Orientierungsschätzungen des Filters gemeinsam zu optimieren.

% 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);

Bereiche initialisieren

Der HelperScrollingPlotter-Bereich ermöglicht die grafische Darstellung von Variablen im Zeitverlauf. Es wird hier verwendet, um Fehler in der Pose zu erfassen. Der HelperPoseViewer-Bereich ermöglicht die 3D-Visualisierung der Filterschätzung und der tatsächlichen Pose. Die Oszilloskope können die Simulation verlangsamen. Um einen Gültigkeitsbereich zu deaktivieren, setzen Sie die entsprechende logische Variable auf 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

Simulationsschleife

Die Hauptsimulationsschleife ist eine While-Schleife mit einer darin enthaltenen For-Schleife. Die while-Schleife wird mit der Frequenz gpsFs ausgeführt, was der GPS-Messrate entspricht. Die verschachtelte for-Schleife wird mit der Abtastrate imuFs ausgeführt, die der IMU-Abtastrate entspricht. Die Messbereiche werden mit der Abtastrate der IMU aktualisiert.

totalSimTime = 30; % seconds

% Log data for final metric computation.
numGPSSamples = floor(min(t(end), totalSimTime) * gpsFs);
numSamples = numGPSSamples*imuSamplesPerGPS;
truePosition = zeros(numSamples,3);
trueOrientation = quaternion.zeros(numSamples,1);
estPosition = zeros(numSamples,3);
estOrientation = quaternion.zeros(numSamples,1);

idx = 0;

for sampleIdx = 1:numGPSSamples
    % 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,:), trueOrientation(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

Figure Scrolling Plotter contains 4 axes objects. Axes object 1 with title Position Z Error, xlabel Time (s), ylabel meters contains an object of type line. Axes object 2 with title Position Y Error, xlabel Time (s), ylabel meters contains an object of type line. Axes object 3 with title Position X Error, xlabel Time (s), ylabel meters contains an object of type line. Axes object 4 with title Quaternion Distance, xlabel Time (s), ylabel degrees contains an object of type line.

MATLAB figure

Fehlermetrikberechnung

Position und Orientierung wurden während der gesamten Simulation protokolliert. Berechnen Sie nun den gesamten mittleren quadratischen Fehler für Position und Orientierung.

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)