Compare commits
8 Commits
3521a7f225
...
8329c00165
| Author | SHA1 | Date | |
|---|---|---|---|
| 8329c00165 | |||
| f69edcf2c9 | |||
| 509f4b0767 | |||
| 4a62d9a007 | |||
| 467bebe9dd | |||
| 41a1a938b9 | |||
| 3607913f13 | |||
| a8760652bd |
@ -6,6 +6,7 @@ TwoMotionCaptureCoordinator::TwoMotionCaptureCoordinator(
|
||||
: QObject(parent)
|
||||
, m_motorCtrl(motorCtrl)
|
||||
, m_isRunning(false)
|
||||
, m_isValidCapturing(false)
|
||||
{
|
||||
//这些信号槽是按照逻辑顺序的
|
||||
connect(this, SIGNAL(moveTo(int, double, double, int)),
|
||||
@ -86,6 +87,7 @@ void TwoMotionCaptureCoordinator::getLocBeforeStart()
|
||||
QMetaObject::Connection conn = QObject::connect(m_motorCtrl, &IrisMultiMotorController::locationSignal,
|
||||
[&](std::vector<double> pos) {
|
||||
m_locBeforeStart = pos;
|
||||
std::cout << "start pos: "<< pos[0] <<", " << pos[1] << std::endl;
|
||||
received = true;
|
||||
loop.quit();
|
||||
});
|
||||
@ -113,7 +115,7 @@ void TwoMotionCaptureCoordinator::move2LocBeforeStart()
|
||||
speed.push_back(tmp.speedTargetYPosition);
|
||||
emit moveTo(m_locBeforeStart, speed, 1000);
|
||||
|
||||
m_isRunning = false;
|
||||
m_isValidCapturing = false;
|
||||
|
||||
m_isMoving2XMin = false;
|
||||
m_isMoving2XMax = false;
|
||||
@ -195,12 +197,12 @@ void TwoMotionCaptureCoordinator::handlePositionReached(int motorID, double pos)
|
||||
|
||||
//QMutexLocker locker(&m_dataMutex);
|
||||
|
||||
PathLine &tmp = m_pathLines[m_numCurrentPathLine];
|
||||
|
||||
if (motorID == 1)//y马达
|
||||
{
|
||||
if (m_isMoving2YTargeLoc)
|
||||
{
|
||||
PathLine& tmp = m_pathLines[m_numCurrentPathLine];
|
||||
|
||||
double threshold = getThre(tmp.targetYPosition, pos);
|
||||
|
||||
if (threshold > 5)
|
||||
@ -230,6 +232,7 @@ void TwoMotionCaptureCoordinator::handlePositionReached(int motorID, double pos)
|
||||
if (m_isMoving2YStartLoc)
|
||||
{
|
||||
m_isMoving2YStartLoc = false;
|
||||
isBack2Origin();
|
||||
|
||||
return;
|
||||
}
|
||||
@ -238,6 +241,8 @@ void TwoMotionCaptureCoordinator::handlePositionReached(int motorID, double pos)
|
||||
{
|
||||
if (m_isMoving2XMin)
|
||||
{
|
||||
PathLine& tmp = m_pathLines[m_numCurrentPathLine];
|
||||
|
||||
double threshold = getThre(tmp.targetXMinPosition, pos);
|
||||
|
||||
if (threshold > 5)
|
||||
@ -266,6 +271,8 @@ void TwoMotionCaptureCoordinator::handlePositionReached(int motorID, double pos)
|
||||
|
||||
if (m_isMoving2XMax)
|
||||
{
|
||||
PathLine& tmp = m_pathLines[m_numCurrentPathLine];
|
||||
|
||||
double threshold = getThre(tmp.targetXMaxPosition, pos);
|
||||
|
||||
if (threshold > 5 && !m_isImagerFrameNumberMeet)//马达没到准确位置 && 【非】光谱仪因帧数限制主动停止采集
|
||||
@ -302,6 +309,7 @@ void TwoMotionCaptureCoordinator::handlePositionReached(int motorID, double pos)
|
||||
if (m_isMoving2XStartLoc)
|
||||
{
|
||||
m_isMoving2XStartLoc = false;
|
||||
isBack2Origin();
|
||||
|
||||
return;
|
||||
}
|
||||
@ -341,9 +349,25 @@ void TwoMotionCaptureCoordinator::startRecordHsi()
|
||||
emit moveTo(0, tmp.targetXMaxPosition, tmp.speedTargetXMaxPosition, 1000);
|
||||
|
||||
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()
|
||||
{
|
||||
m_isImagerFrameNumberMeet = true;
|
||||
@ -387,7 +411,8 @@ void TwoMotionCaptureCoordinator::processNextPathLine()
|
||||
}
|
||||
|
||||
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];
|
||||
tmp.timestamp1 = QDateTime::currentDateTime();
|
||||
|
||||
@ -46,6 +46,8 @@ public:
|
||||
|
||||
signals:
|
||||
void sequenceComplete(int);//0:所有采集线正常运行完成,1:用户主动取消采集
|
||||
void back2OriginSignal();
|
||||
void gotoRecordLineNumSignal(int lineNum);
|
||||
void startRecordLineNumSignal(int lineNum);
|
||||
void finishRecordLineNumSignal(int lineNum);
|
||||
|
||||
@ -75,6 +77,7 @@ private slots:
|
||||
private:
|
||||
void processNextPathLine();
|
||||
void startRecordHsi();
|
||||
void isBack2Origin();
|
||||
void getLocBeforeStart();
|
||||
double getThre(double targetLoc, double actualLoc);
|
||||
|
||||
@ -87,6 +90,7 @@ private:
|
||||
mutable QMutex m_dataMutex;
|
||||
|
||||
bool m_isRunning;
|
||||
bool m_isValidCapturing;
|
||||
bool m_isMoving2YTargeLoc;
|
||||
bool m_isMoving2XMin;
|
||||
bool m_isMoving2XMax;
|
||||
|
||||
14
HPPA/CommunicationInterfaceBase.cpp
Normal file
14
HPPA/CommunicationInterfaceBase.cpp
Normal file
@ -0,0 +1,14 @@
|
||||
#include "CommunicationInterfaceBase.h"
|
||||
|
||||
using namespace MotorParams;
|
||||
|
||||
CommunicationInterfaceBase::CommunicationInterfaceBase(QObject* parent)
|
||||
:QObject(parent)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
CommunicationInterfaceBase::~CommunicationInterfaceBase()
|
||||
{
|
||||
|
||||
}
|
||||
36
HPPA/CommunicationInterfaceBase.h
Normal file
36
HPPA/CommunicationInterfaceBase.h
Normal 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
|
||||
95
HPPA/CommunicationViaTCP.cpp
Normal file
95
HPPA/CommunicationViaTCP.cpp
Normal 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();
|
||||
}
|
||||
45
HPPA/CommunicationViaTCP.h
Normal file
45
HPPA/CommunicationViaTCP.h
Normal 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());
|
||||
};
|
||||
}
|
||||
@ -41,6 +41,11 @@ void DepthCameraWindow::onSelectDataFolder()
|
||||
QString::fromLocal8Bit("选择数据保存路径"),
|
||||
ui.dataFolderLineEdit->text());
|
||||
|
||||
setDataFolder(dir);
|
||||
}
|
||||
|
||||
void DepthCameraWindow::setDataFolder(QString dir)
|
||||
{
|
||||
if (!dir.isEmpty())
|
||||
{
|
||||
ui.dataFolderLineEdit->setText(dir);
|
||||
@ -48,6 +53,11 @@ void DepthCameraWindow::onSelectDataFolder()
|
||||
}
|
||||
}
|
||||
|
||||
void DepthCameraWindow::setCaptureInterval(int captureIntervalSeconds)
|
||||
{
|
||||
m_DepthCameraOperation->setCaptureInterval(captureIntervalSeconds);
|
||||
}
|
||||
|
||||
void DepthCameraWindow::openDepthCamera()
|
||||
{
|
||||
if (!m_DepthCameraOperation->getRecordStatus())
|
||||
@ -83,6 +93,8 @@ DepthCameraOperation::DepthCameraOperation()
|
||||
m_pipe = nullptr;
|
||||
m_func = nullptr;
|
||||
record = false;
|
||||
|
||||
m_captureIntervalMilliseconds = 3000;
|
||||
}
|
||||
|
||||
DepthCameraOperation::~DepthCameraOperation()
|
||||
@ -96,6 +108,11 @@ DepthCameraOperation::~DepthCameraOperation()
|
||||
}
|
||||
}
|
||||
|
||||
void DepthCameraOperation::setCaptureInterval(int captureIntervalSeconds)
|
||||
{
|
||||
m_captureIntervalMilliseconds = captureIntervalSeconds * 1000;
|
||||
}
|
||||
|
||||
void DepthCameraOperation::OpenDepthCamera()
|
||||
{
|
||||
if (m_pipe)
|
||||
@ -142,14 +159,14 @@ void DepthCameraOperation::OpenDepthCamera()
|
||||
|
||||
// Drop several frames
|
||||
for (int i = 0; i < 15; ++i) {
|
||||
auto lost = m_pipe->waitForFrameset(100);
|
||||
auto lost = m_pipe->waitForFrameset(m_captureIntervalMilliseconds);
|
||||
}
|
||||
|
||||
auto pointCloud = std::make_shared<ob::PointCloudFilter>();
|
||||
|
||||
int frameIndex = 0;
|
||||
record = true;
|
||||
QString fileNamePrefix = AppSettings::instance().depthCameraDataFolder() + QDir::separator() + AppSettings::instance().fileName();
|
||||
QString fileNamePrefix = AppSettings::instance().depthCameraDataFolder() + QDir::separator() + "Gemini336L";
|
||||
QString imuFilePath = fileNamePrefix + "_IMU.txt";
|
||||
std::ofstream imuFile(imuFilePath.toStdString(), std::ios::out | std::ios::trunc);
|
||||
while (record)
|
||||
@ -160,7 +177,7 @@ void DepthCameraOperation::OpenDepthCamera()
|
||||
std::cout << "Start recording..." << std::endl;
|
||||
}
|
||||
|
||||
auto frameSet = m_pipe->waitForFrameset(100);
|
||||
auto frameSet = m_pipe->waitForFrameset(m_captureIntervalMilliseconds);
|
||||
if (frameSet == nullptr)
|
||||
{
|
||||
std::cout << "No frames received in 100ms..." << std::endl;
|
||||
@ -218,7 +235,7 @@ void DepthCameraOperation::OpenDepthCamera()
|
||||
pointCloud->setCreatePointFormat(OB_FORMAT_RGB_POINT);
|
||||
std::shared_ptr<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);
|
||||
|
||||
//惯导数据
|
||||
|
||||
@ -33,6 +33,8 @@ public:
|
||||
void setCallback(void(*func)());
|
||||
bool getRecordStatus() const { return record; }
|
||||
|
||||
void setCaptureInterval(int captureIntervalSeconds);
|
||||
|
||||
private:
|
||||
ob::Pipeline* m_pipe;
|
||||
cv::Mat frame;
|
||||
@ -46,6 +48,8 @@ private:
|
||||
|
||||
bool record;
|
||||
|
||||
int m_captureIntervalMilliseconds;
|
||||
|
||||
public slots:
|
||||
void OpenDepthCamera();
|
||||
void OpenDepthCamera_callback();//不使用信号而使用回调函数来通知界面刷新视频
|
||||
@ -68,6 +72,9 @@ public:
|
||||
|
||||
DepthCameraOperation* m_DepthCameraOperation;
|
||||
|
||||
void setDataFolder(QString dir);
|
||||
void setCaptureInterval(int captureIntervalSeconds);
|
||||
|
||||
public Q_SLOTS:
|
||||
void openDepthCamera();
|
||||
void onCamOpened();
|
||||
|
||||
166
HPPA/HPPA.cpp
166
HPPA/HPPA.cpp
@ -575,6 +575,9 @@ HPPA::HPPA(QWidget* parent)
|
||||
|
||||
initMapTools();
|
||||
|
||||
//定时采集
|
||||
initTimedDataCollection();
|
||||
|
||||
QString strPath = QCoreApplication::applicationDirPath() + "/UILayout.ini";
|
||||
QFile file(strPath);
|
||||
if (file.open(QIODevice::ReadOnly))
|
||||
@ -588,6 +591,143 @@ HPPA::HPPA(QWidget* parent)
|
||||
this->showMaximized();
|
||||
}
|
||||
|
||||
void HPPA::initTimedDataCollection()
|
||||
{
|
||||
connect(this->ui.mActionTimedDataCollection, SIGNAL(triggered()), this, SLOT(onTimedDataCollection()));
|
||||
mTimedDataCollectionWindow = new TimedDataCollection();
|
||||
|
||||
// 定时采集控制器 → 相机/马达
|
||||
connect(mTimedDataCollectionWindow, &TimedDataCollection::hyperCamParm, this, &HPPA::setTimedDataCollectionHyperCamParm);
|
||||
connect(mTimedDataCollectionWindow, &TimedDataCollection::camParm, this, &HPPA::setTimedDataCollectionCamParm);
|
||||
connect(mTimedDataCollectionWindow, &TimedDataCollection::motorParm, this, &HPPA::setTimedDataCollectionMotorParm);
|
||||
connect(mTimedDataCollectionWindow, &TimedDataCollection::startRecordSignal, this, &HPPA::onStartTimedDataCollection);
|
||||
|
||||
connect(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()
|
||||
{
|
||||
//自定义菜单栏和工具栏
|
||||
@ -833,6 +973,11 @@ void HPPA::initControlTabwidget()
|
||||
m_pc->setWindowFlags(Qt::Widget);
|
||||
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();
|
||||
connect(m_rac->robotController, SIGNAL(hsiRecordSignal(int)), this, SLOT(recordFromRobotArm(int)));
|
||||
@ -847,7 +992,7 @@ void HPPA::initControlTabwidget()
|
||||
//2轴马达控制
|
||||
m_tmc = new TwoMotorControl(this);
|
||||
//connect(m_tmc, SIGNAL(startLineNumSignal(int)), this, SLOT(onCreateTab(int)));
|
||||
connect(m_tmc, SIGNAL(sequenceComplete()), this, SLOT(onsequenceComplete()));
|
||||
connect(m_tmc, &TwoMotorControl::back2OriginSignal, this, &HPPA::onsequenceComplete);
|
||||
m_tmc->setWindowFlags(Qt::Widget);
|
||||
ui.controlTabWidget->addTab(m_tmc, QString::fromLocal8Bit("2轴控制"));
|
||||
|
||||
@ -1382,7 +1527,8 @@ void HPPA::create3DPlantPhenotypeScenario()
|
||||
m_tabManager->showTab(m_singleLensReflexCameraWindow);
|
||||
//m_tabManager->showTab(m_rgbCameraControlWindow);
|
||||
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_view3DModelManager->switchScenario(View3DModelManager::ScenarioType::PlantPhenotype);
|
||||
@ -1523,22 +1669,6 @@ bool HPPA::showResultMessageBox(QString title, QString msg)
|
||||
|
||||
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();
|
||||
if (!checked)
|
||||
|
||||
12
HPPA/HPPA.h
12
HPPA/HPPA.h
@ -85,6 +85,8 @@
|
||||
|
||||
#include "TimedDataCollection.h"
|
||||
|
||||
#include "PowerControl3D.h"
|
||||
|
||||
#define PI 3.1415926
|
||||
|
||||
QT_CHARTS_USE_NAMESPACE//QChartView 使用 需要加宏, 否则无法使用
|
||||
@ -290,6 +292,7 @@ private:
|
||||
SingleLensReflexCameraWindow* m_singleLensReflexCameraWindow;
|
||||
adjustTable* m_adt;
|
||||
PowerControl* m_pc;
|
||||
PowerControl3D* m_pc3D;
|
||||
RobotArmControl* m_rac;
|
||||
OneMotorControl* m_omc;
|
||||
TwoMotorControl* m_tmc;
|
||||
@ -318,6 +321,9 @@ private:
|
||||
bool showResultMessageBox(QString title, QString msg);
|
||||
void disconnectImagerAndCleanup();
|
||||
|
||||
TimedDataCollection* mTimedDataCollectionWindow;
|
||||
void initTimedDataCollection();
|
||||
|
||||
public Q_SLOTS:
|
||||
void onPlotHyperspectralImageRgbImage(int fileNumber, int frameNumber, QString filePath);
|
||||
void focusPlotSpectralImg(int state);
|
||||
@ -395,6 +401,12 @@ public Q_SLOTS:
|
||||
|
||||
void onMapToolPanTriggered();
|
||||
void onMapToolSpectralTriggered();
|
||||
|
||||
void onTimedDataCollection();
|
||||
void setTimedDataCollectionHyperCamParm(int camType, double f, double e, QString filePath, QString fileName);
|
||||
void setTimedDataCollectionCamParm(int camType, int captureIntervalSeconds, QString folder);
|
||||
void setTimedDataCollectionMotorParm(QString pathLineFilePath);
|
||||
void onStartTimedDataCollection(int camType);
|
||||
protected:
|
||||
void closeEvent(QCloseEvent* event) override;
|
||||
|
||||
|
||||
@ -105,6 +105,7 @@ color:white;
|
||||
<addaction name="action_start_recording"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionOpenDirectory"/>
|
||||
<addaction name="mActionTimedDataCollection"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuhelp">
|
||||
<property name="title">
|
||||
@ -743,6 +744,11 @@ QPushButton:pressed
|
||||
<string>3D植物表型</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="mActionTimedDataCollection">
|
||||
<property name="text">
|
||||
<string>定时采集</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<customwidgets>
|
||||
|
||||
@ -112,6 +112,8 @@
|
||||
<ClCompile Include="AspectRatioLabel.cpp" />
|
||||
<ClCompile Include="CaptureCoordinator.cpp" />
|
||||
<ClCompile Include="Carousel.cpp" />
|
||||
<ClCompile Include="CommunicationInterfaceBase.cpp" />
|
||||
<ClCompile Include="CommunicationViaTCP.cpp" />
|
||||
<ClCompile Include="Corning410Imager.cpp" />
|
||||
<ClCompile Include="CustomDockWidgetBase.cpp" />
|
||||
<ClCompile Include="DepthCameraWindow.cpp" />
|
||||
@ -140,6 +142,7 @@
|
||||
<ClCompile Include="OneMotorControl.cpp" />
|
||||
<ClCompile Include="path_tc.cpp" />
|
||||
<ClCompile Include="PowerControl.cpp" />
|
||||
<ClCompile Include="PowerControl3D.cpp" />
|
||||
<ClCompile Include="QDoubleSlider.cpp" />
|
||||
<ClCompile Include="QMotorDoubleSlider.cpp" />
|
||||
<ClCompile Include="RasterDataProvider.cpp" />
|
||||
@ -189,6 +192,7 @@
|
||||
<QtUic Include="oneMotorControl.ui" />
|
||||
<QtUic Include="PathPlan.ui" />
|
||||
<QtUic Include="PowerControl.ui" />
|
||||
<QtUic Include="PowerControl3D.ui" />
|
||||
<QtUic Include="RadianceConversion.ui" />
|
||||
<QtUic Include="ReflectanceConversion.ui" />
|
||||
<QtUic Include="rgbCamera.ui" />
|
||||
@ -223,6 +227,8 @@
|
||||
<ClInclude Include="AppSettings.h" />
|
||||
<QtMoc Include="FileNameLineEdit.h" />
|
||||
<QtMoc Include="DepthCameraWindow.h" />
|
||||
<QtMoc Include="CommunicationViaTCP.h" />
|
||||
<QtMoc Include="CommunicationInterfaceBase.h" />
|
||||
<ClInclude Include="imager_base.h" />
|
||||
<ClInclude Include="irisximeaimager.h" />
|
||||
<QtMoc Include="OneMotorControl.h" />
|
||||
@ -244,6 +250,7 @@
|
||||
<QtMoc Include="MapToolSpectral.h" />
|
||||
<QtMoc Include="MapTools.h" />
|
||||
<ClInclude Include="MotorWindowBase.h" />
|
||||
<QtMoc Include="PowerControl3D.h" />
|
||||
<ClInclude Include="RasterDataProvider.h" />
|
||||
<ClInclude Include="MultibandRasterRenderer.h" />
|
||||
<ClInclude Include="RasterImageLayer.h" />
|
||||
@ -254,7 +261,7 @@
|
||||
<QtMoc Include="rgbCameraWindow.h" />
|
||||
<QtMoc Include="SingleLensReflexCameraWindow.h" />
|
||||
<QtMoc Include="TimedDataCollection.h" />
|
||||
<ClInclude Include="TimedDataCollectionDataStructures.h" />
|
||||
<QtMoc Include="TimedDataCollectionDataStructures.h" />
|
||||
<ClInclude Include="utility_tc.h" />
|
||||
<QtMoc Include="aboutWindow.h" />
|
||||
<ClInclude Include="hppaConfigFile.h" />
|
||||
|
||||
@ -238,6 +238,15 @@
|
||||
<ClCompile Include="TimedDataCollectionDataStructures.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</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>
|
||||
<QtMoc Include="fileOperation.h">
|
||||
@ -384,6 +393,18 @@
|
||||
<QtMoc Include="TimedDataCollection.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</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>
|
||||
<ClInclude Include="imageProcessor.h">
|
||||
@ -440,9 +461,6 @@
|
||||
<ClInclude Include="MotorWindowBase.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="TimedDataCollectionDataStructures.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<QtUic Include="FocusDialog.ui">
|
||||
@ -496,6 +514,9 @@
|
||||
<QtUic Include="TimedDataCollection_ui.ui">
|
||||
<Filter>Form Files</Filter>
|
||||
</QtUic>
|
||||
<QtUic Include="PowerControl3D.ui">
|
||||
<Filter>Form Files</Filter>
|
||||
</QtUic>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="cpp.hint" />
|
||||
|
||||
100
HPPA/PowerControl3D.cpp
Normal file
100
HPPA/PowerControl3D.cpp
Normal 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
42
HPPA/PowerControl3D.h
Normal 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
350
HPPA/PowerControl3D.ui
Normal 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 "新宋体";
|
||||
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>
|
||||
@ -28,6 +28,8 @@ SingleLensReflexCameraWindow::SingleLensReflexCameraWindow(QWidget* parent)
|
||||
connect(ui.stopTakePhoto_btn, &QPushButton::clicked, this, &SingleLensReflexCameraWindow::stopTakePhoto);
|
||||
connect(this, &SingleLensReflexCameraWindow::stopTakePhotoSignal, m_SingleLensReflexCameraOperation, &SingleLensReflexCameraOperation::stopTakePhoto);
|
||||
|
||||
connect(this, &SingleLensReflexCameraWindow::OpenAndTakePhotoSLRCameraSignal, m_SingleLensReflexCameraOperation, &SingleLensReflexCameraOperation::OpenAndTakePhotoSLRCamera);
|
||||
|
||||
connect(m_SingleLensReflexCameraOperation, &SingleLensReflexCameraOperation::CamOpenedSignal, this, &SingleLensReflexCameraWindow::onCamOpened);
|
||||
connect(m_SingleLensReflexCameraOperation, &SingleLensReflexCameraOperation::CamClosedSignal, this, &SingleLensReflexCameraWindow::onCamClosed);
|
||||
|
||||
@ -75,12 +77,31 @@ SingleLensReflexCameraWindow::~SingleLensReflexCameraWindow()
|
||||
m_SingleLensReflexCameraOperation = nullptr;
|
||||
}
|
||||
|
||||
void SingleLensReflexCameraWindow::onStartTimedDataCollection(int lineNum)
|
||||
{
|
||||
if (lineNum == 0)
|
||||
{
|
||||
OpenAndTakePhotoSLRCamera();
|
||||
}
|
||||
}
|
||||
|
||||
void SingleLensReflexCameraWindow::onStopTimedDataCollection()
|
||||
{
|
||||
stopTakePhoto();
|
||||
closeSLRCamera();
|
||||
}
|
||||
|
||||
void SingleLensReflexCameraWindow::onSelectDataFolder()
|
||||
{
|
||||
QString dir = QFileDialog::getExistingDirectory(this,
|
||||
QString::fromLocal8Bit("选择数据保存路径"),
|
||||
ui.dataFolderLineEdit->text());
|
||||
|
||||
setDataFolder(dir);
|
||||
}
|
||||
|
||||
void SingleLensReflexCameraWindow::setDataFolder(QString dir)
|
||||
{
|
||||
if (!dir.isEmpty())
|
||||
{
|
||||
ui.dataFolderLineEdit->setText(dir);
|
||||
@ -92,6 +113,11 @@ void SingleLensReflexCameraWindow::onSelectDataFolder()
|
||||
}
|
||||
}
|
||||
|
||||
void SingleLensReflexCameraWindow::setCaptureInterval(int captureIntervalSeconds)
|
||||
{
|
||||
m_SingleLensReflexCameraOperation->setCaptureInterval(captureIntervalSeconds);
|
||||
}
|
||||
|
||||
void SingleLensReflexCameraWindow::openSLRCamera()
|
||||
{
|
||||
if (!m_SingleLensReflexCameraOperation->getRecordStatus())
|
||||
@ -108,6 +134,11 @@ void SingleLensReflexCameraWindow::takePhoto()
|
||||
}
|
||||
}
|
||||
|
||||
void SingleLensReflexCameraWindow::OpenAndTakePhotoSLRCamera()
|
||||
{
|
||||
emit OpenAndTakePhotoSLRCameraSignal();
|
||||
}
|
||||
|
||||
void SingleLensReflexCameraWindow::stopTakePhoto()
|
||||
{
|
||||
if (m_SingleLensReflexCameraOperation->getRecordStatus())
|
||||
@ -200,6 +231,7 @@ SingleLensReflexCameraOperation::SingleLensReflexCameraOperation()
|
||||
m_isSessionOpen = false;
|
||||
m_isLiveViewActive = false;
|
||||
m_imageCounter = 0;
|
||||
m_captureIntervalMilliseconds = 3000;
|
||||
|
||||
// 设置保存路径(从 AppSettings 获取,如果为空则使用默认的 CapturedImages 目录)
|
||||
m_savePath = AppSettings::instance().slrDataFolder();
|
||||
@ -780,13 +812,76 @@ void SingleLensReflexCameraOperation::takePhoto()
|
||||
// 启动拍照定时器(每3秒拍一张)
|
||||
if (m_captureTimer && !m_captureTimer->isActive())
|
||||
{
|
||||
m_captureTimer->start(3000);
|
||||
std::cout << "capture timer started (1 photo 3 second)" << std::endl;
|
||||
m_captureTimer->start(m_captureIntervalMilliseconds);
|
||||
//std::cout << "capture timer started (1 photo 3 second)" << std::endl;
|
||||
|
||||
emit CaptureStartedSignal();
|
||||
}
|
||||
}
|
||||
|
||||
void SingleLensReflexCameraOperation::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()
|
||||
{
|
||||
if (m_captureTimer && m_captureTimer->isActive())
|
||||
|
||||
@ -46,6 +46,8 @@ public:
|
||||
// 获取当前实时取景图像
|
||||
QImage getCurrentLiveViewImage();
|
||||
|
||||
void setCaptureInterval(int captureIntervalSeconds);
|
||||
|
||||
private:
|
||||
cv::Mat frame;
|
||||
func m_func;
|
||||
@ -62,6 +64,7 @@ private:
|
||||
|
||||
QString m_savePath;
|
||||
int m_imageCounter;
|
||||
int m_captureIntervalMilliseconds;
|
||||
QMutex m_mutex;
|
||||
QMutex m_liveViewMutex;
|
||||
|
||||
@ -91,6 +94,7 @@ private:
|
||||
public slots:
|
||||
void OpenSLRCamera();
|
||||
void takePhoto();
|
||||
void OpenAndTakePhotoSLRCamera();
|
||||
void stopTakePhoto();
|
||||
void OpenSLRCamera_callback();
|
||||
void CloseSLRCamera();
|
||||
@ -127,12 +131,15 @@ public:
|
||||
~SingleLensReflexCameraWindow();
|
||||
|
||||
SingleLensReflexCameraOperation* m_SingleLensReflexCameraOperation;
|
||||
void setDataFolder(QString dir);
|
||||
void setCaptureInterval(int captureIntervalSeconds);
|
||||
|
||||
public Q_SLOTS:
|
||||
void onSelectDataFolder();
|
||||
|
||||
void openSLRCamera();
|
||||
void takePhoto();
|
||||
void OpenAndTakePhotoSLRCamera();
|
||||
void stopTakePhoto();
|
||||
void onCamOpened();
|
||||
void closeSLRCamera();
|
||||
@ -148,9 +155,13 @@ public Q_SLOTS:
|
||||
void onCaptureStarted();
|
||||
void onCaptureStopped();
|
||||
|
||||
void onStartTimedDataCollection(int lineNum);
|
||||
void onStopTimedDataCollection();
|
||||
|
||||
signals:
|
||||
void openSLRCameraSignal();
|
||||
void takePhotoSignal();
|
||||
void OpenAndTakePhotoSLRCameraSignal();
|
||||
void stopTakePhotoSignal();
|
||||
void closeSLRCameraSignal();
|
||||
void PlotSLRImageSignal();
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
|
||||
TimedDataCollection::TimedDataCollection(QWidget* parent)
|
||||
: QDialog(parent)
|
||||
, m_scheduler(nullptr)
|
||||
{
|
||||
ui.setupUi(this);
|
||||
|
||||
@ -12,21 +13,69 @@ TimedDataCollection::TimedDataCollection(QWidget* parent)
|
||||
ui.treeWidget->setDropIndicatorShown(true); // 显示插入位置指示线
|
||||
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();
|
||||
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()
|
||||
{
|
||||
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)
|
||||
@ -70,8 +119,8 @@ void TimedDataCollection::writeRead()
|
||||
subTask.type = types[j];
|
||||
subTask.startTime = task.scheduledTime.addSecs(j * 3600);
|
||||
subTask.endTime = subTask.startTime.addSecs(1800);
|
||||
subTask.durationSeconds = 1800;
|
||||
subTask.estimatedDurationSeconds = 1800;
|
||||
subTask.durationMinutes = 1800;
|
||||
subTask.estimatedDurationMinutes = 1800;
|
||||
subTask.pathLineFilePath = QString("D:/0tmp/3Dtest/pathLine/%1.RecordLine3").arg(j);
|
||||
subTask.status = TaskStatus::Waiting;
|
||||
|
||||
|
||||
@ -19,7 +19,32 @@ public:
|
||||
void readTimedTaskFromFile(const QString& filePath);
|
||||
|
||||
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:
|
||||
Ui::TimedDataCollection_ui ui;
|
||||
@ -27,4 +52,5 @@ private:
|
||||
void writeRead();
|
||||
|
||||
QVector<TimedTask> m_loadedTasks;
|
||||
TaskScheduler* m_scheduler;
|
||||
};
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
#include "TimedDataCollectionDataStructures.h"
|
||||
#include "TimedDataCollectionDataStructures.h"
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
@ -121,8 +121,8 @@ QJsonObject TimedDataCollectionDataStructuresReaderWriter::subTaskToJson(const S
|
||||
obj["type"] = subTaskTypeToString(subTask.type);
|
||||
obj["startTime"] = subTask.startTime.toString(Qt::ISODate);
|
||||
obj["endTime"] = subTask.endTime.toString(Qt::ISODate);
|
||||
obj["durationSeconds"] = subTask.durationSeconds;
|
||||
obj["estimatedDurationSeconds"] = subTask.estimatedDurationSeconds;
|
||||
obj["durationMinutes"] = subTask.durationMinutes;
|
||||
obj["estimatedDurationMinutes"] = subTask.estimatedDurationMinutes;
|
||||
obj["pathLineFilePath"] = subTask.pathLineFilePath;
|
||||
obj["status"] = taskStatusToString(subTask.status);
|
||||
obj["frameRate"] = subTask.frameRate;
|
||||
@ -137,14 +137,14 @@ bool TimedDataCollectionDataStructuresReaderWriter::jsonToSubTask(const QJsonObj
|
||||
subTask.type = stringToSubTaskType(json["type"].toString());
|
||||
subTask.startTime = QDateTime::fromString(json["startTime"].toString(), Qt::ISODate);
|
||||
subTask.endTime = QDateTime::fromString(json["endTime"].toString(), Qt::ISODate);
|
||||
subTask.durationSeconds = json["durationSeconds"].toInt();
|
||||
subTask.estimatedDurationSeconds = json["estimatedDurationSeconds"].toInt();
|
||||
subTask.durationMinutes = json["durationMinutes"].toDouble();
|
||||
subTask.estimatedDurationMinutes = json["estimatedDurationMinutes"].toDouble();
|
||||
subTask.pathLineFilePath = json["pathLineFilePath"].toString();
|
||||
subTask.status = stringToTaskStatus(json["status"].toString());
|
||||
subTask.frameRate = json["frameRate"].toDouble();
|
||||
subTask.exposureTime = json["exposureTime"].toDouble();
|
||||
subTask.defaultRenderBand = json["defaultRenderBand"].toInt();
|
||||
subTask.captureIntervalSeconds = json["captureIntervalSeconds"].toInt();
|
||||
subTask.captureIntervalSeconds = json["captureIntervalSeconds"].toDouble();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -157,9 +157,10 @@ QJsonObject TimedDataCollectionDataStructuresReaderWriter::timedTaskToJson(const
|
||||
obj["scheduledTime"] = task.scheduledTime.toString(Qt::ISODate);
|
||||
obj["startTime"] = task.startTime.toString(Qt::ISODate);
|
||||
obj["endTime"] = task.endTime.toString(Qt::ISODate);
|
||||
obj["durationSeconds"] = task.durationSeconds;
|
||||
obj["durationMinutes"] = task.durationMinutes;
|
||||
obj["savePath"] = task.savePath;
|
||||
obj["status"] = taskStatusToString(task.status);
|
||||
obj["HalogenLampPreheatingTime_Minute"] = task.HalogenLampPreheatingTime_Minute;
|
||||
|
||||
QJsonArray subTasksArray;
|
||||
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.startTime = QDateTime::fromString(json["startTime"].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.status = stringToTaskStatus(json["status"].toString());
|
||||
task.HalogenLampPreheatingTime_Minute = json["HalogenLampPreheatingTime_Minute"].toDouble();
|
||||
|
||||
QJsonArray subTasksArray = json["subTasks"].toArray();
|
||||
task.subTasks.clear();
|
||||
@ -194,3 +196,420 @@ bool TimedDataCollectionDataStructuresReaderWriter::jsonToTimedTask(const QJsonO
|
||||
|
||||
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 task,for weak up,please 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);
|
||||
}
|
||||
|
||||
@ -4,6 +4,9 @@
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
#include <QMetaType>
|
||||
#include <QTimer>
|
||||
|
||||
#include "CaptureCoordinator.h"
|
||||
|
||||
// ==================== 枚举定义 ====================
|
||||
|
||||
@ -11,7 +14,8 @@
|
||||
enum class TaskStatus {
|
||||
Waiting, // 等待
|
||||
Running, // 运行中
|
||||
Finished // 结束
|
||||
Finished, // 结束
|
||||
Skiped //跳过
|
||||
};
|
||||
|
||||
// 子任务类型
|
||||
@ -30,8 +34,8 @@ struct SubTask {
|
||||
// 共享属性
|
||||
QDateTime startTime;
|
||||
QDateTime endTime;
|
||||
int durationSeconds = 0;
|
||||
int estimatedDurationSeconds = 0;
|
||||
double durationMinutes = 0;
|
||||
double estimatedDurationMinutes = 0;
|
||||
QString pathLineFilePath;
|
||||
TaskStatus status = TaskStatus::Waiting;
|
||||
|
||||
@ -49,16 +53,17 @@ struct TimedTask {
|
||||
QDateTime scheduledTime; // 计划时间
|
||||
QDateTime startTime; // 开始时间
|
||||
QDateTime endTime; // 结束时间
|
||||
int durationSeconds = 0; // 耗时(秒)
|
||||
double durationMinutes = 0; // 耗时(秒)
|
||||
QString savePath; // 数据保存路径
|
||||
QVector<SubTask> subTasks; // 子任务列表
|
||||
TaskStatus status = TaskStatus::Waiting; // 状态
|
||||
double HalogenLampPreheatingTime_Minute;
|
||||
|
||||
// 计算所有子任务的预计总时间
|
||||
int totalEstimatedDuration() const {
|
||||
int total = 0;
|
||||
for (const auto& subTask : subTasks) {
|
||||
total += subTask.estimatedDurationSeconds;
|
||||
total += subTask.estimatedDurationMinutes;
|
||||
}
|
||||
return total;
|
||||
}
|
||||
@ -102,3 +107,129 @@ private:
|
||||
static QString subTaskTypeToString(SubTaskType type);
|
||||
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;
|
||||
};
|
||||
|
||||
@ -6,22 +6,19 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>970</width>
|
||||
<height>456</height>
|
||||
<width>1160</width>
|
||||
<height>576</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0" colspan="3">
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QTreeWidget" name="treeWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>9</x>
|
||||
<y>9</y>
|
||||
<width>491</width>
|
||||
<height>281</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="allColumnsShowFocus">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
@ -224,96 +221,58 @@
|
||||
</item>
|
||||
</item>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="addToptask_btn">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>40</x>
|
||||
<y>310</y>
|
||||
<width>101</width>
|
||||
<height>23</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>添加总计划任务</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="addSubtask_btn">
|
||||
<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>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<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>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QPushButton" name="addToptask_btn">
|
||||
<property name="text">
|
||||
<string>添加总计划任务</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QPushButton" name="delToptask_btn">
|
||||
<property name="text">
|
||||
<string>删除总计划任务</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QPushButton" name="addSubtask_btn">
|
||||
<property name="text">
|
||||
<string>添加子任务</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QComboBox" name="comboBox"/>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QPushButton" name="delSubtask_btn">
|
||||
<property name="text">
|
||||
<string>删除子任务</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<widget class="QPushButton" name="run_btn">
|
||||
<property name="text">
|
||||
<string>运行</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
||||
@ -103,6 +103,113 @@ void TwoMotorControl::record_white()
|
||||
m_whiteCaptureCoordinator->startStepMotion(s);
|
||||
}
|
||||
|
||||
void TwoMotorControl::run2(SingleLensReflexCameraWindow* window)
|
||||
{
|
||||
int rowCount = ui.recordLine_tableWidget->rowCount();
|
||||
if (rowCount == 0)
|
||||
{
|
||||
QMessageBox::information(this, QString::fromLocal8Bit("提示"), QString::fromLocal8Bit("请至少添加一行采集线!"));
|
||||
|
||||
emit sequenceComplete(0);
|
||||
return;
|
||||
}
|
||||
|
||||
m_coordinator_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()
|
||||
{
|
||||
if (getState())
|
||||
@ -116,7 +223,7 @@ void TwoMotorControl::run()
|
||||
{
|
||||
QMessageBox::information(this, QString::fromLocal8Bit("提示"), QString::fromLocal8Bit("请至少添加一行采集线!"));
|
||||
|
||||
emit sequenceComplete();
|
||||
emit sequenceComplete(0);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -129,7 +236,8 @@ void TwoMotorControl::run()
|
||||
connect(this, SIGNAL(stopSignal()), m_coordinator, SLOT(stop()));
|
||||
connect(m_coordinator, SIGNAL(startRecordLineNumSignal(int)), this, SLOT(receiveStartRecordLineNum(int)));
|
||||
connect(m_coordinator, SIGNAL(finishRecordLineNumSignal(int)), this, SLOT(receiveFinishRecordLineNum(int)));
|
||||
connect(m_coordinator, SIGNAL(sequenceComplete(int)), this, SLOT(onSequenceComplete()));
|
||||
connect(m_coordinator, SIGNAL(sequenceComplete(int)), this, SLOT(onSequenceComplete(int)));
|
||||
connect(m_coordinator, &TwoMotionCaptureCoordinator::back2OriginSignal, this, &TwoMotorControl::onBack2Origin);
|
||||
|
||||
connect(m_coordinator, &TwoMotionCaptureCoordinator::startRecordHSISignal, m_Imager, &ImagerOperationBase::start_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;
|
||||
fclose(m_posFileHandle);
|
||||
|
||||
emit sequenceComplete(status);
|
||||
}
|
||||
|
||||
void TwoMotorControl::onBack2Origin()
|
||||
{
|
||||
m_coordinatorThread.quit();
|
||||
m_coordinatorThread.wait();
|
||||
m_coordinator = nullptr;
|
||||
|
||||
emit sequenceComplete();
|
||||
emit back2OriginSignal();
|
||||
emit back2OriginSignal_TimedDataCollection();
|
||||
}
|
||||
|
||||
bool TwoMotorControl::getMotorsConnectionStatus()
|
||||
@ -551,7 +665,10 @@ void TwoMotorControl::onReadRecordLineFile_btn()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
readRecordLineFile(RecordLineFilePath);
|
||||
}
|
||||
void TwoMotorControl::readRecordLineFile(QString RecordLineFilePath)
|
||||
{
|
||||
FILE* RecordLineFileHandle = fopen(RecordLineFilePath.toStdString().c_str(), "rb");
|
||||
double number;
|
||||
|
||||
|
||||
@ -10,6 +10,9 @@
|
||||
#include "CaptureCoordinator.h"
|
||||
#include "MotorWindowBase.h"
|
||||
|
||||
#include "SingleLensReflexCameraWindow.h"
|
||||
#include "DepthCameraWindow.h"
|
||||
|
||||
#define PI 3.1415926
|
||||
|
||||
class TwoMotorControl : public QDialog, public MotorWindowBase
|
||||
@ -28,6 +31,8 @@ public:
|
||||
|
||||
bool getMotorsConnectionStatus();
|
||||
|
||||
void readRecordLineFile(QString RecordLineFilePath);
|
||||
|
||||
private:
|
||||
ImagerOperationBase* m_Imager;
|
||||
bool getState();
|
||||
@ -68,7 +73,12 @@ public Q_SLOTS:
|
||||
void stop();
|
||||
void receiveStartRecordLineNum(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();
|
||||
|
||||
@ -86,7 +96,9 @@ signals:
|
||||
void stopSignal();
|
||||
|
||||
void startLineNumSignal(int lineNum);
|
||||
void sequenceComplete();//所有采集线正常运行完成
|
||||
void sequenceComplete(int status);//所有采集线正常运行完成
|
||||
void back2OriginSignal();
|
||||
void back2OriginSignal_TimedDataCollection();
|
||||
|
||||
void broadcastLocationSignal(std::vector<double>);
|
||||
|
||||
@ -94,6 +106,7 @@ private:
|
||||
Ui::twoMotorControl_UI ui;
|
||||
QThread m_coordinatorThread;
|
||||
TwoMotionCaptureCoordinator* m_coordinator = nullptr;
|
||||
TwoMotionCaptureCoordinator* m_coordinator_TimedDataCollection = nullptr;
|
||||
|
||||
DarkAndWhiteCaptureCoordinator* m_darkCaptureCoordinator = nullptr;
|
||||
DarkAndWhiteCaptureCoordinator* m_whiteCaptureCoordinator = nullptr;
|
||||
|
||||
Reference in New Issue
Block a user