diff --git a/HPPA/CaptureCoordinator.cpp b/HPPA/CaptureCoordinator.cpp index 95232f0..6d4b4b6 100644 --- a/HPPA/CaptureCoordinator.cpp +++ b/HPPA/CaptureCoordinator.cpp @@ -879,3 +879,96 @@ bool TwoMotor1PosCoordinator::checkArrival() { return m_xReached && m_yReached; } + + + + + + + + + + + + + + + +//--------------------------------------------------------------------------------------------------------------------------------------------- + +OneMotionCoordinator::OneMotionCoordinator(IrisMultiMotorController* motorCtrl, QObject* parent) + : QObject(parent) + , m_motorCtrl(motorCtrl) + , m_targetPosition(0) + , m_speed(0) + , m_actualPosition(0) + , m_isMoving(false) + , m_retryTimes(0) + , m_reached(false) +{ + connect(this, SIGNAL(moveTo(int, double, double, int)), m_motorCtrl, SLOT(moveTo(int, double, double, int))); + connect(m_motorCtrl, &IrisMultiMotorController::motorStopSignal, this, &OneMotionCoordinator::handlePositionReached); +} + +OneMotionCoordinator::~OneMotionCoordinator() +{ +} + +void OneMotionCoordinator::moveToTarget(double position, double speed) +{ + QMutexLocker locker(&m_dataMutex); + m_targetPosition = position; + m_speed = speed; + m_retryTimes = 0; + m_reached = false; + m_isMoving = true; + + qDebug() << "OneMotionCoordinator: moving to" << position; + emit moveTo(0, position, speed, 1000); +} + +void OneMotionCoordinator::handlePositionReached(int motorID, double position) +{ + if (!m_isMoving || motorID != 0) + { + return; + } + + QMutexLocker locker(&m_dataMutex); + m_actualPosition = position; + + double errorRate = getErrorRate(m_targetPosition, m_actualPosition); + + if (errorRate > 5 && m_retryTimes < m_retryLimit) + { + m_retryTimes++; + qDebug() << "OneMotionCoordinator: retry" << m_retryTimes << ", target:" << m_targetPosition << ", actual:" << m_actualPosition; + emit moveTo(0, m_targetPosition, m_speed, 1000); + return; + } + + m_retryTimes = 0; + m_reached = true; + m_isMoving = false; + + qDebug() << "OneMotionCoordinator: Arrived at" << m_actualPosition; + + emit sequenceComplete(0); + emit ArrivalSignal(m_actualPosition); +} + +double OneMotionCoordinator::getErrorRate(double targetLoc, double actualLoc) +{ + double targetLocTmp; + if (targetLoc == 0) + { + targetLocTmp = 0.001; + } + else + { + targetLocTmp = targetLoc; + } + double errorRate = abs(targetLoc - actualLoc) / targetLocTmp * 100; + + return errorRate; +} diff --git a/HPPA/CaptureCoordinator.h b/HPPA/CaptureCoordinator.h index 0a4a066..ebadd83 100644 --- a/HPPA/CaptureCoordinator.h +++ b/HPPA/CaptureCoordinator.h @@ -265,3 +265,38 @@ private: bool m_xReached; bool m_yReached; }; + +class OneMotionCoordinator : public QObject +{ + Q_OBJECT +public: + OneMotionCoordinator(IrisMultiMotorController* motorCtrl, QObject* parent = nullptr); + ~OneMotionCoordinator(); + +public slots: + void moveToTarget(double position, double speed); + +signals: + void sequenceComplete(int status); + void ArrivalSignal(double position); + void moveTo(int, double, double, int); + +private slots: + void handlePositionReached(int motorID, double position); + +private: + bool checkArrival(); + double getErrorRate(double targetLoc, double actualLoc); + + IrisMultiMotorController* m_motorCtrl; + mutable QMutex m_dataMutex; + + double m_targetPosition; + double m_speed; + double m_actualPosition; + bool m_isMoving; + + int m_retryLimit = 3; + int m_retryTimes; + bool m_reached; +}; diff --git a/HPPA/HPPA.cpp b/HPPA/HPPA.cpp index b5b2b6f..b581fde 100644 --- a/HPPA/HPPA.cpp +++ b/HPPA/HPPA.cpp @@ -659,6 +659,7 @@ void HPPA::initTimedDataCollection() m_tdc->setAttribute(Qt::WA_DeleteOnClose); m_tmc->connectMotor(false); + m_omc_LiftingPlatform->connectMotor(false); // 定时采集控制器 → 相机/马达 connect(m_tdc, &TimedDataCollection::hyperCamParm, this, &HPPA::setTimedDataCollectionHyperCamParm); @@ -667,7 +668,7 @@ void HPPA::initTimedDataCollection() connect(m_tdc, &TimedDataCollection::startRecordSignal, this, &HPPA::onStartTimedDataCollection); connect(m_tdc, &TimedDataCollection::ObtainingDepthInformationSignals, this, &HPPA::onObtainTargetDepthInformation); - + connect(m_tdc, &TimedDataCollection::switchHalogenLampSignal, m_pc3D, &PowerControl3D::switchHalogenLampPower); connect(m_tdc, &TimedDataCollection::switchD65LampSignal, m_pc3D, &PowerControl3D::switchD65LampPower); connect(m_tdc, &TimedDataCollection::switchSlrSignal, m_pc3D, &PowerControl3D::switchSlrPower); @@ -676,6 +677,11 @@ void HPPA::initTimedDataCollection() connect(m_tmc, &TwoMotorControl::sequenceComplete, m_tdc, &TimedDataCollection::subTaskCompleted); connect(m_tmc, &TwoMotorControl::back2OriginSignal_TimedDataCollection, m_tdc, &TimedDataCollection::onBack2Origin); + //升降台 + connect(m_tdc, &TimedDataCollection::LiftingPlatformSignals, this, &HPPA::onLiftingPlatform); + connect(m_omc_LiftingPlatform, &OneMotorControl_LiftingPlatform::sequenceComplete, m_tdc, &TimedDataCollection::subTaskCompleted); + connect(m_omc_LiftingPlatform, &OneMotorControl_LiftingPlatform::back2OriginSignal_TimedDataCollection, m_tdc, &TimedDataCollection::onBack2Origin); + m_tdc->show(); } @@ -779,6 +785,11 @@ void HPPA::onObtainTargetDepthInformation(SubTask subTaskParams) m_tmc->run4_ObtainTargetDepthInfo(m_depthCameraWindow, subTaskParams.depthType, subTaskParams.depthInfoX, subTaskParams.depthInfoY, subTaskParams.averageNumberOfTimes, subTaskParams.percentageOfEffectiveArea); } +void HPPA::onLiftingPlatform(SubTask subTaskParams) +{ + m_omc_LiftingPlatform->run(); +} + void HPPA::onTimedDataCollection() { QAction* checkedScenario = m_ScenarioActionGroup->checkedAction(); diff --git a/HPPA/HPPA.h b/HPPA/HPPA.h index 3205363..dddf433 100644 --- a/HPPA/HPPA.h +++ b/HPPA/HPPA.h @@ -451,6 +451,7 @@ public Q_SLOTS: void setTimedDataCollectionMotorParm(QString pathLineFilePath); void onStartTimedDataCollection(int camType); void onObtainTargetDepthInformation(SubTask subTaskParams); + void onLiftingPlatform(SubTask subTaskParams); void onStretchedImageReady(int fileNumber, const QString& filePath, QPixmap& pixmap); void onStretchProcessingError(int fileNumber, const QString& filePath, const QString& error); diff --git a/HPPA/OneMotorControl.cpp b/HPPA/OneMotorControl.cpp index dd255b2..a66ffa5 100644 --- a/HPPA/OneMotorControl.cpp +++ b/HPPA/OneMotorControl.cpp @@ -509,11 +509,20 @@ void OneMotorControl_LiftingPlatform::onxMotorStop() void OneMotorControl_LiftingPlatform::run() { - if (m_coordinator)//当高光谱相机停止采集后,马达还未回到原点时,上次任务的m_coordinator还没有被销毁 + m_coordinator = new OneMotionCoordinator(m_multiAxisController,this); + connect(m_coordinator, &OneMotionCoordinator::sequenceComplete, this, &OneMotorControl_LiftingPlatform::sequenceComplete); + connect(m_coordinator, &OneMotionCoordinator::ArrivalSignal, this, &OneMotorControl_LiftingPlatform::onBack2Origin); + + double plantDepthValue = DepthValueLogger::instance().readLatestPlantDepthValue(); + double liftingPlatformDepthValue = DepthValueLogger::instance().readLatestLiftingPlatformDepthValue(); + double targetDepth = liftingPlatformDepthValue - plantDepthValue; + + if (targetDepth < 0) { - onSequenceComplete(0); + return; } + m_coordinator->moveToTarget(targetDepth, ui.speed_lineEdit->text().toDouble()); } void OneMotorControl_LiftingPlatform::stop() @@ -521,17 +530,10 @@ void OneMotorControl_LiftingPlatform::stop() emit stopStepMotionSignal(); } -void OneMotorControl_LiftingPlatform::onSequenceComplete(int state) +void OneMotorControl_LiftingPlatform::onBack2Origin(double pos) { - emit sequenceComplete(); + emit back2OriginSignal_TimedDataCollection(); - disconnect(this, SIGNAL(start(OneMotionCapturePathLine)), m_coordinator, SLOT(startStepMotion(OneMotionCapturePathLine))); - disconnect(this, SIGNAL(stopStepMotionSignal()), m_coordinator, SLOT(stopStepMotion())); - disconnect(m_coordinator, SIGNAL(sequenceComplete(int)), this, SLOT(onSequenceComplete(int))); - - // Use deleteLater() instead of delete: this slot may have been called directly - // from OneMotionCaptureCoordinator's call stack (direct connection), so deleting - // the object here would cause a crash when execution returns to the destroyed object. m_coordinator->deleteLater(); m_coordinator = nullptr; } diff --git a/HPPA/OneMotorControl.h b/HPPA/OneMotorControl.h index db10314..1900363 100644 --- a/HPPA/OneMotorControl.h +++ b/HPPA/OneMotorControl.h @@ -11,6 +11,8 @@ #include "MotorWindowBase.h" #include "AppSettings.h" +#include "DepthValueLogger.h" + class OneMotorControl : public QDialog, public MotorWindowBase { Q_OBJECT @@ -106,7 +108,7 @@ public Q_SLOTS: void onxMotorLeft(); void onxMotorStop(); - void onSequenceComplete(int state); + void onBack2Origin(double pos); signals: void moveSignal(int, bool, double, int); @@ -121,7 +123,8 @@ signals: void start(OneMotionCapturePathLine); void stopStepMotionSignal(); - void sequenceComplete(); + void sequenceComplete(int status); + void back2OriginSignal_TimedDataCollection(); void broadcastLocationSignal(std::vector); @@ -131,7 +134,7 @@ private: QThread m_motorThread; IrisMultiMotorController* m_multiAxisController = nullptr; - QPointer m_coordinator; + QPointer m_coordinator; bool m_xMotorConnectionStatus = false; }; diff --git a/HPPA/TaskTreeModel.cpp b/HPPA/TaskTreeModel.cpp index ed978fa..73e8fa9 100644 --- a/HPPA/TaskTreeModel.cpp +++ b/HPPA/TaskTreeModel.cpp @@ -587,15 +587,17 @@ QString TaskTreeModel::statusToString(TaskStatus status) const QString TaskTreeModel::subTaskTypeToString(SubTaskType type) const { - switch (type) { - case SubTaskType::HyperSpectual400_1000nm: return QString::fromLocal8Bit("高光谱 400-1000nm"); - case SubTaskType::HyperSpectual1000_1700nm: return QString::fromLocal8Bit("高光谱 1000-1700nm"); - case SubTaskType::SingleLensReflex: return QString::fromLocal8Bit("单反相机"); - case SubTaskType::DepthCamera: return QString::fromLocal8Bit("深度相机"); - case SubTaskType::ObtainingDepthInformation: return QString::fromLocal8Bit("探测深度信息"); - case SubTaskType::AutoFocus: return QString::fromLocal8Bit("自动调焦"); + switch (type) + { + case SubTaskType::HyperSpectual400_1000nm: return QString::fromLocal8Bit("高光谱 400-1000nm"); + case SubTaskType::HyperSpectual1000_1700nm: return QString::fromLocal8Bit("高光谱 1000-1700nm"); + case SubTaskType::SingleLensReflex: return QString::fromLocal8Bit("单反相机"); + case SubTaskType::DepthCamera: return QString::fromLocal8Bit("深度相机"); + case SubTaskType::ObtainingDepthInformation: return QString::fromLocal8Bit("探测深度信息"); + case SubTaskType::AutoFocus: return QString::fromLocal8Bit("自动调焦"); + case SubTaskType::LiftingPlatform: return QString::fromLocal8Bit("升降平台"); } - return "未知类型"; + return QString::fromLocal8Bit("未知类型"); } QString TaskTreeModel::formatDuration(double minutes) const diff --git a/HPPA/TimedDataCollection.cpp b/HPPA/TimedDataCollection.cpp index cd2f10e..68531de 100644 --- a/HPPA/TimedDataCollection.cpp +++ b/HPPA/TimedDataCollection.cpp @@ -113,6 +113,7 @@ void TimedDataCollection::setupConnections() this, &TimedDataCollection::startRecordSignal); connect(m_scheduler, &TaskScheduler::ObtainingDepthInformationSignals, this, &TimedDataCollection::ObtainingDepthInformationSignals); + connect(m_scheduler, &TaskScheduler::LiftingPlatformSignals, this, &TimedDataCollection::LiftingPlatformSignals); connect(m_scheduler, &TaskScheduler::switchHalogenLampSignal, this, &TimedDataCollection::switchHalogenLampSignal); diff --git a/HPPA/TimedDataCollection.h b/HPPA/TimedDataCollection.h index 1e8775f..020b95b 100644 --- a/HPPA/TimedDataCollection.h +++ b/HPPA/TimedDataCollection.h @@ -53,6 +53,7 @@ Q_SIGNALS: void startRecordSignal(int camType); void ObtainingDepthInformationSignals(SubTask info); + void LiftingPlatformSignals(SubTask info); void switchHalogenLampSignal(int state); void switchD65LampSignal(int state); diff --git a/HPPA/TimedDataCollectionDataStructures.cpp b/HPPA/TimedDataCollectionDataStructures.cpp index 61fdbdf..7894a42 100644 --- a/HPPA/TimedDataCollectionDataStructures.cpp +++ b/HPPA/TimedDataCollectionDataStructures.cpp @@ -116,6 +116,7 @@ SubTaskType TimedDataCollectionDataStructuresReaderWriter::stringToSubTaskType(c if (str == "ObtainingDepthInformation") return SubTaskType::ObtainingDepthInformation; if (str == "AutoFocus") return SubTaskType::AutoFocus; + if (str == "LiftingPlatform") return SubTaskType::LiftingPlatform; return SubTaskType::SingleLensReflex; } @@ -479,6 +480,12 @@ void TaskExecutor::executeNextSubTask() //执行自动调焦任务 break; } + case SubTaskType::LiftingPlatform: + { + //执行升降平台任务 + emit LiftingPlatformSignals(subTask); + break; + } case SubTaskType::HyperSpectual400_1000nm: { m_camType = 0; @@ -721,6 +728,7 @@ void TaskScheduler::executeTask(TimedTask& task) this, &TaskScheduler::startRecordSignal); connect(m_currentExecutor, &TaskExecutor::ObtainingDepthInformationSignals, this, &TaskScheduler::ObtainingDepthInformationSignals); + connect(m_currentExecutor, &TaskExecutor::LiftingPlatformSignals, this, &TaskScheduler::LiftingPlatformSignals); connect(m_currentExecutor, &TaskExecutor::switchHalogenLampSignal, this, &TaskScheduler::switchHalogenLampSignal); connect(m_currentExecutor, &TaskExecutor::switchD65LampSignal, this, &TaskScheduler::switchD65LampSignal); diff --git a/HPPA/TimedDataCollectionDataStructures.h b/HPPA/TimedDataCollectionDataStructures.h index 84c0046..6e66b51 100644 --- a/HPPA/TimedDataCollectionDataStructures.h +++ b/HPPA/TimedDataCollectionDataStructures.h @@ -27,7 +27,8 @@ enum class SubTaskType { SingleLensReflex, // 单反相机 DepthCamera, // 深度相机采集任务 ObtainingDepthInformation, //通过深度相机获取被测物体的深度信息 - AutoFocus // 自动对焦 + AutoFocus, // 自动对焦 + LiftingPlatform // 升降平台 }; // ==================== 统一子任务封装 ==================== @@ -166,6 +167,7 @@ signals: void startRecordSignal(int camType); void ObtainingDepthInformationSignals(SubTask info); + void LiftingPlatformSignals(SubTask info); void switchHalogenLampSignal(int state); void switchD65LampSignal(int state); @@ -237,6 +239,7 @@ signals: void startRecordSignal(int camType); void ObtainingDepthInformationSignals(SubTask info); + void LiftingPlatformSignals(SubTask info); void switchHalogenLampSignal(int state); void switchD65LampSignal(int state); diff --git a/HPPA/TwoMotorControl.cpp b/HPPA/TwoMotorControl.cpp index a72c060..90596bd 100644 --- a/HPPA/TwoMotorControl.cpp +++ b/HPPA/TwoMotorControl.cpp @@ -222,7 +222,7 @@ void TwoMotorControl::run4_ObtainTargetDepthInfo(DepthCameraWindow* window, int connect(window->m_DepthCameraOperation, &DepthCameraOperation::DepthValueSignal, m_ObtainTargetDepthInfoCoordinator, &TwoMotor1PosCoordinator::back2origin); connect(window->m_DepthCameraOperation, &DepthCameraOperation::DepthValueSignal, this, &TwoMotorControl::sequenceComplete, Qt::UniqueConnection);//关灯 - connect(window->m_DepthCameraOperation, &DepthCameraOperation::DepthValueSignal, this, &TwoMotorControl::saveDepthValue, Qt::UniqueConnection);//控制白板平台升降 + connect(window->m_DepthCameraOperation, &DepthCameraOperation::DepthValueSignal, this, &TwoMotorControl::saveDepthValue, Qt::UniqueConnection); connect(m_ObtainTargetDepthInfoCoordinator, &TwoMotor1PosCoordinator::back2OriginSignal, this, &TwoMotorControl::onBack2Origin3);