Files
line-laser-hmi/docs/design.md
T
2026-06-22 14:39:30 +08:00

4.0 KiB
Raw Blame History

线激光 Modbus 上位机 GUI 设计

本程序是 line-laser-modbus 协议库的 Qt 上位机(HMI),用于操作与监控运动控制器。协议细节见库内 docs/proto.md

1. 技术选型

项目 选择 说明
GUI 框架 PySide6 Qt 官方绑定,LGPL,兼容 Python 3.12
实时曲线 pyqtgraph 高刷新率的科学绘图
协议层 line-laser-modbus 以路径依赖方式引用同仓库 py
串口枚举 pyserial list_ports 自动检测本机 COM 口

2. 线程模型

Modbus 客户端是阻塞式同步调用,绝不能在 GUI 线程执行,否则界面卡死。

  • ModbusWorker(QObject) 持有 LineLaserClient,被 moveToThread 移入独立 QThread
  • GUI 线程通过主窗口的请求信号(requestConnectrequestSwitchMode 等)以队列连接方式投递到 worker 槽。
  • worker 通过结果信号(connectedsnapshotReadyerrorOccurred 等)回传,GUI 线程刷新界面。
  • 轮询用 worker 线程内的 QTimer 周期触发 PollingRunner.run_once,避免无限循环阻塞线程。
GUI 线程  --请求信号(队列)-->  ModbusWorker(子线程)  --结果信号(队列)-->  GUI 线程
                                   |
                                   +-- LineLaserClient / PollingRunner / QTimer

3. 功能面板

面板 模块 对应协议库能力
连接 panels/connection_panel.py SerialConfig、模拟后端开关
模式控制 panels/mode_panel.py switch_mode(状态机校验)、急停 trigger_emergency_stop
状态监控 panels/status_panel.py read_statusread_available_cache_count、时间戳、超时计数
当前位姿 panels/pose_panel.py read_current_pose
轮询与录制 panels/polling_panel.py PollingRunner、CSV 录制
手动下发 panels/manual_panel.py read_available_cache_countwrite_target_posewrite_correction、跟踪目标
实时曲线 panels/chart_panel.py 6 轴位姿趋势
日志窗口 panels/log_panel.pyLogWindow 通信/错误记录、导出;由菜单「视图 → 日志窗口」(Ctrl+L) 打开

界面使用浅色 Fusion 主题(app.apply_light_theme),不跟随系统暗色。连接成功后会自动启动轮询,位姿数码显示与曲线立即刷新,无需手动点击。

4. 模拟模式

为满足无硬件演示,backend.py 提供 DynamicSimulatedBackend

  • 读取当前位姿时按正弦规律围绕基准位姿摆动,使数码显示与曲线动起来;
  • 写入模式命令时联动刷新设备状态字(如进入在线跟踪后状态变为 TRACKING_OK);
  • 默认提供 0xD002 可用缓存数量为 1,便于验证目标示教位姿下发。

勾选连接面板的「模拟模式」即可在没有串口和控制器的机器上完整体验所有功能。

5. 状态机与安全

  • 普通模式切换只包含 0~4,模式 0 在界面显示为「手动示教」。
  • 普通模式切换走 switch_mode,非法切换由协议库抛错并在日志提示。
  • 急停按钮走 force_mode(内部调用 trigger_emergency_stop,不做状态机校验),保证任意状态下可立即下发急停。
  • 手动下发按钮按当前模式启用:模式 2 允许目标示教位姿,模式 3/4 允许 6 轴纠偏量,模式 0/1 不允许下发控制指令。
  • worker 写入前会再次读取当前模式校验,避免按钮状态滞后或信号绕过。
  • 模式 2 下刷新 0xD002 可用缓存数量;目标示教位姿写入前再次读取,数量为 0 时界面提示并拒绝下发。
  • UI 固定使用协议轮询周期 50ms 和单帧超时 150ms;轮询连续失败达到阈值后自动断开连接。

6. 数据录制

recorder.pySnapshotRecorder 将每帧快照追加为 CSVwall_time, device_timestamp, mode, status, x..c,文件按时间戳命名保存在 record_dir