Compare commits
3 Commits
6456232114
...
3521a7f225
| Author | SHA1 | Date | |
|---|---|---|---|
| 3521a7f225 | |||
| 6111634eff | |||
| 4d42314a84 |
@ -2,11 +2,9 @@
|
||||
|
||||
TwoMotionCaptureCoordinator::TwoMotionCaptureCoordinator(
|
||||
IrisMultiMotorController* motorCtrl,
|
||||
ImagerOperationBase* cameraCtrl,
|
||||
QObject* parent)
|
||||
: QObject(parent)
|
||||
, m_motorCtrl(motorCtrl)
|
||||
, m_cameraCtrl(cameraCtrl)
|
||||
, m_isRunning(false)
|
||||
{
|
||||
//这些信号槽是按照逻辑顺序的
|
||||
@ -20,35 +18,6 @@ TwoMotionCaptureCoordinator::TwoMotionCaptureCoordinator(
|
||||
this, &TwoMotionCaptureCoordinator::handlePositionReached);
|
||||
//connect(m_motorCtrl, &IrisMultiMotorController::moveFailed,
|
||||
// this, &TwoMotionCaptureCoordinator::handleError);
|
||||
|
||||
connect(this, &TwoMotionCaptureCoordinator::startRecordHSISignal,
|
||||
m_cameraCtrl, &ImagerOperationBase::start_record);
|
||||
connect(this, &TwoMotionCaptureCoordinator::stopRecordHSISignal,
|
||||
m_cameraCtrl, &ImagerOperationBase::stop_record);
|
||||
connect(m_cameraCtrl, &ImagerOperationBase::RecordFinishedSignal_WhenFrameNumberMeet,
|
||||
this, &TwoMotionCaptureCoordinator::handleCaptureCompleteWhenFrameNumberMeet);
|
||||
//connect(m_cameraCtrl, &ImagerOperationBase::RecordFinishedSignal_WhenFrameNumberNotMeet,
|
||||
// this, &TwoMotionCaptureCoordinator::handleCaptureCompleteWhenFrameNumberNotMeet);
|
||||
//connect(m_cameraCtrl, &ImagerOperationBase::captureFailed,
|
||||
// this, &TwoMotionCaptureCoordinator::handleError);
|
||||
}
|
||||
|
||||
TwoMotionCaptureCoordinator::TwoMotionCaptureCoordinator(
|
||||
IrisMultiMotorController* motorCtrl,
|
||||
QObject* parent)
|
||||
: QObject(parent)
|
||||
, m_motorCtrl(motorCtrl)
|
||||
, m_isRunning(false)
|
||||
{
|
||||
connect(this, SIGNAL(moveTo(int, double, double, int)),
|
||||
m_motorCtrl, SLOT(moveTo(int, double, double, int)));
|
||||
connect(this, SIGNAL(moveTo(const std::vector<double>, const std::vector<double>, int)),
|
||||
m_motorCtrl, SLOT(moveTo(const std::vector<double>, const std::vector<double>, int)));
|
||||
|
||||
connect(m_motorCtrl, &IrisMultiMotorController::motorStopSignal,
|
||||
this, &TwoMotionCaptureCoordinator::handlePositionReached);
|
||||
//connect(m_motorCtrl, &IrisMultiMotorController::moveFailed,
|
||||
// this, &TwoMotionCaptureCoordinator::handleError);
|
||||
}
|
||||
|
||||
TwoMotionCaptureCoordinator::~TwoMotionCaptureCoordinator()
|
||||
@ -98,11 +67,7 @@ void TwoMotionCaptureCoordinator::stop()
|
||||
savePathLinesToCsv();
|
||||
|
||||
emit finishRecordLineNumSignal(m_numCurrentPathLine);
|
||||
//emit stopRecordHSISignal(m_numCurrentPathLine);
|
||||
if (m_cameraCtrl != nullptr)
|
||||
{
|
||||
m_cameraCtrl->stop_record();
|
||||
}
|
||||
emit stopRecordHSISignal(m_numCurrentPathLine);
|
||||
|
||||
move2LocBeforeStart();
|
||||
|
||||
@ -324,11 +289,7 @@ void TwoMotionCaptureCoordinator::handlePositionReached(int motorID, double pos)
|
||||
|
||||
//停止采集高光谱数据
|
||||
emit finishRecordLineNumSignal(m_numCurrentPathLine);
|
||||
//emit stopRecordHSISignal(m_numCurrentPathLine);
|
||||
if (m_cameraCtrl!=nullptr)
|
||||
{
|
||||
m_cameraCtrl->stop_record();
|
||||
}
|
||||
emit stopRecordHSISignal(m_numCurrentPathLine);
|
||||
|
||||
m_isMoving2XMax = false;
|
||||
m_isImagerFrameNumberMeet = false;
|
||||
|
||||
@ -38,9 +38,6 @@ class TwoMotionCaptureCoordinator : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
TwoMotionCaptureCoordinator(IrisMultiMotorController* motorCtrl,
|
||||
ImagerOperationBase* cameraCtrl,
|
||||
QObject* parent = nullptr);
|
||||
TwoMotionCaptureCoordinator(IrisMultiMotorController* motorCtrl,
|
||||
QObject* parent = nullptr);
|
||||
~TwoMotionCaptureCoordinator();
|
||||
@ -62,13 +59,15 @@ signals:
|
||||
|
||||
void recordState(bool state);
|
||||
|
||||
public slots:
|
||||
void handleCaptureCompleteWhenFrameNumberMeet();
|
||||
|
||||
private slots:
|
||||
void start(QVector<PathLine> pathLines);
|
||||
void stop();
|
||||
void getRecordState();
|
||||
|
||||
void handlePositionReached(int motorID, double pos);
|
||||
void handleCaptureCompleteWhenFrameNumberMeet();
|
||||
void handleError(const QString& error);
|
||||
|
||||
void move2LocBeforeStart();
|
||||
|
||||
@ -1523,6 +1523,22 @@ 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)
|
||||
@ -1556,7 +1572,7 @@ void HPPA::onStartRecordStep1()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
//判断光谱仪
|
||||
if(!testImagerVality())
|
||||
{
|
||||
|
||||
@ -83,6 +83,8 @@
|
||||
|
||||
#include "LayerTreeImageNode.h"
|
||||
|
||||
#include "TimedDataCollection.h"
|
||||
|
||||
#define PI 3.1415926
|
||||
|
||||
QT_CHARTS_USE_NAMESPACE//QChartView 使用 需要加宏, 否则无法使用
|
||||
|
||||
@ -161,6 +161,8 @@
|
||||
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Create</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<ClCompile Include="TabManager.cpp" />
|
||||
<ClCompile Include="TimedDataCollection.cpp" />
|
||||
<ClCompile Include="TimedDataCollectionDataStructures.cpp" />
|
||||
<ClCompile Include="TwoMotorControl.cpp" />
|
||||
<ClCompile Include="utility_tc.cpp" />
|
||||
<ClCompile Include="View3D.cpp" />
|
||||
@ -193,6 +195,7 @@
|
||||
<QtUic Include="RobotArmControl.ui" />
|
||||
<QtUic Include="set.ui" />
|
||||
<QtUic Include="SingleLensReflexCamera.ui" />
|
||||
<QtUic Include="TimedDataCollection_ui.ui" />
|
||||
<QtUic Include="twoMotorControl.ui" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@ -250,6 +253,8 @@
|
||||
<QtMoc Include="setWindow.h" />
|
||||
<QtMoc Include="rgbCameraWindow.h" />
|
||||
<QtMoc Include="SingleLensReflexCameraWindow.h" />
|
||||
<QtMoc Include="TimedDataCollection.h" />
|
||||
<ClInclude Include="TimedDataCollectionDataStructures.h" />
|
||||
<ClInclude Include="utility_tc.h" />
|
||||
<QtMoc Include="aboutWindow.h" />
|
||||
<ClInclude Include="hppaConfigFile.h" />
|
||||
|
||||
@ -232,6 +232,12 @@
|
||||
<ClCompile Include="RasterRendererBase.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="TimedDataCollection.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="TimedDataCollectionDataStructures.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<QtMoc Include="fileOperation.h">
|
||||
@ -375,6 +381,9 @@
|
||||
<QtMoc Include="LayerTreeImageNode.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</QtMoc>
|
||||
<QtMoc Include="TimedDataCollection.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</QtMoc>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="imageProcessor.h">
|
||||
@ -431,6 +440,9 @@
|
||||
<ClInclude Include="MotorWindowBase.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="TimedDataCollectionDataStructures.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<QtUic Include="FocusDialog.ui">
|
||||
@ -481,6 +493,9 @@
|
||||
<QtUic Include="SingleLensReflexCamera.ui">
|
||||
<Filter>Form Files</Filter>
|
||||
</QtUic>
|
||||
<QtUic Include="TimedDataCollection_ui.ui">
|
||||
<Filter>Form Files</Filter>
|
||||
</QtUic>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="cpp.hint" />
|
||||
|
||||
120
HPPA/TimedDataCollection.cpp
Normal file
120
HPPA/TimedDataCollection.cpp
Normal file
@ -0,0 +1,120 @@
|
||||
#include "TimedDataCollection.h"
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
|
||||
TimedDataCollection::TimedDataCollection(QWidget* parent)
|
||||
: QDialog(parent)
|
||||
{
|
||||
ui.setupUi(this);
|
||||
|
||||
ui.treeWidget->setDragEnabled(true); // 启用拖拽
|
||||
ui.treeWidget->setAcceptDrops(true); // 接受拖放
|
||||
ui.treeWidget->setDropIndicatorShown(true); // 显示插入位置指示线
|
||||
ui.treeWidget->setDragDropMode(QAbstractItemView::InternalMove); // 内部移动
|
||||
|
||||
//writeRead();
|
||||
readTimedTaskFromFile("D:/0tmp/3Dtest/task.json");
|
||||
|
||||
connect(ui.run_btn, SIGNAL(clicked()), this, SLOT(run()));
|
||||
|
||||
connect(ui.run_btn, &QPushButton::clicked, this, &TimedDataCollection::run);
|
||||
}
|
||||
|
||||
TimedDataCollection::~TimedDataCollection()
|
||||
{
|
||||
}
|
||||
|
||||
void TimedDataCollection::run()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void TimedDataCollection::readTimedTaskFromFile(const QString& filePath)
|
||||
{
|
||||
// 从文件读取
|
||||
if (TimedDataCollectionDataStructuresReaderWriter::loadTasksFromFile(filePath, m_loadedTasks)) {
|
||||
qDebug() << "Tasks loaded successfully, count:" << m_loadedTasks.size();
|
||||
for (const auto& t : m_loadedTasks) {
|
||||
qDebug() << " Task ID:" << t.id << "SubTasks:" << t.subTasks.size();
|
||||
}
|
||||
}
|
||||
else {
|
||||
qDebug() << "Failed to load tasks from:" << filePath;
|
||||
}
|
||||
|
||||
int a = 1;
|
||||
}
|
||||
|
||||
void TimedDataCollection::writeRead()
|
||||
{
|
||||
// 创建2个定时任务测试
|
||||
QVector<TimedTask> tasks;
|
||||
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
TimedTask task;
|
||||
task.id = i + 1;
|
||||
task.scheduledTime = QDateTime::currentDateTime().addDays(i + 1);
|
||||
task.savePath = QString("D:/0tmp/data");
|
||||
task.status = TaskStatus::Waiting;
|
||||
|
||||
// 创建4种子任务
|
||||
QVector<SubTaskType> types = {
|
||||
SubTaskType::HyperSpectual400_1000nm,
|
||||
SubTaskType::HyperSpectual1000_1700nm,
|
||||
SubTaskType::SingleLensReflex,
|
||||
SubTaskType::DepthCamera
|
||||
};
|
||||
|
||||
for (int j = 0; j < types.size(); ++j) {
|
||||
SubTask subTask;
|
||||
subTask.type = types[j];
|
||||
subTask.startTime = task.scheduledTime.addSecs(j * 3600);
|
||||
subTask.endTime = subTask.startTime.addSecs(1800);
|
||||
subTask.durationSeconds = 1800;
|
||||
subTask.estimatedDurationSeconds = 1800;
|
||||
subTask.pathLineFilePath = QString("D:/0tmp/3Dtest/pathLine/%1.RecordLine3").arg(j);
|
||||
subTask.status = TaskStatus::Waiting;
|
||||
|
||||
// 根据类型设置特有属性
|
||||
if (subTask.type == SubTaskType::HyperSpectual400_1000nm ||
|
||||
subTask.type == SubTaskType::HyperSpectual1000_1700nm) {
|
||||
subTask.frameRate = 30.0;
|
||||
subTask.exposureTime = 1;
|
||||
}
|
||||
if (subTask.type == SubTaskType::HyperSpectual1000_1700nm) {
|
||||
subTask.defaultRenderBand = 1200;
|
||||
}
|
||||
if (subTask.type == SubTaskType::SingleLensReflex ||
|
||||
subTask.type == SubTaskType::DepthCamera) {
|
||||
subTask.captureIntervalSeconds = 5;
|
||||
}
|
||||
|
||||
task.subTasks.append(subTask);
|
||||
}
|
||||
|
||||
tasks.append(task);
|
||||
}
|
||||
|
||||
// 保存到文件
|
||||
QString filePath = "D:/0tmp/3Dtest/task.json";
|
||||
if (TimedDataCollectionDataStructuresReaderWriter::saveTasksToFile(filePath, tasks)) {
|
||||
qDebug() << "Tasks saved to:" << filePath;
|
||||
}
|
||||
else {
|
||||
qDebug() << "Failed to save tasks to:" << filePath;
|
||||
}
|
||||
|
||||
// 从文件读取
|
||||
QVector<TimedTask> loadedTasks;
|
||||
if (TimedDataCollectionDataStructuresReaderWriter::loadTasksFromFile(filePath, loadedTasks)) {
|
||||
qDebug() << "Tasks loaded successfully, count:" << loadedTasks.size();
|
||||
for (const auto& t : loadedTasks) {
|
||||
qDebug() << " Task ID:" << t.id << "SubTasks:" << t.subTasks.size();
|
||||
}
|
||||
}
|
||||
else {
|
||||
qDebug() << "Failed to load tasks from:" << filePath;
|
||||
}
|
||||
|
||||
int a = 1;
|
||||
}
|
||||
30
HPPA/TimedDataCollection.h
Normal file
30
HPPA/TimedDataCollection.h
Normal file
@ -0,0 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include <QDialog>
|
||||
#include <QNetworkRequest>
|
||||
#include <QNetworkReply>
|
||||
#include <QNetworkAccessManager>
|
||||
|
||||
#include "ui_TimedDataCollection_ui.h"
|
||||
#include "TimedDataCollectionDataStructures.h"
|
||||
|
||||
class TimedDataCollection : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
TimedDataCollection(QWidget* parent = nullptr);
|
||||
~TimedDataCollection();
|
||||
|
||||
void readTimedTaskFromFile(const QString& filePath);
|
||||
|
||||
public Q_SLOTS:
|
||||
void run();
|
||||
|
||||
private:
|
||||
Ui::TimedDataCollection_ui ui;
|
||||
|
||||
void writeRead();
|
||||
|
||||
QVector<TimedTask> m_loadedTasks;
|
||||
};
|
||||
196
HPPA/TimedDataCollectionDataStructures.cpp
Normal file
196
HPPA/TimedDataCollectionDataStructures.cpp
Normal file
@ -0,0 +1,196 @@
|
||||
#include "TimedDataCollectionDataStructures.h"
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonArray>
|
||||
#include <QFile>
|
||||
#include <QTextStream>
|
||||
#include <QDebug>
|
||||
|
||||
// ==================== 公共接口实现 ====================
|
||||
|
||||
bool TimedDataCollectionDataStructuresReaderWriter::saveTasksToFile(const QString& filePath, const QVector<TimedTask>& tasks)
|
||||
{
|
||||
QJsonObject root;
|
||||
root["version"] = "1.0";
|
||||
root["taskCount"] = tasks.size();
|
||||
|
||||
QJsonArray tasksArray;
|
||||
for (const auto& task : tasks) {
|
||||
tasksArray.append(timedTaskToJson(task));
|
||||
}
|
||||
root["tasks"] = tasksArray;
|
||||
|
||||
QJsonDocument doc(root);
|
||||
QFile file(filePath);
|
||||
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||||
qWarning() << "Failed to open file for writing:" << filePath;
|
||||
return false;
|
||||
}
|
||||
|
||||
QTextStream out(&file);
|
||||
//out.setEncoding(QStringConverter::Utf8);
|
||||
out << doc.toJson(QJsonDocument::Indented);
|
||||
file.close();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TimedDataCollectionDataStructuresReaderWriter::loadTasksFromFile(const QString& filePath, QVector<TimedTask>& tasks)
|
||||
{
|
||||
QFile file(filePath);
|
||||
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
qWarning() << "Failed to open file for reading:" << filePath;
|
||||
return false;
|
||||
}
|
||||
|
||||
QByteArray jsonData = file.readAll();
|
||||
file.close();
|
||||
|
||||
QJsonParseError parseError;
|
||||
QJsonDocument doc = QJsonDocument::fromJson(jsonData, &parseError);
|
||||
if (parseError.error != QJsonParseError::NoError) {
|
||||
qWarning() << "JSON parse error:" << parseError.errorString();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!doc.isObject()) {
|
||||
qWarning() << "Invalid JSON root object";
|
||||
return false;
|
||||
}
|
||||
|
||||
QJsonObject root = doc.object();
|
||||
QJsonArray tasksArray = root["tasks"].toArray();
|
||||
tasks.clear();
|
||||
tasks.reserve(tasksArray.size());
|
||||
|
||||
for (const auto& taskValue : tasksArray) {
|
||||
if (!taskValue.isObject()) continue;
|
||||
TimedTask task;
|
||||
if (jsonToTimedTask(taskValue.toObject(), task)) {
|
||||
tasks.append(task);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ==================== 枚举转换函数 ====================
|
||||
|
||||
QString TimedDataCollectionDataStructuresReaderWriter::taskStatusToString(TaskStatus status)
|
||||
{
|
||||
switch (status) {
|
||||
case TaskStatus::Waiting: return "Waiting";
|
||||
case TaskStatus::Running: return "Running";
|
||||
case TaskStatus::Finished: return "Finished";
|
||||
default: return "Waiting";
|
||||
}
|
||||
}
|
||||
|
||||
TaskStatus TimedDataCollectionDataStructuresReaderWriter::stringToTaskStatus(const QString& str)
|
||||
{
|
||||
if (str == "Running") return TaskStatus::Running;
|
||||
if (str == "Finished") return TaskStatus::Finished;
|
||||
return TaskStatus::Waiting;
|
||||
}
|
||||
|
||||
QString TimedDataCollectionDataStructuresReaderWriter::subTaskTypeToString(SubTaskType type)
|
||||
{
|
||||
switch (type) {
|
||||
case SubTaskType::HyperSpectual400_1000nm: return "HyperSpectual400_1000nm";
|
||||
case SubTaskType::HyperSpectual1000_1700nm: return "HyperSpectual1000_1700nm";
|
||||
case SubTaskType::SingleLensReflex: return "SingleLensReflex";
|
||||
case SubTaskType::DepthCamera: return "DepthCamera";
|
||||
default: return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
SubTaskType TimedDataCollectionDataStructuresReaderWriter::stringToSubTaskType(const QString& str)
|
||||
{
|
||||
if (str == "HyperSpectual400_1000nm") return SubTaskType::HyperSpectual400_1000nm;
|
||||
if (str == "HyperSpectual1000_1700nm") return SubTaskType::HyperSpectual1000_1700nm;
|
||||
if (str == "SingleLensReflex") return SubTaskType::SingleLensReflex;
|
||||
if (str == "DepthCamera") return SubTaskType::DepthCamera;
|
||||
return SubTaskType::SingleLensReflex;
|
||||
}
|
||||
|
||||
// ==================== SubTask序列化 ====================
|
||||
|
||||
QJsonObject TimedDataCollectionDataStructuresReaderWriter::subTaskToJson(const SubTask& subTask)
|
||||
{
|
||||
QJsonObject obj;
|
||||
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["pathLineFilePath"] = subTask.pathLineFilePath;
|
||||
obj["status"] = taskStatusToString(subTask.status);
|
||||
obj["frameRate"] = subTask.frameRate;
|
||||
obj["exposureTime"] = subTask.exposureTime;
|
||||
obj["defaultRenderBand"] = subTask.defaultRenderBand;
|
||||
obj["captureIntervalSeconds"] = subTask.captureIntervalSeconds;
|
||||
return obj;
|
||||
}
|
||||
|
||||
bool TimedDataCollectionDataStructuresReaderWriter::jsonToSubTask(const QJsonObject& json, SubTask& subTask)
|
||||
{
|
||||
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.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();
|
||||
return true;
|
||||
}
|
||||
|
||||
// ==================== TimedTask序列化 ====================
|
||||
|
||||
QJsonObject TimedDataCollectionDataStructuresReaderWriter::timedTaskToJson(const TimedTask& task)
|
||||
{
|
||||
QJsonObject obj;
|
||||
obj["id"] = task.id;
|
||||
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["savePath"] = task.savePath;
|
||||
obj["status"] = taskStatusToString(task.status);
|
||||
|
||||
QJsonArray subTasksArray;
|
||||
for (const auto& subTask : task.subTasks) {
|
||||
subTasksArray.append(subTaskToJson(subTask));
|
||||
}
|
||||
obj["subTasks"] = subTasksArray;
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
bool TimedDataCollectionDataStructuresReaderWriter::jsonToTimedTask(const QJsonObject& json, TimedTask& task)
|
||||
{
|
||||
task.id = json["id"].toInt();
|
||||
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.savePath = json["savePath"].toString();
|
||||
task.status = stringToTaskStatus(json["status"].toString());
|
||||
|
||||
QJsonArray subTasksArray = json["subTasks"].toArray();
|
||||
task.subTasks.clear();
|
||||
task.subTasks.reserve(subTasksArray.size());
|
||||
|
||||
for (const auto& subTaskValue : subTasksArray) {
|
||||
if (!subTaskValue.isObject()) continue;
|
||||
SubTask subTask;
|
||||
if (jsonToSubTask(subTaskValue.toObject(), subTask)) {
|
||||
task.subTasks.append(subTask);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
104
HPPA/TimedDataCollectionDataStructures.h
Normal file
104
HPPA/TimedDataCollectionDataStructures.h
Normal file
@ -0,0 +1,104 @@
|
||||
#pragma once
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
#include <QMetaType>
|
||||
|
||||
// ==================== 枚举定义 ====================
|
||||
|
||||
// 任务状态
|
||||
enum class TaskStatus {
|
||||
Waiting, // 等待
|
||||
Running, // 运行中
|
||||
Finished // 结束
|
||||
};
|
||||
|
||||
// 子任务类型
|
||||
enum class SubTaskType {
|
||||
HyperSpectual400_1000nm, // 400nm-1000nm高光谱相机
|
||||
HyperSpectual1000_1700nm, // 1000nm-1700nm高光谱相机
|
||||
SingleLensReflex, // 单反相机
|
||||
DepthCamera // 深度相机
|
||||
};
|
||||
|
||||
// ==================== 统一子任务封装 ====================
|
||||
|
||||
struct SubTask {
|
||||
SubTaskType type; // 子任务类型
|
||||
|
||||
// 共享属性
|
||||
QDateTime startTime;
|
||||
QDateTime endTime;
|
||||
int durationSeconds = 0;
|
||||
int estimatedDurationSeconds = 0;
|
||||
QString pathLineFilePath;
|
||||
TaskStatus status = TaskStatus::Waiting;
|
||||
|
||||
// 类型特有属性(根据type选择使用)
|
||||
double frameRate = 0.0; // 高光谱相机用
|
||||
double exposureTime = 0.0; // 高光谱相机用
|
||||
int defaultRenderBand = 550; // 1000-1700nm高光谱用
|
||||
int captureIntervalSeconds = 5; // 单反/深度相机用
|
||||
};
|
||||
|
||||
// ==================== 定时任务 ====================
|
||||
|
||||
struct TimedTask {
|
||||
int id = 0; // 任务ID
|
||||
QDateTime scheduledTime; // 计划时间
|
||||
QDateTime startTime; // 开始时间
|
||||
QDateTime endTime; // 结束时间
|
||||
int durationSeconds = 0; // 耗时(秒)
|
||||
QString savePath; // 数据保存路径
|
||||
QVector<SubTask> subTasks; // 子任务列表
|
||||
TaskStatus status = TaskStatus::Waiting; // 状态
|
||||
|
||||
// 计算所有子任务的预计总时间
|
||||
int totalEstimatedDuration() const {
|
||||
int total = 0;
|
||||
for (const auto& subTask : subTasks) {
|
||||
total += subTask.estimatedDurationSeconds;
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
// 获取子任务数量
|
||||
int subTaskCount() const {
|
||||
return subTasks.size();
|
||||
}
|
||||
};
|
||||
|
||||
// ==================== Qt元类型声明 ====================
|
||||
Q_DECLARE_METATYPE(TaskStatus)
|
||||
Q_DECLARE_METATYPE(SubTaskType)
|
||||
Q_DECLARE_METATYPE(SubTask)
|
||||
Q_DECLARE_METATYPE(TimedTask)
|
||||
|
||||
// ==================== 任务文件读写类 ====================
|
||||
|
||||
class TimedDataCollectionDataStructuresReaderWriter
|
||||
{
|
||||
public:
|
||||
// 保存任务到文件
|
||||
static bool saveTasksToFile(const QString& filePath, const QVector<TimedTask>& tasks);
|
||||
|
||||
// 从文件读取任务
|
||||
static bool loadTasksFromFile(const QString& filePath, QVector<TimedTask>& tasks);
|
||||
|
||||
private:
|
||||
// SubTask序列化
|
||||
static QJsonObject subTaskToJson(const SubTask& subTask);
|
||||
static bool jsonToSubTask(const QJsonObject& json, SubTask& subTask);
|
||||
|
||||
// TimedTask序列化
|
||||
static QJsonObject timedTaskToJson(const TimedTask& task);
|
||||
static bool jsonToTimedTask(const QJsonObject& json, TimedTask& task);
|
||||
|
||||
// 枚举转换
|
||||
static QString taskStatusToString(TaskStatus status);
|
||||
static TaskStatus stringToTaskStatus(const QString& str);
|
||||
|
||||
static QString subTaskTypeToString(SubTaskType type);
|
||||
static SubTaskType stringToSubTaskType(const QString& str);
|
||||
};
|
||||
320
HPPA/TimedDataCollection_ui.ui
Normal file
320
HPPA/TimedDataCollection_ui.ui
Normal file
@ -0,0 +1,320 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>TimedDataCollection_ui</class>
|
||||
<widget class="QDialog" name="TimedDataCollection_ui">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>970</width>
|
||||
<height>456</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
</property>
|
||||
<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>
|
||||
<attribute name="headerVisible">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>任务</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>计划时间</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>开始时间</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>结束时间</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>耗时</string>
|
||||
</property>
|
||||
</column>
|
||||
<column>
|
||||
<property name="text">
|
||||
<string>状态</string>
|
||||
</property>
|
||||
</column>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>1</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>
|
||||
<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>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>b</string>
|
||||
</property>
|
||||
</item>
|
||||
</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>
|
||||
<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>
|
||||
<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>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@ -121,14 +121,20 @@ void TwoMotorControl::run()
|
||||
}
|
||||
|
||||
qRegisterMetaType<QVector<PathLine>>("QVector<PathLine>");
|
||||
m_coordinator = new TwoMotionCaptureCoordinator(m_multiAxisController, m_Imager);
|
||||
m_coordinator = new TwoMotionCaptureCoordinator(m_multiAxisController);
|
||||
m_coordinator->moveToThread(&m_coordinatorThread);
|
||||
connect(&m_coordinatorThread, SIGNAL(finished()), m_coordinator, SLOT(deleteLater()));
|
||||
connect(this, SIGNAL(start(QVector<PathLine>)), m_coordinator, SLOT(start(QVector<PathLine>)));
|
||||
|
||||
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, &TwoMotionCaptureCoordinator::startRecordHSISignal, m_Imager, &ImagerOperationBase::start_record);
|
||||
connect(m_coordinator, &TwoMotionCaptureCoordinator::stopRecordHSISignal, this, &TwoMotorControl::stop_record);
|
||||
connect(m_Imager, &ImagerOperationBase::RecordFinishedSignal_WhenFrameNumberMeet, m_coordinator, &TwoMotionCaptureCoordinator::handleCaptureCompleteWhenFrameNumberMeet);
|
||||
|
||||
m_coordinatorThread.start();
|
||||
|
||||
QVector<PathLine> pathLines;
|
||||
@ -158,6 +164,11 @@ void TwoMotorControl::run()
|
||||
emit start(pathLines);
|
||||
}
|
||||
|
||||
void TwoMotorControl::stop_record()
|
||||
{
|
||||
m_Imager->stop_record();
|
||||
}
|
||||
|
||||
void TwoMotorControl::stop()
|
||||
{
|
||||
emit stopSignal();
|
||||
|
||||
@ -70,6 +70,8 @@ public Q_SLOTS:
|
||||
void receiveFinishRecordLineNum(int lineNum);
|
||||
void onSequenceComplete();
|
||||
|
||||
void stop_record();
|
||||
|
||||
signals:
|
||||
void moveSignal(int, bool, double, int);
|
||||
void move2LocSignal(int, double, double, int);
|
||||
|
||||
Reference in New Issue
Block a user