Projectile OpenSeesing

Growing up in the Pine State, you were either a fan of NASCAR or college basketball, and in some cases both. I leaned heavily toward the latter.

The hard dynamics underpins the physics of both sports–and most others. Centripetal forces act on race cars going around turns and projectile motion is a simplified description of a basketball shot.

In problem 12-95 from Hibbeler’s Engineering Mechanics: Dynamics, 14th edition, a jump shot is launched at 30 degrees from horizontal, 30 feet from the basket–from downtown, way beyond the arc. What initial velocity, v0, is required to make the shot? The basketball is released at 7 ft elevation and the hoop is at 10 ft elevation.

Instead of finding the solution with OpenSees, which would require some brute force goal seek, or solving the problem by hand, I looked in the back of the book. The required initial velocity is v0=36.7 ft/sec. This post shows how to simulate the basketball motion in OpenSees, along with an animation.

The model for this problem is defined in two dimensions with two DOFs per node. The basketball is the one and only node, to which an arbitrary non-zero mass is assigned. A downward force in a constant time series accounts for gravity.

The initial velocity is imposed via the setNodeVel command. Be sure to use the -commit option so that the analysis doesn’t try to find some other initial condition on the first step.

From there, the projectile motion is computed via a transient dynamic analysis, with no elements required.

import openseespy.opensees as ops

mass = 1.0
g = 32.2 # ft/sec^2
v0 = 36.7 # ft/sec
theta = 30*3.14159/180 # radians

ops.wipe()
ops.model('basic','-ndm',2,'-ndf',2)

ops.node(1,0,7) # Initial position x=0,y=7 ft
ops.mass(1,mass,mass)

ops.setNodeVel(1,1,v0*math.cos(theta),'-commit')
ops.setNodeVel(1,2,v0*math.sin(theta),'-commit')

ops.timeSeries('Constant',1)
ops.pattern('Plain',1,1)
ops.load(1,0,-mass*g)

ops.integrator('Newmark',0.5,0.25)
ops.analysis('Transient','-noWarnings')

Tmax = 0.944 # v0*cos(theta)/(30 ft)
dt = 0.001
Nsteps = int(Tmax/dt)
for i in range(Nsteps):
    ok = ops.analyze(1,dt)

Following this tutorial, an animation of the analysis is shown below. The silhouette jump shooter, from the Clipart Library, is superimposed on the matplotlib axes using this example.

Nothin’ but net! Try the analysis yourself. What initial velocity is required to make the basket if the shot angle is 40 degrees?


Hill to Laettner, perhaps the most memorable projectile in college basketball history!

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.