# @ferret/physics-vehicles: API

ships, submarines and balloons: hulls, ballast, flooding, thrusters, foils and sails.

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

## Classes

### Airship

*class* · `packages/physics-vehicles/src/airship.ts:86`

```ts
class Airship
```

- `readonly vessel: Vessel`
- `readonly spec: AirshipSpec`
- `readonly contract: AirshipContract`
- `readonly engines: Engine[]`
- `readonly cellIds: number[]`
- `readonly mooringAt: Vec3` — body-frame positions of the mooring point and the ground contacts
- `crash: Crash | null` — the first crash, or null: a hard landing (closing speed over 4 m/s) or the hull driven 2 m into the ground
- `elevator: number` — the elevator and rudder commands, -1..1 (positive: nose up, nose to starboard)
- `rudder: number`
- `helm: { pitch: number | null; heading: number | null }` — The helmsmen: with a target set, the elevator (pitch) or the rudder (heading, rad from +z toward +x) is driven by a PD law each sub-step, as the two helmsmen of the real ship did. The hull is about neutrally stable in pitch and yaw at cruise (the fin lift slope is tuned for that), so a ship left alone drifts slowly; with the helm held it is steady. Set a target to null to take the wheel.
- `ventedKg: number`
- `fuelBurnt: number` — the loads in kg: fuel burnt and ballast dropped so far
- `ballastDropped: number`
- `map(p: Vec3): Vec3` — A point of the model (X nose to tail, Y up, Z to starboard) in the vessel's body frame. The sign of x is chosen so that the model, as the Babylon glTF importer gives it (z flipped), turns into the body frame by a quarter turn about the vertical and not by a reflection: a mirror would be harmless for a ship symmetric about its centre plane, but the picture and the physics must agree on which engine car is where. (Body x is then the model's port side; the ship is symmetric, only the names say which is which.)
- `mapDir(p: Vec3): Vec3` — a direction of the model in the vessel's body frame
- `constructor(spec: AirshipSpec, contract: AirshipContract, o: AirshipOptions = {})`
- `telegraph(command: number, i?: number)` — Telegraph: -1 (full astern) .. 1 (full ahead) for engine i (0-based), or for all when i is omitted.
- `get cruiseCommand()` — the commanded share of the maximum shaft speed that gives the cruise power: (cruise_rpm / max_rpm), ahead
- `valve(id: number, open: boolean)` — Open or shut the manoeuvring valve of a cell (ids from 1, aft to fore); only cells with one respond.
- `dropBallast(i?: number)` — Drop the water of a bag (or of all bags) at its release rate.
- `dropShare(share: number)` — Drop a share of every bag's present load (0..1).
- `get ballastKg()`
- `get fuelKg()`
- `cellFill(id: number): number` — Gas in cell `id` as a share of the cell's volume now.
- `get heaviness(): number` — the heaviness now: the mass less the air the cells displace, in kg (positive: heavy, sinking)
- `get gasMassKg(): number` — the mass of the lifting gas in the cells, kg
- `moor(anchor: Vec3, length: number)`
- `unmoor()`
- `get moored()`
- `tension: number` — tension of the mooring line now, N
- `setGround(on: boolean)`
- `get position(): Vec3`
- `get altitude()` — altitude of the hull axis above sea level, m
- `get airVelocity(): Vec3` — velocity through the air in the body frame [starboard, up, bow], m/s
- `get airspeed()`
- `get groundSpeed()`
- `get climbRate()`
- `get heading()`
- `get pitch()` — pitch (nose up positive) and roll (starboard down positive), rad
- `get roll()`
- `get turnRate()` — yaw rate about the vertical, rad/s (positive: nose to starboard)
- `step(dt: number, h = 0.05)` — Advance by dt seconds in sub-steps of at most `h` s.
- `get groundLoad()` — Total weight on the ground, N (the sum of the contacts)
- `reset()` — Start a run: remember the loads for `ballastDropped`.

### Vessel

*class* · `packages/physics-vehicles/src/vessel.ts:154`

```ts
class Vessel
```

- `readonly spec: VesselSpec`
- `env: Environment`
- `pos: Vec3` — world position of the body origin, orientation, velocity of the centre of gravity, angular velocity (world)
- `q: Quat`
- `v: Vec3`
- `w: Vec3`
- `time: number`
- `readonly tanks: Tank[]`
- `readonly compartments: Comp[]`
- `readonly breaches: Array<BreachSpec & { Cd: number }>`
- `readonly envelopes: Env[]`
- `readonly thrusters: Thr[]`
- `readonly surfaces: Surf[]`
- `crushed: boolean`
- `dynamic: boolean` — step the dynamics; false holds the pose (to read the flooding or the forces alone)
- `onEvent: ((e: VesselEvent) => void) | null`
- `last: { buoyancy: number; weight: number; lift: number; submerged: number; }` — forces seen in the last step, for readouts
- `readonly doors: Array<DoorSpec & { open: boolean }>`
- `constructor(spec: VesselSpec, env: Environment = defaultEnvironment())`
- `mass()` — total mass, centre of gravity and principal inertia now (the body-frame centre the state follows is only moved by a step)
- `world(p: Vec3): Vec3` — world position of a body-frame point
- `body(v: Vec3): Vec3` — body-frame vector of a world vector
- `pointVelocity(p: Vec3): Vec3` — velocity of a body point in the world
- `hydrostatics(): Hydro` — Displaced volume, centre of buoyancy and the force of the water on the hull, from the cells against the surface.
- `get wetShare(): number` — Share of the hull volume under water.
- `get draft(): number` — Draft of the hull: the depth of its lowest point under the surface along the up direction (m).
- `get heel()` — heel (about the bow axis) and trim (about the beam axis) in radians; positive heel lowers the starboard side
- `get trim()`
- `get depth()` — pressure at the gauge, Pa, and the depth of the gauge under the surface, m
- `get pressure()`
- `get altitude()`
- `get total()`
- `stability(): { draft: number; volume: number; kb: number; kg: number; bm: number; gm: number; gmNumeric: number; freeSurface: number }` — Stability: draft, volume, KB, KG, BM = I/V and GM for a box hull, with the GM also found by heeling the hull a little.
- `freeSurfaceLoss(): number` — The metacentric height that free surfaces take: a part-filled compartment lets its water run to the low side as the vessel heels, which acts like a higher centre of gravity by rho_w i / m with i = length x beam^3 / 12 the second moment of its water plane (the formula of the free-surface correction). A full or empty compartment, or one with no `beam`, takes nothing.
- `metacentric(phi = 0.03): number` — GM from the righting arm at a small heel: GZ / sin φ with the draft re-found so that buoyancy equals weight.
- `tank(name: string)`
- `fill(name: string, fraction: number)`
- `blow(name: string)` — Blow the tank with compressed air: it empties (fast).
- `thruster(name: string)`
- `surface(name: string)`
- `envelope(name?: string)`
- `compartment(name: string)`
- `door(name: string)`
- `setDoor(name: string, open: boolean)` — Shut or open a watertight door.
- `breach(b: BreachSpec)`
- `lift(e: Env = this.envelopes[0]): number` — Lift of an envelope now: (ρ_air − ρ_gas)·V·g, N.
- `step(dt: number, sub = 1)`
- `windAt(p: Vec3): Vec3` — the air flow at a world point: the wind of the environment at that height plus the flow field
- `applyForce(f: Vec3, worldPoint?: Vec3)` — A force (N, world) at a world point, held for the step: every sub-step of it sees the force, then the list is cleared. Without a point it acts at the centre of gravity.
- `applyTorque(t: Vec3)` — A torque (N·m, world) held for the step.
- `applyImpulse(j: Vec3, worldPoint?: Vec3)` — An instant push (N·s, world) at a world point: changes the velocity and the angular velocity now.
- `clearExternal()` — Forget the forces and torques applied for the step (the capability does it after reading them).
- `forces(h: number): { F: Vec3; T: Vec3; m: { m: number; cog: Vec3; I: Vec3 } }` — The vessel's parts over a step of h: pumps, flooding and burners change the mass, then every force on the body is summed about the centre of gravity (weight included). The state is not moved; `step` integrates it itself, or a rigid-body kernel does (`adopt`).
- `adopt(pos: Vec3, q: Quat, v: Vec3, w: Vec3)` — Take the pose and the velocities from a body a kernel moves (the velocity of the centre of gravity, the angular velocity).
- `advanceClock(dt: number)` — After a kernel moved the body: the clock and the events.
- `get centreWorld(): Vec3` — world position of the centre of gravity

## Functions

### buildAirship

*function* · `packages/physics-vehicles/src/airship.ts:421`

```ts
function buildAirship(spec: AirshipSpec, contract: AirshipContract, o: AirshipOptions = {}): Airship
```

Build an airship from `spec.json` and `airship.json` (parsed).

### defaultEnvironment

*function* · `packages/physics-vehicles/src/vessel.ts:140`

```ts
function defaultEnvironment: (level?: number) => Environment
```

### discThrust

*function* · `packages/physics-vehicles/src/airship.ts:75`

```ts
function discThrust(p: number, u: number, rho: number, d: number): number
```

Thrust of an actuator disc of diameter d taking `p` watts from the shaft at flight speed u (m/s) in air of density rho: P = T (u/2 + sqrt(u²/4 + T/(2 rho A))).

### neutralFill

*function* · `packages/physics-vehicles/src/airship.ts:415`

```ts
function neutralFill(spec: AirshipSpec, contract: AirshipContract, altitude: number, mass = contract.mass.loaded_kg): number
```

The cell fill (a share of the volume at the pressure and temperature of `altitude`) at which the ship of `mass` kg is neutral with the
cells just full at that altitude; with that many moles at a lower altitude the cells are slack and the ship is neutral there too.

### sailPolar

*function* · `packages/physics-vehicles/src/vessel.ts:657`

```ts
function sailPolar(clAlpha: number, stall: number, cd0: number, k: number, alpha: number)
```

Force of a sail (a surface in the wind) along the boat's heading and across it, for an apparent wind at `beta` from the bow and the sail set at `alpha` to it.

### vehicles

*function* · `packages/physics-vehicles/src/index.ts:32`

```ts
function vehicles(): VehiclesCapability
```

## Interfaces

### AirshipContract

*interface* · `packages/physics-vehicles/src/airship.ts:26`

```ts
interface AirshipContract
```

- `cells: Array<{ id: number; volume_m3: number; centroid: Vec3 }>`
- `mass: { loaded_kg: number; centre: Vec3; groups: Array<{ name: string; kg: number; at: Vec3 }> }`
- `engines: { cars: Array<{ car: string; prop: string; at: Vec3 }> }`
- `surfaces: Array<{ node: string; fin: string; hinge_at: Vec3; hinge_axis: Vec3; max_deflection_deg: number }>`
- `mooring: { at: Vec3 }`

### AirshipOptions

*interface* · `packages/physics-vehicles/src/airship.ts:34`

```ts
interface AirshipOptions
```

- `altitude?: number` — altitude of the hull axis above sea level, m (default 600)
- `heading?: number` — heading of the bow, rad from the world +z toward +x
- `speed?: number` — speed through the air along the bow, m/s
- `fuel?: number` — the start state of the loads: fuel and ballast in kg (the design values by default) and the cell fill (the spec's start fill)
- `ballast?: number`
- `fill?: number`
- `env?: Environment`
- `ground?: boolean` — ground contacts and a mooring line
- `terrain?: (x: number, z: number) => number` — the ground height at (x, z) in metres; without it the ground is flat at the sea level. With it the hull itself is sampled and a hard touch is a crash.

### AirshipSpec

*interface* · `packages/physics-vehicles/src/airship.ts:16`

```ts
interface AirshipSpec
```

A rigid airship (LZ 129 and its kind) on top of `Vessel`: many gas cells, ballast bags and fuel as tanks, engines with a telegraph and
a propeller, four hinged fins, the air's added mass, the hull's aerodynamics (axial drag, Munk moment, cross-flow drag), a mooring line
and the ground. It reads two documents of `examples/zeppelin`: `spec/spec.json` (the design) and `build/airship.json` (the contract the
Blender model writes: cell volumes and centroids, mass groups, hinge lines). The model's axes are X nose to tail, Y up, Z to starboard;
the vessel's body axes are x starboard, y up, z bow, with the origin on the hull axis under the loaded centre of mass in x.

What is estimated rather than sourced: the added-mass coefficients, the cross-flow drag, the fin aspect ratio and the
flap effectiveness, the propeller efficiency split, the reverse-thrust share, the ground contacts.

- `hull: { length: number; diameter: number; xm_share: number; profile_exponent: number }`
- `cells: { count: number; valve_flow_m3s: number; list: Array<{ id: number; auto_valve: boolean; manoeuvre_valve: boolean }> }`
- `gas: { purity: number; start_fill: number; rho_air: number; rho_he: number }`
- `engines: { count: number; max_w: number; max_rpm: number; cruise_w: number; cruise_rpm: number; gear_ratio: number; sfc_kg_per_kwh: number; prop: { diameter: number; eta: number } }`
- `fins: Array<{ name: string; area: number; span: number; control_area: number; max_deflection_deg: number }>`
- `aero: { cd_volume: number; ref_area_m2: number; v_cruise: number; v_max: number }`
- `tanks: { fuel_capacity_kg: number; fuel_density: number; ballast_capacity_kg: number; ballast_bags: number }`
- `design: { payload_kg: number; fuel_kg: number; fuel_x: number; fuel_y: number; ballast_kg: number; bag_kg: number[]; bag_x: number[]; bag_y: number[] }`

### BreachSpec

*interface* · `packages/physics-vehicles/src/vessel.ts:31`

```ts
interface BreachSpec
```

- `name: string`
- `compartment: string`
- `at: Vec3`
- `area: number`
- `Cd?: number`

### CompartmentSpec

*interface* · `packages/physics-vehicles/src/vessel.ts:26`

```ts
interface CompartmentSpec
```

- `name: string`
- `volume: number`
- `at: Vec3`
- `area: number`
- `floor: number`
- `beam?: number`
- `slosh?: boolean | number` — let the water slosh across the beam as a motion: Housner's mass on a spring at the first mode, ω² = (π g / B) tanh(π h / B), with this damping ratio (0.03 when true)

### Crash

*interface* · `packages/physics-vehicles/src/airship.ts:72`

```ts
interface Crash
```

what the ship hit and how hard (set once: the first crash)

- `time: number`
- `speed: number`
- `what: string`
- `position: Vec3`

### DoorSpec

*interface* · `packages/physics-vehicles/src/vessel.ts:30`

```ts
interface DoorSpec
```

A door between two compartments: open, the water between them levels by Torricelli; shut, nothing passes. `at` is its sill in the body frame (the flow starts above it).

- `name: string`
- `a: string`
- `b: string`
- `at: Vec3`
- `area: number`
- `open?: boolean`
- `Cd?: number`

### EnvelopeSpec

*interface* · `packages/physics-vehicles/src/vessel.ts:32`

```ts
interface EnvelopeSpec
```

- `name: string`
- `kind: 'hot' | 'gas'`
- `volume: number` — m³, the full volume of the envelope
- `at: Vec3`
- `temperature?: number` — hot air: the temperature inside, K
- `moles?: number` — lighter gas: moles inside and kg/mol (it expands with height until the envelope is full, then vents)
- `molarMass?: number`
- `burner?: number` — burner power, W, and the lumped loss to the air, W/K
- `loss?: number`
- `vent?: number` — a vent that replaces this share of the hot air per second with ambient air
- `dragArea?: number` — projected area for the wind drag, m², and its coefficient
- `dragCd?: number`
- `dragLinear?: number` — linear damping against the air, N·s/m

### Environment

*interface* · `packages/physics-vehicles/src/vessel.ts:127`

```ts
interface Environment
```

- `surface: (x: number, z: number, t: number) => number` — the water surface height at (x, z, t)
- `waterDensity: number`
- `atmosphere: Atmosphere`
- `wind: (height: number) => Vec3` — wind velocity at a height
- `flow?: (p: Vec3) => Vec3` — extra air flow at a world point (the level's flow sources, `@ferret/flow`); added to `wind`
- `seaLevel: number` — the height of the ground/sea level that the atmosphere counts from

### HullSpec

*interface* · `packages/physics-vehicles/src/vessel.ts:16`

```ts
interface HullSpec
```

- `size: Vec3` — full size of the box hull
- `center?: Vec3` — the centre of the box in the body frame
- `cells?: [number, number, number]` — cells along each axis

### Hydro

*interface* · `packages/physics-vehicles/src/vessel.ts:152`

```ts
interface Hydro
```

- `volume: number`
- `centre: Vec3`
- `force: number`
- `waterline: number`

### SurfaceSpec

*interface* · `packages/physics-vehicles/src/vessel.ts:65`

```ts
interface SurfaceSpec
```

- `name: string`
- `at: Vec3`
- `area: number`
- `hinge: Vec3` — the hinge axis in the body frame
- `chord: Vec3` — direction of the chord from leading to trailing edge when undeflected
- `medium?: 'water' | 'air'`
- `clAlpha?: number` — lift slope per radian (2π·AR/(AR+2) for a finite foil)
- `stall?: number`
- `cd0?: number`
- `k?: number` — induced drag factor: Cd = cd0 + k·Cl²

### TankSpec

*interface* · `packages/physics-vehicles/src/vessel.ts:25`

```ts
interface TankSpec
```

- `name: string`
- `volume: number`
- `at: Vec3`
- `density?: number`
- `fill?: number`
- `rate?: number`

### ThrusterSpec

*interface* · `packages/physics-vehicles/src/vessel.ts:54`

```ts
interface ThrusterSpec
```

- `name: string`
- `at: Vec3`
- `axis: Vec3`
- `maxThrust: number`
- `medium?: 'water' | 'air'`
- `maxSpeed?: number` — speed along the axis at which the thrust is gone, m/s (Infinity = a constant thrust)
- `source?: (u: number) => number` — a machine supplies the thrust instead of the curve: (speed along the axis) → N

### VehiclesCapability

*interface* · `packages/physics-vehicles/src/index.ts:24`

```ts
interface VehiclesCapability extends Capability
```

- `readonly vessels: Map<string, VesselEntry>`
- `surface: Environment['surface'] | null` — A surface height other than the flat water level (a wave field of L2).
- `addVessel(name: string, spec: VesselSpec, entity?: Entity, opts?: { body?: boolean; material?: string }): Vessel` — `body: false` keeps the vessel on its own integrator even when the kernel has rigid bodies (it then meets nothing).

### VesselEntry

*interface* · `packages/physics-vehicles/src/index.ts:23`

```ts
interface VesselEntry
```

A vessel on a rigid-body kernel has a body there: Havok moves it and it meets the shore, a quay and other vessels.

- `vessel: Vessel`
- `entity?: Entity`
- `body?: Body`
- `mass?: number`
- `cog?: Vec3`

### VesselEvent

*interface* · `packages/physics-vehicles/src/vessel.ts:143`

```ts
interface VesselEvent
```

- `type: VesselEventType`
- `part?: string`
- `time: number`

### VesselSpec

*interface* · `packages/physics-vehicles/src/vessel.ts:82`

```ts
interface VesselSpec
```

- `mass: number`
- `cog?: Vec3` — centre of gravity of the dry vessel in the body frame, and its principal inertia about it
- `inertia: Vec3`
- `hull?: HullSpec`
- `tanks?: TankSpec[]`
- `compartments?: CompartmentSpec[]`
- `doors?: DoorSpec[]`
- `addedMass?: Vec3` — Added mass: the water the hull drags along when it accelerates, as a share of the water it displaces, per body axis (surge, heave, sway as x, y, z). About 0.05 to 0.2 along a slender hull, near 1 across a flat bottom. It slows the vessel's response and lowers the heave frequency, not its weight.
- `addedInertia?: Vec3` — Added moment of inertia: the water that turns with the hull, as a share per body axis (roll about z, yaw about y, pitch about x as the axes [x, y, z]) of the moment of the displaced water as a block of the hull's size, rho V_sub (b² + c²) / 12. About 0.3 to 1 in roll for a ship.
- `airAddedMass?: Vec3` — Added mass in air (an airship pushes a mass of air about with it, comparable to its own): kg per body axis at sea-level density (surge, heave, sway as x, y, z), scaled with the air density at the altitude. About k·ρ·V of the displaced air: k ≈ 0.05 along a slender hull, ≈ 0.9 across it.
- `airAddedInertia?: Vec3` — the air that turns with the hull, kg·m² per body axis at sea-level density (scaled the same way)
- `envelopes?: EnvelopeSpec[]`
- `thrusters?: ThrusterSpec[]`
- `surfaces?: SurfaceSpec[]`
- `position?: Vec3`
- `orientation?: Quat`
- `velocity?: Vec3`
- `crushDepth?: number` — a hull that breaks below this depth, m
- `hullDrag?: Vec3` — drag on the hull in the water: quadratic coefficient per axis (½ρ·Cd·A, N/(m/s)²) and linear damping (N·s/m), scaled by the submerged share
- `hullDamping?: Vec3`
- `angularDamping?: Vec3` — angular damping in the water, N·m·s/rad per axis, scaled by the submerged share
- `gravity?: number` — gravity on the vessel's own mass, m/s² (9.80665; zero holds a test vessel up)
- `gauge?: Vec3` — the point the depth gauge reads (body frame; the centre of gravity when missing)

## Types

### VesselEventType

*type* · `packages/physics-vehicles/src/vessel.ts:142`

```ts
type VesselEventType = 'breach' | 'flooded' | 'crushed' | 'surfaced' | 'submerged' | 'capsized'
```

## Constants

### AIRSHIP_ESTIMATES

*const* · `packages/physics-vehicles/src/airship.ts:53`

```ts
const AIRSHIP_ESTIMATES: { kAxial: number; kLateral: number; kRotation: number; cdCross: number; finAspect: number; finInterference: number; flapEffect: number; finStall: number; finCd0: number; propProfile: number; reverseShare: number; rpmRamp: number; }
```

estimated coefficients, one place

### G

*const* · `packages/physics-vehicles/src/vessel.ts:12`

```ts
const G: 9.80665
```

A vessel is one rigid body with parts: a hull that displaces liquid (cells against the water surface), ballast tanks, compartments that
flood through breaches, gas envelopes, thrusters, control surfaces and sails. It integrates its own six degrees of freedom (the light
kernel has no dynamic box and one scalar inertia), reads the water and the air, and reports the readouts a game needs: draft, heel,
trim, metacentric height, depth and buoyancy against weight.

Body axes: x to starboard, y up, z to the bow.

### R_UNIVERSAL

*const* · `packages/physics-vehicles/src/vessel.ts:13`

```ts
const R_UNIVERSAL: 8.314462618
```

### VEHICLES_DEFAULTS

*const* · `packages/physics-vehicles/src/index.ts:20`

```ts
const VEHICLES_DEFAULTS: { waterLevel: number; waterDensity: number; wind: Vec3; }
```

Assemblies of capability V: ships, submarines and balloons. A vessel is one body with parts (a hull, ballast tanks, compartments,
gas envelopes, thrusters, control surfaces and sails) that read the water and the air and write forces. This capability steps them
with the world, moves the scene node that shows each one, and answers the commands a game drives them with.

values (each at world / level / zone / entity scope):
  waterLevel    height of the water surface, m                   (0)
  waterDensity  kg/m³                                            (1000)
  wind          wind velocity at all heights, [x, y, z] m/s       ([0, 0, 0])

events: `vessel:breach`, `vessel:flooded`, `vessel:crushed`, `vessel:surfaced`, `vessel:submerged`, `vessel:capsized`, each { vessel, part? }.

