Files
ozone-tech_owl_prime/src/domain/physicalLayout.ts
root 3aad908aaf feat: engineering measurement architecture in 3D demo
- Stepper motor length measurement (step counting)
- Laser rangefinder height measurement
- Stereo camera width/shape analysis
- PLC decision logic with C-priority
- Actuator pusher animation
- Full measurement overlay with live data
2026-07-09 14:35:58 +02:00

164 lines
6.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Physical Layout — единый источник правды для размеров 3D сцены.
* Все размеры в метрах (1 Three.js unit = 1 meter).
*
* Reference: OZON Track 3 specification
* - Рабочая зона: 6000×10000 мм
* - Конвейер: ширина 500мм, высота 700мм
* - Скорость полотна: 1 м/с
*/
// =========================================================
// Workspace
// =========================================================
export const WORKSPACE_WIDTH_M = 6.0;
export const WORKSPACE_LENGTH_M = 10.0;
// =========================================================
// Conveyor dimensions (per OZON spec)
// =========================================================
export const CONVEYOR_WIDTH_M = 0.5; // 500mm belt width
export const CONVEYOR_HEIGHT_M = 0.7; // 700mm belt top surface from floor
export const CONVEYOR_SPEED_MPS = 1.0; // 1 m/s belt speed
export const CONVEYOR_LENGTH_M = 8.5; // Total belt length
// Belt structure
export const BELT_THICKNESS_M = 0.015; // 15mm belt thickness
export const BELT_TOP_Y = CONVEYOR_HEIGHT_M; // Top surface where items ride
export const BELT_BOTTOM_Y = CONVEYOR_HEIGHT_M - BELT_THICKNESS_M;
// Rollers (under/inside belt)
export const ROLLER_RADIUS_M = 0.04; // 40mm radius
export const ROLLER_DIAMETER_M = ROLLER_RADIUS_M * 2;
export const ROLLER_SPACING_M = 0.15; // 150mm between rollers
export const ROLLER_Y = BELT_BOTTOM_Y - ROLLER_RADIUS_M - 0.01; // Just below belt
// Frame structure
export const FRAME_HEIGHT_M = CONVEYOR_HEIGHT_M - BELT_THICKNESS_M - ROLLER_DIAMETER_M;
export const FRAME_WIDTH_M = 0.06; // 60mm frame profile
export const SIDE_GUARD_HEIGHT_M = 0.08; // 80mm side guards above belt
export const SIDE_GUARD_Y = BELT_TOP_Y + SIDE_GUARD_HEIGHT_M / 2;
// Support legs
export const LEG_WIDTH_M = 0.05; // 50mm square legs
export const LEG_SPACING_M = 2.0; // Every 2m
// =========================================================
// Motor drive
// =========================================================
export const MOTOR_WIDTH_M = 0.12; // 120mm motor body
export const MOTOR_HEIGHT_M = 0.15; // 150mm motor height
export const MOTOR_DEPTH_M = 0.08; // 80mm motor depth
export const DRIVE_ROLLER_RADIUS_M = 0.06; // 60mm drive roller
// =========================================================
// Zone positions (X axis = along conveyor, Z axis = lateral)
// Must be declared before other constants that reference it
// =========================================================
export const ZONES = {
/** Zone A - item spawn point (start of conveyor) */
A: { x: -4.0, z: 0, label: 'A' },
/** Camera/CV detection zone */
CAMERA: { x: -1.5, z: 0 },
/** Laser measurement zone */
LASER: { x: -0.5, z: 0 },
/** Gate/diverter position */
GATE: { x: 1.5, z: 0 },
/** Zone B - main sorter exit (end of main conveyor) */
B: { x: 4.0, z: 0, label: 'B' },
/** Zone C - oversized items (lateral) */
C: { x: 2.0, z: 2.0, label: 'C' },
/** Zone D - round items (lateral opposite) */
D: { x: 2.0, z: -2.0, label: 'D' },
} as const;
// =========================================================
// Stepper motor parameters (for length measurement)
// =========================================================
export const STEPPER_STEP_ANGLE_DEG = 1.8; // 1.8° per full step (200 steps/rev)
export const MICROSTEP_DIVISOR = 16; // 16x microstepping
export const STEPS_PER_REV = 360 / STEPPER_STEP_ANGLE_DEG * MICROSTEP_DIVISOR; // 3200 steps/rev
export const DRIVE_ROLLER_CIRCUMFERENCE_M = Math.PI * DRIVE_ROLLER_RADIUS_M * 2; // ~0.377m
export const MM_PER_STEP = (DRIVE_ROLLER_CIRCUMFERENCE_M * 1000) / STEPS_PER_REV; // ~0.118mm/step
// =========================================================
// Laser rangefinder
// =========================================================
export const LASER_HEIGHT_M = 1.15; // Laser mounted at 1.15m
export const LASER_POSITION_X = ZONES.CAMERA.x; // Co-located with camera
// =========================================================
// Stereo camera
// =========================================================
export const STEREO_CAMERA = {
baseline: 0.12, // 120mm between lenses
focalLength: 0.004, // 4mm focal length
fov: 60, // 60° field of view
mountY: 1.1, // Mounted at 1.1m
};
// =========================================================
// Measurement zone
// =========================================================
export const MEASUREMENT_ZONE = {
startX: ZONES.CAMERA.x - 0.4,
endX: ZONES.CAMERA.x + 0.4,
length: 0.8, // 800mm measurement zone
};
// =========================================================
// Roll cages (C/D destination bins)
// =========================================================
export const ROLL_CAGE = {
width: 1.2, // 1200mm
depth: 0.8, // 800mm
height: 0.8, // 800mm
};
// =========================================================
// Item positioning
// =========================================================
/**
* Calculate item Y position so it sits ON the belt surface.
* @param itemVisualHeight - Visual height of item mesh in meters
* @returns Y position for item center
*/
export function getItemYOnBelt(itemVisualHeight: number): number {
// Item center = belt top + half item height
return BELT_TOP_Y + itemVisualHeight / 2;
}
/**
* Get standard item Y for small/medium items.
* Most items are ~0.1-0.3m tall visually.
*/
export function getStandardItemY(): number {
const averageItemHeight = 0.15; // 150mm average
return getItemYOnBelt(averageItemHeight);
}
// =========================================================
// Camera rig
// =========================================================
export const CAMERA_RIG = {
height: 1.2, // 1.2m overhead frame
poleSpacing: 0.6, // Poles 0.6m apart (outside belt)
cameraY: 1.1, // Camera at 1.1m
};
// =========================================================
// Derived constants for legacy compatibility
// =========================================================
export const CONVEYOR_POSITIONS = {
spawnX: ZONES.A.x,
cameraX: ZONES.CAMERA.x,
laserX: ZONES.LASER.x,
gateX: ZONES.GATE.x,
zoneBX: ZONES.B.x,
zoneCZ: ZONES.C.z,
zoneDZ: ZONES.D.z,
beltY: BELT_TOP_Y,
itemOffsetY: 0.075, // Half of average item height
} as const;