Files
HPPA/HPPA/TwoMotorControl.cpp
tangchao0503 fa6ce1a606 fix
1、【相机----马达】双向意外断掉容错 + 提示:(1)ximea、pica l、pica nir(2)1轴/2轴马达,usb串口/wifi的马达通讯方式;
2、提示弹窗美化;
2026-04-03 19:32:51 +08:00

587 lines
18 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "TwoMotorControl.h"
TwoMotorControl::TwoMotorControl(QWidget* parent) : QDialog(parent)
{
ui.setupUi(this);
ui.recordLine_tableWidget->setFocusPolicy(Qt::NoFocus);
ui.recordLine_tableWidget->setSelectionBehavior(QAbstractItemView::SelectRows);//设置选择行为,以行为单位
//ui.recordLine_tableWidget->setSelectionMode(QAbstractItemView::SingleSelection);//设置选择模式,选择单行
//QHeaderView* headerView = ui.recordLine_tableWidget->verticalHeader();
//headerView->setHidden(true);//去除左边默认自带序列号
connect(this->ui.connect_btn, SIGNAL(pressed()), this, SLOT(onConnectMotor()));
connect(ui.addRecordLine_btn, SIGNAL(clicked()), this, SLOT(onAddRecordLine_btn()));
connect(ui.removeRecordLine_btn, SIGNAL(clicked()), this, SLOT(onRemoveRecordLine_btn()));
connect(ui.deleteRecordLine_btn, SIGNAL(clicked()), this, SLOT(onDeleteRecordLine_btn()));
connect(ui.saveRecordLine2File_btn, SIGNAL(clicked()), this, SLOT(onSaveRecordLine2File_btn()));
connect(ui.readRecordLineFile_btn, SIGNAL(clicked()), this, SLOT(onReadRecordLineFile_btn()));
connect(this->ui.xmotor_right_btn, SIGNAL(pressed()), this, SLOT(onxMotorRight()));
connect(this->ui.xmotor_right_btn, SIGNAL(released()), this, SLOT(onxMotorStop()));
connect(this->ui.xmotor_left_btn, SIGNAL(pressed()), this, SLOT(onxMotorLeft()));
connect(this->ui.xmotor_left_btn, SIGNAL(released()), this, SLOT(onxMotorStop()));
connect(this->ui.ymotor_forward_btn, SIGNAL(pressed()), this, SLOT(onyMotorforward()));
connect(this->ui.ymotor_forward_btn, SIGNAL(released()), this, SLOT(onyMotorStop()));
connect(this->ui.ymotor_backward_btn, SIGNAL(pressed()), this, SLOT(onyMotorbackward()));
connect(this->ui.ymotor_backward_btn, SIGNAL(released()), this, SLOT(onyMotorStop()));
connect(this->ui.move2loc_x_pushButton, SIGNAL(pressed()), this, SLOT(onxMove2Loc()));
connect(this->ui.move2loc_y_pushButton, SIGNAL(pressed()), this, SLOT(onyMove2Loc()));
connect(this->ui.zero_start_btn, SIGNAL(released()), this, SLOT(zeroStart()));
connect(this->ui.rangeMeasurement_btn, SIGNAL(pressed()), this, SLOT(on_rangeMeasurement()));
}
void TwoMotorControl::setImager(ImagerOperationBase* imager)
{
m_Imager = imager;
}
void TwoMotorControl::setPosFileName(QString posFileName)
{
isWritePosFile = true;
m_posFileName = posFileName;
m_posFileHandle = fopen(posFileName.toStdString().c_str(), "w+");
}
bool TwoMotorControl::getState()
{
if (m_coordinator == nullptr)
return false;
QEventLoop loop;
bool tmp = false;
bool received = false;
QTimer timer;
timer.setSingleShot(true);
connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
QMetaObject::Connection conn = QObject::connect(
m_coordinator, &TwoMotionCaptureCoordinator::recordState,
[&](bool state) {
tmp = state;
received = true;
loop.quit();
});
QMetaObject::invokeMethod(m_coordinator, "getRecordState", Qt::QueuedConnection);
timer.start(3000);
loop.exec();
disconnect(conn);
return tmp;
}
void TwoMotorControl::record_dark()
{
double s = ui.xmotor_move_speed_lineEdit->text().toDouble();
if (m_darkCaptureCoordinator == nullptr)
{
m_darkCaptureCoordinator = new DarkAndWhiteCaptureCoordinator(0, m_multiAxisController, m_Imager);
}
m_darkCaptureCoordinator->startStepMotion(s);
}
void TwoMotorControl::record_white()
{
double s = ui.xmotor_move_speed_lineEdit->text().toDouble();
if (m_whiteCaptureCoordinator == nullptr)
{
m_whiteCaptureCoordinator = new DarkAndWhiteCaptureCoordinator(1, m_multiAxisController, m_Imager);
}
m_whiteCaptureCoordinator->startStepMotion(s);
}
void TwoMotorControl::run()
{
if (getState())
{
QMessageBox::information(this, QString::fromLocal8Bit("提示"), QString::fromLocal8Bit("已经开始运行,请勿重复点击!"));
return;
}
int rowCount = ui.recordLine_tableWidget->rowCount();
if(rowCount == 0)
{
QMessageBox::information(this, QString::fromLocal8Bit("提示"), QString::fromLocal8Bit("请至少添加一行采集线!"));
emit sequenceComplete();
return;
}
qRegisterMetaType<QVector<PathLine>>("QVector<PathLine>");
m_coordinator = new TwoMotionCaptureCoordinator(m_multiAxisController, m_Imager);
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()));
m_coordinatorThread.start();
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::stop()
{
emit stopSignal();
}
TwoMotorControl::~TwoMotorControl()
{
m_motorThread.quit();
m_motorThread.wait();
m_coordinatorThread.quit();
m_coordinatorThread.wait();
}
void TwoMotorControl::onConnectMotor()
{
if (getMotorsConnectionStatus())
{
QMessageBox msgBox;
msgBox.setText(QString::fromLocal8Bit("马达已连接!"));
msgBox.exec();
return;
}
if (m_multiAxisController != nullptr)
{
disconnect(m_multiAxisController, SIGNAL(broadcastLocationSignal(std::vector<double>)), this, SLOT(displayRealTimeLoc(std::vector<double>)));
disconnect(this, SIGNAL(moveSignal(int, bool, double, int)), m_multiAxisController, SLOT(move(int, bool, double, int)));
disconnect(this, SIGNAL(move2LocSignal(int, double, double, int)), m_multiAxisController, SLOT(moveTo(int, double, double, int)));
disconnect(this, SIGNAL(stopSignal(int)), m_multiAxisController, SLOT(stop(int)));
disconnect(this, SIGNAL(zeroStartSignal(int)), m_multiAxisController, SLOT(zeroStart(int)));
disconnect(this, SIGNAL(rangeMeasurement(int, double, int)), m_multiAxisController, SLOT(rangeMeasurement(int, double, int)));
disconnect(this, SIGNAL(testConnectivitySignal(int, int)), m_multiAxisController, SLOT(testConnectivity(int, int)));
disconnect(m_multiAxisController, SIGNAL(broadcastConnectivity(std::vector<int>)), this, SLOT(display_motors_connectivity(std::vector<int>)));
m_motorThread.quit();
m_motorThread.wait();
m_multiAxisController = nullptr;
}
try
{
FileOperation* fileOperation = new FileOperation();
string directory = fileOperation->getDirectoryOfExe();
QString configFilePath = QString::fromStdString(directory) + "\\twoMotorConfigFile.cfg";
m_multiAxisController = new IrisMultiMotorController(configFilePath);
}
catch (std::exception const& e)
{
QMessageBox msgBox;
msgBox.setText(QString::fromLocal8Bit("请连接马达!"));
msgBox.exec();
return;
}
m_multiAxisController->moveToThread(&m_motorThread);
connect(&m_motorThread, SIGNAL(finished()), m_multiAxisController, SLOT(deleteLater()));
connect(m_multiAxisController, SIGNAL(broadcastLocationSignal(std::vector<double>)), this, SLOT(displayRealTimeLoc(std::vector<double>)));
connect(this, SIGNAL(moveSignal(int, bool, double, int)), m_multiAxisController, SLOT(move(int, bool, double, int)));
connect(this, SIGNAL(move2LocSignal(int, double, double, int)), m_multiAxisController, SLOT(moveTo(int, double, double, int)));
connect(this, SIGNAL(stopSignal(int)), m_multiAxisController, SLOT(stop(int)));
connect(this, SIGNAL(zeroStartSignal(int)), m_multiAxisController, SLOT(zeroStart(int)));
connect(this, SIGNAL(rangeMeasurement(int, double, int)), m_multiAxisController, SLOT(rangeMeasurement(int, double, int)));
connect(this, SIGNAL(testConnectivitySignal(int, int)), m_multiAxisController, SLOT(testConnectivity(int, int)));
connect(m_multiAxisController, SIGNAL(broadcastConnectivity(std::vector<int>)), this, SLOT(display_motors_connectivity(std::vector<int>)));
m_motorThread.start();
emit testConnectivitySignal(0, 1000);
emit testConnectivitySignal(1, 1000);
}
void TwoMotorControl::receiveStartRecordLineNum(int lineNum)
{
emit startLineNumSignal(lineNum);
for (size_t i = 0; i < ui.recordLine_tableWidget->columnCount(); i++)
{
ui.recordLine_tableWidget->item(lineNum, i)->setBackgroundColor(QColor(255, 0, 0));
}
}
void TwoMotorControl::receiveFinishRecordLineNum(int lineNum)
{
for (size_t i = 0; i < ui.recordLine_tableWidget->columnCount(); i++)
{
ui.recordLine_tableWidget->item(lineNum, i)->setBackgroundColor(QColor(0, 255, 0));
}
}
void TwoMotorControl::onSequenceComplete()
{
isWritePosFile = false;
fclose(m_posFileHandle);
m_coordinatorThread.quit();
m_coordinatorThread.wait();
m_coordinator = nullptr;
emit sequenceComplete();
}
bool TwoMotorControl::getMotorsConnectionStatus()
{
return m_xMotorConnectionStatus && m_yMotorConnectionStatus;
}
void TwoMotorControl::display_motors_connectivity(std::vector<int> connectivity)
{
//std::cout << "-----------------------------------"<<connectivity.size()<< std::endl;
if (connectivity[0])
{
m_xMotorConnectionStatus = true;
this->ui.xMotorStateLabel->setStyleSheet(R"(
QLabel
{
background-color: #08FACE;
border-radius: 4px;
}
)");
}
else
{
m_xMotorConnectionStatus = false;
this->ui.xMotorStateLabel->setStyleSheet(R"(
QLabel
{
background-color: red;
border-radius: 4px;
}
)");
}
if (connectivity[1])
{
m_yMotorConnectionStatus = true;
this->ui.yMotorStateLabel->setStyleSheet(R"(
QLabel
{
background-color: #08FACE;
border-radius: 4px;
}
)");
}
else
{
m_yMotorConnectionStatus = false;
this->ui.yMotorStateLabel->setStyleSheet(R"(
QLabel
{
background-color: red;
border-radius: 4px;
}
)");
}
if(getMotorsConnectionStatus())
{
this->ui.connect_btn->setText(QString::fromLocal8Bit("已连接"));
}
else
{
this->ui.connect_btn->setText(QString::fromLocal8Bit("重新连接"));
}
}
void TwoMotorControl::onxMotorRight()
{
double s = ui.xmotor_move_speed_lineEdit->text().toDouble();
emit moveSignal(0, false, s, 1000);
}
void TwoMotorControl::onxMotorLeft()
{
double s = ui.xmotor_move_speed_lineEdit->text().toDouble();
emit moveSignal(0, true, s, 1000);
}
void TwoMotorControl::onxMotorStop()
{
emit stopSignal(0);
}
void TwoMotorControl::onyMotorforward()
{
double s = ui.ymotor_move_speed_lineEdit->text().toDouble();
emit moveSignal(1, false, s, 1000);
}
void TwoMotorControl::onyMotorbackward()
{
double s = ui.ymotor_move_speed_lineEdit->text().toDouble();
emit moveSignal(1, true, s, 1000);
}
void TwoMotorControl::onyMotorStop()
{
emit stopSignal(1);
}
void TwoMotorControl::onxMove2Loc()
{
double s = ui.xmotor_move_speed_lineEdit->text().toDouble();
double l = ui.move2loc_x_lineEdit->text().toDouble();
emit move2LocSignal(0, l, s, 1000);
}
void TwoMotorControl::onyMove2Loc()
{
double s = ui.ymotor_move_speed_lineEdit->text().toDouble();
double l = ui.move2loc_y_lineEdit->text().toDouble();
emit move2LocSignal(1, l, s, 1000);
}
void TwoMotorControl::displayRealTimeLoc(std::vector<double> loc)
{
double tmp = round(loc[0] * 100) / 100;
if (isWritePosFile)
{
long long timeOs = getNanosecondsSinceMidnight();
fprintf(m_posFileHandle, "%lld,%f\n", timeOs, loc[0]);
}
this->ui.xmotor_realTimeLoc_lineEdit->setText(QString::number(tmp));
tmp = round(loc[1] * 100) / 100;
this->ui.ymotor_realTimeLoc_lineEdit->setText(QString::number(tmp));
emit broadcastLocationSignal(loc);
}
void TwoMotorControl::zeroStart()
{
zeroStartSignal(0);
zeroStartSignal(1);
}
void TwoMotorControl::on_rangeMeasurement()
{
double s0 = ui.xmotor_move_speed_lineEdit->text().toDouble();
emit rangeMeasurement(0, s0, 1000);
s0 = ui.ymotor_move_speed_lineEdit->text().toDouble();
emit rangeMeasurement(1, s0, 1000);
}
void TwoMotorControl::onAddRecordLine_btn()
{
//准备数据获取y马达的当前位置获取x马达的当前位置和最大位置
double currentPosOfYmotor = 15;
double currentPosOfXmotor = 0;
double maxRangeOfXmotor = 50;
//获取选中行的索引
int currentRow = ui.recordLine_tableWidget->currentRow();
std::cout << "currentRow" << currentRow << std::endl;
QTableWidgetItem* Item1 = new QTableWidgetItem(QString::number(currentPosOfYmotor, 10, 2));
QTableWidgetItem* Item2 = new QTableWidgetItem(QString::number(1, 10, 2));
QTableWidgetItem* Item3 = new QTableWidgetItem(QString::number(currentPosOfXmotor, 10, 2));
QTableWidgetItem* Item4 = new QTableWidgetItem(QString::number(1, 10, 2));
QTableWidgetItem* Item5 = new QTableWidgetItem(QString::number(maxRangeOfXmotor, 10, 2));
QTableWidgetItem* Item6 = new QTableWidgetItem(QString::number(1, 10, 2));
Item1->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
Item2->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
Item3->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
Item4->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
Item5->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
Item6->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
if (currentRow == -1)//当没有选中行时
{
int RowCount = ui.recordLine_tableWidget->rowCount();//Returns the number of rows. 从1开始的
ui.recordLine_tableWidget->insertRow(RowCount);//增加一行形参是从0开始的
ui.recordLine_tableWidget->setItem(RowCount, 0, Item1);
ui.recordLine_tableWidget->setItem(RowCount, 1, Item2);
ui.recordLine_tableWidget->setItem(RowCount, 2, Item3);
ui.recordLine_tableWidget->setItem(RowCount, 3, Item4);
ui.recordLine_tableWidget->setItem(RowCount, 4, Item5);
ui.recordLine_tableWidget->setItem(RowCount, 5, Item6);
}
else
{
ui.recordLine_tableWidget->insertRow(currentRow + 1);//增加一行形参是从0开始的
ui.recordLine_tableWidget->setItem(currentRow + 1, 0, Item1);
ui.recordLine_tableWidget->setItem(currentRow + 1, 1, Item2);
ui.recordLine_tableWidget->setItem(currentRow + 1, 2, Item3);
ui.recordLine_tableWidget->setItem(currentRow + 1, 3, Item4);
ui.recordLine_tableWidget->setItem(currentRow + 1, 4, Item5);
ui.recordLine_tableWidget->setItem(currentRow + 1, 5, Item6);
}
}
void TwoMotorControl::onRemoveRecordLine_btn()
{
int rowIndex = ui.recordLine_tableWidget->currentRow();
if (rowIndex != -1)
ui.recordLine_tableWidget->removeRow(rowIndex);
}
void TwoMotorControl::onDeleteRecordLine_btn()
{
int rowCount = ui.recordLine_tableWidget->rowCount();
for (size_t i = 0; i < rowCount; i++)
{
ui.recordLine_tableWidget->removeRow(0);
}
}
void TwoMotorControl::onSaveRecordLine2File_btn()
{
//确保采集线存在
if (ui.recordLine_tableWidget->rowCount() <= 0)
{
QMessageBox::information(this, QString::fromLocal8Bit("提示"), QString::fromLocal8Bit("请先生成轨迹!"));
return;
}
FileOperation* fileOperation = new FileOperation();
string directory = fileOperation->getDirectoryOfExe();
QString RecordLineFilePath = QFileDialog::getSaveFileName(this, tr("Save RecordLine3 File"),
QString::fromStdString(directory),
tr("RecordLineFile3 (*.RecordLine3)"));
if (RecordLineFilePath.isEmpty())
{
return;
}
FILE* RecordLineFileHandle = fopen(RecordLineFilePath.toStdString().c_str(), "wb+");
double number = ui.recordLine_tableWidget->rowCount() * ui.recordLine_tableWidget->columnCount();
fwrite(&number, sizeof(double), 1, RecordLineFileHandle);
double* data = new double[number];
//double data[number];
for (size_t i = 0; i < ui.recordLine_tableWidget->rowCount(); i++)
{
for (size_t j = 0; j < ui.recordLine_tableWidget->columnCount(); j++)
{
data[i * ui.recordLine_tableWidget->columnCount() + j] = ui.recordLine_tableWidget->item(i, j)->text().toDouble();
}
}
fwrite(data, sizeof(double), number, RecordLineFileHandle);
fclose(RecordLineFileHandle);
delete[] data;
//QMessageBox::information(this, QString::fromLocal8Bit("提示"), QString::fromLocal8Bit("保存成功!"));
}
void TwoMotorControl::onReadRecordLineFile_btn()
{
//打开文件
FileOperation* fileOperation = new FileOperation();
string directory = fileOperation->getDirectoryOfExe();
QString RecordLineFilePath = QFileDialog::getOpenFileName(this, tr("Open RecordLine3 File"),
QString::fromStdString(directory),
tr("RecordLineFile (*.RecordLine3)"));
if (RecordLineFilePath.isEmpty())
{
return;
}
FILE* RecordLineFileHandle = fopen(RecordLineFilePath.toStdString().c_str(), "rb");
double number;
//读取数据
fread(&number, sizeof(double), 1, RecordLineFileHandle);
double* data = new double[number];
for (size_t i = 0; i < number; i++)
{
fread(data + i, sizeof(double), 1, RecordLineFileHandle);
//std::cout << *(data + i) << std::endl;
}
//向tableWidget添加采集线
//1去掉tableWidget中所有的行
int rowCount = ui.recordLine_tableWidget->rowCount();
for (size_t i = 0; i < rowCount; i++)
{
ui.recordLine_tableWidget->removeRow(0);
}
//2添加行采集线
int RecordLineCount = number / ui.recordLine_tableWidget->columnCount();
for (size_t i = 0; i < RecordLineCount; i++)
{
ui.recordLine_tableWidget->insertRow(0);
}
//3向tableWidget填充数据
for (size_t i = 0; i < ui.recordLine_tableWidget->rowCount(); i++)
{
for (size_t j = 0; j < ui.recordLine_tableWidget->columnCount(); j++)
{
QTableWidgetItem* tmp = new QTableWidgetItem(QString::number(data[i * ui.recordLine_tableWidget->columnCount() + j], 10, 5));
tmp->setTextAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
ui.recordLine_tableWidget->setItem(i, j, tmp);
}
}
fclose(RecordLineFileHandle);
delete[] data;
//QMessageBox::information(this, QString::fromLocal8Bit("提示"), QString::fromLocal8Bit("读取成功!"));
}