8 Commits

Author SHA1 Message Date
8329c00165 add,计划采集11:
1、完善定时采集流程信息统计:时间;
2、添加状态:跳过;
2026-06-12 10:37:54 +08:00
f69edcf2c9 add,计划采集10:
解决偶发单反唤起失败问题;

任务文件要求:
1、高光谱必须在前面,没有顺序要求,因为在执行高光谱任务前会预热卤素灯,所有高光谱任务完成后才关闭卤素灯;
2、单反/深度必须在后面,没有顺序要求;
3、必须要有高光谱任务:单反存在唤醒程序和一定反应时间,所以必须依赖前一个任务进行唤醒;
 (1)当单反已经是唤醒状态时,重新上电(先下电后上电)后可马上重新唤醒单反:单反适配器剩余电量马上耗尽,所以才能马上重新唤醒单反;
 (2)当单反在上电的状态下,从唤醒状态自动进入休眠状态时,重新下电后需要等待2分15秒(135秒)后,再重新上电才能唤醒单反:等待135秒的目的是将适配器中电容的剩余电量耗尽;
2026-06-11 15:27:02 +08:00
509f4b0767 add,计划采集9:
基本计划采集功能:采集流程电源通断控制ok
2026-06-10 18:10:47 +08:00
4a62d9a007 add,计划采集8:
实现部分计划采集功能:电源通断控制
2026-06-09 11:08:02 +08:00
467bebe9dd add,计划采集7:
实现部分计划采集功能:定时任务可完整执行
2026-06-05 11:36:38 +08:00
41a1a938b9 add,计划采集6:
实现部分计划采集功能:定时任务可控制单反
2026-06-04 18:01:22 +08:00
3607913f13 add,计划采集5:
实现部分计划采集功能:
2026-06-04 16:41:51 +08:00
a8760652bd add,计划采集3:
实现部分计划采集功能
2026-06-03 15:04:03 +08:00
25 changed files with 2086 additions and 355 deletions

View File

@ -6,6 +6,7 @@ TwoMotionCaptureCoordinator::TwoMotionCaptureCoordinator(
: QObject(parent) : QObject(parent)
, m_motorCtrl(motorCtrl) , m_motorCtrl(motorCtrl)
, m_isRunning(false) , m_isRunning(false)
, m_isValidCapturing(false)
{ {
//这些信号槽是按照逻辑顺序的 //这些信号槽是按照逻辑顺序的
connect(this, SIGNAL(moveTo(int, double, double, int)), connect(this, SIGNAL(moveTo(int, double, double, int)),
@ -86,6 +87,7 @@ void TwoMotionCaptureCoordinator::getLocBeforeStart()
QMetaObject::Connection conn = QObject::connect(m_motorCtrl, &IrisMultiMotorController::locationSignal, QMetaObject::Connection conn = QObject::connect(m_motorCtrl, &IrisMultiMotorController::locationSignal,
[&](std::vector<double> pos) { [&](std::vector<double> pos) {
m_locBeforeStart = pos; m_locBeforeStart = pos;
std::cout << "start pos: "<< pos[0] <<", " << pos[1] << std::endl;
received = true; received = true;
loop.quit(); loop.quit();
}); });
@ -113,7 +115,7 @@ void TwoMotionCaptureCoordinator::move2LocBeforeStart()
speed.push_back(tmp.speedTargetYPosition); speed.push_back(tmp.speedTargetYPosition);
emit moveTo(m_locBeforeStart, speed, 1000); emit moveTo(m_locBeforeStart, speed, 1000);
m_isRunning = false; m_isValidCapturing = false;
m_isMoving2XMin = false; m_isMoving2XMin = false;
m_isMoving2XMax = false; m_isMoving2XMax = false;
@ -195,12 +197,12 @@ void TwoMotionCaptureCoordinator::handlePositionReached(int motorID, double pos)
//QMutexLocker locker(&m_dataMutex); //QMutexLocker locker(&m_dataMutex);
PathLine &tmp = m_pathLines[m_numCurrentPathLine];
if (motorID == 1)//y马达 if (motorID == 1)//y马达
{ {
if (m_isMoving2YTargeLoc) if (m_isMoving2YTargeLoc)
{ {
PathLine& tmp = m_pathLines[m_numCurrentPathLine];
double threshold = getThre(tmp.targetYPosition, pos); double threshold = getThre(tmp.targetYPosition, pos);
if (threshold > 5) if (threshold > 5)
@ -230,6 +232,7 @@ void TwoMotionCaptureCoordinator::handlePositionReached(int motorID, double pos)
if (m_isMoving2YStartLoc) if (m_isMoving2YStartLoc)
{ {
m_isMoving2YStartLoc = false; m_isMoving2YStartLoc = false;
isBack2Origin();
return; return;
} }
@ -238,6 +241,8 @@ void TwoMotionCaptureCoordinator::handlePositionReached(int motorID, double pos)
{ {
if (m_isMoving2XMin) if (m_isMoving2XMin)
{ {
PathLine& tmp = m_pathLines[m_numCurrentPathLine];
double threshold = getThre(tmp.targetXMinPosition, pos); double threshold = getThre(tmp.targetXMinPosition, pos);
if (threshold > 5) if (threshold > 5)
@ -266,6 +271,8 @@ void TwoMotionCaptureCoordinator::handlePositionReached(int motorID, double pos)
if (m_isMoving2XMax) if (m_isMoving2XMax)
{ {
PathLine& tmp = m_pathLines[m_numCurrentPathLine];
double threshold = getThre(tmp.targetXMaxPosition, pos); double threshold = getThre(tmp.targetXMaxPosition, pos);
if (threshold > 5 && !m_isImagerFrameNumberMeet)//马达没到准确位置 && 【非】光谱仪因帧数限制主动停止采集 if (threshold > 5 && !m_isImagerFrameNumberMeet)//马达没到准确位置 && 【非】光谱仪因帧数限制主动停止采集
@ -302,6 +309,7 @@ void TwoMotionCaptureCoordinator::handlePositionReached(int motorID, double pos)
if (m_isMoving2XStartLoc) if (m_isMoving2XStartLoc)
{ {
m_isMoving2XStartLoc = false; m_isMoving2XStartLoc = false;
isBack2Origin();
return; return;
} }
@ -341,9 +349,25 @@ void TwoMotionCaptureCoordinator::startRecordHsi()
emit moveTo(0, tmp.targetXMaxPosition, tmp.speedTargetXMaxPosition, 1000); emit moveTo(0, tmp.targetXMaxPosition, tmp.speedTargetXMaxPosition, 1000);
emit startRecordHSISignal(m_numCurrentPathLine); emit startRecordHSISignal(m_numCurrentPathLine);
emit startRecordLineNumSignal(m_numCurrentPathLine);
} }
} }
void TwoMotionCaptureCoordinator::isBack2Origin()
{
if (!m_isRunning) return;
//QMutexLocker locker(&m_dataMutex);
if (!m_isMoving2XStartLoc && !m_isMoving2YStartLoc)
{
m_isRunning = false;
emit back2OriginSignal();
}
}
void TwoMotionCaptureCoordinator::handleCaptureCompleteWhenFrameNumberMeet() void TwoMotionCaptureCoordinator::handleCaptureCompleteWhenFrameNumberMeet()
{ {
m_isImagerFrameNumberMeet = true; m_isImagerFrameNumberMeet = true;
@ -387,7 +411,8 @@ void TwoMotionCaptureCoordinator::processNextPathLine()
} }
std::cout << "\nNew path line: " << m_numCurrentPathLine << std::endl; std::cout << "\nNew path line: " << m_numCurrentPathLine << std::endl;
emit startRecordLineNumSignal(m_numCurrentPathLine); emit gotoRecordLineNumSignal(m_numCurrentPathLine);
m_isValidCapturing = true;
PathLine &tmp = m_pathLines[m_numCurrentPathLine]; PathLine &tmp = m_pathLines[m_numCurrentPathLine];
tmp.timestamp1 = QDateTime::currentDateTime(); tmp.timestamp1 = QDateTime::currentDateTime();

View File

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

View File

@ -0,0 +1,14 @@
#include "CommunicationInterfaceBase.h"
using namespace MotorParams;
CommunicationInterfaceBase::CommunicationInterfaceBase(QObject* parent)
:QObject(parent)
{
}
CommunicationInterfaceBase::~CommunicationInterfaceBase()
{
}

View File

@ -0,0 +1,36 @@
#pragma once
#include <QObject>
#include <QString>
#include "motorParams.h"
namespace MotorParams {
struct TCPConnectionParams
{
QString serverIP;
int port;
};
class CommunicationInterfaceBase :public QObject
{
Q_OBJECT
public:
CommunicationInterfaceBase(QObject* parent = nullptr);
~CommunicationInterfaceBase();
virtual bool connect2Motor() = 0;
//virtual void disconnect() = 0;
//virtual bool isConnected() const = 0;
virtual int sendCommand(const QString command) = 0;
//virtual void sendCommandAsync(const QString& command) = 0;
virtual int recvData(QByteArray& dataRecv) = 0;
signals:
void dataReceived(const QByteArray& data);
void connected(); // <20><><EFBFBD>ܴ<EFBFBD><DCB4>ڻ<EFBFBD><DABB><EFBFBD>TCP<43><50><EFBFBD><EFBFBD><EFBFBD><EFBFBD><E1B7A2><EFBFBD><EFBFBD><EFBFBD>ź<EFBFBD>
void disconnected();
void errorOccurred(QString msg);
};
} // namespace MotorParams

View File

@ -0,0 +1,95 @@
#include "CommunicationViaTCP.h"
using namespace MotorParams;
CommunicationViaTCP::CommunicationViaTCP(MotorParams::TCPConnectionParams connectionParams, QObject* parent)
:MotorParams::CommunicationInterfaceBase(parent)
{
m_bConnected = false;
m_tcpServer = new QTcpServer(this);
connect(m_tcpServer, SIGNAL(newConnection()), this, SLOT(onNewConnection()));
m_tcpServer->listen(QHostAddress::Any, connectionParams.port);
}
CommunicationViaTCP::~CommunicationViaTCP()
{
m_tcpServer->close();
delete m_tcpServer;
//这两行代码要报错,为啥呢?????????????????
//m_tcpSocket->disconnectFromHost();
//delete m_tcpSocket;
}
bool CommunicationViaTCP::connect2Motor()
{
return true;
}
void CommunicationViaTCP::onNewConnection()
{
m_bConnected = true;
m_tcpSocket = m_tcpServer->nextPendingConnection();
connect(m_tcpSocket, SIGNAL(disconnected()), this, SLOT(onTcpSocketDisconnected()));
emit connected();
}
bool CommunicationViaTCP::isConnected() const
{
return m_bConnected;
}
//从拔掉客户端的电源客户端m_tcpSocket断开连接到这个函数被调用有延迟所以这个函数调用也有延迟导致拔掉电源后的一小段时间函数isConnected()还是返回true
void CommunicationViaTCP::onTcpSocketDisconnected()
{
int a = 1;
m_bConnected = false;
m_tcpSocket->deleteLater();
}
int CommunicationViaTCP::sendCommand(const QString cmd)
{
if (!isConnected()) {
QString error = "No client connected";
emit commandSendResult(-1, error);
qWarning() << error << "command:" << cmd;
return -1;
}
qint64 bytesWritten = m_tcpSocket->write(cmd.toUtf8().data());
m_tcpSocket->waitForBytesWritten(50);
return bytesWritten;
}
int CommunicationViaTCP::recvData(QByteArray& dataRecv)
{
if (!isConnected()) {
QString error = "No client connected";
return -1;
}
dataRecv.clear();
QByteArray temp;
temp = m_tcpSocket->readAll();
dataRecv.append(temp);
int counter = 0;
while (dataRecv.size() < 21)
{
counter++;
m_tcpSocket->waitForReadyRead(100);
temp = m_tcpSocket->readAll();
dataRecv.append(temp);
if (counter >= 5)
break;
}
//qDebug() << "Hex:" << dataRecv.toHex();
return dataRecv.size();
}

View File

@ -0,0 +1,45 @@
#pragma once
#include <QObject>
#include <QThread>
#include <QDebug>
#include <QTcpServer>
#include <QTcpSocket>
#include "CommunicationInterfaceBase.h"
namespace MotorParams {
class CommunicationViaTCP :
public CommunicationInterfaceBase
{
Q_OBJECT
public:
CommunicationViaTCP(TCPConnectionParams connectionParams, QObject* parent = nullptr);
~CommunicationViaTCP();
//继承基类
bool connect2Motor();
//void disconnect();
//bool isConnected() const;
int sendCommand(const QString cmd);
//void sendCommandAsync(const QString& command);
int recvData(QByteArray& dataRecv);
private:
QTcpServer* m_tcpServer;
QTcpSocket* m_tcpSocket;
int m_iCommunicationProtocol;
bool m_bConnected;
bool isConnected() const;
public Q_SLOTS:
void onNewConnection();
void onTcpSocketDisconnected();
signals:
void commandSendResult(int bytesWritten, const QString& error = QString());
};
}

View File

@ -41,11 +41,21 @@ void DepthCameraWindow::onSelectDataFolder()
QString::fromLocal8Bit("选择数据保存路径"), QString::fromLocal8Bit("选择数据保存路径"),
ui.dataFolderLineEdit->text()); ui.dataFolderLineEdit->text());
if (!dir.isEmpty()) setDataFolder(dir);
{ }
ui.dataFolderLineEdit->setText(dir);
AppSettings::instance().setDepthCameraDataFolder(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() void DepthCameraWindow::openDepthCamera()
@ -83,6 +93,8 @@ DepthCameraOperation::DepthCameraOperation()
m_pipe = nullptr; m_pipe = nullptr;
m_func = nullptr; m_func = nullptr;
record = false; record = false;
m_captureIntervalMilliseconds = 3000;
} }
DepthCameraOperation::~DepthCameraOperation() DepthCameraOperation::~DepthCameraOperation()
@ -96,6 +108,11 @@ DepthCameraOperation::~DepthCameraOperation()
} }
} }
void DepthCameraOperation::setCaptureInterval(int captureIntervalSeconds)
{
m_captureIntervalMilliseconds = captureIntervalSeconds * 1000;
}
void DepthCameraOperation::OpenDepthCamera() void DepthCameraOperation::OpenDepthCamera()
{ {
if (m_pipe) if (m_pipe)
@ -142,14 +159,14 @@ void DepthCameraOperation::OpenDepthCamera()
// Drop several frames // Drop several frames
for (int i = 0; i < 15; ++i) { 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<ob::PointCloudFilter>(); auto pointCloud = std::make_shared<ob::PointCloudFilter>();
int frameIndex = 0; int frameIndex = 0;
record = true; 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"; QString imuFilePath = fileNamePrefix + "_IMU.txt";
std::ofstream imuFile(imuFilePath.toStdString(), std::ios::out | std::ios::trunc); std::ofstream imuFile(imuFilePath.toStdString(), std::ios::out | std::ios::trunc);
while (record) while (record)
@ -160,7 +177,7 @@ void DepthCameraOperation::OpenDepthCamera()
std::cout << "Start recording..." << std::endl; std::cout << "Start recording..." << std::endl;
} }
auto frameSet = m_pipe->waitForFrameset(100); auto frameSet = m_pipe->waitForFrameset(m_captureIntervalMilliseconds);
if (frameSet == nullptr) if (frameSet == nullptr)
{ {
std::cout << "No frames received in 100ms..." << std::endl; std::cout << "No frames received in 100ms..." << std::endl;
@ -218,7 +235,7 @@ void DepthCameraOperation::OpenDepthCamera()
pointCloud->setCreatePointFormat(OB_FORMAT_RGB_POINT); pointCloud->setCreatePointFormat(OB_FORMAT_RGB_POINT);
std::shared_ptr<ob::Frame> frame = pointCloud->process(frameSet); std::shared_ptr<ob::Frame> 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); ob::PointCloudHelper::savePointcloudToPly(plyPath.toStdString().c_str(), frame, false, false, 50);
//惯导数据 //惯导数据

View File

@ -33,6 +33,8 @@ public:
void setCallback(void(*func)()); void setCallback(void(*func)());
bool getRecordStatus() const { return record; } bool getRecordStatus() const { return record; }
void setCaptureInterval(int captureIntervalSeconds);
private: private:
ob::Pipeline* m_pipe; ob::Pipeline* m_pipe;
cv::Mat frame; cv::Mat frame;
@ -46,6 +48,8 @@ private:
bool record; bool record;
int m_captureIntervalMilliseconds;
public slots: public slots:
void OpenDepthCamera(); void OpenDepthCamera();
void OpenDepthCamera_callback();//不使用信号而使用回调函数来通知界面刷新视频 void OpenDepthCamera_callback();//不使用信号而使用回调函数来通知界面刷新视频
@ -68,6 +72,9 @@ public:
DepthCameraOperation* m_DepthCameraOperation; DepthCameraOperation* m_DepthCameraOperation;
void setDataFolder(QString dir);
void setCaptureInterval(int captureIntervalSeconds);
public Q_SLOTS: public Q_SLOTS:
void openDepthCamera(); void openDepthCamera();
void onCamOpened(); void onCamOpened();

View File

@ -575,6 +575,9 @@ HPPA::HPPA(QWidget* parent)
initMapTools(); initMapTools();
//定时采集
initTimedDataCollection();
QString strPath = QCoreApplication::applicationDirPath() + "/UILayout.ini"; QString strPath = QCoreApplication::applicationDirPath() + "/UILayout.ini";
QFile file(strPath); QFile file(strPath);
if (file.open(QIODevice::ReadOnly)) if (file.open(QIODevice::ReadOnly))
@ -588,6 +591,143 @@ HPPA::HPPA(QWidget* parent)
this->showMaximized(); 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(mTimedDataCollectionWindow, &TimedDataCollection::switchHalogenLampSignal, m_pc3D, &PowerControl3D::switchHalogenLampPower);
connect(mTimedDataCollectionWindow, &TimedDataCollection::switchD65LampSignal, m_pc3D, &PowerControl3D::switchD65LampPower);
connect(mTimedDataCollectionWindow, &TimedDataCollection::switchSlrSignal, m_pc3D, &PowerControl3D::switchSlrPower);
// 相机/马达 → 定时采集控制器
connect(m_tmc, &TwoMotorControl::sequenceComplete, mTimedDataCollectionWindow, &TimedDataCollection::subTaskCompleted);
connect(m_tmc, &TwoMotorControl::back2OriginSignal_TimedDataCollection, mTimedDataCollectionWindow, &TimedDataCollection::onBack2Origin);
}
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_pc3D->slrPowerDown();
m_pc3D->slrPowerOn();
m_singleLensReflexCameraWindow->setDataFolder(folder);
m_singleLensReflexCameraWindow->setCaptureInterval(captureIntervalSeconds);
break;
}
case 3:
{
m_pc3D->d65LampPowerOn();
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:
{
m_tmc->run2(m_singleLensReflexCameraWindow);
break;
}
case 3:
{
m_tmc->run3(m_depthCameraWindow);
break;
}
}
}
void HPPA::onTimedDataCollection()
{
QAction* checkedScenario = m_ScenarioActionGroup->checkedAction();
QString checkedScenarioName = checkedScenario->objectName();
if (checkedScenarioName == "mAction3DPlantPhenotypeScenario")//计划采集
{
mTimedDataCollectionWindow->show();
//mTimedDataCollectionWindow->exec();
return;
}
else if (checkedScenarioName == "mActionPlantPhenotypeScenario")
{
}
}
void HPPA::initMenubarToolbar() void HPPA::initMenubarToolbar()
{ {
//自定义菜单栏和工具栏 //自定义菜单栏和工具栏
@ -833,6 +973,11 @@ void HPPA::initControlTabwidget()
m_pc->setWindowFlags(Qt::Widget); m_pc->setWindowFlags(Qt::Widget);
ui.controlTabWidget->addTab(m_pc, QString::fromLocal8Bit("电源控制")); ui.controlTabWidget->addTab(m_pc, QString::fromLocal8Bit("电源控制"));
//电源控制3D
m_pc3D = new PowerControl3D();
m_pc3D->setWindowFlags(Qt::Widget);
ui.controlTabWidget->addTab(m_pc3D, QString::fromLocal8Bit("电源控制3D"));
//机械臂控制 //机械臂控制
m_rac = new RobotArmControl(); m_rac = new RobotArmControl();
connect(m_rac->robotController, SIGNAL(hsiRecordSignal(int)), this, SLOT(recordFromRobotArm(int))); connect(m_rac->robotController, SIGNAL(hsiRecordSignal(int)), this, SLOT(recordFromRobotArm(int)));
@ -847,7 +992,7 @@ void HPPA::initControlTabwidget()
//2轴马达控制 //2轴马达控制
m_tmc = new TwoMotorControl(this); m_tmc = new TwoMotorControl(this);
//connect(m_tmc, SIGNAL(startLineNumSignal(int)), this, SLOT(onCreateTab(int))); //connect(m_tmc, SIGNAL(startLineNumSignal(int)), this, SLOT(onCreateTab(int)));
connect(m_tmc, SIGNAL(sequenceComplete()), this, SLOT(onsequenceComplete())); connect(m_tmc, &TwoMotorControl::back2OriginSignal, this, &HPPA::onsequenceComplete);
m_tmc->setWindowFlags(Qt::Widget); m_tmc->setWindowFlags(Qt::Widget);
ui.controlTabWidget->addTab(m_tmc, QString::fromLocal8Bit("2轴控制")); ui.controlTabWidget->addTab(m_tmc, QString::fromLocal8Bit("2轴控制"));
@ -1382,7 +1527,8 @@ void HPPA::create3DPlantPhenotypeScenario()
m_tabManager->showTab(m_singleLensReflexCameraWindow); m_tabManager->showTab(m_singleLensReflexCameraWindow);
//m_tabManager->showTab(m_rgbCameraControlWindow); //m_tabManager->showTab(m_rgbCameraControlWindow);
m_tabManager->showTab(m_adt); m_tabManager->showTab(m_adt);
m_tabManager->showTab(m_pc); //m_tabManager->showTab(m_pc);
m_tabManager->showTab(m_pc3D);
m_tabManager->showTab(m_tmc); m_tabManager->showTab(m_tmc);
m_view3DModelManager->switchScenario(View3DModelManager::ScenarioType::PlantPhenotype); m_view3DModelManager->switchScenario(View3DModelManager::ScenarioType::PlantPhenotype);
@ -1523,22 +1669,6 @@ bool HPPA::showResultMessageBox(QString title, QString msg)
void HPPA::onStartRecordStep1() void HPPA::onStartRecordStep1()
{ {
QAction* checkedScenario = m_ScenarioActionGroup->checkedAction();
QString checkedScenarioName = checkedScenario->objectName();
if (checkedScenarioName == "mAction3DPlantPhenotypeScenario")//计划采集
{
TimedDataCollection* tmp = new TimedDataCollection();
/*m_ic->setWindowFlags(Qt::Widget);*/
tmp->show();
//tmp->exec();
return;
}
else if (checkedScenarioName == "mActionPlantPhenotypeScenario")
{
}
//判断移动平台 //判断移动平台
QAction* checked = moveplatformActionGroup->checkedAction(); QAction* checked = moveplatformActionGroup->checkedAction();
if (!checked) if (!checked)

View File

@ -85,6 +85,8 @@
#include "TimedDataCollection.h" #include "TimedDataCollection.h"
#include "PowerControl3D.h"
#define PI 3.1415926 #define PI 3.1415926
QT_CHARTS_USE_NAMESPACE//QChartView 使用 需要加宏, 否则无法使用 QT_CHARTS_USE_NAMESPACE//QChartView 使用 需要加宏, 否则无法使用
@ -290,6 +292,7 @@ private:
SingleLensReflexCameraWindow* m_singleLensReflexCameraWindow; SingleLensReflexCameraWindow* m_singleLensReflexCameraWindow;
adjustTable* m_adt; adjustTable* m_adt;
PowerControl* m_pc; PowerControl* m_pc;
PowerControl3D* m_pc3D;
RobotArmControl* m_rac; RobotArmControl* m_rac;
OneMotorControl* m_omc; OneMotorControl* m_omc;
TwoMotorControl* m_tmc; TwoMotorControl* m_tmc;
@ -318,6 +321,9 @@ private:
bool showResultMessageBox(QString title, QString msg); bool showResultMessageBox(QString title, QString msg);
void disconnectImagerAndCleanup(); void disconnectImagerAndCleanup();
TimedDataCollection* mTimedDataCollectionWindow;
void initTimedDataCollection();
public Q_SLOTS: public Q_SLOTS:
void onPlotHyperspectralImageRgbImage(int fileNumber, int frameNumber, QString filePath); void onPlotHyperspectralImageRgbImage(int fileNumber, int frameNumber, QString filePath);
void focusPlotSpectralImg(int state); void focusPlotSpectralImg(int state);
@ -395,6 +401,12 @@ public Q_SLOTS:
void onMapToolPanTriggered(); void onMapToolPanTriggered();
void onMapToolSpectralTriggered(); 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: protected:
void closeEvent(QCloseEvent* event) override; void closeEvent(QCloseEvent* event) override;

View File

@ -105,6 +105,7 @@ color:white;
<addaction name="action_start_recording"/> <addaction name="action_start_recording"/>
<addaction name="separator"/> <addaction name="separator"/>
<addaction name="actionOpenDirectory"/> <addaction name="actionOpenDirectory"/>
<addaction name="mActionTimedDataCollection"/>
</widget> </widget>
<widget class="QMenu" name="menuhelp"> <widget class="QMenu" name="menuhelp">
<property name="title"> <property name="title">
@ -743,6 +744,11 @@ QPushButton:pressed
<string>3D植物表型</string> <string>3D植物表型</string>
</property> </property>
</action> </action>
<action name="mActionTimedDataCollection">
<property name="text">
<string>定时采集</string>
</property>
</action>
</widget> </widget>
<layoutdefault spacing="6" margin="11"/> <layoutdefault spacing="6" margin="11"/>
<customwidgets> <customwidgets>

View File

@ -112,6 +112,8 @@
<ClCompile Include="AspectRatioLabel.cpp" /> <ClCompile Include="AspectRatioLabel.cpp" />
<ClCompile Include="CaptureCoordinator.cpp" /> <ClCompile Include="CaptureCoordinator.cpp" />
<ClCompile Include="Carousel.cpp" /> <ClCompile Include="Carousel.cpp" />
<ClCompile Include="CommunicationInterfaceBase.cpp" />
<ClCompile Include="CommunicationViaTCP.cpp" />
<ClCompile Include="Corning410Imager.cpp" /> <ClCompile Include="Corning410Imager.cpp" />
<ClCompile Include="CustomDockWidgetBase.cpp" /> <ClCompile Include="CustomDockWidgetBase.cpp" />
<ClCompile Include="DepthCameraWindow.cpp" /> <ClCompile Include="DepthCameraWindow.cpp" />
@ -140,6 +142,7 @@
<ClCompile Include="OneMotorControl.cpp" /> <ClCompile Include="OneMotorControl.cpp" />
<ClCompile Include="path_tc.cpp" /> <ClCompile Include="path_tc.cpp" />
<ClCompile Include="PowerControl.cpp" /> <ClCompile Include="PowerControl.cpp" />
<ClCompile Include="PowerControl3D.cpp" />
<ClCompile Include="QDoubleSlider.cpp" /> <ClCompile Include="QDoubleSlider.cpp" />
<ClCompile Include="QMotorDoubleSlider.cpp" /> <ClCompile Include="QMotorDoubleSlider.cpp" />
<ClCompile Include="RasterDataProvider.cpp" /> <ClCompile Include="RasterDataProvider.cpp" />
@ -189,6 +192,7 @@
<QtUic Include="oneMotorControl.ui" /> <QtUic Include="oneMotorControl.ui" />
<QtUic Include="PathPlan.ui" /> <QtUic Include="PathPlan.ui" />
<QtUic Include="PowerControl.ui" /> <QtUic Include="PowerControl.ui" />
<QtUic Include="PowerControl3D.ui" />
<QtUic Include="RadianceConversion.ui" /> <QtUic Include="RadianceConversion.ui" />
<QtUic Include="ReflectanceConversion.ui" /> <QtUic Include="ReflectanceConversion.ui" />
<QtUic Include="rgbCamera.ui" /> <QtUic Include="rgbCamera.ui" />
@ -223,6 +227,8 @@
<ClInclude Include="AppSettings.h" /> <ClInclude Include="AppSettings.h" />
<QtMoc Include="FileNameLineEdit.h" /> <QtMoc Include="FileNameLineEdit.h" />
<QtMoc Include="DepthCameraWindow.h" /> <QtMoc Include="DepthCameraWindow.h" />
<QtMoc Include="CommunicationViaTCP.h" />
<QtMoc Include="CommunicationInterfaceBase.h" />
<ClInclude Include="imager_base.h" /> <ClInclude Include="imager_base.h" />
<ClInclude Include="irisximeaimager.h" /> <ClInclude Include="irisximeaimager.h" />
<QtMoc Include="OneMotorControl.h" /> <QtMoc Include="OneMotorControl.h" />
@ -244,6 +250,7 @@
<QtMoc Include="MapToolSpectral.h" /> <QtMoc Include="MapToolSpectral.h" />
<QtMoc Include="MapTools.h" /> <QtMoc Include="MapTools.h" />
<ClInclude Include="MotorWindowBase.h" /> <ClInclude Include="MotorWindowBase.h" />
<QtMoc Include="PowerControl3D.h" />
<ClInclude Include="RasterDataProvider.h" /> <ClInclude Include="RasterDataProvider.h" />
<ClInclude Include="MultibandRasterRenderer.h" /> <ClInclude Include="MultibandRasterRenderer.h" />
<ClInclude Include="RasterImageLayer.h" /> <ClInclude Include="RasterImageLayer.h" />
@ -254,7 +261,7 @@
<QtMoc Include="rgbCameraWindow.h" /> <QtMoc Include="rgbCameraWindow.h" />
<QtMoc Include="SingleLensReflexCameraWindow.h" /> <QtMoc Include="SingleLensReflexCameraWindow.h" />
<QtMoc Include="TimedDataCollection.h" /> <QtMoc Include="TimedDataCollection.h" />
<ClInclude Include="TimedDataCollectionDataStructures.h" /> <QtMoc Include="TimedDataCollectionDataStructures.h" />
<ClInclude Include="utility_tc.h" /> <ClInclude Include="utility_tc.h" />
<QtMoc Include="aboutWindow.h" /> <QtMoc Include="aboutWindow.h" />
<ClInclude Include="hppaConfigFile.h" /> <ClInclude Include="hppaConfigFile.h" />

View File

@ -238,6 +238,15 @@
<ClCompile Include="TimedDataCollectionDataStructures.cpp"> <ClCompile Include="TimedDataCollectionDataStructures.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="CommunicationViaTCP.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="CommunicationInterfaceBase.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="PowerControl3D.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<QtMoc Include="fileOperation.h"> <QtMoc Include="fileOperation.h">
@ -384,6 +393,18 @@
<QtMoc Include="TimedDataCollection.h"> <QtMoc Include="TimedDataCollection.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</QtMoc> </QtMoc>
<QtMoc Include="TimedDataCollectionDataStructures.h">
<Filter>Header Files</Filter>
</QtMoc>
<QtMoc Include="CommunicationViaTCP.h">
<Filter>Header Files</Filter>
</QtMoc>
<QtMoc Include="CommunicationInterfaceBase.h">
<Filter>Header Files</Filter>
</QtMoc>
<QtMoc Include="PowerControl3D.h">
<Filter>Header Files</Filter>
</QtMoc>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="imageProcessor.h"> <ClInclude Include="imageProcessor.h">
@ -440,9 +461,6 @@
<ClInclude Include="MotorWindowBase.h"> <ClInclude Include="MotorWindowBase.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="TimedDataCollectionDataStructures.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<QtUic Include="FocusDialog.ui"> <QtUic Include="FocusDialog.ui">
@ -496,6 +514,9 @@
<QtUic Include="TimedDataCollection_ui.ui"> <QtUic Include="TimedDataCollection_ui.ui">
<Filter>Form Files</Filter> <Filter>Form Files</Filter>
</QtUic> </QtUic>
<QtUic Include="PowerControl3D.ui">
<Filter>Form Files</Filter>
</QtUic>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="cpp.hint" /> <None Include="cpp.hint" />

100
HPPA/PowerControl3D.cpp Normal file
View File

@ -0,0 +1,100 @@
#include "PowerControl3D.h"
using namespace MotorParams;
PowerControl3D::PowerControl3D(QWidget* parent)
: QDialog(parent)
{
ui.setupUi(this);
connect(ui.halogenLampPowerOn_btn, &QPushButton::clicked, this, &PowerControl3D::halogenLampPowerOn);
connect(ui.halogenLampPowerDown_btn, &QPushButton::clicked, this, &PowerControl3D::halogenLampPowerDown);
connect(ui.d65LampPowerOn_btn, &QPushButton::clicked, this, &PowerControl3D::d65LampPowerOn);
connect(ui.d65LampPowerDown_btn, &QPushButton::clicked, this, &PowerControl3D::d65LampPowerDown);
connect(ui.slrPowerOn_btn, &QPushButton::clicked, this, &PowerControl3D::slrPowerOn);
connect(ui.slrPowerDown_btn, &QPushButton::clicked, this, &PowerControl3D::slrPowerDown);
MotorParams::TCPConnectionParams tcpConnectionParams6003;
tcpConnectionParams6003.port = 6003;
tcpConnectionParams6003.serverIP = "192.168.1.2";
tcpServer6003 = new CommunicationViaTCP(tcpConnectionParams6003, this);
MotorParams::TCPConnectionParams tcpConnectionParams6004;
tcpConnectionParams6004.port = 6004;
tcpConnectionParams6004.serverIP = "192.168.1.2";
tcpServer6004 = new CommunicationViaTCP(tcpConnectionParams6004, this);
}
PowerControl3D::~PowerControl3D()
{
delete tcpServer6003;
delete tcpServer6004;
}
void PowerControl3D::halogenLampPowerOn()
{
tcpServer6003->sendCommand(R"({"key1":1,"type":"event"})");
}
void PowerControl3D::halogenLampPowerDown()
{
tcpServer6003->sendCommand(R"({"key1":0,"type":"event"})");
}
void PowerControl3D::switchHalogenLampPower(int state)
{
if (state==0)
{
halogenLampPowerDown();
}
else if(state == 1)
{
halogenLampPowerOn();
}
}
void PowerControl3D::d65LampPowerOn()
{
tcpServer6004->sendCommand(R"({"key1":1,"type":"event"})");
}
void PowerControl3D::d65LampPowerDown()
{
tcpServer6004->sendCommand(R"({"key1":0,"type":"event"})");
}
void PowerControl3D::switchD65LampPower(int state)
{
if (state == 0)
{
d65LampPowerDown();
}
else if (state == 1)
{
d65LampPowerOn();
}
}
void PowerControl3D::slrPowerOn()
{
tcpServer6003->sendCommand(R"({"key2":1,"type":"event"})");
}
void PowerControl3D::slrPowerDown()
{
tcpServer6003->sendCommand(R"({"key2":0,"type":"event"})");
}
void PowerControl3D::switchSlrPower(int state)
{
if (state == 0)
{
slrPowerDown();
}
else if (state == 1)
{
slrPowerOn();
}
}

42
HPPA/PowerControl3D.h Normal file
View File

@ -0,0 +1,42 @@
#pragma once
#include <QDialog>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QNetworkAccessManager>
#include "ui_PowerControl3D.h"
#include "CommunicationViaTCP.h"
//using namespace MotorParams;
class PowerControl3D : public QDialog
{
Q_OBJECT
public:
PowerControl3D(QWidget* parent = nullptr);
~PowerControl3D();
public Q_SLOTS:
void halogenLampPowerOn();
void halogenLampPowerDown();
void switchHalogenLampPower(int state);
void d65LampPowerOn();
void d65LampPowerDown();
void switchD65LampPower(int state);
void slrPowerOn();
void slrPowerDown();
void switchSlrPower(int state);
signals:
//void powerOpened();
private:
Ui::PowerControl3D_UI ui;
MotorParams::CommunicationViaTCP* tcpServer6003;
MotorParams::CommunicationViaTCP* tcpServer6004;
};

350
HPPA/PowerControl3D.ui Normal file
View File

@ -0,0 +1,350 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>PowerControl3D_UI</class>
<widget class="QDialog" name="PowerControl3D_UI">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>493</width>
<height>369</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="windowTitle">
<string>PowerControl3D</string>
</property>
<property name="styleSheet">
<string notr="true">QGroupBox
{
border: 12px solid transparent;
/*border-top: 12px solid transparent;
border-right: 0px solid transparent;
border-bottom: 0px solid transparent;
border-left: 0px solid transparent;*/
color: #ACCDFF;
}
QPushButton
{
/*width: 172px;
height: 56px;*/
font: 19pt &quot;新宋体&quot;;
background-color: qlineargradient(
spread:pad,
x1:0.5, y1:0, x2:0.5, y2:1,
stop:0 #283D86,
stop:1 #0F1A40
);
color: white;
border: none;
padding: 8px 16px;
border-radius: 4px;
}
QPushButton:hover
{
background-color: qlineargradient(
spread:pad,
x1:0, y1:0, x2:1, y2:0,
stop:0 #3A4875,
stop:1 #5F6B91
);
}
/* 按下时的效果 */
QPushButton:pressed
{
background-color: qlineargradient(
spread:pad,
x1:0, y1:0, x2:1, y2:0,
stop:0 #1A254F,
stop:1 #3A466B
);
/* 可选:添加下压效果 */
padding-top: 9px;
padding-bottom: 7px;
}</string>
</property>
<layout class="QGridLayout" name="gridLayout_4" rowstretch="1,2,2,2,1" columnstretch="1,10,1">
<item row="0" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>66</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>63</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="1">
<widget class="QGroupBox" name="groupBox_8">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>卤素灯</string>
</property>
<layout class="QGridLayout" name="gridLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>10</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<property name="horizontalSpacing">
<number>18</number>
</property>
<item row="0" column="0">
<widget class="QPushButton" name="halogenLampPowerOn_btn">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>打 开</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="halogenLampPowerDown_btn">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>关 闭</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="1" column="2">
<spacer name="horizontalSpacer_4">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>63</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="0">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>63</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="1">
<widget class="QGroupBox" name="groupBox_7">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>D65灯</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>10</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<property name="horizontalSpacing">
<number>18</number>
</property>
<item row="0" column="0">
<widget class="QPushButton" name="d65LampPowerOn_btn">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>打 开</string>
</property>
</widget>
</item>
<item row="0" column="1">
<widget class="QPushButton" name="d65LampPowerDown_btn">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>关 闭</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="2" column="2">
<spacer name="horizontalSpacer_6">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>63</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="0">
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>63</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="1">
<widget class="QGroupBox" name="groupBox_6">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>单反</string>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>10</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<property name="horizontalSpacing">
<number>18</number>
</property>
<item row="0" column="1">
<widget class="QPushButton" name="slrPowerDown_btn">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>下 电</string>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QPushButton" name="slrPowerOn_btn">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>上 电</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item row="3" column="2">
<spacer name="horizontalSpacer_5">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>63</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="4" column="1">
<spacer name="verticalSpacer_2">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>65</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>

View File

@ -28,6 +28,8 @@ SingleLensReflexCameraWindow::SingleLensReflexCameraWindow(QWidget* parent)
connect(ui.stopTakePhoto_btn, &QPushButton::clicked, this, &SingleLensReflexCameraWindow::stopTakePhoto); connect(ui.stopTakePhoto_btn, &QPushButton::clicked, this, &SingleLensReflexCameraWindow::stopTakePhoto);
connect(this, &SingleLensReflexCameraWindow::stopTakePhotoSignal, m_SingleLensReflexCameraOperation, &SingleLensReflexCameraOperation::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::CamOpenedSignal, this, &SingleLensReflexCameraWindow::onCamOpened);
connect(m_SingleLensReflexCameraOperation, &SingleLensReflexCameraOperation::CamClosedSignal, this, &SingleLensReflexCameraWindow::onCamClosed); connect(m_SingleLensReflexCameraOperation, &SingleLensReflexCameraOperation::CamClosedSignal, this, &SingleLensReflexCameraWindow::onCamClosed);
@ -75,12 +77,31 @@ SingleLensReflexCameraWindow::~SingleLensReflexCameraWindow()
m_SingleLensReflexCameraOperation = nullptr; m_SingleLensReflexCameraOperation = nullptr;
} }
void SingleLensReflexCameraWindow::onStartTimedDataCollection(int lineNum)
{
if (lineNum == 0)
{
OpenAndTakePhotoSLRCamera();
}
}
void SingleLensReflexCameraWindow::onStopTimedDataCollection()
{
stopTakePhoto();
closeSLRCamera();
}
void SingleLensReflexCameraWindow::onSelectDataFolder() void SingleLensReflexCameraWindow::onSelectDataFolder()
{ {
QString dir = QFileDialog::getExistingDirectory(this, QString dir = QFileDialog::getExistingDirectory(this,
QString::fromLocal8Bit("选择数据保存路径"), QString::fromLocal8Bit("选择数据保存路径"),
ui.dataFolderLineEdit->text()); ui.dataFolderLineEdit->text());
setDataFolder(dir);
}
void SingleLensReflexCameraWindow::setDataFolder(QString dir)
{
if (!dir.isEmpty()) if (!dir.isEmpty())
{ {
ui.dataFolderLineEdit->setText(dir); ui.dataFolderLineEdit->setText(dir);
@ -92,6 +113,11 @@ void SingleLensReflexCameraWindow::onSelectDataFolder()
} }
} }
void SingleLensReflexCameraWindow::setCaptureInterval(int captureIntervalSeconds)
{
m_SingleLensReflexCameraOperation->setCaptureInterval(captureIntervalSeconds);
}
void SingleLensReflexCameraWindow::openSLRCamera() void SingleLensReflexCameraWindow::openSLRCamera()
{ {
if (!m_SingleLensReflexCameraOperation->getRecordStatus()) if (!m_SingleLensReflexCameraOperation->getRecordStatus())
@ -108,6 +134,11 @@ void SingleLensReflexCameraWindow::takePhoto()
} }
} }
void SingleLensReflexCameraWindow::OpenAndTakePhotoSLRCamera()
{
emit OpenAndTakePhotoSLRCameraSignal();
}
void SingleLensReflexCameraWindow::stopTakePhoto() void SingleLensReflexCameraWindow::stopTakePhoto()
{ {
if (m_SingleLensReflexCameraOperation->getRecordStatus()) if (m_SingleLensReflexCameraOperation->getRecordStatus())
@ -200,6 +231,7 @@ SingleLensReflexCameraOperation::SingleLensReflexCameraOperation()
m_isSessionOpen = false; m_isSessionOpen = false;
m_isLiveViewActive = false; m_isLiveViewActive = false;
m_imageCounter = 0; m_imageCounter = 0;
m_captureIntervalMilliseconds = 3000;
// 设置保存路径(从 AppSettings 获取,如果为空则使用默认的 CapturedImages 目录) // 设置保存路径(从 AppSettings 获取,如果为空则使用默认的 CapturedImages 目录)
m_savePath = AppSettings::instance().slrDataFolder(); m_savePath = AppSettings::instance().slrDataFolder();
@ -780,13 +812,76 @@ void SingleLensReflexCameraOperation::takePhoto()
// 启动拍照定时器每3秒拍一张 // 启动拍照定时器每3秒拍一张
if (m_captureTimer && !m_captureTimer->isActive()) if (m_captureTimer && !m_captureTimer->isActive())
{ {
m_captureTimer->start(3000); m_captureTimer->start(m_captureIntervalMilliseconds);
std::cout << "capture timer started (1 photo 3 second)" << std::endl; //std::cout << "capture timer started (1 photo 3 second)" << std::endl;
emit CaptureStartedSignal(); emit CaptureStartedSignal();
} }
} }
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;
}
void SingleLensReflexCameraOperation::stopTakePhoto() void SingleLensReflexCameraOperation::stopTakePhoto()
{ {
if (m_captureTimer && m_captureTimer->isActive()) if (m_captureTimer && m_captureTimer->isActive())

View File

@ -46,6 +46,8 @@ public:
// 获取当前实时取景图像 // 获取当前实时取景图像
QImage getCurrentLiveViewImage(); QImage getCurrentLiveViewImage();
void setCaptureInterval(int captureIntervalSeconds);
private: private:
cv::Mat frame; cv::Mat frame;
func m_func; func m_func;
@ -62,6 +64,7 @@ private:
QString m_savePath; QString m_savePath;
int m_imageCounter; int m_imageCounter;
int m_captureIntervalMilliseconds;
QMutex m_mutex; QMutex m_mutex;
QMutex m_liveViewMutex; QMutex m_liveViewMutex;
@ -91,6 +94,7 @@ private:
public slots: public slots:
void OpenSLRCamera(); void OpenSLRCamera();
void takePhoto(); void takePhoto();
void OpenAndTakePhotoSLRCamera();
void stopTakePhoto(); void stopTakePhoto();
void OpenSLRCamera_callback(); void OpenSLRCamera_callback();
void CloseSLRCamera(); void CloseSLRCamera();
@ -127,12 +131,15 @@ public:
~SingleLensReflexCameraWindow(); ~SingleLensReflexCameraWindow();
SingleLensReflexCameraOperation* m_SingleLensReflexCameraOperation; SingleLensReflexCameraOperation* m_SingleLensReflexCameraOperation;
void setDataFolder(QString dir);
void setCaptureInterval(int captureIntervalSeconds);
public Q_SLOTS: public Q_SLOTS:
void onSelectDataFolder(); void onSelectDataFolder();
void openSLRCamera(); void openSLRCamera();
void takePhoto(); void takePhoto();
void OpenAndTakePhotoSLRCamera();
void stopTakePhoto(); void stopTakePhoto();
void onCamOpened(); void onCamOpened();
void closeSLRCamera(); void closeSLRCamera();
@ -148,9 +155,13 @@ public Q_SLOTS:
void onCaptureStarted(); void onCaptureStarted();
void onCaptureStopped(); void onCaptureStopped();
void onStartTimedDataCollection(int lineNum);
void onStopTimedDataCollection();
signals: signals:
void openSLRCameraSignal(); void openSLRCameraSignal();
void takePhotoSignal(); void takePhotoSignal();
void OpenAndTakePhotoSLRCameraSignal();
void stopTakePhotoSignal(); void stopTakePhotoSignal();
void closeSLRCameraSignal(); void closeSLRCameraSignal();
void PlotSLRImageSignal(); void PlotSLRImageSignal();

View File

@ -4,6 +4,7 @@
TimedDataCollection::TimedDataCollection(QWidget* parent) TimedDataCollection::TimedDataCollection(QWidget* parent)
: QDialog(parent) : QDialog(parent)
, m_scheduler(nullptr)
{ {
ui.setupUi(this); ui.setupUi(this);
@ -12,21 +13,69 @@ TimedDataCollection::TimedDataCollection(QWidget* parent)
ui.treeWidget->setDropIndicatorShown(true); // 显示插入位置指示线 ui.treeWidget->setDropIndicatorShown(true); // 显示插入位置指示线
ui.treeWidget->setDragDropMode(QAbstractItemView::InternalMove); // 内部移动 ui.treeWidget->setDragDropMode(QAbstractItemView::InternalMove); // 内部移动
// 初始化调度器
m_scheduler = new TaskScheduler(this);
// 连接调度器信号
connect(m_scheduler, &TaskScheduler::taskStarted, this, &TimedDataCollection::taskStarted);
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::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(m_scheduler, &TaskScheduler::switchHalogenLampSignal, this, &TimedDataCollection::switchHalogenLampSignal);
connect(m_scheduler, &TaskScheduler::switchD65LampSignal, this, &TimedDataCollection::switchD65LampSignal);
connect(m_scheduler, &TaskScheduler::switchSlrSignal, this, &TimedDataCollection::switchSlrSignal);
connect(this, &TimedDataCollection::sequenceCompleteSignal, m_scheduler, &TaskScheduler::sequenceCompleteSignal);
connect(this, &TimedDataCollection::Back2OriginSignal, m_scheduler, &TaskScheduler::Back2OriginSignal);
//writeRead(); //writeRead();
readTimedTaskFromFile("D:/0tmp/3Dtest/task.json"); readTimedTaskFromFile("D:/0tmp/3Dtest/task.json");
connect(ui.run_btn, SIGNAL(clicked()), this, SLOT(run())); // 加载任务到调度器
m_scheduler->loadTasks(m_loadedTasks);
connect(ui.run_btn, &QPushButton::clicked, this, &TimedDataCollection::run); connect(ui.run_btn, &QPushButton::clicked, this, &TimedDataCollection::startScheduler);
startScheduler();
} }
TimedDataCollection::~TimedDataCollection() TimedDataCollection::~TimedDataCollection()
{ {
if (m_scheduler) {
m_scheduler->stop();
}
} }
void TimedDataCollection::run() void TimedDataCollection::subTaskCompleted(int status)
{ {
emit sequenceCompleteSignal(status);
}
void TimedDataCollection::onBack2Origin()
{
emit Back2OriginSignal();
}
void TimedDataCollection::startScheduler()
{
if (m_scheduler) {
m_scheduler->start();
}
}
void TimedDataCollection::stopScheduler()
{
if (m_scheduler) {
m_scheduler->stop();
}
} }
void TimedDataCollection::readTimedTaskFromFile(const QString& filePath) void TimedDataCollection::readTimedTaskFromFile(const QString& filePath)
@ -70,8 +119,8 @@ void TimedDataCollection::writeRead()
subTask.type = types[j]; subTask.type = types[j];
subTask.startTime = task.scheduledTime.addSecs(j * 3600); subTask.startTime = task.scheduledTime.addSecs(j * 3600);
subTask.endTime = subTask.startTime.addSecs(1800); subTask.endTime = subTask.startTime.addSecs(1800);
subTask.durationSeconds = 1800; subTask.durationMinutes = 1800;
subTask.estimatedDurationSeconds = 1800; subTask.estimatedDurationMinutes = 1800;
subTask.pathLineFilePath = QString("D:/0tmp/3Dtest/pathLine/%1.RecordLine3").arg(j); subTask.pathLineFilePath = QString("D:/0tmp/3Dtest/pathLine/%1.RecordLine3").arg(j);
subTask.status = TaskStatus::Waiting; subTask.status = TaskStatus::Waiting;

View File

@ -19,7 +19,32 @@ public:
void readTimedTaskFromFile(const QString& filePath); void readTimedTaskFromFile(const QString& filePath);
public Q_SLOTS: public Q_SLOTS:
void run(); void startScheduler();
void stopScheduler();
void subTaskCompleted(int status);
void onBack2Origin();
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 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 switchHalogenLampSignal(int state);
void switchD65LampSignal(int state);
void switchSlrSignal(int state);
// 马达反馈的信号
void sequenceCompleteSignal(int status);
void Back2OriginSignal();
private: private:
Ui::TimedDataCollection_ui ui; Ui::TimedDataCollection_ui ui;
@ -27,4 +52,5 @@ private:
void writeRead(); void writeRead();
QVector<TimedTask> m_loadedTasks; QVector<TimedTask> m_loadedTasks;
TaskScheduler* m_scheduler;
}; };

View File

@ -1,4 +1,4 @@
#include "TimedDataCollectionDataStructures.h" #include "TimedDataCollectionDataStructures.h"
#include <QJsonDocument> #include <QJsonDocument>
#include <QJsonObject> #include <QJsonObject>
#include <QJsonArray> #include <QJsonArray>
@ -121,8 +121,8 @@ QJsonObject TimedDataCollectionDataStructuresReaderWriter::subTaskToJson(const S
obj["type"] = subTaskTypeToString(subTask.type); obj["type"] = subTaskTypeToString(subTask.type);
obj["startTime"] = subTask.startTime.toString(Qt::ISODate); obj["startTime"] = subTask.startTime.toString(Qt::ISODate);
obj["endTime"] = subTask.endTime.toString(Qt::ISODate); obj["endTime"] = subTask.endTime.toString(Qt::ISODate);
obj["durationSeconds"] = subTask.durationSeconds; obj["durationMinutes"] = subTask.durationMinutes;
obj["estimatedDurationSeconds"] = subTask.estimatedDurationSeconds; obj["estimatedDurationMinutes"] = subTask.estimatedDurationMinutes;
obj["pathLineFilePath"] = subTask.pathLineFilePath; obj["pathLineFilePath"] = subTask.pathLineFilePath;
obj["status"] = taskStatusToString(subTask.status); obj["status"] = taskStatusToString(subTask.status);
obj["frameRate"] = subTask.frameRate; obj["frameRate"] = subTask.frameRate;
@ -137,14 +137,14 @@ bool TimedDataCollectionDataStructuresReaderWriter::jsonToSubTask(const QJsonObj
subTask.type = stringToSubTaskType(json["type"].toString()); subTask.type = stringToSubTaskType(json["type"].toString());
subTask.startTime = QDateTime::fromString(json["startTime"].toString(), Qt::ISODate); subTask.startTime = QDateTime::fromString(json["startTime"].toString(), Qt::ISODate);
subTask.endTime = QDateTime::fromString(json["endTime"].toString(), Qt::ISODate); subTask.endTime = QDateTime::fromString(json["endTime"].toString(), Qt::ISODate);
subTask.durationSeconds = json["durationSeconds"].toInt(); subTask.durationMinutes = json["durationMinutes"].toDouble();
subTask.estimatedDurationSeconds = json["estimatedDurationSeconds"].toInt(); subTask.estimatedDurationMinutes = json["estimatedDurationMinutes"].toDouble();
subTask.pathLineFilePath = json["pathLineFilePath"].toString(); subTask.pathLineFilePath = json["pathLineFilePath"].toString();
subTask.status = stringToTaskStatus(json["status"].toString()); subTask.status = stringToTaskStatus(json["status"].toString());
subTask.frameRate = json["frameRate"].toDouble(); subTask.frameRate = json["frameRate"].toDouble();
subTask.exposureTime = json["exposureTime"].toDouble(); subTask.exposureTime = json["exposureTime"].toDouble();
subTask.defaultRenderBand = json["defaultRenderBand"].toInt(); subTask.defaultRenderBand = json["defaultRenderBand"].toInt();
subTask.captureIntervalSeconds = json["captureIntervalSeconds"].toInt(); subTask.captureIntervalSeconds = json["captureIntervalSeconds"].toDouble();
return true; return true;
} }
@ -157,9 +157,10 @@ QJsonObject TimedDataCollectionDataStructuresReaderWriter::timedTaskToJson(const
obj["scheduledTime"] = task.scheduledTime.toString(Qt::ISODate); obj["scheduledTime"] = task.scheduledTime.toString(Qt::ISODate);
obj["startTime"] = task.startTime.toString(Qt::ISODate); obj["startTime"] = task.startTime.toString(Qt::ISODate);
obj["endTime"] = task.endTime.toString(Qt::ISODate); obj["endTime"] = task.endTime.toString(Qt::ISODate);
obj["durationSeconds"] = task.durationSeconds; obj["durationMinutes"] = task.durationMinutes;
obj["savePath"] = task.savePath; obj["savePath"] = task.savePath;
obj["status"] = taskStatusToString(task.status); obj["status"] = taskStatusToString(task.status);
obj["HalogenLampPreheatingTime_Minute"] = task.HalogenLampPreheatingTime_Minute;
QJsonArray subTasksArray; QJsonArray subTasksArray;
for (const auto& subTask : task.subTasks) { for (const auto& subTask : task.subTasks) {
@ -176,9 +177,10 @@ bool TimedDataCollectionDataStructuresReaderWriter::jsonToTimedTask(const QJsonO
task.scheduledTime = QDateTime::fromString(json["scheduledTime"].toString(), Qt::ISODate); task.scheduledTime = QDateTime::fromString(json["scheduledTime"].toString(), Qt::ISODate);
task.startTime = QDateTime::fromString(json["startTime"].toString(), Qt::ISODate); task.startTime = QDateTime::fromString(json["startTime"].toString(), Qt::ISODate);
task.endTime = QDateTime::fromString(json["endTime"].toString(), Qt::ISODate); task.endTime = QDateTime::fromString(json["endTime"].toString(), Qt::ISODate);
task.durationSeconds = json["durationSeconds"].toInt(); task.durationMinutes = json["durationMinutes"].toDouble();
task.savePath = json["savePath"].toString(); task.savePath = json["savePath"].toString();
task.status = stringToTaskStatus(json["status"].toString()); task.status = stringToTaskStatus(json["status"].toString());
task.HalogenLampPreheatingTime_Minute = json["HalogenLampPreheatingTime_Minute"].toDouble();
QJsonArray subTasksArray = json["subTasks"].toArray(); QJsonArray subTasksArray = json["subTasks"].toArray();
task.subTasks.clear(); task.subTasks.clear();
@ -194,3 +196,420 @@ bool TimedDataCollectionDataStructuresReaderWriter::jsonToTimedTask(const QJsonO
return true; return true;
} }
// ==================== TaskExecutor 实现 ====================
TaskExecutor::TaskExecutor(QObject* parent)
: QObject(parent)
, m_currentSubTaskIndex(0)
, m_isRunning(false)
{
}
TaskExecutor::~TaskExecutor()
{
stop();
}
void TaskExecutor::execute(const TimedTask& task)
{
if (m_isRunning) {
qWarning() << "TaskExecutor: Already running, ignoring execute request";
return;
}
m_task = task;
m_task.startTime = QDateTime::currentDateTime();
m_currentSubTaskIndex = 0;
m_isRunning = true;
qDebug() << "TaskExecutor: Starting task" << task.id;
// 打开卤素灯预热
emit switchHalogenLampSignal(1);
printMsgAndTime("open HalogenLamp");
makeFolder(m_task.savePath);
// 开始执行第一个子任务
double sleepTimeSecond = m_task.HalogenLampPreheatingTime_Minute * 60;
QTimer::singleShot(sleepTimeSecond *1000, this, &TaskExecutor::executeNextSubTask);
}
void TaskExecutor::printMsgAndTime(QString msg)
{
QDateTime now = QDateTime::currentDateTime();
QString timeString = now.toString("yyyy-MM-dd hh:mm:ss.zzz");
qDebug() << msg + " time:" << timeString;
}
void TaskExecutor::stop()
{
if (!m_isRunning) return;
qDebug() << "TaskExecutor: Stopping task" << m_task.id;
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;
qDebug() << "TaskExecutor: Sequence complete, status:" << status;
// 更新当前子任务状态
if (m_currentSubTaskIndex < m_task.subTasks.size()) {
SubTask& subTask = m_task.subTasks[m_currentSubTaskIndex];
subTask.status = (status == 0) ? TaskStatus::Finished : TaskStatus::Waiting;
subTask.endTime = QDateTime::currentDateTime();
subTask.durationMinutes = (double)subTask.startTime.secsTo(subTask.endTime) / 60;
qDebug() << "TaskExecutor: subtask "<< m_currentSubTaskIndex<< " time consuming(Minutes): "<< subTask.durationMinutes;
emit subTaskFinished(m_currentSubTaskIndex, subTask.type, (status == 0));
}
//
switch (m_task.subTasks[m_currentSubTaskIndex].type)
{
case SubTaskType::SingleLensReflex:
{
emit switchD65LampSignal(0);
emit switchSlrSignal(0);
break;
}
case SubTaskType::DepthCamera:
{
emit switchD65LampSignal(0);
break;
}
}
// 判断下一次的任务是否为高光谱任务,如果不是关闭卤素灯
int nestSubTaskIndex = m_currentSubTaskIndex + 1;
if (nestSubTaskIndex >= m_task.subTasks.size())
{
emit switchHalogenLampSignal(0);
return;
}
switch (m_task.subTasks[nestSubTaskIndex].type)
{
case SubTaskType::SingleLensReflex:
{
emit switchHalogenLampSignal(0);
break;
}
case SubTaskType::DepthCamera:
{
emit switchHalogenLampSignal(0);
break;
}
}
}
void TaskExecutor::onBack2Origin()
{
// 检查是否还有更多子任务
m_currentSubTaskIndex++;
if (m_currentSubTaskIndex < m_task.subTasks.size()) {
// 执行下一个子任务
if(m_task.subTasks[m_currentSubTaskIndex].type== SubTaskType::SingleLensReflex)
{
printMsgAndTime("Slr taskfor weak upplease wait 135 seconds!");
emit switchSlrSignal(0);
QTimer::singleShot(135*1000, this, &TaskExecutor::executeNextSubTask);
}
else
{
QTimer::singleShot(1000, this, &TaskExecutor::executeNextSubTask);
}
}
else {
// 所有子任务完成
m_task.endTime = QDateTime::currentDateTime();
m_task.durationMinutes = (double)m_task.startTime.secsTo(m_task.endTime) / 60;
qDebug() << "TaskExecutor: task time consuming(Minutes): " << m_task.durationMinutes;
m_isRunning = false;
qDebug() << "TaskExecutor: All subtasks completed";
emit finished(true);
}
}
void TaskExecutor::onError(const QString& error)
{
if (!m_isRunning) return;
qWarning() << "TaskExecutor: Error occurred:" << error;
m_isRunning = false;
emit errorOccurred(error);
emit finished(false);
}
void TaskExecutor::executeNextSubTask()
{
if (!m_isRunning || m_currentSubTaskIndex >= m_task.subTasks.size()) {
return;
}
SubTask& subTask = m_task.subTasks[m_currentSubTaskIndex];
subTask.status = TaskStatus::Running;
subTask.startTime = QDateTime::currentDateTime();
QString tmp = "TaskExecutor: Starting subtask" + QString::number(m_currentSubTaskIndex) + "type:" + static_cast<int>(subTask.type);
printMsgAndTime(tmp);
//printMsgAndTime("excute " + QString::number(m_currentSubTaskIndex) + " subTask: ");
//qDebug() << "TaskExecutor: Starting subtask" << m_currentSubTaskIndex
// << "type:" << static_cast<int>(subTask.type);
emit subTaskStarted(m_currentSubTaskIndex, subTask.type);
emit motorParm(subTask.pathLineFilePath);
int camType;
switch (subTask.type)
{
case SubTaskType::HyperSpectual400_1000nm:
{
camType = 0;
emit hyperCamParm(camType, subTask.frameRate, subTask.exposureTime, makeSubTaskDataFolder("L"), "test");
break;
}
case SubTaskType::HyperSpectual1000_1700nm:
{
camType = 1;
emit hyperCamParm(camType, subTask.frameRate, subTask.exposureTime, makeSubTaskDataFolder("NIR"), "test");
break;
}
case SubTaskType::SingleLensReflex:
{
camType = 2;
emit camParm(camType, 3, makeSubTaskDataFolder("SLR"));
emit switchD65LampSignal(1);
emit switchSlrSignal(1);
break;
}
case SubTaskType::DepthCamera:
{
camType = 3;
emit camParm(camType, 3, makeSubTaskDataFolder("DepthCamera"));
emit switchD65LampSignal(1);
break;
}
}
emit startRecordSignal(camType);
}
// ==================== TaskScheduler 实现 ====================
TaskScheduler::TaskScheduler(QObject* parent)
: QObject(parent)
, m_timer(nullptr)
, m_currentExecutor(nullptr)
, m_currentTaskId(-1)
{
}
TaskScheduler::~TaskScheduler()
{
stop();
}
void TaskScheduler::loadTasks(const QVector<TimedTask>& tasks)
{
m_tasks = tasks;
qDebug() << "TaskScheduler: Loaded" << tasks.size() << "tasks";
}
void TaskScheduler::start()
{
if (m_timer) {
qDebug() << "TaskScheduler: Already running";
return;
}
qDebug() << "TaskScheduler: Starting";
m_timer = new QTimer(this);
connect(m_timer, &QTimer::timeout, this, &TaskScheduler::checkTasks);
m_timer->start(1000); // 每秒检查一次
emit schedulerStateChanged(true);
}
void TaskScheduler::stop()
{
if (m_timer) {
m_timer->stop();
delete m_timer;
m_timer = nullptr;
}
if (m_currentExecutor) {
m_currentExecutor->stop();
m_currentExecutor->deleteLater();
m_currentExecutor = nullptr;
}
qDebug() << "TaskScheduler: Stopped";
emit schedulerStateChanged(false);
}
void TaskScheduler::checkTasks()
{
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; // 一次只执行一个任务
}
}
void TaskScheduler::onTaskFinished(bool success)
{
if (m_currentTaskId > 0) {
TaskStatus status = success ? TaskStatus::Finished : TaskStatus::Waiting;
updateTaskStatus(m_currentTaskId, status);
emit taskFinished(m_currentTaskId, success);
}
// 清理执行器
if (m_currentExecutor) {
m_currentExecutor->deleteLater();
m_currentExecutor = nullptr;
}
m_currentTaskId = -1;
}
void TaskScheduler::onSubTaskStarted(int subTaskIndex, SubTaskType type)
{
if (m_currentTaskId > 0) {
emit subTaskStarted(m_currentTaskId, subTaskIndex);
}
}
void TaskScheduler::onSubTaskFinished(int subTaskIndex, SubTaskType type, bool success)
{
if (m_currentTaskId > 0) {
emit subTaskFinished(m_currentTaskId, subTaskIndex);
}
}
void TaskScheduler::onExecutorError(const QString& error)
{
emitError(error);
}
void TaskScheduler::executeTask(TimedTask& task)
{
qDebug() << "TaskScheduler: Executing task" << task.id;
updateTaskStatus(task.id, TaskStatus::Running);
m_currentTaskId = task.id;
emit taskStarted(task.id);
// 创建任务执行器
m_currentExecutor = new TaskExecutor(this);
// 连接信号
connect(m_currentExecutor, &TaskExecutor::finished,
this, &TaskScheduler::onTaskFinished);
connect(m_currentExecutor, &TaskExecutor::subTaskStarted,
this, &TaskScheduler::onSubTaskStarted);
connect(m_currentExecutor, &TaskExecutor::subTaskFinished,
this, &TaskScheduler::onSubTaskFinished);
connect(m_currentExecutor, &TaskExecutor::errorOccurred,
this, &TaskScheduler::onExecutorError);
// 采集相关信号透传
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(m_currentExecutor, &TaskExecutor::switchHalogenLampSignal, this, &TaskScheduler::switchHalogenLampSignal);
connect(m_currentExecutor, &TaskExecutor::switchD65LampSignal, this, &TaskScheduler::switchD65LampSignal);
connect(m_currentExecutor, &TaskExecutor::switchSlrSignal, this, &TaskScheduler::switchSlrSignal);
connect(this, &TaskScheduler::sequenceCompleteSignal, m_currentExecutor, &TaskExecutor::onSequenceComplete);
connect(this, &TaskScheduler::Back2OriginSignal, m_currentExecutor, &TaskExecutor::onBack2Origin);
// 开始执行
m_currentExecutor->execute(task);
}
void TaskScheduler::updateTaskStatus(int taskId, TaskStatus status)
{
for (auto& task : m_tasks) {
if (task.id == taskId) {
task.status = status;
if (status == TaskStatus::Running) {
task.startTime = QDateTime::currentDateTime();
} else if (status == TaskStatus::Finished) {
task.endTime = QDateTime::currentDateTime();
}
break;
}
}
}
void TaskScheduler::emitError(const QString& error)
{
qWarning() << "TaskScheduler: Error:" << error;
emit errorOccurred(error);
}

View File

@ -4,6 +4,9 @@
#include <QString> #include <QString>
#include <QVector> #include <QVector>
#include <QMetaType> #include <QMetaType>
#include <QTimer>
#include "CaptureCoordinator.h"
// ==================== 枚举定义 ==================== // ==================== 枚举定义 ====================
@ -11,7 +14,8 @@
enum class TaskStatus { enum class TaskStatus {
Waiting, // 等待 Waiting, // 等待
Running, // 运行中 Running, // 运行中
Finished // 结束 Finished, // 结束
Skiped //跳过
}; };
// 子任务类型 // 子任务类型
@ -30,8 +34,8 @@ struct SubTask {
// 共享属性 // 共享属性
QDateTime startTime; QDateTime startTime;
QDateTime endTime; QDateTime endTime;
int durationSeconds = 0; double durationMinutes = 0;
int estimatedDurationSeconds = 0; double estimatedDurationMinutes = 0;
QString pathLineFilePath; QString pathLineFilePath;
TaskStatus status = TaskStatus::Waiting; TaskStatus status = TaskStatus::Waiting;
@ -49,16 +53,17 @@ struct TimedTask {
QDateTime scheduledTime; // 计划时间 QDateTime scheduledTime; // 计划时间
QDateTime startTime; // 开始时间 QDateTime startTime; // 开始时间
QDateTime endTime; // 结束时间 QDateTime endTime; // 结束时间
int durationSeconds = 0; // 耗时(秒) double durationMinutes = 0; // 耗时(秒)
QString savePath; // 数据保存路径 QString savePath; // 数据保存路径
QVector<SubTask> subTasks; // 子任务列表 QVector<SubTask> subTasks; // 子任务列表
TaskStatus status = TaskStatus::Waiting; // 状态 TaskStatus status = TaskStatus::Waiting; // 状态
double HalogenLampPreheatingTime_Minute;
// 计算所有子任务的预计总时间 // 计算所有子任务的预计总时间
int totalEstimatedDuration() const { int totalEstimatedDuration() const {
int total = 0; int total = 0;
for (const auto& subTask : subTasks) { for (const auto& subTask : subTasks) {
total += subTask.estimatedDurationSeconds; total += subTask.estimatedDurationMinutes;
} }
return total; return total;
} }
@ -102,3 +107,129 @@ private:
static QString subTaskTypeToString(SubTaskType type); static QString subTaskTypeToString(SubTaskType type);
static SubTaskType stringToSubTaskType(const QString& str); static SubTaskType stringToSubTaskType(const QString& str);
}; };
// ==================== 任务执行器 ====================
class TaskExecutor : public QObject
{
Q_OBJECT
public:
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; }
// 获取正在执行的任务
const TimedTask& currentTask() const { return m_task; }
// 是否正在执行
bool isRunning() const { return m_isRunning; }
// 停止执行
void stop();
signals:
void finished(bool success); // 任务完成
void subTaskStarted(int subTaskIndex, SubTaskType type); // 子任务开始
void subTaskFinished(int subTaskIndex, SubTaskType type, bool success); // 子任务完成
void errorOccurred(const QString& error); // 错误发生
// 采集相关信号
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 switchHalogenLampSignal(int state);
void switchD65LampSignal(int state);
void switchSlrSignal(int state);
public slots:
void onSequenceComplete(int status);
void onBack2Origin();
void onError(const QString& error);
private:
void executeNextSubTask();
void printMsgAndTime(QString msg);
TimedTask m_task;
int m_currentSubTaskIndex;
bool m_isRunning;
};
// ==================== 任务调度器 ====================
class TaskScheduler : public QObject
{
Q_OBJECT
public:
explicit TaskScheduler(QObject* parent = nullptr);
~TaskScheduler();
// 加载任务列表
void loadTasks(const QVector<TimedTask>& tasks);
// 获取任务列表
QVector<TimedTask> tasks() const { return m_tasks; }
// 开始调度
void start();
// 停止调度
void stop();
// 是否正在运行
bool isRunning() const { return m_timer != nullptr && m_timer->isActive(); }
signals:
void taskStarted(int taskId); // 任务开始
void taskFinished(int taskId, bool success); // 任务完成
void schedulerStateChanged(bool running); // 调度器状态变化
// 子任务的信号
void subTaskStarted(int taskId, int subTaskIndex); // 子任务开始
void subTaskFinished(int taskId, int subTaskIndex); // 子任务完成
void errorOccurred(const QString& error); // 错误发生
// 采集相关信号 (透传 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 switchHalogenLampSignal(int state);
void switchD65LampSignal(int state);
void switchSlrSignal(int state);
// 马达反馈的信号
void sequenceCompleteSignal(int status);
void Back2OriginSignal();
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);
private:
void executeTask(TimedTask& task);
void updateTaskStatus(int taskId, TaskStatus status);
void emitError(const QString& error);
QTimer* m_timer;
QVector<TimedTask> m_tasks;
TaskExecutor* m_currentExecutor;
int m_currentTaskId;
};

View File

@ -6,314 +6,273 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>970</width> <width>1160</width>
<height>456</height> <height>576</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>Dialog</string> <string>Dialog</string>
</property> </property>
<widget class="QTreeWidget" name="treeWidget"> <layout class="QGridLayout" name="gridLayout_2">
<property name="geometry"> <item row="0" column="0" colspan="3">
<rect> <widget class="QWidget" name="widget" native="true">
<x>9</x> <layout class="QGridLayout" name="gridLayout">
<y>9</y> <item row="0" column="0">
<width>491</width> <widget class="QTreeWidget" name="treeWidget">
<height>281</height> <property name="allColumnsShowFocus">
</rect> <bool>false</bool>
</property> </property>
<property name="allColumnsShowFocus"> <attribute name="headerVisible">
<bool>false</bool> <bool>true</bool>
</property> </attribute>
<attribute name="headerVisible"> <column>
<bool>true</bool> <property name="text">
</attribute> <string>任务</string>
<column> </property>
<property name="text"> </column>
<string>任务</string> <column>
</property> <property name="text">
</column> <string>计划时间</string>
<column> </property>
<property name="text"> </column>
<string>计划时间</string> <column>
</property> <property name="text">
</column> <string>开始时间</string>
<column> </property>
<property name="text"> </column>
<string>开始时间</string> <column>
</property> <property name="text">
</column> <string>结束时间</string>
<column> </property>
<property name="text"> </column>
<string>结束时间</string> <column>
</property> <property name="text">
</column> <string>耗时</string>
<column> </property>
<property name="text"> </column>
<string>耗时</string> <column>
</property> <property name="text">
</column> <string>状态</string>
<column> </property>
<property name="text"> </column>
<string>状态</string> <item>
</property> <property name="text">
</column> <string>1</string>
<item> </property>
<property name="text"> <property name="text">
<string>1</string> <string/>
</property> </property>
<property name="text"> <property name="text">
<string/> <string/>
</property> </property>
<property name="text"> <property name="text">
<string/> <string/>
</property> </property>
<property name="text"> <property name="text">
<string/> <string/>
</property> </property>
<property name="text"> <property name="text">
<string/> <string/>
</property> </property>
<property name="text"> <item>
<string/> <property name="text">
</property> <string>a</string>
<item> </property>
<property name="text"> <property name="text">
<string>a</string> <string/>
</property> </property>
<property name="text"> <property name="text">
<string/> <string/>
</property> </property>
<property name="text"> <property name="text">
<string/> <string/>
</property> </property>
<property name="text"> <property name="text">
<string/> <string/>
</property> </property>
<property name="text"> <property name="text">
<string/> <string/>
</property> </property>
<property name="text"> </item>
<string/> <item>
</property> <property name="text">
</item> <string>b</string>
<item> </property>
<property name="text"> </item>
<string>b</string> </item>
</property> <item>
</item> <property name="text">
<string>2</string>
</property>
<property name="text">
<string/>
</property>
<property name="text">
<string/>
</property>
<property name="text">
<string/>
</property>
<property name="text">
<string/>
</property>
<property name="text">
<string/>
</property>
<item>
<property name="text">
<string>a</string>
</property>
</item>
<item>
<property name="text">
<string>b</string>
</property>
</item>
</item>
<item>
<property name="text">
<string>3</string>
</property>
<property name="text">
<string/>
</property>
<property name="text">
<string/>
</property>
<property name="text">
<string/>
</property>
<property name="text">
<string/>
</property>
<property name="text">
<string/>
</property>
<item>
<property name="text">
<string>a</string>
</property>
</item>
<item>
<property name="text">
<string>b</string>
</property>
</item>
</item>
<item>
<property name="text">
<string>4</string>
</property>
<property name="text">
<string/>
</property>
<property name="text">
<string/>
</property>
<property name="text">
<string/>
</property>
<property name="text">
<string/>
</property>
<property name="text">
<string/>
</property>
<item>
<property name="text">
<string>a</string>
</property>
</item>
<item>
<property name="text">
<string>b</string>
</property>
</item>
</item>
<item>
<property name="text">
<string>5</string>
</property>
<property name="text">
<string/>
</property>
<property name="text">
<string/>
</property>
<property name="text">
<string/>
</property>
<property name="text">
<string/>
</property>
<property name="text">
<string/>
</property>
<item>
<property name="text">
<string>a</string>
</property>
</item>
<item>
<property name="text">
<string>b</string>
</property>
</item>
</item>
</widget>
</item>
<item row="0" column="1">
<widget class="QStackedWidget" name="stackedWidget">
<property name="currentIndex">
<number>1</number>
</property>
<widget class="QWidget" name="page"/>
<widget class="QWidget" name="page_2"/>
</widget>
</item>
</layout>
</widget>
</item> </item>
<item> <item row="1" column="0">
<property name="text"> <widget class="QPushButton" name="addToptask_btn">
<string>2</string>
</property>
<property name="text">
<string/>
</property>
<property name="text">
<string/>
</property>
<property name="text">
<string/>
</property>
<property name="text">
<string/>
</property>
<property name="text">
<string/>
</property>
<item>
<property name="text"> <property name="text">
<string>a</string> <string>添加总计划任务</string>
</property> </property>
</item> </widget>
<item>
<property name="text">
<string>b</string>
</property>
</item>
</item> </item>
<item> <item row="2" column="0">
<property name="text"> <widget class="QPushButton" name="delToptask_btn">
<string>3</string>
</property>
<property name="text">
<string/>
</property>
<property name="text">
<string/>
</property>
<property name="text">
<string/>
</property>
<property name="text">
<string/>
</property>
<property name="text">
<string/>
</property>
<item>
<property name="text"> <property name="text">
<string>a</string> <string>删除总计划任务</string>
</property> </property>
</item> </widget>
<item>
<property name="text">
<string>b</string>
</property>
</item>
</item> </item>
<item> <item row="3" column="0">
<property name="text"> <widget class="QPushButton" name="addSubtask_btn">
<string>4</string>
</property>
<property name="text">
<string/>
</property>
<property name="text">
<string/>
</property>
<property name="text">
<string/>
</property>
<property name="text">
<string/>
</property>
<property name="text">
<string/>
</property>
<item>
<property name="text"> <property name="text">
<string>a</string> <string>添加子任务</string>
</property> </property>
</item> </widget>
<item>
<property name="text">
<string>b</string>
</property>
</item>
</item> </item>
<item> <item row="3" column="1">
<property name="text"> <widget class="QComboBox" name="comboBox"/>
<string>5</string>
</property>
<property name="text">
<string/>
</property>
<property name="text">
<string/>
</property>
<property name="text">
<string/>
</property>
<property name="text">
<string/>
</property>
<property name="text">
<string/>
</property>
<item>
<property name="text">
<string>a</string>
</property>
</item>
<item>
<property name="text">
<string>b</string>
</property>
</item>
</item> </item>
</widget> <item row="4" column="0">
<widget class="QPushButton" name="addToptask_btn"> <widget class="QPushButton" name="delSubtask_btn">
<property name="geometry"> <property name="text">
<rect> <string>删除子任务</string>
<x>40</x> </property>
<y>310</y> </widget>
<width>101</width> </item>
<height>23</height> <item row="4" column="2">
</rect> <widget class="QPushButton" name="run_btn">
</property> <property name="text">
<property name="text"> <string>运行</string>
<string>添加总计划任务</string> </property>
</property> </widget>
</widget> </item>
<widget class="QPushButton" name="addSubtask_btn"> </layout>
<property name="geometry">
<rect>
<x>40</x>
<y>370</y>
<width>101</width>
<height>23</height>
</rect>
</property>
<property name="text">
<string>添加子任务</string>
</property>
</widget>
<widget class="QComboBox" name="comboBox">
<property name="geometry">
<rect>
<x>170</x>
<y>370</y>
<width>69</width>
<height>22</height>
</rect>
</property>
</widget>
<widget class="QPushButton" name="delSubtask_btn">
<property name="geometry">
<rect>
<x>40</x>
<y>410</y>
<width>101</width>
<height>23</height>
</rect>
</property>
<property name="text">
<string>删除子任务</string>
</property>
</widget>
<widget class="QPushButton" name="delToptask_btn">
<property name="geometry">
<rect>
<x>40</x>
<y>340</y>
<width>101</width>
<height>23</height>
</rect>
</property>
<property name="text">
<string>删除总计划任务</string>
</property>
</widget>
<widget class="QStackedWidget" name="stackedWidget">
<property name="geometry">
<rect>
<x>520</x>
<y>20</y>
<width>381</width>
<height>261</height>
</rect>
</property>
<property name="currentIndex">
<number>1</number>
</property>
<widget class="QWidget" name="page"/>
<widget class="QWidget" name="page_2"/>
</widget>
<widget class="QPushButton" name="run_btn">
<property name="geometry">
<rect>
<x>850</x>
<y>420</y>
<width>101</width>
<height>23</height>
</rect>
</property>
<property name="text">
<string>运行</string>
</property>
</widget>
</widget> </widget>
<resources/> <resources/>
<connections/> <connections/>

View File

@ -103,6 +103,113 @@ void TwoMotorControl::record_white()
m_whiteCaptureCoordinator->startStepMotion(s); 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_TimedDataCollection = new TwoMotionCaptureCoordinator(m_multiAxisController);
connect(this, SIGNAL(start(QVector<PathLine>)), m_coordinator_TimedDataCollection, SLOT(start(QVector<PathLine>)));
connect(m_coordinator_TimedDataCollection, &TwoMotionCaptureCoordinator::startRecordLineNumSignal, this, &TwoMotorControl::receiveStartRecordLineNum);
connect(m_coordinator_TimedDataCollection, &TwoMotionCaptureCoordinator::finishRecordLineNumSignal, this, &TwoMotorControl::receiveFinishRecordLineNum);
connect(m_coordinator_TimedDataCollection, &TwoMotionCaptureCoordinator::startRecordLineNumSignal, window, &SingleLensReflexCameraWindow::onStartTimedDataCollection);
connect(m_coordinator_TimedDataCollection, &TwoMotionCaptureCoordinator::sequenceComplete, window, &SingleLensReflexCameraWindow::onStopTimedDataCollection);
connect(m_coordinator_TimedDataCollection, &TwoMotionCaptureCoordinator::sequenceComplete, this, &TwoMotorControl::sequenceComplete);
connect(m_coordinator_TimedDataCollection, &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::run3(DepthCameraWindow* window)
{
int rowCount = ui.recordLine_tableWidget->rowCount();
if (rowCount == 0)
{
QMessageBox::information(this, QString::fromLocal8Bit("提示"), QString::fromLocal8Bit("请至少添加一行采集线!"));
emit sequenceComplete(0);
return;
}
m_coordinator_TimedDataCollection = new TwoMotionCaptureCoordinator(m_multiAxisController);
connect(this, SIGNAL(start(QVector<PathLine>)), m_coordinator_TimedDataCollection, SLOT(start(QVector<PathLine>)));
connect(m_coordinator_TimedDataCollection, &TwoMotionCaptureCoordinator::startRecordLineNumSignal, this, &TwoMotorControl::receiveStartRecordLineNum);
connect(m_coordinator_TimedDataCollection, &TwoMotionCaptureCoordinator::finishRecordLineNumSignal, this, &TwoMotorControl::receiveFinishRecordLineNum);
connect(m_coordinator_TimedDataCollection, &TwoMotionCaptureCoordinator::startRecordLineNumSignal, window, &DepthCameraWindow::openDepthCamera);
connect(m_coordinator_TimedDataCollection, &TwoMotionCaptureCoordinator::sequenceComplete, window, &DepthCameraWindow::closeDepthCamera);
connect(m_coordinator_TimedDataCollection, &TwoMotionCaptureCoordinator::sequenceComplete, this, &TwoMotorControl::sequenceComplete);
connect(m_coordinator_TimedDataCollection, &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_TimedDataCollection->deleteLater();
m_coordinator_TimedDataCollection = nullptr;
emit back2OriginSignal_TimedDataCollection();
}
void TwoMotorControl::run() void TwoMotorControl::run()
{ {
if (getState()) if (getState())
@ -116,7 +223,7 @@ void TwoMotorControl::run()
{ {
QMessageBox::information(this, QString::fromLocal8Bit("提示"), QString::fromLocal8Bit("请至少添加一行采集线!")); QMessageBox::information(this, QString::fromLocal8Bit("提示"), QString::fromLocal8Bit("请至少添加一行采集线!"));
emit sequenceComplete(); emit sequenceComplete(0);
return; return;
} }
@ -129,7 +236,8 @@ void TwoMotorControl::run()
connect(this, SIGNAL(stopSignal()), m_coordinator, SLOT(stop())); connect(this, SIGNAL(stopSignal()), m_coordinator, SLOT(stop()));
connect(m_coordinator, SIGNAL(startRecordLineNumSignal(int)), this, SLOT(receiveStartRecordLineNum(int))); connect(m_coordinator, SIGNAL(startRecordLineNumSignal(int)), this, SLOT(receiveStartRecordLineNum(int)));
connect(m_coordinator, SIGNAL(finishRecordLineNumSignal(int)), this, SLOT(receiveFinishRecordLineNum(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::back2OriginSignal, this, &TwoMotorControl::onBack2Origin);
connect(m_coordinator, &TwoMotionCaptureCoordinator::startRecordHSISignal, m_Imager, &ImagerOperationBase::start_record); connect(m_coordinator, &TwoMotionCaptureCoordinator::startRecordHSISignal, m_Imager, &ImagerOperationBase::start_record);
connect(m_coordinator, &TwoMotionCaptureCoordinator::stopRecordHSISignal, this, &TwoMotorControl::stop_record); connect(m_coordinator, &TwoMotionCaptureCoordinator::stopRecordHSISignal, this, &TwoMotorControl::stop_record);
@ -263,16 +371,22 @@ void TwoMotorControl::receiveFinishRecordLineNum(int lineNum)
} }
} }
void TwoMotorControl::onSequenceComplete() void TwoMotorControl::onSequenceComplete(int status)
{ {
isWritePosFile = false; isWritePosFile = false;
fclose(m_posFileHandle); fclose(m_posFileHandle);
emit sequenceComplete(status);
}
void TwoMotorControl::onBack2Origin()
{
m_coordinatorThread.quit(); m_coordinatorThread.quit();
m_coordinatorThread.wait(); m_coordinatorThread.wait();
m_coordinator = nullptr; m_coordinator = nullptr;
emit sequenceComplete(); emit back2OriginSignal();
emit back2OriginSignal_TimedDataCollection();
} }
bool TwoMotorControl::getMotorsConnectionStatus() bool TwoMotorControl::getMotorsConnectionStatus()
@ -551,7 +665,10 @@ void TwoMotorControl::onReadRecordLineFile_btn()
{ {
return; return;
} }
readRecordLineFile(RecordLineFilePath);
}
void TwoMotorControl::readRecordLineFile(QString RecordLineFilePath)
{
FILE* RecordLineFileHandle = fopen(RecordLineFilePath.toStdString().c_str(), "rb"); FILE* RecordLineFileHandle = fopen(RecordLineFilePath.toStdString().c_str(), "rb");
double number; double number;

View File

@ -10,6 +10,9 @@
#include "CaptureCoordinator.h" #include "CaptureCoordinator.h"
#include "MotorWindowBase.h" #include "MotorWindowBase.h"
#include "SingleLensReflexCameraWindow.h"
#include "DepthCameraWindow.h"
#define PI 3.1415926 #define PI 3.1415926
class TwoMotorControl : public QDialog, public MotorWindowBase class TwoMotorControl : public QDialog, public MotorWindowBase
@ -28,6 +31,8 @@ public:
bool getMotorsConnectionStatus(); bool getMotorsConnectionStatus();
void readRecordLineFile(QString RecordLineFilePath);
private: private:
ImagerOperationBase* m_Imager; ImagerOperationBase* m_Imager;
bool getState(); bool getState();
@ -68,7 +73,12 @@ public Q_SLOTS:
void stop(); void stop();
void receiveStartRecordLineNum(int lineNum); void receiveStartRecordLineNum(int lineNum);
void receiveFinishRecordLineNum(int lineNum); void receiveFinishRecordLineNum(int lineNum);
void onSequenceComplete(); void onSequenceComplete(int status);
void onBack2Origin();
void run2(SingleLensReflexCameraWindow* w);
void run3(DepthCameraWindow* window);
void onBack2Origin2();
void stop_record(); void stop_record();
@ -86,7 +96,9 @@ signals:
void stopSignal(); void stopSignal();
void startLineNumSignal(int lineNum); void startLineNumSignal(int lineNum);
void sequenceComplete();//所有采集线正常运行完成 void sequenceComplete(int status);//所有采集线正常运行完成
void back2OriginSignal();
void back2OriginSignal_TimedDataCollection();
void broadcastLocationSignal(std::vector<double>); void broadcastLocationSignal(std::vector<double>);
@ -94,6 +106,7 @@ private:
Ui::twoMotorControl_UI ui; Ui::twoMotorControl_UI ui;
QThread m_coordinatorThread; QThread m_coordinatorThread;
TwoMotionCaptureCoordinator* m_coordinator = nullptr; TwoMotionCaptureCoordinator* m_coordinator = nullptr;
TwoMotionCaptureCoordinator* m_coordinator_TimedDataCollection = nullptr;
DarkAndWhiteCaptureCoordinator* m_darkCaptureCoordinator = nullptr; DarkAndWhiteCaptureCoordinator* m_darkCaptureCoordinator = nullptr;
DarkAndWhiteCaptureCoordinator* m_whiteCaptureCoordinator = nullptr; DarkAndWhiteCaptureCoordinator* m_whiteCaptureCoordinator = nullptr;