How can add an image to the plot that moves according to the x,y coordinatates?

54 vues (au cours des 30 derniers jours)
I have a script which makes these rectangle boxes and shows the motion of a vehicle on a road. I would like to add an image of a car such that I can overlay it over the rectangle boxes. I have the inputs for x,y and yaw coordinates.

Réponse acceptée

Adam Danz
Adam Danz le 12 Mai 2021
Modifié(e) : Adam Danz le 12 Mai 2021
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
  1. Load any selected image of a car into Matlab.
  2. Scale the car-image so that it maintains a square aspect ratio without affecting the data aspect ratio or axis size.
  3. Define a trajectory that the center of the car-image will follow
  4. 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.
% Read in car image
carFile = 'car.png';
[I,map,transparency] = imread(carFile);
Define the road width (centered at y=0) and the car width in the same units.
roadWidth = 8;
carWidth = 3.5; % same units as road-width
Define the trajectory of the center of the car as (carX, carY) coordinates where carX and carY are vectors.
x = linspace(-7,7,50);
carX = linspace(-150,1150,numel(x)); % car will start and end outside of the axes
carY = (1./(1+exp(-x))*roadWidth - roadWidth/2)*.5; % assumes road is centered at y=0
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 = figure();
fig.Position(3:4) = [1180,420];
fig.Resize = 'off'; % disable fig resize since car size depends on plot aspect ratio.
movegui(fig)
ax = axes(fig,'XLim',[-5, 1100], 'YLim', [-8 8], 'XTick', 0:200:1000, 'ytick', -8:8,'Units','pixels');
box(ax,'on')
hold(ax,'on')
% Plot road edges and center line
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);
% Add trajectory path
traj = plot(carX, carY, '--', 'LineWidth', 3,'Color',[0.9375 0.5 0.5]); %lightcoral
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.
% Compute car length based on specified width and aspect ratio
% xlim and ylim must be set prior to this. Axes & data aspect ratios cannot change after this!
drawnow()
pause(.05)
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]; %[left, right]
carYi = carY(:) + carWidth./[-2,2]; %[lower, upper]
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).
% Draw car at starting point & animate trajectory
carImg = imagesc(carXi(1,:), carYi(1,:), I, 'AlphaData', transparency);
for i = 1:size(carXi,1)
carImg.XData = carXi(i,:);
carImg.YData = carYi(i,:);
drawnow();
% pause(.1); % <--- slow down animation by increasing this value
end
Demo 2: rectangle
Similar to the first demo, this one uses a rectangle which simplifies the task and speeds up the animation.
% Define road and car size
roadWidth = 8;
carWidth = 2.8; % same units as road-width
carLenghtFactor = 1.7; % scaling factor
% Define Trajectory of the center of the car (sigmoid curve in this demo)
x = linspace(-7,7,500);
carY = (1./(1+exp(-x))*roadWidth - roadWidth/2)*.5; % assumes road is centered at y=0
carX = linspace(-150,1150,numel(x)); % car will start and end outside of the axes
% Plot road
fig = figure();
fig.Position(3:4) = [1180,420];
fig.Resize = 'off'; % disable fig resize since car size depends on axis size.
movegui(fig)
ax = axes(fig,'XLim',[-5, 1100], 'YLim', [-8 8], 'XTick', 0:200:1000, 'ytick', -8:8,'Units','pixels');
box(ax,'on')
hold(ax,'on')
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);
% Add trajectory path
traj = plot(carX, carY, '--', 'LineWidth', 3,'Color',[0.9375 0.5 0.5]); %lightcoral
% Compute car length based on specified width and aspect ratio
% xlim and ylim must be set prior to this. Axes & data aspect ratios cannot change after this!
drawnow()
pause(.05)
asScalingFactor = (ax.DataAspectRatio(1)/ax.DataAspectRatio(2)) / ...
(ax.PlotBoxAspectRatio(1)/ax.PlotBoxAspectRatio(2));
carLength = carWidth * carLenghtFactor * asScalingFactor;
% Compute the lower-left corner of the rectanlge at each point on the trajectory
carXi = carX(:) - carLength/2; %[left, right]
carYi = carY(:) - carWidth/2; %[lower, upper]
% Draw car at starting point & animate trajectory
carRect = rectangle(ax, 'Position', [carXi(1), carYi(1), carLength, carWidth],...
'LineWidth', 2, 'EdgeColor', 'b');
for i = 1:size(carXi,1)
carRect.Position(1:2) = [carXi(i),carYi(i)];
drawnow ;
% pause(.1); % <--- slow down animation
end
  3 commentaires
Adam Danz
Adam Danz le 28 Sep 2022
Demo #2 in my answer shows how to animate the position of a rectangle. The same logic can be used with a line object produced by h=plot(x,y,'o'). However, instead of update the rectangle position, you would update the XData and YData of the line object using set(h, 'XData', newx, 'YData', newy).
Thanos
Thanos le 24 Oct 2022
It worked! Thank you!

Connectez-vous pour commenter.

Plus de réponses (0)

Catégories

En savoir plus sur Animation dans Help Center et File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by