MATLAB Answers

billiard animation, set multiple rectangles, funny guy

7 views (last 30 days)
Ansgar Elles
Ansgar Elles on 20 Feb 2021
Answered: darova on 20 Feb 2021
Hi everyone!
Im calculating the movement of billiardballs on a table. The calculations work I think but im having problems with the animation. I cant get the programm to show the desired number of balls at the same time(/in the same frame). The set function always replaces the previously placed ball. Hold on doesnt work.
I preallocated the number of balls(/rectangles) with gobjects. Please help, Im at the end of my latin. Sorry my english is not the yellow from the egg.
global m d r endvelocity num_balls
m=0.17; d=0.15; r=0.04;%0.0285 %; %mass, friction, radius
tspan = 0:0.0025:10;
while_counter = 1; %while loop counter
% for_counter = 1;
stillrolling = 1; % while loop, entry value
endvelocity = 0.1; % end speed at which simulation stops
options = odeset('AbsTol',1e-10,'RelTol',1e-8,'Events', @event_collision_more_balls); %,'AbsTol',1e-10, 'RelTol',1e-8
% set parameters for balls
%known maximum speed of balls is up to 14 meters per second (in real billiard tournaments)
num_balls = 3;
num_variables = num_balls*4; %num_balls now actually refers to the number of kinematic variables
vals_blueball = [0.1 0 2 1]; %[sx vx sy vy]
vals_redball = [0.3 0 3 1];
vals_cyanball = [0.5 0 2 1];
vals_magentaball = [0.5 0 2 1];
vals_yellowball = [1 0 2 1];
vals_blackball = [1.2 0 2 1];
vals_whiteball = [1.4 0 2 1];
vals_balls = [vals_blueball,vals_redball,vals_cyanball,vals_magentaball,vals_yellowball,vals_blackball,vals_whiteball]; %[sx1 vx1 sy1 vy1 sx2 vx2 sy2 vy2]
vals_balls = vals_balls(1:num_variables); %pick the chosen number of values
figure('NumberTitle','Off','Name','elastic_collision');
axis([0 1.78 0 3.57]); axis equal; %Frage: Bringt hier "hold on" etwas?
title('Billiard table');
playingfield = rectangle('Position',[0 0 1.78 3.57],'FaceColor','g');
ballsack = gobjects(1,num_balls);
ballsack(:,:) = rectangle('Position',[-10 -10 2*r 2*r],'Curvature',[1,1],'FaceColor','r');
%redball = rectangle('Position',[-10 -10 2*r 2*r],'Curvature',[1,1],'FaceColor','r');
%up to 7 balls
% blueball = rectangle('Position',[-10 -10 2*r 2*r],'Curvature',[1,1],'FaceColor','b');
% redball = rectangle('Position',[-10 -10 2*r 2*r],'Curvature',[1,1],'FaceColor','r');
% cyanball = rectangle('Position',[-10 -10 2*r 2*r],'Curvature',[1,1],'FaceColor','c');
% magentaball = rectangle('Position',[-10 -10 2*r 2*r],'Curvature',[1,1],'FaceColor','m');
% yellowball = rectangle('Position',[-10 -10 2*r 2*r],'Curvature',[1,1],'FaceColor','y');
% blackball = rectangle('Position',[-10 -10 2*r 2*r],'Curvature',[1,1],'FaceColor','k');
% whiteball = rectangle('Position',[-10 -10 2*r 2*r],'Curvature',[1,1],'FaceColor','w');
%initiate place holder/adress
t_total = zeros(1,1);
y_total = zeros(1,num_variables);
%% While loop
while stillrolling == 1
[t,y,te,ye,ie] = ode45(@kinematics_more_balls,tspan,vals_balls,options);
if ismember(ie,1:num_balls) %left border
vals_balls = y(end,:);
vector = 2:4:num_variables;
idx = vector(ie);
vals_balls(1,idx) = -vals_balls(1,idx);
elseif ismember(ie,num_balls+1:num_balls*2) %right border
ie = ie - num_balls;
vals_balls = y(end,:);
vector = 2:4:num_variables;
idx = vector(ie);
vals_balls(1,idx) = -vals_balls(1,idx);
elseif ismember(ie,num_balls*2+1:num_balls*3) %top border
ie = ie - num_balls*2;
vector = 4:4:num_variables;
idx = vector(ie);
vals_balls(1,idx) = -vals_balls(1,idx);
elseif ismember(ie,num_balls*3+1:num_balls*4) %bottom border
ie = ie - num_balls*3;
vector = 4:4:num_variables;
idx = vector(ie);
vals_balls(1,idx) = -vals_balls(1,idx);
elseif ie == num_balls*4+num_balls*(num_balls-1)/2+1
disp('Die Kugeln rollen nicht mehr.')
stillrolling = 0;
end
t_total = [t_total; t];
y_total = [y_total; y];
while_counter = while_counter+1;
end
hold on
for k1 = 2:length(t_total)
prop_name = {'Position'};
prop_value = {'[y_total(k1,1:4:end)-r; y_total(k1,3:4:end)-r; ones(1,num_balls)*2*r; ones(1,num_balls)*2*r]'};
set(ballsack,prop_name,prop_value)
drawnow
end
function kinematics = kinematics_more_balls(t,y)
global m d num_balls
kinematics = ones(4*num_balls,1);
%kinematics = [y(2), -d/m*y(2), y(4), -d/m*y(4), y(6), -d/m*y(6), y(8), -d/m*y(8)]';
%connection_monitor = sqrt((y(5)-y(1))^2 + ((y(7)-y(3))^2)) - 2*r
%[sx1 vx1 sy1 vy1 sx2 vx2 sy2 vy2 ...]
kinematics(1:4:end) = y(2:4:end);
kinematics(2:4:end) = -d/m*y(2:4:end);
kinematics(3:4:end) = y(4:4:end);
kinematics(4:4:end) = -d/m*y(4:4:end);
end
function [value,isterminal,direction] = event_collision_more_balls(t,y)
%event-Funktion beendet Integration sobald einer der Werte in "value" null
%wird (entspricht Beruehrung der Bande, siehe "isterminal" ==1 d.h. Terminierung auf "true").
global r endvelocity
%with n being the number of balls -1
value = [-y(1:4:end)'+r, y(1:4:end)'+r-1.78, y(3:4:end)'+r-3.57, -y(3:4:end)'+r, -pdist([y(1:4:end),y(3:4:end)]) + 2*r, -max(sqrt((y(2:4:end)).^2 + (y(4:4:end)).^2)) + endvelocity]; %wird negativ, wird negativ, wird positiv, wird positiv (bei verlassen des Spielfeldes)
isterminal = ones(1,length(value)); %2 balls = 10 values
direction = ones(1,length(value)); %"+1" = triggered when event-function is increasing, "-1" when decreasing, "0" = consider both
% connections = pdist([y(1:4:end),y(3:4:end)]);
% %connections is a n*(n+1)/2 dimensional row-vector
end

Answers (1)

darova
darova on 20 Feb 2021
Here is an example
clc,clear
g = 9.8;
n = 3;
x0 = rand(n,1);
y0 = rand(n,1);
vx = rand(n,1);
vy = rand(n,1);
dt = 0.03;
cla
plot([0 1 1 0 0],[0 0 1 1 0])
hold on
for i = 1:100
x1 = x0 + vx*dt;
y1 = y0 + vy*dt;
sx = 0<x1 & x1<1; % inside the rectangle?
sy = 0<y1 & y1<1;
y1 = y1 + (y1<0)*dt.*vy/5; % correction if bottom border
vx = sign(sx-0.5).*vx;
vy = sign(sy-0.5).*vy - g*dt;
plot([x0 x1]',[y0 y1]','.-r')
x0 = x1;
y0 = y1;
pause(0.1)
end
hold off

Community Treasure Hunt

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

Start Hunting!

Translated by