# How can I plot a reflection angle of a projectile in a kinematics model? Overlay projectile motion plots?

7 views (last 30 days)
Chase Martin on 21 Apr 2024
Edited: Alan Stevens on 30 Apr 2024
For a research project my group and I are analyzing the biomechanics of jumps shots for basketball players. We are trying to find trends in data and see if we can draw conclusions based on certain biomechanical factors like arm and length length, height, release angle of a shot, elbow angle, forearm angle, knee angle, and other variables along those lines. We have been developing a kinematics code to supplement the image processing we have already compeleted; the code takes the release height, release angle, and initial velocity of the ball from a users shot motion and uses this information to plot the projectile motion of the ball.
In theory, if the ball goes through the hoop, it will travel back to the ground. However we have been running into some trouble plotting misses and reflection angles. If the ball were to strike any part of the rim or backboard, instead of reflecting the angle of the projectile and plotting it at the point of contact, it plots to reflection of the angle back in the release point. I've attached images below depecting this, as well as the section of the code for plotting the projectile motion. I have also attached our entire code, but it would be too long to put in a discussion board question.
One last question, if we were to fix the projectile motion part of the project, how would you then go about overlaying multiple shots onto the same graph to show a range of data based on different release angles, release points, and ball velocities depending on which value the user chooses to adjust.
Images:
Projectile motion plotting section of Code:
%Kinematics Model
% Constants
g = 9.81; % acceleration due to gravity (m/s^2)
% Convert release angle to radians
% Calculate horizontal and vertical components of the initial velocity
vx0 = imperialBallVelocity * cos(theta);
vy0 = imperialBallVelocity * sin(theta);
% Calculate time of flight
t_flight = (vy0 + sqrt(vy0^2 + 2 * g * release_height)) / g;
% Calculate range of the projectile
range = vx0 * t_flight;
% Generate time points for plotting
t = linspace(0, t_flight, 100);
% Calculate horizontal and vertical positions at each time point
x = vx0 * t;
y = vy0 * t - 0.5 * g * t.^2 + release_height;
% Constants
backboard_x = 189; % x-coordinate of the backboard
backboard_y1 = 106; % Starting y-coordinate of the backboard
backboard_y2 = 154; % Ending y-coordinate of the backboard
% Flag variable to indicate if intersection with the backboard is found
intersection_found = false;
% Check for intersection with the y-axis
y_axis_intersection_idx = find(x >= backboard_x & y <= 0, 1);
% Check for intersection with the backboard
backboard_intersection_idx = find(x >= backboard_x & y >= backboard_y1 & y <= backboard_y2, 1);
if ~isempty(backboard_intersection_idx)
% Flag indicating intersection with the backboard is found
intersection_found = true;
% Reverse the angle of projection for the remaining trajectory
theta(backboard_intersection_idx:end) = -theta(backboard_intersection_idx:end);
% Convert the angle back to radians
% Recalculate horizontal and vertical components of the initial velocity
% Recalculate time of flight considering the reversed angle
t_remaining = linspace(0, t_flight - t(backboard_intersection_idx), length(t) - backboard_intersection_idx + 1);
% Recalculate horizontal and vertical positions at each time point
x(backboard_intersection_idx:end) = vx0 * t_remaining;
y(backboard_intersection_idx:end) = vy0 * t_remaining - 0.5 * g * t_remaining.^2 + release_height;
end
% Plot the trajectory of the projectile
figure;
plot(x, y, 'b-', 'LineWidth', 2);
hold on;
plot(x(1), y(1), 'ro', 'MarkerSize', 8); % Initial point
% Check if intersection with the backboard is found
if intersection_found
% Plot the corrected trajectory after the intersection
plot(x(backboard_intersection_idx:end), y(backboard_intersection_idx:end), 'm-', 'LineWidth', 2);
% Plot the final point of the trajectory before bouncing off the backboard
plot(x(backboard_intersection_idx), y(backboard_intersection_idx), 'go', 'MarkerSize', 8);
% Adjust the trajectory after bouncing off the backboard
x = x(1:backboard_intersection_idx);
y = y(1:backboard_intersection_idx);
else
% Plot the final point if there's no intersection with the backboard
plot(x(end), y(end), 'go', 'MarkerSize', 8); % Final point
end
% Plot the rim and backboard
rim_x = [171, 189];
rim_y = [120, 120];
backboard_x = [189, 189];
backboard_y = [106, 154];
plot(rim_x, rim_y, 'r-', 'LineWidth', 3); % Rim
plot(backboard_x, backboard_y, 'r-', 'LineWidth', 3); % Backboard
xlabel('Horizontal Distance (in)');
ylabel('Vertical Distance (in)');
title('Projectile Motion');
grid on;
% Add labels for release velocity, angle, and height
annotation('textbox', [0.2, 0.7, 0.2, 0.1], 'String', sprintf('Release Velocity: %.2f in/s\nRelease Angle: %.2f degrees\nRelease Height: %.2f inches', imperialBallVelocity, abs(release_angle), release_height), 'FitBoxToText', 'on');
legend('Projectile Trajectory', 'Initial Point', 'Final Point', 'Rim and Backboard', 'Location', 'best');

Alan Stevens on 22 Apr 2024
Edited: Alan Stevens on 22 Apr 2024
Surely you only need to reverse the x-velocity?
imperialBallVelocity = 52.20;
release_angle = 42;
release_height = 64.2;
%Kinematics Model
% Constants
g = 9.81; % acceleration due to gravity (m/s^2)
% Convert release angle to radians
% Calculate horizontal and vertical components of the initial velocity
vx0 = imperialBallVelocity * cos(theta);
vy0 = imperialBallVelocity * sin(theta);
% Calculate time of flight
t_flight = (vy0 + sqrt(vy0^2 + 2 * g * release_height)) / g;
% Calculate range of the projectile
range = vx0 * t_flight;
% Generate time points for plotting
t = linspace(0, t_flight, 100);
% Calculate horizontal and vertical positions at each time point
x = vx0 * t;
y = vy0 * t - 0.5 * g * t.^2 + release_height;
% Constants
backboard_x = 189; % x-coordinate of the backboard
backboard_y1 = 106; % Starting y-coordinate of the backboard
backboard_y2 = 154; % Ending y-coordinate of the backboard
% Flag variable to indicate if intersection with the backboard is found
intersection_found = false;
% Check for intersection with the y-axis
y_axis_intersection_idx = find(x >= backboard_x & y <= 0, 1);
% Check for intersection with the backboard
backboard_intersection_idx = find(x >= backboard_x & y >= backboard_y1 & y <= backboard_y2, 1);
if ~isempty(backboard_intersection_idx)
% Flag indicating intersection with the backboard is found
intersection_found = true;
% Recalculate time of flight considering the reversed angle
t_remaining = linspace(0, t_flight - t(backboard_intersection_idx), length(t) - backboard_intersection_idx + 1);
% Recalculate horizontal and vertical positions at each time point
x(backboard_intersection_idx:end) = backboard_x-vx0 * t_remaining;
% y(backboard_intersection_idx:end) = vy0 * t_remaining - 0.5 * g * t_remaining.^2 + release_height;
end
% Plot the trajectory of the projectile
figure;
plot(x(1), y(1), 'ro', 'MarkerSize', 8); % Initial point
hold on;
% Check if intersection with the backboard is found
if intersection_found
% Plot the corrected trajectory after the intersection
plot(x(1:backboard_intersection_idx), y(1:backboard_intersection_idx), 'b-', 'LineWidth', 2);
plot(x(backboard_intersection_idx:end),y(backboard_intersection_idx:end), 'm-', 'LineWidth', 2);
% Plot the final point of the trajectory before bouncing off the backboard
% plot(x(backboard_intersection_idx), y(backboard_intersection_idx), 'go', 'MarkerSize', 8);
% Adjust the trajectory after bouncing off the backboard
% x = x(1:backboard_intersection_idx);
% y = y(1:backboard_intersection_idx);
else
% Plot the final point if there's no intersection with the backboard
% plot(x(end), y(end), 'go', 'MarkerSize', 8); % Final point
end
plot(x(end), y(end), 'go', 'MarkerSize', 8); % Final point
% Plot the rim and backboard
rim_x = [171, 189];
rim_y = [120, 120];
backboard_x = [189, 189];
backboard_y = [106, 154];
plot(rim_x, rim_y, 'r-', 'LineWidth', 3); % Rim
plot(backboard_x, backboard_y, 'r-', 'LineWidth', 3); % Backboard
xlabel('Horizontal Distance (in)');
ylabel('Vertical Distance (in)');
title('Projectile Motion');
grid on;
% Add labels for release velocity, angle, and height
annotation('textbox', [0.2, 0.7, 0.2, 0.1], 'String', sprintf('Release Velocity: %.2f in/s\nRelease Angle: %.2f degrees\nRelease Height: %.2f inches', imperialBallVelocity, abs(release_angle), release_height), 'FitBoxToText', 'on');
legend('Initial Point', 'Projectile Trajectory', 'Rebound trajectory','Final point', 'Rim and Backboard', 'Location', 'best');
Chase Martin on 28 Apr 2024
This helped us to correct the original error, thank you. Would you know how to overlay multiple shots onto the same plot to show a range of data based on different release angles, release points, and ball velocities depending on which values the user chooses to adjust?
Alan Stevens on 30 Apr 2024
Edited: Alan Stevens on 30 Apr 2024
This should give you some idea of how to go about it. I'll leave you to add any "bells and whistles"!
% Constants
g = 9.81; % acceleration due to gravity (m/s^2)
backboard_x = 189; % x-coordinate of the backboard
backboard_y1 = 106; % Starting y-coordinate of the backboard
backboard_y2 = 154; % Ending y-coordinate of the backboard
theta = deg2rad(42); % release angle
release_height = 64.2;
% Example assuming two initial velocities
imperialBallVelocity = [52.20 51 50];
colr = ['r', 'b', 'k'];
n = numel(imperialBallVelocity);
% Calculate horizontal and vertical components of the initial velocity
vx0 = imperialBallVelocity * cos(theta);
vy0 = imperialBallVelocity * sin(theta);
% Calculate times of flight
t_flight = (vy0 + sqrt(vy0.^2 + 2 * g * release_height)) / g;
% Calculate ranges of the projectile
range = vx0 .* t_flight;
% Now there are n values of vx0, vy0, t_flight and range
figure;
hold on;
% Generate time points for plotting and
% horizontal and vertical positions at each time point
for i = 1:n
t = linspace(0, t_flight(i), 100);
x = vx0(i) * t;
y = vy0(i) * t - 0.5 * g * t.^2 + release_height;
% Check for intersection with the backboard
backboard_intersection_idx = find(x >= backboard_x & y >= backboard_y1 & y <= backboard_y2);
if ~isempty(backboard_intersection_idx)
x(backboard_intersection_idx:end) = 2*backboard_x-x(backboard_intersection_idx:end);
end
plot(x, y, [colr(i) '-'], 'LineWidth', 1);
end
Warning: Colon operands must be real scalars. This warning will become an error in a future release.
Warning: Colon operands must be real scalars. This warning will become an error in a future release.
Warning: Colon operands must be real scalars. This warning will become an error in a future release.
Warning: Colon operands must be real scalars. This warning will become an error in a future release.
% Plot the rim and backboard
rim_x = [171, 189];
rim_y = [120, 120];
backboard_x = [189, 189];
backboard_y = [106, 154];
plot(rim_x, rim_y, 'r-', 'LineWidth', 3); % Rim
plot(backboard_x, backboard_y, 'r-', 'LineWidth', 3); % Backboard
xlabel('Horizontal Distance (in)');
ylabel('Vertical Distance (in)');
title('Projectile Motion');
grid on;
legend(num2str(imperialBallVelocity(1)), num2str(imperialBallVelocity(2)), num2str(imperialBallVelocity(3)), 'Location', 'Best');