跳到主要内容

机器人情绪与动作系统设计最佳实践

综合自:reachy-mini-conversation-app(Pollen Robotics)


问题描述

如何为社交机器人设计情绪和动作系统,使其:

  • 在交互时表现自然
  • 在空闲时保持鲜活感
  • 支持多种情绪/动作的无缝切换
  • 与语音同步产生有机的运动

核心设计原则

1. 永不静止(Always Alive)

原则:机器人永远不应该完全静止。

实现

  • 空闲 0.3 秒后自动进入呼吸动画
  • 呼吸参数:5mm Z 轴浮动 + 天线交替摆动
  • 频率接近人类呼吸(6 次/分钟)

理由:静止的机器人显得机械和"死亡",持续的微运动创造亲和感。


2. 双层融合架构

架构

┌─────────────────────────────────────┐
│ 最终姿态输出(100Hz) │
├─────────────────────────────────────┤
│ 主要动作(互斥) + 次要偏移(叠加) │
│ ├─ 情绪 ├─ 语音摆动 │
│ ├─ 舞蹈 └─ 人脸追踪 │
│ ├─ Goto 定位 │
│ └─ 呼吸 │
└─────────────────────────────────────┘

理由

  • 主要动作互斥避免冲突
  • 次要偏移叠加增加自然感
  • 单一控制点确保一致性

3. 音频驱动自然运动

原则:说话时的运动应该由音频实时驱动。

关键参数

参数作用
延迟补偿200ms对齐音频与机械延迟
VAD 开启阈值-35 dB检测语音开始
VAD 关闭阈值-45 dB滞后避免抖动
振荡轴数6 轴pitch/yaw/roll/x/y/z

理由

  • 多轴独立振荡避免机械感
  • 响度驱动幅度保持动态
  • 随机初始相位增加有机感

方案比较

动作触发方式

方式优点缺点适用场景
LLM 工具调用上下文相关、智能选择延迟较高交互式情绪表达
随机触发简单、不可预测缺乏意图空闲时的自发行为
时间触发可预测、可控机械感定期演示
音频驱动自然同步需要音频输入说话时的辅助运动

推荐:组合使用 - LLM 决定"做什么",音频驱动"怎么做",随机增加"变化"。


呼吸状态设计

参数保守值活跃值推荐
Z 轴浮动3mm10mm5mm
呼吸频率0.08 Hz0.15 Hz0.1 Hz
天线摆动10°20°15°
天线频率0.3 Hz0.7 Hz0.5 Hz

推荐:使用保守值作为基础,在特定人格或情绪状态下调整。


决策矩阵

场景推荐方案理由
用户说话时语音摆动 + 天线冻结避免干扰监听
机器人说话时语音摆动 + 情绪动作增强表达力
短暂空闲(<15s)呼吸动画保持鲜活感
长时间空闲(>15s)LLM 触发创意动作主动吸引注意
情绪切换插值过渡(1s)避免突变

推荐最佳实践

设计层面

  1. 分层设计:将情绪、舞蹈、呼吸作为独立的 Move 对象,通过队列顺序执行

  2. 单一控制点:所有运动通过统一的 set_target 输出,避免并发冲突

  3. 线程安全:控制循环独占状态,外部通过消息队列通信

  4. 时间对齐:使用单调时钟,避免系统时间跳跃影响动画

参数层面

  1. 呼吸优先:任何空闲状态都应该回到呼吸,而不是完全静止

  2. 天线异步:两天线使用相反方向摆动,打破对称感

  3. 相位随机:每次会话使用不同的初始相位,避免重复感

  4. 响度映射:运动幅度应该与音量正相关,使用 gamma 曲线调整

时长与调用层面

  1. 时长协议:所有 Move 必须实现 duration 属性,控制循环依赖它判断完成

  2. 复合时长:多个子动作组成的复合动作,总时长 = Σ 子动作时长

  3. 即时响应:收到完整工具参数后立即执行,异步返回结果给 LLM

  4. 空闲区分:空闲触发的工具调用不生成语音回复,避免打扰


动作时长设计

时长类型

动作类型时长来源特点
情绪动作预录制数据固定,由录制决定
舞蹈动作程序生成固定,由动作定义
Goto 定位参数指定可配置(默认 1s)
呼吸动作float("inf")无限循环,被中断

时长判断

当前时间 - 开始时间 >= 动作时长  →  动作完成,开始下一个

流式工具调用流程

OpenAI Server → response.function_call_arguments.done

dispatch_tool_call()

Tool.__call__()

movement_manager.queue_move()

function_call_output → OpenAI Server

关键事件response.function_call_arguments.done 表示参数完全接收,触发执行。


应避免的反模式

反模式问题替代方案
直接操作姿态绕过队列导致冲突通过队列提交 Move
完全静止机械感、"死亡"感持续呼吸动画
对称运动机械、不自然天线/相位异步
固定相位重复、可预测随机化初始相位
控制循环 I/O阻塞导致掉帧异步/预取数据
突然切换廉价感插值过渡
时长不准动作截断或拖沓精确计算 duration
流式参数处理参数不完整等待 .done 事件

实现检查清单

  • 呼吸动画在空闲 0.3 秒后自动启动
  • 所有主要动作通过统一队列管理
  • 所有 Move 实现 duration 属性
  • 语音摆动与音频输出同步(200ms 延迟)
  • 天线在监听时冻结,恢复时平滑混合
  • 空闲 15 秒后触发 LLM 创意动作
  • 每次会话随机化振荡相位
  • 控制循环保持 100Hz 稳定
  • 工具调用等待完整参数再执行

参考


创建时间:2026-03-02 更新时间:2026-03-02