diff --git a/HPPA/DepthCameraWindow.cpp b/HPPA/DepthCameraWindow.cpp index 4e7a4f4..e9ceb06 100644 --- a/HPPA/DepthCameraWindow.cpp +++ b/HPPA/DepthCameraWindow.cpp @@ -41,11 +41,21 @@ void DepthCameraWindow::onSelectDataFolder() QString::fromLocal8Bit("选择数据保存路径"), ui.dataFolderLineEdit->text()); - if (!dir.isEmpty()) - { - ui.dataFolderLineEdit->setText(dir); - AppSettings::instance().setDepthCameraDataFolder(dir); - } + setDataFolder(dir); +} + +void DepthCameraWindow::setDataFolder(QString dir) +{ + if (!dir.isEmpty()) + { + ui.dataFolderLineEdit->setText(dir); + AppSettings::instance().setDepthCameraDataFolder(dir); + } +} + +void DepthCameraWindow::setCaptureInterval(int captureIntervalSeconds) +{ + m_DepthCameraOperation->setCaptureInterval(captureIntervalSeconds); } void DepthCameraWindow::openDepthCamera() @@ -83,6 +93,8 @@ DepthCameraOperation::DepthCameraOperation() m_pipe = nullptr; m_func = nullptr; record = false; + + m_captureIntervalMilliseconds = 3000; } DepthCameraOperation::~DepthCameraOperation() @@ -96,6 +108,11 @@ DepthCameraOperation::~DepthCameraOperation() } } +void DepthCameraOperation::setCaptureInterval(int captureIntervalSeconds) +{ + m_captureIntervalMilliseconds = captureIntervalSeconds * 1000; +} + void DepthCameraOperation::OpenDepthCamera() { if (m_pipe) @@ -142,14 +159,14 @@ void DepthCameraOperation::OpenDepthCamera() // Drop several frames for (int i = 0; i < 15; ++i) { - auto lost = m_pipe->waitForFrameset(100); + auto lost = m_pipe->waitForFrameset(m_captureIntervalMilliseconds); } auto pointCloud = std::make_shared(); int frameIndex = 0; record = true; - QString fileNamePrefix = AppSettings::instance().depthCameraDataFolder() + QDir::separator() + AppSettings::instance().fileName(); + QString fileNamePrefix = AppSettings::instance().depthCameraDataFolder() + QDir::separator() + "Gemini336L"; QString imuFilePath = fileNamePrefix + "_IMU.txt"; std::ofstream imuFile(imuFilePath.toStdString(), std::ios::out | std::ios::trunc); while (record) @@ -160,7 +177,7 @@ void DepthCameraOperation::OpenDepthCamera() std::cout << "Start recording..." << std::endl; } - auto frameSet = m_pipe->waitForFrameset(100); + auto frameSet = m_pipe->waitForFrameset(m_captureIntervalMilliseconds); if (frameSet == nullptr) { std::cout << "No frames received in 100ms..." << std::endl; @@ -218,7 +235,7 @@ void DepthCameraOperation::OpenDepthCamera() pointCloud->setCreatePointFormat(OB_FORMAT_RGB_POINT); std::shared_ptr frame = pointCloud->process(frameSet); - QString plyPath = fileNamePrefix + "_"+ QString::number(frameIndex) + ".ply"; + QString plyPath = fileNamePrefix + "_PointCloud_"+ QString::number(frameIndex) + ".ply"; ob::PointCloudHelper::savePointcloudToPly(plyPath.toStdString().c_str(), frame, false, false, 50); //惯导数据 diff --git a/HPPA/DepthCameraWindow.h b/HPPA/DepthCameraWindow.h index f1506c7..0053037 100644 --- a/HPPA/DepthCameraWindow.h +++ b/HPPA/DepthCameraWindow.h @@ -33,6 +33,8 @@ public: void setCallback(void(*func)()); bool getRecordStatus() const { return record; } + void setCaptureInterval(int captureIntervalSeconds); + private: ob::Pipeline* m_pipe; cv::Mat frame; @@ -46,6 +48,8 @@ private: bool record; + int m_captureIntervalMilliseconds; + public slots: void OpenDepthCamera(); void OpenDepthCamera_callback();//不使用信号而使用回调函数来通知界面刷新视频 @@ -68,6 +72,9 @@ public: DepthCameraOperation* m_DepthCameraOperation; + void setDataFolder(QString dir); + void setCaptureInterval(int captureIntervalSeconds); + public Q_SLOTS: void openDepthCamera(); void onCamOpened(); diff --git a/HPPA/HPPA.cpp b/HPPA/HPPA.cpp index 2057240..4aa1f3e 100644 --- a/HPPA/HPPA.cpp +++ b/HPPA/HPPA.cpp @@ -576,8 +576,7 @@ HPPA::HPPA(QWidget* parent) initMapTools(); //定时采集 - connect(this->ui.mActionTimedDataCollection, SIGNAL(triggered()), this, SLOT(onTimedDataCollection())); - mTimedDataCollectionWindow = new TimedDataCollection(m_tmc); + initTimedDataCollection(); QString strPath = QCoreApplication::applicationDirPath() + "/UILayout.ini"; QFile file(strPath); @@ -592,6 +591,114 @@ HPPA::HPPA(QWidget* parent) this->showMaximized(); } +void HPPA::initTimedDataCollection() +{ + connect(this->ui.mActionTimedDataCollection, SIGNAL(triggered()), this, SLOT(onTimedDataCollection())); + mTimedDataCollectionWindow = new TimedDataCollection(); + + // 定时采集控制器 → 相机/马达 + connect(mTimedDataCollectionWindow, &TimedDataCollection::hyperCamParm, this, &HPPA::setTimedDataCollectionHyperCamParm); + connect(mTimedDataCollectionWindow, &TimedDataCollection::camParm, this, &HPPA::setTimedDataCollectionCamParm); + connect(mTimedDataCollectionWindow, &TimedDataCollection::motorParm, this, &HPPA::setTimedDataCollectionMotorParm); + connect(mTimedDataCollectionWindow, &TimedDataCollection::startRecordSignal, this, &HPPA::onStartTimedDataCollection); + + // 相机/马达 → 定时采集控制器 + connect(m_tmc, &TwoMotorControl::sequenceComplete, mTimedDataCollectionWindow, &TimedDataCollection::subTaskCompleted); + + //连接马达控制和单反/深度 +} + +void HPPA::setTimedDataCollectionHyperCamParm(int camType, double f, double e, QString filePath, QString fileName) +{ + switch (camType) + { + case 0: + { + disconnectImagerAndCleanup(); + ui.mActionPica_L->setChecked(true); + + AppSettings::instance().setFrameRate(f); + AppSettings::instance().setIntegrationTime(e); + AppSettings::instance().setDataFolder(filePath); + AppSettings::instance().setFileName(fileName); + + this->frame_number->setText("100000"); + + onconnect(); + break; + } + case 1: + { + disconnectImagerAndCleanup(); + ui.mActionPica_NIR->setChecked(true); + + AppSettings::instance().setFrameRate(f); + AppSettings::instance().setIntegrationTime(e); + AppSettings::instance().setDataFolder(filePath); + AppSettings::instance().setFileName(fileName); + + this->frame_number->setText("100000"); + + onconnect(); + break; + } + } +} + +void HPPA::setTimedDataCollectionCamParm(int camType, int captureIntervalSeconds, QString folder) +{ + switch (camType) + { + case 2: + { + m_singleLensReflexCameraWindow->setDataFolder(folder); + m_singleLensReflexCameraWindow->setCaptureInterval(captureIntervalSeconds); + + break; + } + case 3: + { + m_depthCameraWindow->setDataFolder(folder); + m_depthCameraWindow->setCaptureInterval(captureIntervalSeconds); + + break; + } + } + +} + +void HPPA::setTimedDataCollectionMotorParm(QString pathLineFilePath) +{ + m_tmc->readRecordLineFile(pathLineFilePath); + //m_tmc->onConnectMotor(); + //QThread::msleep(1000); +} + +void HPPA::onStartTimedDataCollection(int camType) +{ + switch (camType) + { + case 0: + { + onStartRecordStep1(); + break; + } + case 1: + { + onStartRecordStep1(); + break; + } + case 2: + { + break; + } + case 3: + { + break; + } + } +} + void HPPA::onTimedDataCollection() { QAction* checkedScenario = m_ScenarioActionGroup->checkedAction(); @@ -609,6 +716,7 @@ void HPPA::onTimedDataCollection() } } + void HPPA::initMenubarToolbar() { //自定义菜单栏和工具栏 @@ -868,7 +976,7 @@ void HPPA::initControlTabwidget() //2轴马达控制 m_tmc = new TwoMotorControl(this); //connect(m_tmc, SIGNAL(startLineNumSignal(int)), this, SLOT(onCreateTab(int))); - connect(m_tmc, SIGNAL(sequenceComplete()), this, SLOT(onsequenceComplete())); + connect(m_tmc, &TwoMotorControl::sequenceComplete, this, &HPPA::onsequenceComplete); m_tmc->setWindowFlags(Qt::Widget); ui.controlTabWidget->addTab(m_tmc, QString::fromLocal8Bit("2轴控制")); diff --git a/HPPA/HPPA.h b/HPPA/HPPA.h index 6222afc..d5de2ee 100644 --- a/HPPA/HPPA.h +++ b/HPPA/HPPA.h @@ -319,6 +319,7 @@ private: void disconnectImagerAndCleanup(); TimedDataCollection* mTimedDataCollectionWindow; + void initTimedDataCollection(); public Q_SLOTS: void onPlotHyperspectralImageRgbImage(int fileNumber, int frameNumber, QString filePath); @@ -399,6 +400,10 @@ public Q_SLOTS: void onMapToolSpectralTriggered(); void onTimedDataCollection(); + void setTimedDataCollectionHyperCamParm(int camType, double f, double e, QString filePath, QString fileName); + void setTimedDataCollectionCamParm(int camType, int captureIntervalSeconds, QString folder); + void setTimedDataCollectionMotorParm(QString pathLineFilePath); + void onStartTimedDataCollection(int camType); protected: void closeEvent(QCloseEvent* event) override; diff --git a/HPPA/SingleLensReflexCameraWindow.cpp b/HPPA/SingleLensReflexCameraWindow.cpp index 5ab4f56..3f946d9 100644 --- a/HPPA/SingleLensReflexCameraWindow.cpp +++ b/HPPA/SingleLensReflexCameraWindow.cpp @@ -81,6 +81,11 @@ void SingleLensReflexCameraWindow::onSelectDataFolder() QString::fromLocal8Bit("选择数据保存路径"), ui.dataFolderLineEdit->text()); + setDataFolder(dir); +} + +void SingleLensReflexCameraWindow::setDataFolder(QString dir) +{ if (!dir.isEmpty()) { ui.dataFolderLineEdit->setText(dir); @@ -92,6 +97,11 @@ void SingleLensReflexCameraWindow::onSelectDataFolder() } } +void SingleLensReflexCameraWindow::setCaptureInterval(int captureIntervalSeconds) +{ + m_SingleLensReflexCameraOperation->setCaptureInterval(captureIntervalSeconds); +} + void SingleLensReflexCameraWindow::openSLRCamera() { if (!m_SingleLensReflexCameraOperation->getRecordStatus()) @@ -200,6 +210,7 @@ SingleLensReflexCameraOperation::SingleLensReflexCameraOperation() m_isSessionOpen = false; m_isLiveViewActive = false; m_imageCounter = 0; + m_captureIntervalMilliseconds = 3000; // 设置保存路径(从 AppSettings 获取,如果为空则使用默认的 CapturedImages 目录) m_savePath = AppSettings::instance().slrDataFolder(); @@ -780,13 +791,18 @@ void SingleLensReflexCameraOperation::takePhoto() // 启动拍照定时器(每3秒拍一张) if (m_captureTimer && !m_captureTimer->isActive()) { - m_captureTimer->start(3000); - std::cout << "capture timer started (1 photo 3 second)" << std::endl; + m_captureTimer->start(m_captureIntervalMilliseconds); + //std::cout << "capture timer started (1 photo 3 second)" << std::endl; emit CaptureStartedSignal(); } } +void SingleLensReflexCameraOperation::setCaptureInterval(int captureIntervalSeconds) +{ + m_captureIntervalMilliseconds = captureIntervalSeconds * 1000; +} + void SingleLensReflexCameraOperation::stopTakePhoto() { if (m_captureTimer && m_captureTimer->isActive()) diff --git a/HPPA/SingleLensReflexCameraWindow.h b/HPPA/SingleLensReflexCameraWindow.h index 63ad406..3139bf9 100644 --- a/HPPA/SingleLensReflexCameraWindow.h +++ b/HPPA/SingleLensReflexCameraWindow.h @@ -46,6 +46,8 @@ public: // 获取当前实时取景图像 QImage getCurrentLiveViewImage(); + void setCaptureInterval(int captureIntervalSeconds); + private: cv::Mat frame; func m_func; @@ -62,6 +64,7 @@ private: QString m_savePath; int m_imageCounter; + int m_captureIntervalMilliseconds; QMutex m_mutex; QMutex m_liveViewMutex; @@ -127,6 +130,8 @@ public: ~SingleLensReflexCameraWindow(); SingleLensReflexCameraOperation* m_SingleLensReflexCameraOperation; + void setDataFolder(QString dir); + void setCaptureInterval(int captureIntervalSeconds); public Q_SLOTS: void onSelectDataFolder(); diff --git a/HPPA/TimedDataCollection.cpp b/HPPA/TimedDataCollection.cpp index cc7fcd7..a2c682c 100644 --- a/HPPA/TimedDataCollection.cpp +++ b/HPPA/TimedDataCollection.cpp @@ -1,11 +1,9 @@ #include "TimedDataCollection.h" #include #include -#include "TwoMotorControl.h" -TimedDataCollection::TimedDataCollection(TwoMotorControl* motorControl, QWidget* parent) +TimedDataCollection::TimedDataCollection(QWidget* parent) : QDialog(parent) - , m_motorControl(nullptr) , m_scheduler(nullptr) { ui.setupUi(this); @@ -23,9 +21,16 @@ TimedDataCollection::TimedDataCollection(TwoMotorControl* motorControl, QWidget* connect(m_scheduler, &TaskScheduler::taskFinished, this, &TimedDataCollection::taskFinished); connect(m_scheduler, &TaskScheduler::subTaskStarted, this, &TimedDataCollection::subTaskStarted); connect(m_scheduler, &TaskScheduler::subTaskFinished, this, &TimedDataCollection::subTaskFinished); - connect(m_scheduler, &TaskScheduler::motorPositionUpdated, this, &TimedDataCollection::motorPositionUpdated); connect(m_scheduler, &TaskScheduler::errorOccurred, this, &TimedDataCollection::errorOccurred); + // 采集相关信号透传 + connect(m_scheduler, &TaskScheduler::hyperCamParm, this, &TimedDataCollection::hyperCamParm); + connect(m_scheduler, &TaskScheduler::camParm, this, &TimedDataCollection::camParm); + connect(m_scheduler, &TaskScheduler::motorParm, this, &TimedDataCollection::motorParm); + connect(m_scheduler, &TaskScheduler::startRecordSignal, this, &TimedDataCollection::startRecordSignal); + + connect(this, &TimedDataCollection::sequenceCompleteSignal, m_scheduler, &TaskScheduler::sequenceCompleteSignal); + //writeRead(); readTimedTaskFromFile("D:/0tmp/3Dtest/task.json"); @@ -33,6 +38,8 @@ TimedDataCollection::TimedDataCollection(TwoMotorControl* motorControl, QWidget* m_scheduler->loadTasks(m_loadedTasks); connect(ui.run_btn, &QPushButton::clicked, this, &TimedDataCollection::startScheduler); + + startScheduler(); } TimedDataCollection::~TimedDataCollection() @@ -42,6 +49,11 @@ TimedDataCollection::~TimedDataCollection() } } +void TimedDataCollection::subTaskCompleted(int status) +{ + emit sequenceCompleteSignal(status); +} + void TimedDataCollection::startScheduler() { if (m_scheduler) { @@ -56,13 +68,6 @@ void TimedDataCollection::stopScheduler() } } -void TimedDataCollection::setMotorControl(TwoMotorControl* motorControl) -{ - if (m_scheduler) { - m_scheduler->setMotorControl(motorControl); - } -} - void TimedDataCollection::readTimedTaskFromFile(const QString& filePath) { // 从文件读取 diff --git a/HPPA/TimedDataCollection.h b/HPPA/TimedDataCollection.h index d1d7df5..fce9701 100644 --- a/HPPA/TimedDataCollection.h +++ b/HPPA/TimedDataCollection.h @@ -8,36 +8,40 @@ #include "ui_TimedDataCollection_ui.h" #include "TimedDataCollectionDataStructures.h" -class TwoMotorControl; - class TimedDataCollection : public QDialog { Q_OBJECT public: - TimedDataCollection(TwoMotorControl* motorControl, QWidget* parent = nullptr); + TimedDataCollection(QWidget* parent = nullptr); ~TimedDataCollection(); void readTimedTaskFromFile(const QString& filePath); - // 设置马达控制器供调度器使用 - void setMotorControl(TwoMotorControl* motorControl); - public Q_SLOTS: void startScheduler(); void stopScheduler(); + void subTaskCompleted(int status); Q_SIGNALS: void taskStarted(int taskId); void taskFinished(int taskId, bool success); + void subTaskStarted(int taskId, int subTaskIndex); void subTaskFinished(int taskId, int subTaskIndex); - void motorPositionUpdated(double x, double y); void errorOccurred(const QString& error); + // 采集相关信号 (透传 TaskScheduler) + void hyperCamParm(int camType, double f, double e, QString filePath, QString fileName); + void camParm(int camType, int captureIntervalSeconds, QString folder); + void motorParm(QString pathLineFilePath); + void startRecordSignal(int camType); + + // 马达反馈的信号 + void sequenceCompleteSignal(int status); + private: Ui::TimedDataCollection_ui ui; - TwoMotorControl* m_motorControl; void writeRead(); diff --git a/HPPA/TimedDataCollectionDataStructures.cpp b/HPPA/TimedDataCollectionDataStructures.cpp index 8cb9b64..18f695e 100644 --- a/HPPA/TimedDataCollectionDataStructures.cpp +++ b/HPPA/TimedDataCollectionDataStructures.cpp @@ -197,20 +197,11 @@ bool TimedDataCollectionDataStructuresReaderWriter::jsonToTimedTask(const QJsonO // ==================== TaskExecutor 实现 ==================== -TaskExecutor::TaskExecutor(TwoMotorControl* motorControl, QObject* parent) +TaskExecutor::TaskExecutor(QObject* parent) : QObject(parent) - , m_motorControl(motorControl) , m_currentSubTaskIndex(0) , m_isRunning(false) { - if (m_motorControl) { - connect(m_motorControl, &TwoMotorControl::broadcastLocationSignal, - this, &TaskExecutor::onMotorLocationUpdate); - //connect(m_motorControl, &TwoMotorControl::sequenceComplete, - // this, &TaskExecutor::onSequenceComplete); - //connect(m_motorControl, &TwoMotorControl::errorOccurred, - // this, &TaskExecutor::onError); - } } TaskExecutor::~TaskExecutor() @@ -232,6 +223,7 @@ void TaskExecutor::execute(const TimedTask& task) qDebug() << "TaskExecutor: Starting task" << task.id; // 开始执行第一个子任务 + makeFolder(m_task.savePath); executeNextSubTask(); } @@ -241,14 +233,33 @@ void TaskExecutor::stop() qDebug() << "TaskExecutor: Stopping task" << m_task.id; - if (m_motorControl) { - m_motorControl->stop(); - } - m_isRunning = false; emit finished(false); } +void TaskExecutor::makeFolder(QString savePath) +{ + QDir dir(savePath); + if (!dir.exists()) { + if (dir.mkpath(".")) { + qDebug() << "TaskExecutor: Created data folder:" << savePath; + } else { + qWarning() << "TaskExecutor: Failed to create data folder:" << savePath; + } + } else { + qDebug() << "TaskExecutor: Data folder already exists:" << savePath; + } +} + +QString TaskExecutor::makeSubTaskDataFolder(QString suffix) +{ + QString dateStr = QDateTime::currentDateTime().toString("yyyy-MM-dd_HH-mm-ss"); + QString folderPath = m_task.savePath + QDir::separator() + dateStr + "_" + suffix; + makeFolder(folderPath); + + return folderPath; +} + void TaskExecutor::onSequenceComplete(int status) { if (!m_isRunning) return; @@ -276,13 +287,6 @@ void TaskExecutor::onSequenceComplete(int status) } } -void TaskExecutor::onMotorLocationUpdate(std::vector loc) -{ - if (loc.size() >= 2) { - emit motorPositionUpdated(loc[0], loc[1]); - } -} - void TaskExecutor::onError(const QString& error) { if (!m_isRunning) return; @@ -299,6 +303,8 @@ void TaskExecutor::executeNextSubTask() return; } + std::cerr << "TaskExecutor::executeNextSubTask,执行子任务" << std::endl; + SubTask& subTask = m_task.subTasks[m_currentSubTaskIndex]; subTask.status = TaskStatus::Running; subTask.startTime = QDateTime::currentDateTime(); @@ -307,55 +313,43 @@ void TaskExecutor::executeNextSubTask() << "type:" << static_cast(subTask.type); emit subTaskStarted(m_currentSubTaskIndex, subTask.type); + + emit motorParm(subTask.pathLineFilePath); - //根据任务类型切换相机类型,还需要考虑相关信号和槽 - - // 如果有路径线文件,加载路径线并启动马达 - if (!subTask.pathLineFilePath.isEmpty()) { - loadPathLinesFromFile(subTask.pathLineFilePath); - } else { - qDebug() << "TaskExecutor: No path line file for subtask"; - } -} - -void TaskExecutor::loadPathLinesFromFile(const QString& filePath) -{ - // 从 .RecordLine3 文件加载路径线 - QFile file(filePath); - if (!file.open(QIODevice::ReadOnly)) { - qWarning() << "TaskExecutor: Failed to open path line file:" << filePath; - emit errorOccurred("Failed to open path line file: " + filePath); - return; - } - - double number; - file.read(reinterpret_cast(&number), sizeof(double)); - - QVector pathLines; - for (int i = 0; i < static_cast(number) / 6; ++i) { - PathLine line; - for (int j = 0; j < 6; ++j) { - double value; - file.read(reinterpret_cast(&value), sizeof(double)); - switch (j) { - case 0: line.targetYPosition = value; break; - case 1: line.speedTargetYPosition = value; break; - case 2: line.targetXMinPosition = value; break; - case 3: line.speedTargetXMinPosition = value; break; - case 4: line.targetXMaxPosition = value; break; - case 5: line.speedTargetXMaxPosition = value; break; - } + int camType; + switch (subTask.type) + { + case SubTaskType::HyperSpectual400_1000nm: + { + camType = 0; + emit hyperCamParm(camType, subTask.frameRate, subTask.exposureTime, makeSubTaskDataFolder("L"), "test"); + + break; } - pathLines.append(line); - } - file.close(); + case SubTaskType::HyperSpectual1000_1700nm: + { + camType = 1; + emit hyperCamParm(camType, subTask.frameRate, subTask.exposureTime, makeSubTaskDataFolder("NIR"), "test"); - qDebug() << "TaskExecutor: Loaded" << pathLines.size() << "path lines from" << filePath; + break; + } + case SubTaskType::SingleLensReflex: + { + camType = 2; + emit camParm(camType, 3, makeSubTaskDataFolder("SLR")); - // 通知马达控制器开始执行 - if (m_motorControl) { - emit m_motorControl->start(pathLines); + break; + } + case SubTaskType::DepthCamera: + { + camType = 3; + emit camParm(camType, 3, makeSubTaskDataFolder("DepthCamera")); + + break; + } } + + emit startRecordSignal(camType); } // ==================== TaskScheduler 实现 ==================== @@ -363,7 +357,6 @@ void TaskExecutor::loadPathLinesFromFile(const QString& filePath) TaskScheduler::TaskScheduler(QObject* parent) : QObject(parent) , m_timer(nullptr) - , m_motorControl(nullptr) , m_currentExecutor(nullptr) , m_currentTaskId(-1) { @@ -374,11 +367,6 @@ TaskScheduler::~TaskScheduler() stop(); } -void TaskScheduler::setMotorControl(TwoMotorControl* motorControl) -{ - m_motorControl = motorControl; -} - void TaskScheduler::loadTasks(const QVector& tasks) { m_tasks = tasks; @@ -421,15 +409,22 @@ void TaskScheduler::stop() void TaskScheduler::checkTasks() { - if (!m_motorControl) return; - QDateTime now = QDateTime::currentDateTime(); for (auto& task : m_tasks) { if (task.status != TaskStatus::Waiting) continue; + + // 超过计划时间1分钟以上,认为任务已过时,跳过 + if (task.scheduledTime.addSecs(60) < now) { + std::cerr << "TaskScheduler::checkTasks,任务已过时,跳过:" << task.id << std::endl; + task.status = TaskStatus::Finished; + continue; + } + if (task.scheduledTime > now) continue; // 到达计划时间,启动任务 + std::cerr << "TaskScheduler::checkTasks,到达计划时间,启动任务" << std::endl; executeTask(task); break; // 一次只执行一个任务 } @@ -470,18 +465,8 @@ void TaskScheduler::onExecutorError(const QString& error) emitError(error); } -void TaskScheduler::onExecutorMotorPositionUpdated(double x, double y) -{ - emit motorPositionUpdated(x, y); -} - void TaskScheduler::executeTask(TimedTask& task) { - if (!m_motorControl) { - emitError("Motor control not set"); - return; - } - qDebug() << "TaskScheduler: Executing task" << task.id; updateTaskStatus(task.id, TaskStatus::Running); @@ -490,7 +475,7 @@ void TaskScheduler::executeTask(TimedTask& task) emit taskStarted(task.id); // 创建任务执行器 - m_currentExecutor = new TaskExecutor(m_motorControl, this); + m_currentExecutor = new TaskExecutor(this); // 连接信号 connect(m_currentExecutor, &TaskExecutor::finished, @@ -501,8 +486,18 @@ void TaskScheduler::executeTask(TimedTask& task) this, &TaskScheduler::onSubTaskFinished); connect(m_currentExecutor, &TaskExecutor::errorOccurred, this, &TaskScheduler::onExecutorError); - connect(m_currentExecutor, &TaskExecutor::motorPositionUpdated, - this, &TaskScheduler::onExecutorMotorPositionUpdated); + + // 采集相关信号透传 + connect(m_currentExecutor, &TaskExecutor::hyperCamParm, + this, &TaskScheduler::hyperCamParm); + connect(m_currentExecutor, &TaskExecutor::camParm, + this, &TaskScheduler::camParm); + connect(m_currentExecutor, &TaskExecutor::motorParm, + this, &TaskScheduler::motorParm); + connect(m_currentExecutor, &TaskExecutor::startRecordSignal, + this, &TaskScheduler::startRecordSignal); + + connect(this, &TaskScheduler::sequenceCompleteSignal, m_currentExecutor, &TaskExecutor::onSequenceComplete); // 开始执行 m_currentExecutor->execute(task); diff --git a/HPPA/TimedDataCollectionDataStructures.h b/HPPA/TimedDataCollectionDataStructures.h index a4976a6..3e2e0c7 100644 --- a/HPPA/TimedDataCollectionDataStructures.h +++ b/HPPA/TimedDataCollectionDataStructures.h @@ -6,7 +6,6 @@ #include #include -#include "TwoMotorControl.h" #include "CaptureCoordinator.h" // ==================== 枚举定义 ==================== @@ -107,10 +106,6 @@ private: static SubTaskType stringToSubTaskType(const QString& str); }; -// ==================== 前向声明 ==================== - -class TwoMotorControl; - // ==================== 任务执行器 ==================== class TaskExecutor : public QObject @@ -118,11 +113,13 @@ class TaskExecutor : public QObject Q_OBJECT public: - explicit TaskExecutor(TwoMotorControl* motorControl, QObject* parent = nullptr); + explicit TaskExecutor(QObject* parent = nullptr); ~TaskExecutor(); // 执行任务 void execute(const TimedTask& task); + void makeFolder(QString savePath); + QString makeSubTaskDataFolder(QString suffix); // 获取当前执行的子任务索引 int currentSubTaskIndex() const { return m_currentSubTaskIndex; } @@ -140,19 +137,21 @@ signals: void finished(bool success); // 任务完成 void subTaskStarted(int subTaskIndex, SubTaskType type); // 子任务开始 void subTaskFinished(int subTaskIndex, SubTaskType type, bool success); // 子任务完成 - void motorPositionUpdated(double x, double y); // 马达位置更新 void errorOccurred(const QString& error); // 错误发生 -private slots: + // 采集相关信号 + void hyperCamParm(int camType, double f, double e, QString filePath, QString fileName); + void camParm(int camType, int captureIntervalSeconds, QString folder); + void motorParm(QString pathLineFilePath); + void startRecordSignal(int camType); + +public slots: void onSequenceComplete(int status); - void onMotorLocationUpdate(std::vector loc); void onError(const QString& error); private: void executeNextSubTask(); - void loadPathLinesFromFile(const QString& filePath); - TwoMotorControl* m_motorControl; TimedTask m_task; int m_currentSubTaskIndex; bool m_isRunning; @@ -168,9 +167,6 @@ public: explicit TaskScheduler(QObject* parent = nullptr); ~TaskScheduler(); - // 设置马达控制器 - void setMotorControl(TwoMotorControl* motorControl); - // 加载任务列表 void loadTasks(const QVector& tasks); @@ -189,19 +185,28 @@ public: signals: void taskStarted(int taskId); // 任务开始 void taskFinished(int taskId, bool success); // 任务完成 + + // 子任务的信号 void subTaskStarted(int taskId, int subTaskIndex); // 子任务开始 void subTaskFinished(int taskId, int subTaskIndex); // 子任务完成 - void motorPositionUpdated(double x, double y); // 马达位置更新 void errorOccurred(const QString& error); // 错误发生 void schedulerStateChanged(bool running); // 调度器状态变化 + // 采集相关信号 (透传 TaskExecutor) + void hyperCamParm(int camType, double f, double e, QString filePath, QString fileName); + void camParm(int camType, int captureIntervalSeconds, QString folder); + void motorParm(QString pathLineFilePath); + void startRecordSignal(int camType); + + // 马达反馈的信号 + void sequenceCompleteSignal(int status); + private slots: void checkTasks(); // 检查任务是否该启动 void onTaskFinished(bool success); void onSubTaskStarted(int subTaskIndex, SubTaskType type); void onSubTaskFinished(int subTaskIndex, SubTaskType type, bool success); void onExecutorError(const QString& error); - void onExecutorMotorPositionUpdated(double x, double y); private: void executeTask(TimedTask& task); @@ -210,7 +215,6 @@ private: QTimer* m_timer; QVector m_tasks; - TwoMotorControl* m_motorControl; TaskExecutor* m_currentExecutor; int m_currentTaskId; }; diff --git a/HPPA/TwoMotorControl.cpp b/HPPA/TwoMotorControl.cpp index 0f2384a..668e534 100644 --- a/HPPA/TwoMotorControl.cpp +++ b/HPPA/TwoMotorControl.cpp @@ -116,7 +116,7 @@ void TwoMotorControl::run() { QMessageBox::information(this, QString::fromLocal8Bit("提示"), QString::fromLocal8Bit("请至少添加一行采集线!")); - emit sequenceComplete(); + emit sequenceComplete(0); return; } @@ -129,7 +129,7 @@ void TwoMotorControl::run() connect(this, SIGNAL(stopSignal()), m_coordinator, SLOT(stop())); connect(m_coordinator, SIGNAL(startRecordLineNumSignal(int)), this, SLOT(receiveStartRecordLineNum(int))); connect(m_coordinator, SIGNAL(finishRecordLineNumSignal(int)), this, SLOT(receiveFinishRecordLineNum(int))); - connect(m_coordinator, SIGNAL(sequenceComplete(int)), this, SLOT(onSequenceComplete())); + connect(m_coordinator, SIGNAL(sequenceComplete(int)), this, SLOT(onSequenceComplete(int))); connect(m_coordinator, &TwoMotionCaptureCoordinator::startRecordHSISignal, m_Imager, &ImagerOperationBase::start_record); connect(m_coordinator, &TwoMotionCaptureCoordinator::stopRecordHSISignal, this, &TwoMotorControl::stop_record); @@ -263,7 +263,7 @@ void TwoMotorControl::receiveFinishRecordLineNum(int lineNum) } } -void TwoMotorControl::onSequenceComplete() +void TwoMotorControl::onSequenceComplete(int status) { isWritePosFile = false; fclose(m_posFileHandle); @@ -272,7 +272,7 @@ void TwoMotorControl::onSequenceComplete() m_coordinatorThread.wait(); m_coordinator = nullptr; - emit sequenceComplete(); + emit sequenceComplete(status); } bool TwoMotorControl::getMotorsConnectionStatus() @@ -551,7 +551,10 @@ void TwoMotorControl::onReadRecordLineFile_btn() { return; } - + readRecordLineFile(RecordLineFilePath); +} +void TwoMotorControl::readRecordLineFile(QString RecordLineFilePath) +{ FILE* RecordLineFileHandle = fopen(RecordLineFilePath.toStdString().c_str(), "rb"); double number; diff --git a/HPPA/TwoMotorControl.h b/HPPA/TwoMotorControl.h index c2ce90f..afd9c13 100644 --- a/HPPA/TwoMotorControl.h +++ b/HPPA/TwoMotorControl.h @@ -27,6 +27,8 @@ public: void record_white(); bool getMotorsConnectionStatus(); + + void readRecordLineFile(QString RecordLineFilePath); private: ImagerOperationBase* m_Imager; @@ -68,7 +70,7 @@ public Q_SLOTS: void stop(); void receiveStartRecordLineNum(int lineNum); void receiveFinishRecordLineNum(int lineNum); - void onSequenceComplete(); + void onSequenceComplete(int status); void stop_record(); @@ -86,7 +88,7 @@ signals: void stopSignal(); void startLineNumSignal(int lineNum); - void sequenceComplete();//所有采集线正常运行完成 + void sequenceComplete(int status);//所有采集线正常运行完成 void broadcastLocationSignal(std::vector);