added file that check if optimized trajectory collides with table on which the robot is fixed. Moreover kinematics of UR is derived is analytical form, so it can be used in trajectory optimization in order to stay away from table, however is considerably slows down the optimization. Even on sever with 40 cpus patter search computes it for hours. Moreover, added files for identification of the pendubot.

This commit is contained in:
Shamil Mamedov 2020-02-05 07:55:09 +03:00
parent 141b563911
commit fe3cc01102
50 changed files with 6514 additions and 119004 deletions

View File

@ -0,0 +1,21 @@
function pos = position_fk_UR10E(in1)
%POSITION_FK_UR10E
% POS = POSITION_FK_UR10E(IN1)
% This function was generated by the Symbolic Math Toolbox version 8.2.
% 31-Jan-2020 07:44:23
q1 = in1(1,:);
q2 = in1(2,:);
q3 = in1(3,:);
q4 = in1(4,:);
t2 = sin(1.57079632679);
t3 = cos(q1);
t4 = cos(q2);
t5 = cos(q3);
t6 = sin(q2);
t7 = sin(q3);
t8 = sin(q1);
t9 = cos(q4);
t10 = sin(q4);
pos = [t8.*(-8.7e1./5.0e2)-t2.*t9.*(t2.*t3.*t4.*t7+t2.*t3.*t5.*t6).*(3.0./2.5e1)-t2.*t10.*(t2.*t3.*t4.*t5-t2.*t3.*t6.*t7).*(3.0./2.5e1)+t2.*t3.*t4.*(6.13e2./1.0e3)+t2.*t3.*t4.*t5.*(5.71e2./1.0e3)-t2.*t3.*t6.*t7.*(5.71e2./1.0e3);t3.*(8.7e1./5.0e2)-t2.*t9.*(t2.*t4.*t7.*t8+t2.*t5.*t6.*t8).*(3.0./2.5e1)-t2.*t10.*(t2.*t4.*t5.*t8-t2.*t6.*t7.*t8).*(3.0./2.5e1)+t2.*t4.*t8.*(6.13e2./1.0e3)+t2.*t4.*t5.*t8.*(5.71e2./1.0e3)-t2.*t6.*t7.*t8.*(5.71e2./1.0e3);t2.*t6.*(-6.13e2./1.0e3)-t2.*t9.*(t2.*t4.*t5-t2.*t6.*t7).*(3.0./2.5e1)+t2.*t10.*(t2.*t4.*t7+t2.*t5.*t6).*(3.0./2.5e1)-t2.*t4.*t7.*(5.71e2./1.0e3)-t2.*t5.*t6.*(5.71e2./1.0e3)+1.81e2./1.0e3];

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -3,8 +3,9 @@ function frctn = frictionRegressor(qd_fltrd)
% The function computes friction regressor for each joint of the robot.
% Fv*qd + Fc*sign(qd) + F0, and the second one is continous,
% ---------------------------------------------------------------------
frctn = zeros(6,18);
for i = 1:6
noJoints = size(qd_fltrd,1);
frctn = zeros(noJoints, noJoints*3);
for i = 1:noJoints
frctn(i,3*i-2:3*i) = [qd_fltrd(i), sign(qd_fltrd(i)), 1];
end

24
functions/ur_fk.m Normal file
View File

@ -0,0 +1,24 @@
function pos = ur_fk(q, ur)
T_pk = zeros(4,4,6); % transformation between links
T_0k = zeros(4,4,7); T_0k(:,:,1) = eye(4);
for i = 1:6
jnt_axs_k = str2num(ur.robot.joint{i}.axis.Attributes.xyz)';
% Transformation from parent link frame p to current joint frame
rpy_k = str2num(ur.robot.joint{i}.origin.Attributes.rpy);
R_pj = RPY(rpy_k);
p_pj = str2num(ur.robot.joint{i}.origin.Attributes.xyz)';
T_pj = [R_pj, p_pj; zeros(1,3), 1]; % to avoid numerical errors
% Tranformation from joint frame of the joint that rotaties body k to
% link frame. The transformation is pure rotation
R_jk = Rot(q(i), jnt_axs_k);
p_jk = zeros(3,1);
T_jk = [R_jk, p_jk; zeros(1,3),1];
% Transformation from parent link frame p to current link frame k
T_pk(:,:,i) = T_pj*T_jk;
% Transformation to base
T_0k(:,:,i+1) = T_0k(:,:,i)*T_pk(:,:,i);
end
pos = T_0k(1:3,4,7);
% (T_0k(1:3,4,7)-T_0k(1:3,4,5))'

67
planar2DOF/bags_pndbt.m Normal file
View File

@ -0,0 +1,67 @@
clc; clear all;
name = 'current_A_0.7_v_1.bag';
bag = rosbag(name);
end_time = 20;
% extract the desired topics
start = bag.StartTime;
bagselect_current = select(bag, 'Time', [start start + end_time], 'Topic', '/current_synch' );
bagselect_torque = select(bag, 'Time', [start start + end_time], 'Topic','/netft_data_synch' );
bagselect_command = select(bag, 'Time', [start start + end_time], 'Topic', '/command_synch' );
bagselect_Jstates = select(bag, 'Time', [start start + end_time], 'Topic','/joint_states_synch' );
bagselect_position = select(bag, 'Time', [start start + end_time], 'Topic', '/position_synch' );
bagselect_velocity = select(bag, 'Time', [start start + end_time], 'Topic','/velocity_synch' );
%
% msgs = readMessages(bagselect, [1 2]);
% extract message data as time series
ts_cur = timeseries(bagselect_current, 'Data');
ts_trq = timeseries(bagselect_torque, 'Wrench.Torque.Z');
ts_cmd = timeseries(bagselect_command, 'Data');
ts_pos = timeseries(bagselect_position, 'Data');
ts_vel = timeseries(bagselect_velocity, 'Data');
% extract the joint states as time series
msgs = readMessages(bagselect_Jstates);
js_pos = [];
for i= 1:numel(msgs)
js_pos = [js_pos msgs{i}.Position];
end
js_vel = [];
for i= 1:numel(msgs)
js_vel = [js_vel msgs{i}.Velocity];
end
ts_Js_time = timeseries(bagselect_Jstates, 'Header.Stamp.Sec');
time = ts_Js_time.Time;
%
ts_Js_pos_shldr = timeseries(js_pos(1,:)',time);
ts_Js_pos_elbw = timeseries(js_pos(2,:)',time);
ts_Js_vel_shldr = timeseries(js_vel(1,:)',time);
ts_Js_vel_elbw = timeseries(js_vel(2,:)',time);
len = min([ts_Js_vel_elbw.Length, ts_Js_vel_shldr.Length, ts_Js_pos_elbw.Length, ...
ts_Js_pos_shldr.Length, ts_cur.Length, ts_trq.Length, ts_cmd.Length, ts_pos.Length, ts_vel.Length]);
% building the table of all the topics
time = ts_cur.Time(1:len);
current = ts_cur.Data(1:len);
torque = ts_trq.Data(1:len);
command = ts_cmd.Data(1:len);
position = ts_pos.Data(1:len);
velocity = ts_vel.Data(1:len);
shldr_position = ts_Js_pos_shldr.Data(1:len);
elbw_position = ts_Js_pos_elbw.Data(1:len);
shldr_velocity = ts_Js_vel_shldr.Data(1:len);
elbw_velocity = ts_Js_vel_elbw.Data(1:len);
T = table(time, current, torque, command, position, velocity, shldr_position, elbw_position, shldr_velocity, elbw_velocity);
data = T.Variables;
save(strcat('planar2DOF/data_pndbt/',name(1:end-4),'.mat'),'data');

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,24 @@
function Y = full_regressor_plnr(in1,in2,in3)
%FULL_REGRESSOR_PLNR
% Y = FULL_REGRESSOR_PLNR(IN1,IN2,IN3)
% This function was generated by the Symbolic Math Toolbox version 8.2.
% 03-Feb-2020 10:03:33
q1 = in1(1,:);
q2 = in1(2,:);
q2d1 = in3(1,:);
q2d2 = in3(2,:);
qd1 = in2(1,:);
qd2 = in2(2,:);
t2 = sin(1.5708);
t3 = cos(q2);
t4 = sin(q2);
t5 = cos(q1);
t6 = sin(q1);
t7 = qd2.^2;
t8 = t2.*t5.*(9.81e2./1.0e2);
t9 = q2d1+q2d2;
t10 = t2.*t3.*t5.*(9.81e2./1.0e2);
t11 = qd1.^2;
Y = reshape([0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,q2d1,0.0,t8,0.0,t2.*t6.*(-9.81e2./1.0e2),0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,t9,t9,t10+q2d1.*t3.*2.0+q2d2.*t3-t4.*t7-qd1.*qd2.*t4.*2.0-t2.*t4.*t6.*(9.81e2./1.0e2),t10+q2d1.*t3+t4.*t11-t2.*t4.*t6.*(9.81e2./1.0e2),q2d1.*t4.*-2.0-q2d2.*t4-t3.*t7-qd1.*qd2.*t3.*2.0-t2.*t3.*t6.*(9.81e2./1.0e2)-t2.*t4.*t5.*(9.81e2./1.0e2),-q2d1.*t4+t3.*t11-t2.*t3.*t6.*(9.81e2./1.0e2)-t2.*t4.*t5.*(9.81e2./1.0e2),0.0,0.0,q2d1+t8,0.0],[2,20]);

View File

@ -14,17 +14,17 @@
<link name = "link 1">
<inertial>
<origin xyz = "0.5 0 0"
<origin xyz = "0.125 0 0"
rpy = "0 0 0"/>
<mass value = "1" />
<mass value = "0.29" />
<inertia ixx = "1" iyy = "1" izz = "0.5"
ixy = "0.01" ixz = "0.01" iyz = "0.01" />
</inertial>
<visual>
<origin xyz = "0.5 0 0"
<origin xyz = "0.125 0 0"
rpy = "0 1.5708 0"/>
<geometry>
<cylinder radius = "0.1" length = "1" />
<cylinder radius = "0.1" length = "0.25" />
</geometry>
<material name = "gray C">
<color rgba = "0.3 0.6 0.1 1" />
@ -34,17 +34,17 @@
<link name = "link 2">
<inertial>
<origin xyz = "0.5 0 0"
<origin xyz = "0.125 0 0"
rpy = "0 0 0"/>
<mass value = "0.45" />
<mass value = "0.26" />
<inertia ixx = "1" iyy = "1" izz = "0.3"
ixy = "0.01" ixz = "0.01" iyz = "0.01" />
</inertial>
<visual>
<origin xyz = "0.5 0 0"
<origin xyz = "0.125 0 0"
rpy = "0 1.5708 0"/>
<geometry>
<cylinder radius = "0.1" length = "1" />
<cylinder radius = "0.1" length = "0.25" />
</geometry>
<material name = "gray C">
<color rgba = "0.22 0.67 0.95 1" />
@ -68,7 +68,7 @@
<joint name = "joint 2" type = "revolute">
<parent link = "link 1" />
<child link = "link 2" />
<origin xyz = "1 0 0"
<origin xyz = "0.25 0 0"
rpy = "0 0 0"/>
<axis xyz = "0 0 1" />
<limit effort="100.0" lower="-6.2831853" upper="6.2831853" velocity="2.16"/>
@ -77,7 +77,7 @@
<joint name = "ee_fixed_joint" type = "fixed">
<parent link = "link 2" />
<child link = "ee_link" />
<origin xyz = "1 0 0"
<origin xyz = "0.25 0 0"
rpy = "0 0 0"/>
</joint>

BIN
planar2DOF/plnrBaseQR.mat Normal file

Binary file not shown.

150
planar2DOF/plnr_baseQR.m Normal file
View File

@ -0,0 +1,150 @@
% get robot description
run('plnr_idntfcn.m')
% Seed the random number generator based on the current time
rng('shuffle');
% some parameters
includeMotorDynamics = 1;
% limits on positions, velocities, accelerations
q_min = -deg2rad(160);
q_max = 0;
qd_min = -10;
qd_max = 10;
q2d_min = -100;
q2d_max = 100;
% -----------------------------------------------------------------------
% Find relation between independent columns and dependent columns
% -----------------------------------------------------------------------
% Get observation matrix of identifiable paramters
W = [];
for i = 1:20
q_rnd = q_min + (q_max - q_min).*rand(2,1);
qd_rnd = -qd_max + 2*qd_max.*rand(2,1);
q2d_rnd = -q2d_max + 2*q2d_max.*rand(2,1);
if includeMotorDynamics
Yi = regressorWithMotorDynamicsPndbt(q_rnd, qd_rnd, q2d_rnd);
else
Yi = full_regressor_plnr(q_rnd, qd_rnd, q2d_rnd);
end
W = vertcat(W,Yi);
end
% QR decomposition with pivoting: W*E = Q*R
% R is upper triangular matrix
% Q is unitary matrix
% E is permutation matrix
[Q,R,E] = qr(W);
% matrix W has rank bb which is number number of base parameters
bb = rank(W);
% R = [R1 R2;
% 0 0]
% R1 is bbxbb upper triangular and reguar matrix
% R2 is bbx(c-bb) matrix where c is number of standard parameters
R1 = R(1:bb,1:bb);
R2 = R(1:bb,bb+1:end);
beta = R1\R2; % the zero rows of K correspond to independent columns of WP
beta(abs(beta)<sqrt(eps)) = 0; % get rid of numerical errors
% W2 = W1*beta
% Make sure that the relation holds
W1 = W*E(:,1:bb);
W2 = W*E(:,bb+1:end);
if norm(W2 - W1*beta) > 1e-6
fprintf('Found realationship between W1 and W2 is not correct\n');
return
end
% Defining parameters symbolically
m = sym('m%d',[2,1],'real');
hx = sym('h%d_x',[2,1],'real');
hy = sym('h%d_y',[2,1],'real');
hz = sym('h%d_z',[2,1],'real');
ixx = sym('i%d_xx',[2,1],'real');
ixy = sym('i%d_xy',[2,1],'real');
ixz = sym('i%d_xz',[2,1],'real');
iyy = sym('i%d_yy',[2,1],'real');
iyz = sym('i%d_yz',[2,1],'real');
izz = sym('i%d_zz',[2,1],'real');
im = sym('im',[1,1],'real');
% Vector of symbolic parameters
pi_pndbt_sym = {};
for i = 1:2
pi_pndbt_sym{i} = [ixx(i),ixy(i),ixz(i),iyy(i),iyz(i),izz(i),...
hx(i),hy(i),hz(i),m(i)]';
end
if includeMotorDynamics
pi_pndbt_sym{1} = [pi_pndbt_sym{1}; im];
end
pi_pndbt_sym = [pi_pndbt_sym{1}; pi_pndbt_sym{2}];
% Find base parmaters
pi1 = E(:,1:bb)'*pi_pndbt_sym; % independent paramters
pi2 = E(:,bb+1:end)'*pi_pndbt_sym; % dependent paramteres
% all of the expressions below are equivalent
pi_lgr_base = pi1 + beta*pi2;
pi_lgr_base2 = [eye(bb) beta]*[pi1;pi2];
pi_lgr_base3 = [eye(bb) beta]*E'*pi_pndbt_sym;
% -----------------------------------------------------------------------
% Validation of obtained mappings
% -----------------------------------------------------------------------
fprintf('Validation of mapping from standard parameters to base ones\n')
if includeMotorDynamics
plnr.pi = [plnr.pi(:,1); rand; plnr.pi(:,2)];
else
plnr.pi = [plnr.pi(:,1); plnr.pi(:,2)];
end
% On random positions, velocities, aceeleations
for i = 1:100
q_rnd = q_min + (q_max - q_min).*rand(2,1);
qd_rnd = -qd_max + 2*qd_max.*rand(2,1);
q2d_rnd = -q2d_max + 2*q2d_max.*rand(2,1);
if includeMotorDynamics
Yi = regressorWithMotorDynamicsPndbt(q_rnd,qd_rnd,q2d_rnd);
else
Yi = full_regressor_plnr(q_rnd,qd_rnd,q2d_rnd);
end
tau_full = Yi*plnr.pi;
pi_lgr_base = [eye(bb) beta]*E'*plnr.pi;
Y_base = Yi*E(:,1:bb);
tau_base = Y_base*pi_lgr_base;
nrm_err1(i) = norm(tau_full - tau_base);
end
figure
plot(nrm_err1)
ylabel('||\tau - \tau_b||')
grid on
if ~all(nrm_err1<1e-6)
fprintf('Validation failed')
return
end
% ---------------------------------------------------------------------
% Create structure with the result of QR decompositon and save it
% for further use.
% ---------------------------------------------------------------------
plnrBaseQR = struct;
plnrBaseQR.numberOfBaseParameters = bb;
plnrBaseQR.permutationMatrix = E;
plnrBaseQR.beta = beta;
plnrBaseQR.motorDynamicsIncluded = includeMotorDynamics;
filename = 'planar2DOF/plnrBaseQR.mat';
save(filename,'plnrBaseQR')

View File

@ -1,14 +1,9 @@
clc; clear all; close all;
%-------------------------------------------------------------------------
% Loading file from urdf
% ------------------------------------------------------------------------
plnr = xml2struct('planar_manip.urdf');
% ------------------------------------------------------------------------
% Extracting parameters of the robot
% ------------------------------------------------------------------------
for i = 1:2
% axis of rotation of a joint i in coordinate system of joint i
axis_of_rot = str2num(plnr.robot.joint{i}.axis.Attributes.xyz)';
@ -40,6 +35,7 @@ for i = 1:2
plnr.pi(:,i) = [plnr.I_vec(:,i);plnr.h(:,i);plnr.m(i)];
end
return
% ------------------------------------------------------------------------
% Defining parameters symbolically
% ------------------------------------------------------------------------
@ -180,6 +176,7 @@ for i = 1:2
pi_base_vctr = vertcat(pi_base_vctr,pi_base_num{i});
end
return
% ------------------------------------------------------------------------
% Using lagrange equations of the second kind, find dynamics
% ------------------------------------------------------------------------

View File

@ -0,0 +1,87 @@
% get robot description
run('plnr_idntfcn.m');
% Symbolic generilized coordiates, their first and second deriatives
q_sym = sym('q%d',[2,1],'real');
qd_sym = sym('qd%d',[2,1],'real');
q2d_sym = sym('q2d%d',[2,1],'real');
% Getting energy functions, to derive dynamics
T_pk = sym(zeros(4,4,2)); % transformation between links
w_kk(:,1) = sym(zeros(3,1)); % angular velocity k in frame k
v_kk(:,1) = sym(zeros(3,1)); % linear velocity of the origin of frame k in frame k
g_kk(:,1) = sym([0,0,9.81])'; % vector of graviatational accelerations in frame k
p_kk(:,1) = sym(zeros(3,1)); % origin of frame k in frame k
for i = 1:2
jnt_axs_k = str2num(plnr.robot.joint{i}.axis.Attributes.xyz)';
% Transformation from parent link frame p to current joint frame
rpy_k = sym(str2num(plnr.robot.joint{i}.origin.Attributes.rpy));
R_pj = RPY(rpy_k);
% R_pj(abs(R_pj)<sqrt(eps)) = sym(0); % to avoid numerical errors
R_pj(abs(R_pj)<1e-5) = sym(0); % to avoid numerical errors
p_pj = str2num(plnr.robot.joint{i}.origin.Attributes.xyz)';
T_pj = sym([R_pj, p_pj; zeros(1,3), 1]); % to avoid numerical errors
% Tranformation from joint frame of the joint that rotaties body k to
% link frame. The transformation is pure rotation
R_jk = Rot(q_sym(i),sym(jnt_axs_k));
p_jk = sym(zeros(3,1));
T_jk = [R_jk, p_jk; sym(zeros(1,3)),sym(1)];
% Transformation from parent link frame p to current link frame k
T_pk(:,:,i) = T_pj*T_jk;
z_kk(:,i) = sym(jnt_axs_k);
w_kk(:,i+1) = T_pk(1:3,1:3,i)'*w_kk(:,i) + sym(jnt_axs_k)*qd_sym(i);
v_kk(:,i+1) = T_pk(1:3,1:3,i)'*(v_kk(:,i) + cross(w_kk(:,i),sym(p_pj)));
g_kk(:,i+1) = T_pk(1:3,1:3,i)'*g_kk(:,i);
p_kk(:,i+1) = T_pk(1:3,1:3,i)'*(p_kk(:,i) + sym(p_pj));
K_reg(i,:) = [sym(0.5)*w2wtlda(w_kk(:,i+1)),...
v_kk(:,i+1)'*vec2skewSymMat(w_kk(:,i+1)),...
sym(0.5)*v_kk(:,i+1)'*v_kk(:,i+1)];
P_reg(i,:) = [sym(zeros(1,6)), g_kk(:,i+1)',...
g_kk(:,i+1)'*p_kk(:,i+1)];
end
% Compose lagrangian
Lagr = [K_reg(1,:) - P_reg(1,:), K_reg(2,:) - P_reg(2,:)];
% Use Lagrange equations to derive regressor matrix
dLagr_dq = jacobian(Lagr,q_sym)';
dLagr_dqd = jacobian(Lagr,qd_sym)';
t1 = sym(zeros(2,20));
for i = 1:2
t1 = t1 + diff(dLagr_dqd,q_sym(i))*qd_sym(i)+...
diff(dLagr_dqd,qd_sym(i))*q2d_sym(i);
end
Y = simplify(t1 - dLagr_dq);
Y_fcn = matlabFunction(Y,'Vars',{q_sym, qd_sym, q2d_sym});
% Testing if regressor computed correctly using matlab Robotics Robotics
rbt = importrobot('planar_manip.urdf');
rbt.DataFormat = 'column';
rbt.Gravity = [0 0 -9.81];
noIter = 100;
err1 = zeros(noIter,1);
for i = 1:noIter
q = rand(2,1);
qd = rand(2,1);
q2d = rand(2,1);
Ylgr = Y_fcn(q,qd,q2d);
tau1 = inverseDynamics(rbt,q,qd,q2d);
tau2 = Ylgr*reshape(plnr.pi,[20,1]);
% verifying if regressor is computed correctly
err1(i) = norm(tau1 - tau2);
end
if all(err1<1e-6)
disp('Regressor matrix is computed correctly!')
disp('Generating regressor matrix function...')
matlabFunction(Y,'File','planar2DOF/full_regressor_plnr',...
'Vars',{q_sym, qd_sym, q2d_sym});
else
disp('Regressor matrix is not computed correctly. Check derivation')
end

View File

@ -0,0 +1,39 @@
function plnr_visualize(q, plnr)
figure
for j = 1:10:length(q)
clf
qj = q(j,:);
T_0k(:,:,1) = eye(4);
for i = 1:2
R_pj = RPY(str2num(plnr.robot.joint{i}.origin.Attributes.rpy));
p_pj = str2num(plnr.robot.joint{i}.origin.Attributes.xyz)';
T_pj = [R_pj, p_pj; zeros(1,3), 1];
R_jk = Rot(qj(i),plnr.k(:,i));
p_jk = zeros(3,1);
T_jk = [R_jk, p_jk; zeros(1,3),1];
T_pk(:,:,i) = T_pj*T_jk;
T_0k(:,:,i+1) = T_0k(:,:,i)*T_pk(:,:,i);
z_0k(:,i) = T_0k(1:3,1:3,i+1)*plnr.k(:,i);
r_0k(:,i) = [eye(3),zeros(3,1)]*T_0k(:,:,i+1)*[plnr.r_com(:,i);1];
end
R_pee = RPY(str2num(plnr.robot.joint{3}.origin.Attributes.rpy));
p_pee = str2num(plnr.robot.joint{3}.origin.Attributes.xyz)';
T_pee = [R_pee, p_pee; zeros(1,3), 1];
T_0ee = T_0k(:,:,3)*T_pee;
MARKER_SIZE = 100; %marker size of the scatter function
scatter(T_0k(1,4,2), T_0k(3,4,2),MARKER_SIZE,'k','filled')
hold on
scatter(T_0k(1,4,3), T_0k(3,4,3),MARKER_SIZE,'k','filled')
% scatter(Tee0(1,3), Tee0(2,3))
line([T_0k(1,4,2) T_0k(1,4,3)], [T_0k(3,4,2), T_0k(3,4,3)],'Color','k','LineWidth',1.5)
line([T_0k(1,4,3) T_0ee(1,4)], [T_0k(3,4,3), T_0ee(3,4)],'Color','k','LineWidth',1.5)
xlim([-0.5 0.5])
ylim([-0.6 0.2])
pause(1e-1)
end

View File

@ -0,0 +1,121 @@
% clc; clear all; close all;
% get robot description
run('plnr_idntfcn.m')
% load pendubot data
% rawData = load('current_A_5_v_4.mat');
rawData = load('current_A_0.7_v_1.mat');
% parse pendubot data
pendubot.time = rawData.data(:,1) - rawData.data(1,1);
pendubot.current = rawData.data(:,2);
pendubot.current_desired = rawData.data(:,4);
pendubot.torque = rawData.data(:,3);
pendubot.shldr_position = rawData.data(:,7) - pi/2; % to fit model
pendubot.shldr_velocity = rawData.data(:,9);
pendubot.elbw_position = rawData.data(:,8);
pendubot.elbw_velocity = rawData.data(:,10);
pendubot.position_desired = rawData.data(:,5);
pendubot.velocity_desired = rawData.data(:,6);
% filter velocties with zero phas filter
vlcty_fltr = designfilt('lowpassiir','FilterOrder',5, ...
'HalfPowerFrequency',0.25,'DesignMethod','butter');
pendubot.shldr_velocity_filtered = filtfilt(vlcty_fltr, pendubot.shldr_velocity);
pendubot.elbw_velocity_filtered = filtfilt(vlcty_fltr, pendubot.elbw_velocity);
% estimating accelerations based on filtered velocities
q2d1 = zeros(size(pendubot.shldr_velocity));
q2d2 = zeros(size(pendubot.elbw_velocity));
for i = 2:size(pendubot.shldr_velocity,1)-1
q2d1(i) = (pendubot.shldr_velocity_filtered(i+1) - pendubot.shldr_velocity_filtered(i-1))/...
(pendubot.time(i+1) - pendubot.time(i-1));
q2d2(i) = (pendubot.elbw_velocity_filtered(i+1) - pendubot.elbw_velocity_filtered(i-1))/...
(pendubot.time(i+1) - pendubot.time(i-1));
end
pendubot.shldr_acceleration = q2d1;
pendubot.elbow_acceleration = q2d2;
% filter estimated accelerations with zero phase filter
aclrtn_fltr = designfilt('lowpassiir','FilterOrder',5, ...
'HalfPowerFrequency',0.25,'DesignMethod','butter');
pendubot.shldr_acceleration_filtered = filtfilt(aclrtn_fltr, pendubot.shldr_acceleration);
pendubot.elbow_acceleration_filtered = filtfilt(aclrtn_fltr, pendubot.elbow_acceleration);
% filter torque measurements using zero phase filter
trq_fltr = designfilt('lowpassiir','FilterOrder',5, ...
'HalfPowerFrequency',0.2,'DesignMethod','butter');
pendubot.torque_filtered = filtfilt(trq_fltr, pendubot.torque);
%%
return
plotJointPositions(pendubot)
plotJointVelocities(pendubot)
plotJointAccelerations(pendubot)
plnr_visualize([pendubot.shldr_position, pendubot.elbw_position], plnr)
%% Functions
function plotJointPositions(pendubot)
figure
subplot(2,1,1)
plot(pendubot.time, pendubot.shldr_position)
xlim([0 1])
xlabel('$t$, sec','interpreter', 'latex')
ylabel('$q_1$, rad','interpreter', 'latex')
grid on
subplot(2,1,2)
plot(pendubot.time, pendubot.elbw_position)
xlim([0 1])
xlabel('$t$, sec','interpreter', 'latex')
ylabel('$q_2$, rad','interpreter', 'latex')
grid on
end
function plotJointVelocities(pendubot)
figure
subplot(2,1,1)
plot(pendubot.time, pendubot.shldr_velocity)
hold on
plot(pendubot.time, pendubot.shldr_velocity_filtered)
xlim([0 5])
xlabel('$t$, sec','interpreter', 'latex')
ylabel('$\dot{q}_1$, rad/s','interpreter', 'latex')
legend('measured', 'filtered')
grid on
subplot(2,1,2)
plot(pendubot.time, pendubot.elbw_velocity)
hold on
plot(pendubot.time, pendubot.elbw_velocity_filtered)
xlim([0 5])
xlabel('t, sec','interpreter', 'latex')
ylabel('$\dot{q}_2$, rad/s','interpreter', 'latex')
legend('measured', 'filtered')
grid on
end
function plotJointAccelerations(pendubot)
figure
subplot(2,1,1)
plot(pendubot.time, pendubot.shldr_acceleration)
hold on
plot(pendubot.time, pendubot.shldr_acceleration_filtered)
xlim([0 2])
xlabel('$t$, sec','interpreter', 'latex')
ylabel('$\ddot{q}_1$, rad/s$^2$','interpreter', 'latex')
legend('estimate', 'filetered estimate')
grid on
subplot(2,1,2)
plot(pendubot.time, pendubot.elbow_acceleration)
hold on
plot(pendubot.time, pendubot.elbow_acceleration_filtered)
xlim([0 2])
xlabel('$t$, sec','interpreter', 'latex')
ylabel('$\ddot{q}_2$, rad/s$^2$','interpreter', 'latex')
legend('estimate', 'filetered estimate')
grid on
end

View File

@ -0,0 +1,88 @@
% run data processing script
run('pndbt_data_processing.m')
% load mapping from standard parameters to base parameters
load('plnrBaseQR.mat')
% compose observation matrix and torque vector
noObservations = length(pendubot.time);
W = []; Tau = [];
for i = 1:noObservations
qi = [pendubot.shldr_position(i), pendubot.elbw_position(i)]';
qdi = [pendubot.shldr_velocity_filtered(i), pendubot.elbw_velocity_filtered(i)]';
q2di = [pendubot.shldr_acceleration_filtered(i), pendubot.elbow_acceleration_filtered(i)]';
if plnrBaseQR.motorDynamicsIncluded
Yi = regressorWithMotorDynamicsPndbt(qi, qdi, q2di);
else
Yi = full_regressor_plnr(qi, qdi, q2di);
end
Ybi = Yi*plnrBaseQR.permutationMatrix(:,1:plnrBaseQR.numberOfBaseParameters);
Yfrctni = frictionRegressor(qdi);
W = vertcat(W, [Ybi, Yfrctni]);
taui = [pendubot.torque(i), 0]';
Tau = vertcat(Tau, taui);
end
%% Usual Least Squares Approach
pi_hat = (W'*W)\(W'*Tau)
%% Set-up SDP optimization procedure
physicalConsistency = 1;
pi_frctn = sdpvar(6,1);
pi_b = sdpvar(plnrBaseQR.numberOfBaseParameters,1); % variables for base paramters
pi_d = sdpvar(15,1); % variables for dependent paramters
% Bijective mapping from [pi_b; pi_d] to standard parameters pi
pii = plnrBaseQR.permutationMatrix*[eye(plnrBaseQR.numberOfBaseParameters), ...
-plnrBaseQR.beta; ...
zeros(15,plnrBaseQR.numberOfBaseParameters), ...
eye(15)]*[pi_b; pi_d];
cnstr = [];
if physicalConsistency
for i = 1:11:21
link_inertia_i = [pii(i), pii(i+1), pii(i+2); ...
pii(i+1), pii(i+3), pii(i+4); ...
pii(i+2), pii(i+4), pii(i+5)];
frst_mmnt_i = pii(i+6:i+8);
Di = [0.5*trace(link_inertia_i)*eye(3) - link_inertia_i, ...
frst_mmnt_i; frst_mmnt_i', pii(i+9)];
cnstr = [cnstr, Di>0];
end
else
for i = 1:11:21
link_inertia_i = [pii(i), pii(i+1), pii(i+2); ...
pii(i+1), pii(i+3), pii(i+4); ...
pii(i+2), pii(i+4), pii(i+5)];
frst_mmnt_i = vec2skewSymMat(pii(i+6:i+8));
Di = [link_inertia_i, frst_mmnt_i'; frst_mmnt_i, pii(i+9)*eye(3)];
cnstr = [cnstr, Di>0];
end
end
cnstr = [cnstr, pii(11) > 0]; % first motor inertia constraint
% Feasibility constraints on the friction prameters
for i = 1:2
cnstr = [cnstr, pi_frctn(3*i-2)>0, pi_frctn(3*i-1)>0];
end
% Defining pbjective function
obj = norm(Tau - W*[pi_b; pi_frctn], 2);
% Solving sdp problem
sol2 = optimize(cnstr, obj, sdpsettings('solver','sdpt3'));
pi_b = value(pi_b) % variables for base paramters
pi_frctn = value(pi_frctn)

76
planar2DOF/pndbt_vldtn.m Normal file
View File

@ -0,0 +1,76 @@
% load pendubot data
% rawData = load('current_A_0.7_v_1.mat');
rawData = load('current_A_5_v_4.mat');
% parse pendubot data
pendubot.time = rawData.data(:,1) - rawData.data(1,1);
pendubot.current = rawData.data(:,2);
pendubot.current_desired = rawData.data(:,4);
pendubot.torque = rawData.data(:,3);
pendubot.shldr_position = rawData.data(:,7) - pi/2; % to fit model
pendubot.shldr_velocity = rawData.data(:,9);
pendubot.elbw_position = rawData.data(:,8);
pendubot.elbw_velocity = rawData.data(:,10);
pendubot.position_desired = rawData.data(:,5);
pendubot.velocity_desired = rawData.data(:,6);
% filter velocties with zero phas filter
vlcty_fltr = designfilt('lowpassiir','FilterOrder',5, ...
'HalfPowerFrequency',0.25,'DesignMethod','butter');
pendubot.shldr_velocity_filtered = filtfilt(vlcty_fltr, pendubot.shldr_velocity);
pendubot.elbw_velocity_filtered = filtfilt(vlcty_fltr, pendubot.elbw_velocity);
% estimating accelerations based on filtered velocities
q2d1 = zeros(size(pendubot.shldr_velocity));
q2d2 = zeros(size(pendubot.elbw_velocity));
for i = 2:size(pendubot.shldr_velocity,1)-1
q2d1(i) = (pendubot.shldr_velocity_filtered(i+1) - pendubot.shldr_velocity_filtered(i-1))/...
(pendubot.time(i+1) - pendubot.time(i-1));
q2d2(i) = (pendubot.elbw_velocity_filtered(i+1) - pendubot.elbw_velocity_filtered(i-1))/...
(pendubot.time(i+1) - pendubot.time(i-1));
end
pendubot.shldr_acceleration = q2d1;
pendubot.elbow_acceleration = q2d2;
% filter estimated accelerations with zero phase filter
aclrtn_fltr = designfilt('lowpassiir','FilterOrder',5, ...
'HalfPowerFrequency',0.25,'DesignMethod','butter');
pendubot.shldr_acceleration_filtered = filtfilt(aclrtn_fltr, pendubot.shldr_acceleration);
pendubot.elbow_acceleration_filtered = filtfilt(aclrtn_fltr, pendubot.elbow_acceleration);
% filter torque measurements using zero phase filter
trq_fltr = designfilt('lowpassiir','FilterOrder',5, ...
'HalfPowerFrequency',0.2,'DesignMethod','butter');
pendubot.torque_filtered = filtfilt(trq_fltr, pendubot.torque);
% Validation
vldtnRange = 1:200;
tau_prdctd_OLS = []; tau_prdctd_SDP = [];
for i = vldtnRange
qi = [pendubot.shldr_position(i), pendubot.elbw_position(i)]';
qdi = [pendubot.shldr_velocity_filtered(i), pendubot.elbw_velocity_filtered(i)]';
q2di = [pendubot.shldr_acceleration_filtered(i), pendubot.elbow_acceleration_filtered(i)]';
if plnrBaseQR.motorDynamicsIncluded
Yi = regressorWithMotorDynamicsPndbt(qi, qdi, q2di);
else
Yi = full_regressor_plnr(qi, qdi, q2di);
end
Ybi = Yi*plnrBaseQR.permutationMatrix(:,1:plnrBaseQR.numberOfBaseParameters);
Yfrctni = frictionRegressor(qdi);
tau_prdctd_OLS = horzcat(tau_prdctd_OLS, [Ybi, Yfrctni]*pi_hat);
tau_prdctd_SDP = horzcat(tau_prdctd_SDP, [Ybi, Yfrctni]*[pi_b; pi_frctn]);
end
%%
figure
plot(pendubot.time(vldtnRange), pendubot.torque(vldtnRange),'r')
hold on
plot(pendubot.time(vldtnRange), tau_prdctd_OLS(1,:),'b-')
plot(pendubot.time(vldtnRange), tau_prdctd_SDP(1,:),'k-')
% plot(pendubot.time(vldtnRange), pendubot.torque(vldtnRange) - tau_prdctd(1,:)', 'k--')
legend('measured', 'predicted OLS', 'predicted SDP')
grid on

View File

@ -0,0 +1,15 @@
function Y = regressorWithMotorDynamicsPndbt(q,qd,q2d)
% ----------------------------------------------------------------------
% This function adds motor dynamics to rigid body regressor.
% It is simplified model of motor dynamics, it adds only reflected
% inertia i.e. I_rflctd = Im*N^2 where N is reduction ratio - I_rflctd*q_2d
% parameter is added to existing vector of each link [pi_i I_rflctd_i]
% so that each link has 11 parameters
% ----------------------------------------------------------------------
if size(q,1)==2 && size(q,2)==1 && size(qd,1)==2 && size(qd,2)==1 ...
&& size(q2d,1)==2 && size(q2d,2)==1
Y_rgd_bdy = full_regressor_plnr(q,qd,q2d);
Y = [Y_rgd_bdy(:,1:10), [q2d(1) 0]', Y_rgd_bdy(:,11:20)];
else
error('Input dimension error!')
end

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,6 @@
a1 = [63.14445447,3.8464372,0.4158832844,0.3695524202,0.08746106361,-0.1337522786,0.2961289419,0.1481741796,-0.2353883251,0.09399249647,-0.1538978199,0.233615134]
a2 = [64.11741816,3.419368669,0.9569679605,0.3840862501,0.07814075303,-0.1229639591,0.02985321809,0.1491091833,0.02899625285,0.05196032274,0.2596098438,0.07364049564]
a3 = [63.99585112,3.795840113,0.3484088895,0.4071788941,0.08260375437,0.2451950051,0.09884994438,-0.04640752829,-0.04826315454,0.2385501641,0.04460446056,0.1202201747]
a4 = [16.02097434,1.253074147,-0.255199746,0.4398665024,-0.2171605318,-0.0671930056,0.04760909641,0.05378361497,0.1664478999,-0.1412713881,-0.107594707,-0.01160368875]
a5 = [8.719760589,0.812418026,-0.1530323563,0.1242863329,-0.09048595915,-0.07278439425,0.09679122168,-0.04824579569,-0.1194642801,0.08013340566,-0.01283551447,0.005705712498]
a6 = [64.61350353,3.897149875,0.8834439241,-0.007566380055,0.3211701597,0.1278674554,0.07810124808,0.1587321747,0.1003165104,0.03590044572,0.03013318791,-0.01484059122]

View File

@ -0,0 +1,6 @@
b1 = [-0.7092040412,0.5230610431,0.1976180106,-0.2377492599,0.09662808559,-0.0442446606,0.04546091583,-0.05527008338,0.07999041891,-0.1954301078,0.02276381324,-0.0003037708343]
b2 = [16.44144409,1.96646412,0.4413777885,0.01535646862,0.1699440808,-0.04517986656,0.08204914487,0.09802980971,0.1107566817,0.164257973,0.1687008776,-0.1158379341]
b3 = [15.91827703,1.738289041,0.6396138544,0.4400174545,0.06841133754,0.1540512842,-0.01213731937,0.1288104914,0.01749713258,0.2106228112,-0.1025715439,-0.03232628298]
b4 = [3.07591063,0.4116519318,0.1342122544,-0.02000429905,0.1916582385,0.1154067377,0.03839347039,0.01232415683,-0.1919967103,-0.01691073997,0.01163710601,0.04178807472]
b5 = [32.38341148,4.112282002,1.463403865,0.4409561611,0.3426812758,0.1595795442,0.1184208908,0.05993487595,-0.09285686628,0.01674492771,0.09477511091,0.168557236]
b6 = [32.04972222,3.852785925,1.284364462,-0.1618577222,0.456724459,0.2217872019,0.2525677551,0.1450619486,0.09508517903,0.04484496664,0.1612198891,-0.003833787606]

View File

@ -0,0 +1,6 @@
c1 = [-1.39519063326,-68.1126607632,0.14374629977,1.6884418891,-0.127351873182,0.00255422477862]
c2 = [54.6442907022,-69.4261871541,-4.21007966412,2.15666264527,-0.140699300074,0.00260348201828]
c3 = [54.6708156721,-69.2826318354,-4.08927819065,2.14099361495,-0.140128130168,0.00259809869383]
c4 = [9.14854552465,-17.1817325285,-0.781047135654,0.507648026779,-0.0341683663301,0.00064431496982]
c5 = [111.953260927,-9.34224698765,-8.34694011304,1.06825018599,-0.0383840633844,0.000350334262037]
c6 = [110.057813716,-70.2239115388,-8.2522415789,2.58082194636,-0.152300438083,0.00263339668271]

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,4 +1,4 @@
function [c,ceq] = traj_cnstr(opt_vars,traj_par)
function [c,ceq] = traj_cnstr(opt_vars, traj_par)
% --------------------------------------------------------------------
% The function computes constraints on trajectory for trajectoty
% optimization needed for dynamic parameter identification

View File

@ -0,0 +1,53 @@
function [c,ceq] = traj_cnstr_fsblty(opt_vars, traj_par, baseQR)
% --------------------------------------------------------------------
% The function computes constraints on trajectory for trajectoty
% optimization needed for dynamic parameter identification more
% precisely for searching feasibly solutions with condition number
% less than 100 that guarantees good estimate
% -------------------------------------------------------------------
% Trajectory parameters
N = traj_par.N;
wf = traj_par.wf;
T = traj_par.T;
t = traj_par.t;
% As paramters of the trajectory are in a signle vector we reshape them as
% to feed the function that computes the trajectory
ab = reshape(opt_vars,[12,N]);
a = ab(1:6,:); % sin coeffs
b = ab(7:12,:); % cos coeffs
% To guarantee that positions, velocities and accelerations are zero in the
% beginning and at time T, we add fifth order polynomial to fourier
% series. The parameters of the polynomial depends on the parameters of
% fourier series. Here we compute them.
c_pol = getPolCoeffs(T, a, b, wf, N, traj_par.q0);
% Compute trajectory (Fouruer series + fifth order polynomail)
[q,qd,q2d] = mixed_traj(t, c_pol, a, b, wf, N);
% Obtain observation matrix by computing regressor for each sampling time
E1 = baseQR.permutationMatrix(:,1:baseQR.numberOfBaseParameters);
W = [];
for i = 1:length(t)
% Y = base_regressor_UR10E(q(:,i),qd(:,i),q2d(:,i));
if baseQR.motorDynamicsIncluded
Y = [regressorWithMotorDynamics(q(:,i),qd(:,i),q2d(:,i))*E1, ...
frictionRegressor(qd(:,i))];
else
Y = [full_regressor_UR10E(q(:,i),qd(:,i),q2d(:,i))*E1, ...
frictionRegressor(qd(:,i))];
end
W = vertcat(W,Y);
end
% Inequality constraints
c(1:6) = traj_par.q_min - min(q,[],2); % upper joint limit constraint
c(7:12) = max(q,[],2) - traj_par.q_max; % lower joint limit constraint
c(13:18) = max(abs(qd),[],2) - traj_par.qd_max; % max joint velocity const
c(19:24) = max(abs(q2d),[],2) - traj_par.q2d_max; % max joint acceleration constr
c(25) = cond(W) - 100;
% Equality contrsints
ceq = [];

View File

@ -86,7 +86,7 @@ bb = rank(W);
% R = [R1 R2;
% 0 0]
% R1 is bbxbb upper triangular and reguar matrix
% R2 is bbx(c-bb) matrix where c is number of identifiable parameters
% R2 is bbx(c-bb) matrix where c is number of standard parameters
R1 = R(1:bb,1:bb);
R2 = R(1:bb,bb+1:end);
beta = R1\R2; % the zero rows of K correspond to independent columns of WP

View File

@ -8,6 +8,7 @@ load('baseQR.mat'); % load mapping from full parameters to base parameters
% Choose optimization algorithm: 'patternsearch', 'ga', 'fmincon'
optmznAlgorithm = 'patternsearch';
searchOnlyForFeasibleSolution = 1;
% Getting limits on posistion and velocities. Moreover we get some
% constant parmeters of the robot that allow us to accelerate computation
@ -30,17 +31,17 @@ ur10.r_com = r_com;
% Trajectory parameters
traj_par.T = 20; % period of signal
traj_par.T = 25; % period of signal
traj_par.wf = 2*pi/traj_par.T; % fundamental frequency
traj_par.t_smp = 1e-1; % sampling time
traj_par.t_smp = 2e-1; % sampling time
traj_par.t = 0:traj_par.t_smp:traj_par.T; % time
traj_par.N = 5; % number of harmonics
traj_par.N = 7; % number of harmonics
traj_par.q0 = deg2rad([0 -90 0 -90 0 0 ]');
% Use different limit for positions for safety
traj_par.q_min = -deg2rad([180 180 160 180 90 90]');
traj_par.q_max = deg2rad([180 0 160 0 90 90]');
traj_par.q_min = -deg2rad([180 180 100 180 90 90]');
traj_par.q_max = deg2rad([180 0 100 0 90 90]');
traj_par.qd_max = qd_max;
traj_par.q2d_max = 2*ones(6,1);
traj_par.q2d_max = [2 1 1 1 1 2.5]';
% ----------------------------------------------------------------------
% Otimization
@ -50,19 +51,26 @@ Aeq = []; beq = [];
lb = []; ub = [];
if strcmp(optmznAlgorithm, 'patternsearch')
x0 = rand(6*2*traj_par.N,1);
load('ptrnSrch_N7T25QR.mat')
% x0 = rand(6*2*traj_par.N,1);
x0 = reshape([a b], [6*2*traj_par.N, 1]);
optns_pttrnSrch = optimoptions('patternsearch');
optns_pttrnSrch.Display = 'iter';
optns_pttrnSrch.StepTolerance = 1e-3;
optns_pttrnSrch.FunctionTolerance = 1;
optns_pttrnSrch.StepTolerance = 1e-1;
optns_pttrnSrch.FunctionTolerance = 10;
optns_pttrnSrch.ConstraintTolerance = 1e-6;
optns_pttrnSrch.MaxTime = inf;
optns_pttrnSrch.MaxFunctionEvaluations = 1e+6;
if searchOnlyForFeasibleSolution
[x,fval] = patternsearch(@(x)0, x0, A, [], Aeq, beq, lb, ub, ...
@(x)traj_cnstr_fsblty(x, traj_par, baseQR), ...
optns_pttrnSrch);
else
[x,fval] = patternsearch(@(x)traj_cost_lgr(x,traj_par,baseQR), x0, ...
A, b, Aeq, beq, lb, ub, ...
@(x)traj_cnstr(x,traj_par), optns_pttrnSrch);
end
elseif strcmp(optmznAlgorithm, 'ga')
optns_ga = optimoptions('ga');
optns_ga.Display = 'iter';
@ -120,14 +128,16 @@ subplot(3,1,3)
grid on
legend('q2d1','q2d2','q2d3','q2d4','q2d5','q2d6')
%%
% %{
pathToFolder = 'trajectory_optmzn/';
t1 = strcat('N',num2str(traj_par.N),'T',num2str(traj_par.T));
if strcmp(optmznAlgorithm, 'patternsearch')
filename = strcat(pathToFolder,'ptrnSrch_',t1,'QR2.mat');
filename = strcat(pathToFolder,'ptrnSrch_',t1,'QR.mat');
elseif strcmp(optmznAlgorithm, 'ga')
filename = strcat(pathToFolder,'ga_',t1,'.mat');
elseif strcmp(optmznAlgorithm, 'fmincon')
filename = strcat(pathToFolder,'fmncn_',t1,'.mat');
end
save(filename,'a','b','c_pol','traj_par')
%}

View File

@ -3,10 +3,12 @@ clc; clear all; close all;
% ------------------------------------------------------------------------
% Load data and procces it (filter and estimate accelerations)
% ------------------------------------------------------------------------
unloadedTrajectory = parseURData('ur-19_12_23_free.csv', 1, 2036);
% unloadedTrajectory = parseURData('ur-19_12_23_free.csv', 1, 2036);
unloadedTrajectory = parseURData('ur-20_01_31-unload.csv', 300, 2623);
unloadedTrajectory = filterData(unloadedTrajectory);
loadedTrajectory = parseURData('ur-20_01_13-load_2600.csv', 250, 2274);
% loadedTrajectory = parseURData('ur-20_01_13-load_2600.csv', 250, 2274);
loadedTrajectory = parseURData('ur-20_01_31-load.csv', 370, 2881);
loadedTrajectory = filterData(loadedTrajectory);
% ------------------------------------------------------------------------
@ -16,7 +18,8 @@ loadedTrajectory = filterData(loadedTrajectory);
% load('full2base_mapping.mat');
load('baseQR.mat'); % load mapping from full parameters to base parameters
E1 = baseQR.permutationMatrix(:,1:baseQR.numberOfBaseParameters);
m_load = 2.602;
m_load = 2.805;
% m_load = 2.602;
% Constracting regressor matrix for unloaded case
Wb_uldd = []; I_uldd = [];
@ -165,7 +168,6 @@ sol = optimize(cnstr,obj,sdpsettings('solver','sdpt3'));
% Getting values of the estimated patamters
drvGainsSDP = value(drv_gns)
return
%% Saving obtained drive gains
drvGains = drvGainsSDP;
filename = 'driveGains.mat';

View File

@ -61,7 +61,7 @@ x1 = fminsearch(@(x)costFcn(x, link1.qd_fltrd(:,1), link1.deltaTau), x10, fminsr
x2 = fminsearch(@(x)costFcn(x, link2.qd_fltrd(:,2), link2.deltaTau), x20, fminsrchOptns);
x3 = fminsearch(@(x)costFcn(x, link3.qd_fltrd(:,3), link3.deltaTau), x30, fminsrchOptns);
x4 = fminsearch(@(x)costFcn(x, link4.qd_fltrd(:,4), link4.deltaTau), x40, fminsrchOptns);
x5 = fminsearch(@(x)costFcn(x, link5.qd_fltrd(:,5), link5.deltaTau), x50, fminsrchOptns);
x5 = fminsearch(@(x)costFcn(x, link5.qd_fltrd(:,5), link5.deltaTau), x4, fminsrchOptns);
x6 = fminsearch(@(x)costFcn(x, link6.qd_fltrd(:,6), link6.deltaTau), x5, fminsrchOptns);
pi_nonlnr_frcn = [x1; x2; x3; x4; x5; x6];
@ -77,7 +77,7 @@ plotFrictionModels(link4, 4, pi_frctn(10:12), x4)
plotFrictionModels(link5, 5, pi_frctn(13:15), x5)
plotFrictionModels(link6, 6, pi_frctn(16:18), x6)
return
%% Plot torque prediction with different friction models
plotTroqueEstimation(link1, 1, drvGains(1), pi_frctn(1:3), x1)
plotTroqueEstimation(link2, 2, drvGains(2), pi_frctn(4:6), x2)
@ -87,8 +87,6 @@ plotTroqueEstimation(link5, 5, drvGains(5), pi_frctn(13:15), x5)
plotTroqueEstimation(link6, 6, drvGains(6), pi_frctn(16:18), x6)
%% Utilized Functions
function plotTroqueEstimation(link, noLink, drvGain, linear, nonlinear)
@ -104,20 +102,12 @@ end
function plotFrictionModels(link, noLink, linear, nonlinear)
figure
subplot(1,2,1)
hold on
scatter(link.qd(:,noLink), link.deltaTau, '.')
plot(link.qd(:,noLink), nonlinearFrictionModel(nonlinear, link.qd(:,noLink)))
plot(link.qd(:,noLink), linearFrictionModel(linear, link.qd(:,noLink)))
legend('real', 'nonlinear model', 'linear model','Location','northwest')
title(strcat('Link ',num2str(noLink),' friction model'))
subplot(1,2,2)
hold on
scatter(link.q(:,noLink), link.deltaTau, '.')
plot(link.q(:,noLink), nonlinearFrictionModel(nonlinear, link.qd(:,noLink)))
plot(link.q(:,noLink), linearFrictionModel(linear, link.qd(:,noLink)))
legend('real', 'nonlinear model', 'linear model','Location','northwest')
title(strcat('Link ',num2str(noLink),' friction model'))
end

View File

@ -4,6 +4,7 @@ clc; clear all; close all;
% Load data and procces it (filter and estimate accelerations)
% ------------------------------------------------------------------------
unloadedTrajectory = parseURData('ur-19_12_23_free.csv', 1, 2005);
% unloadedTrajectory = parseURData('ur-20_01_31-unload.csv', 300, 2623);
unloadedTrajectory = filterData(unloadedTrajectory);
% ------------------------------------------------------------------------
@ -18,11 +19,11 @@ E1 = baseQR.permutationMatrix(:,1:baseQR.numberOfBaseParameters);
load('driveGains.mat')
% drvGains = [14.87; 13.26; 11.13; 10.62; 11.03; 11.47]; % deLuca gains
% drvGains = [11.1272; 11.83; 9.53; 12.64; 10.24; 5.53];
% drvGains = [15.87; 11.83; 9.53; 11.92; 15.24; 18.47];
%Constracting regressor matrix
Wb_uldd = []; Tau_uldd = [];
for i = 1:2:length(unloadedTrajectory.t)
for i = 1:1:length(unloadedTrajectory.t)
Y_ulddi = regressorWithMotorDynamics(unloadedTrajectory.q(i,:)',...
unloadedTrajectory.qd_fltrd(i,:)',...
unloadedTrajectory.q2d_est(i,:)');
@ -31,9 +32,16 @@ for i = 1:2:length(unloadedTrajectory.t)
Wb_uldd = vertcat(Wb_uldd, Ybi_uldd);
Tau_uldd = vertcat(Tau_uldd, diag(drvGains)*unloadedTrajectory.i_fltrd(i,:)');
% Tau_uldd = vertcat(Tau_uldd, unloadedTrajectory.tau_des(i,:)');
end
%% Usual least squares
pib_hat = (Wb_uldd'*Wb_uldd)\(Wb_uldd'*Tau_uldd);
pi_b = pib_hat(1:40); % variables for base paramters
pi_frctn = pib_hat(41:end);
%% Set-up SDP optimization procedure
physicalConsistency = 1;
@ -62,6 +70,8 @@ for i = 1:6
end
if physicalConsistency
for i = 1:11:66
link_inertia_i = [pii(i), pii(i+1), pii(i+2); ...

130
ur_knmtcs.m Normal file
View File

@ -0,0 +1,130 @@
% Get robot description
run('main_ur.m')
%{
q_sym = sym('q%d',[6,1], 'real');
T_pk = sym(zeros(4,4,6)); % transformation between links
T_0k = sym(zeros(4,4,7)); T_0k(:,:,1) = sym(eye(4));
for i = 1:6
jnt_axs_k = str2num(ur10.robot.joint{i}.axis.Attributes.xyz)';
% Transformation from parent link frame p to current joint frame
rpy_k = sym(str2num(ur10.robot.joint{i}.origin.Attributes.rpy));
R_pj = RPY(rpy_k);
R_pj(abs(R_pj)<sqrt(eps)) = sym(0); % to avoid numerical errors
p_pj = str2num(ur10.robot.joint{i}.origin.Attributes.xyz)';
T_pj = sym([R_pj, p_pj; zeros(1,3), 1]); % to avoid numerical errors
% Tranformation from joint frame of the joint that rotaties body k to
% link frame. The transformation is pure rotation
R_jk = Rot(q_sym(i),sym(jnt_axs_k));
p_jk = sym(zeros(3,1));
T_jk = [R_jk, p_jk; sym(zeros(1,3)),sym(1)];
% Transformation from parent link frame p to current link frame k
T_pk(:,:,i) = T_pj*T_jk;
T_0k(:,:,i+1) = T_0k(:,:,i)*T_pk(:,:,i);
end
pos = T_0k(1:3,4,7);
matlabFunction(pos,'File','autogen/position_fk_UR10E','Vars',{q_sym})
%}
% load('ptrnSrch_N6T20QR.mat');
% load('ptrnSrch_N8T20QR.mat');
% load('ptrnSrch_N10T20QR.mat');
load('ptrnSrch_N12T20QR.mat');
traj_par.t_smp = 5e-2;
traj_par.t = 0:traj_par.t_smp:traj_par.T;
[q,qd,q2d] = mixed_traj(traj_par.t, c_pol, a, b, traj_par.wf, traj_par.N);
%%
for i = 1:size(q,2)
% pos(:,i) = ur_fk(q(:,i), ur10);
pos(:,i) = position_fk_UR10E(q(:,i));
end
% Needed for surface
[x, y] = meshgrid(-0.7:0.05:0.7); % Generate x and y data
z = zeros(size(x, 1)); % Generate z data
figure
hold on
surf(x, y, z) % Plot the surface
for i = 1:size(q,2)
scatter3(pos(1,i), pos(2,i), pos(3,i))
end
xlabel('X')
ylabel('Y')
zlabel('Z')
axis equal
view(3)
%% write into file
writeTrajectoryCoefficientsIntoFile(a, b, c_pol)
%%
% figure1 = figure;
% axes1 = axes('Parent',figure1);
% hold(axes1,'on');
% for i = 1:6
% scatter3(T_0k(1,4,i), T_0k(2,4,i), T_0k(3,4,i))
% line([T_0k(1,4,i) T_0k(1,4,i+1)], [T_0k(2,4,i) T_0k(2,4,i+1)], ...
% [T_0k(3,4,i) T_0k(3,4,i+1)])
% end
% xlabel('X')
% ylabel('Y')
% zlabel('Z')
% axis equal
function writeTrajectoryCoefficientsIntoFile(a, b, c_pol)
prcsn = 10;
a_coefs = {};
b_coefs = {};
a_coefs{1} = 'a1 = ['; a_coefs{2} = 'a2 = ['; a_coefs{3} = 'a3 = [';
a_coefs{4} = 'a4 = ['; a_coefs{5} = 'a5 = ['; a_coefs{6} = 'a6 = [';
b_coefs{1} = 'b1 = ['; b_coefs{2} = 'b2 = ['; b_coefs{3} = 'b3 = [';
b_coefs{4} = 'b4 = ['; b_coefs{5} = 'b5 = ['; b_coefs{6} = 'b6 = [';
for i = 1:size(a,2)
if i < size(a,2)
for j = 1:6
a_coefs{j} = strcat(a_coefs{j}, num2str(a(j,i), prcsn), ',');
b_coefs{j} = strcat(b_coefs{j}, num2str(b(j,i), prcsn), ',');
end
elseif i == size(a,2)
for j = 1:6
a_coefs{j} = strcat(a_coefs{j}, num2str(a(j,i), prcsn), ']\n');
b_coefs{j} = strcat(b_coefs{j}, num2str(b(j,i), prcsn), ']\n');
end
end
end
c_coefs = {};
c_coefs{1} = 'c1 = ['; c_coefs{2} = 'c2 = ['; c_coefs{3} = 'c3 = [';
c_coefs{4} = 'c4 = ['; c_coefs{5} = 'c5 = ['; c_coefs{6} = 'c6 = [';
for i = 1:size(c_pol,2)
if i < size(c_pol,2)
for j = 1:6
c_coefs{j} = strcat(c_coefs{j}, num2str(c_pol(j,i), prcsn+2), ',');
end
elseif i == size(c_pol,2)
for j = 1:6
c_coefs{j} = strcat(c_coefs{j}, num2str(c_pol(j,i), prcsn+2), ']\n');
end
end
end
fileID_a = fopen('trajectory_optmzn/coeffs4_UR/a_coeffs.script','w');
fileID_b = fopen('trajectory_optmzn/coeffs4_UR/b_coeffs.script','w');
fileID_c = fopen('trajectory_optmzn/coeffs4_UR/c_coeffs.script','w');
for i = 1:6
fprintf(fileID_a, a_coefs{i});
fprintf(fileID_b, b_coefs{i});
fprintf(fileID_c, c_coefs{i});
end
fclose(fileID_a);
fclose(fileID_b);
fclose(fileID_c);
end

View File

@ -5,19 +5,14 @@
% vldtnTrjctry = parseURData('ur-19_10_01-14_04_13.csv', 1, 759);
% vldtnTrjctry = parseURData('ur-19_10_01-13_51_41.csv', 1, 660);
% vldtnTrjctry = parseURData('ur-19_09_27-11_28_22.csv', 1, 594);
% vldtnTrjctry = parseURData('ur-20_01_17-p1.csv', 1, 250);
vldtnTrjctry = parseURData('ur-20_01_17-ptp_10_points.csv', 1, 5346);
vldtnTrjctry = parseURData('ur-20_01_17-p2.csv', 1, 250);
% vldtnTrjctry = parseURData('ur-20_01_17-ptp_10_points.csv', 1, 5346);
vldtnTrjctry = filterData(vldtnTrjctry);
% -----------------------------------------------------------------------
% Predicting torques
% -----------------------------------------------------------------------
pi_rigidBody = reshape(identifiedUR10E.standardParameters,[11,6]);
pi_rigidBody = pi_rigidBody(1:10,:);
pi_rigidBody = reshape(pi_rigidBody,[60 1]);
%Constracting regressor matrix
tau_msrd = []; tau_prdctd1 = []; tau_prdctd2 = [];
i_prdct1 = []; i_prdct2 = [];
@ -26,7 +21,7 @@ for i = 1:length(vldtnTrjctry.t)
vldtnTrjctry.qd_fltrd(i,:)',...
vldtnTrjctry.q2d_est(i,:)');
tau_withoutFriction = Yi*E1*identifiedUR10E.baseParameters;
tau_withoutFriction = Yi*E1*pi_b;
tau_lnr_frcn = zeros(6,1);
% tau_nonlnr_frcn = zeros(6,1);
@ -36,7 +31,7 @@ for i = 1:length(vldtnTrjctry.t)
% tau_nonlnr_frcn(j) = nonlinearFrictionModel(pi_nonlnr_frcn(5*(j-1)+1:5*(j-1)+5),...
% vldtnTrjctry.qd_fltrd(i,j)');
end
tau_msrd = horzcat(tau_msrd, diag(drvGains)*vldtnTrjctry.i_fltrd(i,:)');
tau_msrd = horzcat(tau_msrd, diag(drvGains)*vldtnTrjctry.i(i,:)');
tau_prdctd1 = horzcat(tau_prdctd1, tau_withoutFriction + tau_lnr_frcn);
% tau_prdctd2 = horzcat(tau_prdctd2, tau_withoutFriction + tau_nonlnr_frcn);
@ -45,16 +40,44 @@ for i = 1:length(vldtnTrjctry.t)
end
%%
plotTorquesWithLinearFriction = 0;
plotTorquesWithNonlinearFriction = 0;
for i = 1:6
figure
hold on
plot(vldtnTrjctry.t, tau_msrd(i,:), 'r-')
% plot(vldtnTrjctry.t, vldtnTrjctry.tau_des(:,i))
plot(vldtnTrjctry.t, tau_prdctd1(i,:),'k-')
legend('measured', 'desired', 'predicted')
plot(vldtnTrjctry.t, vldtnTrjctry.i(:,i), 'r-')
plot(vldtnTrjctry.t, i_prdct1(i,:), 'k-')
legend('measured', 'prdctd1')
grid on
end
if plotTorquesWithLinearFriction
for i = 1:6
figure
hold on
plot(vldtnTrjctry.t, tau_msrd(i,:), 'r-')
plot(vldtnTrjctry.t, tau_prdctd1(i,:), 'k-')
plot(vldtnTrjctry.t, tau_prdctd1(i,:) - tau_msrd(i,:), '--')
legend('measured', 'predicted', 'error')
grid on
end
end
if plotTorquesWithNonlinearFriction
for i = 1:6
figure
hold on
plot(vldtnTrjctry.t, tau_msrd(i,:), 'r-')
plot(vldtnTrjctry.t, tau_prdctd2(i,:), 'k-')
plot(vldtnTrjctry.t, tau_prdctd2(i,:) - tau_msrd(i,:), '--')
legend('measured', 'predicted', 'error')
grid on
end
end
return
for i = 1:6
figure