# 山猫 S10 遥控指令整理 > **资料依据** > - 《山猫S10 软件开发指南》V1.0.2(2026-10-13)第 1 章「本体监控协议」 > - 《DeepRoboticsLab 2.5.4 备份与密钥分析》(2026-10-29)连接与加密实测部分 > > **整理日期:**2026-10-29 > > 本文只整理「遥控(手动/半自主)控制」所需的内容:连接方式、帧格式、控制类指令、必要的状态回读。 > 导航任务下发、CPU/电池等设备监控、ROS2 话题不在本文范围内。 --- ## 0. 一分钟速查 | 功能 | Type | Command | 关键 Items | 响应 | |---|---|---|---|---| | 心跳(保活 + 开启状态上报) | `0x00100064` | `0x00000005` | 无 | 有 | | 使用模式切换 | `0x00100002` | `0x00500002` | `Mode` | 有 | | 运动状态转换(站/趴/阻尼) | `0x00100001` | `0x00200002` | `MotionParam` | 有 | | 运动步态切换 | `0x00100001` | `0x00300002` | `GaitParam` | 有 | | 运动控制(轴指令) | `0x00100001` | `0x00100002` | `X/Y/Z/Roll/Pitch/Yaw` | **无响应帧** | | 运动控制(速度指令) | `0x00100001` | `0x00110002` | `X/Y/Z/Roll/Pitch/Yaw` | **无响应帧** | | 自定义灯语 | `0x00100005` | `0x00200002` | `CustomMode`、`Led[]` | 有 | | 自主充电 | `0x00100004` | `0x00100002` | `Charge` | 有 | | 运动 SDK 模式 | `0x00100005` | `0x00300002` | `SDKEnable`、`Frequency` | 有 | | 休眠模式设置 | `0x00100002` | `0x00400002` | `Sleep`、`Auto`、`Time` | 有 | 十进制换算(JSON 里必须写数字,不能写带空格的十六进制): | 十六进制 | 十进制 | 十六进制 | 十进制 | |---|---|---|---| | `0x00100001` | 1048577 | `0x00000005` | 5 | | `0x00100002` | 1048578 | `0x00100002` | 1048578 | | `0x00100004` | 1048580 | `0x00110002` | 1114114 | | `0x00100005` | 1048581 | `0x00200002` | 2097154 | | `0x00100064` | 1048676 | `0x00300002` | 3145730 | | `0x0010007f` | 1048703 | `0x00400002` | 4194306 | | `0x00f00000` | 15728640 | `0x00500002` | 5242882 | --- ## 1. 连接与帧格式 ### 1.1 连接参数 | 项目 | 值 | |---|---| | 机器人地址(实测) | `10.21.33.103` | | TLS(TCP + 加密) | 端口 **30003** | | DTLS(UDP + 加密) | 端口 **30004** | | 角色 | 机器人为服务端,上位机/外部板卡为客户端 | | 加密 | 默认开启;关闭需修改 `robotserver` 配置文件(联系技术支持),系统更新不会覆盖该配置 | **安全机制是 mTLS 双向认证**(实测结论,不是可选的): - 客户端必须提供 `client_chain.crt` + `client.key`,服务端用同一 CA 链验证; - 不带客户端证书,服务端直接返回 `TLSV13_ALERT_CERTIFICATE_REQUIRED`; - 明文 TCP 会被服务端用 TLS alert 拒绝(`15 03 03 00 02 02 16`); - 实测协商结果:TLSv1.3 / `TLS_AES_256_GCM_SHA384`,服务端证书 `CN=server.local`,可用导出的 `root_ca.crt` 校验通过。 证书材料来自 App 的 `assets/certs/`,运行时复制到 `filesDir/certs/`: | 文件 | 说明 | |---|---| | `client.key` | 客户端私钥,RSA 2048 / PKCS#8 / PEM,无口令 | | `client_chain.crt` | 客户端证书链(client.local ← TLS CA ← Project CA ← Root CA) | | `root_ca.crt` | 根 CA,有效期 2026-04-03 ~ 2036-03-31 | > 客户端叶子证书有效期 2026-04-03 ~ 2027-04-03,过期后需重新获取。 > TCP 与 DTLS 复用同一套证书和同一个 TLS 上下文,不存在单独的对称密钥或 PSK。 ### 1.2 协议帧(16 字节头 + ASDU) | 偏移 | 长度 | 字段 | 说明 | |---|---|---|---| | 0 | 4 | 同步字符 | 固定 `EB 91 EB 90` | | 4 | 2 | 长度 | ASDU 字节数,**小端**;单帧 ASDU ≤ 1000 字节,分包总长 ≤ 65535 | | 6 | 2 | 报文 ID | 小端,请求/响应同值,0 → 65535 循环;分包须一致 | | 8 | 1 | ASDU 格式 | `0x00` = XML,`0x01` = JSON | | 9 | 1 | 当前包编号 | 从 0 递增,≤ 255 | | 10 | 1 | 协议版本 | 固定 `0x01` | | 11 | 5 | 预留 | 全 0 | ### 1.3 ASDU 结构 根节点固定为 `PatrolDevice`,四个字段: | 字段 | 含义 | |---|---| | `Type` | 消息类型 | | `Command` | 消息命令码 | | `Time` | 本地时区发送时间,`YYYY-MM-DD HH:MM:SS`(实测响应带毫秒,如 `2026-10-29 19:50:18.403`,两种均可) | | `Items` | 参数项 | 推荐 JSON(官方说明:JSON 处理更快、支持的消息类型更全)。 ### 1.4 数值写法(容易踩坑) 官方文档示例里写的是 `"Type": 0x0010 0064` 这种**带空格的十六进制,这不是合法 JSON**。实际发送必须用整数: ```json {"PatrolDevice":{"Type":1048676,"Command":5,"Time":"2026-01-01 00:00:00","Items":{}}} ``` --- ## 2. 手动遥控操作时序 ``` ① 建立 mTLS 连接 (30003/TCP 或 30004/UDP) │ ② 心跳 0x00100064 / 0x00000005,频率 ≥ 1Hz(持续保活) │ └─ 机器人开始向该 IP:端口 上报状态(2Hz/10Hz/1Hz) │ ③ 使用模式 0x00100002 / 0x00500002 Mode=0 常规(手动) │ ④ 运动状态 0x00100001 / 0x00200002 MotionParam=1 站立 │ └─ ASDU 下发站立完成后会自动进入 RL 控制状态 │ ⑤ 步态 0x00100001 / 0x00300002 GaitParam=0x1001 基础 │ (必须在机器人完全停止后下发) │ ⑥ 轴指令 0x00100001 / 0x00100002 持续下发 X/Y/Yaw(建议 ≥10Hz) │ (无响应帧,靠状态上报确认) │ ⑦ 结束:轴指令全 0 → 趴下 MotionParam=4,或直接断开 ``` **导航(半自主)路线**与上面的差异: ``` ③ Mode=1 导航模式 ⑤ GaitParam=0x3002(平地导航)/ 0x3003(楼梯导航,须在进楼梯前切换) ⑥ 改用速度指令 0x00100001 / 0x00110002(单位 m/s、rad/s,仅导航模式生效,建议 10Hz) ``` **关键约束** - 心跳必须持续发:连续 **2 秒** 未收到就关闭主动上报,需重新建立连接。 - 轴指令/速度指令要求 **2 秒内来自同一客户端**,否则返回 `0xE006`。 - 步态切换必须在机器人**完全停止**后下发,否则指令被缓存、停机后才执行。 - 站立后:走 **ASDU** 会自动进 RL 控制,可直接发速度/步态;走 **ROS2 话题**不会自动进,需要再补一条 RL 控制指令。 - 轴指令和速度指令**不返回响应帧**,只能靠状态上报判断是否生效。 --- ## 3. 控制类指令详解 ### 3.1 心跳指令 | Type | Command | 说明 | |---|---|---| | `0x00100064` | `0x00000005` | 心跳,Items 为空 | ```json {"PatrolDevice":{"Type":1048676,"Command":5,"Time":"2026-01-01 00:00:00","Items":{}}} ``` - 建议 ≥ 1Hz。 - 机器人会向**持续发送心跳的 IP 和端口**主动上报实时状态与异常状态。 - 超时 2 秒关闭主动上报,超时后需要重新建立链接。 ### 3.2 使用模式切换 | Type | Command | 说明 | |---|---|---| | `0x00100002` | `0x00500002` | 切换机器人使用模式 | | 参数 | 类型 | 取值 | |---|---|---| | `Mode` | int | `0` 常规模式 / `1` 导航模式 / `2` 辅助模式 | ```json {"PatrolDevice":{"Type":1048578,"Command":5242882,"Time":"2026-01-01 00:00:00","Items":{"Mode":0}}} ``` - 常规模式下支持轴指令;导航模式下支持导航任务。 - 切换结果需通过状态上报 `ControlUsageMode` 确认。 ### 3.3 运动状态转换 | Type | Command | 说明 | |---|---|---| | `0x00100001` | `0x00200002` | 转换机器人运动状态 | | 参数 | 类型 | 取值 | |---|---|---| | `MotionParam` | int | `-2` 软急停 / `0` 默认(初始、趴卧)/ `1` 站立 / `2` 关节阻尼 / `4` 趴下 / `5` 标零 / `17` RL 控制 / `0x1001` 阻尼趴下 | ```json {"PatrolDevice":{"Type":1048577,"Command":2097154,"Time":"2026-01-01 00:00:00","Items":{"MotionParam":1}}} ``` > 「空闲」与「软急停」只能查询,**不能通过该指令下发转换**。 > 用途:`MotionParam=1` 站立、`4` 趴下是最常用的两条;`2` 关节阻尼可作为软急停后的安全态。 ### 3.4 运动步态切换 | Type | Command | 说明 | |---|---|---| | `0x00100001` | `0x00300002` | 切换运动步态 | | 参数 | 类型 | 取值 | |---|---|---| | `GaitParam` | int | `0x1001` 基础(常规)/ `0x1003` 楼梯(常规)/ `0x3002` 平地(导航)/ `0x3003` 楼梯(导航) | ```json {"PatrolDevice":{"Type":1048577,"Command":3145730,"Time":"2026-01-01 00:00:00","Items":{"GaitParam":4097}}} ``` - 步态切换会自动切到对应运动模式,运动模式切换也会自动切到默认步态。 - 二次开发做自主导航时**必须**用导航专用步态:平地 `0x3002`,楼梯 `0x3003`,且楼梯步态要在**进楼梯前**切换,严禁进楼梯后再切。 - 必须停机后下发。 ### 3.5 运动控制(轴指令) | Type | Command | 说明 | |---|---|---| | `0x00100001` | `0x00100002` | 六自由度速度比例控制,**无响应帧** | ```json {"PatrolDevice":{"Type":1048577,"Command":1048578,"Time":"2026-01-01 00:00:00","Items":{"X":0.0,"Y":0.0,"Z":0.0,"Roll":0.0,"Pitch":0.0,"Yaw":0.0}}} ``` | 参数 | 含义 | 单位 | 范围 | |---|---|---|---| | `X` | 前后速度 | %(相对最大速度比例) | [-1, 1] | | `Y` | 左右速度 | % | [-1, 1] | | `Z` | 高度方向速度 | % | [-1, 1] | | `Roll` | 翻滚角速度 | % | [-1, 1] | | `Pitch` | 俯仰角速度 | % | [-1, 1] | | `Yaw` | 偏航角速度 | % | [-1, 1] | - 仅常规模式和辅助模式可用(导航模式请用速度指令)。 - **基础步态只响应 X、Y、Yaw**;Z、Roll、Pitch、Yaw 的额外自由度仅在特殊步态下有效。 - 正方向按右手坐标系;X 正为前进、Y 正为左移、Yaw 正为逆时针。 - 需要连续下发维持运动;停止时发全 0。 ### 3.6 运动控制(速度指令) | Type | Command | 说明 | |---|---|---| | `0x00100001` | `0x00110002` | 真实物理量速度控制,**无响应帧** | ```json {"PatrolDevice":{"Type":1048577,"Command":1114114,"Time":"2026-01-01 00:00:00","Items":{"X":0.0,"Y":0.0,"Z":0.0,"Roll":0.0,"Pitch":0.0,"Yaw":0.0}}} ``` | 参数 | 含义 | 单位 | 范围 | |---|---|---|---| | `X` | 前后速度 | m/s | ±1.67 | | `Y` | 左右速度 | m/s | ±0.4 | | `Z` | 高度方向速度 | m/s | — | | `Roll` | 翻滚角速度 | rad/s | — | | `Pitch` | 俯仰角速度 | rad/s | — | | `Yaw` | 偏航角速度 | rad/s | ±1.0 | - 字段与轴指令完全相同,差别是**不做速度换算、原样下发执行端**,单位为物理量。 - **仅导航模式生效**,建议 10Hz 下发。 ### 3.7 自定义灯语 | Type | Command | 说明 | |---|---|---| | `0x00100005` | `0x00200002` | 分别设置头灯、尾灯的灯光模式/颜色/占空比 | | 参数 | 类型 | 取值 | |---|---|---| | `CustomMode` | bool | `true` 开启自定义 / `false` 关闭 | | `Led[0]` | object | 头灯 | | `Led[1]` | object | 尾灯 | | `Led[].Type` | int | `0` 常亮 / `1` 填充式流水 / `2` 移动式流水 / `3` 渐变式流水 / `4` 呼吸 / `5` 单色闪烁 | | `Led[].Color` | array\ | `0` 黑 / `1` 白 / `2` 绿 / `3` 蓝 | | `Led[].Cycle` | int | 占空比,单位 s;仅呼吸、闪烁模式使用 | ```json {"PatrolDevice":{"Type":1048581,"Command":2097154,"Time":"2026-01-01 00:00:00","Items":{"CustomMode":true,"Led":[{"Type":0,"Color":[1],"Cycle":1},{"Type":0,"Color":[2],"Cycle":1}]}}} ``` > 官方原文的 JSON 示例缺逗号、`"Led"` 后直接跟数组,不是合法 JSON;上面是修正后的可直接发送版本。 ### 3.8 自主充电 | Type | Command | 说明 | |---|---|---| | `0x00100004` | `0x00100002` | 控制自主充电 | | 参数 | 类型 | 取值 | |---|---|---| | `Charge` | int | `0` 结束充电 / `1` 开始充电 / `2` 清除充电状态、恢复空闲 | ```json {"PatrolDevice":{"Type":1048580,"Command":1048578,"Time":"2026-01-01 00:00:00","Items":{"Charge":1}}} ``` > `Charge=2` 会强制切断充电电流、状态归零并清除相关错误记录,**有风险,慎用**。 ### 3.9 运动 SDK 模式 | Type | Command | 说明 | |---|---|---| | `0x00100005` | `0x00300002` | 进入/退出 SDK 运动控制模式 | | 参数 | 类型 | 取值 | |---|---|---| | `SDKEnable` | bool | `true` 开启 / `false` 关闭 | | `Frequency` | int | 关节话题数据发布频率,[1, 200] 且能整除 1000 | ```json {"PatrolDevice":{"Type":1048581,"Command":3145730,"Time":"2026-01-01 00:00:00.000","Items":{"SDKEnable":true,"Frequency":100}}} ``` ### 3.10 休眠模式设置 | Type | Command | 说明 | |---|---|---| | `0x00100002` | `0x00400002` | 设置休眠/自动休眠 | | 参数 | 类型 | 取值 | |---|---|---| | `Sleep` | bool | `true` 进入休眠 / `false` 唤醒 | | `Auto` | bool | 到时间是否自动休眠 | | `Time` | uint(min) | 心跳断联后等待多久休眠 | ```json {"PatrolDevice":{"Type":1048578,"Command":4194306,"Time":"2026-01-01 00:00:00.000","Items":{"Sleep":false,"Auto":true,"Time":5}}} ``` --- ## 4. 遥控必须回读的状态 心跳建立后机器人主动上报。上报地址 = 最近发心跳的 IP:端口。 | 上报 | Type | Command | 频率 | 遥控关注点 | |---|---|---|---|---| | 基础状态 | `0x00100064` | `0x00f00000` | 2Hz | `MotionState`、`Gait`、`ControlUsageMode`、`HES`、`Charge` | | 运控状态 | `0x00100001` | `0x00f00000` | 10Hz | 实际速度、姿态、关节角,用于闭环 | | 设备状态 | `0x00100002` | `0x00f00000` | 2Hz | 电池、电机温度、外设使能 | | 异常状态 | `0x0010007f` | `0x00f00000` | 2Hz | 故障列表,状态变化时额外上报 | | 导航状态 | `0x00100003` | `0x00f00000` | 1Hz | 导航任务状态、定位状态 | ### 4.1 基础状态 `BasicStatus` | 字段 | 含义 | 取值 | |---|---|---| | `MotionState` | 运动状态 | `-2` 软急停 / `0` 默认 / `1` 站立 / `2` 关节阻尼 / `4` 趴下 / `5` 标零 / `17` RL 控制 / `0x1001` 阻尼趴下 | | `Gait` | 步态 | `0x1001` 基础 / `0x1002` 高台 / `0x3002` 平地(导航)/ `0x3003` 楼梯(导航) | | `HES` | 硬急停 | `0` 未触发 / `1` 已触发 | | `ControlUsageMode` | 使用模式 | `0` 常规 / `1` 导航 / `2` 辅助 | | `PowerManagement` | 电源模式 | `0` 常规 / `1` 单电池 | | `Sleep` | 休眠 | `0` 非休眠 / `1` 休眠 / `2` 进入休眠中 | | `Model` | 型号 | 如 `CD1` | | `Version` | 版本 | `STD` 标准 / `PRO` 增强 | | `Charge` | 充电状态 | `0x0000` 空闲 / `0x0001` 前往电桩 / `0x0002` 充电中 / `0x0003` 退出电桩 / `0x0004` 异常 / `0x0005` 在桩未充电 / `0x0006` 线充 | > 注意:步态上报里有 `0x1002` 高台,但《运动步态切换》指令表没列出 `0x1002`;下发时以指令表为准。 ### 4.2 运控状态 `MotionStatus`(10Hz,闭环用) | 字段 | 含义 | 单位 | |---|---|---| | `LinearX` / `LinearY` | 自身坐标系 x/y 线速度 | m/s | | `AngularZ` | yaw 角速度 | rad/s | | `Roll` / `Pitch` / `Yaw` | 姿态角 | rad | | `OmegaX/Y/Z` | IMU 三轴角速度 | rad/s | | `AccX/Y/Z` | 三轴加速度 | m/s² | | `Height` | 机身高度 | m | | `Payload` | 负载 | kg | | `RemainMile` | 预测剩余里程 | km | | `Gait` / `MotionState` | 当前步态 / 运动状态 | — | | `MotorStatus.Joint` | 16 关节角度数组 | rad | `MotorStatus.Joint` 顺序(16 个):LeftFrontHipX、LeftFrontHipY、LeftFrontKnee、LeftFrontWheel、RightFrontHipX、RightFrontHipY、RightFrontKnee、RightFrontWheel、LeftBackHipX、LeftBackHipY、LeftBackKnee、LeftBackWheel、RightBackHipX、RightBackHipY、RightBackKnee、RightBackWheel。 ### 4.3 异常状态 `ErrorList` 每组含 `Code`、`Name`、`Severities`(`3` WARN / `4` ERROR / `5` FATAL)、`Resources`、`Source`、`Timestamp`、`Type`(`1` 开始/等级变化,`2` 消除)。遥控常见故障码: | 码 | 含义 | 码 | 含义 | |---|---|---|---| | `0x8001` | 电机温度过高 | `0x8101` | 电池电量低 | | `0x8002` | 驱动器温度过高 | `0x8108` | 电池温度过高 | | `0x8014` | 关节位置超限 | `0x810A` | 放电电流过大 | | `0x8016` | 关节数据无效 | `0x8201` | IMU 发布超时/无更新 | | `0x8006` | 驱动器通信超时 | `0x8204` | IMU 数据无效 | | `0x8301` | CPU 温度过高 | `0x8304` | 可用内存过低 | --- ## 5. 通用返回与错误码 除轴指令、速度指令外,所有控制指令都会返回同 Type/Command 的通用状态响应: ```json {"PatrolDevice":{"Type":1048676,"Command":5,"Time":"2026-10-29 19:50:18.403","Items":{"ErrorCode":0,"ErrorMessage":"Success"}}} ``` | ErrorCode | ErrorMessage | 含义 | |---|---|---| | `0x0000` | Success | 成功 | | `0xE001` | Unsupported data format | 数据格式不支持(非 XML/JSON) | | `0xE002` | Data parsing failed | 解析失败(缺 PatrolDevice/Items/Type/Command) | | `0xE003` | Unsupported protocol type | 找不到 Type+Command 对应协议 | | `0xE004` | Missing necessary fields | 缺少必要字段 | | `0xE005` | Mismatched data type | 字段类型不匹配 | | `0xE006` | Mismatched request client | 请求客户端不匹配(如 2 秒内轴指令来自不同客户端) | | `0xE007` | No operation permission | 无操作权限 | | `0xE008` | Not allowed operation | 不允许的操作 | | `0xE009` | Operation failure | 操作失败 | | `0xE00A` | Unsupported function | 不支持的功能(如标准版不支持导航) | | `0xE00B` | Internal error | 内部错误 | > 实测返回里 `Items` 可能只带 `ErrorCode` 而不带 `ErrorMessage`,解析时两者都要兼容。 --- ## 6. 注意事项汇总 1. **心跳是前提**:≥1Hz,2 秒断流即关闭上报并需重连。 2. **mTLS 是强制的**:无客户端证书连不上;明文 TCP 直接被拒。 3. **JSON 数值必须写整数**,不能用文档示例里的 `0x0010 0064` 带空格写法。 4. **轴指令/速度指令没有响应帧**,必须靠状态上报验证;且 2 秒内必须同一客户端。 5. **轴指令 vs 速度指令**:轴指令 = [-1,1] 比例、常规/辅助模式;速度指令 = 物理量、仅导航模式。 6. **步态切换要停机**,否则被缓存延后执行。 7. **楼梯步态先进后退**:必须在进入楼梯前切到 `0x3003`,严禁楼梯上切换。 8. **基础步态只有 X/Y/Yaw 有效**,Z/Roll/Pitch 需要特殊步态。 9. **站立后模式差异**:ASDU 站立自动进 RL 控制;ROS2 话题站立需手动补 RL 控制。 10. **`Charge=2` 有风险**:强制断电、状态归零、清错误记录。 11. **导航功能仅 PRO 版**,标准版会返回 `0xE00A`。 12. 报文 ID 请求/响应同值,便于把异步上报与请求响应区分开。 --- ## 7. 配合 `send_adsu.py` 使用 `send_adsu.py` 已实现帧封装 + mTLS 连接,`--type/--command` 接受任意进制写法,`Items` 用 JSON 传入。 ```bash # 心跳 python3 send_adsu.py --type 0x00100064 --command 0x00000005 --items-json '{}' # 常规模式 python3 send_adsu.py --type 0x00100002 --command 0x00500002 --items-json '{"Mode":0}' # 站立 python3 send_adsu.py --type 0x00100001 --command 0x00200002 --items-json '{"MotionParam":1}' # 基础步态 python3 send_adsu.py --type 0x00100001 --command 0x00300002 --items-json '{"GaitParam":4097}' # 前进(轴指令,无响应,需脚本循环维持) python3 send_adsu.py --type 0x00100001 --command 0x00100002 \ --items-json '{"X":0.3,"Y":0.0,"Z":0.0,"Roll":0.0,"Pitch":0.0,"Yaw":0.0}' # 导航模式下的速度指令(m/s、rad/s) python3 send_adsu.py --type 0x00100001 --command 0x00110002 \ --items-json '{"X":0.5,"Y":0.0,"Z":0.0,"Roll":0.0,"Pitch":0.0,"Yaw":0.0}' # 趴下 python3 send_adsu.py --type 0x00100001 --command 0x00200002 --items-json '{"MotionParam":4}' ``` 脚本当前默认**不校验证书链**(根 CA 缺 keyUsage 扩展,Python 3.13+ 严格校验会拒绝);已用 `openssl s_client` 单独确认服务端证书可信。需要严格校验时加 `--verify`,但部分 Python 版本会失败。 > 做遥控闭环时不要每条指令新建连接:轴指令要求 2 秒内同一客户端,应在同一个 TLS 会话里循环发送,并同时读状态上报。