You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

186 lines
4.9 KiB

function [qt,histout] = ikine2(robot, tr, varargin)
% set default parameters for solution
opt.ilimit = 1000;
opt.tol = 1e-6;
opt.alpha = 1;
opt.plot = false;
opt.pinv = true;
opt.varstep = false;
tau = 1e-2;
v = 2;
[opt,args] = tb_optparse(opt, varargin);
n = robot.n;
% robot.ikine(tr, q)
if ~isempty(args)
q = args{1};
if isempty(q)
q = zeros(1, n);
else
q = q(:)';
end
else
q = zeros(1, n);
end
% robot.ikine(tr, q, m)
if length(args) > 1
m = args{2};
m = m(:);
if numel(m) ~= 6
error('RTB:ikine:badarg', 'Mask matrix should have 6 elements');
end
if numel(find(m)) > robot.n
error('RTB:ikine:badarg', 'Number of robot DOF must be >= the same number of 1s in the mask matrix')
end
else
if n < 6
error('RTB:ikine:badarg', 'For a manipulator with fewer than 6DOF a mask matrix argument must be specified');
end
m = ones(6, 1);
end
% make this a logical array so we can index with it
m = logical(m);
npoints = size(tr,3); % number of points
qt = zeros(npoints, n); % preallocate space for results
tcount = 0; % total iteration count
if ~ishomog(tr)
error('RTB:ikine:badarg', 'T is not a homog xform');
end
J0 = jacob0(robot, q);
J0 = J0(m, :);
if cond(J0) > 100
warning('RTB:ikine:singular', 'Initial joint angles results in near-singular configuration, this may slow convergence');
end
history = [];
failed = false;
e = zeros(6,1);
revolutes = [robot.links.sigma] == 0;
for i=1:npoints % for each transform on trajectory
T = tr(:,:,i);
nm = Inf;
% initialize state for the ikine loop
eprev = Inf;
save.e = [Inf Inf Inf Inf Inf Inf];
save.q = [];
count = 0;
while true % iterate the solution
% update the count and test against iteration limit
count = count + 1;
if count > opt.ilimit
warning('ikine: iteration limit %d exceeded (row %d), final err %f', ...
opt.ilimit, i, nm);
failed = true;
%q = NaN*ones(1,n);
break
end
% compute the error
[en,e] = errfun(robot, T, q, m);
if en <= opt.tol
break
end
% compute the Jacobian
J = jacob0(robot, q);
% compute change in joint angles to reduce the error,
% based on the square sub-Jacobian
J = J(m,:);
JJ = J'*J;
lambda = tau *diag(JJ);
while true % the Levenberg-Marquadt iteration
dq1 = inv(JJ + diag(lambda))*J' * e(m)';
en1 = errfun(robot, T, q-dq1', m);
% dq2 = inv(JJ + diag(lambda/v))*J' * e(m)';
% en2 = errfun(robot, T, q-dq2', m);
if en1 > en
disp('increase lambda');
lambda = lambda * v;
else
q = q - dq1';
break; % dq1 is good
end
[en en1]
% if en2 > en
% if en1 > en
% disp('increase lambda');
% lambda = lambda * v;
% else
% break; % dq1 is good
% end
% else
% disp('decrease lambda');
%
% lambda = lambda / v;
% end
end
disp(' done');
% update the estimated solution
%q = q + dq1';
% wrap angles for revolute joints
k = (q > pi) & revolutes;
q(k) = q(k) - 2*pi;
k = (q < -pi) & revolutes;
q(k) = q(k) + 2*pi;
if norm(e) > 1.5*norm(eprev)
warning('RTB:ikine:diverged', 'solution diverging, try reducing alpha');
end
eprev = e;
end % end ikine solution for tr(:,:,i)
qt(i,:) = q';
tcount = tcount + count;
if opt.verbose
fprintf('%d iterations\n', count);
end
end
if opt.verbose && npoints > 1
fprintf('TOTAL %d iterations\n', tcount);
end
end
function [nm,e] = errfun(robot, T, q, m)
Tq = robot.fkine(q');
e(1:3) = transl(T - Tq);
Rq = t2r(Tq);
[th,n] = tr2angvec(t2r(T)*Rq');
e(4:6) = th*n;
nm = norm(e(m));
end