import React from 'react'; import type { Object3D } from 'three'; import { planetaryGearState, } from '../../../animations/mechanics'; import type { MachineAnimationModule } from '../../../animations/types'; import { BoltCircle, MachinePart, Shaft, ToothedGear, } from './primitives'; import { EngineeringBaseplate, PartLabels, getPartVisualProps, } from './proceduralSceneHelpers'; import type { ProceduralMachineDefinition, ProceduralMachineModule, ProceduralMachineSceneProps, } from './types'; const PLANET_COUNT = 3; const ORBIT_RADIUS = 1.08; const definition: ProceduralMachineDefinition = { id: 'planetary-gearbox', slug: 'planetary-gearbox', title: 'Planetary Gearbox', subtitle: 'Coaxial reduction with sun, planets, ring, and carrier', category: 'Gearboxes & Drives', difficulty: 'Intermediate', summary: 'A compact epicyclic gear train showing sun input, fixed ring gear, planet orbit, and reduced carrier output.', description: 'Planetary gearboxes pack high reduction ratios into a coaxial assembly. In this demonstration the sun gear is the input, the ring gear is fixed to the housing, and the planet carrier becomes the reduced-speed output shaft.', keywords: ['gearbox', 'planetary', 'epicyclic', 'gear ratio', 'reduction'], complexity: 7, dateAdded: '2025-02-04', typicalRpm: 'Input 500–6,000 RPM', facts: [ { label: 'Demo ratio', value: '4:1 reduction', detail: 'With 24 sun teeth and 72 ring teeth, the carrier speed is sun/(sun+ring) = 0.25× input.', }, { label: 'Architecture', value: 'Coaxial input/output', detail: 'The input and output shafts share the same centerline, valuable for compact transmissions.', }, { label: 'Load sharing', value: 'Three planets', detail: 'Multiple planets distribute tooth load and increase torque density.', }, { label: 'Common uses', value: 'Automatics, robotics, turbines', detail: 'Epicyclic stages are common in automatic transmissions, wheel hubs, and servo reducers.', }, ], parts: [ { id: 'sun-gear', name: 'Sun gear', description: 'Central input gear meshing with every planet gear.', material: 'Case-hardened steel', labelPosition: [0, 0.2, 0.78], engineeringNote: 'The sun gear often carries high speed and moderate torque.', }, { id: 'ring-gear', name: 'Ring gear', description: 'Internally toothed outer gear fixed in this reduction configuration.', material: 'Nitrided alloy steel', labelPosition: [-1.88, 1.12, 0.6], engineeringNote: 'Holding the ring stationary creates carrier speed reduction.', defaultOpacity: 0.74, }, { id: 'planet-carrier', name: 'Planet carrier', description: 'Rotating frame that supports planet pins and provides the reduced output.', material: 'Forged steel carrier', labelPosition: [1.6, 1.08, 0.72], }, { id: 'planet-gear-a', name: 'Planet gear A', description: 'One of three identical gears rolling between the sun and ring.', labelPosition: [1.28, 0.28, 0.72], }, { id: 'planet-gear-b', name: 'Planet gear B', description: 'Second planet gear sharing torque with the other planets.', labelPosition: [-1.02, 1.18, 0.72], }, { id: 'planet-gear-c', name: 'Planet gear C', description: 'Third planet gear completing the balanced carrier set.', labelPosition: [-0.9, -0.98, 0.72], }, { id: 'input-shaft', name: 'Input shaft', description: 'Shaft connected to the sun gear.', material: 'Splined steel shaft', labelPosition: [0, -1.7, 0.58], }, { id: 'output-shaft', name: 'Output shaft', description: 'Coaxial output connected to the planet carrier.', material: 'Splined steel shaft', labelPosition: [1.85, -0.82, 0.58], }, { id: 'housing', name: 'Housing', description: 'Stationary case that holds the ring gear and bearings.', material: 'Cast aluminium', labelPosition: [-2.05, -1.12, 0.55], defaultOpacity: 0.36, }, ], cameraPresets: [ { id: 'iso', label: 'Isometric', position: [3.8, 2.8, 4.4], target: [0, 0, 0], fov: 40 }, { id: 'front', label: 'Gear mesh', position: [0, 0, 5.4], target: [0, 0, 0], fov: 36 }, { id: 'side', label: 'Coaxial shafts', position: [4.6, 1.2, 2.2], target: [0, 0, 0], fov: 42 }, ], tour: { id: 'tour-planetary-gearbox', machineId: 'planetary-gearbox', title: 'See how an epicyclic reducer works', description: 'Follow torque from the sun gear through rolling planets to the slower carrier output.', steps: [ { id: 'sun-input', title: 'Sun gear input', body: 'The central sun gear is driven directly by the input shaft.', durationSeconds: 4, partIds: ['sun-gear', 'input-shaft'], camera: { position: [0.6, 1.4, 4.6], target: [0, 0, 0], duration: 1.1 }, rpm: 420, }, { id: 'planet-load-sharing', title: 'Planets share tooth load', body: 'Three planets roll between the sun and the fixed ring, splitting transmitted torque.', durationSeconds: 5, partIds: ['planet-gear-a', 'planet-gear-b', 'planet-gear-c'], camera: { position: [2.9, 2.4, 4.1], target: [0, 0, 0], duration: 1.1 }, rpm: 360, }, { id: 'ring-fixed', title: 'Fixed ring creates reduction', body: 'Because the ring cannot rotate, the planet carrier orbits much slower than the sun input.', durationSeconds: 5, partIds: ['ring-gear', 'housing', 'planet-carrier'], camera: { position: [-3.2, 2.1, 3.9], target: [0, 0, 0], duration: 1.1 }, rpm: 360, }, { id: 'carrier-output', title: 'Carrier is the output', body: 'The carrier output turns at one quarter of the input speed in this tooth-count example.', durationSeconds: 4, partIds: ['planet-carrier', 'output-shaft'], camera: { position: [4.2, 1.3, 2.2], target: [0.2, 0, 0], duration: 1.1 }, rpm: 420, }, ], }, relatedMachineIds: ['differential-gear', 'geneva-drive', 'ball-bearing'], }; function partProps( partId: string, props: ProceduralMachineSceneProps, explodeDirection: [number, number, number] = [0, 0, 0], ) { return { partId, registerPart: props.registerPart, explodeDirection, explodedDistance: props.explodedDistance ?? 0, onSelectPart: props.onSelectPart, onHoverPart: props.onHoverPart, ...getPartVisualProps(partId, props), }; } function setPlanetPose(object: Object3D | undefined, angle: number, spin: number): void { if (!object) return; object.position.set(Math.cos(angle) * ORBIT_RADIUS, Math.sin(angle) * ORBIT_RADIUS, 0); object.rotation.z = spin; } export const planetaryGearboxAnimation: MachineAnimationModule = { id: 'planetary-gearbox-fixed-ring', machineId: 'planetary-gearbox', label: 'Fixed-ring planetary reduction', version: '1.0.0', defaultRpm: 360, minRpm: 30, maxRpm: 1800, cycleRevolutions: 1, cycleSteps: 18, loop: true, supportsReverse: true, reducedMotionStrategy: 'slow', update(context) { const state = planetaryGearState(context.shaftAngle, 24, 72, 24); const sun = context.getPart('sun-gear'); const carrier = context.getPart('planet-carrier'); const input = context.getPart('input-shaft'); const output = context.getPart('output-shaft'); if (sun) sun.rotation.z = -state.sunAngle; if (carrier) carrier.rotation.z = -state.carrierAngle; if (input) input.rotation.z = -state.sunAngle; if (output) output.rotation.z = -state.carrierAngle; for (let index = 0; index < PLANET_COUNT; index += 1) { const baseAngle = (index / PLANET_COUNT) * Math.PI * 2; setPlanetPose( context.getPart(`planet-gear-${String.fromCharCode(97 + index)}`), baseAngle + state.planetOrbitAngle, state.planetSpinAngle - baseAngle, ); } context.setPhaseLabel(`Fixed-ring reduction — carrier output ${state.outputRatio.toFixed(2)}× input speed`); context.clearHighlights(); if (context.cycleProgress < 0.25) context.highlightParts(['sun-gear', 'input-shaft'], 0.75); else if (context.cycleProgress < 0.6) context.highlightParts(['planet-gear-a', 'planet-gear-b', 'planet-gear-c'], 0.75); else context.highlightParts(['planet-carrier', 'output-shaft'], 0.75); }, }; function PlanetGear({ id, props, index, }: { id: string; props: ProceduralMachineSceneProps; index: number; }): JSX.Element { const angle = (index / PLANET_COUNT) * Math.PI * 2; return ( ); } export function PlanetaryGearboxScene(props: ProceduralMachineSceneProps): JSX.Element { return ( {Array.from({ length: 72 }, (_, index) => { const angle = (index / 72) * Math.PI * 2; return ( ); })} {Array.from({ length: PLANET_COUNT }, (_, index) => { const angle = (index / PLANET_COUNT) * Math.PI * 2; return ( ); })} ); } export const planetaryGearbox: ProceduralMachineModule = { definition, animationModule: planetaryGearboxAnimation, Scene: PlanetaryGearboxScene, };