Implementing a Kinematic Flight Modeler to a Prototype Ball Shooter

Part 2 of 3: Optimizing Trajectories and Comparing Actual Data

Sajiv Shah
Towards Data Science

--

Link to part 1:

Long Shot Slow-Motion, Gif by Author

After creating a working algorithm to simulate our trajectories, we need to determine what parameter we should optimize the trajectory for. Because many different combinations of velocity and angle result in a “score” from a singular distance, we have many options. Using that data, we then need to test our actual prototype and analyze the errors and inaccuracies.

Trajectory Optimization

A. Power

When determining what factors to optimize our trajectories for, an obvious one that comes to mind is power. Our robots run off a lead-acid battery, and after about 3 minutes of running the robot at an average duty (basic cruising and running of subsystems such as the shooter), the battery voltage significantly drops and the motors began to underperform. To minimize the power we draw from the battery to ensure it can power the shooter and other subsystems throughout the entire match, we should optimize the trajectory from each distance for the power required from the motors.

The motor power draw is directly related to the rpm and torque of the motor[1]. In our case, the torque is also related to the rpm because a certain amount of torque is required to accelerate the ball to the max velocity, which is a function of the set rpm of the motor[2]. Therefore, we know that as the set motor rpm decreases, so does the power draw. This means we must find the trajectory that has the slowest ball velocity.

In our script, we base the calculation of the trajectory on the motor speed itself, meaning the implementation of this optimization is very simple. The iteration of the ball path at a given distance starts at 30 motor rotations/second and works its way up to 600 in increments of 1.

def iterate():
global run
for w_r in range(30,600): #6380 rpm in rps
for theta in range(15,75):
if(run):
trajectory(w_r, theta*math.pi/180)

When the trajectory() function is called, it calculates the ball velocity and spin based on the motor rps value, and then calls the runPath() function which uses the spin and velocity variables from the trajectory() function to plot the position of the ball at many time intervals in order to generate a graph of the ball path. In this function, we test if the ball goes through the target by checking if the x-position, or the horizontal distance, has traveled the length between the shooter and the target, and by checking if the y-position is close to the height of the shooter.

if(((x_dist > distance - .01) and (x_dist < distance + .01)) and ((y_dist > height - .01) and (y_dist < height + .01))):
through = False
global w_min
plt.plot(x,y)
omega_array.append(round(w*60/(2*math.pi),1))
theta_array.append(round(theta_i*180/math.pi,1))
print ("w: " + str(w*60/(2*math.pi)) + " a: " + str(theta_i*180/math.pi))
global run
run = False

In the script adjusted for the power-optimized scenario, we set the run variable to false as soon as the ball first reaches the target, which stops the iterate() function from running until it is called again to test a path from a new distance. We used a simple for loop to run many paths, plot them, and output the motor speed and angle for each path.

for i in range(0,max_trials):
#trial_array.append(i+1)
distance = 2.3 + ((7-2.3) / max_trials)*i
#distance_array.append(distance)
print(str(i+1) + " , " + str(distance))
iterate()

plt.savefig("power_optimized" + str(max_trials) + "_trials.png")
plt.show()

We generated the following plot and table using this algorithm.

Images by Author

B. Peak-Based

As mentioned in part 1, we also wanted to configure our simulation to output trajectories in which the ball would pass through the scoring hole at the peak of its trajectory. There are three main benefits to scoring the ball at the peak of its trajectory

  1. It would be easy to visualize as we can see where in the path the ball actually went through the scoring hole using a slow-motion camera
  2. The ball would be traveling relatively flat, so small errors would have a smaller impact on scoring
  3. The ball would be at its minimum velocity (based on the energy equation below) because it would have the maximum possible gravitational potential energy[3], and therefore have a smaller chance of hitting the back wall of the scoring target and bouncing out instead of falling down into the scoring gates.

To adjust our algorithm to record and output paths at which the ball scored at the peak of its trajectory, we could do one of many things.

The first would be to check if the angle of the velocities was 0, as the ball would theoretically be traveling completely flat because it would have no y-velocity and only an x-velocity.

Image by Author

Based on the same logic, we could also check if the velocity in the y-direction was near 0. Not only that, but we could also streamline our algorithm to end the calculation of that path if the y-velocity dropped below 0, since that would mean it is traveling downward.

We implemented this into our runPath() function:

if(v_y < 0.1 and v_y > -0.1):
if(((x_dist > distance - .01) and (x_dist < distance + .01))
and ((y_dist > height - .015) and (y_dist < height + .015))):
through = False
global w_min
plt.plot(x,y)
omega_array.append(round(w*60/(2*math.pi),2))
theta_array.append(round(theta_i*180/math.pi,2))
print ("w: " + str(w*60/(2*math.pi)) + " a: " + str(theta_i*180/math.pi))
global run
run = False

if(v_y < -0.15):
through = False

The “through” variable must be held true for the function to continue to calculate the position of the ball along the path and plot it, so we set that to false once the velocity drops below 0.15 m/s.

Running this algorithm generated the following plot and table:

Images by Author

Prototype Shooter Data

Testing Peak-Based Trajectories, Gif by Author

To test our trajectories, we designed a prototype that would allow us to test our shooting, and change multiple parameters such as ball compression and the angle of the shooter, as well as the speed of the flywheels.

CAD Model of Prototype, Image by Author

Using the peak-based trajectory parameters, we aligned the shooter at different distances, and set the motor-free speed and the angle to the values generated by the simulator. We did our best to ensure the ball was following this path and did some slight tuning to ensure the motor held the free speed we aimed to set them at.

Because of the electronics and software limitations, as well as the fact that it is not possible to set the flywheel speed to a certain amount for the entire shot, it was difficult to measure the accuracy of the trajectory simulator. Additionally, we found many errors in the calculation of the wheel speed.

In part 3, we will analyze the effects of compression and inertia on the trajectory and attempt to accommodate for them to tune our algorithm.

References

[1] What is the Difference Between Speed Versus Torque?. (2021). Retrieved 8 March 2021, from https://www.powerelectric.com/motor-resources/motors101/speed-vs-torque#:~:text=Power%3A%20The%20m

[2] The Relationship Between RPM & Torque | Kurz Industrial Solutions. (2019). Retrieved 8 March 2021, from https://kurz.com/understanding-relationship-between-rpm-torque/

[3] “ Potential And Kinetic Energy “. 2021. Zebu.Uoregon.Edu. http://zebu.uoregon.edu/1999/ph161/l5

Acknowledgments

The students of MSET 649 would like to thank all our donors, adult mentors, student mentors, parent volunteers, and especially our sponsors for allowing us to explore the STEM field and design robots, even in the toughest of times.

--

--