# Machines

# Machines

Package `@ferret/physics-mechanisms`, capability `machine`.

## What it is for

Use it wherever something turns something else: a car's gearbox and differential, a crane winch with a brake, a windmill driving a millstone, a paddle wheel that sweeps crates off a belt, a turbine feeding a generator. The capability does not make torque by itself. Engines come from combustion (skill `ferret`), generators and motors from electric (skill `ferret-physics-electric`). Machines is what connects them to loads, and what decides how fast everything ends up turning.

## How to think about it

A machine is a small network. The nodes are **shafts**: each one spins at one speed and has inertia, so it takes time to speed up. The links are **couplings** that force a relation between two speeds: a gear pair makes them proportional, a clutch makes them equal while it grips, a brake pins one to zero.

Torque is added by **drivers**: a motor, an engine, a turbine, or a load, which is just a negative driver. Every step the network works out the speed each shaft must have so that all couplings are satisfied at once. This is exact even for stiff ratios, so a 1:100 reduction does not wobble.

Nothing is free. Each gear mesh passes on only part of the torque (its efficiency); the rest turns into heat, and the network keeps the account. Work done by drivers equals what the loads took, plus losses, plus what the shafts store as spin. A page of numbers that does not add up is a sign something is wrong with the setup.

## Choosing a coupling

| You want | Use | What it does |
|---|---|---|
| Gears with a fixed ratio | `gear` | speeds in proportion to the tooth counts, direction reversed; efficiency, backlash and a breaking limit are optional |
| A big reduction that cannot be back-driven | `worm` | self-locks when the thread angle is shallow enough: the load cannot turn the motor |
| A belt or chain | `belt` | same direction; a belt slips when overloaded, a chain does not |
| Compact gear sets | `planetary` | one carrier shaft, driven by the sun and the ring together |
| Two wheels on one axle | `differential` | the cage gets the average speed; both outputs get the same torque |
| A shaft that bends | `cardan` | a universal joint; two in phase cancel the speed ripple |
| A motor with a set speed | `speed` | an ideal motor: holds a shaft at a given speed whatever the load |
| Engage and disengage | `clutch` | locks when the plates stick; slips when the load asks for more than its capacity |
| Stop a shaft | `brake` | holds when its command is 1 |
| One-way drive | `freewheel` | the output may turn faster than the input, never the other way |

Clutches and brakes take a **command** between 0 and 1: the pedal or lever position. A brake starts released and a clutch starts engaged, which is the usual surprise when "nothing moves".

## Using it

```ts
import { Drivetrain } from '@ferret/physics-mechanisms';

const train = new Drivetrain();
const motorShaft = train.shaft({ name: 'in', J: 0.1 });
const wheel = train.shaft({ name: 'out', J: 0.5, b: 0.5 });   // J: inertia, b: drag that grows with speed
train.speed('motor', motorShaft, () => 10);                     // 10 rad/s
train.gear('mesh', motorShaft, wheel, 20, 40, { efficiency: 0.95 });
train.step(1 / 240);
```

A reduction of 20 teeth to 40 turns the wheel at half the motor's speed, in the other direction, with about twice the torque less the losses.

In a game you hand the drive train to the capability, so it advances with the world:

```ts
import { machines } from '@ferret/physics-mechanisms';

const host = world.addService(new PhysicsHost({ capabilities: [machines(train)] }));
host.enable('machine');
```

## Connecting to the scene

- **A mesh that turns.** Give the shaft a `node` name and `axis`: the scene node of that name rotates with the shaft. Wheels, fans, gauges.
- **A paddle, a turntable, a crane jib** (`bind`). The shaft turns a *kinematic* body around a pivot. What the world does back to the body, such as a crate in the way, comes back as a load on the shaft, so a paddle slows when it pushes something and the motor stalls when it jams.
- **A free wheel** (`couple`). The shaft turns a *dynamic* body held on its axis, through a viscous coupling. The body keeps its momentum, and the shaft slips against a load it cannot move.

## What drives and what loads

- A motor, engine or load is a `drive(shaft, fn)` where `fn(omega, angle, time)` returns a torque. A load is a negative number.
- Wind and water turbines are drivers: `windTurbine` takes the radius and a wind speed, `waterTurbine` takes flow and head. Both obey the physical limits: no wind turbine can pull more than 59 % of the wind's power (Betz), and a water turbine delivers `efficiency × density × gravity × flow × head`.
- Pumps, fans and compressors are loads (`pumpLoad`): the shaft pays flow times pressure rise divided by efficiency.
- `propeller` gives thrust and a torque load from speed.
- A piston engine from combustion (skill `ferret`) plugs in as `drive(crank, (w, th) => engine.torque(w, th))`. Give the crank a flywheel inertia (`J` of 0.1 to 0.2) so the speed does not jerk with every stroke.

## Things that break

A gear with a `limit`, or a shaft with a `diameter` and `shear` strength, breaks when the torque passes it. A broken part simply stops transmitting, and the event `machine:break { element, torque }` says which. `lewisForce` gives the bending limit of a tooth from its material, module and width; `toothContactPressure` and `STEEL_FLANK` do the same for surface wear.

Backlash leaves a gap between teeth where nothing is transmitted; closing it at speed loses the energy of the knock.

A motor with a driver that sits below `stall.speed` for `stall.time` seconds raises `machine:stall`. A clutch starting or stopping slipping raises `machine:slip`; the heat of the slip is in the coupling's `loss`, and `slipHeats` in links (skill `ferret-physics-links`) turns it into heat in a housing.

## Parameters

| Value | Default | Effect |
|---|---|---|
| `substeps` | 4 | solver steps per world step; raise it for very stiff chains |
| `stall` | speed 0.05, torque 1, time 0.5 | what counts as a stall |

## Commands

`machine.info`, `machine.set { element, command }`, `machine.state` (speeds, torques, energy), `machine.step { dt, substeps? }`.

`machine.set` also takes an object for an element with a model (`{ element: "gearbox", command: { gear: 3 } }`) and names a control that is not a coupling (`throttle`, `brake`); `machine.state` adds `models` and `controls`. A manual gearbox is described in gearbox (skill `ferret`).

## Cost

Each substep solves a dense system the size of the number of couplings. Dozens of machines are cheap. Hundreds of couplings in one drive train get expensive; keep independent machines in separate `Drivetrain`s.

## When it does not behave

| Symptom | Cause |
|---|---|
| The output does not move | a brake is on (`command` 1), or the motor drives the wrong shaft |
| A shaft spins up without bound | no load and no friction: give it `b` |
| A clutch never locks | its capacity is below the torque it must carry, so it slips by design |
| Everything shakes | a very large inertia ratio across a gear at a coarse step; raise `substeps` |
| `bind` throws | the body is not kinematic; use `couple` for dynamic bodies |
| `machine:stall` on a shaft you did not expect | it has a driver and sits still for `stall.time`; a shaft without a driver never stalls |

Worked scenarios with numbers (gearbox, planetary set, differential, clutch, breaking gear, turbines) are in the tests: `tests/unit/examples/physics-mechanisms.test.ts`.

## Speed sources and housings

`train.speedSource(name, shaft, { speed, ramp })` makes a shaft of infinite inertia that sets its own speed (a water-wheel axle, a motor on a governor). Gears, belts and clutches behind it still carry real torques, so a gear can strip and a clutch can slip while the source keeps turning. `src.setSpeed(w, ramp)` goes to a new speed along a linear ramp; `src.torque` and `src.power` read what it delivers.

A shaft can name a `housing` (an object with `torque(vector, dt)`): whatever changes the shaft's angular momentum (a motor, a load through a gear, friction) puts the opposite torque on the housing, once per step, as the mean of that step along the shaft's axis. The capability that owns the housing body turns it into `kernel.applyTorque`. A shaft without a housing is fixed to the world. The shaft's speed is relative to the housing; the housing's own turning does not feed back into it.

## Reference

`machines`, `Drivetrain`, `Shaft`, `Coupling`, `windTurbine`, `waterTurbine`, `gasPower`, `pumpLoad`, `propeller`, `lewisForce`.
