function model = autoTree( nb, bf, skew, taper )
% autoTree Create System Models of Kinematic Trees
% autoTree(nb,bf,skew,taper) creates system models of kinematic trees
% having revolute joints. nb and bf specify the number of bodies in the
% tree, and the branching factor, respectively. The latter is the average
% number of children of a nonterminal node, and must be >=1. bf=1 produces
% an unbranched tree; bf=2 produces a binary tree; and non-integer values
% produce trees in which the number of children alternates between
% floor(bf) and ceil(bf) in such a way that the average is bf. Trees are
% constructed (and numbered) breadth-first. Link i is a thin-walled
% cylindrical tube of length l(i), radius l(i)/20, and mass m(i), lying
% between 0 and l(i) on the x axis of its local coordinate system. The
% values of l(i) and m(i) are determined by the tapering coefficient:
% l(i)=taper^(i-1) and m(i)=taper^(3*(i-1)). Thus, if taper=1 then
% m(i)=l(i)=1 for all i. The inboard joint axis of link i lies on the
% local z axis, and its outboard axis passes through the point (l(i),0,0)
% and is rotated about the x axis by an angle of skew radians relative to
% the inboard axis. If the link has more than one outboard joint then they
% all have the same axis. If skew=0 then the mechanism is planar. The
% final one, two or three arguments can be omitted, in which case they
% assume default values of taper=1, skew=0 and bf=1.
if nargin < 4
taper = 1;
end
if nargin < 3
skew = 0;
end
if nargin < 2
bf = 1;
end
model.NB = nb;
model.pitch = zeros(1,nb);
for i = 1:nb
model.parent(i) = floor((i-2+ceil(bf))/bf);
if model.parent(i) == 0
model.Xtree{1} = Xtrans([0 0 0]);
else
model.Xtree{i} = Xrotx(skew) * Xtrans([len(model.parent(i)),0,0]);
end
len(i) = taper^(i-1);
mass = taper^(3*(i-1));
CoM = len(i) * [0.5,0,0];
Icm = mass * len(i)^2 * diag([0.0025,1.015/12,1.015/12]);
model.I{i} = mcI( mass, CoM, Icm );
end
% drawing instructions
model.appearance{1} = {...
{ 'box', [-0.2, 0.2; -0.3, 0.3; -0.2, -0.06] } };
p0 = -1;
for i = 1:nb
p1 = model.parent(i);
tap = taper^(i-1);
if p1 == 0
ptap = 1;
else
ptap = taper^(p1-1);
end
if ( p1 > p0 )
model.appearance{i+1} = {...
{ 'cyl', [0.5 0 0]*tap, 0.05*tap, 1*tap, 'X' },...
{ 'cyl', [0 0 0], 0.08*ptap, 0.12*ptap, 'Z' } };
p0 = p1;
else
model.appearance{i+1} = {...
{ 'cyl', [0.5 0 0]*tap, 0.05*tap, 1*tap, 'X' } };
end
end