FERRETGame engine over Babylon.js
Ferret

@ferret/physics-mechanisms

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

59 exports · source in packages/physics-mechanisms/src

Classes

Drivetrain class

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 } = {}): SpeedSourceA 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(): numberThe kinetic energy plus the losses and friction less the work of the external torques: should stay near zero.

packages/physics-mechanisms/src/drivetrain.ts:140

Gearbox class

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 | nullthe gear locked to the output (dogs in), or null in neutral / during a shift
active: GearDef | nullthe gear whose sleeve is displaced from neutral (engaged or in the middle of a shift)
target: GearDef | 'N' | null
phase: Phase
effort: numberselector 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): numberReflected 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()

packages/physics-mechanisms/src/gearbox.ts:138

GearboxLife class

class GearboxLife
readonly net: ThermalNet
readonly churn: Churn[]
readonly bearings: BearingDef[]
readonly rattlers: Rattler[]
readonly audio: SoundEvent[]
readonly opt: Required<LifeOptions>
level: numberoil 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()

packages/physics-mechanisms/src/gearbox-life.ts:68

SpeedSource class

class SpeedSource

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

coupling: Coupling
target: numberthe speed asked for, rad/s
constructor(private readonly dt: Drivetrain, readonly shaft: Shaft, speed: number)
at(t: number): numberThe 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

packages/physics-mechanisms/src/drivetrain.ts:119

ThermalNet class

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)

packages/physics-mechanisms/src/gearbox-life.ts:13

Functions

buildTransaxle function

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).

packages/physics-mechanisms/src/gearbox.ts:544

cardanAngle function

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

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

packages/physics-mechanisms/src/drivetrain.ts:553

cardanRatio function

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).

packages/physics-mechanisms/src/drivetrain.ts:548

cpCurve function

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.

packages/physics-mechanisms/src/turbines.ts:10

crankSlider function

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

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

packages/physics-mechanisms/src/drivetrain.ts:560

gasPower function

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)).

packages/physics-mechanisms/src/turbines.ts:31

gauss function

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

packages/physics-mechanisms/src/drivetrain.ts:526

gearInertia function

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.

packages/physics-mechanisms/src/gearbox.ts:492

lewisForce function

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.

packages/physics-mechanisms/src/drivetrain.ts:562

lewisY function

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.

packages/physics-mechanisms/src/gearbox.ts:42

machines function

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

packages/physics-mechanisms/src/index.ts:41

meshStiffness function

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.

packages/physics-mechanisms/src/drivetrain.ts:587

oilViscosity function

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.

packages/physics-mechanisms/src/gearbox-life.ts:37

pairLimit function

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).

packages/physics-mechanisms/src/gearbox.ts:48

propeller function

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⁴.

packages/physics-mechanisms/src/turbines.ts:42

pumpLoad function

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.

packages/physics-mechanisms/src/turbines.ts:37

registerMachineCommands function

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).

packages/physics-mechanisms/src/index.ts:132

toothContactLimit function

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.

packages/physics-mechanisms/src/drivetrain.ts:579

toothContactPressure function

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.

packages/physics-mechanisms/src/drivetrain.ts:572

waterPower function

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.

packages/physics-mechanisms/src/turbines.ts:23

waterTurbine function

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).

packages/physics-mechanisms/src/turbines.ts:26

windPower function

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.

packages/physics-mechanisms/src/turbines.ts:7

windTurbine function

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.

packages/physics-mechanisms/src/turbines.ts:13

Interfaces

BodyBinding interface

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

packages/physics-mechanisms/src/index.ts:26

Coupled interface

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

packages/physics-mechanisms/src/index.ts:39

Coupling interface

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: numbertorque capacity N·m (friction couplings), scaled by command for a clutch and a brake
command: number
limit?: numbertooth 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: numbertorque through the coupling over the last step (on its first shaft), N·m
lead?: numberworm: lead angle (rad) and friction coefficient
mu?: number
beta?: numbercardan: shaft angle beta (rad) and the orientation of the fork on the input shaft
phase?: number
lash?: numberbacklash: 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: numberenergy lost in the coupling, J
model?: CouplingModel

packages/physics-mechanisms/src/drivetrain.ts:78

CouplingBase interface

interface CouplingBase
name: string
efficiency?: number

packages/physics-mechanisms/src/drivetrain.ts:74

CouplingModel interface

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): unknowna command object from machine.set
state?(): unknown

packages/physics-mechanisms/src/drivetrain.ts:66

DrivetrainFile interface

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[] }

packages/physics-mechanisms/src/gearbox.ts:35

Engine interface

interface Engine
throttle: number
ripple: number
idle: number
peak: number
limit: number
torque(omega: number): number

packages/physics-mechanisms/src/gearbox.ts:519

FlankMaterial interface

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

packages/physics-mechanisms/src/drivetrain.ts:565

GearboxOptions interface

interface GearboxOptions
grindAfter?: numbertime 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?: numberspeed difference (rad/s on the input shaft) under which the blocker lets the sleeve pass
releaseTorque?: numbertorque on the dogs (N·m, input side) the sleeve can pull out of engagement; a bigger load holds the gear in
wearLife?: numberenergy (J) that wears a cone out completely
coneHeatCapacity?: numberthermal mass (J/K) and conductance to the oil (W/K) of a cone, and the ambient air temperature
coneToOil?: number
ambient?: number
life?: LifeOptionsoil, 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

packages/physics-mechanisms/src/gearbox.ts:96

GearboxSpec interface

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 }

packages/physics-mechanisms/src/gearbox.ts:22

GearDef interface

interface GearDef
id: GearId
ratio: numberomega_in / omega_out, negative for reverse
sync: string
side: -1 | 1-1 = the first gear of the sleeve's pair, +1 = the second
eta: numberproduct of the engaged meshes' efficiencies
limit: numbertorque 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: numberinertia of the free gear (and the idler), kg·m²
broken: boolean

packages/physics-mechanisms/src/gearbox.ts:59

Housing interface

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

packages/physics-mechanisms/src/drivetrain.ts:31

LifeOptions interface

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

packages/physics-mechanisms/src/gearbox-life.ts:44

MachineCapability interface

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 }): CoupledDynamic mode: a shaft turns a body that a kernel hinge holds (see Coupled).

packages/physics-mechanisms/src/index.ts:27

Reciprocator interface

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) => numberforce on the mass as a function of position and speed (spring, gas, load), N

packages/physics-mechanisms/src/drivetrain.ts:53

Shaft interface

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: numberthe 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: numberlargest torque any coupling put on the shaft in the last step, N·m

packages/physics-mechanisms/src/drivetrain.ts:35

ShaftDef interface

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: numbermoment of inertia, kg·m²
b?: numberviscous friction, N·m·s/rad
coulomb?: numberdry (Coulomb) friction torque, N·m
omega?: number
theta?: number
diameter?: numbershaft diameter (m) and the shear stress (Pa) it carries: it breaks when 16·T / (π·d³) passes the limit
shear?: number
node?: stringthe scene node this shaft turns, and the axis
axis?: [number, number, number]
housing?: Housingthe body the shaft is mounted in: whatever turns the shaft pushes the opposite way on it; none = fixed to the world

packages/physics-mechanisms/src/drivetrain.ts:6

ShiftStatus interface

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

packages/physics-mechanisms/src/gearbox.ts:117

SpecPair interface

interface SpecPair
mn: number
z_in: number
z_out: number
beta: number
b: number

packages/physics-mechanisms/src/gearbox.ts:17

SpecSync interface

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

packages/physics-mechanisms/src/gearbox.ts:18

SyncUnit interface

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

packages/physics-mechanisms/src/gearbox.ts:79

Transaxle interface

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(): numberforward 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): voidclutch pedal 0 (up, engaged) .. 1 (down)

packages/physics-mechanisms/src/gearbox.ts:521

TransaxleOptions interface

interface TransaxleOptions
dt?: DrivetrainFile
gearbox?: GearboxOptions
flywheelJ?: numberengine flywheel inertia (kg·m²); peak torque and speed limit default to the spec's design torque and rpm limit
idleRpm?: number
wheelRadius?: numbervehicle: 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?: numberfriction torque of one brake at the wheel, N·m
clutchMargin?: numberclutch capacity as a multiple of the design torque
finalBacklash?: numbermesh backlash of the final drive, rad on the pinion (omit: none)

packages/physics-mechanisms/src/gearbox.ts:499

Types

CouplingKind type

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

packages/physics-mechanisms/src/drivetrain.ts:60

GearId type

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

packages/physics-mechanisms/src/gearbox.ts:13

MachineEvent type

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 }

packages/physics-mechanisms/src/drivetrain.ts:109

SoundEvent type

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 }

packages/physics-mechanisms/src/gearbox-life.ts:39

TorqueSource type

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

packages/physics-mechanisms/src/drivetrain.ts:33

Constants

BETZ const

const BETZ: number

Betz limit of a wind turbine's power coefficient.

packages/physics-mechanisms/src/turbines.ts:4

MACHINE_DEFAULTS const

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 }.

packages/physics-mechanisms/src/index.ts:19

STEEL_FLANK const

const STEEL_FLANK: FlankMaterial

packages/physics-mechanisms/src/drivetrain.ts:566