%MSTRAJ Multi-segment multi-axis trajectory

%

% TRAJ = MSTRAJ(WP, QDMAX, TSEG, Q0, DT, TACC, OPTIONS) is a trajectory

% (KxN) for N axes moving simultaneously through M segment. Each segment

% is linear motion and polynomial blends connect the segments. The axes

% start at Q0 (1xN) and pass through M-1 via points defined by the rows of

% the matrix WP (MxN), and finish at the point defined by the last row of WP.

% The trajectory matrix has one row per time step, and one column per

% axis. The number of steps in the trajectory K is a function of the

% number of via points and the time or velocity limits that apply.

%

% - WP (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 speed limits which cannot be exceeded,

% - TSEG (1xM) are the durations for each of the K segments

% - Q0 (1xN) are the initial axis coordinates

% - DT is the time step

% - TACC (1x1) is the acceleration time used for all segment transitions

% - TACC (1xM) is the acceleration time per 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(WP, QDMAX, TSEG, [], DT, TACC, OPTIONS) as above but the

% initial coordinates are taken from the first row of WP.

%

% TRAJ = MSTRAJ(WP, QDMAX, Q0, DT, TACC, QD0, QDF, OPTIONS) as above

% but additionally specifies the initial and final axis velocities (1xN).

%

% Options::

% 'verbose' Show details.

%

% Notes::

% - Only one of QDMAX or TSEG can be specified, the other is set to [].

% - 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(end,:) is the destination.

% - The motion has M segments from Q0 to P(1,:) to P(2,:) ... to P(end,:).

% - 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 where the "axes"

% correspond to translation and orientation in RPY or Euler angle form.

% - If qdmax is a scalar then all axes are assumed to have the same

% maximum speed.

%

% See also MTRAJ, LSPB, CTRAJ.

% Copyright (C) 1993-2017, 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.petercorke.com

function [TG, t, info] = mstraj(segments, qdmax, tsegment, q0, dt, Tacc, varargin)

if isempty(q0)

q0 = segments(1,:);

segments = segments(2:end,:);

end

assert(size(segments,2) == size(q0,2), 'RTB:mstraj:badarg', 'WP and Q0 must have same number of columns');

assert(xor(~isempty(qdmax), ~isempty(tsegment)), 'RTB:mstraj:badarg', 'Must specify either qdmax or tsegment, but not both');

if isempty(qdmax)

assert(length(tsegment) == size(segments,1), 'RTB:mstraj:badarg', 'Length of TSEG does not match number of segments');

end

if isempty(tsegment)

if length(qdmax) == 1

% if qdmax is a scalar assume all axes have the same speed

qdmax = repmat(qdmax, 1, numcols(segments));

end

assert(length(qdmax) == size(segments,2), 'RTB:mstraj:badarg', 'Length of QDMAX does not match number of axes');

end

ns = numrows(segments);

nj = numcols(segments);

[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 = q0;

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);

info(seg).slowest = slowest;

info(seg).segtime = tseg;

info(seg).axtime = tt;

info(seg).clock = clock;

% 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(q0, 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;

q0 = (1-s) * q_prev + s * q_next; % linear step

tg = [tg; q0];

clock = clock + dt;

end

q_prev = q_next; % next target becomes previous target

qd_prev = qd;

end

% add the final blend

qb = jtraj(q0, q_next, 0:dt:tacc2, qd_prev, qdf);

tg = [tg; qb(2:end,:)];

info(seg+1).segtime = tacc2;

info(seg+1).clock = clock;

% 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))

return

end

if nargout > 0

TG = tg;

end

if nargout > 1

t = (0:numrows(tg)-1)'*dt;

end

if nargout > 2

infout = info;

end

一键复制

编辑

Web IDE

原始数据

按行查看

历史

Logo

瓜分20万奖金 获得内推名额 丰厚实物奖励 易参与易上手

更多推荐