1033 lines
28 KiB
C++
1033 lines
28 KiB
C++
#include "stdafx.h"
|
||
#include "focusWindow.h"
|
||
#include <QSvgRenderer>
|
||
#include <QMouseEvent>
|
||
|
||
focusWindow::focusWindow(QWidget *parent, ImagerOperationBase* imager)
|
||
{
|
||
ui.setupUi(this);
|
||
|
||
setWindowFlags(Qt::FramelessWindowHint);
|
||
ui.titlebarWidget->installEventFilter(this);
|
||
|
||
QSvgRenderer svgRenderer(QString(":/svg/resources/icons/svg/focus.svg"));
|
||
QPixmap pixmap(24, 24);
|
||
pixmap.fill(Qt::transparent); // 背景透明
|
||
QPainter painter(&pixmap);
|
||
svgRenderer.render(&painter);
|
||
ui.iconLabel->setPixmap(pixmap);
|
||
|
||
//读取配置文件
|
||
string HPPACfgFile = getPathofEXE() + "\\HPPA.cfg";
|
||
Configfile configfile;
|
||
configfile.setConfigfilePath(HPPACfgFile);
|
||
if (!configfile.isConfigfileExist())
|
||
configfile.createConfigFile();
|
||
|
||
configfile.parseConfigfile();
|
||
configfile.getPositionRestriction(m_iMaxPos, m_iMinPos);
|
||
|
||
|
||
disableBeforeConnect(true);
|
||
|
||
setAttribute(Qt::WA_DeleteOnClose);//设置关闭窗体就调用窗体的析构函数
|
||
|
||
m_Imager = imager;
|
||
m_FocusState = 0;
|
||
m_ctrlFocusMotor = nullptr;
|
||
|
||
m_AutoFocusThread = new QThread();
|
||
|
||
connect(this->ui.connectMotor_btn, SIGNAL(clicked()), this, SLOT(onConnectMotor()));
|
||
connect(this->ui.logicZero_btn, SIGNAL(clicked()), this, SLOT(onMove2MotorLogicZero()));
|
||
connect(this->ui.max_btn, SIGNAL(clicked()), this, SLOT(onMove2MotorMax()));
|
||
connect(this->ui.add_btn, SIGNAL(clicked()), this, SLOT(onAdd()));
|
||
connect(this->ui.subtract_btn, SIGNAL(clicked()), this, SLOT(onSubtract()));
|
||
connect(this->ui.ultrasound_radioButton, SIGNAL(released()), this, SLOT(onUltrasound_radioButton()));
|
||
connect(this->ui.autoFocus_btn, SIGNAL(clicked()), this, SLOT(onAutoFocus()));
|
||
connect(this->ui.manualFocus_btn, SIGNAL(clicked()), this, SLOT(onManualFocus()));
|
||
|
||
connect(this->ui.updateCurrentLocation_btn, SIGNAL(clicked()), this, SLOT(onUpdateCurrentLocation()));
|
||
connect(this->ui.moveto_btn, SIGNAL(clicked()), this, SLOT(onMoveto()));
|
||
|
||
connect(this->ui.rangeMeasurement_btn, SIGNAL(pressed()), this, SLOT(onx_rangeMeasurement()));
|
||
connect(this->ui.closeBtn, SIGNAL(released()), this, SLOT(onExit()));
|
||
|
||
connect(this->ui.is_new_version_radioButton, &QRadioButton::toggled, this, [this](bool checked) {
|
||
ui.stackedWidget_connetcParm->setCurrentIndex(checked ? 0 : 1);
|
||
});
|
||
|
||
//查找可用串口,并显示
|
||
foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
|
||
{
|
||
QSerialPort serial;
|
||
serial.setPort(info);
|
||
if (serial.open(QIODevice::ReadWrite))
|
||
{
|
||
ui.motorPort_comboBox->addItem(serial.portName());
|
||
ui.ultrasoundPort_comboBox->addItem(serial.portName());
|
||
serial.close();
|
||
}
|
||
}
|
||
|
||
//设置自动调焦进度条
|
||
ui.autoFocusProgress_progressBar->setMinimum(0);
|
||
ui.autoFocusProgress_progressBar->setMaximum(100);
|
||
ui.autoFocusProgress_progressBar->reset();
|
||
|
||
m_dSpeed = 1.0;
|
||
}
|
||
|
||
void focusWindow::showMessageBox(QString msg, QString title)
|
||
{
|
||
QMessageBox msgBox(this);
|
||
msgBox.setWindowTitle(title);
|
||
msgBox.setText(msg);
|
||
msgBox.setStyleSheet(R"(
|
||
QMessageBox {
|
||
background-color: #0D1233;
|
||
}
|
||
QMessageBox QLabel {
|
||
color: #ACCDFF;
|
||
font-size: 14px;
|
||
}
|
||
QPushButton {
|
||
background-color: #142D7F;
|
||
color: #e6eeff;
|
||
border: 1px solid #2f6bff;
|
||
border-radius: 6px;
|
||
padding: 6px 20px;
|
||
min-width: 60px;
|
||
font-size: 13px;
|
||
}
|
||
QPushButton:hover {
|
||
border: 1px solid #4d8dff;
|
||
background-color: red;
|
||
}
|
||
QPushButton:pressed {
|
||
background-color: #23345c;
|
||
}
|
||
)");
|
||
|
||
msgBox.exec();
|
||
}
|
||
|
||
focusWindow::~focusWindow()
|
||
{
|
||
printf("destroy focusWindow-------------------------\n");
|
||
|
||
emit StartManualFocusSignal(0);//当用户没有点击停止调焦就关闭窗口
|
||
emit closeSignal();
|
||
|
||
delete m_ctrlFocusMotor;
|
||
//delete thread1, progressThread;
|
||
|
||
m_motorThread.quit();
|
||
m_motorThread.wait();
|
||
|
||
m_MotionCaptureCoordinatorThread.quit();
|
||
m_MotionCaptureCoordinatorThread.wait();
|
||
}
|
||
|
||
void focusWindow::onExit()
|
||
{
|
||
this->close();
|
||
}
|
||
|
||
bool focusWindow::eventFilter(QObject *obj, QEvent *event)
|
||
{
|
||
if (obj == ui.titlebarWidget)
|
||
{
|
||
if (event->type() == QEvent::MouseButtonPress)
|
||
{
|
||
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
|
||
if (mouseEvent->button() == Qt::LeftButton)
|
||
{
|
||
m_bDrag = true;
|
||
m_dragPosition = mouseEvent->globalPos() - frameGeometry().topLeft();
|
||
return true;
|
||
}
|
||
}
|
||
else if (event->type() == QEvent::MouseMove)
|
||
{
|
||
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
|
||
if (m_bDrag && (mouseEvent->buttons() & Qt::LeftButton))
|
||
{
|
||
move(mouseEvent->globalPos() - m_dragPosition);
|
||
return true;
|
||
}
|
||
}
|
||
else if (event->type() == QEvent::MouseButtonRelease)
|
||
{
|
||
QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
|
||
if (mouseEvent->button() == Qt::LeftButton)
|
||
{
|
||
m_bDrag = false;
|
||
return true;
|
||
}
|
||
}
|
||
}
|
||
return QDialog::eventFilter(obj, event);
|
||
}
|
||
|
||
void focusWindow::disableBeforeConnect(bool disable)
|
||
{
|
||
ui.controlMotor_widget->setDisabled(disable);
|
||
ui.autoFocus_btn->setDisabled(disable);
|
||
}
|
||
|
||
bool test(void *pCaller, int *x, int *y, void **pvdata)
|
||
{
|
||
focusWindow *p = (focusWindow *)pCaller;
|
||
|
||
p->m_Imager->GetFrameSize(*x, *y);
|
||
USHORT *pusData = new USHORT[(*x)*(*y)];
|
||
|
||
p->m_Imager->imagerStartCollect();
|
||
p->m_Imager->getFrame(pusData);
|
||
p->m_Imager->imagerStopCollect();
|
||
|
||
|
||
BYTE *pbData = (BYTE*)pusData;
|
||
*pvdata = pbData;
|
||
return true;
|
||
}
|
||
|
||
void focusWindow::onConnectMotor()
|
||
{
|
||
if (ui.is_new_version_radioButton->isChecked())
|
||
{
|
||
connectMotor(true);
|
||
}
|
||
else
|
||
{
|
||
if (m_ctrlFocusMotor != nullptr)
|
||
{
|
||
printf("不能重复连接-------------------------\n");
|
||
return;
|
||
}
|
||
|
||
bool isUltrasound = ui.ultrasound_radioButton->isChecked();
|
||
|
||
QString motorPortTmp = ui.motorPort_comboBox->currentText();
|
||
QString ultrasoundPortTmp = ui.ultrasoundPort_comboBox->currentText();
|
||
|
||
QRegExp rx("\\d+$");
|
||
rx.indexIn(motorPortTmp, 0);
|
||
int motorPort = rx.cap(0).toInt();
|
||
rx.indexIn(ultrasoundPortTmp, 0);
|
||
int ultrasoundPort = rx.cap(0).toInt();
|
||
|
||
|
||
|
||
if (isUltrasound)
|
||
{
|
||
PortInfo motor;
|
||
motor.iPortType = 0;
|
||
motor.indexParity = 0;
|
||
|
||
motor.iPortNumber = motorPort;
|
||
motor.indexBaudRate = 0x13;
|
||
motor.indexBytesize = 3;
|
||
motor.indexStopBits = 0;
|
||
|
||
PortInfo ultrasound;
|
||
ultrasound.iPortType = 0;
|
||
ultrasound.indexParity = 0;
|
||
ultrasound.iPortNumber = ultrasoundPort;
|
||
ultrasound.indexBaudRate = 0x0C;
|
||
ultrasound.indexBytesize = 3;
|
||
ultrasound.indexStopBits = 0;
|
||
|
||
m_ctrlFocusMotor = new CFocusMotorControl();
|
||
|
||
m_ctrlFocusMotor->SetLogicZero(m_iMinPos);
|
||
m_ctrlFocusMotor->SetLimit(m_iMinPos, m_iMaxPos);
|
||
m_ctrlFocusMotor->InitSystem(motor, ultrasound, test, this);
|
||
//m_ctrlFocusMotor->MoveToLogicZero();
|
||
}
|
||
else
|
||
{
|
||
PortInfo motor;
|
||
motor.iPortType = 0;
|
||
motor.indexParity = 0;
|
||
motor.iPortNumber = motorPort;
|
||
motor.indexBaudRate = 0x13;
|
||
motor.indexBytesize = 3;
|
||
motor.indexStopBits = 0;
|
||
|
||
m_ctrlFocusMotor = new CFocusMotorControl();
|
||
|
||
m_ctrlFocusMotor->SetLogicZero(m_iMinPos);
|
||
m_ctrlFocusMotor->SetLimit(m_iMinPos, m_iMaxPos);
|
||
m_ctrlFocusMotor->InitSystem(motor, test, this);
|
||
m_ctrlFocusMotor->MoveToLogicZero();
|
||
}
|
||
}
|
||
|
||
disableBeforeConnect(false);
|
||
}
|
||
|
||
void focusWindow::connectMotor(bool isNotification)//需要修改这个函数
|
||
{
|
||
if (getMotorsConnectionStatus())
|
||
{
|
||
if (isNotification)
|
||
{
|
||
showMessageBox(QString::fromLocal8Bit("马达已连接!"));
|
||
}
|
||
return;
|
||
}
|
||
|
||
if (m_multiAxisController)
|
||
{
|
||
disconnect(&m_motorThread, SIGNAL(finished()), m_multiAxisController, SLOT(deleteLater()));
|
||
disconnect(this, SIGNAL(rmoveSignal(int, double, double, int)), m_multiAxisController, SLOT(rmove(int, double, double, int)));
|
||
disconnect(this, SIGNAL(move2LocSignal(int, double, double, int)), m_multiAxisController, SLOT(moveTo(int, double, double, int)));
|
||
disconnect(this, SIGNAL(rangeMeasurementSignal(int, double, int)), m_multiAxisController, SLOT(rangeMeasurement(int, double, int)));
|
||
disconnect(this, SIGNAL(zeroStartSignal(int)), m_multiAxisController, SLOT(zeroStart(int)));
|
||
disconnect(this, SIGNAL(move2MaxLocSignal(int, double, int)), m_multiAxisController, SLOT(moveToMax(int, double, int)));
|
||
disconnect(m_multiAxisController, SIGNAL(broadcastLocationSignal(std::vector<double>)), this, SLOT(display_x_loc(std::vector<double>)));
|
||
disconnect(m_multiAxisController, SIGNAL(motorStopSignal(int, double)), this, SLOT(moveAfterAutoFocus(int, double)));
|
||
disconnect(m_multiAxisController, SIGNAL(broadcastConnectivity(std::vector<int>)), this, SLOT(display_motors_connectivity(std::vector<int>)));
|
||
|
||
m_motorThread.quit();
|
||
m_motorThread.wait();
|
||
m_multiAxisController->deleteLater();
|
||
}
|
||
|
||
if (m_coordinator)
|
||
{
|
||
disconnect(&m_MotionCaptureCoordinatorThread, SIGNAL(finished()), m_coordinator, SLOT(deleteLater()));
|
||
disconnect(this, SIGNAL(startStepMotionSignal(double, int, double, double)), m_coordinator, SLOT(startStepMotion(double, int, double, double)));
|
||
disconnect(m_coordinator, SIGNAL(progressChanged(int)), this, SLOT(onAutoFocusProgress(int)));
|
||
disconnect(m_coordinator, SIGNAL(sequenceComplete()), this, SLOT(onAutoFocusFinished()));
|
||
|
||
m_MotionCaptureCoordinatorThread.quit();
|
||
m_MotionCaptureCoordinatorThread.wait();
|
||
m_coordinator->deleteLater();
|
||
}
|
||
|
||
try
|
||
{
|
||
FileOperation* fileOperation = new FileOperation();
|
||
string directory = fileOperation->getDirectoryOfExe();
|
||
QString configFilePath = QString::fromStdString(directory) + "\\oneMotorConfigFile_focus.cfg";
|
||
|
||
m_multiAxisController = new IrisMultiMotorController(configFilePath);
|
||
}
|
||
catch (std::exception const& e)
|
||
{
|
||
showMessageBox(QString::fromLocal8Bit("请连接马达!"));
|
||
return;
|
||
}
|
||
|
||
m_multiAxisController->moveToThread(&m_motorThread);
|
||
connect(&m_motorThread, SIGNAL(finished()), m_multiAxisController, SLOT(deleteLater()));
|
||
connect(this, SIGNAL(rmoveSignal(int, double, double, int)), m_multiAxisController, SLOT(rmove(int, double, double, int)));
|
||
connect(this, SIGNAL(move2LocSignal(int, double, double, int)), m_multiAxisController, SLOT(moveTo(int, double, double, int)));
|
||
connect(this, SIGNAL(rangeMeasurementSignal(int, double, int)), m_multiAxisController, SLOT(rangeMeasurement(int, double, int)));
|
||
connect(this, SIGNAL(zeroStartSignal(int)), m_multiAxisController, SLOT(zeroStart(int)));
|
||
connect(this, SIGNAL(move2MaxLocSignal(int, double, int)), m_multiAxisController, SLOT(moveToMax(int, double, int)));
|
||
connect(m_multiAxisController, SIGNAL(broadcastLocationSignal(std::vector<double>)), this, SLOT(display_x_loc(std::vector<double>)));
|
||
connect(m_multiAxisController, SIGNAL(motorStopSignal(int, double)), this, SLOT(moveAfterAutoFocus(int, double)));
|
||
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 zeroStartSignal(0);
|
||
|
||
//自动调焦逻辑
|
||
m_coordinator = new MotionCaptureCoordinator(m_multiAxisController, m_Imager);
|
||
m_coordinator->moveToThread(&m_MotionCaptureCoordinatorThread);
|
||
connect(&m_MotionCaptureCoordinatorThread, SIGNAL(finished()), m_coordinator, SLOT(deleteLater()));
|
||
connect(this, SIGNAL(startStepMotionSignal(double, int, double, double)), m_coordinator, SLOT(startStepMotion(double, int, double, double)));
|
||
connect(m_coordinator, SIGNAL(progressChanged(int)), this, SLOT(onAutoFocusProgress(int)));
|
||
connect(m_coordinator, SIGNAL(sequenceComplete()), this, SLOT(onAutoFocusFinished()));
|
||
m_MotionCaptureCoordinatorThread.start();
|
||
|
||
}
|
||
|
||
void focusWindow::display_motors_connectivity(std::vector<int> connectivity)
|
||
{
|
||
//std::cout << "-----------------------------------"<<connectivity.size()<< std::endl;
|
||
if (connectivity[0])
|
||
{
|
||
m_xMotorConnectionStatus = true;
|
||
|
||
this->ui.motor_state_label->setStyleSheet(R"(
|
||
QLabel
|
||
{
|
||
background-color: #08FACE;
|
||
border-radius: 4px;
|
||
}
|
||
)");
|
||
}
|
||
else
|
||
{
|
||
m_xMotorConnectionStatus = false;
|
||
|
||
this->ui.motor_state_label->setStyleSheet(R"(
|
||
QLabel
|
||
{
|
||
background-color: red;
|
||
border-radius: 4px;
|
||
}
|
||
)");
|
||
}
|
||
|
||
if (getMotorsConnectionStatus())
|
||
{
|
||
this->ui.connectMotor_btn->setText(QString::fromLocal8Bit("已连接"));
|
||
}
|
||
else
|
||
{
|
||
this->ui.connectMotor_btn->setText(QString::fromLocal8Bit("重新连接"));
|
||
}
|
||
}
|
||
|
||
bool focusWindow::getMotorsConnectionStatus()
|
||
{
|
||
return m_xMotorConnectionStatus;
|
||
}
|
||
|
||
void focusWindow::display_x_loc(std::vector<double> loc)
|
||
{
|
||
double tmp = round(loc[0] * 100) / 100;
|
||
this->ui.currentLocation_lineEdit->setText(QString::number(tmp));
|
||
}
|
||
|
||
void focusWindow::onx_rangeMeasurement()
|
||
{
|
||
emit rangeMeasurementSignal(0, m_dSpeed, 1000);
|
||
}
|
||
|
||
void focusWindow::onMove2MotorLogicZero()
|
||
{
|
||
if (ui.is_new_version_radioButton->isChecked())
|
||
{
|
||
emit zeroStartSignal(0);
|
||
}
|
||
else
|
||
{
|
||
m_ctrlFocusMotor->MoveToLogicZero();
|
||
}
|
||
}
|
||
|
||
void focusWindow::onMove2MotorMax()
|
||
{
|
||
if (ui.is_new_version_radioButton->isChecked())
|
||
{
|
||
emit move2MaxLocSignal(0, m_dSpeed, 1000);
|
||
}
|
||
else
|
||
{
|
||
m_ctrlFocusMotor->MoveToPos(m_iMaxPos);
|
||
}
|
||
}
|
||
|
||
void focusWindow::onAdd()
|
||
{
|
||
double rdistance = ui.addStepSize_lineEdit->text().toDouble();
|
||
|
||
if (ui.is_new_version_radioButton->isChecked())
|
||
{
|
||
emit rmoveSignal(0, (double)abs(rdistance), m_dSpeed, 1000);
|
||
}
|
||
else
|
||
{
|
||
DriverInfo di;
|
||
m_ctrlFocusMotor->GetDriverStatus(di);
|
||
|
||
m_ctrlFocusMotor->MoveToPos(di.iAbsPosition + rdistance);
|
||
}
|
||
}
|
||
|
||
void focusWindow::onSubtract()
|
||
{
|
||
double rdistance = ui.subtractStepSize_lineEdit->text().toDouble();
|
||
|
||
if (ui.is_new_version_radioButton->isChecked())
|
||
{
|
||
emit rmoveSignal(0, (double)abs(rdistance) * -1, m_dSpeed, 1000);
|
||
}
|
||
else
|
||
{
|
||
DriverInfo di;
|
||
m_ctrlFocusMotor->GetDriverStatus(di);
|
||
|
||
m_ctrlFocusMotor->MoveToPos(di.iAbsPosition - rdistance);
|
||
}
|
||
}
|
||
|
||
void focusWindow::onAutoFocus()
|
||
{
|
||
if (ui.is_new_version_radioButton->isChecked())
|
||
{
|
||
//先按照一定间隔从负极限到正极限获取一系列(位置,调焦指数)
|
||
m_iStepSize = ui.sample_ratio_lineEdit->text().toInt();
|
||
ui.autoFocusProgress_progressBar->setMinimum(0);
|
||
ui.autoFocusProgress_progressBar->setMaximum(m_iStepSize);
|
||
ui.autoFocusProgress_progressBar->reset();
|
||
|
||
//获取马达最大位置
|
||
std::vector<double> maxRangeLocations = m_multiAxisController->getMaxPos();
|
||
double maxPos = maxRangeLocations[0];
|
||
emit startStepMotionSignal(m_dSpeed, m_iStepSize, 0, maxPos);
|
||
}
|
||
else
|
||
{
|
||
bool isUltrasound = ui.ultrasound_radioButton->isChecked();
|
||
WorkerThread2* thread1 = new WorkerThread2(m_ctrlFocusMotor, isUltrasound);
|
||
|
||
connect(thread1, SIGNAL(AutoFocusFinishedSignal()), this, SLOT(onAutoFocusFinished()));
|
||
|
||
thread1->start();
|
||
|
||
WorkerThread4* progressThread = new WorkerThread4(m_ctrlFocusMotor);
|
||
connect(progressThread, SIGNAL(AutoFocusProgressSignal(int)), this, SLOT(onAutoFocusProgress(int)));
|
||
progressThread->start();
|
||
ui.autoFocusProgress_progressBar->reset();
|
||
}
|
||
this->setDisabled(true);
|
||
}
|
||
|
||
void focusWindow::onManualFocus()
|
||
{
|
||
if (ui.is_new_version_radioButton->isChecked())
|
||
{
|
||
|
||
}
|
||
else
|
||
{
|
||
|
||
}
|
||
|
||
m_FocusState += 1;
|
||
std::cout << "点击调焦按钮!" << std::endl;
|
||
|
||
|
||
if (m_FocusState % 2 == 1)
|
||
{
|
||
//开始调焦
|
||
emit StartManualFocusSignal(1);
|
||
ui.manualFocus_btn->setText(QString::fromLocal8Bit("停止调焦"));
|
||
|
||
ui.manualFocus_btn->setStyleSheet("QWidget{background-color:rgb(255,0,0);}");
|
||
|
||
ui.autoFocus_btn->setDisabled(true);
|
||
|
||
//std::cout << "------------------------------------------:" << m_FocusState << std::endl;
|
||
}
|
||
else
|
||
{
|
||
emit StartManualFocusSignal(0);
|
||
m_Imager->setFocusControlState(false);
|
||
|
||
ui.manualFocus_btn->setText(QString::fromLocal8Bit("调焦"));
|
||
|
||
ui.manualFocus_btn->setStyleSheet("QWidget{background-color:rgb(0,255,0);}");
|
||
|
||
ui.autoFocus_btn->setDisabled(false);
|
||
}
|
||
}
|
||
|
||
void focusWindow::onUpdateCurrentLocation()
|
||
{
|
||
if (ui.is_new_version_radioButton->isChecked())
|
||
{
|
||
//因为新版的马达控制是实时反馈位置信息,所以不需要做任何事
|
||
}
|
||
else
|
||
{
|
||
DriverInfo di;
|
||
m_ctrlFocusMotor->GetDriverStatus(di);
|
||
ui.currentLocation_lineEdit->setText(QString::number(di.iAbsPosition));
|
||
}
|
||
}
|
||
|
||
void focusWindow::onMoveto()
|
||
{
|
||
double pos = ui.move2_lineEdit->text().toDouble();
|
||
|
||
if (ui.is_new_version_radioButton->isChecked())
|
||
{
|
||
emit move2LocSignal(0, (double)pos, m_dSpeed, 1000);
|
||
}
|
||
else
|
||
{
|
||
//需要做参数有效性验证,查看是否在有效范围内
|
||
|
||
m_ctrlFocusMotor->MoveToPos(pos);
|
||
}
|
||
}
|
||
|
||
void focusWindow::onAutoFocusFinished()
|
||
{
|
||
if (ui.is_new_version_radioButton->isChecked())
|
||
{
|
||
//通过高斯拟合获取最佳位置
|
||
QVector<PositionData> positionData = m_coordinator->getAllPositionData();
|
||
|
||
std::vector<double> actualPositions;
|
||
std::vector<double> cameraIndices;
|
||
|
||
actualPositions.reserve(positionData.size());
|
||
cameraIndices.reserve(positionData.size());
|
||
|
||
int scaleFactor = 100;
|
||
for (const auto& data : positionData)
|
||
{
|
||
actualPositions.push_back(data.actualPosition * scaleFactor);
|
||
cameraIndices.push_back(data.cameraIndex);
|
||
}
|
||
double a_init, mu_init, sigma_init, c_init;
|
||
getGaussianInitParam(actualPositions, cameraIndices, a_init, mu_init, sigma_init, c_init);
|
||
|
||
double a = a_init, mu = mu_init, sigma = sigma_init, c = c_init;
|
||
gaussian_fit(actualPositions, cameraIndices, a, mu, sigma, c);
|
||
|
||
mu_init = mu_init / scaleFactor;
|
||
mu = mu / scaleFactor;
|
||
|
||
std::cout << "mu 初值:" << mu_init << std::endl << "mu 拟合值:" << mu << std::endl;
|
||
|
||
//对拟合值进行判断,排除错误拟合情况(地物没有纹理)
|
||
std::vector<double> maxRangeLocations = m_multiAxisController->getMaxPos();
|
||
double maxPos = maxRangeLocations[0];
|
||
if (mu < 0 || mu > maxPos)
|
||
{
|
||
std::cout << "拟合失败!!!!!" << std::endl;
|
||
m_goodPos = mu_init;
|
||
m_isAutoFocusSuccess = false;
|
||
}
|
||
else
|
||
{
|
||
std::cout << "拟合成功!!!!!" << std::endl;
|
||
m_goodPos = mu;
|
||
m_isAutoFocusSuccess = true;
|
||
}
|
||
|
||
FileOperation* fileOperation = new FileOperation();
|
||
string directory = fileOperation->getDirectoryOfExe();
|
||
QDateTime now = QDateTime::currentDateTime();
|
||
QString format1 = "yyyyMMdd_HHmmss";
|
||
QString fileName = now.toString("yyyyMMdd_HHmmss");
|
||
|
||
QString fitDataFile = QDir::cleanPath(QString::fromStdString(directory) + QDir::separator() + fileName + "_" + QString::number(m_iStepSize) + "interval_" + QString::number(mu) + ".csv");
|
||
m_coordinator->saveToCsv(fitDataFile);
|
||
|
||
//由于马达移动准确性较低,自动调焦完成后,直接移动到m_goodPos效果不好,所以先移动到tmpPos,然后移动到m_goodPos
|
||
double tmpPos = m_goodPos - positionData[positionData.size() - 1].actualPosition / 10;
|
||
m_isMoveAfterAutoFocus = true;
|
||
emit move2LocSignal(0, (double)tmpPos, m_dSpeed, 1000);
|
||
}
|
||
else
|
||
{
|
||
onUpdateCurrentLocation();
|
||
}
|
||
|
||
this->setDisabled(false);
|
||
}
|
||
|
||
void focusWindow::moveAfterAutoFocus(int motorID, double location)
|
||
{
|
||
//QObject* obj = sender();
|
||
|
||
//if (obj == m_multiAxisController)
|
||
//{
|
||
// qDebug() << "sender is m_multiAxisController.";
|
||
//}
|
||
|
||
if (!m_isMoveAfterAutoFocus)
|
||
{
|
||
//std::cout << "focusWindow::moveAfterAutoFocus" << std::endl;
|
||
return;
|
||
}
|
||
|
||
std::cout << "\n已经到达位置:" << location << std::endl;
|
||
|
||
double errorRate = getErrorRate(m_goodPos, location);
|
||
if (errorRate < 5|| m_moveRetryCount > MAX_MOVE_RETRY)
|
||
{
|
||
m_isMoveAfterAutoFocus = false;
|
||
m_moveRetryCount = 0;
|
||
if (!m_isAutoFocusSuccess)
|
||
{
|
||
qDebug() << "纹理较弱,自动调焦效果不佳!请使用调焦纸进行自动调焦!";
|
||
//showMessageBox(QString::fromLocal8Bit("纹理较弱,自动调焦效果不佳!请使用调焦纸进行自动调焦!"));
|
||
}
|
||
else
|
||
{
|
||
qDebug() << "自动调焦成功!";
|
||
//showMessageBox(QString::fromLocal8Bit("自动调焦成功!"));
|
||
}
|
||
emit AutoFocusFinishedSignal(0);
|
||
}
|
||
else
|
||
{
|
||
m_moveRetryCount++;
|
||
qDebug() << "自动调焦后目标马达位置,重试次数:" << m_moveRetryCount;
|
||
//移动马达到最佳位置
|
||
emit move2LocSignal(0, (double)m_goodPos, m_dSpeed, 1000);
|
||
}
|
||
}
|
||
|
||
double focusWindow::getErrorRate(double targetLoc, double actualLoc)
|
||
{
|
||
double targetLocTmp;
|
||
if (targetLoc == 0)
|
||
{
|
||
targetLocTmp = 0.001;
|
||
}
|
||
else
|
||
{
|
||
targetLocTmp = targetLoc;
|
||
}
|
||
double errorRate = abs(targetLoc - actualLoc) / targetLocTmp * 100;
|
||
|
||
return errorRate;
|
||
}
|
||
|
||
void focusWindow::getGaussianInitParam(const std::vector<double>& pos, const std::vector<double>& index, double& a_init, double& mu_init, double& sigma_init, double& c_init)
|
||
{
|
||
auto minmax_element = std::minmax_element(index.begin(), index.end());
|
||
a_init = *minmax_element.second - *minmax_element.first;
|
||
mu_init = pos[std::distance(index.begin(), minmax_element.second)];
|
||
c_init = *minmax_element.first;
|
||
|
||
//sigma_init
|
||
double half_max = (*minmax_element.second + *minmax_element.first) / 2.0;
|
||
size_t peak_idx = std::distance(index.begin(), minmax_element.second);
|
||
size_t left_idx = peak_idx;// 找左半高点
|
||
while (left_idx > 0 && index[left_idx] > half_max) left_idx--;
|
||
size_t right_idx = peak_idx;// 找右半高点
|
||
while (right_idx < index.size() - 1 && index[right_idx] > half_max) right_idx++;
|
||
double fwhm = pos[right_idx] - pos[left_idx];
|
||
sigma_init = fwhm / 2.3548;
|
||
}
|
||
|
||
// 使用 Gauss-Newton 进行高斯拟合
|
||
void focusWindow::gaussian_fit(const std::vector<double>& x_data,
|
||
const std::vector<double>& y_data,
|
||
double& a, double& mu, double& sigma, double& c)
|
||
{
|
||
const int max_iter = 100;
|
||
for (int iter = 0; iter < max_iter; iter++)
|
||
{
|
||
Eigen::MatrixXd J(x_data.size(), 4);
|
||
Eigen::VectorXd r(x_data.size());
|
||
|
||
for (size_t i = 0; i < x_data.size(); i++)
|
||
{
|
||
double xi = x_data[i];
|
||
double yi = y_data[i];
|
||
double exp_part = std::exp(-(xi - mu) * (xi - mu) / (2 * sigma * sigma));
|
||
double fi = a * exp_part + c;
|
||
|
||
r(i) = yi - fi;
|
||
|
||
// 雅可比
|
||
J(i, 0) = -exp_part; // ∂f/∂a
|
||
J(i, 1) = -a * exp_part * ((xi - mu) / (sigma * sigma)); // ∂f/∂mu
|
||
J(i, 2) = -a * exp_part * ((xi - mu) * (xi - mu) / (sigma * sigma * sigma)); // ∂f/∂sigma
|
||
J(i, 3) = -1.0; // ∂f/∂c
|
||
}
|
||
|
||
Eigen::VectorXd delta = (J.transpose() * J).ldlt().solve(-J.transpose() * r);
|
||
|
||
a += delta(0);
|
||
mu += delta(1);
|
||
sigma += delta(2);
|
||
c += delta(3);
|
||
|
||
if (delta.norm() < 1e-8) break;
|
||
}
|
||
}
|
||
|
||
void focusWindow::onAutoFocusProgress(int progress)
|
||
{
|
||
//std::cout << "进度:" << progress << std::endl;
|
||
|
||
ui.autoFocusProgress_progressBar->setValue(progress);
|
||
}
|
||
|
||
void focusWindow::onUltrasound_radioButton()
|
||
{
|
||
bool isUltrasound = ui.ultrasound_radioButton->isChecked();
|
||
|
||
if (isUltrasound)
|
||
{
|
||
ui.ultrasoundPort_comboBox->setEnabled(true);
|
||
}
|
||
else
|
||
{
|
||
ui.ultrasoundPort_comboBox->setEnabled(false);
|
||
}
|
||
}
|
||
|
||
WorkerThread2::WorkerThread2(CFocusMotorControl * ctrlFocusMotor, bool isUltrasound)
|
||
{
|
||
m_ctrlFocusMotor = ctrlFocusMotor;
|
||
m_bIsUltrasound = isUltrasound;
|
||
}
|
||
|
||
void WorkerThread2::run()
|
||
{
|
||
//配置文件
|
||
string HPPACfgFile = getPathofEXE() + "\\HPPA.cfg";
|
||
Configfile configfile;
|
||
configfile.setConfigfilePath(HPPACfgFile);
|
||
if (!configfile.isConfigfileExist())
|
||
configfile.createConfigFile();
|
||
configfile.parseConfigfile();
|
||
|
||
int coarse, fine;
|
||
configfile.getTuningStepSize(coarse, fine);
|
||
float fa, fb;
|
||
configfile.getFitParams(fa, fb);
|
||
int max_FocusRange, min_FocusRange;
|
||
configfile.getAutoFocusRange(max_FocusRange, min_FocusRange);
|
||
|
||
if (m_bIsUltrasound)
|
||
{
|
||
m_ctrlFocusMotor->SetFitParams(fa, fb);
|
||
m_ctrlFocusMotor->StartAutoFocus(5, 2);
|
||
}
|
||
else
|
||
{
|
||
m_ctrlFocusMotor->StartAutoFocus(min_FocusRange, max_FocusRange, coarse, fine);
|
||
}
|
||
|
||
emit AutoFocusFinishedSignal();
|
||
}
|
||
|
||
WorkerThread4::WorkerThread4(CFocusMotorControl * ctrlFocusMotor)
|
||
{
|
||
m_ctrlFocusMotor = ctrlFocusMotor;
|
||
}
|
||
|
||
void WorkerThread4::run()
|
||
{
|
||
while (true)
|
||
{
|
||
int progress = m_ctrlFocusMotor->GetProgressIndex();
|
||
|
||
//std::cout << "WorkerThread4::run----自动调焦进度:" << progress << std::endl;
|
||
|
||
emit AutoFocusProgressSignal(progress);
|
||
if (progress == 100)
|
||
{
|
||
//std::cout << "自动调焦完成!" << std::endl;
|
||
break;
|
||
}
|
||
|
||
msleep(200);
|
||
}
|
||
}
|
||
|
||
|
||
//-------------------------------------------------------------------------------------------------------------------------------------------------------------
|
||
|
||
MotionCaptureCoordinator::MotionCaptureCoordinator(
|
||
IrisMultiMotorController* motorCtrl,
|
||
ImagerOperationBase* cameraCtrl,
|
||
QObject* parent)
|
||
: QObject(parent)
|
||
, m_motorCtrl(motorCtrl)
|
||
, m_cameraCtrl(cameraCtrl)
|
||
, m_currentPos(0)
|
||
, m_endPos(0)
|
||
, m_isRunning(false)
|
||
, m_isZeroing(false)
|
||
{
|
||
//这些信号槽是按照逻辑顺序的
|
||
connect(this, SIGNAL(moveTo(int, double, double, int)),
|
||
m_motorCtrl, SLOT(moveTo(int, double, double, int)));
|
||
|
||
connect(this, &MotionCaptureCoordinator::zeroStart,
|
||
m_motorCtrl, &IrisMultiMotorController::zeroStart);
|
||
|
||
connect(m_motorCtrl, &IrisMultiMotorController::motorStopSignal,
|
||
this, &MotionCaptureCoordinator::handlePositionReached);
|
||
//connect(m_motorCtrl, &IrisMultiMotorController::moveFailed,
|
||
// this, &MotionCaptureCoordinator::handleError);
|
||
|
||
connect(this, SIGNAL(getFocusIndexSobel()),
|
||
m_cameraCtrl, SLOT(getFocusIndexSobel()));
|
||
|
||
connect(m_cameraCtrl, &ImagerOperationBase::FocusIndexSobelSignal,
|
||
this, &MotionCaptureCoordinator::handleCaptureComplete);
|
||
//connect(m_cameraCtrl, &ImagerOperationBase::captureFailed,
|
||
// this, &MotionCaptureCoordinator::handleError);
|
||
}
|
||
|
||
MotionCaptureCoordinator::~MotionCaptureCoordinator()
|
||
{
|
||
|
||
}
|
||
|
||
void MotionCaptureCoordinator::startStepMotion(double speed, int stepInterval, double startPos, double endPos)
|
||
{
|
||
QMutexLocker locker(&m_dataMutex);
|
||
|
||
if (m_isRunning)
|
||
{
|
||
emit errorOccurred("Sequence already running");
|
||
return;
|
||
}
|
||
|
||
m_counter = 0;
|
||
|
||
m_positionData.clear();
|
||
|
||
m_speed = speed;
|
||
m_iStepInterval = stepInterval;
|
||
m_iStepIntervalRealTime = 1;
|
||
m_startPos = startPos;
|
||
m_endPos = endPos;
|
||
m_posInternal = (endPos - startPos) / stepInterval;
|
||
|
||
m_isRunning = true;
|
||
m_isZeroing = true;
|
||
|
||
// 先执行归零操作
|
||
emit zeroStart(0);
|
||
qDebug() << "MotionCaptureCoordinator::startStepMotion: Zeroing started.";
|
||
}
|
||
|
||
void MotionCaptureCoordinator::startMotionSequence()
|
||
{
|
||
QMutexLocker locker(&m_dataMutex);
|
||
|
||
m_currentPos = m_startPos;
|
||
m_isZeroing = false;
|
||
qDebug() << "MotionCaptureCoordinator::startMotionSequence: Zeroing complete. Starting motion sequence.";
|
||
|
||
processNextPosition();
|
||
}
|
||
|
||
void MotionCaptureCoordinator::handleZeroComplete(int motorID, double pos)
|
||
{
|
||
if (!m_isRunning || !m_isZeroing) return;
|
||
|
||
// 归零完成,开始分步运动
|
||
startMotionSequence();
|
||
}
|
||
|
||
void MotionCaptureCoordinator::stopStepMotion()
|
||
{
|
||
QMutexLocker locker(&m_dataMutex);
|
||
m_isRunning = false;
|
||
emit sequenceStopped();
|
||
}
|
||
|
||
QVector<PositionData> MotionCaptureCoordinator::getAllPositionData() const
|
||
{
|
||
//QMutexLocker locker(&m_dataMutex);
|
||
return m_positionData;
|
||
}
|
||
|
||
bool MotionCaptureCoordinator::saveToCsv(const QString& filename)
|
||
{
|
||
//QMutexLocker locker(&m_dataMutex);
|
||
|
||
QFile file(filename);
|
||
if (!file.open(QIODevice::WriteOnly | QIODevice::Text))
|
||
{
|
||
return false;
|
||
}
|
||
|
||
QTextStream out(&file);
|
||
out << "Timestamp,targetPosition,ActualPosition,FocusIndex\n";
|
||
|
||
for (const auto& data : m_positionData)
|
||
{
|
||
out << data.timestamp.toString("yyyy-MM-dd HH:mm:ss.zzz") << ","
|
||
<< QString::number(data.targetPosition, 'f', 4) << ","
|
||
<< QString::number(data.actualPosition, 'f', 4) << ","
|
||
<< QString::number(data.cameraIndex, 'f', 4) << "\n";
|
||
}
|
||
|
||
file.close();
|
||
return true;
|
||
}
|
||
|
||
void MotionCaptureCoordinator::handlePositionReached(int motorID, double pos)
|
||
{
|
||
if (!m_isRunning) return;
|
||
|
||
// 如果正在等待归零完成,调用归零完成处理
|
||
if (m_isZeroing)
|
||
{
|
||
handleZeroComplete(motorID, pos);
|
||
return;
|
||
}
|
||
|
||
QMutexLocker locker(&m_dataMutex);
|
||
|
||
//验证马达运动位置是否到达指定位置
|
||
//if (pos != m_currentPos) return;
|
||
|
||
// 记录位置信息
|
||
PositionData data;
|
||
data.targetPosition = m_currentPos;
|
||
data.actualPosition = pos;
|
||
data.timestamp = QDateTime::currentDateTime();
|
||
m_positionData.append(data);
|
||
|
||
// 开始采集
|
||
emit getFocusIndexSobel();
|
||
}
|
||
|
||
void MotionCaptureCoordinator::handleCaptureComplete(double index)
|
||
{
|
||
if (!m_isRunning) return;
|
||
|
||
QMutexLocker locker(&m_dataMutex);
|
||
|
||
// 更新最近一条记录的相机指数
|
||
//if (!m_positionData.isEmpty() &&
|
||
// m_positionData.last().targetPosition == m_positionData.last().actualPosition)
|
||
//{
|
||
// m_positionData.last().cameraIndex = index;
|
||
//}
|
||
m_positionData.last().cameraIndex = index;
|
||
|
||
m_currentPos += m_posInternal;
|
||
m_iStepIntervalRealTime++;
|
||
emit progressChanged(m_iStepIntervalRealTime);
|
||
|
||
m_counter += 1;
|
||
|
||
std::cout << "第" << m_counter << "次采集:" << std::endl;
|
||
std::cout << "目标位置:" << m_positionData.last().targetPosition << std::endl;
|
||
std::cout << "实际位置:" << m_positionData.last().actualPosition << std::endl;
|
||
|
||
processNextPosition();
|
||
}
|
||
|
||
void MotionCaptureCoordinator::handleError(const QString& error)
|
||
{
|
||
QMutexLocker locker(&m_dataMutex);
|
||
m_isRunning = false;
|
||
emit errorOccurred(error);
|
||
}
|
||
|
||
void MotionCaptureCoordinator::processNextPosition()
|
||
{
|
||
if (!m_isRunning) return;
|
||
|
||
if (m_currentPos > m_endPos)
|
||
{
|
||
m_isRunning = false;
|
||
emit sequenceComplete();
|
||
|
||
return;
|
||
}
|
||
|
||
emit moveTo(0, m_currentPos, m_speed, 1000);
|
||
}
|