20 KiB
DroneScrewbolt 项目设计文档
1. 项目定位
DroneScrewbolt 采用远端服务端和地面端控制应用分离的结构。
- DroneScrewServer:部署在远端板卡,直接连接双目相机,负责采集、推流、算法检测和 ZMQ 协议服务。
- WDRemoteReceiver:地面端通信库,封装设备发现、控制命令、检测结果订阅和原始图像订阅。
- DroneScrewCtrlApp:地面端用户应用,负责连接远端服务、切换工作模式、展示图像和检测结果,并提供参数配置入口。
服务端是算法和设备控制中心,地面端不直接操作相机和算法,只通过 WDRemoteReceiver 调用服务端能力。
2. 工作模式
2.0 模式参数总表
| 模式 | 控制命令 | detectMode | 相机降采样 | 采集/处理帧率 | 图像输出 | 压缩参数 | 视频链路 | result 输出 | 地面端显示 | 测试入口 |
|---|---|---|---|---|---|---|---|---|---|---|
| 距离检测(RTMP/RTSP) | start_stream / stop_stream |
不使用 | 关闭 binning,使用 DecimationHorizontal/Vertical=4x4 相机端抽样下采样;4096x3000 输出 1024x750;曝光直接使用配置曝光 |
30fps |
单路实时视频,默认 1024x750 |
H.264,Rtsp.bitrateKbps 默认 4096Kbps,GOP 固定为 fps/2,约 0.5s |
DroneScrewServer 内部推 rtmp://127.0.0.1:1935/live/dronescrew,地面端拉 rtsp://<server-ip>:8554/live/dronescrew |
DetectDistance 持续发布 boxes/distances,协议距离单位为 mm |
DroneScrewCtrlApp 拉 RTSP,测距结果 overlay 和列表按 m 显示 | Test\WDRemoteReceiverTest 的 LiveStream |
| 精准检测(双图 raw) | set_detect_mode=binocular 后 start / stop |
binocular |
1x1/关闭 binning |
2fps |
左图 + 右图,全分辨率 raw | zlib 无损压缩,失败时 raw 兜底 | 关闭 RTSP/RTMP | Detect 精准检测结果持续发布 |
用于联调/测试双目 raw 链路;正式 DroneScrewCtrlApp 默认不进入该传输方式 | Test\WDRemoteReceiverTest 选择 binocular 后 Start |
| 精准检测(单图 raw) | set_detect_mode=mono 后 start / stop |
mono |
1x1/关闭 binning |
2fps |
左图,右图为空;4096x3000 输入压缩后约 1024x750 | 固定有损压缩:Mono8 先按 1/4 缩放,再 MJPEG quality=25;不动态算带宽、不跳帧 |
关闭 RTSP/RTMP | Detect 精准检测结果持续发布,result 坐标系固定为算法输入原图尺寸 |
DroneScrewCtrlApp 使用压缩后左图显示,raw/result 按 frameId 对齐后按原图坐标比例叠框,图像中只标框和序号,列表显示每个目标 | Test\WDRemoteReceiverTest 选择 mono 后 Start |
| 程序 | 定位 | 应覆盖的模式 |
|---|---|---|
Test\WDRemoteReceiverTest |
通信库和模式链路测试工具 | 距离检测、精准检测双图 raw、精准检测单图 raw |
DroneScrewCtrlApp |
正式地面端用户程序 | 距离检测(RTSP + result) 和精准检测单图 raw(MJPEG + result) |
2.1 距离检测模式
距离检测模式用于实时观察和距离检测。
服务端行为:
- 双目相机关闭 binning,固定使用
DecimationHorizontal/Vertical=4x4相机端抽样下采样采集。 Decimation是相机输出阶段的像素抽样降采样,不是压缩,也不是求平均/求和合并;它会改变相机输出分辨率,4096x3000 在 4x4 decimation 后输出 1024x750。- MVS SDK 自带
Features.xml中未提供BinningMode、Average、Sum这类 binning 合并模式选择;已确认的DecimationHorizontal/Vertical描述为 image sub-sampling,因此距离模式固定使用 decimation 来保持与精准检测相同的曝光语义。 - 距离检测和精准检测使用同一个配置曝光值;运行中通过
set_exposure修改曝光时也直接按当前配置曝光下发,不再按 binning 倍率做/16换算。 - 当前设计帧率为 30fps。
- 现场双目相机分别连接两个独立 USB 控制器;1024x750 Mono8 30fps 单路原始数据约 23MB/s(约 184Mbps),两路分摊到独立 USB2.0 控制器后按 30fps 设计。该约束不适用于两台相机共用同一个 USB2.0 root hub 的接法。
- 算法走 DetectDistance 距离检测 pipeline。
- 启动实时视频链路:服务端内部 RTMP 推到本机 mediamtx,地面端通过 RTSP 拉取配置指定的单路相机画面。
- 同时通过 ZMQ result 通道发布距离检测结果。
地面端行为:
- 通过 RTSP 拉流显示实时画面。
- 同时订阅 ZMQ result,接收距离检测结果。
- result 中的 boxes/distances 用于显示检测框和距离信息;协议内距离仍以 mm 保存,地面端距离检测 UI 按 m 显示。
- 该模式不依赖 ZMQ raw 图像通道显示画面。
设计要求:
- 距离检测模式必须同时具备 RTSP 拉流和 result 订阅。
- 地面端进入距离检测模式时不能停止 result 订阅。
- 服务端 start_stream 不能只被理解为“单纯推流”,它代表“decimation 距离检测 + 实时推流”。
2.2 精准螺栓检测模式
精准螺栓检测模式用于高分辨率螺栓检测。
服务端行为:
- 双目相机关闭 binning,使用原始分辨率采集。
- 当前设计帧率为 2fps。
- 算法走 Detect 精准检测 pipeline。
- 停止实时视频链路。
- 通过 ZMQ raw 图像通道发布图像。
- 通过 ZMQ result 通道发布检测框和距离结果。
地面端行为:
- 不拉 RTSP。
- 订阅 ZMQ raw 图像,用 raw 左目图作为显示画面。
- 订阅 ZMQ result,用检测结果叠加检测框并展示列表。正式地面端按最新帧刷新结果列表:精准检测显示每个目标,距离检测显示最新测距结果。
- raw 图像和 result 必须按 frameId 对齐后再叠加;单图 raw 显示图为压缩后尺寸,但 result 坐标系保持算法输入原图尺寸,由地面端按比例缩放绘制。
- 地面端绘制时必须把已经匹配的 raw/result 成对送入绘制队列,不能在绘制线程再读取“最新结果”;框坐标只按 result 的 imageWidth/imageHeight 到当前 QImage 像素尺寸缩放,QGraphicsView 的 fitInView 只负责最终显示缩放。
- 默认可使用 detectMode=mono,只传左目 raw 图以降低网络带宽;算法内部仍使用服务端双目输入。
设计要求:
- detectMode 只影响 raw 图像传输内容,不代表算法变为单目。
- 精准检测模式启动后应持续检测,不应只处理一帧或两帧后停止。
2.3 检测图像保存
服务端进入检测状态后,必须把进入算法的左右图像对异步保存到本地磁盘。保存线程独立于检测线程,检测线程只负责深拷贝图像并放入保存队列,PNG 编码和写盘由保存线程完成。
目录规则:
- 根目录固定为
/home/cat。 - 二级目录为启动当天日期,格式
yyyyMMdd。 - 三级目录为当前检测模式:距离检测为
distance,精准单图 raw 为precision_mono,精准双图 raw 为precision_binocular。 - 文件名按本轮检测序号从 1 开始递增:
leftImage_N.png、rightImage_N.png。
示例:
/home/cat/20260629/distance/leftImage_1.png/home/cat/20260629/distance/rightImage_1.png
保存失败或队列满时只记录日志,不允许阻塞检测线程或导致检测流程退出。
3. 通信通道
| 通道 | 默认端口 | 模式 | 用途 |
|---|---|---|---|
| UDP discovery | 5554 | 广播/应答 | 地面端搜索 DroneScrewServer |
| ZMQ control | 5555 | REQ/REP | start/stop/open/get_info/参数设置 |
| ZMQ result | 5556 | PUB/SUB | 检测结果 boxes/distances |
| ZMQ raw | 5557 | PUB/SUB | 精准检测模式下的 raw 图像 |
| RTMP publish | 1935 | FFmpeg/FLV | DroneScrewServer 推到本机 mediamtx 的内部入口 |
| RTSP pull | 8554 | RTSP/TCP | 地面端和 VLC 从 mediamtx 拉取距离检测实时画面 |
3.1 实时推流设计
实时推流只属于距离检测模式,也就是 start_stream 对应的 LiveStream 状态。它不是单独的视频功能,而是和 4x4 decimation 采集、DetectDistance 距离检测、result 发布一起启动。
服务端推流链路:
start_stream到达 DroneScrewServer。- 服务端停止精准检测相关状态,配置相机为距离检测模式:binning=1x1、decimation=4x4,默认 30fps。
- 服务端启动单路实时画面编码,输入为 Mono8,缩放到配置尺寸,转换为 NV12。
CVrFFMediaPusher使用 Rockchip MPP 编码 H.264,码率由Rtsp.bitrateKbps配置,默认 4096Kbps;GOP 按当前 fps 的一半设置,30fps 时约 0.5s,减少新客户端等待关键帧的时间。- 服务端内部推流地址固定为
rtmp://127.0.0.1:1935/live/dronescrew。 - mediamtx 接收 RTMP publish,并对外提供 RTSP 拉流。
- 对外拉流地址通过 discovery/get_info/start_stream 返回给地面端,格式为
rtsp://<板子IP>:8554/live/dronescrew。
端口边界:
1935是服务端内部 RTMP publish 端口,只给 DroneScrewServer 推到本机 mediamtx 使用。8554是客户端 RTSP pull 端口,DroneScrewCtrlApp、VLC、ffplay 都必须拉这个端口。- 配置文件
<Rtsp port="...">表示对外 RTSP pull 端口,不表示内部 RTMP publish 端口。 - 如果旧配置误写成
1935,服务端应警告并自动改用8554作为对外拉流端口。
mediamtx 职责:
- 监听
rtmpAddress: :1935,接收服务端内部 RTMP 推流。 - 监听
rtspAddress: :8554,给地面端提供 RTSP 拉流。 - 路径使用
/live/dronescrew,不需要为该路径预先创建固定配置,按 publisher 动态建立。
地面端拉流链路:
- DroneScrewCtrlApp 通过 WDRemoteReceiver 发送
start_stream。 - WDRemoteReceiver 启动 result 订阅,关闭 raw 订阅。
start_stream成功后,DroneScrewCtrlApp 读取服务端返回或 get_info 返回的rtsp字段。- 拉流地址以服务端返回为准;如果服务端未返回地址,则用配置中的
serverIp + rtspPort + rtspPath生成兜底地址。 - 地面端必须把旧地址
rtmp://...:1935/...规范化为rtsp://...:8554/...。 - 如果服务端返回
0.0.0.0、127.0.0.1或localhost,地面端必须替换为发现到的服务端 IP。 - start_stream 成功返回后,认为服务端 RTSP 链路已经建立;DroneScrewCtrlApp 固定多次打开本地 RTSP puller,默认最多 5 次、间隔 500ms,每次 open/read 超时按 5s 处理。成功标准不是 puller
Start()返回,而是收到并解码出第一帧 RTSP 图像;探测参数为probesize=262144、analyzeduration=500000us、fflags=nobuffer、max_delay=0、reorder_queue_size=0。 - 本地 RTSP puller 多次启动或首帧等待全部失败时,只提示“服务端已开流但本地拉流未启动”,不能自动发送
stop_stream;服务端 LiveStream 状态必须保持运行,便于用户用 VLC/ffplay 或网络工具继续定位 8554 拉流问题。
低延迟约束:
- 服务端 RTMP/FLV muxer 使用 flush packets、零 interleave delay,并且单视频流直接
av_write_frame,避免 muxer 为多流交织排序引入等待。 - 服务端每个 IDR 内嵌 SPS/PPS,GOP 约 0.5s,降低 VLC/DroneScrewCtrlApp 中途接入时等待关键帧的时间。
- 地面端点击“开始实时显示”后必须立即弹出“正在拉流,请稍候...”提示框,同时禁用开始/检测按钮;
StartLiveStream()返回后关闭提示框,并按结果切换 UI 状态。 - 地面端收到第一帧 RTSP 后显示“RTSP 已出图”,用于区分“服务端已开流”和“画面已经解码显示”两个阶段。
现场日志判定:
FFMediaPusher: init done (...)表示编码器和封装器初始化成功。[RTMP] pusher init ok ... push=rtmp://127.0.0.1:1935/live/dronescrew pull=rtsp://<板子IP>:8554/live/dronescrew表示内部推流地址和外部拉流地址已经拆清。FFMediaPusher: connected to mediamtx, header written表示服务端已经连上 mediamtx,RTMP 头已写入。[LIVE] started ... url=rtsp://<板子IP>:8554/live/dronescrew表示 LiveStream 状态已启动。start_stream返回ok=true且rawImagePublish=false是正确状态,距离检测模式显示走 RTSP,不走 raw。- start_stream 成功返回后如果地面端多次打开 RTSP 或等待首帧仍失败,应按真实错误处理,不自动发送
stop_stream关闭服务端 LiveStream;优先检查拉流 URL、mediamtx 和 8554 端口。 - 同尺寸推流时服务端直接拷贝 Mono8 到 NV12 Y 平面,不调用 RGA;只有输入输出尺寸不一致时才尝试 RGA 缩放,失败后回退 CPU 缩放继续推流。
VLC 或地面端提示“输入无法被打开”时,优先检查:
- 拉流 URL 是否为
rtsp://<板子IP>:8554/live/dronescrew,不能是rtsp://<板子IP>:1935/...。 - mediamtx 服务是否运行,且
rtspAddress: :8554、rtmpAddress: :1935是否被监听。 - 服务端是否打印
connected to mediamtx, header written。 - 服务端是否已有相机帧进入
pushRtspFrame,日志中的rtsp_push是否增长、rtsp_fail是否增长。 - 网络侧是否允许地面端访问板卡 8554 端口。
4. 控制命令
核心命令:
- open:按 machineCode 打开指定服务端并返回服务信息。
- get_info:读取服务端运行状态、相机参数、算法参数和端口信息。
- start_stream:进入距离检测模式,开启 decimation 4x4 下采样、RTSP 推流和 result 发布。
- stop_stream:退出距离检测模式,停止推流和距离检测。
- start:进入精准螺栓检测模式,关闭 binning 和 decimation,开启 raw/result 发布。
- stop:退出精准螺栓检测模式。
- single:执行单次精准检测。
- set_detect_mode:设置精准检测模式下 raw 图像传输方式,支持 mono/binocular。
- set_exposure / set_gain:下发相机曝光和增益。
- set_algo_params:下发算法参数。
- swap_cameras:交换左右相机角色。
5. 结果数据
检测结果由服务端通过 topic=result 发布,地面端由 WDRemoteReceiver 解析为 WDRemoteDetectionFrame。
主要字段:
- frameId:帧号。
- timestampUs:时间戳。
- imageWidth / imageHeight:检测坐标对应的图像尺寸。
- success:算法是否成功。
- errorCode:错误码或算法拒绝原因。
- message:详细消息。
- boxes:检测框列表。
- distances:距离结果列表,协议单位为 mm;距离检测 UI 显示时换算为 m,精准螺杆/螺栓相关尺寸和坐标保持原图坐标语义。
距离检测模式和精准检测模式都应发布 result。区别在于图像显示来源不同:距离检测模式显示 RTSP,精准检测模式显示 raw。
6. 原始图像数据
raw 图像使用 topic=raw 发布,主要服务于精准检测模式。
当前协议:
- payload = WDRemoteBinocularRawImageHeader + leftData + rightData。
- magic 为 BIWI。
- 支持 raw、png、mjpeg、zlib 压缩标识。
- 精准检测双图 raw 使用 zlib 无损压缩,左右图同时发送;zlib 失败时回退 raw。
- 精准检测单图 raw 使用固定有损压缩比例:Mono8 左图先按
1/4缩放,再用 MJPEGquality=25编码;不按运行时 payload 动态计算带宽,不因为带宽丢 raw 帧。 - 单图 raw 的 result 仍使用算法原始图像坐标,服务端发布 result 前把
imageWidth/imageHeight固定为算法输入左图尺寸,地面端按显示图尺寸做比例叠框。 - MJPEG 编码失败时可回退 zlib/raw,保证图像链路不断。
- detectMode=mono 时 right 字段为空,仅传 left。
7. 组件职责边界
DroneScrewServer
负责:
- 相机连接、左右角色、曝光/增益、binning/decimation、采集频率。
- 两种 pipeline 切换:DetectDistance 和 Detect。
- 实时视频链路:RTMP publish 到本机 mediamtx,并向地面端发布 RTSP pull URL。
- ZMQ control/result/raw 服务。
- UDP discovery。
- 算法参数加载和更新。
不负责:
- 地面端 UI 状态。
- 用户交互流程。
WDRemoteReceiver
负责:
- 搜索和连接服务端。
- 封装控制命令。
- 订阅 result。
- 订阅 raw。
- 解析服务端 JSON 和 raw payload。
- 通过回调把数据交给业务层。
不负责:
- UI 显示。
- 算法业务判断。
- 画框叠加。
DroneScrewCtrlApp
负责:
- 用户操作入口。
- 服务端连接状态展示。
- 距离检测模式:RTSP 画面 + result 距离结果展示。
- 精准检测模式:raw 图像 + result 检测框展示。
- 曝光、增益、算法参数配置。
- 单次检测测试。
不负责:
- 直接操作相机。
- 直接调用算法。
- 解析底层 ZMQ 协议细节。
8. 推荐状态流
8.1 地面端启动
- 创建 WDRemoteReceiver。
- 注册 event/result/raw 回调。
- UDP 搜索服务端。
- 通过 machineCode open。
- get_info 更新 UI 参数。
8.2 进入距离检测模式
- 地面端停止精准检测模式相关 raw 订阅。
- 地面端保持或启动 result 订阅。
- 地面端发送 start_stream。
- 服务端开启 decimation 4x4 下采样采集。
- 服务端启动 RTSP 推流。
- 服务端持续执行 DetectDistance。
- 地面端拉 RTSP 显示画面。
- 地面端接收 result 显示距离检测结果。
8.3 进入精准螺栓检测模式
- 地面端停止 RTSP 拉流。
- 地面端发送 stop_stream。
- 地面端设置 detectMode,默认 mono。
- 地面端启动 result/raw 订阅。
- 地面端发送 start。
- 服务端关闭 binning 和 decimation,停止 RTSP 推流。
- 服务端持续执行 Detect。
- 服务端发布 raw/result。
- 地面端用 raw 图像叠加 result 检测框。
8.4 停止
距离检测模式停止:
- 地面端发送 stop_stream。
- 服务端停止 RTSP 推流和距离检测。
精准检测模式停止:
- 地面端发送 stop。
- 服务端停止精准检测线程。
- 地面端停止 raw/result 订阅。
全部停止:
- 地面端释放 RTSP puller。
- 发送 stop。
- 发送 stop_stream。
9. 实现约束
- 两种模式互斥,不能同时启动 RTSP 距离检测和 raw 精准检测。
- 服务端算法始终使用双目输入。
- detectMode=mono 只减少地面端 raw 图像传输量。
- 距离检测模式必须订阅 result,否则只能看到画面,看不到距离检测结果。
- 精准检测模式依赖 raw 图像显示,不依赖 RTSP。
- 服务端开始检测后应持续处理最新有效帧;相机不同步时应使用最新缓存帧继续推进,不能因为 ready 标志被清空而停住。
10. 状态机约束
10.1 服务端状态
服务端只允许三种外部可见状态:
| 状态 | RTSP | raw PUB | result PUB | 算法 pipeline | 相机降采样 |
|---|---|---|---|---|---|
| Idle | 关闭 | 关闭 | 无业务结果 | 无 | 精准默认配置:binning=1x1, decimation=1x1 |
| LiveStream | 开启 | 关闭 | 持续发布 | DetectDistance | binning=1x1, decimation=4x4 |
| Detection | 关闭 | 开启 | 持续发布 | Detect | binning=1x1, decimation=1x1 |
合法转换:
- Idle -> LiveStream:收到 start_stream。
- Idle -> Detection:收到 start。
- LiveStream -> Idle:收到 stop_stream。
- Detection -> Idle:收到 stop。
- LiveStream -> Detection:必须先 stop_stream 成功,再 start 成功。
- Detection -> LiveStream:必须先 stop 成功,再 start_stream 成功。
非法或无效转换:
- LiveStream 状态下收到 start,应返回模式冲突或由调用方先 stop_stream。
- Detection 状态下收到 start_stream,应返回模式冲突或由调用方先 stop。
- LiveStream 状态下收到 stop 不应关闭距离检测结果链路。
- Detection 状态下收到 stop_stream 不应关闭精准检测线程。
10.2 WDRemoteReceiver 本地状态
WDRemoteReceiver 使用 Idle / LiveStream / Detection 记录最后一次已确认的远端模式:
| 本地状态 | result 订阅 | raw 订阅 | 地面端图像来源 |
|---|---|---|---|
| Idle | 关闭 | 关闭 | 无 |
| LiveStream | 开启 | 关闭 | RTSP puller |
| Detection | 开启 | 开启 | ZMQ raw |
状态推进规则:
- 只有控制命令返回成功后才更新本地状态。
- 停旧模式失败时保留旧状态,不能提前置为 Idle。
- 旧模式已确认停止,但新模式启动或订阅失败时,必须清理已打开订阅并进入 Idle。
- StopWork 只在停止当前活跃模式成功时关闭订阅并进入 Idle;停止非当前模式不能破坏当前模式的订阅。
- Disconnect 必须关闭 result/raw 订阅并进入 Idle。