Demo 1 shows animation of a car, demo 2 shows animation of a rectangle.
Also see this answer that animates a truck crossing a bridge. Demo 1: car-image
This demo shows how to
- Load any selected image of a car into Matlab.
- Scale the car-image so that it maintains a square aspect ratio without affecting the data aspect ratio or axis size.
- Define a trajectory that the center of the car-image will follow
- Animate the car's trajectory - animation only depicts translation, there is no change in orientation but you could add a rotation matrix to implement that if you wish.
First, select any image of a car but preferably one that has a transparent background and fills the entire image space. I have not attached my car-image file for copyright purposes.
[I,map,transparency] = imread(carFile);
Define the road width (centered at y=0) and the car width in the same units.
Define the trajectory of the center of the car as (carX, carY) coordinates where carX and carY are vectors.
carX = linspace(-150,1150,numel(x));
carY = (1./(1+exp(-x))*roadWidth - roadWidth/2)*.5;
Plot the road and the car's trajectory line.
The car image will be scaled to the data aspect ration and plot aspect ratio so if the figure is resized, it will scretch the car-image. To prevent that from happening, figure-resize is turned off. It's also important to set the xlim and ylim and to hold the axes prior to adding the car-image.
fig.Position(3:4) = [1180,420];
ax = axes(fig,'XLim',[-5, 1100], 'YLim', [-8 8], 'XTick', 0:200:1000, 'ytick', -8:8,'Units','pixels');
rightEdge = plot(xlim(ax), roadWidth./[-2,-2], 'k-', 'LineWidth', 5);
leftEdge = plot(xlim(ax), roadWidth./[2,2], 'k-', 'LineWidth', 5);
leftEdge = plot(xlim(ax), [0 0], 'k--', 'LineWidth', 3);
traj = plot(carX, carY, '--', 'LineWidth', 3,'Color',[0.9375 0.5 0.5]);
Here is where the car-image-length will be calculated according to the width you set in carWidth and according to the PlotBoxAspectRatio and DataAspectRatio. Again, it's important to set the axis limits and to hold the axes prior to this step.
asScalingFactor = (ax.DataAspectRatio(1)/ax.DataAspectRatio(2)) / ...
(ax.PlotBoxAspectRatio(1)/ax.PlotBoxAspectRatio(2));
carLength = carWidth * size(I,2)/size(I,1) * asScalingFactor;
The (carX,carY) trajectory specifies the position of the center of the car at each point in time. However, the image coordinate is specified by the lower-left corner of the rectangluar image. We also need the upper-right corner of the image at each point along the trajectory. Therefore, (carX,carY) representing the center of the car is converted to (carXi,carYi) which are two nx2 matrices representing the lower-left and upper-right corners of the car-image, scaled to size.
carXi = carX(:) + carLength./[-2,2];
carYi = carY(:) + carWidth./[-2,2];
The car is rendered at the first coordinates of the trajectory and then animated in a loop where each iteration moves the car to its new position. Since it is a complex image, animation could be slow. To speed up animation, use a simpler image or no image at all (a rectangle for example). There are four way to control the speed of the animation below. 1) increase/decrease the number of coordinates in the trajectory, 2) increase the pause command (currently commented-out), 3) reduce the reslution of the image (see imresize), 4) record the animation and specify any playback speed you wish (see getframe/movie).
carImg = imagesc(carXi(1,:), carYi(1,:), I, 'AlphaData', transparency);
carImg.XData = carXi(i,:);
carImg.YData = carYi(i,:);
Demo 2: rectangle
Similar to the first demo, this one uses a rectangle which simplifies the task and speeds up the animation.
carY = (1./(1+exp(-x))*roadWidth - roadWidth/2)*.5;
carX = linspace(-150,1150,numel(x));
fig.Position(3:4) = [1180,420];
ax = axes(fig,'XLim',[-5, 1100], 'YLim', [-8 8], 'XTick', 0:200:1000, 'ytick', -8:8,'Units','pixels');
rightEdge = plot(xlim(ax), roadWidth./[-2,-2], 'k-', 'LineWidth', 5);
leftEdge = plot(xlim(ax), roadWidth./[2,2], 'k-', 'LineWidth', 5);
leftEdge = plot(xlim(ax), [0 0], 'k--', 'LineWidth', 3);
traj = plot(carX, carY, '--', 'LineWidth', 3,'Color',[0.9375 0.5 0.5]);
asScalingFactor = (ax.DataAspectRatio(1)/ax.DataAspectRatio(2)) / ...
(ax.PlotBoxAspectRatio(1)/ax.PlotBoxAspectRatio(2));
carLength = carWidth * carLenghtFactor * asScalingFactor;
carXi = carX(:) - carLength/2;
carYi = carY(:) - carWidth/2;
carRect = rectangle(ax, 'Position', [carXi(1), carYi(1), carLength, carWidth],...
'LineWidth', 2, 'EdgeColor', 'b');
carRect.Position(1:2) = [carXi(i),carYi(i)];