import React from 'react'; import { discBrakeState, } from '../../../animations/mechanics'; import type { MachineAnimationModule } from '../../../animations/types'; import { MachinePart, Shaft, } from './primitives'; import { EngineeringBaseplate, PartLabels, getPartVisualProps, } from './proceduralSceneHelpers'; import type { ProceduralMachineDefinition, ProceduralMachineModule, ProceduralMachineSceneProps, } from './types'; const definition: ProceduralMachineDefinition = { id: 'disc-brake-caliper', slug: 'disc-brake-caliper', title: 'Disc Brake Caliper', subtitle: 'Hydraulic clamping and friction heat generation', category: 'Structural / Other', difficulty: 'Beginner', summary: 'A floating disc brake caliper showing piston extension, pad clamp, rotor deceleration, and heat band.', description: 'Disc brakes convert kinetic energy into heat through friction. Hydraulic pressure moves the piston and pads against the rotor, generating braking torque proportional to clamp force and friction coefficient.', keywords: ['brake', 'caliper', 'rotor', 'hydraulic', 'friction', 'heat'], complexity: 5, dateAdded: '2025-02-04', typicalRpm: 'Wheel speed dependent', facts: [ { label: 'Energy conversion', value: 'Kinetic energy → heat', detail: 'Brake components must absorb and reject heat without fade or cracking.', }, { label: 'Actuation', value: 'Hydraulic piston', detail: 'Fluid pressure multiplies pedal force into clamp force at the pads.', }, { label: 'Friction pair', value: 'Pad against iron/steel rotor', detail: 'Pad compound affects bite, noise, dust, wear, and temperature range.', }, { label: 'Thermal design', value: 'Ventilation and mass', detail: 'Rotor vanes, diameter, and thickness set thermal capacity and cooling.', }, ], parts: [ { id: 'rotor', name: 'Brake rotor', description: 'Rotating disc clamped by pads to create braking torque.', material: 'Cast iron / carbon ceramic', labelPosition: [-0.9, 0.8, 0.86], }, { id: 'hub', name: 'Wheel hub', description: 'Central mounting boss tying the rotor to the wheel bearing and axle.', material: 'Steel / aluminium', labelPosition: [-0.98, -0.75, 0.72], }, { id: 'caliper-body', name: 'Caliper body', description: 'Bridge structure carrying hydraulic piston and pad reaction loads.', material: 'Cast aluminium / iron', labelPosition: [1.35, 0.85, 0.78], }, { id: 'inner-pad', name: 'Inner brake pad', description: 'Friction material pressed against the inboard rotor face.', labelPosition: [0.52, -0.98, 0.84], }, { id: 'outer-pad', name: 'Outer brake pad', description: 'Friction material pressed against the outboard rotor face.', labelPosition: [1.45, -0.55, 0.84], }, { id: 'piston', name: 'Hydraulic piston', description: 'Piston extending under brake fluid pressure to move the inner pad.', labelPosition: [1.68, 0.18, 0.84], }, { id: 'brake-line', name: 'Brake line', description: 'Hydraulic feed supplying pressurized fluid to the caliper.', labelPosition: [2.1, 1.28, 0.78], }, { id: 'heat-band', name: 'Heat band', description: 'Warm glow showing friction heating on the swept area of the rotor.', labelPosition: [-0.15, 1.28, 0.82], defaultOpacity: 0.42, }, ], cameraPresets: [ { id: 'iso', label: 'Isometric', position: [3.7, 2.5, 4.0], target: [0, 0, 0], fov: 42 }, { id: 'front', label: 'Rotor face', position: [0, 0.4, 5.3], target: [0, 0, 0], fov: 38 }, { id: 'caliper', label: 'Caliper clamp', position: [4.0, 1.4, 2.8], target: [0.45, 0, 0], fov: 42 }, ], tour: { id: 'tour-disc-brake-caliper', machineId: 'disc-brake-caliper', title: 'Hydraulic braking in one clamp cycle', description: 'Watch pressure build, pads close, friction heat rise, and pressure release.', steps: [ { id: 'rotor', title: 'Rotor spins with the wheel', body: 'The rotor is fixed to the hub and carries wheel kinetic energy.', durationSeconds: 4, partIds: ['rotor', 'hub'], camera: { position: [-2.6, 1.5, 4.0], target: [0, 0, 0], duration: 1.1 }, rpm: 220, }, { id: 'pressure', title: 'Hydraulic pressure extends the piston', body: 'Brake fluid pressure moves the piston and forces the inner pad toward the rotor.', durationSeconds: 4.5, partIds: ['brake-line', 'piston', 'inner-pad'], phaseRange: [0.18, 0.42], camera: { position: [3.4, 1.6, 3.3], target: [0.55, 0, 0], duration: 1.1 }, rpm: 180, }, { id: 'clamp', title: 'Pads clamp both faces', body: 'The caliper bridge reacts the force so both pads squeeze the disc and create braking torque.', durationSeconds: 5, partIds: ['caliper-body', 'inner-pad', 'outer-pad', 'rotor'], phaseRange: [0.43, 0.7], camera: { position: [4.1, 1.2, 2.6], target: [0.35, 0, 0], duration: 1.1 }, }, { id: 'heat', title: 'Friction becomes heat', body: 'The swept rotor band heats rapidly under clamp load, so ventilation and material matter.', durationSeconds: 4, partIds: ['heat-band', 'rotor'], phaseRange: [0.54, 0.86], camera: { position: [0.8, 1.7, 4.7], target: [0, 0, 0], duration: 1.1 }, }, ], }, relatedMachineIds: ['ball-bearing', 'differential-gear', 'four-stroke-petrol-engine'], }; 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), }; } export const discBrakeCaliperAnimation: MachineAnimationModule = { id: 'disc-brake-hydraulic-clamp', machineId: 'disc-brake-caliper', label: 'Hydraulic clamp and heat cycle', version: '1.0.0', defaultRpm: 220, minRpm: 5, maxRpm: 1500, cycleRevolutions: 1, cycleSteps: 16, loop: true, supportsReverse: true, reducedMotionStrategy: 'slow', update(context) { const state = discBrakeState(context.shaftAngle, context.cycleProgress); const rotor = context.getPart('rotor'); if (rotor) rotor.rotation.z = -state.rotorAngle; const hub = context.getPart('hub'); if (hub) hub.rotation.z = -state.rotorAngle; const innerPad = context.getPart('inner-pad'); if (innerPad) innerPad.position.z = -0.24 + state.padTravel; const outerPad = context.getPart('outer-pad'); if (outerPad) outerPad.position.z = 0.24 - state.padTravel; const piston = context.getPart('piston'); if (piston) { piston.position.z = -0.48 + state.padTravel * 0.95; piston.scale.z = 1 + state.brakePressure * 0.18; } const brakeLine = context.getPart('brake-line'); if (brakeLine) brakeLine.scale.setScalar(1 + state.brakePressure * 0.04); const heatBand = context.getPart('heat-band'); if (heatBand) { heatBand.scale.setScalar(1 + state.heat * 0.03); heatBand.rotation.z = -state.rotorAngle * 0.88; } context.setPartOpacity('heat-band', 0.12 + state.heat * 0.78); context.setPhaseLabel( state.brakePressure > 0.15 ? `Brake pressure ${Math.round(state.brakePressure * 100)}% — pads clamping rotor` : 'Released — rotor spinning freely between pads', ); context.clearHighlights(); if (state.brakePressure > 0.15) context.highlightParts(['piston', 'inner-pad', 'outer-pad', 'heat-band'], 0.9); else context.highlightParts(['rotor', 'hub'], 0.65); }, }; export function DiscBrakeCaliperScene(props: ProceduralMachineSceneProps): JSX.Element { return ( {Array.from({ length: 18 }, (_, index) => { const angle = (index / 18) * Math.PI * 2; return ( ); })} ); } export const discBrakeCaliper: ProceduralMachineModule = { definition, animationModule: discBrakeCaliperAnimation, Scene: DiscBrakeCaliperScene, };