FERRETGame engine over Babylon.js
Ferret

Rotors and blades

Package @ferret/physics-rotor, capability rotors, phase field. It reads the medium of physics-media (density and the flow, which includes the flow field) at the rotor, so wind, a mill race and a whirlpool drive it without any wiring.

A rotor#

"physics": {
  "capabilities": ["media", "rotors"],
  "rotors": [
    { "name": "sails", "shaft": "MillShaft", "axis": [0, 0, 1], "at": [0, 10, 0], "radius": 2,
      "elements": { "kind": "blade", "count": 3, "area": 0.18, "pitch": "6deg" } },
    { "name": "wheel", "node": "WheelHub", "axis": [1, 0, 0], "radius": 2.4, "medium": "water",
      "elements": { "kind": "paddle", "count": 16, "area": 0.5, "depth": 0.5 } },
    { "name": "overshot", "shaft": "FlumeShaft", "axis": [1, 0, 0], "radius": 2.4,
      "elements": { "kind": "bucket", "count": 12, "capacity": 5, "fill": { "angle": 0.5, "width": 0.3, "rate": 2 }, "empty": { "from": 3.5 } } }
  ]
}

A rotor names a shaft (a shaft of the drivetrain: it becomes one more torque source of that shaft, so gears, clutches, the load and the housing reaction all follow) and/or a node (a body: the thrust, the weight of the water and the reaction go to it). With a node and no shaft the rotor spins by itself: spin: { J, friction } is a free rotor (a windmill on a boat), spin: { speed } holds a speed (a driven propeller). axis and at are in the body's frame with a node, in the world without one. Angle 0 of the elements points up (default world up); a positive turn goes from up towards axis × up.

ElementForce from
bladeblade-element and momentum theory at the 0.7 R station: the flow along the axis and the speed give the angle of attack, lift and drag from a polar (clSlope, clMax, cd0, cdMax, or your own cl / cd functions); the induced flow and the tip loss are iterated, so the power never passes the Betz limit. pitch is the angle of the chord from the plane of rotation. Windmill sails, wind turbine, fan; a propeller is a blade pitched past the inflow angle (negative torque and thrust). induction: false turns the induced flow off (a propeller at the bollard)
paddlethe drag ½ρ·Cd·A·(v − ω·r)² of the immersed part of flat paddles, sampled at four points along each paddle's depth, in the local water: undershot wheel, paddle steamer
bucketthe weight of the water in each bucket: it fills at fill.angle (within width, rate kg/s, scaled by the rotor's command: a sluice) and pours from empty.from on: overshot wheel

model: "lumped" (blades only) is the cheap mode: the torque is windPower(Cp(λ)) / ω with lumped: { cpMax, peak, ct }, fitted to the elements (fitLumped) when you give none, or a propeller lumped: { kt, kq, diameter }.

Readouts and commands#

rotor.state { name? }: omega, theta, torque, power, thrust, force, tipSpeedRatio, flow (along the axis, against the rotor), cp, pitch, command, fill (kg per bucket). rotor.pitch { name, pitch } turns the blades (a windmill turned to the wind, a variable-pitch propeller), rotor.command { name, command } opens or shuts the sluice; editor: edit.physics.rotor.set | remove | list.

The blade actuator#

{ "name": "oar", "node": "Boat", "kind": "blade", "point": "Oarlock_L", "area": 0.12, "normal": [0, 0, 1], "stroke": { "dir": [0, 0, -1], "speed": 1 } }: a plate in the medium. The force comes from the plate's velocity against the local flow (plateForce: drag along the relative flow, lift across it); the profile drives the stroke (the plate moves relative to the body at speed × profile), not the force, so the same stroke gives less against the current. The kind is registered when @ferret/physics-rotor is loaded. How the stroke follows the oar's path and immersion comes with stage A7.

Not here#

Housing reactions of angle profiles (A10), the render of rotors (A9), the .ferret library build (M).