BIRDy/Benchmark/Robot_Identification_Algori.../CLIE/CLIE_identification.m

202 lines
12 KiB
Mathematica
Raw Permalink Normal View History

2021-04-29 09:42:38 +00:00
function [Beta_CLIE, fval, output, exitflag, lambda, jacobian] = CLIE_identification(robot, benchmarkSettings, experimentDataStruct, expNb, Beta_0, optionsCLIE)
% Authors: Quentin Leboutet, Julien Roux, Alexandre Janot and Gordon Cheng
%
% Parameter identification using the Closed-Loop Input Error (CLIE) method.
%% Data Decimation and Filtering:
[~, ~, ~, ~, ~, ~, Tau_decim, ~, ~, ~, optionsCLIE] = getFilteredData(robot, benchmarkSettings, experimentDataStruct, optionsCLIE, expNb, 'CLIE');
%% CLIE Identification:
% Interesting: allows to visualize the optimization landscape for two variables... Takes a lot of time to execute !
% fcontour(@(x, y) compute_CLIE_Cost(robot, benchmarkSettings, [x;y;Beta_0(3:end)], Tau_decim, optionsCLIE, t_ndecim),[benchmarkSettings.Beta_L(1) benchmarkSettings.Beta_U(1) benchmarkSettings.Beta_L(2) benchmarkSettings.Beta_U(2)], 'MeshDensity',10)
if optionsCLIE.isParamWise == true % Parameter-wise identification (takes a very long time !!!)
Beta_it = Beta_0;
Beta_next_it = Beta_0;
Betas = zeros(robot.paramVectorSize, optionsCLIE.stopCrit.Max_it+1);
F = compute_CLIE_Cost(robot, benchmarkSettings, Beta_0, Tau_decim, optionsCLIE);
stop_1 = 1;
stop_2 = 1;
it = 1;
while it <= optionsCLIE.stopCrit.Max_it && stop_1 > optionsCLIE.stopCrit.tol_1 && stop_2 > optionsCLIE.stopCrit.tol_2
Betas(:,it)=Beta_it;
lambda.upper = 0;
lambda.lower = 0;
jacobian = 0;
for coeff_beta=1:robot.paramVectorSize
fprintf('Iteration %d, Parameter %d', it, coeff_beta)
switch optionsCLIE.paramwiseOptimizer
case 'simplex'
if optionsCLIE.debug == true
options = optimset('Display', 'iter', 'PlotFcns', {@optimplotx, @optimplotfunccount});
else
options = optimset('Display', 'iter');
end
[Beta_next_it(coeff_beta),fval,exitflag,output] = fminsearch(@(val_beta) compute_CLIE_Cost(robot, benchmarkSettings, Beta_it, Tau_decim, optionsCLIE, coeff_beta, val_beta), Beta_next_it(coeff_beta), options);
case 'lsqnonlin'
if optionsCLIE.debug == true
options = optimoptions('lsqnonlin', 'Algorithm','levenberg-marquardt', 'PlotFcn',{@optimplotx, @optimplotfunccount, @optimplotresnorm, @optimplotstepsize, @optimplotfirstorderopt});
else
options = optimoptions('lsqnonlin', 'Algorithm','levenberg-marquardt');
end
[Beta_next_it(coeff_beta),resnorm,fval,exitflag,output,lambda,jacobian] = lsqnonlin(@(val_beta) compute_CLIE_Cost(robot, benchmarkSettings, Beta_it, Tau_decim, optionsCLIE, coeff_beta, val_beta), Beta_next_it(coeff_beta), [], [], options);
otherwise
error("CLIE: unknown paramwiseOptimizer option");
end
end
% Updating stop criteria:
stop_1 = norm(Beta_next_it-Beta_it)/norm(Beta_it);
G = compute_CLIE_Cost(robot, benchmarkSettings, Beta_next_it, Tau_decim, optionsCLIE);
stop_2 = abs(G-F);
F = G;
Beta_it = Beta_next_it;
it = it+1;
end
Beta_CLIE = Beta_next_it;
if it == optionsCLIE.stopCrit.Max_it+1
flag = 1;
elseif stop_1 <= optionsCLIE.stopCrit.tol_1
flag = 2;
elseif stop_2 <= optionsCLIE.stopCrit.tol_2
flag = 3;
else
flag = 0;
end
else % Global parameter vector identification
numcores = feature('numcores');
population = 20*numcores;
lambda.upper = 0;
lambda.lower = 0;
jacobian = 0;
switch optionsCLIE.globalOptimizer
case 'simplex'
if optionsCLIE.debug == true
options = optimset('Display', 'iter', 'MaxIter', optionsCLIE.stopCrit.Max_it, 'TolFun', optionsCLIE.stopCrit.tol_1, 'TolX', optionsCLIE.stopCrit.tol_2, 'PlotFcns', {@optimplotx, @optimplotfunccount, @optimplotfval});
else
options = optimset('Display', 'iter', 'MaxIter', optionsCLIE.stopCrit.Max_it, 'TolFun', optionsCLIE.stopCrit.tol_1, 'TolX', optionsCLIE.stopCrit.tol_2);
end
[Beta_CLIE,fval,exitflag,output] = fminsearch(@(beta) compute_CLIE_Cost(robot, benchmarkSettings, beta, Tau_decim, optionsCLIE), Beta_0, options);
case 'lsqnonlin'
if optionsCLIE.debug == true
options = optimoptions('lsqnonlin', 'Algorithm','levenberg-marquardt', 'MaxIterations', optionsCLIE.stopCrit.Max_it, 'FunctionTolerance', optionsCLIE.stopCrit.tol_1, 'StepTolerance', optionsCLIE.stopCrit.tol_2,'UseParallel', true, 'PlotFcn',{@optimplotx, @optimplotfunccount, @optimplotresnorm, @optimplotstepsize, @optimplotfirstorderopt});
else
options = optimoptions('lsqnonlin', 'Algorithm','levenberg-marquardt', 'MaxIterations', optionsCLIE.stopCrit.Max_it, 'FunctionTolerance', optionsCLIE.stopCrit.tol_1, 'StepTolerance', optionsCLIE.stopCrit.tol_2,'UseParallel', true);
end
[Beta_CLIE,resnorm,fval,exitflag,output,lambda,jacobian] = lsqnonlin(@(beta) compute_CLIE_Cost(robot, benchmarkSettings, beta, Tau_decim, optionsCLIE), Beta_0,[],[], options);
case 'pso'
initialPopulationMatrix = repmat(Beta_0',population,1);
initialPopulationMatrix = initialPopulationMatrix + 0.01*randn(size(initialPopulationMatrix)).*initialPopulationMatrix;
if optionsCLIE.debug == true
options = optimoptions('particleswarm', 'SwarmSize', population, 'InitialSwarmMatrix', initialPopulationMatrix, 'Display', 'iter', 'PlotFcn', @pswplotbestf, 'UseParallel', true);
else
options = optimoptions('particleswarm', 'SwarmSize', population, 'InitialSwarmMatrix', initialPopulationMatrix, 'Display', 'iter', 'UseParallel', true);
end
[Beta_CLIE,fval,exitflag,output] = particleswarm(@(beta) compute_CLIE_Cost(robot, benchmarkSettings, beta', Tau_decim, optionsCLIE), robot.paramVectorSize, benchmarkSettings.Beta_L, benchmarkSettings.Beta_U, options);
Beta_CLIE = Beta_CLIE.';
case 'ga'
initialPopulationMatrix = repmat(Beta_0',population,1);
initialPopulationMatrix = initialPopulationMatrix + 0.01*randn(size(initialPopulationMatrix)).*initialPopulationMatrix;
if optionsCLIE.debug == true
options = optimoptions('ga', 'MaxStallGenerations', 20, 'MutationFcn', @mutationadaptfeasible, 'FunctionTolerance', optionsCLIE.stopCrit.tol_1, 'Display', 'iter', 'MaxGenerations', optionsCLIE.stopCrit.Max_it, 'PlotFcn', {@gaplotbestindiv,@gaplotdistance,@gaplotrange}, 'PopulationSize', population, 'InitialPopulationMatrix', initialPopulationMatrix, 'UseParallel', true, 'EliteCount', floor(population/2), 'CrossoverFraction', 0.9);
else
options = optimoptions('ga', 'MaxStallGenerations', 20, 'MutationFcn', @mutationadaptfeasible, 'FunctionTolerance', optionsCLIE.stopCrit.tol_1, 'Display', 'iter', 'MaxGenerations', optionsCLIE.stopCrit.Max_it, 'PopulationSize', population, 'InitialPopulationMatrix', initialPopulationMatrix, 'UseParallel', true, 'EliteCount', floor(population/2), 'CrossoverFraction', 0.9);
end
[Beta_CLIE,fval,exitflag,output] = ga(@(beta) compute_CLIE_Cost(robot, benchmarkSettings, beta', Tau_decim, optionsCLIE), robot.paramVectorSize, [], [], [], [], benchmarkSettings.Beta_L, benchmarkSettings.Beta_U, [], options);
Beta_CLIE = Beta_CLIE.';
end
end
%% Debug plot
debugPlot(robot, benchmarkSettings, experimentDataStruct, Beta_0, Beta_CLIE, optionsCLIE, expNb, 'CLIE');
end
function [costVariable] = compute_CLIE_Cost(robot, benchmarkSettings, beta, Tau_decim, optionsCLIE, coeff_beta, val_beta)
if nargin >= 10
Beta = beta;
Beta(coeff_beta) = val_beta;
else
Beta = beta;
end
if strcmp(benchmarkSettings.codeImplementation,'optim')
% Compute the sampled vector:
Y_tau = torqueVector_mex(Tau_decim);
elseif strcmp(benchmarkSettings.codeImplementation,'classic')
% Compute the sampled vector:
Y_tau = torqueVector(Tau_decim);
else
error("CLIE: unknown option");
end
W = zeros(robot.nbDOF*optionsCLIE.nbSampleDecim, robot.paramVectorSize);
t_ctrl = linspace(benchmarkSettings.t_i, benchmarkSettings.t_f, benchmarkSettings.nbCtrlSamples); % Control epochs
augmentedDesiredState = benchmarkSettings.trajectoryData.getTrajectoryData(t_ctrl, benchmarkSettings.interpolationAlgorithm); % augmentedState = [Qpp; Qp; Q];
% Simulation of the robot:
if strcmp(benchmarkSettings.codeImplementation,'optim')
% Simulation of the robot using the current parameters:
[~, State_it, Qpp_itt] = integrateClosedLoopDynamics_mex(augmentedDesiredState, Beta, robot.name, robot.numericalParameters.Geometry, ...
robot.numericalParameters.Gravity, benchmarkSettings.t_i, benchmarkSettings.t_f, benchmarkSettings.nbCtrlSamples, benchmarkSettings.nbSamples, ...
robot.controlParameters.Kp, robot.controlParameters.Ki, robot.controlParameters.Kd, robot.controlParameters.Ktau, robot.controlParameters.antiWindup, ...
robot.physicalConstraints.limQ_L, robot.physicalConstraints.limQ_U, robot.physicalConstraints.limQp_L, robot.physicalConstraints.limQp_U, ...
robot.physicalConstraints.limQpp_L, robot.physicalConstraints.limQpp_U, robot.physicalConstraints.limTau_L, robot.physicalConstraints.limTau_U, benchmarkSettings.integrationAlgorithm);
elseif strcmp(benchmarkSettings.codeImplementation,'classic')
% Simulation of the robot using the current parameters:
[~, State_it, Qpp_itt] = integrateClosedLoopDynamics(augmentedDesiredState, Beta, robot.name, robot.numericalParameters.Geometry, ...
robot.numericalParameters.Gravity, benchmarkSettings.t_i, benchmarkSettings.t_f, benchmarkSettings.nbCtrlSamples, benchmarkSettings.nbSamples, ...
robot.controlParameters.Kp, robot.controlParameters.Ki, robot.controlParameters.Kd, robot.controlParameters.Ktau, robot.controlParameters.antiWindup, ...
robot.physicalConstraints.limQ_L, robot.physicalConstraints.limQ_U, robot.physicalConstraints.limQp_L, robot.physicalConstraints.limQp_U, ...
robot.physicalConstraints.limQpp_L, robot.physicalConstraints.limQpp_U, robot.physicalConstraints.limTau_L, robot.physicalConstraints.limTau_U, benchmarkSettings.integrationAlgorithm);
else
error("CLIE: unknown implementation option");
end
Qp_it = State_it(1:robot.nbDOF,benchmarkSettings.samplingBorder+1:end-benchmarkSettings.samplingBorder);
Q_it = State_it(robot.nbDOF+1:end,benchmarkSettings.samplingBorder+1:end-benchmarkSettings.samplingBorder);
Qpp_it = Qpp_itt(:,benchmarkSettings.samplingBorder+1:end-benchmarkSettings.samplingBorder);
if strcmp(benchmarkSettings.codeImplementation,'optim')
% Building of the observation matrix W for the current iteration of Beta:
W_ndec = observationMatrix_mex(robot.name, robot.paramVectorSize, robot.numericalParameters.Geometry, robot.numericalParameters.Gravity, Q_it, Qp_it, Qpp_it);
elseif strcmp(benchmarkSettings.codeImplementation,'classic')
% Building of the observation matrix W for the current iteration of Beta:
W_ndec = observationMatrix(robot.name, robot.paramVectorSize, robot.numericalParameters.Geometry, robot.numericalParameters.Gravity, Q_it, Qp_it, Qpp_it);
else
error("CLIE: unknown option");
end
% Decimation filter
for col=1:robot.paramVectorSize
for i = 1:robot.nbDOF
W(i:robot.nbDOF:end,col) = decimate(W_ndec(i:robot.nbDOF:end,col),benchmarkSettings.decimRate);
end
end
Y_tau_reconstructed = W*Beta;
err = Y_tau_reconstructed - Y_tau;
if strcmp(optionsCLIE.globalOptimizer, 'lsqnonlin')
costVariable = err(:);
else
costVariable = err(:)'*err(:);
end
end