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.
 
 
 
 
 
 

203 lines
6.3 KiB

%MSTRAJ Multi-segment multi-axis trajectory
%
% TRAJ = MSTRAJ(P, QDMAX, Q0, DT, TACC, OPTIONS) is a multi-segment trajectory (KxN)
% based on via points P (MxN) and axis velocity limits QDMAX (1xN). The
% path comprises linear segments with polynomial blends. The output
% trajectory matrix has one row per time step, and one column per axis.
%
% - P (MxN) is a matrix of via points, 1 row per via point, one column
% per axis. The last via point is the destination.
% - QDMAX (1xN) are axis velocity limits which cannot be exceeded, or
% - QDMAX (Mx1) are the durations for each of the M segments
% - Q0 (1xN) are the initial axis coordinates
% - DT is the time step
% - TACC (1x1) this acceleration time is applied to all segment transitions
% - TACC (1xM) acceleration time for each segment, TACC(i) is the acceleration
% time for the transition from segment i to segment i+1. TACC(1) is also
% the acceleration time at the start of segment 1.
%
% TRAJ = MSTRAJ(SEGMENTS, QDMAX, Q0, DT, TACC, QD0, QDF, OPTIONS) as above but
% additionally specifies the initial and final axis velocities (1xN).
%
% Options::
% 'verbose' Show details.
%
% Notes::
% - If no output arguments are specified the trajectory is plotted.
% - The path length K is a function of the number of via points, Q0, DT
% and TACC.
% - The final via point P(M,:) is the destination.
% - The motion has M segments from Q0 to P(1,:) to P(2,:) to P(M,:).
% - All axes reach their via points at the same time.
% - Can be used to create joint space trajectories where each axis is a joint
% coordinate.
% - Can be used to create Cartesian trajectories with the "axes" assigned
% to translation and orientation in RPY or Euler angle form.
%
% See also MSTRAJ, LSPB, CTRAJ.
% Copyright (C) 1993-2011, by Peter I. Corke
%
% This file is part of The Robotics Toolbox for Matlab (RTB).
%
% RTB is free software: you can redistribute it and/or modify
% it under the terms of the GNU Lesser General Public License as published by
% the Free Software Foundation, either version 3 of the License, or
% (at your option) any later version.
%
% RTB is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU Lesser General Public License for more details.
%
% You should have received a copy of the GNU Leser General Public License
% along with RTB. If not, see <http://www.gnu.org/licenses/>.
function [TG, taxis] = mstraj(segments, qdmax, tsegment, q, dt, Tacc, varargin)
ns = numrows(segments);
nj = numcols(segments);
if ~isempty(qdmax) && ~isempty(tsegment)
error('Can only specify one of qdmax or tsegment');
end
if isempty(qdmax) && isempty(tsegment)
error('Must specify one of qdmax or tsegment');
end
[opt,args] = tb_optparse([], varargin);
if length(args) > 0
qd0 = args{1};
else
qd0 = zeros(1, nj);
end
if length(args) > 1
qdf = args{2};
else
qdf = zeros(1, nj);
end
% set the initial conditions
q_prev = q;
qd_prev = qd0;
clock = 0; % keep track of time
arrive = []; % record planned time of arrival at via points
tg = [];
taxis = [];
for seg=1:ns
if opt.verbose
fprintf('------------------- segment %d\n', seg);
end
% set the blend time, just half an interval for the first segment
if length(Tacc) > 1
tacc = Tacc(seg);
else
tacc = Tacc;
end
tacc = ceil(tacc/dt)*dt;
tacc2 = ceil(tacc/2/dt) * dt;
if seg == 1
taccx = tacc2;
else
taccx = tacc;
end
% estimate travel time
% could better estimate distance travelled during the blend
q_next = segments(seg,:); % current target
dq = q_next - q_prev; % total distance to move this segment
%% probably should iterate over the next section to get qb right...
% while 1
% qd_next = (qnextnext - qnext)
% tb = abs(qd_next - qd) ./ qddmax;
% qb = f(tb, max acceleration)
% dq = q_next - q_prev - qb
% tl = abs(dq) ./ qdmax;
if ~isempty(qdmax)
% qdmax is specified, compute slowest axis
qb = taccx * qdmax / 2; % distance moved during blend
tb = taccx;
% convert to time
tl = abs(dq) ./ qdmax;
%tl = abs(dq - qb) ./ qdmax;
tl = ceil(tl/dt) * dt;
% find the total time and slowest axis
tt = tb + tl;
[tseg,slowest] = max(tt);
taxis(seg,:) = tt;
% best if there is some linear motion component
if tseg <= 2*tacc
tseg = 2 * tacc;
end
elseif ~isempty(tsegment)
% segment time specified, use that
tseg = tsegment(seg);
slowest = NaN;
end
% log the planned arrival time
arrive(seg) = clock + tseg;
if seg > 1
arrive(seg) = arrive(seg) + tacc2;
end
if opt.verbose
fprintf('seg %d, slowest axis %d, time required %.4g\n', ...
seg, slowest, tseg);
end
%% create the trajectories for this segment
% linear velocity from qprev to qnext
qd = dq / tseg;
% add the blend polynomial
qb = jtraj(q, q_prev+tacc2*qd, 0:dt:taccx, qd_prev, qd);
tg = [tg; qb(2:end,:)];
clock = clock + taccx; % update the clock
% add the linear part, from tacc/2+dt to tseg-tacc/2
for t=tacc2+dt:dt:tseg-tacc2
s = t/tseg;
q = (1-s) * q_prev + s * q_next; % linear step
tg = [tg; q];
clock = clock + dt;
end
q_prev = q_next; % next target becomes previous target
qd_prev = qd;
end
% add the final blend
qb = jtraj(q, q_next, 0:dt:tacc2, qd_prev, qdf);
tg = [tg; qb(2:end,:)];
% plot a graph if no output argument
if nargout == 0
t = (0:numrows(tg)-1)'*dt;
clf
plot(t, tg, '-o');
hold on
plot(arrive, segments, 'bo', 'MarkerFaceColor', 'k');
hold off
grid
xlabel('time');
xaxis(t(1), t(end))
else
TG = tg;
end