Metadata-Version: 2.4
Name: robot-console-cli
Version: 1.0.0
Summary: 机器人控制台（robot-console）连接器的 CLI 执行体：用命令行控制宇树 Unitree 人形与四足机器人
License-Expression: LicenseRef-Proprietary
Keywords: unitree,robot,humanoid,quadruped,g1,go2,h1,b2,dds,robotics,embodied-ai
Classifier: Programming Language :: Python :: 3
Classifier: Operating System :: MacOS
Classifier: Operating System :: POSIX :: Linux
Classifier: Operating System :: Microsoft :: Windows
Classifier: Topic :: System :: Hardware
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: cyclonedds>=0.10

# robot-console-cli

WorkBuddy「机器人控制台」连接器的 CLI 执行体。通过 DDS 在**本地局域网**控制人形 / 四足机器人，不经云端。

## 安装

一条命令，**无需 C 编译器、无需访问 GitHub**：

```bash
python -m pip install robot-console-cli
```

会自动带上 DDS 绑定 `cyclonedds`（PyPI 有各平台预编译包）。
Unitree 官方机器人驱动**已内嵌在包内**（`robot_console/_vendor/unitree_sdk2py`，BSD-3），
因此不需要另行安装 SDK。

覆盖平台：macOS（Intel / Apple Silicon）、Linux（x86_64）、Windows（x86_64）。

> 想接官方仿真器 `unitree_mujoco` 或低层开发，才需要额外装官方 SDK——本连接器不需要。

## 命令

| 命令 | 级别 | 说明 |
|---|---|---|
| `robot-console list` | L0 | 列出已发现与已绑定的机器人 |
| `robot-console status --robot NAME` | L0 | 查询实时状态（含分层通信诊断） |
| `robot-console status --check --quiet` | L0 | 仅输出 `bound` / `no_robot`（供平台轮询） |
| `robot-console doctor` | L0 | 环境与连通性自检（含手臂动作表核对） |
| `robot-console bind --auto` | — | 自动发现并绑定（DDS 探活通过才允许绑定） |
| `robot-console unbind --all` | — | 清除绑定 |
| `robot-console say --robot NAME --text "..."` | L1 | 语音播报（人形机型） |
| `robot-console pose --robot NAME --pose stand\|sit\|recover` | L1 | 切换姿态 |
| `robot-console action --robot NAME --name wave\|heart\|shake_hand` | L2 | 预设动作（仅人形） |
| `robot-console move ...` | L2 | 移动（v1.0 默认关闭） |
| `robot-console estop --robot NAME` | L3 | 急停，任何状态可用 |
| `robot-console config --enable-move` | — | 开启移动能力开关 |
| `robot-console config --set-fsm G1:stand=4` | — | 站点级 FSM 标定 |
| `robot-console sim --start / --stop` | — | 起停本地假机器人 |
| `robot-console verify --contract g1-v1` | — | 核对实际发出的 DDS 报文 |

所有命令支持 `--json` 输出。

### 全局参数

| 参数 | 说明 |
|---|---|
| `--backend auto\|mock\|unitree\|sim` | 后端选择。默认 `auto`（真机） |
| `--domain N` | DDS 域。**真机 0，仿真 1**。不填时按后端取默认值 |
| `--iface NAME` | DDS 网卡，如 `eth0` / `lo`。默认交给 DDS 自动选择 |

## 三层通信与 `status` 输出

`status` 会分层报告，一眼看出卡在哪一层：

```
G1-01（G1）：在线，姿态 站立就绪
通信层：dds_lowstate√，rpc√
```

| 层 | 通道 | 含义 |
|---|---|---|
| `dds_lowstate` | 订阅 `rt/lowstate` | 链路是否通（有没有心跳） |
| `dds_sportmode` | 订阅 `rt/sportmodestate` | 仅四足有 |
| `rpc` | `rt/api/{service}/request` | 高层语义（读回 FSM 等） |

## 无真机验证

有**两条**路，互补覆盖。

### 路一：纯逻辑验证（`--backend mock`，零依赖）

```bash
robot-console --backend mock bind --auto
robot-console --backend mock pose --robot G1-01 --pose stand
robot-console --backend mock estop --robot G1-01
```

> 从源码目录直接跑时，才需要 `PYTHONPATH=src`（Windows：`set PYTHONPATH=src`）。

> mock 后端的状态只存在于单次进程内，不跨命令持久化；因此每次调用看到的是全新的模拟状态。

### 路二：本地假机器人（`--backend sim`，真 DDS，走真机后端代码）

在单机内实现 `sport` / `arm` / `voice` 三个 RPC 服务端 + 遥测发布，
**走的是 `backends/unitree.py` 这份真机后端代码**，只差 DDS 域号。

```bash
robot-console sim --start --model G1        # 起假机器人（DDS 域 1）
robot-console --backend sim bind --auto
robot-console --backend sim status --robot G1-01
robot-console --backend sim pose --robot G1-01 --pose stand
robot-console --backend sim say  --robot G1-01 --text "大家好"
robot-console --backend sim action --robot G1-01 --name wave
robot-console --backend sim estop --robot G1-01
robot-console verify --contract g1-v1       # 核对实际发出的报文
robot-console sim --stop
```

**故障注入**（真机上几乎无法稳定复现）：

```bash
robot-console sim --start --fault 7101=7302
robot-console --backend sim pose --robot G1-01 --pose stand
# → 错误：[7302] 无效的 FSM ID
```

### 一键全量验证

```bash
python tests/offline_e2e.py --model G1
python tests/offline_e2e.py --model GO2
```

会依次完成：起桩 → 发现绑定 → 三层状态 → 按契约跑全部命令 → 契约核对 →
护栏校验（拦截 / 限速 / 幂等 / 标定）→ 故障注入 → `doctor`，最后给出通过率。

### 也支持官方仿真器 `unitree_mujoco`

同一个 `--backend sim` 也能连官方仿真器（域 1 + 回环），无需改配置：

```bash
cd unitree_mujoco/simulate_python && python3 unitree_mujoco.py
robot-console --backend sim bind --auto      # L1/L2 通过
```

> 官方仿真器只仿**低层**（`rt/lowcmd` / `rt/lowstate`），**不实现内置高层服务**，
> 因此 `pose` / `say` / `action` 会返回 `3104` 超时或 `3203` 未实现——这是预期行为。
> 高层语义请用上面的本地假机器人验证。

## 真机注意

- FSM 编号与动作 ID 已**逐行对照官方源码定案**，见 `src/robot_console/constants.py`。
- 不同固件的 FSM 编号可能漂移（社区实测 G1 的"站立"出现过 `4` 与 `500`）。
  现场用 `config --set-fsm G1:stand=4` 标定即可，**不需要改代码**。
- 机器人若处于调试模式，内置运控退出，高层接口会失效。
- `ChannelFactory` 是**进程级单例**，一个进程只能连一个 DDS 域；
  要同时连真机（域 0）与仿真器（域 1），必须拆成两个进程。

## 目录与安全

- 配置、审计日志默认落在 `~/.robot-console/`（可用 `ROBOT_CONSOLE_CONFIG_DIR` 覆盖）。
- 所有控制指令写入 `audit.jsonl`，敏感字段自动脱敏。
- 硬约束：`duration` 0.5–3 s，线速度 ≤0.5 m/s，角速度 ≤0.5 rad/s，越界直接拒绝而非截断。
- 高风险命令（`move` / `action`）带幂等键，避免重试造成重复动作。
- 全部通信在本地局域网内完成，**不经云端**。
