add,计划采集6:

实现部分计划采集功能:定时任务可控制单反
This commit is contained in:
tangchao0503
2026-06-04 18:01:22 +08:00
parent 3607913f13
commit 41a1a938b9
11 changed files with 205 additions and 6 deletions

View File

@ -6,6 +6,7 @@ TwoMotionCaptureCoordinator::TwoMotionCaptureCoordinator(
: QObject(parent)
, m_motorCtrl(motorCtrl)
, m_isRunning(false)
, m_isValidCapturing(false)
{
//这些信号槽是按照逻辑顺序的
connect(this, SIGNAL(moveTo(int, double, double, int)),
@ -113,7 +114,7 @@ void TwoMotionCaptureCoordinator::move2LocBeforeStart()
speed.push_back(tmp.speedTargetYPosition);
emit moveTo(m_locBeforeStart, speed, 1000);
m_isRunning = false;
m_isValidCapturing = false;
m_isMoving2XMin = false;
m_isMoving2XMax = false;
@ -195,12 +196,12 @@ void TwoMotionCaptureCoordinator::handlePositionReached(int motorID, double pos)
//QMutexLocker locker(&m_dataMutex);
PathLine &tmp = m_pathLines[m_numCurrentPathLine];
if (motorID == 1)//y马达
{
if (m_isMoving2YTargeLoc)
{
PathLine& tmp = m_pathLines[m_numCurrentPathLine];
double threshold = getThre(tmp.targetYPosition, pos);
if (threshold > 5)
@ -230,6 +231,7 @@ void TwoMotionCaptureCoordinator::handlePositionReached(int motorID, double pos)
if (m_isMoving2YStartLoc)
{
m_isMoving2YStartLoc = false;
isBack2Origin();
return;
}
@ -238,6 +240,8 @@ void TwoMotionCaptureCoordinator::handlePositionReached(int motorID, double pos)
{
if (m_isMoving2XMin)
{
PathLine& tmp = m_pathLines[m_numCurrentPathLine];
double threshold = getThre(tmp.targetXMinPosition, pos);
if (threshold > 5)
@ -266,6 +270,8 @@ void TwoMotionCaptureCoordinator::handlePositionReached(int motorID, double pos)
if (m_isMoving2XMax)
{
PathLine& tmp = m_pathLines[m_numCurrentPathLine];
double threshold = getThre(tmp.targetXMaxPosition, pos);
if (threshold > 5 && !m_isImagerFrameNumberMeet)//马达没到准确位置 && 【非】光谱仪因帧数限制主动停止采集
@ -302,6 +308,7 @@ void TwoMotionCaptureCoordinator::handlePositionReached(int motorID, double pos)
if (m_isMoving2XStartLoc)
{
m_isMoving2XStartLoc = false;
isBack2Origin();
return;
}
@ -344,6 +351,21 @@ void TwoMotionCaptureCoordinator::startRecordHsi()
}
}
void TwoMotionCaptureCoordinator::isBack2Origin()
{
if (!m_isRunning) return;
//QMutexLocker locker(&m_dataMutex);
if (!m_isMoving2XStartLoc && !m_isMoving2YStartLoc)
{
m_isRunning = false;
emit back2OriginSignal();
}
}
void TwoMotionCaptureCoordinator::handleCaptureCompleteWhenFrameNumberMeet()
{
m_isImagerFrameNumberMeet = true;
@ -388,6 +410,7 @@ void TwoMotionCaptureCoordinator::processNextPathLine()
std::cout << "\nNew path line: " << m_numCurrentPathLine << std::endl;
emit startRecordLineNumSignal(m_numCurrentPathLine);
m_isValidCapturing = true;
PathLine &tmp = m_pathLines[m_numCurrentPathLine];
tmp.timestamp1 = QDateTime::currentDateTime();

View File

@ -46,6 +46,7 @@ public:
signals:
void sequenceComplete(int);//0所有采集线正常运行完成1用户主动取消采集
void back2OriginSignal();
void startRecordLineNumSignal(int lineNum);
void finishRecordLineNumSignal(int lineNum);
@ -75,6 +76,7 @@ private slots:
private:
void processNextPathLine();
void startRecordHsi();
void isBack2Origin();
void getLocBeforeStart();
double getThre(double targetLoc, double actualLoc);
@ -87,6 +89,7 @@ private:
mutable QMutex m_dataMutex;
bool m_isRunning;
bool m_isValidCapturing;
bool m_isMoving2YTargeLoc;
bool m_isMoving2XMin;
bool m_isMoving2XMax;

View File

@ -604,6 +604,7 @@ void HPPA::initTimedDataCollection()
// 相机/马达 → 定时采集控制器
connect(m_tmc, &TwoMotorControl::sequenceComplete, mTimedDataCollectionWindow, &TimedDataCollection::subTaskCompleted);
connect(m_tmc, &TwoMotorControl::back2OriginSignal, mTimedDataCollectionWindow, &TimedDataCollection::onBack2Origin);
//连接马达控制和单反/深度
}
@ -690,10 +691,13 @@ void HPPA::onStartTimedDataCollection(int camType)
}
case 2:
{
m_tmc->run2(m_singleLensReflexCameraWindow);
break;
}
case 3:
{
//m_tmc->setImager(m_Imager);
//m_tmc->run2();
break;
}
}
@ -976,7 +980,7 @@ void HPPA::initControlTabwidget()
//2轴马达控制
m_tmc = new TwoMotorControl(this);
//connect(m_tmc, SIGNAL(startLineNumSignal(int)), this, SLOT(onCreateTab(int)));
connect(m_tmc, &TwoMotorControl::sequenceComplete, this, &HPPA::onsequenceComplete);
connect(m_tmc, &TwoMotorControl::back2OriginSignal, this, &HPPA::onsequenceComplete);
m_tmc->setWindowFlags(Qt::Widget);
ui.controlTabWidget->addTab(m_tmc, QString::fromLocal8Bit("2轴控制"));

View File

@ -28,6 +28,8 @@ SingleLensReflexCameraWindow::SingleLensReflexCameraWindow(QWidget* parent)
connect(ui.stopTakePhoto_btn, &QPushButton::clicked, this, &SingleLensReflexCameraWindow::stopTakePhoto);
connect(this, &SingleLensReflexCameraWindow::stopTakePhotoSignal, m_SingleLensReflexCameraOperation, &SingleLensReflexCameraOperation::stopTakePhoto);
connect(this, &SingleLensReflexCameraWindow::OpenAndTakePhotoSLRCameraSignal, m_SingleLensReflexCameraOperation, &SingleLensReflexCameraOperation::OpenAndTakePhotoSLRCamera);
connect(m_SingleLensReflexCameraOperation, &SingleLensReflexCameraOperation::CamOpenedSignal, this, &SingleLensReflexCameraWindow::onCamOpened);
connect(m_SingleLensReflexCameraOperation, &SingleLensReflexCameraOperation::CamClosedSignal, this, &SingleLensReflexCameraWindow::onCamClosed);
@ -75,6 +77,20 @@ SingleLensReflexCameraWindow::~SingleLensReflexCameraWindow()
m_SingleLensReflexCameraOperation = nullptr;
}
void SingleLensReflexCameraWindow::onStartTimedDataCollection(int lineNum)
{
if (lineNum == 0)
{
OpenAndTakePhotoSLRCamera();
}
}
void SingleLensReflexCameraWindow::onStopTimedDataCollection()
{
stopTakePhoto();
closeSLRCamera();
}
void SingleLensReflexCameraWindow::onSelectDataFolder()
{
QString dir = QFileDialog::getExistingDirectory(this,
@ -118,6 +134,11 @@ void SingleLensReflexCameraWindow::takePhoto()
}
}
void SingleLensReflexCameraWindow::OpenAndTakePhotoSLRCamera()
{
emit OpenAndTakePhotoSLRCameraSignal();
}
void SingleLensReflexCameraWindow::stopTakePhoto()
{
if (m_SingleLensReflexCameraOperation->getRecordStatus())
@ -798,6 +819,64 @@ void SingleLensReflexCameraOperation::takePhoto()
}
}
void SingleLensReflexCameraOperation::OpenAndTakePhotoSLRCamera()
{
std::cout << "SingleLensReflexCameraOperation::OpenSLRCamera, 打开单反相机" << std::endl;
EdsError err = EDS_ERR_OK;
// 初始化SDK
err = initializeSDK();
if (err != EDS_ERR_OK)
{
emit ErrorSignal(QString::fromLocal8Bit("初始化SDK失败错误码: %1").arg(err));
return;
}
// 打开相机
err = openCamera();
if (err != EDS_ERR_OK)
{
terminateSDK();
emit ErrorSignal(QString::fromLocal8Bit("打开相机失败,错误码: %1").arg(err));
return;
}
// 设置保存到PC
err = setupSaveToHost();
if (err != EDS_ERR_OK)
{
closeCamera();
terminateSDK();
emit ErrorSignal(QString::fromLocal8Bit("设置保存位置失败,错误码: %1").arg(err));
return;
}
// 启动实时取景
err = startLiveView();
if (err != EDS_ERR_OK)
{
std::cout << "Warning: Failed to start live view, error: " << err << std::endl;
// 实时取景启动失败不是致命错误,继续执行
}
m_isRecord = true;
// 启动实时取景定时器约30fps
if (m_liveViewTimer && !m_liveViewTimer->isActive()) {
m_liveViewTimer->start(33); // 约30fps
}
m_captureTimer->start(m_captureIntervalMilliseconds);
//std::cout << "capture timer started (1 photo 3 second)" << std::endl;
emit CaptureStartedSignal();
emit CamOpenedSignal();
std::cout << "Camera opened, live view started." << std::endl;
}
void SingleLensReflexCameraOperation::setCaptureInterval(int captureIntervalSeconds)
{
m_captureIntervalMilliseconds = captureIntervalSeconds * 1000;

View File

@ -94,6 +94,7 @@ private:
public slots:
void OpenSLRCamera();
void takePhoto();
void OpenAndTakePhotoSLRCamera();
void stopTakePhoto();
void OpenSLRCamera_callback();
void CloseSLRCamera();
@ -138,6 +139,7 @@ public Q_SLOTS:
void openSLRCamera();
void takePhoto();
void OpenAndTakePhotoSLRCamera();
void stopTakePhoto();
void onCamOpened();
void closeSLRCamera();
@ -153,9 +155,13 @@ public Q_SLOTS:
void onCaptureStarted();
void onCaptureStopped();
void onStartTimedDataCollection(int lineNum);
void onStopTimedDataCollection();
signals:
void openSLRCameraSignal();
void takePhotoSignal();
void OpenAndTakePhotoSLRCameraSignal();
void stopTakePhotoSignal();
void closeSLRCameraSignal();
void PlotSLRImageSignal();

View File

@ -30,6 +30,7 @@ TimedDataCollection::TimedDataCollection(QWidget* parent)
connect(m_scheduler, &TaskScheduler::startRecordSignal, this, &TimedDataCollection::startRecordSignal);
connect(this, &TimedDataCollection::sequenceCompleteSignal, m_scheduler, &TaskScheduler::sequenceCompleteSignal);
connect(this, &TimedDataCollection::Back2OriginSignal, m_scheduler, &TaskScheduler::Back2OriginSignal);
//writeRead();
readTimedTaskFromFile("D:/0tmp/3Dtest/task.json");
@ -54,6 +55,11 @@ void TimedDataCollection::subTaskCompleted(int status)
emit sequenceCompleteSignal(status);
}
void TimedDataCollection::onBack2Origin()
{
emit Back2OriginSignal();
}
void TimedDataCollection::startScheduler()
{
if (m_scheduler) {

View File

@ -22,6 +22,7 @@ public Q_SLOTS:
void startScheduler();
void stopScheduler();
void subTaskCompleted(int status);
void onBack2Origin();
Q_SIGNALS:
void taskStarted(int taskId);
@ -39,6 +40,7 @@ Q_SIGNALS:
// 马达反馈的信号
void sequenceCompleteSignal(int status);
void Back2OriginSignal();
private:
Ui::TimedDataCollection_ui ui;

View File

@ -273,13 +273,17 @@ void TaskExecutor::onSequenceComplete(int status)
emit subTaskFinished(m_currentSubTaskIndex, subTask.type, (status == 0));
}
}
void TaskExecutor::onBack2Origin()
{
// 检查是否还有更多子任务
m_currentSubTaskIndex++;
if (m_currentSubTaskIndex < m_task.subTasks.size()) {
// 执行下一个子任务
QTimer::singleShot(100, this, &TaskExecutor::executeNextSubTask);
} else {
}
else {
// 所有子任务完成
m_isRunning = false;
qDebug() << "TaskExecutor: All subtasks completed";
@ -498,6 +502,7 @@ void TaskScheduler::executeTask(TimedTask& task)
this, &TaskScheduler::startRecordSignal);
connect(this, &TaskScheduler::sequenceCompleteSignal, m_currentExecutor, &TaskExecutor::onSequenceComplete);
connect(this, &TaskScheduler::Back2OriginSignal, m_currentExecutor, &TaskExecutor::onBack2Origin);
// 开始执行
m_currentExecutor->execute(task);

View File

@ -147,6 +147,7 @@ signals:
public slots:
void onSequenceComplete(int status);
void onBack2Origin();
void onError(const QString& error);
private:
@ -200,6 +201,7 @@ signals:
// 马达反馈的信号
void sequenceCompleteSignal(int status);
void Back2OriginSignal();
private slots:
void checkTasks(); // 检查任务是否该启动

View File

@ -103,6 +103,61 @@ void TwoMotorControl::record_white()
m_whiteCaptureCoordinator->startStepMotion(s);
}
void TwoMotorControl::run2(SingleLensReflexCameraWindow* window)
{
int rowCount = ui.recordLine_tableWidget->rowCount();
if (rowCount == 0)
{
QMessageBox::information(this, QString::fromLocal8Bit("提示"), QString::fromLocal8Bit("请至少添加一行采集线!"));
emit sequenceComplete(0);
return;
}
m_coordinator = new TwoMotionCaptureCoordinator(m_multiAxisController);
connect(this, SIGNAL(start(QVector<PathLine>)), m_coordinator, SLOT(start(QVector<PathLine>)));
connect(m_coordinator, &TwoMotionCaptureCoordinator::startRecordLineNumSignal, this, &TwoMotorControl::receiveStartRecordLineNum);
connect(m_coordinator, &TwoMotionCaptureCoordinator::finishRecordLineNumSignal, this, &TwoMotorControl::receiveFinishRecordLineNum);
connect(m_coordinator, &TwoMotionCaptureCoordinator::startRecordLineNumSignal, window, &SingleLensReflexCameraWindow::onStartTimedDataCollection);
connect(m_coordinator, &TwoMotionCaptureCoordinator::sequenceComplete, window, &SingleLensReflexCameraWindow::onStopTimedDataCollection);
connect(m_coordinator, &TwoMotionCaptureCoordinator::back2OriginSignal, this, &TwoMotorControl::onBack2Origin2);
QVector<PathLine> pathLines;
//int columnCount = ui.recordLine_tableWidget->columnCount();
for (size_t i = 0; i < rowCount; i++)
{
PathLine tmp;
tmp.targetYPosition = ui.recordLine_tableWidget->item(i, 0)->text().toDouble();
tmp.speedTargetYPosition = ui.recordLine_tableWidget->item(i, 1)->text().toDouble();
tmp.targetXMinPosition = ui.recordLine_tableWidget->item(i, 2)->text().toDouble();
tmp.speedTargetXMinPosition = ui.recordLine_tableWidget->item(i, 3)->text().toDouble();
tmp.targetXMaxPosition = ui.recordLine_tableWidget->item(i, 4)->text().toDouble();
tmp.speedTargetXMaxPosition = ui.recordLine_tableWidget->item(i, 5)->text().toDouble();
pathLines.append(tmp);
}
for (size_t i = 0; i < ui.recordLine_tableWidget->rowCount(); i++)
{
for (size_t j = 0; j < ui.recordLine_tableWidget->columnCount(); j++)
{
ui.recordLine_tableWidget->item(i, j)->setBackgroundColor(QColor("#0E1C4C"));
}
}
emit start(pathLines);
}
void TwoMotorControl::onBack2Origin2()
{
m_coordinator->deleteLater();
emit back2OriginSignal();
}
void TwoMotorControl::run()
{
if (getState())
@ -130,6 +185,7 @@ void TwoMotorControl::run()
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(int)));
connect(m_coordinator, &TwoMotionCaptureCoordinator::back2OriginSignal, this, &TwoMotorControl::onBack2Origin);
connect(m_coordinator, &TwoMotionCaptureCoordinator::startRecordHSISignal, m_Imager, &ImagerOperationBase::start_record);
connect(m_coordinator, &TwoMotionCaptureCoordinator::stopRecordHSISignal, this, &TwoMotorControl::stop_record);
@ -268,11 +324,16 @@ void TwoMotorControl::onSequenceComplete(int status)
isWritePosFile = false;
fclose(m_posFileHandle);
emit sequenceComplete(status);
}
void TwoMotorControl::onBack2Origin()
{
m_coordinatorThread.quit();
m_coordinatorThread.wait();
m_coordinator = nullptr;
emit sequenceComplete(status);
emit back2OriginSignal();
}
bool TwoMotorControl::getMotorsConnectionStatus()

View File

@ -10,6 +10,9 @@
#include "CaptureCoordinator.h"
#include "MotorWindowBase.h"
#include "SingleLensReflexCameraWindow.h"
#include "DepthCameraWindow.h"
#define PI 3.1415926
class TwoMotorControl : public QDialog, public MotorWindowBase
@ -71,6 +74,10 @@ public Q_SLOTS:
void receiveStartRecordLineNum(int lineNum);
void receiveFinishRecordLineNum(int lineNum);
void onSequenceComplete(int status);
void onBack2Origin();
void run2(SingleLensReflexCameraWindow* w);
void onBack2Origin2();
void stop_record();
@ -89,6 +96,7 @@ signals:
void startLineNumSignal(int lineNum);
void sequenceComplete(int status);//所有采集线正常运行完成
void back2OriginSignal();
void broadcastLocationSignal(std::vector<double>);