Ordinate 2D Marketplace Community Open the studio

Marketplace › From Ordinate 2D

Pendulum period against amplitude

Script by Ordinate 2D ✓ · Oscillations and waves

Release a pendulum from 5° to 150°: the period against 2π√(L/g) and the exact value.

Use in Ordinate 2DOpens in the Script tab: it runs when you press Run. Free, no account needed.
"""Pendulum period against amplitude: T = 2π√(L/g) only holds for small swings.

A 1 m pendulum is released from rest at one angle after another; the script times a full swing (two crossings of the
vertical in the same direction) and records it with the small-angle value and the exact one, T = T₀ / AGM(1, cos(θ₀/2)) (AGM: the arithmetic-geometric mean).

Runs in the studio (Script tab → Run) and locally:  python3 pendulum_period.py
"""
import math
import studio as s

L, G = 1.0, 9.81
ANGLES = [5, 20, 40, 60, 90, 120, 150]      # release angles, degrees

s.clear()
s.gravity = (0, -G)
anchor = s.box(0, 2.0, 0.3, 0.1, static=True, name="Anchor", color="#8b939b")
bob = s.circle(0, 2.0 - L, 0.08, mass=1, name="Bob", color="#e5484d", collide=False, restitution=0)
s.rod(anchor, bob, at_a=(0, 2.0), at_b=(0, 2.0 - L))
trial, last_cross, last_x = 0, None, 0.0


def agm(a, b):
    for _ in range(12):
        a, b = (a + b) / 2, math.sqrt(a * b)
    return a


def release(deg):
    global last_x, last_cross
    a = math.radians(deg)
    bob.position = (L * math.sin(a), 2.0 - L * math.cos(a))
    bob.velocity = (0, 0)
    last_x, last_cross = L * math.sin(a), None


@s.on_start
def start():
    global trial
    trial = 0
    release(ANGLES[0])


@s.on_step
def watch(t, dt):
    global trial, last_cross, last_x
    x = bob.x
    if last_x < 0 <= x:                                  # upward crossing of the vertical
        if last_cross is None:
            last_cross = t
        else:
            period = t - last_cross
            t0 = 2 * math.pi * math.sqrt(L / G)
            exact = t0 / agm(1, math.cos(math.radians(ANGLES[trial]) / 2))
            s.record(amplitude=ANGLES[trial], period=period, small_angle=t0, exact=exact)
            print(f"{ANGLES[trial]:>4}°: T = {period:.4f} s, small-angle {t0:.4f} s, exact {exact:.4f} s")
            trial += 1
            if trial >= len(ANGLES):
                s.stop()
                return
            release(ANGLES[trial])
            return
    last_x = x


s.run(40)

table rod experiment