今天看的是
为什么Axis显示动捕设备是96 Hz,但我们的程序通过BVH/MocapApi只能得到约60~64帧/秒?
重点讲我们如何从发现现象开始,一步步修改程序、增加证据、排除可能原因,最后把问题定位到Axis普通BVH/MocapApi输出边界。
一、最开始我们看到了什么
第一次动捕服成功连接后,链路已经能跑通:
动捕服
↓
PNLink
↓
Axis Studio
↓
MocapApi
↓
GMR
↓
ZMQ
↓
MuJoCo
Axis里的人物会跟随真人,MuJoCo里的G1也会动。
但终端不断出现:
[NoitomJump]
prev_posture_index=100
posture_index=102
delta=2
missing_posture_indices=[101]
大白话就是:
上一帧编号是100
下一次收到的编号是102
编号101没有出现
同时,程序统计的接收频率只有:
约60~64 Hz
但Axis设备页面显示:
帧率(动捕设备):96
于是产生了最初的疑问:
是Axis本来就只发约64帧,还是我们的程序、GMR、ZMQ或MuJoCo弄丢了约三分之一?
这时不能直接下结论,因为从Axis到MuJoCo中间有很多环节,任何一层都可能造成少帧。
二、第一步:不靠“看起来”,建立分层计数
一开始只看终端里的NoitomJump,无法知道帧究竟丢在哪里。
所以我们的第一个核心思路是:
给流水线中的每一层都安装“水表”。
最终形成以下计数:
Axis/MocapApi实际交给程序多少帧
↓ source_received
GMR处理了多少帧
↓ gmr_processed
生成了多少机器人动作
↓ motion_generated
ZMQ成功发送多少帧
↓ zmq_sent
MuJoCo接收多少帧
↓ received
MuJoCo实际应用多少帧
↓ applied
同时记录:
source_missing_indices
input_pending
robot_pending
gaps
invalid
stale
这样我们就能问:
是输入时就少了?
还是GMR处理时少了?
还是ZMQ发送时少了?
还是MuJoCo接收时少了?
这一步是整个排查最关键的基础。
三、建立AuditCore:检查电脑发送端
我们增加了AuditCore。
它记录:
source_received
source_missing_indices
first_posture_index
last_posture_index
gmr_processed
motion_generated
zmq_sent
grpc_sent
input_pending
robot_pending
max_input_queue
max_robot_queue
为什么需要它?
因为如果最终看到:
source_received=1000
gmr_processed=650
就说明GMR或输入队列丢了350帧。
如果看到:
motion_generated=1000
zmq_sent=650
就说明ZMQ发送端丢了350帧。
如果它们都相等,就说明问题不在这些层。
四、建立AuditViewer:检查MuJoCo接收端
发送端说“我发送成功了”还不够,因为接收端可能没拿全。
所以MuJoCo端又增加:
received
applied
pending
gaps
invalid
stale
latest_frame_id
delay_ms
最重要的是:
gaps
我们给每个ZMQ动作帧增加连续编号:
frame_id=1
frame_id=2
frame_id=3
如果MuJoCo收到:
1
2
4
那么:
gaps=1
这样可以直接判断ZMQ通信有没有漏掉动作帧。
五、先排查MuJoCo是不是处理不过来
第一次看到明显延迟时,最容易怀疑:
会不会MuJoCo渲染太慢,导致动作积压或丢失?
于是我们观察Viewer:
received
applied
pending
gaps
invalid
测试结果出现过:
received=1862
applied=1862
pending=0
gaps=0
invalid=0
delay≈0.3 ms
这意味着:
- 收到1862帧;
- 实际应用1862帧;
- 没有尚未处理的积压;
- frame_id没有断号;
- Header、CRC、protobuf没有损坏;
- 本机ZMQ延迟很低。
所以排除:
MuJoCo渲染导致丢帧
MuJoCo接收后没有应用
MuJo


343

被折叠的 条评论
为什么被折叠?



