Ordinate 2D Marketplace Community Open the studio

Marketplace › From Ordinate 2D

Measure g with pendulums (a least-squares fit)

Script by Ordinate 2D ✓ · Oscillations and waves

Six pendulums from 0.25 to 2 m are timed; a straight-line fit of T² against L gives g = 4π²/slope.

Use in Ordinate 2DOpens in the Script tab: it runs when you press Run. Free, no account needed.
"""Measure g with pendulums: time six pendulums of different lengths and fit T² = (4π²/g) L.

Six pendulums hang side by side, from 0.25 m to 2 m, each let go from 5°. The script times five full swings of each
(upward crossings of the vertical), records L, T and T² in the Script sheet, and fits a straight line through the origin
by least squares: slope = Σ L T² / Σ L², so g = 4π² / slope. Chart T² against L in the Table tab: a straight line.

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

LENGTHS = [0.25, 0.5, 0.75, 1.0, 1.5, 2.0]   # m
SWINGS = 5                                   # full swings timed per pendulum
TOP, ANGLE = 2.6, math.radians(5)

s.clear()
s.gravity = (0, -9.81)
s.air_density = 0
pendulums = []
for i, L in enumerate(LENGTHS):
    x0 = (i - 2.5) * 0.7
    anchor = s.box(x0, TOP, 0.2, 0.06, static=True, name=f"Anchor {L} m", color="#8b939b")
    bob = s.circle(x0 + L * math.sin(ANGLE), TOP - L * math.cos(ANGLE), 0.05, mass=0.5, name=f"Bob {L} m",
                   color="#e5484d", collide=False, restitution=0)
    s.rod(anchor, bob, at_a=(x0, TOP), at_b=bob.position)
    pendulums.append({"L": L, "x0": x0, "bob": bob, "last_x": bob.x - x0, "first": None, "count": 0, "done": False})


@s.on_step
def watch(t, dt):
    for p in pendulums:
        if p["done"]:
            continue
        x = p["bob"].x - p["x0"]
        if p["last_x"] < 0 <= x:                          # an upward crossing of the vertical: one full swing since the last
            if p["first"] is None:
                p["first"] = t
            else:
                p["count"] += 1
                if p["count"] == SWINGS:
                    T = (t - p["first"]) / SWINGS
                    s.record(L=p["L"], T=T, T2=T * T)
                    print(f"L = {p['L']:.2f} m: T = {T:.4f} s")
                    p["done"] = True
        p["last_x"] = x
    if all(p["done"] for p in pendulums):
        rows = s.rows()
        slope = sum(r["L"] * r["T2"] for r in rows) / sum(r["L"] ** 2 for r in rows)
        g = 4 * math.pi ** 2 / slope
        print(f"fit T² = {slope:.4f} · L  →  g = 4π²/slope = {g:.3f} m/s² (set: {-s.gravity[1]:.3f})")
        s.stop()


s.run(30)

table rod experiment curve fit