I needed to calculate some free fall timings recently and while I could have used a calculator I decided I’d write a package to encapsulate the math for more convenient reuse if I ever needed to do so again. Once I had a couple calculations I expanded it to add more. Using the package I can determine distance fallen after a given number of seconds. The final velocity after falling for some amount of time, or if given a distance fallen instead, the velocity after falling that far. I can also reverse the calculation determine the time it takes to fall a given distance.
All of the calculations can be made with or without air resistance. In the process of coding those I added functions terminal_velocity and a function to calculate air resistance coefficient from the air density, cross section area and drag coefficient.
I also found that among all of the mathematical functions available in Oracle SQL, there is no ACOSH (inverse hyperbolic cosine) so I had to create one one of those too for calculating falling time over a known distance with air resistance.
I’ll concede it’s not likely to be a package I use often but it was an interesting exercise to dig into as some of the formulas were not ones I had previously known.
CREATE OR REPLACE PACKAGE free_fall IS -- .///. -- (0 o) ---------------0000--(_)--0000--------------- -- -- Sean D. Stuber -- sean.stuber@gmail.com -- -- oooO Oooo --------------( )-----( )--------------- -- \ ( ) / -- \_) (_/ -- Default coefficient of air resistance 0.24kg/m -- corrresponds to typical skydiver c_default_air_resistance CONSTANT NUMBER := 0.24; -- Default acceleration due to gravity on Earth in m/(s^2) c_gravity_acceleration NUMBER := 9.80665; -- The functions below accept an air resistance coefficient -- If it is not known, it can be calculated from: -- air density (kg per cubic meter) -- cross-section area of the object (square meters) -- drag coefficient of the object's shape (dimensionless) FUNCTION air_resistance(p_density IN NUMBER, p_area IN NUMBER, p_drag IN NUMBER) RETURN NUMBER; -- Given time (and optionally air resistance coefficient and mass) -- calculate the distance an object will fall -- With a NULL coefficient then calculation assumes no air resistance -- air resistance coefficient, if used, should be in kg/m -- mass, if used, should be in kg FUNCTION distance(p_seconds IN NUMBER, p_coeff IN NUMBER DEFAULT NULL, p_mass IN NUMBER DEFAULT NULL) RETURN NUMBER DETERMINISTIC; -- Given time (and optionally air resistance coefficient and mass) -- calculate the final velocity of an object -- With a NULL coefficient then calculation assumes no air resistance -- air resistance coefficient, if used, should be in kg/m -- mass, if used, should be in kg FUNCTION velocity_t(p_seconds IN NUMBER, p_coeff IN NUMBER DEFAULT NULL, p_mass IN NUMBER DEFAULT NULL) RETURN NUMBER DETERMINISTIC; -- Given distance (and optionally air resistance coefficient and mass) -- calculate the final velocity of an object -- With a NULL coefficient then calculation assumes no air resistance -- air resistance coefficient, if used, should be in kg/m -- mass, if used, should be in kg FUNCTION velocity_d(p_distance IN NUMBER, p_coeff IN NUMBER DEFAULT NULL, p_mass IN NUMBER DEFAULT NULL) RETURN NUMBER DETERMINISTIC; -- Given air resistance coefficient and mass -- calculate the terminal velocity of an object -- air resistance coefficient should be in kg/m -- mass should be in kg -- The return result will be in m/s FUNCTION terminal_velocity(p_coeff IN NUMBER DEFAULT NULL, p_mass IN NUMBER DEFAULT NULL) RETURN NUMBER DETERMINISTIC; -- Given distance (and optionally air resistance coefficient and mass) -- calculate the time required for an object to fall that distance -- With a NULL coefficient then calculation assumes no air resistance -- air resistance coefficient, if used, should be in kg/m -- mass, if used, should be in kg FUNCTION time(p_distance IN NUMBER, p_coeff IN NUMBER DEFAULT NULL, p_mass IN NUMBER DEFAULT NULL) RETURN NUMBER DETERMINISTIC; END;
CREATE OR REPLACE PACKAGE BODY free_fall IS -- .///. -- (0 o) ---------------0000--(_)--0000--------------- -- -- Sean D. Stuber -- sean.stuber@gmail.com -- -- oooO Oooo --------------( )-----( )--------------- -- \ ( ) / -- \_) (_/ -- The functions below accept an air resistance coefficient -- If it is not known, it can be calculated from: -- air density (kg per cubic meter) -- cross-section area of the object (square meters) -- drag coefficient of the object's shape (dimensionless) FUNCTION air_resistance(p_density IN NUMBER, p_area IN NUMBER, p_drag IN NUMBER) RETURN NUMBER IS BEGIN RETURN p_density * p_area * p_drag / 2; END air_resistance; -- Given time (and optionally air resistance coefficient and mass) -- calculate the distance an object will fall -- With a NULL coefficient then calculation assumes no air resistance -- air resistance coefficient, if used, should be in kg/m -- mass, if used, should be in kg FUNCTION distance(p_seconds IN NUMBER, p_coeff IN NUMBER DEFAULT NULL, p_mass IN NUMBER DEFAULT NULL) RETURN NUMBER DETERMINISTIC IS BEGIN RETURN CASE WHEN p_coeff IS NOT NULL THEN p_mass / p_coeff * LN( COSH( p_seconds / SQRT( p_mass / (c_gravity_acceleration * p_coeff)))) WHEN p_coeff IS NULL THEN c_gravity_acceleration * p_seconds * p_seconds / 2 END; END distance; -- Given time (and optionally air resistance coefficient and mass) -- calculate the final velocity of an object -- With a NULL coefficient then calculation assumes no air resistance -- air resistance coefficient, if used, should be in kg/m -- mass, if used, should be in kg FUNCTION velocity_t(p_seconds IN NUMBER, p_coeff IN NUMBER DEFAULT NULL, p_mass IN NUMBER DEFAULT NULL) RETURN NUMBER DETERMINISTIC IS BEGIN RETURN CASE WHEN p_coeff IS NOT NULL THEN SQRT(p_mass * c_gravity_acceleration / p_coeff) * TANH( p_seconds / SQRT( p_mass / (c_gravity_acceleration * p_coeff))) WHEN p_coeff IS NULL THEN c_gravity_acceleration * p_seconds END; END velocity_t; -- Given distance (and optionally air resistance coefficient and mass) -- calculate the final velocity of an object -- With a NULL coefficient then calculation assumes no air resistance -- air resistance coefficient, if used, should be in kg/m -- mass, if used, should be in kg FUNCTION velocity_d(p_distance IN NUMBER, p_coeff IN NUMBER DEFAULT NULL, p_mass IN NUMBER DEFAULT NULL) RETURN NUMBER DETERMINISTIC IS v_seconds number := free_fall.time(p_distance,p_coeff,p_mass); BEGIN RETURN CASE WHEN p_coeff IS NOT NULL THEN SQRT(p_mass * c_gravity_acceleration / p_coeff) * TANH( v_seconds / SQRT( p_mass / (c_gravity_acceleration * p_coeff))) WHEN p_coeff IS NULL THEN sqrt(2 * c_gravity_acceleration * p_distance) END; END velocity_d; -- Given air resistance coefficient and mass -- calculate the terminal velocity of an object -- air resistance coefficient should be in kg/m -- mass should be in kg -- The return result will be in m/s FUNCTION terminal_velocity(p_coeff IN NUMBER DEFAULT NULL, p_mass IN NUMBER DEFAULT NULL) RETURN NUMBER DETERMINISTIC IS BEGIN RETURN SQRT(p_mass * c_gravity_acceleration / p_coeff); END terminal_velocity; FUNCTION acosh(x IN NUMBER) RETURN NUMBER IS BEGIN RETURN LN(x + SQRT(x * x - 1)); END acosh; -- Given distance (and optionally air resistance coefficient and mass) -- calculate the number of seconds required for an object to fall that distance -- With a NULL coefficient then calculation assumes no air resistance -- air resistance coefficient, if used, should be in kg/m -- mass, if used, should be in kg FUNCTION time(p_distance IN NUMBER, p_coeff IN NUMBER DEFAULT NULL, p_mass IN NUMBER DEFAULT NULL) RETURN NUMBER DETERMINISTIC IS BEGIN RETURN CASE WHEN p_coeff IS NOT NULL THEN SQRT(p_mass / (c_gravity_acceleration * p_coeff)) * acosh(EXP(p_distance * p_coeff / p_mass)) WHEN p_coeff IS NULL THEN SQRT(2 * p_distance / c_gravity_acceleration) END; END time; END;
If you ever find yourself needing to do some of this math, hopefully this package will be helpful. If not, hopefully you find it as interesting to read through as I did in writing it. Questions and comments, as always, are welcome.