# R1 机器人 Ubuntu 开发快速入门指南

> 本文档面向直接在 Ubuntu 上进行 R1 二次开发的开发者，假设网络条件正常。

---

## 一、前提条件

| 项目 | 要求 |
|------|------|
| 操作系统 | Ubuntu 20.04+（推荐），22.04 经测试可用 |
| Python | 3.8+ |
| 网络 | 有线网线直连 R1 |
| 机器人状态 | 开机并进入开发者模式 |

---

## 二、硬件连接

### 2.1 网线直连

将 Ubuntu 电脑通过网线直接连接 R1 的 LAN 口。**必须使用有线连接**，R1 的 DDS 调试服务仅绑定在有线网卡上。

### 2.2 确认有线网卡

```bash
ip addr show
```

找到新接入的有线网卡，通常名字类似 `enx000e0988a670`、`eth0`、`enp0s31f6` 等。

### 2.3 配置静态 IP

将电脑有线网卡配置到 `192.168.123.x` 网段：

```bash
sudo ip addr add 192.168.123.99/24 dev 你的网卡名
sudo ip link set 你的网卡名 up
```

### 2.4 测试连通性

```bash
ping 192.168.123.161
```

R1 机载电脑默认有线 IP 为 `192.168.123.161`，ping 通即可继续。

---

## 三、安装 Python SDK

### 3.1 克隆 SDK

```bash
cd ~
git clone https://github.com/unitreerobotics/unitree_sdk2_python.git
```

或直接使用已有的源码包。

### 3.2 安装依赖

```bash
cd unitree_sdk2_python
pip3 install .
```

这会安装 `cyclonedds==0.10.2`、`numpy`、`opencv-python` 等依赖。

### 3.3 验证安装

```bash
python3 -c "from unitree_sdk2py.idl.unitree_hg.msg.dds_ import LowState_; print('SDK OK')"
```

---

## 四、配置 DDS

创建 CycloneDDS 配置文件，指定使用有线网卡和 R1 的 IP：

```bash
cat > ~/cyclonedds.xml << 'EOF'
<?xml version="1.0" encoding="UTF-8" ?>
<CycloneDDS xmlns="https://cdds.io/config" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="https://cdds.io/config https://raw.githubusercontent.com/eclipse-cyclonedds/cyclonedds/master/etc/cyclonedds.xsd">
    <Domain id="0">
        <General>
            <NetworkInterfaceAddress>你的网卡名</NetworkInterfaceAddress>
        </General>
        <Discovery>
            <Peers>
                <Peer address="192.168.123.161"/>
            </Peers>
        </Discovery>
    </Domain>
</CycloneDDS>
EOF
```

> 将 `你的网卡名` 替换为实际的有线网卡名，如 `enx000e0988a670`。

---

## 五、读取机器人数据

### 5.1 编写读取脚本

```python
import os
import sys
import time

os.environ["CYCLONEDDS_URI"] = "file:///home/你的用户名/cyclonedds.xml"

from unitree_sdk2py.core.channel import ChannelFactoryInitialize, ChannelSubscriber
from unitree_sdk2py.idl.unitree_hg.msg.dds_ import LowState_

counter = 0

def LowStateHandler(msg: LowState_):
    global counter
    counter += 1
    if counter % 100 == 0:
        print(f"\n=== Frame {counter} ===")
        print(f"IMU RPY: {msg.imu_state.rpy}")
        motor_count = len(msg.motor_state)
        print(f"Motor count: {motor_count}")
        for i in range(min(3, motor_count)):
            print(f"Motor {i}: q={msg.motor_state[i].q:.4f}, dq={msg.motor_state[i].dq:.4f}")

if __name__ == "__main__":
    print("Connecting to R1...")
    ChannelFactoryInitialize(0, "你的网卡名")
    
    subscriber = ChannelSubscriber("rt/lowstate", LowState_)
    subscriber.Init(LowStateHandler, 10)
    
    print("Subscribed! Waiting for data... (Ctrl+C to stop)")
    while True:
        time.sleep(1)
```

### 5.2 运行

```bash
export CYCLONEDDS_URI=file:///home/你的用户名/cyclonedds.xml
python3 read_r1.py
```

---

## 六、预期输出

正常运行时，每 100 帧打印一次：

```
Connecting to R1...
Subscribed! Waiting for data... (Ctrl+C to stop)

=== Frame 100 ===
IMU RPY: [0.0062, -0.0751, 0.0130]
Motor count: 35
Motor 0: q=0.0199, dq=0.0031
Motor 1: q=-0.0064, dq=-0.0031
Motor 2: q=0.0000, dq=0.0000
```

- **IMU RPY**：机器人当前姿态（Roll/Pitch/Yaw）
- **Motor count**：R1 共 35 个关节电机
- **q**：关节角度（弧度）
- **dq**：关节角速度

---

## 七、关键知识点

### 7.1 为什么必须网线直连？

R1 的 DDS 调试服务和 SSH 仅绑定在有线网卡（`192.168.123.161`）。WiFi 接口（`192.168.0.63`）上没有开放这些服务。

### 7.2 如何进入开发者模式？

使用遥控器，**同时按下 `L2 + R2`** 键。机器人进入开发者模式后才会通过 DDS 发布底层数据。

### 7.3 R1 使用什么消息类型？

R1 使用 `unitree_hg`（humanoid general）接口，与 G1 兼容：

| Topic | 类型 | 说明 |
|-------|------|------|
| `rt/lowstate` | `LowState_` | 底层状态（关节、IMU、电量） |
| `rt/lowcmd` | `LowCmd_` | 底层控制指令 |

### 7.4 帧率

正常情况下，数据帧率约为 **500~1000 Hz**，取决于网络状况和机器人负载。

---

## 八、常见问题

### Q1: ping 不通 192.168.123.161
- 确认网线已插紧，R1 已开机
- 确认电脑网卡已正确配置 IP（`192.168.123.99/24`）
- 尝试更换网线或网口

### Q2: 运行后没有数据
- 确认 R1 已进入开发者模式（遥控器 L2+R2）
- 确认 `cyclonedds.xml` 中的网卡名正确
- 确认 `CYCLONEDDS_URI` 环境变量已设置

### Q3: pip install 报错
- 确保 Python 版本 >= 3.8
- 如缺少编译工具，先安装：`sudo apt install python3-pip cmake build-essential`

---

## 九、下一步

| 方向 | 说明 |
|------|------|
| 读取全部关节 | 修改脚本遍历 `msg.motor_state` 打印 35 个电机 |
| 读取其他 topic | 如视频流 (`rt/videodata`)、遥控器数据等 |
| 下发控制指令 | 通过 `rt/lowcmd` Topic 控制关节运动（⚠️ 先悬挂机器人） |
| SSH 进机器人 | `ssh unitree@192.168.123.161`（密码需尝试 unitree/123/000000） |
| 修改机器人 IP | 将 R1 有线网卡改为 DHCP，接入路由器统一管理 |

---

## 参考文档

- [宇树官方文档](https://support.unitree.com/home/zh/R1_developer/quick_development)
- [unitree_sdk2_python GitHub](https://github.com/unitreerobotics/unitree_sdk2_python)
