# @ferret/physics-mechanisms: API

drivetrains of shafts and couplings, gears, clutches, turbines, tooth strength.

59 exports. Generated from the source (`packages/physics-mechanisms/src`), so it matches the code.

## Classes

### Drivetrain

*class* · `packages/physics-mechanisms/src/drivetrain.ts:140`

```ts
class Drivetrain
```

- `readonly shafts: Shaft[]`
- `readonly couplings: Coupling[]`
- `time: number`
- `onEvent: ((e: MachineEvent) => void) | null`
- `stall: { speed: number; torque: number; time: number; }` — A driven shaft that holds under `stallSpeed` rad/s with a driving torque above `stallTorque` N m for `stallTime` s has stalled (`stall` event; again with `stalled: false` when it turns).
- `readonly energy: { work: number; loss: number; friction: number; }` — energy accounting, J
- `shaft(d: ShaftDef): Shaft`
- `find(name: string)`
- `coupling(name: string)`
- `gear(name: string, a: Shaft, b: Shaft, za: number, zb: number, o: { efficiency?: number; internal?: boolean; limit?: number; backlash?: number } = {})` — External gears: z_a·omega_a + z_b·omega_b = 0 (reverses); `internal` keeps the direction. `backlash` (rad of the first shaft) leaves the teeth a gap: inside it nothing is transmitted, at either flank the mesh locks (the impact loses the kinetic energy of the closing speed) and it lets go when the torque reverses.
- `worm(name: string, worm: Shaft, wheel: Shaft, starts: number, zw: number, lead: number, mu: number)` — A worm (one shaft) driving a wheel of `zw` teeth with `starts` threads; `lead` is the lead angle (rad), `mu` the thread friction.
- `belt(name: string, a: Shaft, b: Shaft, da: number, db: number, o: { mu?: number; wrap?: number; tension?: number; wedge?: number; toothed?: boolean; efficiency?: number; limit?: number } = {})` — Belt or chain over pulleys of diameters da and db, same direction. A belt slips beyond the capstan limit; a chain (`toothed`) does not.
- `planetary(name: string, sun: Shaft, ring: Shaft, carrier: Shaft, zs: number, zr: number, efficiency = 1)` — Sun (a), ring (b), carrier (c) by the Willis relation z_s·omega_s + z_r·omega_r = (z_s + z_r)·omega_c.
- `differential(name: string, left: Shaft, right: Shaft, carrier: Shaft, efficiency = 1)` — omega_1 + omega_2 = 2·omega_carrier: the carrier torque splits equally.
- `cardan(name: string, input: Shaft, output: Shaft, beta: number, phase = 0)` — Hooke's joint at the angle beta between the shafts; beta = 0 is a constant-velocity joint.
- `speed(name: string, s: Shaft, w: (t: number) => number)` — Holds a shaft to a given speed (a prescribed drive).
- `speedSource(name: string, s: Shaft, o: { speed?: number; ramp?: number } = {}): SpeedSource` — A speed source: a shaft of infinite inertia that sets its own speed, optionally along a ramp. The gears, belts and clutches behind it feel real torques (a gear can still strip, a clutch still slip); only the shaft is eternal. `torque` and `power` read what it delivers.
- `clutch(name: string, a: Shaft, b: Shaft, capacity: number)` — Friction clutch: couples a and b up to `capacity` x command.
- `gearbox(name: string, input: Shaft, output: Shaft, model: CouplingModel)` — A gearbox between `input` and `output`: omega_out = omega_in / ratio for the engaged gear, nothing in neutral, a friction cone while a synchroniser drags the gear to the shaft speed. The ratio list, the sleeves and the selector belong to the `model` (see `Gearbox` in gearbox.ts), which sets the relation and the capacity of the coupling in every sub-step; the solver treats it as a clutch whose capacity is the cone torque, or infinite once the dogs are in.
- `impact(c: Coupling)` — The kinetic energy of a closing speed is lost when a coupling locks while its sides still differ: books the shortfall of this step to `c`.
- `readonly controls: Map<string, { set(command: unknown): unknown; state?(): unknown; }>` — Named controls a game or a wire sets with `machine.set` (a throttle, a pedal): they are not couplings.
- `brake(name: string, s: Shaft, capacity: number)` — Brake: holds a shaft against the frame up to `capacity` x command.
- `freewheel(name: string, a: Shaft, b: Shaft)` — One-way element: b can overrun a but never lag behind it.
- `drive(s: Shaft, f: TorqueSource)` — Add a torque (a motor, a load, a turbine) acting on a shaft.
- `attach(s: Shaft, r: Reciprocator)`
- `kinetic(): number`
- `step(dt: number, substeps = 1)`
- `balance(): number` — The kinetic energy plus the losses and friction less the work of the external torques: should stay near zero.

### Gearbox

*class* · `packages/physics-mechanisms/src/gearbox.ts:138`

```ts
class Gearbox implements CouplingModel
```

The selector and synchronisers of a gearbox, attached to a `gearbox` coupling of a drivetrain (see `Gearbox.attach`).

A shift is the sequence a real selector goes through: the sleeve of the engaged gear is pulled out (needs the load off the dogs), the finger crosses to
the rail of the wanted gear (if it is another sleeve), the sleeve runs to the blocker ring, and there the cone drags the gear to the shaft speed with
T = mu·F·r_m / sin(alpha) while the blocker holds the sleeve back until the speed difference is gone; then the sleeve passes the blocker and the dogs go
in. With the speeds matched and the load off, the sequence takes `nominal_time_s` of the sleeve. Without the clutch the cone cannot drag the engine:
it slips against the blocker, heats and wears, grinds after `grindAfter` and the shift is given up after `refuseAfter` (the gear stays in neutral).

- `readonly gears: Map<GearId, GearDef>`
- `readonly syncs: Map<string, SyncUnit>`
- `coupling: Coupling`
- `train: Drivetrain`
- `input: Shaft`
- `output: Shaft`
- `engaged: GearDef | null` — the gear locked to the output (dogs in), or null in neutral / during a shift
- `active: GearDef | null` — the gear whose sleeve is displaced from neutral (engaged or in the middle of a shift)
- `target: GearDef | 'N' | null`
- `phase: Phase`
- `effort: number` — selector effort: the shift force relative to the nominal one
- `gate: string`
- `oilTemperature: number`
- `status: ShiftStatus`
- `power: { in: number; out: number; loss: number; }` — power through the box over the last sub-step, W, and its losses
- `energy: { in: number; out: number; loss: number; }`
- `readonly opt: Required<Omit<GearboxOptions, 'gearJ' | 'dt' | 'life'>>`
- `life: GearboxLife`
- `constructor(readonly spec: GearboxSpec, o: GearboxOptions = {})`
- `reflectedInertia(idlerJ = 0): number` — Reflected onto the input shaft: every free gear turns at omega_in / ratio, the idler of reverse at omega_in * z_in / z_idler.
- `attach(train: Drivetrain, input: Shaft, output: Shaft, name = 'gearbox'): Coupling`
- `command(cmd: unknown): { ok: boolean; gear?: string; reason?: string }` — `{ gear: 3 }`, `{ gear: 'R' }`, `{ gear: 0 }` or `'N'` for neutral, and `{ effort: 1.5 }` for the force on the lever relative to nominal.
- `get gear(): GearId | 'N'` — the gear that is in, or 'N'
- `pre(h: number)`
- `post(h: number)`
- `nodeAngles(): { node: string; angle?: number; slide?: number; scale?: number; axis: [number, number, number] }[]` — angle (rad) of the nodes that turn with the box but are not shafts of the drivetrain: the free gears (meshed with the input), the idler, the sleeves' slide
- `meshFrequencies(): number[]` — Tooth-mesh frequencies (Hz) of the meshes that carry load: z·n/60 (`life.whine()` has the harmonics and levels).
- `state()`

### GearboxLife

*class* · `packages/physics-mechanisms/src/gearbox-life.ts:68`

```ts
class GearboxLife
```

- `readonly net: ThermalNet`
- `readonly churn: Churn[]`
- `readonly bearings: BearingDef[]`
- `readonly rattlers: Rattler[]`
- `readonly audio: SoundEvent[]`
- `readonly opt: Required<LifeOptions>`
- `level: number` — oil level as a fraction of the nominal (1 = the spec's oil_level_z) and the height it stands at, mm
- `readonly nu40: number`
- `readonly levelNominal: number`
- `readonly levelBottom: number`
- `metalPpm: number`
- `churnPower: number`
- `readonly pitting: Record<string, number>` — damage by pitting (1 = pitted) of each gear's mesh and of the final drive
- `readonly pitted: Set<string>`
- `readonly bearingLoss: { power: number; energy: number; }`
- `rattleRate: number`
- `rattleIntensity: number`
- `constructor(private gb: Gearbox, private spec: GearboxSpec, o: LifeOptions = {})`
- `get oilTemperature()`
- `get viscosity()`
- `get levelZ()` — oil level height, mm (spec z axis: up is positive)
- `setLevel(f: number)`
- `get coldFactor()` — how much heavier a shift is in cold oil than at 40 °C: the sleeve and fork push through oil
- `dip(axisZ: number, r: number)` — immersion depth (mm) of a gear of tip radius r (mm) on an axis at height z (mm)
- `attach(input: Shaft, output: Shaft)` — register the oil-dipping gears, the shaft drags and the bearings; called by `Gearbox.attach`
- `watchFinalDrive(fd: Coupling, diff: Coupling, carrier: Shaft)` — the final drive and differential: their losses heat the oil, the crown dips and wears
- `post(h: number, c: { meshLoss: number; coneLoss: number; cone: SyncUnit | null })`
- `drain(): SoundEvent[]` — hand the queued sound events to the audio layer
- `clunk(gear: string, intensity: number)`
- `grind(gear: string, grinding: boolean, intensity: number)`
- `whine()` — mesh whine of the loaded meshes: f = z·n/60 and its first harmonics, louder with load and with pitting
- `state()`

### SpeedSource

*class* · `packages/physics-mechanisms/src/drivetrain.ts:119`

```ts
class SpeedSource
```

A prescribed shaft speed that can be changed along a linear ramp (see `Drivetrain.speedSource`).

- `coupling: Coupling`
- `target: number` — the speed asked for, rad/s
- `constructor(private readonly dt: Drivetrain, readonly shaft: Shaft, speed: number)`
- `at(t: number): number` — The speed at drivetrain time t.
- `setSpeed(w: number, ramp = 0)` — Go to `w` rad/s over `ramp` seconds (at once when 0), from the speed it has now.
- `get torque()` — the torque the source puts on its shaft over the last step, N·m (what the gears behind it carry)
- `get power()` — the power it delivers, W

### ThermalNet

*class* · `packages/physics-mechanisms/src/gearbox-life.ts:13`

```ts
class ThermalNet
```

- `readonly nodes: Map<string, { C: number; T: number; }>`
- `constructor(readonly ambient: number)`
- `add(name: string, C: number, T = this.ambient)`
- `link(a: string, b: string, G: number)`
- `toAir(a: string, G: () => number)`
- `heat(name: string, J: number)`
- `T(name: string)`
- `step(h: number)`

## Functions

### buildTransaxle

*function* · `packages/physics-mechanisms/src/gearbox.ts:544`

```ts
function buildTransaxle(train: Drivetrain, spec: GearboxSpec, o: TransaxleOptions = {}): Transaxle
```

Build the transaxle drivetrain from spec.json into `train`. Shaft names: flywheel, Shaft_In, Shaft_Out, Diff_Carrier, Halfshaft_L, Halfshaft_R.
Controls (`machine.set { element, command }`): `gearbox` ({gear, effort}), `clutch` (engagement 0..1, a coupling), `throttle` (0..1), `brake` (0..1).

### cardanAngle

*function* · `packages/physics-mechanisms/src/drivetrain.ts:553`

```ts
function cardanAngle(theta: number, beta: number, near: number): number
```

Output angle of Hooke's joint, continuous with `near` (tan(out) = tan(in) / cos(beta)).

### cardanRatio

*function* · `packages/physics-mechanisms/src/drivetrain.ts:548`

```ts
function cardanRatio(theta: number, beta: number): number
```

Hooke's joint: the output / input speed ratio, the derivative of tan(out) = tan(in) / cos(beta), with the angles measured from
the plane of the bend: cos(beta) / (1 - sin²(beta)·cos²(theta)). The extremes are 1/cos(beta) and cos(beta).

### cpCurve

*function* · `packages/physics-mechanisms/src/turbines.ts:10`

```ts
function cpCurve: (cpMax?: number, peak?: number) => (lambda: number) => number
```

A typical Cp(lambda) curve with its peak at `peak` (tip-speed ratio) and height `cpMax` (clamped to Betz): a parabola, zero at 0 and at twice the peak.

### crankSlider

*function* · `packages/physics-mechanisms/src/drivetrain.ts:560`

```ts
function crankSlider: (r: number, l: number) => (theta: number) => number
```

Crank-slider position, x = r·cos(theta) + sqrt(l² − r²·sin²(theta)).

### gasPower

*function* · `packages/physics-mechanisms/src/turbines.ts:31`

```ts
function gasPower(o: { eta: number; mdot: number; cp: number; T1: number; pressureRatio: number; gamma?: number }): number
```

Power of a gas or steam turbine, W: P = eta·mdot·cp·T1·(1 − (1/PR)^((gamma−1)/gamma)).

### gauss

*function* · `packages/physics-mechanisms/src/drivetrain.ts:526`

```ts
function gauss(A: number[][], b: number[]): number[]
```

### gearInertia

*function* · `packages/physics-mechanisms/src/gearbox.ts:492`

```ts
function gearInertia(z: number, mn: number, beta: number, b: number, rho = 7850): number
```

Placeholder inertia of a gear until `drivetrain.json` has the measured one: a rim with a web, 60 % of the solid disc.

### lewisForce

*function* · `packages/physics-mechanisms/src/drivetrain.ts:562`

```ts
function lewisForce: (sigma: number, module: number, width: number, Y?: number) => number
```

Lewis tooth bending limit: the tangential force (N) a tooth of module m (m) and face width b (m) carries at allowable stress sigma and form factor Y.

### lewisY

*function* · `packages/physics-mechanisms/src/gearbox.ts:42`

```ts
function lewisY: (z: number, beta?: number) => number
```

Lewis form factor from the virtual tooth count (z / cos³ beta): the usual fit Y = 0.484 - 2.87 / z.

### machines

*function* · `packages/physics-mechanisms/src/index.ts:41`

```ts
function machines(train: Drivetrain = new Drivetrain()): MachineCapability
```

### meshStiffness

*function* · `packages/physics-mechanisms/src/drivetrain.ts:587`

```ts
function meshStiffness(b: number, rb: number, cPrime = 14e9): { linear: number; torsional: number }
```

Stiffness of a mesh across the face width b: the pair of teeth together bend and flatten by about 1/(14 GPa) of the load per metre of width
(a spur pair of steel, c' ≈ 14 N/(µm·mm)); the torsional stiffness at base radius rb (m) is that times rb², N·m/rad.

### oilViscosity

*function* · `packages/physics-mechanisms/src/gearbox-life.ts:37`

```ts
function oilViscosity: (nu40: number, T: number) => number
```

Kinematic viscosity of the oil (cSt) at T °C from its value at 40 °C: about a factor 7 between 40 and 100 °C for a gear oil.

### pairLimit

*function* · `packages/physics-mechanisms/src/gearbox.ts:48`

```ts
function pairLimit(p: { mn: number; z1: number; z2: number; beta: number; b: number }, sigmaF: number, sigmaH: number, E = 210e9)
```

The tangential force (N) one pair of teeth carries before the weaker of Lewis bending (either gear, at the allowable bending stress) and the Hertz
pressure (allowable flank pressure) is reached, and the torque on the first gear it stands for (N·m).

### propeller

*function* · `packages/physics-mechanisms/src/turbines.ts:42`

```ts
function propeller(o: { rho: number; diameter: number; kt: number; kq: number })
```

A propeller: thrust (N) and the shaft torque it needs, from the thrust and torque coefficients, T = kt·rho·n²·D⁴.

### pumpLoad

*function* · `packages/physics-mechanisms/src/turbines.ts:37`

```ts
function pumpLoad(o: { flow: (omega: number) => number; rise: (omega: number) => number; eta: number }): TorqueSource
```

A pump, fan or compressor as a load: shaft power = flow x pressure rise / efficiency, as a torque against rotation.

### registerMachineCommands

*function* · `packages/physics-mechanisms/src/index.ts:132`

```ts
function registerMachineCommands(c: { register(name: string, description: string, fn: (a: any) => unknown): unknown }, train: Drivetrain)
```

The `machine.*` commands on any registry with `register(name, description, fn)`.

### toothContactLimit

*function* · `packages/physics-mechanisms/src/drivetrain.ts:579`

```ts
function toothContactLimit(b: number, d1: number, d2: number, m1: FlankMaterial = STEEL_FLANK, m2: FlankMaterial = m1, alpha = (20 * Math.PI) / 180): number
```

The tangential force a pair of teeth carries before the Hertz pressure reaches the weaker flank's allowable value, N: the inverse of `toothContactPressure`.

### toothContactPressure

*function* · `packages/physics-mechanisms/src/drivetrain.ts:572`

```ts
function toothContactPressure(Ft: number, b: number, d1: number, d2: number, m1: FlankMaterial = STEEL_FLANK, m2: FlankMaterial = m1, alpha = (20 * Math.PI) / 180): number
```

Hertz contact of two teeth at the pitch point as two cylinders of the radii of curvature d·sin(α)/2 pressed along the face width `b` (m): the
pressure for a tangential tooth force Ft (N) on pitch diameters d1, d2 (m) at pressure angle α. Zero when a diameter or the width is not above zero.

### waterPower

*function* · `packages/physics-mechanisms/src/turbines.ts:23`

```ts
function waterPower: (eta: number, flow: number, head: number, rho?: number, g?: number) => number
```

Power of a water turbine, W: P = eta·rho·g·Q·H.

### waterTurbine

*function* · `packages/physics-mechanisms/src/turbines.ts:26`

```ts
function waterTurbine(o: { eta: number; flow: () => number; head: () => number; rho?: number }): TorqueSource
```

A water turbine as a torque: the power from the head and flow, divided by the speed (with a floor so it starts from rest).

### windPower

*function* · `packages/physics-mechanisms/src/turbines.ts:7`

```ts
function windPower: (rho: number, area: number, v: number, cp: number) => number
```

Power of a wind turbine, W: P = ½·rho·A·v³·Cp, with Cp never above the Betz limit.

### windTurbine

*function* · `packages/physics-mechanisms/src/turbines.ts:13`

```ts
function windTurbine(o: { rho?: number; radius: number; wind: () => number; cp?: (lambda: number) => number }): TorqueSource
```

A wind turbine as a torque on its shaft: T = P / omega with P from the tip-speed ratio.

## Interfaces

### BodyBinding

*interface* · `packages/physics-mechanisms/src/index.ts:26`

```ts
interface BodyBinding
```

Body mode: a shaft turns a kinematic body of the kernel (a paddle, a wheel, a turntable, a crane's jib) about a pivot and an axis, so the
machine moves things in the world; what the world does back (the contacts' impulses about the axis) is a load torque on the shaft, so
a paddle that meets a crate slows, and one that meets what it cannot move jams.

- `shaft: Shaft`
- `body: Body`
- `pivot: Vec3`
- `axis: Vec3`
- `rest: Quat`
- `offset: Vec3`
- `theta0: number`
- `reaction: number`

### Coupled

*interface* · `packages/physics-mechanisms/src/index.ts:39`

```ts
interface Coupled
```

A rotor joined to a dynamic body by a viscous coupling: it puts `damping x (shaft speed - body speed about the axis)` on the body and
takes the same from the shaft, so angular momentum is kept and the shaft slips against a load it cannot turn (the joint, the kernel's
hinge, holds the body to its axis). Stable while `damping x dt` stays below the smaller of the inertias.

- `shaft: Shaft`
- `body: Body`
- `axis: Vec3`
- `damping: number`
- `torque: number`

### Coupling

*interface* · `packages/physics-mechanisms/src/drivetrain.ts:78`

```ts
interface Coupling
```

- `readonly id: number`
- `readonly name: string`
- `readonly kind: CouplingKind`
- `shafts: Shaft[]`
- `a: number[]` — coefficients of sum(a_k·omega_k) = 0 (or = speed for 'speed'); the first shaft has 1
- `efficiency: number`
- `capacity: number` — torque capacity N·m (friction couplings), scaled by `command` for a clutch and a brake
- `command: number`
- `limit?: number` — tooth or belt limit on the torque through the coupling, N·m; it breaks beyond it
- `state: 'stuck' | 'slip' | 'free' | 'locked'`
- `slipDir: number`
- `broken: boolean`
- `torque: number` — torque through the coupling over the last step (on its first shaft), N·m
- `lead?: number` — worm: lead angle (rad) and friction coefficient
- `mu?: number`
- `beta?: number` — cardan: shaft angle beta (rad) and the orientation of the fork on the input shaft
- `phase?: number`
- `lash?: number` — backlash: the free play (rad of the first shaft), where the teeth are inside it (rad), and the flank in contact (+1, -1; 0 = in the gap)
- `lashPhi?: number`
- `lashSide?: number`
- `speed?: (t: number) => number`
- `loss: number` — energy lost in the coupling, J
- `model?: CouplingModel`

### CouplingBase

*interface* · `packages/physics-mechanisms/src/drivetrain.ts:74`

```ts
interface CouplingBase
```

- `name: string`
- `efficiency?: number`

### CouplingModel

*interface* · `packages/physics-mechanisms/src/drivetrain.ts:66`

```ts
interface CouplingModel
```

Behaviour a coupling takes from outside the solver (the synchronisers of a gearbox): `pre` runs at the start of every sub-step and sets what the
solver reads (`a`, `capacity`, `efficiency`), `post` runs after the speeds are solved and advances the model's own state.

- `pre?(h: number): void`
- `post?(h: number): void`
- `command?(cmd: unknown): unknown` — a command object from `machine.set`
- `state?(): unknown`

### DrivetrainFile

*interface* · `packages/physics-mechanisms/src/gearbox.ts:35`

```ts
interface DrivetrainFile
```

`build/drivetrain.json` as far as the machine reads it: the measured inertias and the node names.

- `shafts?: Record<string, unknown>`
- `nodes?: { sleeves?: Record<string, string>; forks?: Record<string, string>; rails?: Record<string, string>; oil?: string; housing?: string[] }`

### Engine

*interface* · `packages/physics-mechanisms/src/gearbox.ts:519`

```ts
interface Engine
```

- `throttle: number`
- `ripple: number`
- `idle: number`
- `peak: number`
- `limit: number`
- `torque(omega: number): number`

### FlankMaterial

*interface* · `packages/physics-mechanisms/src/drivetrain.ts:565`

```ts
interface FlankMaterial
```

Material of a tooth flank for the contact check: Young's modulus (Pa), Poisson's ratio, the allowable Hertz pressure (Pa, from the pitting fatigue limit).

- `E: number`
- `nu: number`
- `sigmaH: number`

### GearboxOptions

*interface* · `packages/physics-mechanisms/src/gearbox.ts:96`

```ts
interface GearboxOptions
```

- `grindAfter?: number` — time the cone may slip against the blocker before it is felt as a grind (s), and before the shift is given up (s)
- `refuseAfter?: number`
- `passSpeed?: number` — speed difference (rad/s on the input shaft) under which the blocker lets the sleeve pass
- `releaseTorque?: number` — torque on the dogs (N·m, input side) the sleeve can pull out of engagement; a bigger load holds the gear in
- `wearLife?: number` — energy (J) that wears a cone out completely
- `coneHeatCapacity?: number` — thermal mass (J/K) and conductance to the oil (W/K) of a cone, and the ambient air temperature
- `coneToOil?: number`
- `ambient?: number`
- `life?: LifeOptions` — oil, thermal network, sound, wear (see gearbox-life.ts)
- `gearJ?: Partial<Record<GearId, number>>` — inertia of the free gears and the idler, by gear: from `drivetrain.json` when given
- `dt?: DrivetrainFile`

### GearboxSpec

*interface* · `packages/physics-mechanisms/src/gearbox.ts:22`

```ts
interface GearboxSpec
```

- `meta: { design_torque_nm: number; rpm_limit: number }`
- `pairs: Record<string, SpecPair>`
- `reverse: { mn: number; z_in: number; z_out: number; z_idler: number; b: number; beta?: number }`
- `final_drive: { z_pinion: number; z_crown: number; mn: number; b: number; beta: number }`
- `sync: Record<string, SpecSync>`
- `material: { sigma_f_allow: number; sigma_h_allow: number; tau_allow?: number; density_steel?: number; e_steel?: number }`
- `efficiency: { mesh: number }`
- `shafts?: { input?: { d: number; length: number }; output?: { d: number; length: number } }`
- `tolerance?: { backlash_min?: number; backlash_max?: number }`
- `housing?: { oil_volume_l?: number }`

### GearDef

*interface* · `packages/physics-mechanisms/src/gearbox.ts:59`

```ts
interface GearDef
```

- `id: GearId`
- `ratio: number` — omega_in / omega_out, negative for reverse
- `sync: string`
- `side: -1 | 1` — -1 = the first gear of the sleeve's pair, +1 = the second
- `eta: number` — product of the engaged meshes' efficiencies
- `limit: number` — torque on the input shaft at which the gear's teeth give way, N·m
- `teeth: number[]` — pitch circle radii and tooth counts along the path, for the whine frequencies
- `node: string`
- `brokenNode: string`
- `J: number` — inertia of the free gear (and the idler), kg·m²
- `broken: boolean`

### Housing

*interface* · `packages/physics-mechanisms/src/drivetrain.ts:31`

```ts
interface Housing
```

The mounting of a shaft. Every step the drivetrain hands it the mean reaction torque of that step as a vector (N·m, in the housing's frame, along the
shaft's axis): the capability turns it into `kernel.applyTorque` on the housing body or the vessel. The shaft's speed is relative to the housing; the
pseudo-torque from the housing's own turning is ignored (the housing is heavy against the shaft, or it is the world).

- `torque(t: [number, number, number], dt: number): void`

### LifeOptions

*interface* · `packages/physics-mechanisms/src/gearbox-life.ts:44`

```ts
interface LifeOptions
```

- `fatigueSpeedup?: number` — accelerated life test: damage per revolution is multiplied by this (1 = real time)
- `bearingScale?: number` — multiplies the dynamic rating C of every bearing
- `pittingLimit?: number` — endurance limit of the flanks, Pa (default 0.68 of the static allowable) and the Woehler exponent and corner cycles
- `pittingExponent?: number`
- `pittingCycles?: number`
- `airSpeed?: () => number` — relative torque ripple of the engine at the input of the box (as a fraction of the design torque) used by `ripple()`
- `restitution?: number` — coefficient of restitution of a tooth impact in the backlash
- `freeGearDrag?: number` — drag torque of a free gear on its needle bearing, N·m
- `ambient?: number`

### MachineCapability

*interface* · `packages/physics-mechanisms/src/index.ts:27`

```ts
interface MachineCapability extends Capability
```

- `readonly train: Drivetrain`
- `readonly bound: BodyBinding[]`
- `bind(shaft: Shaft, body: Body, opts?: { pivot?: Vec3; axis?: Vec3 }): BodyBinding`
- `couple(shaft: Shaft, body: Body, opts?: { axis?: Vec3; damping?: number }): Coupled` — Dynamic mode: a shaft turns a body that a kernel hinge holds (see `Coupled`).

### Reciprocator

*interface* · `packages/physics-mechanisms/src/drivetrain.ts:53`

```ts
interface Reciprocator
```

A mass that moves with the shaft's angle: x = s(theta). A slider on a crank, a cam follower, a lead screw, a Scotch yoke.

- `s: (theta: number) => number`
- `mass: number`
- `load?: (x: number, v: number) => number` — force on the mass as a function of position and speed (spring, gas, load), N

### Shaft

*interface* · `packages/physics-mechanisms/src/drivetrain.ts:35`

```ts
interface Shaft
```

- `readonly id: number`
- `readonly name: string`
- `J: number`
- `b: number`
- `coulomb: number`
- `omega: number`
- `theta: number`
- `diameter?: number`
- `shear?: number`
- `node?: string`
- `axis: [number, number, number]`
- `housing?: Housing`
- `reaction: number` — the mean torque the shaft put on its housing over the last step, N·m about the shaft's axis (positive along it)
- `sources: TorqueSource[]`
- `reciprocators: Reciprocator[]`
- `broken: boolean`
- `transmitted: number` — largest torque any coupling put on the shaft in the last step, N·m

### ShaftDef

*interface* · `packages/physics-mechanisms/src/drivetrain.ts:6`

```ts
interface ShaftDef
```

A drivetrain as a small network: shafts (one degree of freedom each, with inertia) joined by couplings that fix a speed relation.
Each step solves the velocity constraints with Lagrange multipliers (implicit, so a stiff ratio is exact at any step), then the
efficiency of every mesh is applied to the torque that reaches the driven side, so power in = power out + losses.

- `name: string`
- `J: number` — moment of inertia, kg·m²
- `b?: number` — viscous friction, N·m·s/rad
- `coulomb?: number` — dry (Coulomb) friction torque, N·m
- `omega?: number`
- `theta?: number`
- `diameter?: number` — shaft diameter (m) and the shear stress (Pa) it carries: it breaks when 16·T / (π·d³) passes the limit
- `shear?: number`
- `node?: string` — the scene node this shaft turns, and the axis
- `axis?: [number, number, number]`
- `housing?: Housing` — the body the shaft is mounted in: whatever turns the shaft pushes the opposite way on it; none = fixed to the world

### ShiftStatus

*interface* · `packages/physics-mechanisms/src/gearbox.ts:117`

```ts
interface ShiftStatus
```

- `target: GearId | 'N' | null`
- `phase: Phase`
- `elapsed: number` — s since the command
- `last: { gear: string; time: number; ok: boolean; reason?: string } | null` — time the last finished shift took, s, and how it ended
- `grinding: boolean`

### SpecPair

*interface* · `packages/physics-mechanisms/src/gearbox.ts:17`

```ts
interface SpecPair
```

- `mn: number`
- `z_in: number`
- `z_out: number`
- `beta: number`
- `b: number`

### SpecSync

*interface* · `packages/physics-mechanisms/src/gearbox.ts:18`

```ts
interface SpecSync
```

- `gears: [string, string]`
- `cone_angle: number`
- `mean_radius: number`
- `mu: number`
- `spring_n: number`
- `shift_force_n: number`
- `nominal_time_s: number`
- `sleeve_travel: number`

### SyncUnit

*interface* · `packages/physics-mechanisms/src/gearbox.ts:79`

```ts
interface SyncUnit
```

- `name: string`
- `spec: SpecSync`
- `x: number` — sleeve position along the shaft, mm from neutral: negative toward the first gear of the pair
- `temperature: number` — cone temperature, °C, and wear 0 (new) .. 1 (finished)
- `wear: number`
- `sleeveNode: string`
- `forkNode: string`
- `railNode: string`
- `slipEnergy: number` — energy slipped in the cone over its life, J

### Transaxle

*interface* · `packages/physics-mechanisms/src/gearbox.ts:521`

```ts
interface Transaxle
```

- `train: Drivetrain`
- `gearbox: Gearbox`
- `engine: Engine`
- `shafts: { flywheel: Shaft; input: Shaft; output: Shaft; carrier: Shaft; left: Shaft; right: Shaft }`
- `clutch: Coupling`
- `finalDrive: Coupling`
- `differential: Coupling`
- `brakes: Coupling[]`
- `speed(): number` — forward speed of the vehicle, m/s
- `state(): Record<string, unknown>`
- `nodeAngles(): { node: string; angle?: number; slide?: number; scale?: number; axis: [number, number, number] }[]`
- `setPedal(p: number): void` — clutch pedal 0 (up, engaged) .. 1 (down)

### TransaxleOptions

*interface* · `packages/physics-mechanisms/src/gearbox.ts:499`

```ts
interface TransaxleOptions
```

- `dt?: DrivetrainFile`
- `gearbox?: GearboxOptions`
- `flywheelJ?: number` — engine flywheel inertia (kg·m²); peak torque and speed limit default to the spec's design torque and rpm limit
- `idleRpm?: number`
- `wheelRadius?: number` — vehicle: wheel radius (m), mass (kg), inertia of one wheel with its tyre (kg·m²), rolling coefficient, Cd·A (m²)
- `vehicleMass?: number`
- `wheelJ?: number`
- `rolling?: number`
- `cdA?: number`
- `brakeTorque?: number` — friction torque of one brake at the wheel, N·m
- `clutchMargin?: number` — clutch capacity as a multiple of the design torque
- `finalBacklash?: number` — mesh backlash of the final drive, rad on the pinion (omit: none)

## Types

### CouplingKind

*type* · `packages/physics-mechanisms/src/drivetrain.ts:60`

```ts
type CouplingKind = 'gear' | 'worm' | 'belt' | 'planetary' | 'differential' | 'cardan' | 'speed' | 'clutch' | 'brake' | 'freewheel' | 'gearbox'
```

### GearId

*type* · `packages/physics-mechanisms/src/gearbox.ts:13`

```ts
type GearId = '1' | '2' | '3' | '4' | '5' | 'R'
```

### MachineEvent

*type* · `packages/physics-mechanisms/src/drivetrain.ts:109`

```ts
type MachineEvent = | { kind: 'break'; element: string; torque: number; node?: string; broken?: string; mode?: 'stripped' | 'sheared' | 'overload' } | { kind: 'wear'; element: string; mode: 'pitting' | 'bearing'; damage: number } | { kind: 'slip'; element: string; slipping: boolean; grind?: boolean; gear?: string } | { kind: 'shift'; element: string; gear: string; ok: boolean; reason?: string; time?: number } | { kind: 'stall'; element: string; stalled: boolean; torque: number }
```

### SoundEvent

*type* · `packages/physics-mechanisms/src/gearbox-life.ts:39`

```ts
type SoundEvent = | { t: number; kind: 'clunk'; gear: string; intensity: number } | { t: number; kind: 'grind'; gear: string; grinding: boolean; intensity: number } | { t: number; kind: 'rattle'; gear: string; intensity: number }
```

### TorqueSource

*type* · `packages/physics-mechanisms/src/drivetrain.ts:33`

```ts
type TorqueSource = (omega: number, theta: number, t: number) => number
```

## Constants

### BETZ

*const* · `packages/physics-mechanisms/src/turbines.ts:4`

```ts
const BETZ: number
```

Betz limit of a wind turbine's power coefficient.

### MACHINE_DEFAULTS

*const* · `packages/physics-mechanisms/src/index.ts:19`

```ts
const MACHINE_DEFAULTS: { substeps: number; }
```

machines. A `Drivetrain` of shafts and couplings is stepped with the world; limits become events and the shafts
turn the scene nodes they name. The machine has no input binding: a game or a wire sets a command and reads speeds and torques.

values (each at world / level / zone / entity scope):
  substeps   solver sub-steps per world step                    (4)

events: `machine:break` { element, torque }, `machine:slip` { element, slipping }, `machine:stall` { element, stalled, torque }.

### STEEL_FLANK

*const* · `packages/physics-mechanisms/src/drivetrain.ts:566`

```ts
const STEEL_FLANK: FlankMaterial
```

