7. Curvature and the TNB frame

📖 Reading · 11 min
💡 Every code box below is live — edit it and hit Run.

§9.5 stripped a curve's parameterization down to pure arc length, removing every trace of "how fast." What's left, after speed is factored out entirely, is the curve's shape — and this closing lesson of the module measures that shape directly: how sharply the curve bends, and a three-vector frame that rides along it, tracking its orientation at every point the way a coordinate axis would if it were bolted to a moving car.

The unit tangent vector

\vec T(t)=\frac{\vec r'(t)}{|\vec r'(t)|}

— the velocity direction, stripped of speed (§9.0's unit-vector construction, applied to velocity). \vec T always has magnitude 1, and it points in the exact direction the curve is currently heading.

Curvature

Curvature measures how fast \vec T itself turns, per unit of arc length traveled — a straight line has \vec T constant, so its curvature is 0; a tight circle has \vec T swinging rapidly per unit distance covered, so its curvature is large.

\kappa=\left|\frac{d\vec T}{ds}\right|

Computing this directly needs the arc-length parameterization from §9.5, which is often inconvenient to find explicitly. The chain rule (§2.4) converts the definition into a formula usable directly on t:

\frac{d\vec T}{ds}=\frac{d\vec T}{dt}\cdot\frac{dt}{ds}=\frac{\vec T'(t)}{|\vec r'(t)|}\ \Longrightarrow\ \kappa=\frac{|\vec T'(t)|}{|\vec r'(t)|}

A further simplification (derivable from expanding \vec T in terms of \vec r' and \vec r'', and using that \vec T\times\vec T' isolates only the perpendicular part of \vec r'') gives the most practical computational form, using §9.2's cross product directly on the original parametrization — no need to ever compute \vec T at all:

\kappa=\frac{|\vec r'(t)\times\vec r''(t)|}{|\vec r'(t)|^3}

A clean sanity-check case: for a circle of radius R traced at constant angular speed, this formula gives \kappa=\frac1R exactly — curvature is the reciprocal of radius, matching the intuitive sense that a small circle bends sharply (large \kappa) and a large circle bends gently (small \kappa). The quantity \frac1\kappa is called the radius of curvature — the radius of the circle that best matches the curve's bend at that instant.

The unit normal vector

Since |\vec T(t)|=1 is constant, §9.4's product-rule consequence applies directly: \vec T(t)\cdot\vec T'(t)=0\vec T' is always perpendicular to \vec T. Normalizing it gives the unit normal vector:

\vec N(t)=\frac{\vec T'(t)}{|\vec T'(t)|}

\vec N points in the direction the curve is turning toward — toward the concave side, the direction a car's steering wheel is pointed at that instant.

The binormal vector and the TNB frame

\vec B(t)=\vec T(t)\times\vec N(t)

Since \vec T\perp\vec N (perpendicular by construction) and both are unit vectors, \vec B is automatically a unit vector perpendicular to both (§9.2's cross-product magnitude formula, with \theta=90° giving |\vec T||\vec N|\sin90°=1\cdot1\cdot1=1).

\{\vec T,\vec N,\vec B\} together form the TNB frame (or Frenet frame) — three mutually perpendicular unit vectors, riding along the curve, giving a local coordinate system that turns and reorients itself at every point to match the curve's own geometry. \vec T tracks direction of travel, \vec N tracks which way the curve is bending, and \vec B completes the frame, defining the local "up" out of the plane the curve is momentarily bending within (the osculating plane, spanned by \vec T and \vec N).

Doing it in Python

Curvature of the helix, computed via the direct cross-product formula — no arc-length parameterization needed:

import sympy as sp

t = sp.Symbol('t')
r = sp.Matrix([sp.cos(t), sp.sin(t), t])

r_prime = r.diff(t)
r_double_prime = r_prime.diff(t)

cross_mag = sp.simplify(sp.sqrt(r_prime.cross(r_double_prime).dot(r_prime.cross(r_double_prime))))
speed = sp.simplify(sp.sqrt(r_prime.dot(r_prime)))

curvature = sp.simplify(cross_mag / speed**3)
print(f"curvature of the helix = {curvature}   (constant!)")

Confirming curvature =\frac1R for a circle of radius R — the sanity check that grounds the whole formula:

import sympy as sp

t, R = sp.symbols('t R', positive=True)
r = sp.Matrix([R * sp.cos(t), R * sp.sin(t), 0])

r_prime = r.diff(t)
r_double_prime = r_prime.diff(t)

cross_mag = sp.sqrt(r_prime.cross(r_double_prime).dot(r_prime.cross(r_double_prime)))
speed = sp.sqrt(r_prime.dot(r_prime))
curvature = sp.simplify(cross_mag / speed**3)
print(f"curvature of a radius-{R} circle = {curvature}")

Building the full TNB frame for the helix, and confirming all three vectors are mutually perpendicular unit vectors:

import sympy as sp

t = sp.Symbol('t')
r = sp.Matrix([sp.cos(t), sp.sin(t), t])

r_prime = r.diff(t)
speed = sp.sqrt(r_prime.dot(r_prime))
T = sp.simplify(r_prime / speed)

T_prime = T.diff(t)
T_prime_mag = sp.simplify(sp.sqrt(T_prime.dot(T_prime)))
N = sp.simplify(T_prime / T_prime_mag)

B = sp.simplify(T.cross(N))

print(f"T = {T.T}")
print(f"N = {N.T}")
print(f"B = {B.T}")
print(f"\nT.N = {sp.simplify(T.dot(N))}, T.B = {sp.simplify(T.dot(B))}, N.B = {sp.simplify(N.dot(B))}")
print(f"|T| = {sp.simplify(sp.sqrt(T.dot(T)))}, |N| = {sp.simplify(sp.sqrt(N.dot(N)))}, |B| = {sp.simplify(sp.sqrt(B.dot(B)))}")

Worked example

Find the curvature of the helix \vec r(t)=\langle\cos t,\sin t,t\rangle.

\vec r'(t)=\langle-\sin t,\cos t,1\rangle,\qquad\vec r''(t)=\langle-\cos t,-\sin t,0\rangle

\vec r'(t)\times\vec r''(t)=\langle(\cos t)(0)-(1)(-\sin t),\ (1)(-\cos t)-(-\sin t)(0),\ (-\sin t)(-\sin t)-(\cos t)(-\cos t)\rangle

=\langle\sin t,\,-\cos t,\,\sin^2t+\cos^2t\rangle=\langle\sin t,-\cos t,1\rangle

|\vec r'\times\vec r''|=\sqrt{\sin^2t+\cos^2t+1}=\sqrt2

From §9.5, |\vec r'(t)|=\sqrt2, so |\vec r'(t)|^3=2\sqrt2:

\kappa=\frac{\sqrt2}{2\sqrt2}=\boxed{\frac12}

Sanity check. The curvature is constant — independent of t — which makes geometric sense: a helix looks identical at every point along its length (just rotated and shifted), so it should bend by the same amount everywhere. Compare to the circle formula \kappa=\frac1R: the helix's curvature of \frac12 suggests it bends similarly to a circle of "radius" 2 — plausible for a helix of unit radius that's also climbing steadily (the climbing motion stretches out the bend, making it gentler than a flat unit circle, whose curvature would be exactly 1). ✓

Your turn

1. Find the curvature of \vec r(t)=\langle t,t^2,0\rangle (a parabola in the xy-plane) at t=0, using \kappa=\dfrac{|\vec r'\times\vec r''|}{|\vec r'|^3}.

2. Explain why a straight line \vec r(t)=\vec r_0+t\vec v always has curvature exactly 0, without computing anything (think about what \vec r''(t) is for a line).

3. True or false: the binormal vector \vec B(t) is only meaningful for curves in three dimensions, not for plane curves confined to the xy-plane.

Solutions

1. \vec r'(t)=\langle1,2t,0\rangle, \vec r''(t)=\langle0,2,0\rangle.

\vec r'\times\vec r''=\langle(2t)(0)-(0)(2),\,(0)(0)-(1)(0),\,(1)(2)-(2t)(0)\rangle=\langle0,0,2\rangle

|\vec r'\times\vec r''|=2,\qquad|\vec r'(0)|=|\langle1,0,0\rangle|=1

\kappa(0)=\frac2{1^3}=\boxed2

2. For a line, \vec r'(t)=\vec v is a constant vector — direction never changes. So \vec r''(t)=\vec0. The cross product \vec r'(t)\times\vec r''(t)=\vec r'(t)\times\vec0=\vec0 always (the cross product of anything with the zero vector is zero, §9.2). So \kappa=\dfrac{|\vec0|}{|\vec r'|^3}=0 — a line never bends, exactly as geometric intuition demands, confirmed directly from the formula without plugging in specific numbers.

3. False. Even a curve confined entirely to the xy-plane (so z(t)=0 always) still has a well-defined \vec B(t) — it's simply constant, equal to \pm\vec k=\langle0,0,\pm1\rangle, perpendicular to the plane the whole curve lives in. It's not undefined for plane curves; it's just uninteresting there, since a curve that never leaves a plane never needs to twist out of that plane's orientation. (When \vec B does change — as it typically does for genuine space curves like the helix — that rate of change measures torsion, a further refinement of space-curve geometry beyond this course's scope.)

Check yourself in code

For the helix \vec r(t)=\langle\cos t,\sin t,t\rangle, compute the curvature \kappa using the cross-product formula.

Print exactly this:

curvature = 1/2
import sympy as sp

t = sp.Symbol('t')
r = sp.Matrix([sp.cos(t), sp.sin(t), t])

r_prime = r.diff(t)
r_double_prime = r_prime.diff(t)

cross_mag = sp.simplify(sp.sqrt(r_prime.cross(r_double_prime).dot(r_prime.cross(r_double_prime))))
speed = sp.simplify(sp.sqrt(r_prime.dot(r_prime)))
curvature = sp.simplify(cross_mag / speed**3)
print("curvature = ...")
import sympy as sp

t = sp.Symbol('t')
r = sp.Matrix([sp.cos(t), sp.sin(t), t])

r_prime = r.diff(t)
r_double_prime = r_prime.diff(t)

cross_mag = sp.simplify(sp.sqrt(r_prime.cross(r_double_prime).dot(r_prime.cross(r_double_prime))))
speed = sp.simplify(sp.sqrt(r_prime.dot(r_prime)))
curvature = sp.simplify(cross_mag / speed**3)
print(f"curvature = {curvature}")

Curvature, $\kappa=\left|\dfrac{d\vec T}{ds}\right|=\dfrac{|\vec r'\times\vec r''|}{|\vec r'|^3}$, measures how fast the unit tangent turns per unit of arc length — the reciprocal of a circle's radius, and exactly 0 for a straight line, whose direction never changes at all. The TNB frame — tangent \vec T, normal \vec N, and binormal \vec B — rides along the curve as three mutually perpendicular unit vectors, built one after another from §9.0's unit-vector construction, §9.4's constant-magnitude-implies-perpendicular-derivative fact, and §9.2's cross product.

That closes this module's tour of vectors and the curves they build — algebra for direction and area in §9.0–§9.2, geometry for lines and planes in §9.3, and calculus on curves in §9.4–§9.6. Next: functions of more than one variable, where the derivative itself has to be rebuilt for a world where "which direction" is no longer a single choice.