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.