Automatic Tuning of the insfilterAsync Filter
The insfilterAsync (Navigation Toolbox) object is a complex extended Kalman filter that estimates the device pose. However, manually tuning the filter or finding the optimal values for the noise parameters can be a challenging task. This example illustrates how to use the tune (Navigation Toolbox) function to optimize the filter noise parameters.
Trajectory and Sensor Setup
To illustrate the tuning process of the insfilterAsync filter, use a simple random waypoint trajectory. The imuSensor and gpsSensor objects create inputs for the filter.
% The IMU runs at 100 Hz and the GPS runs at 1 Hz. imurate = 100; gpsrate = 1; decim = imurate/gpsrate; % Create a random waypoint trajectory. rng(1) Npts = 4; % number of waypoints wpPer = 5; % time between waypoints tstart = 0; tend = wpPer*(Npts -1); wp = waypointTrajectory('Waypoints',5*rand(Npts,3), ... 'TimeOfArrival',tstart:wpPer:tend, ... 'Orientation',[quaternion.ones; randrot(Npts-1,1)], ... 'SampleRate', imurate); [Position,Orientation,Velocity,Acceleration,AngularVelocity] = lookupPose(... wp, tstart:(1/imurate):tend); % Set up an IMU and process the trajectory. imu = imuSensor('SampleRate',imurate); loadparams(imu,fullfile(matlabroot, ... "toolbox","shared","positioning","positioningdata","generic.json"), ... "GenericLowCost9Axis"); [Accelerometer, Gyroscope, Magnetometer] = imu(Acceleration, ... AngularVelocity, Orientation); imuData = timetable(Accelerometer,Gyroscope,Magnetometer,'SampleRate',imurate); % Set up a GPS sensor and process the trajectory. gps = gpsSensor('SampleRate', gpsrate,'DecayFactor',0.5, ... 'HorizontalPositionAccuracy',1.6,'VerticalPositionAccuracy',1.6, ... 'VelocityAccuracy',0.1); [GPSPosition,GPSVelocity] = gps(Position(1:decim:end,:), Velocity(1:decim:end,:)); gpsData = timetable(GPSPosition,GPSVelocity,'SampleRate',gpsrate); % Create a timetable for the tune function. sensorData = synchronize(imuData,gpsData); % Create a timetable capturing the ground truth pose. groundTruth = timetable(Position,Orientation,'SampleRate',imurate);
Construct the Filter
The insfilterAsync filter fuses data from multiple sensors operating asynchronously.
filtUntuned = insfilterAsync;
Determine Filter Initial Conditions
Set the initial values for the State and StateCovariance properties based on the ground truth. Normally to obtain the initial values, you would use the first several samples of sensorData along with calibration routines. However, in this example the groundTruth is used to set the initial state for fast convergence of the filter.
idx = stateinfo(filtUntuned);
filtUntuned.State(idx.Orientation) = compact(Orientation(1));
filtUntuned.State(idx.AngularVelocity) = AngularVelocity(1,:);
filtUntuned.State(idx.Position) = Position(1,:);
filtUntuned.State(idx.Velocity) = Velocity(1,:);
filtUntuned.State(idx.Acceleration) = Acceleration(1,:);
filtUntuned.State(idx.AccelerometerBias) = imu.Accelerometer.ConstantBias;
filtUntuned.State(idx.GyroscopeBias) = imu.Gyroscope.ConstantBias;
filtUntuned.State(idx.GeomagneticFieldVector) = imu.MagneticField;
filtUntuned.State(idx.MagnetometerBias) = imu.Magnetometer.ConstantBias;
filtUntuned.StateCovariance = 1e-5*eye(numel(filtUntuned.State));
% Create a copy of the filtUntuned object for tuning later.
filtTuned = copy(filtUntuned);Process sensorData with an Untuned Filter
Use the tunernoise function to create measurement noises which also need to be tuned. To illustrate the necessity for tuning, first use the filter with its default parameters.
mn = tunernoise('insfilterAsync');
[posUntunedEst, orientUntunedEst] = fuse(filtUntuned, sensorData, mn);Tune the Filter and Process sensorData
Use the tune function to minimize the root mean squared (RMS) error between the groundTruth and state estimates.
cfg = tunerconfig(class(filtTuned),'MaxIterations',15,'StepForward',1.1); tunedmn = tune(filtTuned,mn,sensorData,groundTruth,cfg);
Iteration Parameter Metric
_________ _________ ______
1 AccelerometerNoise 3.9157
1 GyroscopeNoise 3.9157
1 MagnetometerNoise 3.8618
1 GPSPositionNoise 3.8162
1 GPSVelocityNoise 3.6551
1 QuaternionNoise 3.6522
1 AngularVelocityNoise 3.4632
1 PositionNoise 3.4632
1 VelocityNoise 3.4632
1 AccelerationNoise 3.4420
1 GyroscopeBiasNoise 3.4420
1 AccelerometerBiasNoise 3.4389
1 GeomagneticVectorNoise 3.4389
1 MagnetometerBiasNoise 3.4389
2 AccelerometerNoise 3.4389
2 GyroscopeNoise 3.4389
2 MagnetometerNoise 3.3792
2 GPSPositionNoise 3.3792
2 GPSVelocityNoise 3.2526
2 QuaternionNoise 3.2506
2 AngularVelocityNoise 2.6514
2 PositionNoise 2.6514
2 VelocityNoise 2.6514
2 AccelerationNoise 2.6514
2 GyroscopeBiasNoise 2.6514
2 AccelerometerBiasNoise 2.6496
2 GeomagneticVectorNoise 2.6496
2 MagnetometerBiasNoise 2.6386
3 AccelerometerNoise 2.6351
3 GyroscopeNoise 2.6351
3 MagnetometerNoise 2.6165
3 GPSPositionNoise 2.6165
3 GPSVelocityNoise 2.5219
3 QuaternionNoise 2.4994
3 AngularVelocityNoise 2.4183
3 PositionNoise 2.4183
3 VelocityNoise 2.4183
3 AccelerationNoise 2.4032
3 GyroscopeBiasNoise 2.4032
3 AccelerometerBiasNoise 2.3922
3 GeomagneticVectorNoise 2.3922
3 MagnetometerBiasNoise 2.3922
4 AccelerometerNoise 2.3888
4 GyroscopeNoise 2.3888
4 MagnetometerNoise 2.3888
4 GPSPositionNoise 2.3888
4 GPSVelocityNoise 2.2745
4 QuaternionNoise 2.2641
4 AngularVelocityNoise 2.1749
4 PositionNoise 2.1749
4 VelocityNoise 2.1749
4 AccelerationNoise 2.1628
4 GyroscopeBiasNoise 2.1628
4 AccelerometerBiasNoise 2.1624
4 GeomagneticVectorNoise 2.1624
4 MagnetometerBiasNoise 2.1589
5 AccelerometerNoise 2.1587
5 GyroscopeNoise 2.1587
5 MagnetometerNoise 2.1587
5 GPSPositionNoise 2.1573
5 GPSVelocityNoise 2.0520
5 QuaternionNoise 2.0518
5 AngularVelocityNoise 2.0044
5 PositionNoise 2.0044
5 VelocityNoise 2.0044
5 AccelerationNoise 2.0013
5 GyroscopeBiasNoise 2.0013
5 AccelerometerBiasNoise 1.9900
5 GeomagneticVectorNoise 1.9900
5 MagnetometerBiasNoise 1.9900
6 AccelerometerNoise 1.9893
6 GyroscopeNoise 1.9893
6 MagnetometerNoise 1.9893
6 GPSPositionNoise 1.9893
6 GPSVelocityNoise 1.8894
6 QuaternionNoise 1.8894
6 AngularVelocityNoise 1.8273
6 PositionNoise 1.8273
6 VelocityNoise 1.8273
6 AccelerationNoise 1.8189
6 GyroscopeBiasNoise 1.8189
6 AccelerometerBiasNoise 1.8189
6 GeomagneticVectorNoise 1.8188
6 MagnetometerBiasNoise 1.8188
7 AccelerometerNoise 1.8188
7 GyroscopeNoise 1.8188
7 MagnetometerNoise 1.8177
7 GPSPositionNoise 1.8157
7 GPSVelocityNoise 1.7122
7 QuaternionNoise 1.7122
7 AngularVelocityNoise 1.6420
7 PositionNoise 1.6420
7 VelocityNoise 1.6420
7 AccelerationNoise 1.6420
7 GyroscopeBiasNoise 1.6420
7 AccelerometerBiasNoise 1.6412
7 GeomagneticVectorNoise 1.6412
7 MagnetometerBiasNoise 1.6412
8 AccelerometerNoise 1.6412
8 GyroscopeNoise 1.6411
8 MagnetometerNoise 1.6411
8 GPSPositionNoise 1.6383
8 GPSVelocityNoise 1.5216
8 QuaternionNoise 1.5216
8 AngularVelocityNoise 1.5004
8 PositionNoise 1.5004
8 VelocityNoise 1.5004
8 AccelerationNoise 1.5000
8 GyroscopeBiasNoise 1.5000
8 AccelerometerBiasNoise 1.5000
8 GeomagneticVectorNoise 1.5000
8 MagnetometerBiasNoise 1.4998
9 AccelerometerNoise 1.4998
9 GyroscopeNoise 1.4998
9 MagnetometerNoise 1.4998
9 GPSPositionNoise 1.4998
9 GPSVelocityNoise 1.4106
9 QuaternionNoise 1.4106
9 AngularVelocityNoise 1.3916
9 PositionNoise 1.3916
9 VelocityNoise 1.3916
9 AccelerationNoise 1.3916
9 GyroscopeBiasNoise 1.3916
9 AccelerometerBiasNoise 1.3911
9 GeomagneticVectorNoise 1.3911
9 MagnetometerBiasNoise 1.3911
10 AccelerometerNoise 1.3911
10 GyroscopeNoise 1.3910
10 MagnetometerNoise 1.3910
10 GPSPositionNoise 1.3892
10 GPSVelocityNoise 1.2977
10 QuaternionNoise 1.2977
10 AngularVelocityNoise 1.2977
10 PositionNoise 1.2977
10 VelocityNoise 1.2977
10 AccelerationNoise 1.2975
10 GyroscopeBiasNoise 1.2975
10 AccelerometerBiasNoise 1.2975
10 GeomagneticVectorNoise 1.2975
10 MagnetometerBiasNoise 1.2974
11 AccelerometerNoise 1.2973
11 GyroscopeNoise 1.2973
11 MagnetometerNoise 1.2973
11 GPSPositionNoise 1.2973
11 GPSVelocityNoise 1.2031
11 QuaternionNoise 1.2030
11 AngularVelocityNoise 1.1998
11 PositionNoise 1.1998
11 VelocityNoise 1.1998
11 AccelerationNoise 1.1998
11 GyroscopeBiasNoise 1.1998
11 AccelerometerBiasNoise 1.1995
11 GeomagneticVectorNoise 1.1995
11 MagnetometerBiasNoise 1.1994
12 AccelerometerNoise 1.1993
12 GyroscopeNoise 1.1992
12 MagnetometerNoise 1.1992
12 GPSPositionNoise 1.1982
12 GPSVelocityNoise 1.1009
12 QuaternionNoise 1.1008
12 AngularVelocityNoise 1.0972
12 PositionNoise 1.0972
12 VelocityNoise 1.0972
12 AccelerationNoise 1.0972
12 GyroscopeBiasNoise 1.0972
12 AccelerometerBiasNoise 1.0968
12 GeomagneticVectorNoise 1.0968
12 MagnetometerBiasNoise 1.0967
13 AccelerometerNoise 1.0966
13 GyroscopeNoise 1.0965
13 MagnetometerNoise 1.0965
13 GPSPositionNoise 1.0955
13 GPSVelocityNoise 0.9830
13 QuaternionNoise 0.9829
13 AngularVelocityNoise 0.9829
13 PositionNoise 0.9829
13 VelocityNoise 0.9829
13 AccelerationNoise 0.9829
13 GyroscopeBiasNoise 0.9829
13 AccelerometerBiasNoise 0.9825
13 GeomagneticVectorNoise 0.9825
13 MagnetometerBiasNoise 0.9824
14 AccelerometerNoise 0.9822
14 GyroscopeNoise 0.9822
14 MagnetometerNoise 0.9822
14 GPSPositionNoise 0.9812
14 GPSVelocityNoise 0.8868
14 QuaternionNoise 0.8867
14 AngularVelocityNoise 0.8816
14 PositionNoise 0.8816
14 VelocityNoise 0.8816
14 AccelerationNoise 0.8815
14 GyroscopeBiasNoise 0.8815
14 AccelerometerBiasNoise 0.8812
14 GeomagneticVectorNoise 0.8812
14 MagnetometerBiasNoise 0.8811
15 AccelerometerNoise 0.8809
15 GyroscopeNoise 0.8809
15 MagnetometerNoise 0.8809
15 GPSPositionNoise 0.8799
15 GPSVelocityNoise 0.7916
15 QuaternionNoise 0.7916
15 AngularVelocityNoise 0.7916
15 PositionNoise 0.7916
15 VelocityNoise 0.7916
15 AccelerationNoise 0.7916
15 GyroscopeBiasNoise 0.7916
15 AccelerometerBiasNoise 0.7913
15 GeomagneticVectorNoise 0.7913
15 MagnetometerBiasNoise 0.7913
[posTunedEst, orientTunedEst] = fuse(filtTuned,sensorData,tunedmn);
Compare Tuned vs Untuned Filter
Plot the position estimates from the tuned and untuned filters along with the ground truth positions. Then, plot the orientation error (quaternion distance) in degrees for both tuned and untuned filters. The tuned filter estimates the position and orientation better than the untuned filter.
% Position error figure; t = sensorData.Time; subplot(3,1,1); plot(t, [posTunedEst(:,1) posUntunedEst(:,1) Position(:,1)]); title('Position'); ylabel('X-axis'); legend('Tuned', 'Untuned', 'Truth'); subplot(3,1,2); plot(t, [posTunedEst(:,2) posUntunedEst(:,2) Position(:,2)]); ylabel('Y-axis'); subplot(3,1,3); plot(t, [posTunedEst(:,3) posUntunedEst(:,3) Position(:,3)]); ylabel('Z-axis');

% Orientation Error figure; plot(t, rad2deg(dist(Orientation, orientTunedEst)), ... t, rad2deg(dist(Orientation, orientUntunedEst))); title('Orientation Error'); ylabel('Degrees'); legend('Tuned', 'Untuned');
