内容
# 法兰卡接口
基于libfranka和ROS的法兰卡机器人轻量级接口。
功能:
- 关节阻抗控制
- 实时状态访问
- 关节位置
- 关节速度
- 关节扭矩
- TCP姿态
- TCP速度
- 简单的Python API
- 使用pybind11绑定的C++后端
- 低延迟和最小依赖
## 当前软件包
该仓库目前提供一个ROS 1 `ros_control`控制器软件包:
- 软件包:`franka_interface`
- 控制器插件:`franka_interface/JointImpedanceController`
- 官方保持配置:`config/joint_impedance_official_hold.yaml`
- 顺从保持配置:`config/joint_impedance_compliant_hold.yaml`
- 非常软的保持配置:`config/joint_impedance_very_soft_hold.yaml`
- 阻尼模式配置:`config/joint_impedance_damping_mode.yaml`
- 高阻尼模式配置:`config/joint_impedance_high_damping_mode.yaml`
- 完整启动文件:`launch/joint_impedance_controller.launch`
- 完整放松臂和夹持器启动文件:`launch/full_system_relaxed.launch`
- 仅加载启动文件:`launch/load_joint_impedance_controller.launch`
- 跟随启动文件:`launch/joint_impedance_follow.launch`
- 放松碰撞启动文件:`launch/franka_control_relaxed_collision.launch`
- 官方样式启动文件:`launch/joint_impedance_controller_official_style.launch`
- 上游参考文件:`reference/franka_example_controllers/`
控制器实现关节级阻抗:
```text
tau_cmd =
K * (q_d - q)
+ D * (dq_d - dq_filtered)
+ coriolis_factor * coriolis
```
对于`libfranka`/`franka_ros`,关节扭矩命令在没有重力和摩擦的情况下指定。此控制器遵循官方的法兰卡关节阻抗示例,不会明确将重力或摩擦项添加到命令扭矩中。默认启用科里奥利补偿。
## 在Ubuntu 20.04 Docker/franka_ros环境中构建
推荐的布局是将此仓库放在容器的catkin工作区`src`目录中:
```bash
cd ~/catkin_ws/src
ln -s /path/in/container/franka_interface franka_interface
cd ~/catkin_ws
catkin_make
source devel/setup.bash
```
如果仓库是从Ubuntu 22.04主机挂载的,请在Ubuntu 20.04中启动容器并绑定挂载仓库,然后在Ubuntu 20.04中构建:
```bash
docker run --rm -it --net=host --privileged \
-v /home/sqz/projects/franka_interface:/root/catkin_ws/src/franka_interface \
<your-franka-ros-image> bash
```
在容器内:
```bash
source /opt/ros/noetic/setup.bash
cd /root/catkin_ws
catkin_make
source devel/setup.bash
```
## 运行
首先使用`config/joint_impedance_official_hold.yaml`启动,该配置使用与官方法兰卡关节阻抗示例相同的关节增益,但保持当前关节姿态,而不是生成笛卡尔圆形轨迹。之后,当稳定时,切换到`config/joint_impedance_compliant_hold.yaml`进行手引导顺从测试。
- `arm_id`: 通常为`panda`
- `joint_names`: 必须与机器人命名空间匹配
- `k_gains`、`d_gains`: 首先使用官方保持配置文件,然后慢慢调整顺从配置文件
启动:
```bash
roslaunch franka_interface joint_impedance_controller.launch robot_ip:=<robot-ip>
```
命令一个7-DoF关节目标:
```bash
rostopic pub -1 /joint_impedance_controller/command std_msgs/Float64MultiArray \
"data: [0.0, -0.785398, 0.0, -2.35619, 0.0, 1.5708, 0.785398]"
```
您还可以发送14个值:前7个是`q_d`,后7个是`dq_d`。
发送一个小的相对关节步长:
```bash
rosrun franka_interface send_joint_step.py _joint_index:=1 _step_deg:=-5.0
```
单独运行关节空间线性插值器:
```bash
roslaunch franka_interface joint_linear_interpolator.launch
```
发送一个具有默认持续时间的目标:
```bash
rostopic pub -1 /joint_linear_interpolator/target std_msgs/Float64MultiArray \
"data: [0.0, -0.785398, 0.0, -2.35619, 0.0, 1.5708, 0.785398]"
```
完整的放松启动也会默认启动此插值器。使用以下命令覆盖其发布率:
```bash
roslaunch franka_interface full_system_relaxed.launch \
robot_ip:=172.16.0.2 interpolator_rate:=500.0
```
发送一个具有显式持续时间的目标,持续时间作为第8个值,默认情况下持续时间被限制在[1.0, 30.0]秒内:
```bash
rostopic pub -1 /joint_linear_interpolator/target std_msgs/Float64MultiArray \
"data: [0.0, -0.785398, 0.0, -2.35619, 0.0, 1.5708, 0.785398, 3.0]"
```
对于已经以固定速率采样的轨迹,请使用航点播放器。它接受一个`trajectory_msgs/JointTrajectory`;每个点的`positions`字段是一个七关节航点。`source_rate`描述规划采样率,而`rate`是实际命令发布率。当它们不同时,播放器会在相邻航点之间进行线性插值。速度不是必需的:
默认的`full_system_relaxed.launch`和`start_full_system.sh`会自动启动此播放器。它的默认源速率为40 Hz,命令输出速率为200 Hz。要以40 Hz规划和200 Hz命令输出启动完整系统:
```bash
roslaunch franka_interface full_system_relaxed.launch \
robot_ip:=172.16.0.2 \
waypoint_source_rate:=40.0 waypoint_rate:=200.0
```
对于独立测试,请使用`joint_waypoint_player.launch`并传入`source_rate:=40.0 rate:=200.0`。
在`/joint_waypoint_player/trajectory`上发布轨迹。播放器发布 `[q_d, dq_d]`,其中 `dq_d` 设置为七个零。不要同时运行主动航点播放器和主动目标/增量命令,因为它们都发布到同一个阻抗控制器命令主题上。
对于一个小的测试轨迹,`send_joint_step_trajectory.py`读取当前的控制器目标并从该目标生成一个轨迹:
```bash
rosrun franka_interface send_joint_step_trajectory.py \
_joint_index:=1 _step_deg:=5.0 _duration:=2.0 _source_rate:=40.0
```
调试数据在`publish_rate`下发布到:
```text
/joint_impedance_controller/debug_tau
```
消息类型为`std_msgs/Float64MultiArray`,布局如下:
```text
[0:7] tau_commanded
[7:14] tau_measured
[14:21] tau_J_d
[21:28] coriolis
[28:35] q
[35:42] q_d
[42:49] dq_filtered
```
干净地停止和卸载控制器:
```bash
rosrun franka_interface stop_joint_impedance_controller.sh
```
在`franka_control`运行后运行外部跟随目标节点:
```bash
roslaunch franka_interface joint_impedance_follow.launch arm_id:=panda
```
使用默认机器人IP启动法兰卡控制:
```bash
rosrun franka_interface start_franka_control.sh
```
使用放松的碰撞阈值启动法兰卡控制:
```bash
roslaunch franka_interface franka_control_relaxed_collision.launch \
robot_ip:=172.16.0.2 load_gripper:=false
```
或者启动法兰卡控制和顺从关节阻抗控制器:
```bash
roslaunch franka_interface joint_impedance_controller_relaxed_collision.launch \
robot_ip:=172.16.0.2 load_gripper:=false
```
放松的阈值位于`config/franka_control_relaxed_collision.yaml`。它们降低了顺从性/手引导测试的反射灵敏度;它们不会改变libfranka的硬扭矩、速度或加速度限制。
启动完整的放松臂和法兰卡手堆栈:
```bash
roslaunch franka_interface full_system_relaxed.launch robot_ip:=172.16.0.2
```
此启动程序启动放松的`franka_control`、顺从的关节阻抗控制器、官方的`franka_gripper`和`gripper_interface`包装器。不要在单独启动`franka_gripper.launch`。
便捷脚本:
```bash
rosrun franka_interface start_full_system.sh
```
恢复法兰卡反射/错误状态:
```bash
rosrun franka_interface recover_franka_errors.sh
```
## 安全注意事项
- 首先使用低刚度测试。
- 保持用户停止可用。
- 保持第一个控制器版本与官方的`PD + coriolis`扭矩命令对齐,然后添加实验性前馈项。
## 手动ROS启动
ROS堆栈从Ubuntu主机手动启动。安装命令:
```bash
sudo install -m 0755 host/start-franka /usr/local/bin/start-franka
sudo install -m 0755 host/my_command /usr/local/bin/my_command
```
启用FCI并确保机器人静止后运行:
```bash
start-franka
```
在任何时候打印命令指南:
```bash
my_command
```
该命令确保`franka_fci_dev`正在运行,获取ROS和catkin工作区,并在容器内执行现有的`start_full_system.sh`。它附加到终端中的启动进程;按`Ctrl-C`停止完整的ROS堆栈。停止后,再次运行`start-franka`以启动新的启动。
该命令故意作为前台命令。如果SSH会话关闭,附加的ROS堆栈也可能终止。只有当堆栈必须在SSH断开连接时存活时,才使用`tmux`或`screen`。
旧的主机侧FCI监督器文件不再是启动路径的一部分。它们对于MCP服务或手动ROS工作流程不再需要。
## MCP服务
仓库包含一个两进程MCP集成:
- `host/franka_mcp_server.py`是一个主机侧、始终在线的MCP可流式HTTP服务器。它不导入ROS,在FCI被禁用时保持可用。
- `scripts/franka_mcp_ros_gateway.py`与手动启动的ROS堆栈一起启动,仅监听`127.0.0.1:8765`。它读取法兰卡状态并将完整的轨迹提交到本地ROS节点。
面向网络的端点旨在由主机在`https://172.16.0.1:8443/mcp`提供服务。MCP服务公开:
- `get_status`
- `get_robot_state`
- `get_full_robot_state`
- `move_to_joint_target`
- `track_joint_trajectory`
- `open_gripper`
- `close_gripper`
- `move_gripper`(默认禁用)
运动命令在FCI或机器人不可用时被拒绝。它们不会被排队以供稍后执行。航点请求作为一个完整的列表发送;本地航点播放器使用其时间戳在配置的200 Hz输出速率下进行插值。阻抗控制器仍然是本地1 kHz扭矩环。`open_gripper`和`move_gripper`调用现有的配置的夹持器命令,而不改变其参数。`close_gripper`在没有参数的情况下使用现有的默认关闭力;显式`force`使用现有的`/gripper_interface/close_force`命令。`move_gripper`采用绝对开启宽度(以米为单位)。
`move_gripper`实现保留兼容性,但默认情况下不注册。 在MCP服务环境中设置`FRANKA_MCP_ENABLE_MOVE_GRIPPER=true`并重新启动服务以再次公开它。
官方MCP Python SDK当前需要Python 3.10或更高版本,因此在主机虚拟环境中安装,而不是在ROS Noetic Python 3.8环境中:
```bash
python3 --version
sudo install -d -m 0755 /opt/franka-mcp
sudo python3 -m venv /opt/franka-mcp/venv
sudo /opt/franka-mcp/venv/bin/pip install --upgrade pip
sudo /opt/franka-mcp/venv/bin/pip install -r /home/sqz/projects/franka_interface/host/mcp-requirements.txt
```
创建包含机器人主机IP的本地证书,配置`/etc/default/franka-mcp`中的随机令牌,然后安装并启动服务:
```bash
sudo install -d -m 0750 -o root -g sqz /etc/franka-mcp
sudo openssl req -x509 -newkey rsa:3072 -nodes -days 825 \
-keyout /etc/franka-mcp/server.key \
-out /etc/franka-mcp/server.crt \
-subj "/CN=172.16.0.1" \
-addext "subjectAltName=IP:172.16.0.1"
sudo chown root:sqz /etc/franka-mcp/server.key /etc/franka-mcp/server.crt
sudo chmod 0640 /etc/franka-mcp/server.key
sudo chmod 0644 /etc/franka-mcp/server.crt
sudo install -m 0644 systemd/franka-mcp.env.example /etc/default/franka-mcp
# 在启动服务之前编辑FRANKA_MCP_TOKEN。
sudo install -m 0644 systemd/franka-mcp.service /etc/systemd/system/franka-mcp.service
sudo systemctl daemon-reload
sudo systemctl enable --now franka-mcp.service
```
ROS工作区仍需要在容器内重建,以便安装本地网关:
```bash
cd /root/catkin_ws
source /opt/ros/noetic/setup.bash
catkin_make
source devel/setup.bash
```
MCP服务器和ROS堆栈具有独立的生命周期。当手动ROS堆栈停止时,`get_status`仍然可用并报告`fci_connected: false`;状态和运动调用报告机器人不可用。MCP准备状态直接来自本地ROS网关,而不是来自监督器状态文件。
在Mix上,Codex可以直接通过有线`172.16.0.0/24`网络连接。当前的Codex配置格式适用于流式HTTP服务器,在`host/mix_codex_config.toml.example`中显示;将该表合并到Mix的`~/.codex/config.toml`中,导出相同的`FRANKA_MCP_TOKEN`,并重启Codex。因为服务使用私有证书,所以在连接之前,请将`/etc/franka-mcp/server.crt`安装到Mix的受信任CA存储中。