Spaces:
Running
Running
| import type { USBCalibrationManager } from './USBCalibrationManager.js'; | |
| import type { JointCalibration } from '../models.js'; | |
| import { ROBOT_CONFIG } from '../config.js'; | |
| export class CalibrationState { | |
| private manager: USBCalibrationManager; | |
| // Reactive state using Svelte 5 runes - direct state management | |
| private _isCalibrating = $state(false); | |
| private _progress = $state(0); | |
| private _isCalibrated = $state(false); | |
| private _needsCalibration = $state(true); | |
| private _jointValues = $state<Record<string, number>>({}); | |
| private _jointCalibrations = $state<Record<string, JointCalibration>>({}); | |
| constructor(manager: USBCalibrationManager) { | |
| this.manager = manager; | |
| // Initialize reactive state | |
| manager.jointNames_.forEach(name => { | |
| this._jointValues[name] = 0; | |
| this._jointCalibrations[name] = { isCalibrated: false }; | |
| }); | |
| // Subscribe to manager changes | |
| this.setupManagerSubscription(); | |
| // Initial state sync | |
| this.syncManagerState(); | |
| } | |
| // Reactive getters - now use internal reactive state | |
| get isCalibrating(): boolean { return this._isCalibrating; } | |
| get progress(): number { return this._progress; } | |
| get isCalibrated(): boolean { return this._isCalibrated; } | |
| get needsCalibration(): boolean { return this._needsCalibration; } | |
| get jointValues(): Record<string, number> { return this._jointValues; } | |
| get jointCalibrations(): Record<string, JointCalibration> { return this._jointCalibrations; } | |
| // Get current value for a specific joint | |
| getCurrentValue(jointName: string): number | undefined { | |
| return this._jointValues[jointName]; | |
| } | |
| // Get calibration for a specific joint | |
| getJointCalibration(jointName: string): JointCalibration | undefined { | |
| return this._jointCalibrations[jointName]; | |
| } | |
| // Get range for a specific joint | |
| getJointRange(jointName: string): number { | |
| const calibration = this._jointCalibrations[jointName]; | |
| if (!calibration?.minServoValue || !calibration?.maxServoValue) return 0; | |
| return Math.abs(calibration.maxServoValue - calibration.minServoValue); | |
| } | |
| private updateInterval: Timer | null = null; | |
| private managerUnsubscribe: (() => void) | null = null; | |
| private setupManagerSubscription(): void { | |
| // Use centralized config for UI update frequency | |
| this.updateInterval = setInterval(() => { | |
| this.syncManagerState(); | |
| }, ROBOT_CONFIG.polling.uiUpdateRate); // Centralized UI update rate | |
| // Also listen to manager calibration changes for immediate updates | |
| const unsubscribe = this.manager.onCalibrationChange(() => { | |
| console.debug('[CalibrationState] Manager calibration changed, syncing state'); | |
| this.syncManagerState(); | |
| }); | |
| // Store unsubscribe function for cleanup | |
| this.managerUnsubscribe = unsubscribe; | |
| } | |
| private syncManagerState(): void { | |
| // Sync manager state to reactive state | |
| this._isCalibrating = this.manager.calibrationState.isCalibrating; | |
| this._progress = this.manager.calibrationState.progress; | |
| this._isCalibrated = this.manager.isCalibrated; | |
| this._needsCalibration = this.manager.needsCalibration; | |
| // Update joint values and calibrations | |
| this.manager.jointNames_.forEach(name => { | |
| const currentValue = this.manager.getCurrentRawValue(name); | |
| if (currentValue !== undefined) { | |
| this._jointValues[name] = currentValue; | |
| } | |
| const calibration = this.manager.getJointCalibration(name); | |
| if (calibration) { | |
| // Create new object to ensure reactivity | |
| this._jointCalibrations[name] = { ...calibration }; | |
| } | |
| }); | |
| } | |
| // Cleanup method | |
| destroy(): void { | |
| if (this.updateInterval) { | |
| clearInterval(this.updateInterval); | |
| this.updateInterval = null; | |
| } | |
| if (this.managerUnsubscribe) { | |
| this.managerUnsubscribe(); | |
| this.managerUnsubscribe = null; | |
| } | |
| } | |
| // Format servo value for display | |
| formatServoValue(value: number | undefined): string { | |
| return value !== undefined ? value.toString() : '---'; | |
| } | |
| } |