diff --git a/@SerialLink/SerialLink.m b/@SerialLink/SerialLink.m index 3b9f40ee..942b3f99 100644 --- a/@SerialLink/SerialLink.m +++ b/@SerialLink/SerialLink.m @@ -310,7 +310,7 @@ L = arg{1}; - if isa(L, 'Link') + if isa(L, 'LinkDH') % passed an array of Link objects r.links = L; @@ -1119,9 +1119,25 @@ function dyn(r, j) end end % methods + + methods (Static) + function URDF(filename) + + try + parse = urdfparse(filename); + except + error('RTB:SerialLink.URDF:badfile', 'File doesn''t exist or not parseable'); + end + + assert(length(parse.endlinks) == 1, 'Robot definition must be a single serial chain, with only one end-effector'); + + end + end end % classdef + + % utility function function s = mat2str(m) if isa(m, 'sym') @@ -1152,3 +1168,4 @@ function dyn(r, j) end end + diff --git a/Link.m b/Link.m index 67e059ac..53a02b68 100644 --- a/Link.m +++ b/Link.m @@ -1,1006 +1,3 @@ -%LinkRobot manipulator Link class -% -% A Link object holds all information related to a robot joint and link such as -% kinematics parameters, rigid-body inertial parameters, motor and -% transmission parameters. -% -% Constructors:: -% Link general constructor -% Prismatic construct a prismatic joint+link using standard DH -% PrismaticMDH construct a prismatic joint+link using modified DH -% Revolute construct a revolute joint+link using standard DH -% RevoluteMDH construct a revolute joint+link using modified DH -% -% Information/display methods:: -% display print the link parameters in human readable form -% dyn display link dynamic parameters -% type joint type: 'R' or 'P' -% -% Conversion methods:: -% char convert to string -% -% Operation methods:: -% A link transform matrix -% friction friction force -% nofriction Link object with friction parameters set to zero% -% -% Testing methods:: -% islimit test if joint exceeds soft limit -% isrevolute test if joint is revolute -% isprismatic test if joint is prismatic -% issym test if joint+link has symbolic parameters -% -% Overloaded operators:: -% + concatenate links, result is a SerialLink object -% -% Properties (read/write):: -% -% theta kinematic: joint angle -% d kinematic: link offset -% a kinematic: link length -% alpha kinematic: link twist -% jointtype kinematic: 'R' if revolute, 'P' if prismatic -% mdh kinematic: 0 if standard D&H, else 1 -% offset kinematic: joint variable offset -% qlim kinematic: joint variable limits [min max] -%- -% m dynamic: link mass -% r dynamic: link COG wrt link coordinate frame 3x1 -% I dynamic: link inertia matrix, symmetric 3x3, about link COG. -% B dynamic: link viscous friction (motor referred) -% Tc dynamic: link Coulomb friction -%- -% G actuator: gear ratio -% Jm actuator: motor inertia (motor referred) -% -% Examples:: -% -% L = Link([0 1.2 0.3 pi/2]); -% L = Link('revolute', 'd', 1.2, 'a', 0.3, 'alpha', pi/2); -% L = Revolute('d', 1.2, 'a', 0.3, 'alpha', pi/2); -% -% Notes:: -% - This is a reference class object. -% - Link objects can be used in vectors and arrays. -% - Convenience subclasses are Revolute, Prismatic, RevoluteMDH and -% PrismaticMDH. -% -% References:: -% - Robotics, Vision & Control, P. Corke, Springer 2011, Chap 7. -% -% See also Link, Revolute, Prismatic, SerialLink, RevoluteMDH, PrismaticMDH. - - - -% 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 - -classdef Link < matlab.mixin.Copyable - properties - % kinematic parameters - theta % kinematic: link angle - d % kinematic: link offset - alpha % kinematic: link twist - a % kinematic: link length - jointtype % revolute='R', prismatic='P' -- should be an enum - mdh % standard DH=0, MDH=1 - offset % joint coordinate offset - name % joint coordinate name - flip % joint moves in opposite direction - - % dynamic parameters - m % dynamic: link mass - r % dynamic: position of COM with respect to link frame (3x1) - I % dynamic: inertia of link with respect to COM (3x3) - Jm % dynamic: motor inertia - B % dynamic: motor viscous friction (1x1 or 2x1) - - Tc % dynamic: motor Coulomb friction (1x2 or 2x1) - G % dynamic: gear ratio - qlim % joint coordinate limits (2x1) - end - - methods - function l = Link(varargin) - %Link Create robot link object - % - % This the class constructor which has several call signatures. - % - % L = Link() is a Link object with default parameters. - % - % L = Link(LNK) is a Link object that is a deep copy of the link - % object LNK and has type Link, even if LNK is a subclass. - % - % L = Link(OPTIONS) is a link object with the kinematic and dynamic - % parameters specified by the key/value pairs. - % - % Options:: - % 'theta',TH joint angle, if not specified joint is revolute - % 'd',D joint extension, if not specified joint is prismatic - % 'a',A joint offset (default 0) - % 'alpha',A joint twist (default 0) - % 'standard' defined using standard D&H parameters (default). - % 'modified' defined using modified D&H parameters. - % 'offset',O joint variable offset (default 0) - % 'qlim',L joint limit (default []) - % 'I',I link inertia matrix (3x1, 6x1 or 3x3) - % 'r',R link centre of gravity (3x1) - % 'm',M link mass (1x1) - % 'G',G motor gear ratio (default 1) - % 'B',B joint friction, motor referenced (default 0) - % 'Jm',J motor inertia, motor referenced (default 0) - % 'Tc',T Coulomb friction, motor referenced (1x1 or 2x1), (default [0 0]) - % 'revolute' for a revolute joint (default) - % 'prismatic' for a prismatic joint 'p' - % 'standard' for standard D&H parameters (default). - % 'modified' for modified D&H parameters. - % 'sym' consider all parameter values as symbolic not numeric - % - % Notes:: - % - It is an error to specify both 'theta' and 'd' - % - The joint variable, either theta or d, is provided as an argument to - % the A() method. - % - The link inertia matrix (3x3) is symmetric and can be specified by giving - % a 3x3 matrix, the diagonal elements [Ixx Iyy Izz], or the moments and products - % of inertia [Ixx Iyy Izz Ixy Iyz Ixz]. - % - All friction quantities are referenced to the motor not the load. - % - Gear ratio is used only to convert motor referenced quantities such as - % friction and interia to the link frame. - % - % Old syntax:: - % L = Link(DH, OPTIONS) is a link object using the specified kinematic - % convention and with parameters: - % - DH = [THETA D A ALPHA SIGMA OFFSET] where SIGMA=0 for a revolute and 1 - % for a prismatic joint; and OFFSET is a constant displacement between the - % user joint variable and the value used by the kinematic model. - % - DH = [THETA D A ALPHA SIGMA] where OFFSET is zero. - % - DH = [THETA D A ALPHA], joint is assumed revolute and OFFSET is zero. - % - % Options:: - % - % 'standard' for standard D&H parameters (default). - % 'modified' for modified D&H parameters. - % 'revolute' for a revolute joint, can be abbreviated to 'r' (default) - % 'prismatic' for a prismatic joint, can be abbreviated to 'p' - % - % Notes:: - % - The parameter D is unused in a revolute joint, it is simply a placeholder - % in the vector and the value given is ignored. - % - The parameter THETA is unused in a prismatic joint, it is simply a placeholder - % in the vector and the value given is ignored. - % - % Examples:: - % A standard Denavit-Hartenberg link - % L3 = Link('d', 0.15005, 'a', 0.0203, 'alpha', -pi/2); - % since 'theta' is not specified the joint is assumed to be revolute, and - % since the kinematic convention is not specified it is assumed 'standard'. - % - % Using the old syntax - % L3 = Link([ 0, 0.15005, 0.0203, -pi/2], 'standard'); - % the flag 'standard' is not strictly necessary but adds clarity. Only 4 parameters - % are specified so sigma is assumed to be zero, ie. the joint is revolute. - % - % L3 = Link([ 0, 0.15005, 0.0203, -pi/2, 0], 'standard'); - % the flag 'standard' is not strictly necessary but adds clarity. 5 parameters - % are specified and sigma is set to zero, ie. the joint is revolute. - % - % L3 = Link([ 0, 0.15005, 0.0203, -pi/2, 1], 'standard'); - % the flag 'standard' is not strictly necessary but adds clarity. 5 parameters - % are specified and sigma is set to one, ie. the joint is prismatic. - % - % For a modified Denavit-Hartenberg revolute joint - % L3 = Link([ 0, 0.15005, 0.0203, -pi/2, 0], 'modified'); - % - % Notes:: - % - Link object is a reference object, a subclass of Handle object. - % - Link objects can be used in vectors and arrays. - % - The joint offset is a constant added to the joint angle variable before - % forward kinematics and subtracted after inverse kinematics. It is useful - % if you want the robot to adopt a 'sensible' pose for zero joint angle - % configuration. - % - The link dynamic (inertial and motor) parameters are all set to - % zero. These must be set by explicitly assigning the object - % properties: m, r, I, Jm, B, Tc. - % - The gear ratio is set to 1 by default, meaning that motor friction and - % inertia will be considered if they are non-zero. - % - % See also Revolute, Prismatic, RevoluteMDH, PrismaticMDH. - - %TODO eliminate legacy dyn matrix - - if nargin == 0 - % create an 'empty' Link object - % this call signature is needed to support arrays of Links - - %% kinematic parameters - l.alpha = 0; - l.a = 0; - l.theta = 0; - l.d = 0; - l.jointtype = 'R'; - l.mdh = 0; - l.offset = 0; - l.flip = false; - l.qlim = []; - - %% dynamic parameters - % these parameters must be set by the user if dynamics is used - l.m = 0; - l.r = [0 0 0]; - l.I = zeros(3,3); - - % dynamic params with default (zero friction) - l.Jm = 0; - l.G = 1; - l.B = 0; - l.Tc = [0 0]; - elseif nargin == 1 && isa(varargin{1}, 'Link') - % clone the passed Link object - this = varargin{1}; - - for j=1:length(this) - l(j) = Link(); - - % Copy all non-hidden properties. - p = properties(this(j)); - for i = 1:length(p) - l(j).(p{i}) = this(j).(p{i}); - end - end - - else - % Create a new Link based on parameters - - % parse all possible options - opt.theta = []; - opt.a = 0; - opt.d = []; - opt.alpha = 0; - opt.G = 0; - opt.B = 0; - opt.Tc = [0 0]; - opt.Jm = 0; - opt.I = zeros(3,3); - opt.m = 0; - opt.r = [0 0 0]; - opt.offset = 0; - opt.qlim = []; - opt.type = {'revolute', 'prismatic', 'fixed'}; - opt.convention = {'standard', 'modified'}; - opt.sym = false; - opt.flip = false; - - [opt,args] = tb_optparse(opt, varargin); - - % return a parameter as a number of symbol depending on - % the 'sym' option - - if isempty(args) - % This is the new call format, where all parameters are - % given by key/value pairs - % - % eg. L3 = Link('d', 0.15005, 'a', 0.0203, 'alpha', -pi/2); - if ~isempty(opt.theta) - % constant value of theta means it must be prismatic - l.theta = value( opt.theta, opt); - l.jointtype = 'P'; - end - - if ~isempty(opt.d) - % constant value of d means it must be revolute - l.d = value( opt.d, opt); - l.jointtype = 'R'; - end - if ~isempty(opt.d) && ~isempty(opt.theta) - error('RTB:Link:badarg', 'specify only one of ''d'' or ''theta'''); - end - - l.a = value( opt.a, opt); - l.alpha = value( opt.alpha, opt); - - l.offset = value( opt.offset, opt); - l.flip = value( opt.flip, opt); - - l.qlim = value( opt.qlim, opt); - - l.m = value( opt.m, opt); - l.r = value( opt.r, opt); - l.I = value( opt.I, opt); - l.Jm = value( opt.Jm, opt); - l.G = value( opt.G, opt); - l.B = value( opt.B, opt); - l.Tc = value( opt.Tc, opt); - else - % This is the old call format, where all parameters are - % given by a vector containing kinematic-only, or - % kinematic plus dynamic parameters - % - % eg. L3 = Link([ 0, 0.15005, 0.0203, -pi/2, 0], 'standard'); - dh = args{1}; - if length(dh) < 4 - error('RTB:Link:badarg', 'must provide params (theta d a alpha)'); - end - - % set the kinematic parameters - l.theta = dh(1); - l.d = dh(2); - l.a = dh(3); - l.alpha = dh(4); - - l.jointtype = 'R'; % default to revolute - l.offset = 0; - l.flip = false; - l.mdh = 0; % default to standard D&H - - % optionally set sigma and offset - if length(dh) >= 5 - if dh(5) == 1 - l.jointtype = 'P'; - end - end - if length(dh) == 6 - l.offset = dh(6); - end - - if length(dh) > 6 - % legacy DYN matrix - - if dh(5) > 0 - l.jointtype = 'P'; - else - l.jointtype = 'R'; - end - l.mdh = 0; % default to standard D&H - l.offset = 0; - - % it's a legacy DYN matrix - l.m = dh(6); - l.r = dh(7:9).'; % a column vector - v = dh(10:15); - l.I = [ v(1) v(4) v(6) - v(4) v(2) v(5) - v(6) v(5) v(3)]; - if length(dh) > 15 - l.Jm = dh(16); - end - if length(dh) > 16 - l.G = dh(17); - else - l.G = 1; - end - if length(dh) > 17 - l.B = dh(18); - else - l.B = 0.0; - end - if length(dh) > 18 - l.Tc = dh(19:20); - else - l.Tc = [0 0]; - end - l.qlim = []; - else - % we know nothing about the dynamics - l.m = []; - l.r = []; - l.I = []; - l.Jm = []; - l.G = 0; - l.B = 0; - l.Tc = [0 0]; - l.qlim = []; - end - end - - % set the kinematic convention to be used - if strcmp(opt.convention, 'modified') - l.mdh = 1; - else - l.mdh = 0; - end - - end - - function out = value(v, opt) - if opt.sym - out = sym(v); - else - out = v; - end - end - - end % link() - - function tau = friction(l, qd) - %Link.friction Joint friction force - % - % F = L.friction(QD) is the joint friction force/torque (1xN) for joint - % velocity QD (1xN). The friction model includes: - % - Viscous friction which is a linear function of velocity. - % - Coulomb friction which is proportional to sign(QD). - % - % Notes:: - % - The friction value should be added to the motor output torque, it has a - % negative value when QD>0. - % - The returned friction value is referred to the output of the gearbox. - % - The friction parameters in the Link object are referred to the motor. - % - Motor viscous friction is scaled up by G^2. - % - Motor Coulomb friction is scaled up by G. - % - The appropriate Coulomb friction value to use in the non-symmetric case - % depends on the sign of the joint velocity, not the motor velocity. - % - The absolute value of the gear ratio is used. Negative gear ratios are - % tricky: the Puma560 has negative gear ratio for joints 1 and 3. - % - % See also Link.nofriction. - - % viscous friction - tau = l.B * abs(l.G) * qd; - - % Coulomb friction - if ~isa(qd, 'sym') - if qd > 0 - tau = tau + l.Tc(1); - elseif qd < 0 - tau = tau + l.Tc(2); - end - end - - % scale up by gear ratio - tau = -abs(l.G) * tau; % friction opposes motion - end % friction() - - function tau = friction2(l, qd) - - % experimental code - qdm = qd / l.G; - taum = -l.B * qdm; - if qdm > 0 - taum = taum - l.Tc(1); - elseif qdm < 0 - taum = taum - l.Tc(2); - end - tau = taum * l.G; - end - - - function l2 = nofriction(l, only) - %Link.nofriction Remove friction - % - % LN = L.nofriction() is a link object with the same parameters as L except - % nonlinear (Coulomb) friction parameter is zero. - % - % LN = L.nofriction('all') as above except that viscous and Coulomb friction - % are set to zero. - % - % LN = L.nofriction('coulomb') as above except that Coulomb friction is set to zero. - % - % LN = L.nofriction('viscous') as above except that viscous friction is set to zero. - % - % Notes:: - % - Forward dynamic simulation can be very slow with finite Coulomb friction. - % - % See also Link.friction, SerialLink.nofriction, SerialLink.fdyn. - - l2 = copy(l); - - if nargin == 1 - only = 'coulomb'; - end - - switch only - case 'all' - l2.B = 0; - l2.Tc = [0 0]; - case 'viscous' - l2.B = 0; - case 'coulomb' - l2.Tc = [0 0]; - end - end - - function v = RP(l) - warning('RTB:Link:deprecated', 'use the .type() method instead'); - v = l.type(); - end - - function v = type(l) - %Link.type Joint type - % - % c = L.type() is a character 'R' or 'P' depending on whether joint is - % revolute or prismatic respectively. If L is a vector of Link objects - % return an array of characters in joint order. - % - % See also SerialLink.config. - v = ''; - for ll=l - switch ll.jointtype - case 'R' - v = strcat(v, 'R'); - case 'P' - v = strcat(v, 'P'); - otherwise - error('RTB:Link:badval', 'bad value for link jointtype %d', ll.type); - end - end - end - - function set.r(l, v) - %Link.r Set centre of gravity - % - % L.r = R sets the link centre of gravity (COG) to R (3-vector). - % - if isempty(v) - return; - end - assert(length(v) == 3, 'RTB:Link:badarg', 'COG must be a 3-vector'); - - l.r = v(:).'; - end % set.r() - - function set.Tc(l, v) - %Link.Tc Set Coulomb friction - % - % L.Tc = F sets Coulomb friction parameters to [F -F], for a symmetric - % Coulomb friction model. - % - % L.Tc = [FP FM] sets Coulomb friction to [FP FM], for an asymmetric - % Coulomb friction model. FP>0 and FM<0. FP is applied for a positive - % joint velocity and FM for a negative joint velocity. - % - % Notes:: - % - The friction parameters are defined as being positive for a positive - % joint velocity, the friction force computed by Link.friction uses the - % negative of the friction parameter, that is, the force opposing motion of - % the joint. - % - % See also Link.friction. - if isempty(v) - return; - end - - if isa(v,'sym') && ~isempty(symvar(v)) - l.Tc = sym('Tc'); - elseif isa(v,'sym') && isempty(symvar(v)) - v = double(v); - end - - if length(v) == 1 ~isa(v,'sym') - l.Tc = [v -v]; - elseif length(v) == 2 && ~isa(v,'sym') - assert(v(1) >= v(2), 'RTB:Link:badarg', 'Coulomb friction is [Tc+ Tc-]'); - l.Tc = v; - else - error('RTB:Link:badarg', 'Coulomb friction vector can have 1 (symmetric) or 2 (asymmetric) elements only') - end - end % set.Tc() - - function set.I(l, v) - %Link.I Set link inertia - % - % L.I = [Ixx Iyy Izz] sets link inertia to a diagonal matrix. - % - % L.I = [Ixx Iyy Izz Ixy Iyz Ixz] sets link inertia to a symmetric matrix with - % specified inertia and product of intertia elements. - % - % L.I = M set Link inertia matrix to M (3x3) which must be symmetric. - if isempty(v) - return; - end - if all(size(v) == [3 3]) - if isa(v, 'double') && norm(v-v') > eps - error('RTB:Link:badarg', 'inertia matrix must be symmetric'); - end - l.I = v; - elseif length(v) == 3 - l.I = diag(v); - elseif length(v) == 6 - l.I = [ v(1) v(4) v(6) - v(4) v(2) v(5) - v(6) v(5) v(3) ]; - else - error('RTB:Link:badarg', 'must set I to 3-vector, 6-vector or symmetric 3x3'); - end - end % set.I() - - function v = islimit(l, q) - %Link.islimit Test joint limits - % - % L.islimit(Q) is true (1) if Q is outside the soft limits set for this joint. - % - % Note:: - % - The limits are not currently used by any Toolbox functions. - assert(~isempty(l.qlim), 'RTB:Link:badarg', 'no limits assigned to link') - v = (q > l.qlim(2)) - (q < l.qlim(1)); - end % islimit() - - function v = isrevolute(L) - %Link.isrevolute Test if joint is revolute - % - % L.isrevolute() is true (1) if joint is revolute. - % - % See also Link.isprismatic. - - v = [L.jointtype] == 'R'; - end - - function v = isprismatic(L) - %Link.isprismatic Test if joint is prismatic - % - % L.isprismatic() is true (1) if joint is prismatic. - % - % See also Link.isrevolute. - v = ~L.isrevolute(); - end - - - function T = A(L, q) - %Link.A Link transform matrix - % - % T = L.A(Q) is an SE3 object representing the transformation between link - % frames when the link variable Q which is either the Denavit-Hartenberg - % parameter THETA (revolute) or D (prismatic). For: - % - standard DH parameters, this is from the previous frame to the current. - % - modified DH parameters, this is from the current frame to the next. - % - % Notes:: - % - For a revolute joint the THETA parameter of the link is ignored, and Q used instead. - % - For a prismatic joint the D parameter of the link is ignored, and Q used instead. - % - The link offset parameter is added to Q before computation of the transformation matrix. - % - % See also SerialLink.fkine. - sa = sin(L.alpha); ca = cos(L.alpha); - if L.flip - q = -q + L.offset; - else - q = q + L.offset; - end - if L.isrevolute - % revolute - st = sin(q); ct = cos(q); - d = L.d; - else - % prismatic - st = sin(L.theta); ct = cos(L.theta); - d = q; - end - - if L.mdh == 0 - % standard DH - - T = [ ct -st*ca st*sa L.a*ct - st ct*ca -ct*sa L.a*st - 0 sa ca d - 0 0 0 1]; - else - % modified DH - - T = [ ct -st 0 L.a - st*ca ct*ca -sa -sa*d - st*sa ct*sa ca ca*d - 0 0 0 1]; - end - - T = SE3(T); - - end % A() - - function display(l) - %Link.display Display parameters - % - % L.display() displays the link parameters in compact single line format. If L is a - % vector of Link objects displays one line per element. - % - % Notes:: - % - This method is invoked implicitly at the command line when the result - % of an expression is a Link object and the command has no trailing - % semicolon. - % - % See also Link.char, Link.dyn, SerialLink.showlink. - loose = strcmp( get(0, 'FormatSpacing'), 'loose'); - if loose - disp(' '); - end - disp([inputname(1), ' = ']) - disp( char(l) ); - end % display() - - function s = char(links, from_robot) - %Link.char Convert to string - % - % s = L.char() is a string showing link parameters in a compact single line format. - % If L is a vector of Link objects return a string with one line per Link. - % - % See also Link.display. - - % display in the order theta d a alpha - if nargin < 2 - from_robot = false; - end - - s = ''; - - for j=1:length(links) - l = links(j); - - if l.mdh == 0 - conv = 'std'; - else - conv = 'mod'; - end - if length(links) == 1 - qname = 'q'; - else - qname = sprintf('q%d', j); - end - - if from_robot - fmt = '%11g'; - % invoked from SerialLink.char method, format for table - if l.isprismatic - % prismatic joint - js = sprintf('|%3d|%11s|%11s|%11s|%11s|%11s|', ... - j, ... - render(l.theta, fmt), ... - qname, ... - render(l.a, fmt), ... - render(l.alpha, fmt), ... - render(l.offset, fmt)); - else - % revolute joint - js = sprintf('|%3d|%11s|%11s|%11s|%11s|%11s|', ... - j, ... - qname, ... - render(l.d, fmt), ... - render(l.a, fmt), ... - render(l.alpha, fmt), ... - render(l.offset, fmt)); - end - else - if length(links) == 1 - if l.isprismatic - % prismatic joint - js = sprintf('Prismatic(%s): theta=%s, d=%s, a=%s, alpha=%s, offset=%s', ... - conv, ... - render(l.theta,'%g'), ... - qname, ... - render(l.a,'%g'), ... - render(l.alpha,'%g'), ... - render(l.offset,'%g') ); - else - % revolute - js = sprintf('Revolute(%s): theta=%s, d=%s, a=%s, alpha=%s, offset=%s', ... - conv, ... - qname, ... - render(l.d,'%g'), ... - render(l.a,'%g'), ... - render(l.alpha,'%g'), ... - render(l.offset,'%g') ); - end - else - if l.isprismatic - % prismatic joint - js = sprintf('Prismatic(%s): theta=%s d=%s a=%s alpha=%s offset=%s', ... - conv, ... - render(l.theta), ... - qname, ... - render(l.a), ... - render(l.alpha), ... - render(l.offset) ); - else - % revolute - js = sprintf('Revolute(%s): theta=%s d=%s a=%s alpha=%s offset=%s', ... - conv, ... - qname, ... - render(l.d), ... - render(l.a), ... - render(l.alpha), ... - render(l.offset) ); - end - end - end - if isempty(s) - s = js; - else - s = char(s, js); - end - end - - - end % char() - - function dyn(links) - %Link.dyn Show inertial properties of link - % - % L.dyn() displays the inertial properties of the link object in a multi-line - % format. The properties shown are mass, centre of mass, inertia, friction, - % gear ratio and motor properties. - % - % If L is a vector of Link objects show properties for each link. - % - % See also SerialLink.dyn. - - for j=1:numel(links) - l = links(j); - if numel(links) > 1 - fprintf('\nLink %d::', j); - end - fprintf('%s\n', l.char()); - if ~isempty(l.m) - fprintf(' m = %s\n', render(l.m)) - end - if ~isempty(l.r) - s = render(l.r); - fprintf(' r = %s %s %s\n', s{:}); - end - if ~isempty(l.I) - s = render(l.I(1,:)); - fprintf(' I = | %s %s %s |\n', s{:}); - s = render(l.I(2,:)); - fprintf(' | %s %s %s |\n', s{:}); - s = render(l.I(3,:)); - fprintf(' | %s %s %s |\n', s{:}); - end - if ~isempty(l.Jm) - fprintf(' Jm = %s\n', render(l.Jm)); - end - if ~isempty(l.B) - fprintf(' Bm = %s\n', render(l.B)); - end - if ~isempty(l.Tc) - fprintf(' Tc = %s(+) %s(-)\n', ... - render(l.Tc(1)), render(l.Tc(2))); - end - if ~isempty(l.G) - fprintf(' G = %s\n', render(l.G)); - end - if ~isempty(l.qlim) - fprintf(' qlim = %f to %f\n', l.qlim(1), l.qlim(2)); - end - end - end % dyn() - - % Make a copy of a handle object. - % http://www.mathworks.com/matlabcentral/newsreader/view_thread/257925 -% function new = copy(this) -% -% for j=1:length(this) -% % Instantiate new object of the same class. -% %new(j) = feval(class(this(j))); -% new(j) = Link(); -% % Copy all non-hidden properties. -% p = properties(this(j)); -% for i = 1:length(p) -% new(j).(p{i}) = this(j).(p{i}); -% end -% end -% end - - function links = horzcat(varargin) - %Link.horzcat Concatenate link objects - % - % [L1 L2] is a vector that contains deep copies of the Link class objects - % L1 and L2. - % - % Notes:: - % - The elements of the vector are all of type Link. - % - If the elements were of a subclass type they are convered to type Link. - % - Extends to arbitrary number of objects in list. - % - % See also Link.plus. - - % convert all elements to Link type - l = cellfun(@Link, varargin, 'UniformOutput', 0); - - % convert to vector, cell2mat won't do this for me - links = cat(2, l{:}); - end - - function links = vertcat(this, varargin) - links = this.horzcat(varargin{:}); - end - - - function R = plus(L1, L2) - %Link.plus Concatenate link objects into a robot - % - % L1+L2 is a SerialLink object formed from deep copies of the Link class objects - % L1 and L2. - % - % Notes:: - % - The elements can belong to any of the Link subclasses. - % - Extends to arbitrary number of objects, eg. L1+L2+L3+L4. - % - % See also SerialLink, SerialLink.plus, Link.horzcat. - assert( isa(L1, 'Link') && isa(L2, 'Link'), 'RTB:Link: second operand for + operator must be a Link class'); - - R = SerialLink([L1 L2]); - - end - - function res = issym(l) - %Link.issym Check if link is a symbolic model - % - % res = L.issym() is true if the Link L has any symbolic parameters. - % - % See also Link.sym. - - res = any( cellfun(@(x) isa(l.(x), 'sym'), properties(l)) ); - end - - function l = sym(l) - %Link.sym Convert link parameters to symbolic type - % - % LS = L.sym is a Link object in which all the parameters are symbolic - % ('sym') type. - % - % See also Link.issym. - -% sl = Link(l); % clone the link - - if ~isempty(l.theta) - l.theta = sym(l.theta); - end - if ~isempty(l.d) - l.d = sym(l.d); - end - l.alpha = sym(l.alpha); - l.a = sym(l.a); - l.offset = sym(l.offset); - - l.I = sym(l.I); - l.r = sym(l.r); - l.m = sym(l.m); - - l.Jm = sym(l.Jm); - l.G = sym(l.G); - l.B = sym(l.B); - l.Tc = sym(l.Tc); - end - - - end % methods - - -end % class - -function s = render(v, fmt) - if nargin < 2 - fmt = '%-11.4g'; - end - if length(v) == 1 - if isa(v, 'double') - s = sprintf(fmt, v); - elseif isa(v, 'sym') - s = char(v); - else - error('RTB:Link:badarg', 'Link parameter must be numeric or symbolic'); - end - else - - for i=1:length(v) - if isa(v, 'double') - s{i} = sprintf(fmt, v(i)); - elseif isa(v, 'sym') - s{i} = char(v(i)); - else - error('RTB:Link:badarg', 'Link parameter must be numeric or symbolic'); - end - end - end +function l = Link(varargin) + l = LinkDH(varargin{:}); end diff --git a/Prismatic.m b/Prismatic.m index 522c3930..f20f372d 100644 --- a/Prismatic.m +++ b/Prismatic.m @@ -80,7 +80,7 @@ % along with RTB. If not, see . % % http://www.petercorke.com -classdef Prismatic < Link +classdef Prismatic < LinkDH methods function L = Prismatic(varargin) %Prismatic.Prismatic Create prismatic robot link object @@ -116,7 +116,7 @@ % friction and interia to the link frame. % % See also Link, Prismatic, RevoluteMDH. - L = L@Link(varargin{:}); + L = L@LinkDH(varargin{:}); if nargin == 0 L.d = []; diff --git a/PrismaticMDH.m b/PrismaticMDH.m index 6a5488c3..ea7ad17f 100644 --- a/PrismaticMDH.m +++ b/PrismaticMDH.m @@ -81,7 +81,7 @@ % along with RTB. If not, see . % % http://www.petercorke.com -classdef PrismaticMDH < Link +classdef PrismaticMDH < LinkDH methods function L = PrismaticMDH(varargin) %PrismaticMDH.PrismaticMDH Create prismatic robot link object using MDH notaton @@ -117,7 +117,7 @@ % friction and interia to the link frame. % % See also Link, Prismatic, RevoluteMDH. - L = L@Link(varargin{:}); + L = L@LinkDH(varargin{:}); if nargin == 0 L.d = []; diff --git a/Revolute.m b/Revolute.m index 939c334e..1bad48b5 100644 --- a/Revolute.m +++ b/Revolute.m @@ -81,7 +81,7 @@ % % http://www.petercorke.com -classdef Revolute < Link +classdef Revolute < LinkDH methods function L = Revolute(varargin) %Revolute.Revolute Create revolute robot link object @@ -117,7 +117,7 @@ % friction and interia to the link frame. % % See also Link, Prismatic, RevoluteMDH. - L = L@Link(varargin{:}); + L = L@LinkDH(varargin{:}); if nargin == 0 L.theta = []; diff --git a/RevoluteMDH.m b/RevoluteMDH.m index fb1f9a9b..48276484 100644 --- a/RevoluteMDH.m +++ b/RevoluteMDH.m @@ -82,7 +82,7 @@ % % http://www.petercorke.com -classdef RevoluteMDH < Link +classdef RevoluteMDH < LinkDH methods function L = RevoluteMDH(varargin) %RevoluteMDH.RevoluteMDH Create revolute robot link object using MDH notation @@ -118,7 +118,7 @@ % friction and interia to the link frame. % % See also Link, Prismatic, RevoluteMDH. - L = L@Link(varargin{:}); + L = L@LinkDH(varargin{:}); if nargin == 0 L.theta = []; diff --git a/new_rtb_classes/RTBJoint.m b/new_rtb_classes/RTBJoint.m new file mode 100644 index 00000000..1a95b8fc --- /dev/null +++ b/new_rtb_classes/RTBJoint.m @@ -0,0 +1,36 @@ +classdef RTBJoint < RTBRobotComponent + %RTBJOINT RTB Representation of a robot joint + % + % This is the place where a potentially new RTB robot classe will be + % born. At current stage it is a game of thoughts and place of + % conceptual design considerations. This is NOT productive code. + + % The RTBJoint class could be a base class for the existing revolute + % and prismatic 'link' classes. Though, here we might get a little into + % trouble because the original 'link' class does both jobs, the joint + % and the link job. + % + % The RTBJoint class would allow for arbitrary single and multi-dof + % joint implementation including their dynamics. This could allow + % straightforward interfacing with the CompliantJointToolbox. + % + + properties + Property1 + end + + methods + function obj = RTBJoint(inputArg1,inputArg2) + %RTBJOINT Construct an instance of this class + % Detailed explanation goes here + obj.Property1 = inputArg1 + inputArg2; + end + + function outputArg = method1(obj,inputArg) + %METHOD1 Summary of this method goes here + % Detailed explanation goes here + outputArg = obj.Property1 + inputArg; + end + end +end + diff --git a/new_rtb_classes/RTBLink.m b/new_rtb_classes/RTBLink.m new file mode 100644 index 00000000..0c66b560 --- /dev/null +++ b/new_rtb_classes/RTBLink.m @@ -0,0 +1,37 @@ +classdef RTBLink < RTBRobotComponent + %RTBLINK RTB Representation of a robot link. + % + % This is the place where a potentially new RTB robot classes will be + % born. At current stage it is a game of thoughts and place of + % conceptual design considerations. This is NOT productive code. + + % The RTBJoint class could be a base class for the existing 'link' class. + % Though, here we might get a little into trouble because the original + % 'link' class does both jobs, the joint and the link job. This would + % maybe the place to implement an optional link (i.e. a handle or + % class name) to a joint class instance for backwards compatibility. + % + % Most robots are build from a few different link types. The RTBLink + % class would allow to associate a visual representation to a link + % object and reuse this type of link in different ways and in + % combinations with different joints. + + properties + Property1 + end + + methods + function obj = RTBLink(inputArg1,inputArg2) + %RTBLINK Construct an instance of this class + % Detailed explanation goes here + obj.Property1 = inputArg1 + inputArg2; + end + + function outputArg = method1(obj,inputArg) + %METHOD1 Summary of this method goes here + % Detailed explanation goes here + outputArg = obj.Property1 + inputArg; + end + end +end + diff --git a/new_rtb_classes/RTBRobot.m b/new_rtb_classes/RTBRobot.m new file mode 100644 index 00000000..0f45319d --- /dev/null +++ b/new_rtb_classes/RTBRobot.m @@ -0,0 +1,124 @@ +classdef RTBRobot < handle + %RTBROBOT RTB Representation of a Robot + % This is the place where a potentially new RTB robot classe will be + % born. At current stage it is a game of thoughts and place of + % conceptual design considerations. This is NOT productive code. + + % RTBRobot: A handle class object + % A full robot, especially a legged one, can easily become abig data + % object. So it might not be a good idea to always pass deep copies + % around. Next, robots are supposed to do things, interact with and + % manipulate their environment. Deep copies can still be achieved if + % really necessary by implementing an explicit 'copy' method. + % So it might be a nice feature to exploit also the plenty of methods + % that natively ship with the handles class, such as notifiers and + % listeners. + % + % Other potential parent classes are: + % matlab.mixin.SetGet — Provides set and get methods to access + % property values. + % dynamicprops — Enables you to define properties that are associated + % with an object, but not the class in general. + % matlab.mixin.Copyable Provides a copy method that you can customize + % for your class. + % + % The existing SerialLink objects can be modified to be a specialized + % subclass of RTBRobot. It should be feasible to keep the function + % interface consistent and backwards compatible while updating the + % SerialLink implementation to make use of RTBRobot functionality. This + % would enable backwards compatibility. + % + + properties + graph % graph representation of the physical robot + name % robot name (e.g. Wall-e) + gravity % gravity + base % index of (floating) base node + tool % legacy tool transform + manufacturer% name of the manufacturer + comment % some user information + plotopt % how to draw the robot + fast % + interface % SOME + ikineType % + trail % MORE + movie % + delay % ORIGINAL + loop % + model3d % SERIALLINK + faces % + points % CLASS + plotopt3d % + n % PROPERTIES + links % legacy... + T % + config % + offset % should go to joint objects? method for backwards compatibility + qlim % should go to joint objects? method for backwards compatibility + d % + a % + alpha % + theta % + end + + methods + function obj = RTBRobot(EdgeTable,NodeTable) + %RTBROBOT Construct an instance of this class + % Detailed explanation goes here + + % The kinematic structure of the RTBRobot is represented as a + % graph. The digraph class implemens a graph theory interface + % for directed graphs including loops. This would serve for the + % definition of serial, tree-like and closed kinematic chains. + % + % The EdgeTable and NodeTable option to create a graph could be + % less efficient but human readable option to create the graph. + % In particular because it permits the addition of arbitrary + % variables and values to the edges and nodes. + % + % Another option could be to keep a separate vector or cell of + % joint and link objects. The index within the vector or cell + % would correspond to the index in the digraph. + % + % It might be a good idea to follow the approach in RBDL, where + % links are nodes and joints are directed edges. This motivates + % a generalized 'RTBLink' and a separate RTBJoint class, which + % replace the original 'link' class. + % + % RBDL is pretty fast and mature. Any implementation in MATLAB + % will likely be slower. So it would be nice, to follow a dual + % approach with the original RTB functions and optional + % wrappers for RBDL for those, who are willing to include the + % additional code dependency. + obj.graph = digraph(EdgeTable,NodeTable) + end + + function outputArg = method1(obj,inputArg) + %METHOD1 Summary of this method goes here + % Detailed explanation goes here + outputArg = obj.Property1 + inputArg; + end + + function clone = copy(obj) + % COPY Creates an explicit deep copy of the robot. + % Detailed explanation goes here + + % The big amount of work is then to implement the already existing + % functionality using the new data structure: + % A copy genforces ikunc itorque pay rne_mdh + % DH coriolis getpos inertia jacob0 paycap sym + % MDH display gravjac isconfig jacob_dot payload teach + % SerialLink dyn gravload isdh jacobe perturb todegrees + % accel edit ikcon islimit jacobn plot toradians + % addprop fdyn ikine ismdh jointdynamics plot3d trchain + % animate fellipse ikine3 isprismatic jtraj plus twists + % char fkine ikine6s isrevolute maniplty qmincon vellipse + % cinertia friction ikine_sym isspherical mtimes rne + % collisions gencoords ikinem issym nofriction rne_dh + % + % Static methods: + % + % URDF + end +end + diff --git a/new_rtb_classes/RTBRobotComponent.m b/new_rtb_classes/RTBRobotComponent.m new file mode 100644 index 00000000..be0eba3e --- /dev/null +++ b/new_rtb_classes/RTBRobotComponent.m @@ -0,0 +1,27 @@ +classdef RTBRobotComponent + %RTBROBOTCOMPONENT Abstract base class for robot components such as + %joints, links and tools. + % + % This is the place where a potentially new RTB robot classe will be + % born. At current stage it is a game of thoughts and place of + % conceptual design considerations. This is NOT productive code. + + properties + Property1 + end + + methods + function obj = RTBRobotComponent(inputArg1,inputArg2) + %RTBROBOTCOMPONENT Construct an instance of this class + % Detailed explanation goes here + obj.Property1 = inputArg1 + inputArg2; + end + + function outputArg = method1(obj,inputArg) + %METHOD1 Summary of this method goes here + % Detailed explanation goes here + outputArg = obj.Property1 + inputArg; + end + end +end + diff --git a/new_rtb_classes/RTBTool.m b/new_rtb_classes/RTBTool.m new file mode 100644 index 00000000..616065cc --- /dev/null +++ b/new_rtb_classes/RTBTool.m @@ -0,0 +1,31 @@ +classdef RTBTool < RTBRobotComponent + %RTBTOOL RTB Representation of a robot tool + % + % This is the place where a potentially new RTB robot classe will be + % born. At current stage it is a game of thoughts and place of + % conceptual design considerations. This is NOT productive code. + + % The RTBJoint class would implement the functionality of a generalized + % end-effector. This could be a gripper, a wheel, a foot, a camera, a + % welding device, whatever... It could have dynamic properties in + % addition to some standardized properties. (dynamicprops inheritance). + % + properties + Property1 + end + + methods + function obj = RTBTool(inputArg1,inputArg2) + %RTBTOOL Construct an instance of this class + % Detailed explanation goes here + obj.Property1 = inputArg1 + inputArg2; + end + + function outputArg = method1(obj,inputArg) + %METHOD1 Summary of this method goes here + % Detailed explanation goes here + outputArg = obj.Property1 + inputArg; + end + end +end + diff --git a/unit_test/edgelisttest.m b/unit_test/edgelisttest.m deleted file mode 100644 index a7ea8edc..00000000 --- a/unit_test/edgelisttest.m +++ /dev/null @@ -1,27 +0,0 @@ -im = [ - 0 0 0 0 0 0 0 0 - 0 0 0 0 0 0 0 0 - 0 0 0 1 1 1 0 0 - 0 0 0 1 1 1 0 0 - 0 0 1 1 1 1 0 0 - 0 0 0 1 1 1 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 0 0 0 0 - ]; - - seeds = [3 5; 4 6; 5 6; 4 5; 2 5; 3 6; 4 7; 2 6]; - for seed=seeds' - edge = edgelist(im, seed); - for e=edge - assert( im(e(2),e(1)) == im(seed(2), seed(1)) ); - end - - edge = edgelist(im, seed, 1); - for e=edge - assert( im(e(2),e(1)) == im(seed(2), seed(1)) ); - end - end - - pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy