修改棒材的协议
This commit is contained in:
parent
467dc2d6cb
commit
b5ef4a0a5d
@ -17,7 +17,7 @@
|
||||
|
||||
| 地址 | 寄存器数 | 类型 | 读/写 | 说明 |
|
||||
|------|----------|------|-------|------|
|
||||
| 0 | 1 | uint16 | R/W | 检测触发(写入非零值触发,1=相机1,2=相机2,触发后自动清零) |
|
||||
| 0 | 1 | uint16 | R/W | 控制命令(写入后自动清零,命令见下表) |
|
||||
| 1 | 1 | uint16 | R | 状态码 |
|
||||
| 2 | 2 | float | R | X(中心点 X 坐标,mm) |
|
||||
| 4 | 2 | float | R | Y(中心点 Y 坐标,mm) |
|
||||
@ -30,14 +30,22 @@
|
||||
|
||||
> **坐标系**:XYZ 为机械臂坐标系下的值(已经过手眼标定转换),RPY 为 ZYX 外旋欧拉角
|
||||
|
||||
## 3.1 控制命令(地址 0)
|
||||
|
||||
| 命令值 | 说明 |
|
||||
|--------|------|
|
||||
| 1 | 触发相机1执行检测 |
|
||||
| 2 | 触发相机2执行检测 |
|
||||
| 10 | 读取下一个缓存棒材结果(从上次检测结果中依次获取) |
|
||||
|
||||
## 4. 状态码定义
|
||||
|
||||
| 状态码 | 说明 |
|
||||
|--------|------|
|
||||
| 0 | 正在检测 |
|
||||
| 1 | 检测成功(地址 2~13 数据有效) |
|
||||
| 1 | 成功(地址 2~13 数据有效) |
|
||||
| 2 | 检测失败 |
|
||||
| 3 | 检测成功但结果为空 |
|
||||
| 3 | 结果为空 / 无更多缓存结果 |
|
||||
|
||||
## 5. 通信流程
|
||||
|
||||
@ -46,6 +54,7 @@
|
||||
1. 外部客户端写入地址 0,值为相机编号(1 或 2)
|
||||
2. 视觉系统自动清零地址 0,并将地址 1 设为 0(正在检测)
|
||||
3. 视觉系统触发对应相机的检测
|
||||
4. 检测完成后自动输出第一个棒材结果(地址 1=1,地址 2~13=坐标)
|
||||
|
||||
### 5.2 读取结果
|
||||
|
||||
@ -55,27 +64,55 @@
|
||||
2. 外部客户端轮询地址 1,当值从 0 变为非零时表示检测完成
|
||||
3. 状态码为 1 时,读取地址 2~13 获取定位结果
|
||||
|
||||
### 5.3 典型时序
|
||||
### 5.3 典型时序(单棒材)
|
||||
|
||||
```
|
||||
客户端 视觉系统
|
||||
| |
|
||||
|--- 写入 地址0 = 1 (触发相机1) ----->|
|
||||
|--- 写入 地址0 = 1 (触发相机1) ------>|
|
||||
| |-- 清零地址0,地址1=0(正在检测)
|
||||
| |-- 执行检测...
|
||||
| |
|
||||
|<-- 读取 地址1 = 0 (正在检测) -------|
|
||||
|<-- 读取 地址1 = 0 (正在检测) --------|
|
||||
| |
|
||||
|<-- 读取 地址1 = 1 (检测成功) -------|
|
||||
| |-- 写入地址1=1, 地址2~13=结果
|
||||
|<-- 读取 地址2~13 (XYZ+RPY) --------|
|
||||
|<-- 读取 地址1 = 1 (检测成功) --------|
|
||||
| |-- 写入地址1=1, 地址2~13=第1个棒材结果
|
||||
|<-- 读取 地址2~13 (XYZ+RPY) ---------|
|
||||
| |
|
||||
```
|
||||
|
||||
### 5.4 读取多棒材结果时序
|
||||
|
||||
当检测到多个棒材时,可通过写命令 10 依次获取后续结果:
|
||||
|
||||
```
|
||||
客户端 视觉系统
|
||||
| |
|
||||
|--- 写入 地址0 = 1 (触发相机1) ------>|
|
||||
| |-- 清零地址0,地址1=0(正在检测)
|
||||
| |-- 执行检测(发现N个棒材)...
|
||||
| |
|
||||
|<-- 读取 地址1 = 1 (成功) -----------|
|
||||
| |-- 自动输出第1个棒材结果
|
||||
|<-- 读取 地址2~13 (棒材1坐标) --------|
|
||||
| |
|
||||
|--- 写入 地址0 = 10 (读取下一个) ---->|
|
||||
| |-- 输出第2个棒材结果
|
||||
|<-- 读取 地址1 = 1 (成功) -----------|
|
||||
|<-- 读取 地址2~13 (棒材2坐标) --------|
|
||||
| |
|
||||
|--- 写入 地址0 = 10 (继续读取) ------>|
|
||||
| |-- 无更多结果
|
||||
|<-- 读取 地址1 = 3 (无更多结果) ------|
|
||||
| |
|
||||
```
|
||||
|
||||
> **注意**:触发新的检测(写1或写2)后,缓存索引自动归零,写10将重新从第2个棒材开始读取。
|
||||
|
||||
## 6. 注意事项
|
||||
|
||||
1. 触发寄存器写入后会自动清零,无需客户端手动清零
|
||||
2. 仅输出第一个检测到的棒材结果
|
||||
2. 检测完成后自动输出第一个棒材结果;写命令 10 可依次获取第2、3...个结果
|
||||
3. 坐标数据为机械臂坐标系下的值(已经过手眼标定转换)
|
||||
4. 欧拉角为 ZYX 外旋顺序(从轴向方向和法向方向构建旋转矩阵提取)
|
||||
5. 浮点数字节序(大端/小端)由网络配置中的 byteOrder 参数决定
|
||||
|
||||
@ -158,8 +158,11 @@ private:
|
||||
// 根据相机索引获取调平参数
|
||||
SSG_planeCalibPara _GetCameraCalibParam(int cameraIndex);
|
||||
|
||||
// 发送检测结果到Modbus寄存器
|
||||
void _SendDetectionResultToModbus(const DetectionResult& result, int cameraIndex);
|
||||
// 发送检测结果到Modbus寄存器(index指定发送第几个棒材结果)
|
||||
void _SendDetectionResultToModbus(const DetectionResult& result, int cameraIndex, int index = 0);
|
||||
|
||||
// 发送缓存中的下一个棒材结果
|
||||
void _SendNextCachedResult();
|
||||
|
||||
private:
|
||||
// RodAndBarPositionPresenter 特有的成员变量
|
||||
@ -170,6 +173,11 @@ private:
|
||||
|
||||
// 手眼标定矩阵列表(从独立文件加载,暂时保留在Presenter中)
|
||||
std::vector<CalibMatrix> m_clibMatrixList;
|
||||
|
||||
// 多棒材结果缓存(支持写10逐个读取)
|
||||
DetectionResult m_lastDetectionResult;
|
||||
int m_resultIndex = 0;
|
||||
std::mutex m_resultCacheMutex;
|
||||
};
|
||||
|
||||
#endif // RODANDBARPOSITIONPRESENTER_H
|
||||
|
||||
@ -232,8 +232,14 @@ int RodAndBarPositionPresenter::ProcessAlgoDetection(std::vector<std::pair<EVzRe
|
||||
QString statusMsg = QString("检测完成,发现%1个棒材").arg(detectionResult.positions.size());
|
||||
if (auto pStatus = GetStatusCallback<IYRodAndBarPositionStatus>()) pStatus->OnStatusUpdate(statusMsg.toStdString());
|
||||
|
||||
// 发送检测结果到Modbus寄存器
|
||||
_SendDetectionResultToModbus(detectionResult, m_currentCameraIndex);
|
||||
// 缓存检测结果,重置索引(首次发送index=0,下次写10从1开始)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_resultCacheMutex);
|
||||
m_lastDetectionResult = detectionResult;
|
||||
m_resultIndex = 1;
|
||||
}
|
||||
// 发送第0个结果
|
||||
_SendDetectionResultToModbus(detectionResult, m_currentCameraIndex, 0);
|
||||
|
||||
// 9. 检测完成后,将工作状态更新为"完成"
|
||||
SetWorkStatus(WorkStatus::Completed);
|
||||
@ -616,21 +622,30 @@ void RodAndBarPositionPresenter::SetAlgoParams(const AlgoParams& params)
|
||||
|
||||
void RodAndBarPositionPresenter::OnModbusWriteCallback(uint16_t startAddress, const uint16_t* data, uint16_t count)
|
||||
{
|
||||
// 检测触发寄存器 (地址 0):写入非零值触发检测
|
||||
// 检测触发寄存器 (地址 0):写入非零值触发检测或读取缓存结果
|
||||
if (startAddress == 0 && count >= 1 && data[0] != 0) {
|
||||
int cameraIndex = data[0]; // 1=相机1, 2=相机2
|
||||
LOG_INFO("Modbus trigger detection: cameraIndex=%d\n", cameraIndex);
|
||||
int cmd = data[0]; // 1=触发相机1, 2=触发相机2, 10=读取下一个缓存结果
|
||||
LOG_INFO("Modbus command received: cmd=%d\n", cmd);
|
||||
|
||||
// 清除触发寄存器
|
||||
uint16_t clearValue = 0;
|
||||
WriteModbusRegisters(0, &clearValue, 1);
|
||||
|
||||
// 设置状态为"正在检测"
|
||||
uint16_t detecting = 0;
|
||||
WriteModbusRegisters(1, &detecting, 1);
|
||||
|
||||
// 触发检测
|
||||
TriggerDetection(cameraIndex);
|
||||
if (cmd == 10) {
|
||||
// 读取缓存中的下一个棒材结果
|
||||
_SendNextCachedResult();
|
||||
} else {
|
||||
// 新检测触发,索引归零
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_resultCacheMutex);
|
||||
m_resultIndex = 0;
|
||||
}
|
||||
// 设置状态为"正在检测"
|
||||
uint16_t detecting = 0;
|
||||
WriteModbusRegisters(1, &detecting, 1);
|
||||
// 触发对应相机检测
|
||||
TriggerDetection(cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -643,7 +658,7 @@ void RodAndBarPositionPresenter::OnModbusServerStatusChanged(bool isConnected)
|
||||
}
|
||||
}
|
||||
|
||||
void RodAndBarPositionPresenter::_SendDetectionResultToModbus(const DetectionResult& result, int cameraIndex)
|
||||
void RodAndBarPositionPresenter::_SendDetectionResultToModbus(const DetectionResult& result, int cameraIndex, int index)
|
||||
{
|
||||
if (!IsModbusServerRunning()) {
|
||||
LOG_WARNING("Modbus server not running, skip sending result\n");
|
||||
@ -654,18 +669,18 @@ void RodAndBarPositionPresenter::_SendDetectionResultToModbus(const DetectionRes
|
||||
ConfigResult configResult = m_pConfigManager->GetConfigResult();
|
||||
bool bigEndian = (configResult.byteOrder == 0); // 0=大端序, 1=小端序
|
||||
|
||||
// 地址 1:状态码(0=正在检测,1=成功,2=失败,3=结果为空)
|
||||
// 地址 1:状态码(0=正在检测,1=成功,2=失败,3=结果为空/无更多结果)
|
||||
uint16_t statusCode = 1; // 默认成功
|
||||
if (!result.success) {
|
||||
statusCode = 2; // 检测失败
|
||||
} else if (result.positions.empty()) {
|
||||
statusCode = 3; // 成功但结果为空
|
||||
} else if (result.positions.empty() || index >= (int)result.positions.size()) {
|
||||
statusCode = 3; // 成功但结果为空或索引越界
|
||||
}
|
||||
WriteModbusRegisters(1, &statusCode, 1);
|
||||
|
||||
// 地址 2~13:第一个棒材的 XYZ + RPY(6 个 float = 12 个寄存器)
|
||||
if (!result.positions.empty()) {
|
||||
const auto& pos = result.positions[0];
|
||||
// 地址 2~13:指定索引棒材的 XYZ + RPY(6 个 float = 12 个寄存器)
|
||||
if (statusCode == 1) {
|
||||
const auto& pos = result.positions[index];
|
||||
float values[6] = {
|
||||
(float)pos.x, (float)pos.y, (float)pos.z,
|
||||
(float)pos.roll, (float)pos.pitch, (float)pos.yaw
|
||||
@ -683,6 +698,32 @@ void RodAndBarPositionPresenter::_SendDetectionResultToModbus(const DetectionRes
|
||||
WriteModbusRegisters(2, regs, 12);
|
||||
}
|
||||
|
||||
LOG_INFO("Detection result sent via Modbus, camera: %d, status: %d\n",
|
||||
cameraIndex, statusCode);
|
||||
LOG_INFO("Detection result sent via Modbus, camera: %d, index: %d, status: %d\n",
|
||||
cameraIndex, index, statusCode);
|
||||
}
|
||||
|
||||
void RodAndBarPositionPresenter::_SendNextCachedResult()
|
||||
{
|
||||
if (!IsModbusServerRunning()) {
|
||||
LOG_WARNING("Modbus server not running, skip sending cached result\n");
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(m_resultCacheMutex);
|
||||
if (m_lastDetectionResult.positions.empty() ||
|
||||
m_resultIndex >= (int)m_lastDetectionResult.positions.size()) {
|
||||
// 无更多结果,写状态码3
|
||||
uint16_t statusCode = 3;
|
||||
WriteModbusRegisters(1, &statusCode, 1);
|
||||
LOG_INFO("No more cached results, index=%d, total=%zu\n",
|
||||
m_resultIndex, m_lastDetectionResult.positions.size());
|
||||
return;
|
||||
}
|
||||
|
||||
LOG_INFO("Sending cached result index=%d, total=%zu\n",
|
||||
m_resultIndex, m_lastDetectionResult.positions.size());
|
||||
_SendDetectionResultToModbus(m_lastDetectionResult,
|
||||
m_lastDetectionResult.cameraIndex,
|
||||
m_resultIndex);
|
||||
m_resultIndex++;
|
||||
}
|
||||
|
||||
@ -103,6 +103,7 @@ win32:CONFIG(debug, debug|release) {
|
||||
LIBS += -L../RodAndBarPositionConfig -lRodAndBarPositionConfig
|
||||
LIBS += -L../../../AppUtils/UICommon -lUICommon
|
||||
LIBS += -L../../../AppUtils/AppCommon -lAppCommon
|
||||
LIBS += -L../../../AppUtils/AppConfig -lAppConfig
|
||||
LIBS += -L../../../Module/AuthModule -lAuthModule
|
||||
LIBS += -L../../../Utils/CloudUtils -lCloudUtils
|
||||
LIBS += -L../../../Device/VrEyeDevice -lVrEyeDevice
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
// 应用名称
|
||||
#define RODANDBARPOSITION_APP_NAME "棒材定位"
|
||||
|
||||
#define RODANDBARPOSITION_VERSION_STRING "1.0.0"
|
||||
#define RODANDBARPOSITION_VERSION_STRING "1.0.1"
|
||||
#define RODANDBARPOSITION_BUILD_STRING "1"
|
||||
#define RODANDBARPOSITION_FULL_VERSION_STRING "V" RODANDBARPOSITION_VERSION_STRING "_" RODANDBARPOSITION_BUILD_STRING
|
||||
|
||||
|
||||
8
App/RodAndBarPosition/RodAndBarPositionApp/Version.md
Normal file
8
App/RodAndBarPosition/RodAndBarPositionApp/Version.md
Normal file
@ -0,0 +1,8 @@
|
||||
# 1.0.1 2026-03-27
|
||||
## build_1
|
||||
1. 修复协议,增加读取下一个目标的
|
||||
|
||||
# 1.0.0 2026-03-11
|
||||
## build_1
|
||||
1. 初始版本
|
||||
|
||||
@ -63,6 +63,12 @@ QT_LIB_PATH=/opt/sysroot/firefly-arm64-sysroot-20.04/lib/aarch64-linux-gnu
|
||||
cp -rfd ${QT_PKG_PATH}/ext ${PKG_PATH}/opt/firefly_qt5.15
|
||||
cp ${QT_PKG_PATH}/target_qtEnv.sh ${PKG_PATH}/etc/profile.d/
|
||||
|
||||
echo "清理不需要的 Qt WebEngine 库文件..."
|
||||
rm -f ${PKG_PATH}/opt/firefly_qt5.15/lib/libQt5WebEngine*
|
||||
rm -rf ${PKG_PATH}/opt/firefly_qt5.15/libexec/QtWebEngineProcess
|
||||
rm -rf ${PKG_PATH}/opt/firefly_qt5.15/resources/qtwebengine*
|
||||
rm -rf ${PKG_PATH}/opt/firefly_qt5.15/translations/qtwebengine*
|
||||
|
||||
# 复制 Qt 库文件
|
||||
for libfile in ${QT_LIB_PATH}/*.so*; do
|
||||
# 获取文件名用于比较
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user