forked from petercorke/robotics-toolbox-matlab
-
Notifications
You must be signed in to change notification settings - Fork 0
/
plot_vehicle.m
222 lines (201 loc) · 7.57 KB
/
plot_vehicle.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
%plot_vehicle Draw mobile robot pose
%
% PLOT_VEHICLE(X,OPTIONS) draws an oriented triangle to represent the pose
% of a mobile robot moving in a planar world. The pose X (1x3) = [x,y,theta].
% If X is a matrix (Nx3) then an animation of the robot motion is shown and
% animated at the specified frame rate.
%
% Image mode::
%
% Create a structure with the following elements and pass it with the
% 'model' option.
%
% image an RGB image (HxWx3)
% alpha an alpha plane (HxW) with pixels 0 if transparent
% rotation image rotation in degrees required for front to pointing to the right
% centre image coordinate (U,V) of the centre of the back axle
% length length of the car in real-world units
%
% Animation mode::
%
% H = PLOT_VEHICLE(X,OPTIONS) as above draws the robot and returns a handle.
%
% PLOT_VEHICLE(X, 'handle', H) updates the pose X (1x3) of the previously drawn
% robot.
%
% Options::
% 'scale',S draw vehicle with length S x maximum axis dimension (default
% 1/60)
% 'size',S draw vehicle with length S
% 'fillcolor',F the color of the circle's interior, MATLAB color spec
% 'alpha',A transparency of the filled circle: 0=transparent, 1=solid
% 'box' draw a box shape (default is triangle)
% 'fps',F animate at F frames per second (default 10)
% 'image',I use an image to represent the robot pose
% 'retain' when X (Nx3) then retain the robots, leaving a trail
% 'model',M animate an image of the vehicle. M is a structure with
% elements: image, alpha, rotation (deg), centre (pix), length (m).
% 'axis',h handle of axis or UIAxis to draw into (default is current axis)
% 'movie',M create a movie file in file M
%
% Example::
% [car.image,~,car.alpha] = imread('car2.png'); % image and alpha layer
% car.rotation = 180; % image rotation to align front with world x-axis
% car.centre = [648; 173]; % image coordinates of centre of the back wheels
% car.length = 4.2; % real world length for scaling (guess)
% h = plot_vehicle(x, 'model', car) % draw car at configuration x
% plot_vehicle(x, 'handle', h) % animate car to configuration x
%
% Notes::
% - The vehicle is drawn relative to the size of the axes, so set them
% first using axis().
% - For backward compatibility, 'fill', is a synonym for 'fillcolor'
% - For the 'model' option, you provide a monochrome or color image of the
% vehicle. Optionally you can provide an alpha mask (0=transparent).
% Specify the reference point on the vehicle as the (x,y) pixel
% coordinate within the image. Specify the rotation, in degrees, so that
% the car's front points to the right. Finally specify a length of the
% car, the image is scaled to be that length in the plot.
% - Set 'fps' to Inf to have zero pause
%
% See also Vehicle.plot, Animate, plot_poly, demos/car_animation
% 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.gnu.org/licenses/>.
%
% http://www.petercorke.com
% TODO needs to work for 3D point
function h_ = plot_vehicle(x, varargin)
opt.scale = 1/60;
opt.size = [];
opt.shape = {'triangle', 'box'};
opt.fps = 20;
opt.handle = [];
opt.image = [];
opt.model = [];
opt.retain = false;
opt.axis = [];
opt.trail = '';
opt.movie = [];
if numel(x) == 3
x = x(:)'; % enforce row vector
end
[opt,args] = tb_optparse(opt, varargin);
if isempty(opt.handle)
% create a new robot
% compute some default dimensions based on axis scaling
if isempty(opt.axis)
opt.axis = gca;
end
ax = opt.axis;
a = [ax.XLim ax.YLim];
d = (a(2)+a(4) - a(1)-a(3)) * opt.scale;
% create the robot
h.vehicle = draw_robot(d, opt, args);
if ~isempty(opt.trail)
hold on
h.trail = plot(0,0, opt.trail);
hold off
end
h.opt = opt;
plot_vehicle(x, 'handle', h, varargin{:});
else
% we are animating
h = opt.handle;
anim = Animate(opt.movie);
for i=1:numrows(x)
h.vehicle.Matrix = SE2(x(i,:)).SE3.T; % convert (x,y,th) to SE(3)
% check if retain is on
if h.opt.retain
plot_vehicle(x(i,:));
end
% extend the line if required
if ~isempty(h.opt.trail)
l = h.trail;
l.XData = [l.XData x(i,1)];
l.YData = [l.YData x(i,2)];
end
% pause a while
anim.add();
if ~isinf(h.opt.fps)
pause(1/h.opt.fps)
end
end
anim.close();
end
if nargout > 0
h_ = h;
end
end
function h = draw_robot(d, opt, args)
if ~isempty(opt.model)
% display an image of a vehicle, pass in a struct
if isstruct(opt.model)
img = opt.model.image;
rotation = opt.model.rotation;
centre = opt.model.centre;
scale = opt.model.length / max(numcols(img), numrows(img)) ;
else
img = opt.image;
centre = [numcols(img)/2 numrows(img)/2];
end
h = hgtransform('Tag', 'image');
h2 = hgtransform('Matrix', trotz(rotation, 'deg')*trscale(scale)*transl(-centre(1), -centre(2),0), 'Parent', h );
if isfield(opt.model, 'alpha')
% use alpha data if provided
alpha = opt.model.alpha;
else
% otherwise black pixels (0,0,0) are set to transparent
alpha = any(img>0,3);
end
image(img, 'AlphaData', alpha, 'Parent', h2);
%axis equal
else
% display a simple polygon
switch opt.shape
case 'triangle'
if ~isempty(opt.size)
d = opt.size;
end
L = d; W = 0.6*d;
corners = [
L 0
-L -W
-L W]';
case 'box'
if ~isempty(opt.size)
switch length(opt.size)
case 1
W = opt.size/2; L1 = opt.size/2; L2 = opt.size/2;
case 2
W = opt.size(1)/2; L1 = opt.size(2)/2; L2 = opt.size(2)/2;
case 3
W = opt.size(1)/2; L1 = opt.size(2); L2 = opt.size(3);
end
else
L1 = d; L2 = d; W = 0.6*d;
end
corners = [
-L1 W
0.6*L2 W
L2 0.5*W
L2 -0.5*W
0.6*L2 -W
-L1 -W ]';
end
h = plot_poly(corners, 'animate', 'axis', opt.axis, args{:});
end
end