# so101 **Repository Path**: zzuos/so101 ## Basic Information - **Project Name**: so101 - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-09-22 - **Last Updated**: 2026-09-24 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # SO101 ROS 2 环境安装 ## 合并后的统一入口 本目录已经把原 `so101` 启动/硬件节点和 `lerobot_so101-main` 的安全点动、串口检查、回归测试及训练检查能力合并为一个工作区。图形界面统一使用 PySide6 Qt,不再使用 Tkinter。 ```bash ./so101_check.sh # 检查 Python、ROS、串口和校准文件 ./so101_start.sh follower # 启动 Follower(主动运动前按提示确认) ./so101_gui.sh # 打开 Qt 六关节点动界面 ./so101_control.sh # 单客户端启动 Follower 和 Qt 控制器 ./so101_jog.sh shoulder_pan 2 --dry-run # 先预览安全点动目标 ./so101_jog.sh shoulder_pan 2 # 执行小步点动 ``` `lerobot_leader.sh`、`run_single_arm.sh` 和 `run_gui.sh` 仍保留为兼容入口;原有校准、双相机、关节合并、远程推理和 ROS launch 文件也继续保留。首次部署可运行 `install_so101_dependencies.sh`,它会从本目录的 `lerobot/` 源码安装 PySide6、LeRobot/Feetech 依赖并构建 ROS 包。 以下步骤适用于 Ubuntu 22.04(ROS 2 Humble)。Miniconda 安装包示例使用 Linux `aarch64` 架构;如果是其他架构,请从 Miniconda 官网选择对应安装包。 ## 1. 设置系统语言环境 ```bash sudo apt update sudo apt install -y locales sudo locale-gen en_US en_US.UTF-8 sudo update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8 export LANG=en_US.UTF-8 locale ``` ## 2. 安装 ROS 2 Humble ```bash sudo apt install -y software-properties-common sudo add-apt-repository universe sudo apt update sudo apt install -y curl export ROS_APT_SOURCE_VERSION=$(curl -s https://api.github.com/repos/ros-infrastructure/ros-apt-source/releases/latest \ | grep -F "tag_name" \ | awk -F'"' '{print $4}') echo "ROS_APT_SOURCE_VERSION=${ROS_APT_SOURCE_VERSION}" curl -L -o /tmp/ros2-apt-source.deb \ "https://github.com/ros-infrastructure/ros-apt-source/releases/download/${ROS_APT_SOURCE_VERSION}/ros2-apt-source_${ROS_APT_SOURCE_VERSION}.$(. /etc/os-release && echo ${UBUNTU_CODENAME:-${VERSION_CODENAME}})_all.deb" sudo dpkg -i /tmp/ros2-apt-source.deb sudo apt update sudo apt install -y ros-humble-desktop ``` 每个新终端使用 ROS 2 前加载环境: ```bash source /opt/ros/humble/setup.bash ``` ## 3. 安装 Miniconda ```bash sudo apt install -y wget wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-aarch64.sh bash Miniconda3-latest-Linux-aarch64.sh ``` 安装程序完成后初始化当前 Shell: ```bash eval "$(/root/miniconda3/bin/conda shell.bash hook)" conda init bash source ~/.bashrc conda config --set auto_activate_base false ``` ## 4. 安装 LeRobot 和 Feetech SDK 本目录已经内置 `lerobot/` 源码和 `.venv/` 虚拟环境,不需要再单独克隆或安装到 工作区外。首次部署直接运行: ```bash ./install_so101_dependencies.sh ``` 以后每个新终端执行: ```bash cd /path/to/so101 source so101_env.sh ``` ## 5. 构建本 SO101 ROS 2 工作区 将本项目克隆到本机后,在工作区根目录构建: ```bash git clone git@gitee.com:zzuos/so101.git cd so101 ./install_so101_dependencies.sh source so101_env.sh ``` 如果项目目录已经存在,直接执行: ```bash cd /path/to/so101 source so101_env.sh python -m colcon build --symlink-install --base-paths src source install/setup.bash ``` ## 6. 使用双 Leader 启动脚本 项目根目录提供 `lerobot_leader.sh`,用于同时启动左右两路 SO101 Leader: ```bash cd /root/so101/xlz bash lerobot_leader.sh ``` 脚本当前连接以下设备和校准文件: ```text 左 Leader: /dev/lerobot_left -> jz_left 右 Leader: /dev/lerobot_right -> jz_right ``` 两路 Leader 当前都会为 `wrist_roll` 增加 `-90°`: ```text -p joint_offsets.wrist_roll:=-90.0 ``` 脚本会把日志写入 `/root/start_logs/`,按 `Ctrl+C` 会停止两个 Leader 进程组。 脚本中的工作区路径是 `/root/so101/xlz`;如果项目放在其他目录,需要同步修改脚本中的 `source`、`cd` 路径。设备名和校准文件也应根据实际硬件修改。启动前确认两个串口没有被 其他进程占用。 # SO101 ROS 2 工作区项目说明 这是整理后的 SO101 Colcon 工作区。所有活动程序集中在唯一的 `so101` 功能包中;旧版 XLeRobot、实验脚本和原始配置保存在 `archive/`,不会参与构建。 ## 目录结构 ```text ├── src │ └── so101 # 全部 SO101 节点、工具、launch 和配置 ├── lerobot # 内置 LeRobot 源码 ├── .venv # 本项目 Python 依赖环境 ├── docs # 历史说明文档 ├── archive # 旧代码,仅供查阅 ├── build # colcon 生成,不纳入源码 ├── install # colcon 生成,不纳入源码 └── log # colcon 生成,不纳入源码 ``` ## 环境和构建 LeRobot 安装在 `lerobot` Conda 环境中,ROS 2 使用 Humble。每个新终端按以下顺序初始化: ```bash source /root/miniconda3/etc/profile.d/conda.sh conda activate lerobot source /opt/ros/humble/setup.bash ``` 首次构建或修改代码后执行: ```bash cd python -m colcon build --symlink-install source install/setup.bash ``` 不要用一个自定义 `PYTHONPATH` 覆盖 ROS 2 的 Python 路径。当前机械臂节点依赖 LeRobot 0.4.x 中的 `lerobot.robots.so101_follower`。 ## SO101 校准 校准程序 `jizozhun` 使用与官方 `SO101Follower.calibrate()` 相同的中心偏移、范围记录、校准写入和 JSON 保存操作,并提供中文分步提示。它输出完整的 LeRobot SO101 校准 JSON,而不是旧版自定义偏移量文件。直接启动且不传参数时会进入中文交互菜单,可以选择自动发现的串口并输入校准文件名: ```bash ros2 run so101 jizozhun ``` 确认设备和文件名后,程序进入 LeRobot 官方的两个校准步骤:先把所有关节放在各自行程的中间位置并按 Enter;然后依次让每个关节走过正反两个方向的完整安全行程,全部完成后再按 Enter 保存。 新电机第一次使用时,先按 LeRobot 的 SO101 文档设置电机 ID: ```bash lerobot-setup-motors --robot.type=so101_follower --robot.port=/dev/ttyACM0 ``` 也可以跳过菜单,直接用参数校准左臂: ```bash ros2 run so101 jizozhun -- \ --port /dev/ttyACM0 \ --id s101_left ``` 校准右臂: ```bash ros2 run so101 jizozhun -- \ --port /dev/ttyACM1 \ --id s101_right ``` 新增机械臂时必须使用新的唯一 ID,例如: ```bash ros2 run so101 jizozhun -- \ --port /dev/serial/by-id/你的设备 \ --id s101_test_01 ``` 默认校准目录是功能包源码中的 `config`: ```text config/ ``` 目录中的校准 JSON 会在构建时安装到 `share/so101/config`,因此复制 `src/so101` 到新工作区后重新构建即可继续使用。 如果同 ID 文件已经存在,程序会拒绝覆盖。确认要重新校准时增加 `--overwrite`,旧 JSON 会先保存成带时间戳的备份。校准期间必须停止所有占用该串口的节点,并手扶机械臂缓慢走过每个关节的安全全行程。 ## 主从臂遥操作 主臂和从臂现在使用同一个可执行程序 `so101_arm`。每次启动必须依次提供四个参数: ```text 0: role leader(主臂)或 follower(从臂) 1: port 本次连接的串口设备 2: group 主从组名,只允许字母、数字和下划线 3: calibration_file 校准 ID、JSON 文件名或完整 JSON 路径 ``` 默认 launch 配置: | 角色 | 节点 | 串口 | 组 | 校准 ID | 行为 | |---|---|---|---|---|---| | 右臂 Leader | `so101_arm` | `/dev/ttyACM1` | `default` | `s101_right` | 关闭力矩,手动拖动并发布状态 | | 左臂 Follower | `so101_arm` | `/dev/ttyACM0` | `default` | `s101_left` | 接收同组命令并主动跟随 | 一条命令启动: ```bash ros2 launch so101 so101_teleoperation.launch.py ``` 串口、组名或校准文件不同的启动示例: ```bash ros2 launch so101 so101_teleoperation.launch.py \ group:=arm_a \ leader_port:=/dev/ttyACM3 leader_calibration:=s101_leader_new \ follower_port:=/dev/ttyACM2 follower_calibration:=s101_follower_new \ max_relative_target:=8.0 ``` 也可以分别启动: ```bash ros2 run so101 so101_arm -- \ leader /dev/ttyACM1 arm_a s101_right ros2 run so101 so101_arm -- \ follower /dev/ttyACM0 arm_a s101_left \ --ros-args \ -p max_relative_target:=10.0 ``` Leader 发布前可以为前五个旋转关节设置角度偏移。例如让 `wrist_roll` 的发布值增加 `90°`: ```bash ros2 run so101 so101_arm -- \ leader /dev/ttyACM1 arm_a s101_right \ --ros-args \ -p joint_offsets.wrist_roll:=90.0 ``` 可用参数为 `joint_offsets.shoulder_pan`、`joint_offsets.shoulder_lift`、 `joint_offsets.elbow_flex`、`joint_offsets.wrist_flex` 和 `joint_offsets.wrist_roll`。默认都是 `0.0°`。非零偏移后的结果会折返到 `[-180, 180)`,例如 `175° + 10° = -175°`。`gripper` 是 `0..100` 开合百分比,不支持角度偏移。该功能只对 Leader 有效,偏移后的话题值会 被 Follower 当作真实运动目标。 校准参数也可以使用完整路径: ```bash ros2 run so101 so101_arm -- \ follower /dev/ttyACM0 arm_a \ config/s101_left.json ``` 主从链路为: ```text SO101 Leader (group=arm_a) -> /so101/arm_a/leader_joint_states (sensor_msgs/JointState) -> SO101 Follower -> /so101/arm_a/follower_joint_states (sensor_msgs/JointState) ``` 不同组自动使用不同话题。例如 `arm_a` 使用 `/so101/arm_a/...`,`arm_b` 使用 `/so101/arm_b/...`,两套主从臂不会互相接收命令。两个节点都按以下固定顺序处理六个关节:`shoulder_pan`、`shoulder_lift`、`elbow_flex`、`wrist_flex`、`wrist_roll`、`gripper`。Follower 会按消息中的关节名重新排序,并使用 `max_relative_target` 限制单次目标变化。 ## 状态合并 ```bash ros2 run so101 joint_state_combiner_node --ros-args \ -r /left_arm_joint_states:=/so101/arm_a/follower_joint_states ``` 它以 40 Hz 组合以下数据: | 输入 | 输出 | 内容 | |---|---|---| | `/left_arm_joint_states` + `/velocity` | `/joint_states` | 六个 SO101 关节和三项实测底盘速度 | | `/left_arm_joint_states` + `/cmd_vel` | `/joint_states_action` | 六个 SO101 关节和三项底盘命令 | 收到第一条 `/cmd_vel` 之前,动作中的三项底盘速度为零。 ## 远程推理 机器人端常用进程: ```bash ros2 run so101 dual_camera_publisher ros2 run so101 joint_state_combiner_node --ros-args \ -r /left_arm_joint_states:=/so101/arm_a/follower_joint_states ros2 run so101 action_splitter --ros-args \ -r /right_arm_joint_states:=/so101/arm_a/leader_joint_states ros2 run so101 remote_inference_client -- \ --host 192.168.1.100 --port 5555 --task '单臂抓取物体。' ``` GPU 推理服务器: ```bash ros2 run so101 remote_inference_server -- \ --model /path/to/pretrained_model \ --tokenizer /path/to/paligemma-tokenizer \ --host 0.0.0.0 --port 5555 --gpu-id 0 ``` 需要中继机器时: ```bash ros2 run so101 remote_inference_relay -- \ --listen-port 6666 \ --inference-host 192.168.1.100 --inference-port 5555 ``` 推理控制链路: ```text /ca1, /ca2, /joint_states -> remote_inference_client -> TCP 推理服务器 -> /joint_ctrl_cmd -> action_splitter -> /right_arm_joint_states + /cmd_vel -> SO101 Follower + 移动底盘 ``` 推理模式下不要同时启动同组 Leader,因为 remap 后的 `action_splitter` 和该 Leader 都会发布 `/so101//leader_joint_states`。双摄像头程序当前使用 `/dev/video0` 和 `/dev/video2`,发布 `/ca1` 和 `/ca2`。图像转换直接使用 `sensor_msgs/Image` 和 NumPy,不依赖与当前 NumPy 2.x 不兼容的 ROS Humble `cv_bridge` 二进制扩展。 `joint_state_combiner_node` 和 `action_splitter` 内部仍保留原来的固定话题;接入分组机械臂时必须像上面的示例一样使用 ROS remap。多套完整推理链路还需要分别 remap `/joint_states`、`/joint_states_action`、`/joint_ctrl_cmd` 和 `/cmd_vel`,避免不同组之间共享控制数据。 ## 安全要求 1. 启动 Follower 前确认校准 ID 与实际机械臂严格对应,禁止混用另一台机械臂的校准文件。 2. 第一次测试时将 `max_relative_target` 设小,降低动作幅度,并保持低速。 3. 机械臂工作区不得有人或障碍物,操作者必须能立即断电或急停。 4. Leader 启动后会关闭自身力矩;Follower 启动后会主动输出力矩,二者不可接反。 5. 一个串口同一时间只能由一个进程占用。 6. AI 推理输出会直接进入 Follower 和底盘,接入实体硬件前先检查话题数据范围和方向。 ## 旧代码 `archive/legacy_xlerobot_package` 保存原硬件包及实验节点,`archive/loose_scripts` 保存原工作区根目录脚本,`archive/workspace_metadata` 保存原编辑器配置。这些内容没有放入 `src`,因此不会被 Colcon 发现。 `docs/legacy_teleoperation.md` 和 `docs/moveit_interactive_markers.md` 是原项目文档,描述的部分 XLeRobot 文件名、模型和路径已经过时,仅供历史参考。