2024-01-23 13:42:25 +00:00
|
|
|
function robot = get_baseParams(robot,opt)
|
|
|
|
|
% Seed the random number generator based on the current time
|
2024-10-25 15:41:23 +00:00
|
|
|
rng("default");
|
2024-01-23 13:42:25 +00:00
|
|
|
ndof = robot.ndof;
|
|
|
|
|
includeMotorDynamics = false;
|
|
|
|
|
% ------------------------------------------------------------------------
|
|
|
|
|
% Set limits on posistion and velocities
|
|
|
|
|
% ------------------------------------------------------------------------
|
|
|
|
|
q_min = -pi*ones(ndof,1);
|
|
|
|
|
q_max = pi*ones(ndof,1);
|
|
|
|
|
qd_max = 3*pi*ones(ndof,1);
|
|
|
|
|
q2d_max = 6*pi*ones(ndof,1);
|
|
|
|
|
% -----------------------------------------------------------------------
|
|
|
|
|
% Find relation between independent columns and dependent columns
|
|
|
|
|
% -----------------------------------------------------------------------
|
|
|
|
|
% Get observation matrix of identifiable paramters
|
2024-11-10 16:23:28 +00:00
|
|
|
W = [];
|
2024-10-25 15:41:23 +00:00
|
|
|
for i = 1:25
|
2024-01-23 13:42:25 +00:00
|
|
|
q_rnd = q_min + (q_max - q_min).*rand(ndof,1);
|
|
|
|
|
qd_rnd = -qd_max + 2*qd_max.*rand(ndof,1);
|
|
|
|
|
q2d_rnd = -q2d_max + 2*q2d_max.*rand(ndof,1);
|
|
|
|
|
|
|
|
|
|
if includeMotorDynamics
|
|
|
|
|
% Y = regressorWithMotorDynamics(q_rnd,qd_rnd,q2d_rnd);
|
2024-11-10 16:23:28 +00:00
|
|
|
elseif opt.isJointTorqueSensor
|
2024-01-23 13:42:25 +00:00
|
|
|
standard_regressor_func = sprintf('standard_regressor_%s',opt.robotName);
|
|
|
|
|
Y = feval(standard_regressor_func, q_rnd,qd_rnd,q2d_rnd);
|
2024-11-10 16:23:28 +00:00
|
|
|
% joint_idex = ndof-2;
|
|
|
|
|
% Y = Y(joint_idex:end,:);
|
|
|
|
|
elseif opt.isSixAxisFTSensor
|
2024-11-05 15:20:47 +00:00
|
|
|
regressor_func = sprintf('regressor_%s',opt.robotName);
|
|
|
|
|
Y = feval(regressor_func, q_rnd,qd_rnd,q2d_rnd);
|
|
|
|
|
joint_idex = ndof-2;
|
|
|
|
|
Y = Y(6*(joint_idex-1)+1:6*(joint_idex),:);
|
2024-11-05 12:54:56 +00:00
|
|
|
% FIXME hack here
|
2024-11-05 15:20:47 +00:00
|
|
|
% standard_regressor_func = sprintf('standard_regressor_%s',opt.robotName);
|
|
|
|
|
% Y = feval(standard_regressor_func, q_rnd,qd_rnd,q2d_rnd);
|
|
|
|
|
% Zeros_ = zeros(size(Y));
|
|
|
|
|
% Zeros_(ndof-2,:) = Y(ndof-2,:);
|
|
|
|
|
% Y = Zeros_;
|
2024-01-23 13:42:25 +00:00
|
|
|
end
|
|
|
|
|
W = vertcat(W,Y);
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
% QR decomposition with pivoting: W*E = Q*R
|
|
|
|
|
% R is upper triangular matrix
|
|
|
|
|
% Q is unitary matrix
|
|
|
|
|
% E is permutation matrix
|
2024-10-25 15:41:23 +00:00
|
|
|
[~, R, E] = qr(W);
|
2024-01-23 13:42:25 +00:00
|
|
|
|
|
|
|
|
% matrix W has rank qr_rank which is number number of base parameters
|
|
|
|
|
qr_rank = rank(W);
|
|
|
|
|
|
|
|
|
|
% R = [R1 R2;
|
|
|
|
|
% 0 0]
|
2024-10-25 14:34:21 +00:00
|
|
|
% R1 is bbxbb upper triangular and regu ar matrix
|
2024-01-23 13:42:25 +00:00
|
|
|
% R2 is bbx(c-qr_rank) matrix where c is number of standard parameters
|
|
|
|
|
R1 = R(1:qr_rank,1:qr_rank);
|
|
|
|
|
R2 = R(1:qr_rank,qr_rank+1:end);
|
|
|
|
|
beta = R1\R2; % the zero rows of K correspond to independent columns of WP
|
2024-10-25 15:41:23 +00:00
|
|
|
beta(abs(beta)<10^-5) = 0; % get rid of numerical errors
|
2024-01-23 13:42:25 +00:00
|
|
|
% W2 = W1*beta
|
|
|
|
|
|
|
|
|
|
% Make sure that the relation holds
|
|
|
|
|
W1 = W*E(:,1:qr_rank);
|
|
|
|
|
W2 = W*E(:,qr_rank+1:end);
|
2024-10-25 15:41:23 +00:00
|
|
|
assert(norm(W2 - W1*beta) < 1e-3,...
|
2024-01-23 13:42:25 +00:00
|
|
|
'Found realationship between W1 and W2 is not correct\n');
|
|
|
|
|
|
|
|
|
|
% -----------------------------------------------------------------------
|
|
|
|
|
% Find base parmaters
|
|
|
|
|
% -----------------------------------------------------------------------
|
2024-10-25 14:34:21 +00:00
|
|
|
if(opt.Isreal)
|
|
|
|
|
pi_lgr_num = robot.pi;
|
|
|
|
|
[nLnkPrms, nLnks] = size(pi_lgr_num);
|
|
|
|
|
pi_lgr_num = reshape(pi_lgr_num, [nLnkPrms*nLnks, 1]);
|
|
|
|
|
pi1 = E(:,1:qr_rank)'*pi_lgr_num; % independent paramters
|
|
|
|
|
pi2 = E(:,qr_rank+1:end)'*pi_lgr_num; % dependent paramteres
|
|
|
|
|
pi_lgr_base = pi1 + beta*pi2;
|
|
|
|
|
else
|
|
|
|
|
pi_lgr_sym = robot.regressor.pi;
|
|
|
|
|
pi1 = E(:,1:qr_rank)'*pi_lgr_sym; % independent paramters
|
|
|
|
|
pi2 = E(:,qr_rank+1:end)'*pi_lgr_sym; % dependent paramteres
|
|
|
|
|
|
|
|
|
|
% all of the expressions below are equivalent
|
|
|
|
|
pi_lgr_base = pi1 + beta*pi2;
|
|
|
|
|
% pi_lgr_base = [eye(qr_rank) beta]*[pi1;pi2];
|
|
|
|
|
% pi_lgr_base = [eye(qr_rank) beta]*E'*pi_lgr_sym;
|
|
|
|
|
end
|
2024-01-23 13:42:25 +00:00
|
|
|
% ---------------------------------------------------------------------
|
|
|
|
|
% Create structure with the result of QR decompositon a
|
|
|
|
|
% ---------------------------------------------------------------------
|
|
|
|
|
baseQR = struct;
|
|
|
|
|
baseQR.numberOfBaseParameters = qr_rank;
|
|
|
|
|
baseQR.permutationMatrix = E;
|
|
|
|
|
baseQR.beta = beta;
|
|
|
|
|
baseQR.motorDynamicsIncluded = includeMotorDynamics;
|
|
|
|
|
baseQR.baseParams = pi_lgr_base;
|
|
|
|
|
robot.baseQR = baseQR;
|
|
|
|
|
robot.baseQR.regressor = robot.regressor.K*robot.baseQR.permutationMatrix(:,1:robot.baseQR.numberOfBaseParameters);
|
2024-10-25 14:34:21 +00:00
|
|
|
|
2024-11-10 16:23:28 +00:00
|
|
|
% Get observation matrix of identifiable paramters
|
|
|
|
|
for j = 1:robot.ndof
|
|
|
|
|
W = [];
|
|
|
|
|
for i = 1:25
|
|
|
|
|
q_rnd = q_min + (q_max - q_min).*rand(ndof,1);
|
|
|
|
|
qd_rnd = -qd_max + 2*qd_max.*rand(ndof,1);
|
|
|
|
|
q2d_rnd = -q2d_max + 2*q2d_max.*rand(ndof,1);
|
|
|
|
|
standard_regressor_func = sprintf('standard_regressor_%s',opt.robotName);
|
|
|
|
|
Y = feval(standard_regressor_func, q_rnd,qd_rnd,q2d_rnd);
|
|
|
|
|
W = vertcat(W,Y(j,:));
|
|
|
|
|
end
|
|
|
|
|
% matrix W has rank qr_rank which is number number of base parameters
|
|
|
|
|
robot.baseQR.rank(j) = rank(W);
|
|
|
|
|
end
|
|
|
|
|
|
2024-10-25 14:34:21 +00:00
|
|
|
if(opt.reGenerate)
|
|
|
|
|
tic
|
|
|
|
|
disp('compiling robot.baseQR.regressor');
|
|
|
|
|
% ---------------------------------------------------------------------
|
|
|
|
|
% Gen base_regressor
|
|
|
|
|
% ---------------------------------------------------------------------
|
|
|
|
|
q_sym = sym('q%d',[ndof+1,1],'real');
|
|
|
|
|
qd_sym = sym('qd%d',[ndof+1,1],'real');
|
|
|
|
|
q2d_sym = sym('qdd%d',[ndof+1,1],'real');
|
|
|
|
|
matlabFunction(robot.baseQR.regressor,'File',sprintf('autogen/base_regressor_%s',opt.robotName),...
|
|
|
|
|
'Vars',{q_sym,qd_sym,q2d_sym});
|
|
|
|
|
fprintf("The total compile time was: = %d minutes, %d seconds\n", floor(compileTime/60), ceil(rem(compileTime,60)));
|
|
|
|
|
end
|