FERRETGame engine over Babylon.js
Ferret

@ferret/physics-rotor

blades, paddles and buckets around an axis turning wind and water into torque, and the blade actuator: a plate in a medium.

20 exports · source in packages/physics-rotor/src

Functions

bladeCp function

function bladeCp(r: BladeRotor, rho: number, U: number, lambda: number): number

The power coefficient of a blade rotor at the tip-speed ratio λ in a wind U: what the lumped mode is fitted to.

packages/physics-rotor/src/loads.ts:108

bladeLoads function

function bladeLoads(r: BladeRotor, rho: number, U: number, omega: number): BladeLoads

Blade-element and momentum theory at one station of the blades: the flow U along the axis and the speed ω give the angle of attack; the lift and drag turn into the torque and the thrust; the induced flow (a, a′) from momentum theory is iterated with the tip loss, so the power can never pass the Betz limit. Positive torque turns the rotor the way ω does (a turbine); a propeller (pitched past the inflow angle) gives negative torque and negative thrust. For the thrust sign U is taken as its magnitude: the caller turns the force to the flow.

packages/physics-rotor/src/loads.ts:68

fitLumped function

function fitLumped(r: BladeRotor, rho = 1.225, U = 8): { cpMax: number; peak: number }

Fit the lumped curve (cpCurve: a parabola with its peak at peak, height cpMax) to the element model by sweeping the tip-speed ratio.

packages/physics-rotor/src/loads.ts:114

frameOf function

function frameOf(axis: Vec3, up: Vec3): { a: Vec3; u: Vec3; t: Vec3 }

The in-plane frame of a rotor: radial reference u, the direction t = a × u that a positive turn moves towards.

packages/physics-rotor/src/loads.ts:124

plateForce function

function plateForce(W: Vec3, n: Vec3, rho: number, A: number, polar?: Polar): Vec3

The force of a flat plate of area A and unit normal n in a flow W relative to it (the fluid's velocity minus the plate's): drag along W, lift across it on the side the plate is hit from. At right angles it is the drag of a plate facing the flow; edge-on it is skin friction only.

packages/physics-rotor/src/loads.ts:37

polarAt function

function polarAt(p: Polar | undefined, alpha: number): { cl: number; cd: number }

Lift and drag coefficients at the angle of attack α (rad, any value): attached up to the stall, then falling to zero lift at 90°; the plate is symmetric.

packages/physics-rotor/src/loads.ts:21

rotors function

function rotors(): RotorsCapability

packages/physics-rotor/src/index.ts:124

strokePose function

function strokePose(o: OarStroke, time: number): StrokePose

packages/physics-rotor/src/stroke.ts:40

validateRotor function

function validateRotor(d: unknown, path = 'rotor'): string[]

packages/physics-rotor/src/index.ts:81

windAvailable function

function windAvailable: (rho: number, radius: number, U: number) => number

Power available in the wind through the disc, W.

packages/physics-rotor/src/loads.ts:105

Interfaces

BladeLoads interface

interface BladeLoads
thrust: number
torque: number
a: number
ap: number
phi: number
alpha: number
power: number

packages/physics-rotor/src/loads.ts:60

BladeRotor interface

interface BladeRotor
count: numbernumber of blades, rotor radius, hub radius (default 0.15 R) and the area of one blade
radius: number
hub?: number
area: number
pitch: numberangle of the chord from the plane of rotation, rad
station?: numberthe station along the blade the loads are taken at, as a share of the radius (0.7)
polar?: Polar
induction?: booleanswitch the induced flow off (a propeller at the bollard, a quick estimate)

packages/physics-rotor/src/loads.ts:49

BladeSpec interface

interface BladeSpec

The blade kind of actuator: a plate in a medium. area, normal (the body's frame) and a polar; the force comes from the plate's velocity against the local flow. The profile drives the plate's stroke, not the force: stroke: { dir, speed } moves the plate relative to the body at speed × profile (an oar sweeping through the water), so the same stroke gives less against the current.

area: number
normal?: Vec3
polar?: Polar
stroke?: { dir: Vec3; speed: number }
oar?: OarStroke

packages/physics-rotor/src/index.ts:374

OarStroke interface

interface OarStroke

The stroke of an oar: where the blade is, and how the plate faces, at a point of the cycle. The oar pivots at the oarlock (pivot, the body's frame); the blade is at the end of reach (from the pivot, at the middle of the sweep) turned about axis by an angle that goes arc[0] to arc[1] in the drive (a share drive of the cycle) and back in the recovery. In the recovery the blade is lifted out of the water along the axis by up to lift metres and the plate turns edge-on (feathered), so the same stroke pulls in the water and slips through the air. Immersion is not a number here: the force is read from the medium at the blade's place, so the lift decides it.

pivot: Vec3
reach: Vec3
axis: Vec3
arc: [number, number]angles of the sweep, rad: the blade is at arc[0] at the catch and at arc[1] at the finish
period: numberseconds of a whole stroke (drive + recovery)
drive?: numbershare of the cycle that is the drive (default 0.4)
lift?: numbermetres the blade is lifted along the axis at the middle of the recovery (default 0.25); it reaches it within a quarter of the recovery and holds it
feather?: booleanturn the plate edge-on in the recovery (default true)

packages/physics-rotor/src/stroke.ts:10

Polar interface

interface Polar

Pure load models of the plan and the blade kind of 3.2: no host, no world, so they are tested against the analytic values and reused by the capability and by anything that wants the numbers (a tool, a game's own rotor).

clSlope?: numberslope of the lift in the attached range, per rad (2π for a thin plate)
clMax?: numberthe lift at stall
cd0?: number
cdMax?: numberthe drag of a plate facing the flow
cl?: (alpha: number) => numbercode: your own curves, α in [0, π/2]; lift for the positive side (the polar is odd), drag even
cd?: (alpha: number) => number

packages/physics-rotor/src/loads.ts:7

RotorDef interface

interface RotorDef
name: string
node?: stringthe body the rotor sits on (reaction and thrust go to it), and/or the drivetrain shaft it turns
shaft?: string
axis: Vec3the axis: in the body's frame with a node, in the world without one
at?: Vec3the centre, in the body's frame (with a node) or the world
up?: Vec3the direction radial angle 0 points to (default up)
radius: number
medium?: 'air' | 'water'
model?: 'elements' | 'lumped'
elements: { kind: RotorElementKind; count: number; /** blade, paddle: area of one element, m² */ area?: number; /** blade: pitch of the chord from the plane of rotation (rad or "5deg"), hub radius, station, polar, induction */ pitch?: number | string; hub?: number; station?: number; polar?: Polar; induction?: boolean; /** paddle: how far in from the rim the paddle reaches (m), drag coefficient */ depth?: number; cd?: number; /** bucket: capacity in kg of water; filled by `fill`, emptied from the angle `empty.from` on */ capacity?: number; fill?: { angle: number; width: number; rate: number }; empty?: { from: number; rate?: number }; }
lumped?: { cpMax?: number; peak?: number; ct?: number; kt?: number; kq?: number; diameter?: number }lumped mode: a turbine { cpMax, peak, ct } (fitted from the elements with fitLumped when missing) or a propeller { kt, kq, diameter }
spin?: { J?: number; friction?: number; speed?: number | string; theta?: number }a rotor on a body with no shaft spins by itself: inertia, bearing friction (N·m·s), or a held speed (rad/s or "300rpm") of a driven rotor
command?: number0..1 multiplier of the water flow into the buckets (a sluice)

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

RotorsCapability interface

interface RotorsCapability extends Capability
readonly rotors: Map<string, RotorState>
set(def: RotorDef): void
remove(name: string): void
list(): RotorDef[]
state(name?: string): RotorState | RotorState[]
pitch(name: string, value: number | string): void
command(name: string, value: number): void
useDrivetrain(train: Drivetrain): voida drivetrain whose shafts rotors can turn
addTarget(node: string, target: ForceTarget): voida body that is not a RigidBody (a vessel) for rotors naming node

packages/physics-rotor/src/index.ts:64

RotorState interface

interface RotorState
name: string
omega: number
theta: number
torque: number
power: number
thrust: number
force: Vec3
tipSpeedRatio: numbertip speed over the wind along the axis (blades)
flow: numberthe flow along the axis against the rotor, m/s, and the power coefficient (blades)
cp: number
pitch: number
command: number
fill: number[]
error?: string

packages/physics-rotor/src/index.ts:54

StrokePose interface

interface StrokePose
at: Vec3the blade in the body's frame, and the unit normal of the plate there
normal: Vec3
raised: number0 in the drive, up to 1 at the middle of the recovery
phase: numberthe cycle position 0..1 and whether the blade is in the drive
driving: boolean

packages/physics-rotor/src/stroke.ts:24

Types

RotorElementKind type

type RotorElementKind = 'blade' | 'paddle' | 'bucket'

rotors. N blades, paddles or buckets around an axis, on a body or on a drivetrain shaft, summed into one torque (and a force) each step without a body per element:

  blade   blade-element and momentum theory in the local flow (windmill sails, wind turbine, propeller, fan), or a lumped curve fitted to it
  paddle  the drag of the immersed part of flat paddles in the local water (undershot wheel, paddle steamer)
  bucket  the weight of the water in buckets filled at one angle and emptied at another (overshot wheel)

Also here: the blade kind of actuator, a plate in a medium whose stroke is driven by the profile (an oar).

packages/physics-rotor/src/index.ts:18