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.
325 lines
9.2 KiB
325 lines
9.2 KiB
%TRPLOT Draw a coordinate frame
|
|
%
|
|
% TRPLOT(T, OPTIONS) draws a 3D coordinate frame represented by the homogeneous
|
|
% transform T (4x4).
|
|
%
|
|
% H = TRPLOT(T, OPTIONS) as above but returns a handle.
|
|
%
|
|
% TRPLOT(H, T) moves the coordinate frame described by the handle H to
|
|
% the pose T (4x4).
|
|
%
|
|
% TRPLOT(R, OPTIONS) draws a 3D coordinate frame represented by the orthonormal
|
|
% rotation matrix R (3x3).
|
|
%
|
|
% H = TRPLOT(R, OPTIONS) as above but returns a handle.
|
|
%
|
|
% TRPLOT(H, R) moves the coordinate frame described by the handle H to
|
|
% the orientation R.
|
|
%
|
|
% Options::
|
|
% 'color',C The color to draw the axes, MATLAB colorspec C
|
|
% 'noaxes' Don't display axes on the plot
|
|
% 'axis',A Set dimensions of the MATLAB axes to A=[xmin xmax ymin ymax zmin zmax]
|
|
% 'frame',F The frame is named {F} and the subscript on the axis labels is F.
|
|
% 'text_opts', opt A cell array of MATLAB text properties
|
|
% 'handle',H Draw in the MATLAB axes specified by the axis handle H
|
|
% 'view',V Set plot view parameters V=[az el] angles, or 'auto'
|
|
% for view toward origin of coordinate frame
|
|
% 'arrow' Use arrows rather than line segments for the axes
|
|
% 'width', w Width of arrow tips (default 1)
|
|
% 'thick',t Thickness of lines (default 0.5)
|
|
% '3d' Plot in 3D using anaglyph graphics
|
|
% 'anaglyph',A Specify anaglyph colors for '3d' as 2 characters for
|
|
% left and right (default colors 'rc'):
|
|
% 'r' red
|
|
% 'g' green
|
|
% 'b' green
|
|
% 'c' cyan
|
|
% 'm' magenta
|
|
% 'dispar',D Disparity for 3d display (default 0.1)
|
|
%
|
|
% Examples::
|
|
%
|
|
% trplot(T, 'frame', 'A')
|
|
% trplot(T, 'frame', 'A', 'color', 'b')
|
|
% trplot(T1, 'frame', 'A', 'text_opts', {'FontSize', 10, 'FontWeight', 'bold'})
|
|
%
|
|
% h = trplot(T, 'frame', 'A', 'color', 'b');
|
|
% trplot(h, T2);
|
|
%
|
|
% 3D anaglyph plot
|
|
% trplot(T, '3d');
|
|
%
|
|
% Notes::
|
|
% - The arrow option requires the third party package arrow3.
|
|
% - The handle H is an hgtransform object.
|
|
% - When using the form TRPLOT(H, ...) the axes are not rescaled.
|
|
% - The '3d' option requires that the plot is viewed with anaglyph glasses.
|
|
% - You cannot specify 'color'
|
|
%
|
|
% See also TRPLOT2, TRANIMATE.
|
|
|
|
|
|
% 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/>.
|
|
|
|
% TODO
|
|
% need to decide how to handle scaling
|
|
% what does hold on mean? don't touch scaling?
|
|
|
|
function hout = trplot(T, varargin)
|
|
|
|
if isscalar(T) && ishandle(T)
|
|
% trplot(H, T)
|
|
H = T; T = varargin{1};
|
|
if isrot(T)
|
|
T = r2t(T);
|
|
end
|
|
set(H, 'Matrix', T);
|
|
|
|
% for the 3D case retrieve the right hgtransform and set it
|
|
hg2 = get(H, 'UserData');
|
|
if ~isempty(hg2)
|
|
set(hg2, 'Matrix', T);
|
|
end
|
|
|
|
return;
|
|
end
|
|
|
|
if size(T,3) > 1
|
|
error('trplot cannot operate on a sequence');
|
|
end
|
|
if ~ishomog(T) && ~isrot(T)
|
|
error('trplot operates only on transform (4x4) or rotation matrix (3x3)');
|
|
end
|
|
|
|
opt.color = [];
|
|
opt.axes = true;
|
|
opt.axis = [];
|
|
opt.frame = [];
|
|
opt.text_opts = [];
|
|
opt.view = [];
|
|
opt.width = 1;
|
|
opt.arrow = false;
|
|
opt.handle = [];
|
|
opt.anaglyph = 'rc';
|
|
opt.d_3d = false;
|
|
opt.dispar = 0.1;
|
|
opt.thick = 0.5;
|
|
|
|
opt = tb_optparse(opt, varargin);
|
|
|
|
if ~isempty(opt.color) && opt.d_3d
|
|
error('cannot specify ''color'' and ''3d'', use ''anaglyph'' option');
|
|
end
|
|
if isempty(opt.color)
|
|
opt.color = 'b';
|
|
end
|
|
if isempty(opt.text_opts)
|
|
opt.text_opts = {};
|
|
end
|
|
|
|
if opt.d_3d
|
|
opt.color = ag_color(opt.anaglyph(1));
|
|
end
|
|
|
|
if isempty(opt.axis)
|
|
% determine some default axis dimensions
|
|
|
|
% get the origin of the frame
|
|
if isrot(T)
|
|
c = [0 0 0]; % at zero for a rotation matrix
|
|
else
|
|
c = transl(T);
|
|
end
|
|
|
|
d = 1.2;
|
|
opt.axis = [c(1)-d c(1)+d c(2)-d c(2)+d c(3)-d c(3)+d];
|
|
|
|
end
|
|
|
|
% TODO: should do the 2D case as well
|
|
|
|
if ~isempty(opt.handle)
|
|
hax = opt.handle;
|
|
hold(hax);
|
|
else
|
|
ih = ishold;
|
|
if ~ih
|
|
% if hold is not on, then clear the axes and set scaling
|
|
cla
|
|
if ~isempty(opt.axis)
|
|
axis(opt.axis);
|
|
end
|
|
daspect([1 1 1]);
|
|
|
|
if opt.axes
|
|
xlabel( 'X');
|
|
ylabel( 'Y');
|
|
zlabel( 'Z');
|
|
rotate3d on
|
|
end
|
|
new_plot = true;
|
|
end
|
|
hax = gca;
|
|
hold on
|
|
end
|
|
% hax is the handle for the axis we will work with, either new or
|
|
% passed by option 'handle'
|
|
|
|
opt.text_opts = [opt.text_opts, 'Color', opt.color];
|
|
|
|
|
|
hg = hgtransform('Parent', hax);
|
|
|
|
|
|
% trplot( Q.R, fmt, color);
|
|
if isrot(T)
|
|
T = r2t(T);
|
|
end
|
|
|
|
% create unit vectors
|
|
o = [0 0 0]';
|
|
x1 = [1 0 0]';
|
|
y1 = [0 1 0]';
|
|
z1 = [0 0 1]';
|
|
|
|
% draw the axes
|
|
|
|
mstart = [o o o]';
|
|
mend = [x1 y1 z1]';
|
|
|
|
if opt.arrow
|
|
% draw the 3 arrows
|
|
S = [opt.color num2str(opt.width)];
|
|
ha = arrow3(mstart, mend, S);
|
|
for h=ha'
|
|
set(h, 'Parent', hg);
|
|
end
|
|
else
|
|
for i=1:3
|
|
plot2([mstart(i,1:3); mend(i,1:3)], 'Color', opt.color, ...
|
|
'LineWidth', opt.thick, ...
|
|
'Parent', hg);
|
|
end
|
|
end
|
|
|
|
% label the axes
|
|
if isempty(opt.frame)
|
|
fmt = '%c';
|
|
else
|
|
fmt = sprintf('%%c_{%s}', opt.frame);
|
|
end
|
|
|
|
% add the labels to each axis
|
|
h = text(x1(1), x1(2), x1(3), sprintf(fmt, 'X'), 'Parent', hg);
|
|
set(h, opt.text_opts{:});
|
|
|
|
h = text(y1(1), y1(2), y1(3), sprintf(fmt, 'Y'), 'Parent', hg);
|
|
set(h, opt.text_opts{:});
|
|
|
|
h = text(z1(1), z1(2), z1(3), sprintf(fmt, 'Z'), 'Parent', hg);
|
|
set(h, opt.text_opts{:});
|
|
|
|
% label the frame
|
|
if ~isempty(opt.frame)
|
|
h = text(o(1)-0.04*x1(1), o(2)-0.04*y1(2), o(3)-0.04*z1(3), ...
|
|
['\{' opt.frame '\}'], 'Parent', hg);
|
|
set(h, 'VerticalAlignment', 'middle', ...
|
|
'HorizontalAlignment', 'center', opt.text_opts{:});
|
|
end
|
|
|
|
if ~opt.axes
|
|
set(gca, 'visible', 'off');
|
|
end
|
|
if ischar(opt.view) && strcmp(opt.view, 'auto')
|
|
cam = x1+y1+z1;
|
|
view(cam(1:3));
|
|
elseif ~isempty(opt.view)
|
|
view(opt.view);
|
|
end
|
|
if isempty(opt.handle) && ~ih
|
|
grid on
|
|
hold off
|
|
end
|
|
|
|
% now place the frame in the desired pose
|
|
set(hg, 'Matrix', T);
|
|
|
|
|
|
if opt.d_3d
|
|
% 3D display. The original axes are for the left eye, and we add
|
|
% another set of axes to the figure for the right eye view and
|
|
% displace its camera to the right of that of that for the left eye.
|
|
% Then we recursively call trplot() to create the right eye view.
|
|
|
|
left = gca;
|
|
right = axes;
|
|
|
|
% compute the offset in world coordinates
|
|
off = -t2r(view(left))'*[opt.dispar 0 0]';
|
|
pos = get(left, 'CameraPosition');
|
|
|
|
set(right, 'CameraPosition', pos+off');
|
|
set(right, 'CameraViewAngle', get(left, 'CameraViewAngle'));
|
|
set(right, 'CameraUpVector', get(left, 'CameraUpVector'));
|
|
target = get(left, 'CameraTarget');
|
|
set(right, 'CameraTarget', target+off');
|
|
|
|
% set perspective projections
|
|
set(left, 'Projection', 'perspective');
|
|
set(right, 'Projection', 'perspective');
|
|
|
|
% turn off axes for right view
|
|
set(right, 'Visible', 'Off');
|
|
|
|
% set color for right view
|
|
hg2 = trplot(T, 'color', ag_color(opt.anaglyph(2)));
|
|
|
|
% the hgtransform for the right view is user data for the left
|
|
% view hgtransform, we need to change both when we rotate the
|
|
% frame.
|
|
set(hg, 'UserData', hg2);
|
|
end
|
|
|
|
% optionally return the handle, for later modification of pose
|
|
if nargout > 0
|
|
hout = hg;
|
|
end
|
|
end
|
|
|
|
function out = ag_color(c)
|
|
|
|
% map color character to an color triple, same as anaglyph.m
|
|
|
|
% map single letter color codes to image planes
|
|
switch c
|
|
case 'r'
|
|
out = [1 0 0]; % red
|
|
case 'g'
|
|
out = [0 1 0]; % green
|
|
case 'b'
|
|
% blue
|
|
out = [0 0 1];
|
|
case 'c'
|
|
out = [0 1 1]; % cyan
|
|
case 'm'
|
|
out = [1 0 1]; % magenta
|
|
case 'o'
|
|
out = [1 1 0]; % orange
|
|
end
|
|
end
|