171 lines
6.7 KiB
Matlab
171 lines
6.7 KiB
Matlab
function [Beta_KF, State, Covariance, pNoise, errorFlag] = KF_identification(robot, benchmarkSettings, experimentDataStruct, expNb, Beta_0, optionsKF)
|
|
|
|
% Authors: Quentin Leboutet, Julien Roux, Alexandre Janot and Gordon Cheng
|
|
%
|
|
% Parameter identification using Nonlinear Kalman filtering.
|
|
|
|
%% Data Decimation and Filtering:
|
|
|
|
optionsKF.filter = 'no'; % Otherwise there is no interest at all in using a Kalman filter with an extended state right ?
|
|
[t, ~, ~, ~, ~, t_decim, Tau_decim, Qpp_decim, Qp_decim, Q_decim, optionsKF] = getFilteredData(robot, benchmarkSettings, experimentDataStruct, optionsKF, expNb, optionsKF.type);
|
|
|
|
%% Kalman Filter Parameter Initialization
|
|
|
|
[x_aug, P, S, Rv, Rn, Sv, Sn, Particules, w, alpha, beta, kappa, h, paramSize, pNoiseAdaptParams, State, Covariance, pNoise] = initKalman(robot, benchmarkSettings, Tau_decim, Qpp_decim, Qp_decim, Q_decim, expNb, Beta_0, optionsKF);
|
|
|
|
errorFlag = 1;
|
|
it=1;
|
|
|
|
%% Kalman Filter Loop
|
|
|
|
% iDq=zeros(robot.nbDOF,1);
|
|
counter=1;
|
|
if optionsKF.debug == true
|
|
StateDebug = [];
|
|
figure('Name','Covariance Matrix');
|
|
end
|
|
|
|
for index=2:optionsKF.nbSampleDecim
|
|
|
|
% Acquire measurement:
|
|
y = acquireMeasurement(Tau_decim, Qpp_decim, Qp_decim, Q_decim, index);
|
|
|
|
% Process noise annealing for the parameters (inspired by the ReBEL toolkit from Rudolph Van der Merwe):
|
|
[Rv, Sv, pNoiseAdaptParams] = annealingNoiseCovariance(P, Rv, Sv, pNoiseAdaptParams, paramSize, optionsKF);
|
|
Tau = Tau_decim(:, index-1);
|
|
% Compute torque command:
|
|
if optionsKF.useComputedTorque == true
|
|
% Use the computed torque as a control input:
|
|
t_ctrl = linspace(t_decim(index-1), t_decim(index), (t_decim(index)-t_decim(index-1))/benchmarkSettings.dt_ctrl); % Control epochs btween two Kalman iterations
|
|
augmentedDesiredState = benchmarkSettings.trajectoryData.getTrajectoryData(t_ctrl, benchmarkSettings.interpolationAlgorithm); % augmentedState = [Qpp; Qp; Q];
|
|
% Nonlinear Kalman Filter:
|
|
[x_aug, P, S, Particules, w, status] = iterateKalman(robot, benchmarkSettings, index, t_decim, optionsKF, x_aug, Tau, P, S, y, Rv, Rn, Sv, Sn, Particules, w, alpha, beta, kappa, h, augmentedDesiredState, optionsKF.useComputedTorque);
|
|
else
|
|
% Use the measured torque as a control input:
|
|
Tau = Tau_decim(:, index);
|
|
% Nonlinear Kalman Filter:
|
|
[x_aug, P, S, Particules, w, status] = iterateKalman(robot, benchmarkSettings, index, t_decim, optionsKF, x_aug, Tau, P, S, y, Rv, Rn, Sv, Sn, Particules, w, alpha, beta, kappa, h, 0, optionsKF.useComputedTorque);
|
|
end
|
|
if optionsKF.debug == true
|
|
StateDebug = [StateDebug; x_aug.'];
|
|
end
|
|
if strcmp(status, 'error')
|
|
errorFlag = 0;
|
|
break;
|
|
end
|
|
|
|
if mod(it,optionsKF.samplingFactor)==0
|
|
if optionsKF.debug == true
|
|
fprintf('Debug: Initial parameter error = %d\n', norm(Beta_0-benchmarkSettings.Beta_obj));
|
|
fprintf('Debug: Current parameter error = %d\n', norm(x_aug(end-paramSize+1:end)-benchmarkSettings.Beta_obj));
|
|
else
|
|
fprintf('.')
|
|
end
|
|
pNoise(counter) = pNoiseAdaptParams.cov(1);
|
|
State(counter,:) = x_aug.';
|
|
Covariance(:,:,counter) = P;
|
|
if optionsKF.debug == true
|
|
image(1e3*P);
|
|
title('Covariance Matrix')
|
|
drawnow
|
|
end
|
|
counter = counter+1;
|
|
end
|
|
it = it+1;
|
|
end
|
|
|
|
fprintf('.\n')
|
|
|
|
%% Debug plot
|
|
|
|
if optionsKF.debug == true
|
|
augmentedDesiredState = benchmarkSettings.trajectoryData.getTrajectoryData(t, benchmarkSettings.interpolationAlgorithm); % augmentedState = [Qpp; Qp; Q];
|
|
for i = 1:3*robot.nbDOF
|
|
augmentedDesiredState_decim(i,:) = decimate(augmentedDesiredState(i,:),benchmarkSettings.decimRate);
|
|
end
|
|
|
|
figure('Name',sprintf('%s: Position Estimation',optionsKF.type));
|
|
for jointNb = 1:robot.nbDOF
|
|
subplot(ceil(robot.nbDOF/2),2,jointNb)
|
|
graph(1) = plot(augmentedDesiredState_decim(2*robot.nbDOF+jointNb,:),'Color',[0,0,0.5], 'LineWidth',1);
|
|
hold on
|
|
graph(2) = plot(Q_decim(jointNb,2:end),'Color',[0.8,0,0],'LineWidth',1);
|
|
hold on
|
|
graph(3) = plot(StateDebug(:,robot.nbDOF+jointNb),'Color',[0,0.75,0], 'LineWidth',1);
|
|
xlabel('\textbf{Iterations}','Interpreter', 'LaTeX');
|
|
ylabel('\textbf{Joint position [rad]}','Interpreter', 'LaTeX');
|
|
title(sprintf('\\textbf{Joint %d}', jointNb),'Interpreter', 'LaTeX');
|
|
grid on
|
|
grid minor
|
|
end
|
|
sgtitle('Nonlinear Kalman Position Estimation','Interpreter', 'LaTeX')
|
|
legendInfo{1}='Desired';
|
|
legendInfo{2}='Measured';
|
|
legendInfo{3}='Kalman estimate';
|
|
legend(graph,legendInfo{:},'Interpreter', 'LaTeX')
|
|
|
|
|
|
figure('Name',sprintf('%s: Velocity Estimation',optionsKF.type));
|
|
for jointNb = 1:robot.nbDOF
|
|
subplot(ceil(robot.nbDOF/2),2,jointNb)
|
|
graph(1) = plot(augmentedDesiredState_decim(robot.nbDOF+jointNb,:),'Color',[0,0,0.5], 'LineWidth',1);
|
|
hold on
|
|
graph(2) = plot(Qp_decim(jointNb,2:end).','Color',[0.8,0,0], 'LineWidth',1);
|
|
hold on
|
|
graph(3) = plot(StateDebug(:,jointNb),'Color',[0,0.75,0], 'LineWidth',1);
|
|
xlabel('\textbf{Iterations}','Interpreter', 'LaTeX');
|
|
ylabel('\textbf{Joint velocity [rad/s]}','Interpreter', 'LaTeX');
|
|
title(sprintf('\\textbf{Joint %d}', jointNb),'Interpreter', 'LaTeX');
|
|
grid on
|
|
grid minor
|
|
end
|
|
sgtitle('Nonlinear Kalman Velocity Estimation','Interpreter', 'LaTeX')
|
|
legendInfo{1}='Desired';
|
|
legendInfo{2}='Measured';
|
|
legendInfo{3}='Kalman estimate';
|
|
legend(graph,legendInfo{:},'Interpreter', 'LaTeX')
|
|
|
|
figure('Name',sprintf('%s: Parameter Estimation',optionsKF.type));
|
|
cc=parula(robot.paramVectorSize);
|
|
for i=1:robot.paramVectorSize
|
|
plot(StateDebug(:,2*robot.nbDOF+i),'LineWidth',2 ,'color',cc(i,:))
|
|
hold on
|
|
plot(repmat(benchmarkSettings.Beta_obj(i),1,numel(t_decim)-1)','--','LineWidth',2,'color',cc(i,:))
|
|
end
|
|
legend('Identified Parameters','True Parameters')
|
|
xlabel('Iterations');
|
|
ylabel('Beta');
|
|
title('Nonlinear Kalman Parameter Estimation')
|
|
grid on
|
|
grid minor
|
|
|
|
err = State(2:end-9,2*robot.nbDOF+1:end)-repmat(benchmarkSettings.Beta_obj',size(State,1)-10,1);
|
|
err2 = sum(err'.^2,1);
|
|
|
|
figure('Name','Convergence');
|
|
subplot(2,1,1)
|
|
plot(err2,'LineWidth',2 )
|
|
legend('Squared Error')
|
|
ylim([0 10]);
|
|
xlabel('Iterations');
|
|
ylabel('Error');
|
|
title('Convergence of KF Parameter Estimation')
|
|
grid on
|
|
grid minor
|
|
subplot(2,1,2)
|
|
plot(pNoise(2:end),'LineWidth',2)
|
|
legend('Annealing factor')
|
|
xlabel('Samples');
|
|
ylabel('Annealing');
|
|
title('Covariance Matrix Annealing')
|
|
grid on
|
|
grid minor
|
|
|
|
pause
|
|
end
|
|
|
|
Beta_KF = x_aug(end-paramSize+1:end);
|
|
|
|
end
|
|
|