GELLO Franka FR3 ROS2 环境搭建与开发指南
参考:https://github.com/wuphilipp/gello_software/blob/main/ros2/README.md
适用:Franka FR3 机械臂 + GELLO 遥操作手臂
1. 项目概述
本项目提供 GELLO 遥操作手臂 与 Franka FR3 机械臂 之间的完整 ROS2 接口。
核心功能
功能模块 | 说明 |
GELLO 状态发布 | 读取 Dynamixel 舵机角度,发布为 ROS2 话题 |
关节阻抗控制 | 订阅 GELLO 状态,转换为 FR3 力矩指令 |
夹爪管理 | 支持 Franka Hand 和 Robotiq 2F-85 两种夹爪 |
硬件组成
GELLO 单臂版:
├─ 7 个 Dynamixel XL330-M288 舵机(7 DOF)
├─ U2D2 或 OpenRB-150 通信板
└─ Franka Hand 或 Robotiq 2F-85 夹爪
GELLO 双臂版(Duo):
├─ 2 × 7 = 14 个 Dynamixel 舵机
├─ 2 个通信板
└─ 双臂协同控制
硬件连线:单臂版本

2. 环境搭建
方式一:VS Code Dev Container(⭐ 推荐)
最适合:快速上手,环境一致,避免依赖地狱。
步骤
1. 打开项目
用 VS Code 打开 gello_software 仓库中的 ros2/ 子文件夹
(注意:不是整个 gello_software 文件夹)
2. 启动容器
- 如果弹出提示:「Reopen in Container」 → 点击确认
- 如果没有提示:按 Ctrl+Shift+P → 输入 Dev Containers: Reopen in Container

3. 等待构建
- 第一次构建需要几分钟(自动安装所有依赖)
- 构建完成后,终端自动进入容器环境
⚠️ 注意事项
● 版本匹配:Dev Container 中的libfranka、franka_ros2、franka_description版本需要与你的 Franka 机器人系统版本匹配。
● 修改版本:如果需要调整版本,编辑ros2/.devcontainer/Dockerfile中的版本参数。
● 兼容性文档:参考Franka 官方兼容性表
方式二:本地安装
最适合:需要深度定制,或无法使用 Docker 的环境。
前置依赖
依赖项 | 安装指南 |
ROS2 Humble Desktop | 官方安装教程 |
libfranka | Franka 官方文档 |
franka_ros2 | 同上(注意版本匹配) |
ros2_robotiq_gripper | GitHub 仓库 |
Cyclone DDS | ROS2 RMW 文档 |
安装示例(参考 Dockerfile)
# 这些命令可以从 ros2/.devcontainer/Dockerfile 中复制
# 根据你的系统环境调整路径和版本
# 示例:安装 libfranka
cd ~
git clone --branch 0.15.0 https://github.com/frankarobotics/libfranka.git
cd libfranka
mkdir build && cd build
cmake .. -DCMAKE_BUILD_TYPE=Release
make -j$(nproc)
sudo make install
# 安装 franka_ros2
mkdir -p ~/franka_ws/src
cd ~/franka_ws/src
git clone --branch humble https://ghfast.top/https://github.com/frankarobotics/franka_ros2.git
cd ..
rosdep install --from-paths src --ignore-src -r -y
colcon build --symlink-install
安装工作区依赖
# 进入 ros2 工作区
cd ~/projects/ros2Gello/gello_software/ros2
# 运行依赖安装脚本
bash install_workspace_dependencies.bash
▎ 提示:如果添加了新依赖,记得更新 requirements.txt、requirements_dev.txt 或 package.xml,然后重新运行脚本。
3. 快速开始
场景 A:预组装 Franka GELLO 单臂版(带 Franka Hand)
配置步骤
1. 修改配置文件
- franka_gello_single.yaml → 设置 com_port
- example_fr3_config_franka_hand.yaml → 设置 com_port
- example_fr3_config.yaml → 设置 robot_ip
2. 启动命令
# 【重要】如果使用 Dev Container,/workspace/ 就是 ros2/ 文件夹
# 本地安装请把 /workspace/ 替换成你的 gello_software 路径
# Step 1: 进入工作区,构建,加载环境
cd ~/projects/ros2Gello/gello_software/
colcon build
source install/setup.bash
# Step 2: 启动 GELLO 节点(读取手柄状态)
ros2 launch franka_gello_state_publisher main.launch.py config_file:=franka_gello_single.yaml
# Step 3: 启动 Franka Hand 夹爪节点
ros2 launch franka_gripper_manager franka_gripper_client.launch.py config_file:=example_fr3_config_franka_hand.yaml
# Step 4: 启动机器人控制器
# 【注意】先握住 GELLO 手柄,放在舒适位置(距离底座一定距离)
# 启动后机器人会直接同步到 GELLO 的当前位置
# 同步过程中不要突然移动 GELLO,避免机器人剧烈动作
ros2 launch franka_fr3_arm_controllers franka_fr3_arm_controllers.launch.py robot_config_file:=example_fr3_config.yaml
场景 B:预组装 Franka GELLO Duo 双臂版(带 Robotiq 夹爪)
配置步骤
1. 修改配置文件
- franka_gello_duo.yaml → 设置 com_port(两个手柄需要两个端口)
- example_fr3_duo_config_robotiq.yaml → 设置 com_port
- example_fr3_duo_config.yaml → 设置 robot_ip
2. 启动命令
cd ~/projects/ros2Gello/gello_software/ros2/
colcon build
source install/setup.bash
# 启动两个 GELLO 手柄
ros2 launch franka_gello_state_publisher main.launch.py config_file:=franka_gello_duo.yaml
# 启动 Robotiq 夹爪
ros2 launch franka_gripper_manager robotiq_gripper_controller_client.launch.py config_file:=example_fr3_duo_config_robotiq.yaml
# 启动机器人控制器(双臂)
# 【注意】双手握住 GELLO 手柄,放在舒适位置
ros2 launch franka_fr3_arm_controllers franka_fr3_arm_controllers.launch.py robot_config_file:=example_fr3_duo_config.yaml
4. 详细启动流程
4.1 启动 GELLO 发布器
Step 1:确定通信端口 ID
# 插入 U2D2 或 OpenRB-150 后运行
ls /dev/serial/by-id
输出示例:
# U2D2:
usb-FTDI_USB__-__Serial_Converter_FT7WBG6
# OpenRB-150:
usb-ROBOTIS_OpenRB-150_2B375CB3503059384C2E3120FF053624-if00
记录这个 ID,后面要填到配置文件中。
Step 2:校准装配偏移(仅自制 GELLO 需要)
▎ ⚡ 跳过此步骤的条件:
- 使用官方预组装的 "Franka GELLO" 或 "Franka GELLO Duo"
- 严格按照官方组装指南装配
▎ 满足以上条件,可以直接用 franka_gello_state_publisher/config/ 里的默认配置文件。
如果是自己组装的 GELLO,需要确定以下参数:
参数 | 说明 | 默认值(官方组装) |
joint_signs | 每个关节的方向符号(1 或 -1) | 1 -1 1 -1 1 1 1 |
assembly_offsets | 装配偏移(由于 Dynamixel 法兰有 4 种安装方向,可能需要 ±90° 偏移) | 0 0 0 0 0 0 0 |
gripper_range_rad | 夹爪开合对应的关节角度范围 | 根据组装确定 |
使用校准脚本:
# 进入脚本目录
cd ~/projects/ros2Gello/gello_software/ros2/src/franka_gello_state_publisher/scripts/
# 单臂 GELLO 校准
python3 get_offsets.py \ --start-joints 0 0 0 -1.57 0 1.57 0 \ --joint-signs 1 -1 1 -1 1 1 1 \ --port /dev/serial/by-id/<你的端口ID>
# 双臂左臂校准
python3 get_offsets.py \ --start-joints -1.57 -0.80 1.80 -3.00 1.40 1.50 -2.10 \ --joint-signs 1 -1 1 -1 1 1 1 \ --port /dev/serial/by-id/<你的端口ID>
# 双臂右臂校准
python3 get_offsets.py \ --start-joints 1.57 -0.80 -1.80 -3.00 -1.40 1.50 2.10 \ --joint-signs 1 -1 1 -1 1 1 1 \ --port /dev/serial/by-id/<你的端口ID>
校准姿势参考:
单臂:参见

双臂:参见

脚本输出:会显示 assembly_offsets 和 gripper_range_rad 的建议值。
应用校准结果:
1. 打开你的配置文件(在 franka_gello_state_publisher/config/ 目录)
2. 更新 assembly_offsets 和 gripper_range_rad 字段
3. 重新构建工作区:
cd ~/projects/ros2Gello/gello_software/ros2
colcon build
Step 3:启动 GELLO 发布器节点
创建或编辑配置文件:
- 位置:src/franka_gello_state_publisher/config/your_config.yaml
- 或者直接使用提供的示例文件
配置参数说明:
参数 | 说明 | 示例 |
com_port | 通信端口 ID | /dev/serial/by-id/usb-FTDI_USB... |
namespace | ROS2 命名空间(需与机器人和夹爪一致) | franka |
num_joints | 关节数量(Franka FR3 = 7) | 7 |
joint_signs | 关节方向符号 | [1, -1, 1, -1, 1, 1, 1] |
gripper | 是否使用 GELLO 夹爪状态 | true |
assembly_offsets | 装配偏移 | [0, 0, 0, 0, 0, 0, 0] |
gripper_range_rad | 夹爪角度范围 | [0.0, 1.0] |
dynamixel_torque_enable | 是否使能力矩 | [1, 1, 0, 1, 0, 0, 0] |
dynamixel_goal_position | 目标位置(脉冲,4095 = 360°) | [2048, ...] |
dynamixel_kp_p | 比例增益(虚拟弹簧刚度) | [280, ...] |
dynamixel_kp_i | 积分增益(建议为 0) | [0, ...] |
dynamixel_kd_d | 微分增益(虚拟阻尼) | [50, ...] |
启动命令:
ros2 launch franka_gello_state_publisher main.launch.py config_file:=your_config.yaml
▎ 注意:config_file 参数是可选的。如果不提供,默认使用 example_single.yaml。
虚拟弹簧与阻尼配置(关键)
GELLO 的核心优势之一是手感优化,通过 Dynamixel 内置的 PID 控制器实现"虚拟弹簧"和"虚拟阻尼"效果。
原理
每个 Dynamixel 舵机可以配置为"基于电流的位置控制"模式:
- 虚拟弹簧:目标位置 ≠ 当前位置 → 产生恢复力矩
- 虚拟阻尼:移动速度快 → 产生阻力矩
效果:
- 关节不会"软塌塌"(弹簧支撑)
- 不会"甩太快"(阻尼缓冲)
- 手感接近真实机械臂的惯性
配置参数详解
参数 | 说明 | 推荐值 |
dynamixel_torque_enable | 是否使能力矩(1=开启,0=关闭) | 需要虚拟弹簧的关节设为 1 |
dynamixel_goal_position | 目标位置(脉冲值,4095 = 360°) | 校准姿势对应的脉冲值 |
dynamixel_kp_p | 比例增益(弹簧刚度) | 0 ~ 1000,推荐 280 |
dynamixel_kp_i | 积分增益 | 推荐 0(所有关节) |
dynamixel_kd_d | 微分增益(阻尼系数) | 0 ~ 1000,下盘关节用更强阻尼 |
推荐起始值(参考官方配置)
dynamixel_torque_enable: [1, 1, 0, 1, 0, 0, 0]
dynamixel_goal_position: [2048, 2048, 2048, 2048, 2048, 2048, 2048]
dynamixel_kp_p: [280, 280, 0, 150, 0, 0, 0] # 关节1、2、4加弹簧
dynamixel_kd_d: [50, 100, 150, 200, 100, 50, 0] # 下盘阻尼更强
物理意义
● kp_p = 280→ 弹簧常数约 0.25 Nm/rad(与 GELLO 机械结构中的物理扭簧相当)
● 最大偏转角:约 48° 时达到电流限制(600mA)
● 舵机规格:XL330-M288 堵转扭矩 0.52 Nm(5V,1.47A),但持续大电流会过热。推荐使用 600mA 电流限制。
在线调整
启动后可以用 rqt 工具实时调整:
# 安装 rqt_reconfigure(如果还没装)
sudo apt install ros-humble-rqt-reconfigure
# 启动 rqt
rqt
# 然后:Plugins → Configuration → Dynamic Reconfigure
# 选择 franka_gello_state_publisher 节点,调整参数
⚠️ 重要警告(OpenRB-150 用户)
如果使用 OpenRB-150 通信板:
【危险操作】:
- 不要在没有外接 5V 电源的情况下使能力矩!
- 仅靠 USB 供电驱动力矩模式会烧坏你的电脑 USB 端口!

【正确操作】:
1. 给 OpenRB-150 的电源端子接上 5V 外接电源
2. 把跳线帽设为 "VIN(DXL)"
3. 确认电源指示灯亮起后,再使能力矩
参考:OpenRB-150 手册
4.2 启动关节阻抗控制器
功能说明
● 订阅话题:/gello/joint_states(来自 GELLO 发布器)
● 发布指令:发送给 Franka FR3 的力矩控制接口
● 控制算法:关节阻抗控制(Joint Impedance Control)
配置文件
● 位置:src/franka_fr3_arm_controllers/config/your_config.yaml
● 或直接使用示例:example_fr3_config.yaml
启动命令
ros2 launch franka_fr3_arm_controllers franka_fr3_arm_controllers.launch.py robot_config_file:=your_config.yaml
▎ 注意:robot_config_file 参数是可选的。如果不提供,默认使用 example_fr3_config.yaml。
配置参数(详见 franka.launch.py 第 16 行起)
参数 | 说明 |
robot_ip | Franka 机器人的 IP 地址 |
namespace | ROS2 命名空间 |
阻抗控制参数 | 刚度、阻尼、前馈力矩等 |
4.3 启动夹爪管理器
支持两种夹爪
夹爪类型 | 启动命令 |
Franka Hand(Franka 原装) | franka_gripper_client.launch.py |
Robotiq 2F-85(第三方) | robotiq_gripper_controller_client.launch.py |
Franka Hand 启动示例
ros2 launch franka_gripper_manager franka_gripper_client.launch.py config_file:=example_fr3_config_franka_hand.yaml
配置参数:
- namespace:ROS2 命名空间(需与 GELLO 和机器人一致)
- 其他参数详见配置文件
Robotiq 2F-85 启动示例
ros2 launch franka_gripper_manager robotiq_gripper_controller_client.launch.py config_file:=example_fr3_config_robotiq.yaml
配置参数:
- namespace:ROS2 命名空间
- com_port:Robotiq 夹爪的串口 ID(通过 ls /dev/serial/by-id 确定)
5. 软件包说明
5.1 franka_fr3_arm_controllers
功能:为 Franka FR3 提供关节阻抗控制器。
核心特性:
- 实现 JointImpedanceController,直接发送力矩指令
- 订阅 /gello/joint_states 话题获取 GELLO 状态
启动文件:
- franka.launch.py:启动 Franka 机器人的 ROS 接口
- franka_fr3_arm_controllers.launch.py:启动关节阻抗控制器
5.2 franka_gello_state_publisher
功能:读取 GELLO 手柄的 Dynamixel 舵机角度,发布为 sensor_msgs/msg/JointState 消息。
核心特性:
- 发布话题:/gello/joint_states
- 可选:配置 Dynamixel 内部控制参数(虚拟弹簧/阻尼)
启动文件:
- main.launch.py:启动 GELLO 发布器节点
5.3 franka_gripper_manager
功能:管理连接到 Franka 机器人的夹爪。
核心特性:
- 订阅话题:/gripper/gripper_client/target_gripper_width_percent
- 支持夹爪开合控制和回零(homing)操作
启动文件:
- franka_gripper_client.launch.py:启动 Franka Hand 夹爪管理节点
- robotiq_gripper_controller_client.launch.py:启动 Robotiq 2F-85 夹爪管理节点
6. 构建与测试
6.1 构建项目
# 【重要】所有命令必须在 ros2/ 目录下执行
cd ~/projects/ros2Gello/gello_software/ros2
# 构建(带 clang-tidy 检查)
colcon build --cmake-args -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DCHECK_TIDY=ON
6.2 运行测试
# 运行所有测试用例
colcon test
# 查看测试结果
colcon test-result --all
7. 故障排查
错误 1:串口无法打开
错误信息:
SerialException(msg.errno, "could not open port {}: {}".format(self._port, msg))
可能原因:
1. 端口路径错误:必须使用完整路径(如 /dev/serial/by-id/usb-FTDI_***)
2. 容器启动后插入设备:重新打开 VS Code Dev Container
3. 权限不足:检查用户是否在 dialout 组
解决方法:
# 检查端口是否存在
ls -la /dev/serial/by-id/
# 如果是容器问题,重新打开容器
# VS Code → 左下角 → 重新打开容器
# 如果是权限问题
sudo usermod -a -G dialout $USER
# 注销后重新登录
错误 2:libfranka 版本不兼容
错误信息:
libfranka: Incompatible library version (server version: X, library version: Y)
原因:libfranka 版本与 Franka 机器人系统版本不匹配。
解决方法:
1. 查看 Franka 兼容性表
2. 修改 ros2/.devcontainer/Dockerfile 中的版本参数:
LIBFRANKA_VERSION=0.15.0
FRANKA_ROS2_VERSION=0.15.0
FRANKA_DESCRIPTION_VERSION=0.15.0
3. 重新构建 Dev Container
错误 3:机器人运动卡顿
现象:从臂运动不流畅,或者频繁报"力阈值超限"错误。
原因:USB 延迟过高(默认 16ms)。
解决方法(临时):
# 1. 确定你的 U2D2/OpenRB-150 对应的 tty 设备
ls -la /dev/serial/by-id/
# 假设输出显示它映射到 ttyUSB0
# 2. 降低 USB 延迟(16ms → 1ms)
echo 1 | sudo tee /sys/bus/usb-serial/devices/ttyUSB0/latency_timer
解决方法(永久):
# 创建 udev 规则文件
sudo nano /etc/udev/rules.d/99-gello.rules
# 写入以下内容(针对 U2D2 和 OpenRB-150)
# 降低延迟定时器(1ms 代替默认的 16ms)并修复权限
ACTION=="add", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6001", MODE="0666", RUN+="/bin/sh -c 'echo 1 > /sys/bus/usb-serial/devices/$kernel/latency_timer'"
ACTION=="add", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6014", MODE="0666", RUN+="/bin/sh -c 'echo 1 > /sys/bus/usb-serial/devices/$kernel/latency_timer'"
# 重新加载 udev 规则
sudo udevadm control --reload-rules
sudo udevadm trigger
附录:话题与接口
GELLO 发布的话题
话题名称 | 消息类型 | 说明 |
/gello/joint_states | sensor_msgs/msg/JointState | GELLO 手柄的关节角度 |
控制器订阅的话题
话题名称 | 消息类型 | 说明 |
/gello/joint_states | sensor_msgs/msg/JointState | GELLO 状态输入 |
夹爪控制话题
话题名称 | 消息类型 | 说明 |
/gripper/gripper_client/target_gripper_width_percent | std_msgs/msg/Float32 | 夹爪开合指令(0~100%) |
附录:参考资源
资源 | 链接 |
GELLO 论文 | arXiv:2310.13018 |
Franka 官方文档 | https://frankarobotics.github.io/docs/index.html |
ROS2 Humble 文档 | https://docs.ros.org/en/humble/ |
Dynamixel XL330 规格 | https://emanual.robotis.com/docs/en/dxl/x/xl330-m288/ |
VS Code Dev Containers | https://code.visualstudio.com/docs/devcontainers/containers |
<< 上一篇