I try to simulate a robot motion by using a line, 'o'
, as a robot. I update its motion using set
. But I have a problem to update the new position and angle of the robot's view angle. I use surf
as a robot view angle, because I want to show color gradients. Now I have to delete the surf
plot, and replot it again every time.
How can I update the figure, rather than completely redrawing it every time?
This is my code:
classdef Robot6<handle
properties
velocity = 0;
position = [0 0];
angle=0;
end
methods
function Runn(obj)
set( gcf,'WindowKeyPressFcn', @keyboard_down,'CloseRequestFcn', @close_window, 'WindowKeyReleaseFcn', @keyboard_up)
set( gca,'color', 'white','xlim', [-100, 100],'ylim', [-100, 100])
robot=line(obj.position(1), obj.position(2),'marker','o');
hold(gca,'on')
program_on = 1;
while program_on
userdataStore=[obj.velocity obj.angle obj.position]
%pause(0.001);
vel = [userdataStore(1)*cosd(userdataStore(2)),userdataStore(1)*sind(userdataStore(2))];
pos = userdataStore(3:4);
new_position = pos + vel;
if (abs(new_position(1)) > 100 || abs(new_position(2)) > 100)
new_position = pos;
end
obj.position = new_position;
set(robot, 'XData', new_position(1), 'YData', new_position(2));
%set(orient,'XData', new_position(1)+2*cos(userdataStore(2)), 'YData', new_position(2)+2*sin(userdataStore(2)));
%delete(orient)
x=[new_position(1) new_position(1)+10*cosd(userdataStore(2))+(10*tand(35)*cosd(90-userdataStore(2))) new_position(1)+10*cosd(userdataStore(2))-(10*tand(35)*cosd(90-userdataStore(2)))];
y=[new_position(2) new_position(2)+10*sind(userdataStore(2))-10*tand(35)*sind(90-userdataStore(2)) new_position(2)+10*sind(userdataStore(2))+10*tand(35)*sind(90-userdataStore(2))];
z=[100 0 0];
xv = linspace(min(x), max(x), 1000);
yv = linspace(min(y), max(y), 1000);
[X,Y] = meshgrid(xv, yv);
Z = griddata(x,y,z,X,Y);
figure(1)
orient=surf(X, Y, Z);
grid off
%set(gca, 'ZLim',[0 500])
shading interp
colormap(jet(80))
view(2)
pause(1)
delete(orient)
pause(0.00000000001)
end
delete(gcf);
function close_window(~,~)
program_on = 0;
end
function keyboard_down(~, event)
switch event.Key
case 'downarrow'
obj.velocity = -5;
case 'uparrow'
obj.velocity = 5;
case 'leftarrow'
obj.angle = obj.angle + 6;
case 'rightarrow'
obj.angle = obj.angle - 6;
otherwise
disp('unknown key');
end
end
function keyboard_up(~,~)
obj.velocity = 0;
end
end
end
end
You can do that the same way you update your robot
graphic object. Initialise an empty surf
object just after you initialise the robot
, then in the while loop you only update the surface with set
.
So for your code, just under your lines:
robot=line(obj.position(1), obj.position(2),'marker','o');
hold(gca,'on')
declare the empty surface object (it will exist but will not apear at this point because it is empty of data point):
orient = surf([],[],[]) ;
Then in the main while loop, replace the line:
orient=surf(X, Y, Z);
with this one:
set(orient,'XData',X,'YData',Y,'ZData',Z)
That answers your main question on how to update a surf
plot instead of redrawing it every time. Note that now you are not recreating a plot at every loop, a lot of the axes
and figure
properties won't be recalculated at each update, so you can also take all these lines:
grid off
%set(gca, 'ZLim',[0 500])
shading interp
colormap(jet(80))
view(2)
out of the main loop and place them right after the surface creation. These properties will stay like that and don't need to be set again at each loop iteration.