3

Quite a simple question but just couldn't find the answer online... I want to visualise a point cloud gathered from a lidar. I can plot the individual frames but wanted to loop them to create a "animation". I know how to do it for normal plots with drawnow but can't get it working with a scatter3. If I simply call scatter3 again like I have done in the commented code then the frame that I am viewing in the scatter plot jumps around with every update (Very uncomfortable). How do i get the scatter3 plot to update to the new points without changing the UI of the scatter ie. Still be able to pan and zoom around the visualised point cloud while it loops through.

EDIT: The file is a rosbag file, I cannot attach it because it is 170MB. The problem doesn't happen when using scatter3 in a loop with a normal array seems to be something with using scatter3 to call a PointCloud2 type file using frame = readMessages(rawBag, i).

EDIT: The problem does not seem to be with the axis limits but rather with the view of the axis within the figure window. When the scatter is initialised it is viewed with the positive x to the right side, positive y out of the screen and positive z upwards, as shown in view 1. Then after a short while it jumps to the second view, where the axis have changed, positive x is now out of the screen, positive y to the right and positive z upwards (both views shown in figures). This makes it not possible to view in a loop as it is constantly switching. So basically how to update the plot without calling scatter3(pointCloudData)?


rawBag = rosbag('jackwalking.bag');

frame = readMessages(rawBag, 1);
scatter3(frame{1});
hold on

for i = 1:length(readMessages(rawBag))
    disp(i)
    frame = readMessages(rawBag, i);

    % UPDATE the 3D Scatter %
    % drawnow does not work?
    % Currently using:
    scatter3(frame{1})
    pause(.01)
end

View 1

View 2

Jack Hayton
  • 363
  • 4
  • 18
  • The relevant bit of code is the stuff under `% UPDATE the 3D Scatter %` that you deleted. Please include that in your question. Ideally, you'd provide a small data set and complete code that shows the problem. See [mcve]. – Cris Luengo Jan 16 '19 at 19:58
  • Unfortunately I cannot share the data because its a 170mb .bag file. The problem only arises when using scatter3 to plot the data from this format... What would solve my problem is if there is a way to update a plot without making a new one? – Jack Hayton Jan 16 '19 at 20:22
  • See [here](https://stackoverflow.com/a/39059154/2627163), [here](https://stackoverflow.com/a/39633588/2627163), [here](https://stackoverflow.com/a/45532129/2627163) and [here](https://stackoverflow.com/a/53463426/2627163) how to animate your data without plotting it again and again. This may solve problems of memory and keep your axes without 'jumps'. – EBH Jan 16 '19 at 21:18

2 Answers2

2

The trick is to not use functions such as scatter or plot in an animation, but instead modify the data in the plot that is already there. These functions always reset axes properties, which is why you see the view reset. When modifying the existing plot, the axes are not affected.

The function scatter3 (as do all plotting functions) returns a handle to the graphics object that renders the plot. In the case of scatter3, this handle has three properties of interest here: XData, YData, and ZData. You can update these properties to change the location of the points:

N = 100;
data = randn(N,3) * 40;

h = scatter3(data(:,1),data(:,2),data(:,3));
for ii = 1:500
   data = data + randn(N,3);
   set(h,'XData',data(:,1),'YData',data(:,2),'ZData',data(:,3));
   drawnow
   pause(1/5)
end

The new data can be totally different too, it doesn't even need to contain the same number of points.

But when modifying these three properties, you will see the XLim, YLim and ZLim properties of the axes change. That is, the axes will rescale to accommodate all the data. If you need to prevent this, set the axes' XLimMode, YLimMode and ZLimMode to 'manual':

set(gca,'XLimMode','manual','YLimMode','manual','ZLimMode','manual')

When manually setting the limits, the limit mode is always set to manual.

Cris Luengo
  • 55,762
  • 10
  • 62
  • 120
0

As far as I understood what you describe as "plots jumpying around", the reason for this are the automatically adjusted x,y,z limits of the scatter3 plot. You can change the XLimMode, YLimMode, ZLimMode behaviour to manual to force the axis to stay fixed. You have to provide initial axes limits, though.

% Mock data, since you haven't provided a data sample
x = randn(200,50);
y = randn(200,50);
z = randn(200,50);

% Plot first frame before loop
HS = scatter3(x(:,1), y(:,1), z(:,1));
hold on

% Provide initial axes limits (adjust to your data)
xlim([-5,5])
ylim([-5,5])
zlim([-5,5])
% Set 'LimModes' to 'manual' to prevent auto resaling of the plot
set(gca, 'XLimMode', 'manual', 'YLimMode', 'manual', 'ZLimMode', 'manual')

for i=2:len(x,2)
    scatter3(x(:,i), y(:,i), z(:,i))
    pause(1)
end 

This yields an "animation" of plots, where you can pan and zoom into the data while continuous points are added in the loop

gehbiszumeis
  • 3,525
  • 4
  • 24
  • 41
  • Thanks for the answer, problem does not seem to be the limits. I have added more to my question and 2 screenshots. – Jack Hayton Jan 16 '19 at 19:37