Files
EJM_Display/Pages/P601_TransportPage.cpp

285 lines
15 KiB
C++
Raw Normal View History

2025-08-20 23:06:28 +08:00
#include "P601_TransportPage.h"
#include "ui_P601_TransportPage.h"
2025-10-10 17:44:10 +08:00
#include <GlobalDefinitions/Variable.h>
#include <FileOperation/ConfigFiles.h>
2025-08-20 23:06:28 +08:00
P601_TransportPage::P601_TransportPage(QWidget *parent) :
QWidget(parent),
ui(new Ui::P601_TransportPage)
{
ui->setupUi(this);
2025-10-10 17:44:10 +08:00
QTimer::singleShot(1000, this, &P601_TransportPage::WinInit);
// QTimer::singleShot(2000, this, &P601_TransportPage::Show3D);
2025-08-20 23:06:28 +08:00
}
P601_TransportPage::~P601_TransportPage()
{
delete ui;
}
2025-10-10 17:44:10 +08:00
void P601_TransportPage::WinInit(){
for (int row = 1; row < CutConditionConfigFile.size(); ++row)
{
QString TextObjName = QString("Text_SSConditions_%1").arg(row);
QLabel* Label = findChild<QLabel*>(TextObjName);
if (Label) {
QString Text = CutConditionConfigFile.at(row)[1];
Text.replace("\\n","\n",Qt::CaseInsensitive);
Label->setText(Text);
}
TrueColor.append(CutConditionConfigFile.at(row)[2]);
FalseColor.append(CutConditionConfigFile.at(row)[3]);
}
// 现在 ui->CPW_1 已经是一个 CurvePlotWidget*
ui->CPW_L1->addSeries("左U", Qt::green);
ui->CPW_L1->addSeries("左V", Qt::blue);
ui->CPW_L1->addSeries("左W", Qt::darkCyan);
// 现在 ui->CPW_1 已经是一个 CurvePlotWidget*
ui->CPW_L2->addSeries("左温", Qt::green);
// 现在 ui->CPW_1 已经是一个 CurvePlotWidget*
ui->CPW_R1->addSeries("右U", Qt::green);
ui->CPW_R1->addSeries("右V", Qt::blue);
ui->CPW_R1->addSeries("右W", Qt::darkCyan);
// 现在 ui->CPW_1 已经是一个 CurvePlotWidget*
ui->CPW_R2->addSeries("右温", Qt::green);
//所用定时器初始化
QTimer* UIRefresh_Timer = new QTimer(this);
connect(UIRefresh_Timer, &QTimer::timeout, this, &P601_TransportPage::UIRefreshTimeOut);
UIRefresh_Timer->setInterval(100); // 设置定时器间隔为 1000 毫秒1 秒)
UIRefresh_Timer->start();
//所用定时器初始化
QTimer* TrailRefresh_Timer = new QTimer(this);
connect(TrailRefresh_Timer, &QTimer::timeout, this, &P601_TransportPage::TrailRefreshTimeOut);
TrailRefresh_Timer->setInterval(100); // 设置定时器间隔为 1000 毫秒1 秒)
TrailRefresh_Timer->start();
}
void P601_TransportPage::Show3D()
{
DevName3D = "运输、铲板电机";
mObjLoader = new ObjLoader();
mObjLoader->setEnDebug(true);
mObjLoader->init3DScene(ui->Frame_Dev3D);
mObjLoader->setCameraSpeed(200.0, 200.0);
// 准备模型路径
QString filePath = "./3D模型文件/掘锚一体机/电机/" + DevName3D + ".obj";
m_currentDevName = DevName3D;
m_currentFilePath = filePath;
m_currentPosition = QVector3D(356.67, 65.0579, -0.231415);
// 检查文件是否存在
if (!QFile::exists(filePath)) {
qCritical() << "模型文件不存在: " << filePath;
return;
}
// 创建工作线程和工作对象
m_workerThread = new QThread(this);
m_workerLoader = new ObjLoader(); // 专用预处理加载器
// 移动工作对象到工作线程
m_workerLoader->moveToThread(m_workerThread);
// 连接信号槽
connect(m_workerThread, &QThread::started, [=]() {
// 在工作线程中预处理模型(仅计算中心和半径)
QVector3D center = m_workerLoader->parseObjCenter(filePath);
float radius = m_workerLoader->calculateModelRadiusFromFile(filePath);
emit preprocessFinished(center, radius);
});
// 预处理完成后,在主线程加载模型
connect(this, &P601_TransportPage::preprocessFinished, this, [=](QVector3D center, float radius) {
m_modelCenter = center;
m_modelRadius = radius;
// 使用定时器确保在主线程事件循环中执行
QTimer::singleShot(0, this, [=]() {
emit loadModelRequest(m_currentDevName, m_currentFilePath, center, radius);
});
// 清理工作线程
m_workerThread->quit();
m_workerThread->wait();
m_workerLoader->deleteLater();
});
// 主线程中实际加载模型
connect(this, &P601_TransportPage::loadModelRequest, this, [=](const QString& devName, const QString& filePath, QVector3D center, float radius) {
bool TransportOK = mObjLoader->loadModelAsync(devName, filePath, QVector3D(0, 0, 0), center, radius);
if (!TransportOK) {
qCritical() << "装载电机加载:失败";
return;
}
mObjLoader->addAxisGizmo(nullptr, 5.0f);
mObjLoader->addAxisGizmo(mObjLoader->getDevice(devName)->entity, 3.0f);
SetPos(0.005,QVector3D(356.67, 65.0579, -0.231415),QVector3D(0, 0, 0));
if (TransportOK) {
QTimer *RotateDev_Timer = new QTimer(this);
connect(RotateDev_Timer, &QTimer::timeout, this, &P601_TransportPage::RotateDev);
RotateDev_Timer->setInterval(33);
RotateDev_Timer->start();
}
});
// 启动工作线程
m_workerThread->start();
}
void P601_TransportPage::SetPos(float Zoom,QVector3D Move,QVector3D Pos){
mObjLoader->scaleDevice(DevName3D,Zoom);
mObjLoader->moveArmLocalOriginTo(DevName3D, Move);//14.1, -1.4, 3.4
mObjLoader->setParentDevicePosition(DevName3D, Pos); // 世界坐标
// 6. 重置相机(确保能看到所有设备)
Qt3DRender::QCamera* cam = mObjLoader->getCamera();
if (cam) {
cam->setPosition(QVector3D(0, 3, 12)); // 相机在 Z 轴 30 位置,远离模型
cam->setViewCenter(QVector3D(0, 0, 0)); // 看向电控箱体的世界位置
}
}
void P601_TransportPage::SetProgressBar(QProgressBar *PB,const uint16_t Value,const uint8_t ColorIndex,const QStringList Color){
PB->setValue(Value);
if(ColorIndex < Color.length()){
PB->setStyleSheet("QProgressBar {\n background-color: transparent;\n border: 2px solid #888888;\n border-radius: 3px;\n}\nQProgressBar::chunk {\n background-color:"+Color[ColorIndex]+";\n}");
}
}
void P601_TransportPage::SetProgressBar(QProgressBar *PB,QLCDNumber *LCD,const QString NodeGroup,const QString NodeLCD,const QStringList Color){
// 从OPC节点获取油位显示组数据32位无符号整数
uint32_t PB_Group = gOPC_NodeValue["ns=6;s=::AsGlobalPV:" + NodeGroup].toUInt();
// 从32位数据中拆分出16位油位百分比值和颜色值
uint16_t Percentage = static_cast<uint16_t>(PB_Group >> 16); // 高16位百分比
uint16_t ColorIndex = static_cast<uint16_t>(PB_Group & 0xFFFF); // 低16位颜色值索引
// 设置油位进度条显示(百分比、颜色和样式)
SetProgressBar(PB, Percentage, ColorIndex, Color);
// 在LCD上显示实际油位测量值
LCD->display(gOPC_NodeValue["ns=6;s=::AsGlobalPV:" +NodeLCD].toReal());
}
void P601_TransportPage::UIRefreshTimeOut()
{
if(!gPageIndexStr.contains("P601"))
return;
/************************************* 电机基本信息 *************************************/
// 从OPC节点获取切割设备电机相关的状态数据32位无符号整数
uint32_t PB_GroupL1 = gOPC_NodeValue["ns=6;s=::AsGlobalPV:PB_Curr_TransportL.PageGroup1"].toUInt(); // 电流显示组1数据
uint32_t PB_GroupL2 = gOPC_NodeValue["ns=6;s=::AsGlobalPV:PB_Curr_TransportL.PageGroup2"].toUInt(); // 电流显示组2数据
uint32_t PB_MotorTempL = gOPC_NodeValue["ns=6;s=::AsGlobalPV:PB_Temp_TransportL.PageGroup"].toUInt(); // 电机温度显示数据
// 从32位数据中提取16位百分比值高16位和低16位拆分
uint16_t PercentageCurLU = static_cast<uint16_t>(PB_GroupL1 >> 16); // U相电流百分比高16位
uint16_t PercentageCurLV = static_cast<uint16_t>(PB_GroupL1 & 0xFFFF); // V相电流百分比低16位
uint16_t PercentageCurLW = static_cast<uint16_t>(PB_GroupL2 >> 16); // W相电流百分比高16位
uint16_t PercentageTmpColorL = static_cast<uint16_t>(PB_GroupL2 & 0xFFFF); // 温度颜色百分比低16位
uint16_t PercentageMotorTempL= static_cast<uint16_t>(PB_MotorTempL >> 16); // 电机温度百分比高16位
uint16_t ColorTempL = static_cast<uint16_t>(PB_MotorTempL & 0xFFFF); // 温度颜色值低16位
// 解析颜色值(从百分比中提取个位、十位、百位)
uint8_t ColorLU = (PercentageTmpColorL / 10) % 10; // U相颜色值十位
uint8_t ColorLV = (PercentageTmpColorL / 100) % 10; // V相颜色值百位
uint8_t ColorLW = PercentageTmpColorL % 10; // W相颜色值个位
// 设置进度条显示(电流和温度)
SetProgressBar(ui->PB_CurL_1, PercentageCurLU, ColorLU, glMotorCurColor); // U相电流进度条
SetProgressBar(ui->PB_CurL_2, PercentageCurLV, ColorLV, glMotorCurColor); // V相电流进度条
SetProgressBar(ui->PB_CurL_3, PercentageCurLW, ColorLW, glMotorCurColor); // W相电流进度条
SetProgressBar(ui->PB_TempL, PercentageMotorTempL, ColorTempL, glMotorTempColor); // 电机温度进度条
// 在LCD上显示实际测量值电流和温度
ui->LCD_CurL_1->display(gOPC_NodeValue["ns=6;s=::AsGlobalPV:IN_PhaseTransportL.Filtered30_U"].toReal()); // U相电流实际值
ui->LCD_CurL_2->display(gOPC_NodeValue["ns=6;s=::AsGlobalPV:IN_PhaseTransportL.Filtered30_V"].toReal()); // V相电流实际值
ui->LCD_CurL_3->display(gOPC_NodeValue["ns=6;s=::AsGlobalPV:IN_PhaseTransportL.Filtered30_W"].toReal()); // W相电流实际值
ui->LCD_TempL->display(gOPC_NodeValue["ns=6;s=::AsGlobalPV:IN_PhaseTransportL.Filtered_Temp"].toReal()); // 电机温度实际值
/**************************************************************************************/
/************************************* 电机基本信息 *************************************/
// 从OPC节点获取切割设备电机相关的状态数据32位无符号整数
uint32_t PB_GroupR1 = gOPC_NodeValue["ns=6;s=::AsGlobalPV:PB_Curr_TransportR.PageGroup1"].toUInt(); // 电流显示组1数据
uint32_t PB_GroupR2 = gOPC_NodeValue["ns=6;s=::AsGlobalPV:PB_Curr_TransportR.PageGroup2"].toUInt(); // 电流显示组2数据
uint32_t PB_MotorTempR = gOPC_NodeValue["ns=6;s=::AsGlobalPV:PB_Temp_TransportR.PageGroup"].toUInt(); // 电机温度显示数据
// 从32位数据中提取16位百分比值高16位和低16位拆分
uint16_t PercentageCurRU = static_cast<uint16_t>(PB_GroupR1 >> 16); // U相电流百分比高16位
uint16_t PercentageCurRV = static_cast<uint16_t>(PB_GroupR1 & 0xFFFF); // V相电流百分比低16位
uint16_t PercentageCurRW = static_cast<uint16_t>(PB_GroupR2 >> 16); // W相电流百分比高16位
uint16_t PercentageTmpColorR = static_cast<uint16_t>(PB_GroupR2 & 0xFFFF); // 温度颜色百分比低16位
uint16_t PercentageMotorTempR= static_cast<uint16_t>(PB_MotorTempR >> 16); // 电机温度百分比高16位
uint16_t ColorTempR = static_cast<uint16_t>(PB_MotorTempR & 0xFFFF); // 温度颜色值低16位
// 解析颜色值(从百分比中提取个位、十位、百位)
uint8_t ColorRU = (PercentageTmpColorR / 10) % 10; // U相颜色值十位
uint8_t ColorRV = (PercentageTmpColorR / 100) % 10; // V相颜色值百位
uint8_t ColorRW = PercentageTmpColorR % 10; // W相颜色值个位
// 设置进度条显示(电流和温度)
SetProgressBar(ui->PB_CurR_1, PercentageCurRU, ColorRU, glMotorCurColor); // U相电流进度条
SetProgressBar(ui->PB_CurR_2, PercentageCurRV, ColorRV, glMotorCurColor); // V相电流进度条
SetProgressBar(ui->PB_CurR_3, PercentageCurRW, ColorRW, glMotorCurColor); // W相电流进度条
SetProgressBar(ui->PB_TempR, PercentageMotorTempR, ColorTempR, glMotorTempColor); // 电机温度进度条
// 在LCD上显示实际测量值电流和温度
ui->LCD_CurR_1->display(gOPC_NodeValue["ns=6;s=::AsGlobalPV:IN_PhaseTransportR.Filtered30_U"].toReal()); // U相电流实际值
ui->LCD_CurR_2->display(gOPC_NodeValue["ns=6;s=::AsGlobalPV:IN_PhaseTransportR.Filtered30_V"].toReal()); // V相电流实际值
ui->LCD_CurR_3->display(gOPC_NodeValue["ns=6;s=::AsGlobalPV:IN_PhaseTransportR.Filtered30_W"].toReal()); // W相电流实际值
ui->LCD_TempR->display(gOPC_NodeValue["ns=6;s=::AsGlobalPV:IN_PhaseTransportR.Filtered_Temp"].toReal()); // 电机温度实际值
/**************************************************************************************/
/************************************* 启停条件信息 *************************************/
uint32_t SSConditions = gOPC_NodeValue["ns=6;s=::AsGlobalPV:StartStopConditions.Transport"].toUInt(); // 启停条件状态数据
// 更新32个启停条件状态标签的显示样式
for (int i = 0; i < 32; ++i)
{
// 根据索引查找对应的标签控件
QLabel* Label = findChild<QLabel*>(QString("Text_SSConditions_%1").arg(i));
// 如果找到标签
if (Label){
// 基础样式:默认背景图
QString StyleStr = "border-image: url(:/Frames/null.png);\n";
// 根据状态位设置不同颜色True/False对应不同样式
StyleStr += getBitOf32Data(SSConditions, i, false) ? TrueColor[i] + "\n" : FalseColor[i] + "\n";
// 应用样式到标签
Label->setStyleSheet(StyleStr);
}
}
/**************************************************************************************/
}
void P601_TransportPage::TrailRefreshTimeOut(){
ui->CPW_L1->appendPoint(0, gOPC_NodeValue["ns=6;s=::AsGlobalPV:IN_PhaseTransportL.Filtered30_U"] .toReal());
ui->CPW_L1->appendPoint(1, gOPC_NodeValue["ns=6;s=::AsGlobalPV:IN_PhaseTransportL.Filtered30_V"] .toReal());
ui->CPW_L1->appendPoint(2, gOPC_NodeValue["ns=6;s=::AsGlobalPV:IN_PhaseTransportL.Filtered30_W"] .toReal());
ui->CPW_L2->appendPoint(0,gOPC_NodeValue["ns=6;s=::AsGlobalPV:IN_PhaseTransportL.Filtered_Temp"] .toDouble());
ui->CPW_R1->appendPoint(0, gOPC_NodeValue["ns=6;s=::AsGlobalPV:IN_PhaseTransportR.Filtered30_U"] .toReal());
ui->CPW_R1->appendPoint(1, gOPC_NodeValue["ns=6;s=::AsGlobalPV:IN_PhaseTransportR.Filtered30_V"] .toReal());
ui->CPW_R1->appendPoint(2, gOPC_NodeValue["ns=6;s=::AsGlobalPV:IN_PhaseTransportR.Filtered30_W"] .toReal());
ui->CPW_R2->appendPoint(0,gOPC_NodeValue["ns=6;s=::AsGlobalPV:IN_PhaseTransportR.Filtered_Temp"] .toDouble());
}
void P601_TransportPage::RotateDev(){
if(!gPageIndexStr.contains("P601"))
return;
mAngle = mAngle + 1;
if(mAngle > 360) mAngle =0;
mObjLoader->rotateArmToAbsoluteYAngle(DevName3D, mAngle);
}