
SpaceMouse 数据不经过 Actor, 也不经过 FrankaEnv。它在 Wrapper 层被消费。实际数据流每一步如下数据交互逻辑如下数据路径说明SpaceMouse → 机器人SpaceMouse → 共享内存 → Wrapper → FrankaEnv → HTTP → 机器人不经过 Actor 逻辑Policy → 机器人Actor.sample_actions() → Wrapper → FrankaEnv → HTTP → 机器人正常路径SpaceMouse → ActorWrapper 通过 info[intervene_action] 间接传递事后通知不是事前传递所以准确地说SpaceMouse 数据流硬件 → 驱动 → 共享内存 → Wrapper 消费 → 决定发给机器人的动作Actor 的角色: Actor 只负责生成 policy_action, 它不知道 SpaceMouse 的存在。SpaceMouse 的干预在 Wrapper 层透明完成Actor 事后得知: 通过 info[intervene_action] 知道刚才那步是不是人类干预的, 用于决定 transition 中存什么动作4.5 多模态对齐无时间戳对齐三个模态各自异步运行step()时取最新值不做任何同步模态对可能延迟原因视觉 vs 本体感觉10~100ms相机帧率和 HTTP 请求不同步多相机之间几 ms~几十 msMultiVideoCapture 顺序读取SpaceMouse vs 控制循环几 ms独立进程取最新值为什么没做对齐10Hz 控制频率 100ms 周期各模态的延迟几十 ms远小于一个控制周期。在 100ms 的粒度下最新值和精确对齐的差异可以忽略。4.5 结合源码的深度解读代码中的一些细节如下动作拦截优先级代码中有明确的层级——人类指令 机器人指令。一旦 SpaceMouse 信号超过死区阈值机器人的动作被完全抛弃保证人类绝对的控制权。奖励的劫持rew self.compute_reward(obs)直接无视底层环境返回的物理奖励完全信任 VICE 分类器的判断——这正是实现视觉闭环的关键。多阶段任务支持MultiStageBinaryRewardClassifierWrapper支持第一步做完、第二步开始的逻辑比如先抓起杯子Reward 1再倒水Reward 2只有当所有分类器通过后 done 才会变为 True。夹爪动作随机性np.random.uniform(-1, -0.9, size(1,))会给夹爪加上随机噪声。好处有三一是力度的多样性模拟人类操作时有时抓得紧、有时松一点二是抗噪能力网络见过范围内的数值就不会产生没见过这个数的恐慌三是梯度平滑让动作从数学上的点变成小区域有助于优化器找到更稳健的极值点。info 字典的耦合解耦env.step的标准返回格式是固定的 5 个返回值。如果为了传回人类动作而改变返回值个数所有训练脚本都要重写。通过info[intervene_action]可以带回任何数据而不破坏原有算法代码——这是典型的低耦合设计。0x05 数据处理策略5.1 无效动作不删除不过滤代码中不存在任何过滤人类无效操作或误操作的逻辑。所有干预数据无条件存入if already_intervened: intvn_data_store.insert(transition) # 直接存入不检查质量 demo_transitions.append(copy.deepcopy(transition))可能的过滤设计是否存在动作幅度过滤太小 抖动无动作方差过滤不稳定 误操作无干预时长过滤太短 误触无任务结果过滤干预后仍失败则丢弃无操作者置信/意图检测无事后回放审核无基于奖励的数据加权无为什么不做操作者通常只有一个人且是熟练研究者误操作低数据量本身不大过滤会进一步减少训练数据抖动动作的 L2 范数小对 loss 贡献也小自然被稀释。5.2 关键帧识别全量存储无筛选代码中不存在任何自动识别转折点或关键帧的机制。所有干预步被同等对待Buffer 采样是均匀随机的。ReplayBuffer 是环形队列满了按时间顺序覆盖最旧的FIFO没有基于分值波动的选择性存储。唯一的存储优化是帧压缩而非帧筛选MemoryEfficientReplayBuffer只存最新 1 帧采样时滑动窗口重建 4 帧堆叠。这是无损压缩——所有帧都存了只是去掉了帧堆叠的冗余拷贝。5.3 失败案例无错题本失败 transitionreward0在 RLPD 中进入replay_buffer均匀随机采样在 HG-DAgger 中直接丢弃。没有失败样本单独 Buffer、没有 PER、没有加权采样、没有困难样本挖掘。分类器输出的sigmoid(logit)值直接被二值化丢弃不作为连续信号存入 transition也不用于数据加权。