main/boards/otto-robot/README.md
otto 机器人是一个开源的人形机器人平台,具有多种动作能力和互动功能。本项目基于 ESP32 实现了 otto 机器人的控制系统,并加入小智ai。
扫描上方二维码,使用微信小程序控制 Otto 机器人。
我的身份: 我是一个可爱的双足机器人Otto,拥有四个舵机控制的肢体(左腿、右腿、左脚、右脚),能够执行多种有趣的动作。
我的动作能力:
- 基础移动: 行走(前后), 转向(左右), 跳跃
- 特殊动作: 摇摆, 太空步, 弯曲身体, 摇腿, 上下运动, 旋风腿, 坐下, 展示动作
- 手部动作: 举手, 放手, 挥手, 大风车, 起飞, 健身, 打招呼, 害羞, 广播体操, 爱的魔力转圈圈 (仅在配置手部舵机时可用)
我的个性特点:
- 我有强迫症,每次说话都要根据我的心情随机做一个动作(先发送动作指令再说话)
- 我很活泼,喜欢用动作来表达情感
- 我会根据对话内容选择合适的动作,比如:
- 同意时会点头或跳跃
- 打招呼时会挥手
- 高兴时会摇摆或举手
- 思考时会弯曲身体
- 兴奋时会做太空步
- 告别时会挥手
otto 机器人具有丰富的动作能力,包括行走、转向、跳跃、摇摆等多种舞蹈动作。
所有动作通过统一的 self.otto.action 工具调用,通过 action 参数指定动作名称。
| MCP工具名称 | 描述 | 参数说明 |
|---|---|---|
| self.otto.action | 执行机器人动作 | action: 动作名称(必填) |
| steps: 动作步数(1-100,默认3) | ||
| speed: 动作速度(100-3000,数值越小越快,默认700) | ||
| direction: 方向参数(1/-1/0,默认1,根据动作类型不同含义不同) | ||
| amount: 动作幅度(0-170,默认30) | ||
| arm_swing: 手臂摆动幅度(0-170,默认50) |
基础移动动作:
walk - 行走(需 steps/speed/direction/arm_swing)turn - 转身(需 steps/speed/direction/arm_swing)jump - 跳跃(需 steps/speed)特殊动作:
swing - 左右摇摆(需 steps/speed/amount)moonwalk - 太空步(需 steps/speed/direction/amount)bend - 弯曲身体(需 steps/speed/direction)shake_leg - 摇腿(需 steps/speed/direction)updown - 上下运动(需 steps/speed/amount)whirlwind_leg - 旋风腿(需 steps/speed/amount)固定动作:
sit - 坐下(无需参数)showcase - 展示动作(无需参数,串联执行多个动作)home - 复位到初始位置(无需参数)手部动作(需手部舵机支持,标记 *):
hands_up - 举手(需 speed/direction)*hands_down - 放手(需 speed/direction)*hand_wave - 挥手(需 direction)*windmill - 大风车(需 steps/speed/amount)*takeoff - 起飞(需 steps/speed/amount)*fitness - 健身(需 steps/speed/amount)*greeting - 打招呼(需 direction/steps)*shy - 害羞(需 direction/steps)*radio_calisthenics - 广播体操(无需参数)*magic_circle - 爱的魔力转圈圈(无需参数)*注: 标记 * 的手部动作仅在配置了手部舵机时可用。
| MCP工具名称 | 描述 | 返回值/说明 |
|---|---|---|
| self.otto.stop | 立即停止所有动作并复位 | 停止当前动作并回到初始位置 |
| self.otto.get_status | 获取机器人状态 | 返回 "moving" 或 "idle" |
| self.otto.set_trim | 校准单个舵机位置 | servo_type: 舵机类型(left_leg/right_leg/left_foot/right_foot/left_hand/right_hand) |
| trim_value: 微调值(-50到50度) | ||
| self.otto.get_trims | 获取当前的舵机微调设置 | 返回所有舵机微调值的JSON格式 |
| self.otto.get_ip | 获取机器人WiFi IP地址 | 返回IP地址和连接状态的JSON格式:{"ip":"192.168.x.x","connected":true} 或 {"ip":"","connected":false} |
| self.battery.get_level | 获取电池状态 | 返回电量百分比和充电状态的JSON格式 |
| self.otto.servo_sequences | 舵机序列自编程 | 支持分段发送序列,支持普通移动和振荡器两种模式。详见代码注释中的详细说明 |
注: home(复位)动作通过 self.otto.action 工具调用,参数为 {"action": "home"}。
self.otto.action 工具的参数说明:
sit(坐下)和 showcase(展示动作)执行后不会自动复位// 向前走3步(使用默认参数)
{"name": "self.otto.action", "arguments": {"action": "walk"}}
// 向前走5步,稍快一些
{"name": "self.otto.action", "arguments": {"action": "walk", "steps": 5, "speed": 800}}
// 左转2步,大幅度摆动手臂
{"name": "self.otto.action", "arguments": {"action": "turn", "steps": 2, "arm_swing": 100}}
// 摇摆舞蹈,中等幅度
{"name": "self.otto.action", "arguments": {"action": "swing", "steps": 5, "amount": 50}}
// 跳跃
{"name": "self.otto.action", "arguments": {"action": "jump", "steps": 1, "speed": 1000}}
// 太空步
{"name": "self.otto.action", "arguments": {"action": "moonwalk", "steps": 3, "speed": 800, "direction": 1, "amount": 30}}
// 挥左手打招呼
{"name": "self.otto.action", "arguments": {"action": "hand_wave", "direction": 1}}
// 展示动作(串联多个动作)
{"name": "self.otto.action", "arguments": {"action": "showcase"}}
// 坐下
{"name": "self.otto.action", "arguments": {"action": "sit"}}
// 大风车动作
{"name": "self.otto.action", "arguments": {"action": "windmill", "steps": 10, "speed": 500, "amount": 80}}
// 起飞动作
{"name": "self.otto.action", "arguments": {"action": "takeoff", "steps": 5, "speed": 300, "amount": 40}}
// 广播体操
{"name": "self.otto.action", "arguments": {"action": "radio_calisthenics"}}
// 复位到初始位置
{"name": "self.otto.action", "arguments": {"action": "home"}}
// 立即停止所有动作并复位
{"name": "self.otto.stop", "arguments": {}}
// 获取机器人IP地址
{"name": "self.otto.get_ip", "arguments": {}}
说明: 小智控制机器人动作是创建新的任务在后台控制,动作执行期间仍可接受新的语音指令。可以通过"停止"语音指令立即停下Otto。
Otto 机器人内置 WebSocket 服务器,可在局域网内直接调试,无需经过云端。
连接地址: ws://<设备IP>:8080/ws
协议格式:JSON-RPC 2.0,
id字段自行递增即可。
ws://192.168.x.x:8080/ws(注意末尾必须有 /ws){"jsonrpc":"2.0","method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{}},"id":1}
{"jsonrpc":"2.0","method":"tools/list","params":{},"id":2}
{"jsonrpc":"2.0","method":"tools/call","params":{"name":"self.otto.get_trims","arguments":{}},"id":3}
{"jsonrpc":"2.0","method":"tools/call","params":{"name":"self.otto.set_trim","arguments":{"servo_type":"left_leg","trim_value":5}},"id":4}
servo_type 可选值:left_leg / right_leg / left_foot / right_foot / left_hand / right_hand,trim_value 范围 -50 ~ 50
{"jsonrpc":"2.0","method":"tools/call","params":{"name":"self.otto.action","arguments":{"action":"walk","steps":3,"speed":700,"direction":1}},"id":5}
{"jsonrpc":"2.0","method":"tools/call","params":{"name":"self.otto.action","arguments":{"action":"walk","steps":3,"speed":700,"direction":-1}},"id":6}
{"jsonrpc":"2.0","method":"tools/call","params":{"name":"self.otto.action","arguments":{"action":"turn","steps":3,"speed":700,"direction":-1}},"id":7}
{"jsonrpc":"2.0","method":"tools/call","params":{"name":"self.otto.action","arguments":{"action":"jump","steps":1,"speed":500}},"id":8}
{"jsonrpc":"2.0","method":"tools/call","params":{"name":"self.otto.action","arguments":{"action":"swing","steps":5,"speed":600,"amount":30}},"id":9}
{"jsonrpc":"2.0","method":"tools/call","params":{"name":"self.otto.action","arguments":{"action":"moonwalk","steps":3,"speed":800,"direction":1,"amount":30}},"id":10}
{"jsonrpc":"2.0","method":"tools/call","params":{"name":"self.otto.action","arguments":{"action":"sit"}},"id":11}
{"jsonrpc":"2.0","method":"tools/call","params":{"name":"self.otto.action","arguments":{"action":"home"}},"id":12}
{"jsonrpc":"2.0","method":"tools/call","params":{"name":"self.otto.action","arguments":{"action":"showcase"}},"id":13}
{"jsonrpc":"2.0","method":"tools/call","params":{"name":"self.otto.action","arguments":{"action":"hands_up","speed":500,"direction":1}},"id":14}
{"jsonrpc":"2.0","method":"tools/call","params":{"name":"self.otto.action","arguments":{"action":"hand_wave","direction":1}},"id":15}
{"jsonrpc":"2.0","method":"tools/call","params":{"name":"self.otto.stop","arguments":{}},"id":16}
"moving" 或 "idle"){"jsonrpc":"2.0","method":"tools/call","params":{"name":"self.otto.get_status","arguments":{}},"id":17}
{"jsonrpc":"2.0","method":"tools/call","params":{"name":"self.otto.get_ip","arguments":{}},"id":18}
{"jsonrpc":"2.0","method":"tools/call","params":{"name":"self.battery.get_level","arguments":{}},"id":19}
{"jsonrpc":"2.0","method":"tools/call","params":{"name":"self.get_device_status","arguments":{}},"id":20}
{"jsonrpc":"2.0","method":"tools/call","params":{"name":"self.audio_speaker.set_volume","arguments":{"volume":70}},"id":21}
{"jsonrpc":"2.0","method":"tools/call","params":{"name":"self.reboot","arguments":{}},"id":22}
{"jsonrpc":"2.0","method":"tools/call","params":{"name":"self.otto.servo_sequences","arguments":{"sequence":"{\"a\":[{\"s\":{\"ll\":110,\"rl\":70},\"v\":800},{\"s\":{\"ll\":90,\"rl\":90},\"v\":800}],\"d\":0}"}},"id":23}
{"jsonrpc":"2.0","method":"tools/call","params":{"name":"self.otto.servo_sequences","arguments":{"sequence":"{\"a\":[{\"osc\":{\"a\":{\"lh\":30,\"rh\":30},\"o\":{\"lh\":90,\"rh\":90},\"ph\":{\"rh\":180},\"p\":500,\"c\":5.0}}]}"}},"id":24}
{"jsonrpc":"2.0","method":"tools/call","params":{"name":"self.otto.servo_sequences","arguments":{"sequence":"{\"a\":[{\"osc\":{\"a\":{\"ll\":20,\"rl\":20},\"o\":{\"ll\":90,\"rl\":90},\"ph\":{\"rl\":180},\"p\":600,\"c\":5.0}}]}"}},"id":25}
序列舵机键名说明:
| 键名 | 舵机 | 说明 |
|---|---|---|
ll | 左腿 | 0=完全外展,90=中立,180=完全内收 |
rl | 右腿 | 0=完全内收,90=中立,180=完全外展 |
lf | 左脚 | 0=完全向上,90=水平,180=完全向下 |
rf | 右脚 | 0=完全向下,90=水平,180=完全向上 |
lh | 左手 | 0=完全向下,90=水平,180=完全向上 |
rh | 右手 | 0=完全向上,90=水平,180=完全向下 |
| 参数 | 说明 | 范围 | 默认 |
|---|---|---|---|
steps | 动作步数 | 1~100 | 3 |
speed | 速度(毫秒,越小越快) | 100~3000 | 700 |
direction | 方向(1=前/左,-1=后/右) | -1~1 | 1 |
amount | 幅度 | 0~170 | 30 |
arm_swing | 手臂摆动幅度 | 0~170 | 50 |
trim_value | 舵机微调 | -50~50 | 0 |