#pragma once #include "fgc/Geometry.h" #include #include #include #include #include #include namespace fgc { class IMotorController; class IImuSource; // Live progress of a running calibration, for the TUI activity strip. struct CalibProgress { bool running = false; char axis = '?'; // 'Y' / 'P' int step = 0; // 1-based current step int total = 0; // steps per axis std::string phase; // "moving" / "dwelling" / "fitting" / ... }; // Structured outcome of the last completed calibration (persists for display). struct CalibReport { struct Axis { char axis = '?'; bool ok = false; double counts_per_deg = 0; long zero_count = 0; double r2 = 0; int n = 0; }; bool valid = false; long long ts_ms = 0; // wall-clock completion time (epoch ms) bool all_ok = false; std::vector axes; }; // `gimbal calib`: an IMU-referenced steps<->degrees calibration. Runs on its own // thread (the motor/imu/Logger interfaces are thread-safe), sweeping each axis // across its homed soft-limit travel in equal step intervals, dwelling at each to // record the IMU orientation, then least-squares fitting counts vs degrees. The // resulting Geometry is published via takeResult() for the main thread to apply // to the live session; the raw samples + fit are written to a logfile. Progress // is streamed to the LOG pane via LOG_INFO. Cancellable and one-at-a-time. class CalibrationRoutine { public: CalibrationRoutine(IMotorController& motor, IImuSource& imu, Geometry initial); ~CalibrationRoutine(); // Begin on a worker thread. Logs a reason and returns false if already // running (prechecks happen on the worker and abort there). bool start(); void cancel(); bool running() const { return running_.load(); } // If a finished run produced a new calibration, returns it once (then clears). std::optional takeResult(); // Live progress (thread-safe copy) and the last completed report (persists). CalibProgress progress() const; CalibReport report() const; private: void run(); void setProgress(char axis, int step, int total, const char* phase); IMotorController& motor_; IImuSource& imu_; Geometry initial_; std::thread thread_; std::atomic running_{false}; std::atomic cancel_{false}; mutable std::mutex result_mutex_; std::optional result_; CalibReport report_; mutable std::mutex progress_mutex_; CalibProgress progress_; }; } // namespace fgc