← 返回博客列表  |  上一篇:ROS 总览

一、ROS 机械臂开发生态概览

ROS 为机械臂(Manipulator / Robot Arm / Cobot)开发提供了业界最完善的软件栈,其中 MoveIt! 是事实上的标准运动规划框架,被 Universal Robots、KUKA、ABB、Franka Emika、Fanuc 等几乎所有主流机械臂厂商官方支持。一个典型的 ROS 机械臂系统,其软件栈分层如下:

应用层
任务调度 / 行为树 / 抓取策略
↓ MoveGroup Action / ROS2 PlanningPipeline
MoveIt! 运动规划层
规划场景 · 运动学 · 碰撞检测 · 规划器 · 执行管理
↓ FollowJointTrajectory Action
ros2_control 控制器层
JointTrajectoryController / PositionController
↓ 硬件接口(UART / EtherCAT / CAN / TCP)
硬件驱动层
UR ROS Driver / KUKA FRI / Franka ROS / 厂商 SDK
核心组件速查:
· MoveIt!:运动规划框架(正逆运动学、路径规划、碰撞检测、抓取规划)
· URDF / SRDF:机器人描述文件(关节结构、Mesh 模型、规划组定义)
· ros2_control:ROS2 官方控制器框架,取代 ROS1 的 ros_control
· Gazebo / Ignition:物理仿真器,支持机械臂模型与仿真控制器
· 机器人厂商官方 Driver:UR Driver、Franka ROS2、kuka_driver 等,直接对接真实硬件
· Pick/Place 插件:MoveIt Grasping、GPD、Acronym 等抓取检测与执行框架

二、MoveIt! 核心组件与能力

MoveIt! 是 ROS 机械臂开发的核心引擎,目前最新版本为 MoveIt2(适配 ROS2)。它由一组松耦合的 ROS 节点和 C++ 库组成,通过 MoveGroup 接口对外提供统一服务。其内部核心组件如下:

Planning Scene Monitor
规划场景监控
维护机器人状态与障碍物
Robot State / Model
机器人状态模型
URDF 解析 + 正运动学
Motion Planner (OMPL/CHOMP/STOMP)
运动规划核心
构型空间无碰撞路径求解


Kinematics Solver
运动学求解
KDL / IKFast / TRAC-IK
Collision Detection (FCL)
碰撞检测
自碰撞 + 环境碰撞
Trajectory Processing
轨迹后处理
时间参数化 / 速度平滑
Execution Manager
执行管理器
FollowJointTrajectory Action

三、九大核心能力详解

① URDF 机器人建模

基于 XML 的 URDF + 可视化 Mesh(STL/DAE)描述机器人的关节、连杆、惯量、碰撞几何,可加载 RViz/Gazebo 可视化与仿真。

② 正/逆运动学求解

给定关节角求末端位姿(FK)或给定期望位姿求关节角(IK)。提供 KDL 通用数值解、IKFast 解析解、TRAC-IK 优化解三种方案,速度从 ms 到 μs 级。

③ 无碰撞运动规划

OMPL 规划库内置 RRT/RRT*/PRM/A*/BIT* 等 10+ 种采样/图搜索规划器,在高维构型空间(6/7 轴)毫秒级求解无碰路径。

④ 碰撞检测与距离场

FCL 库支持 Mesh/Box/Cylinder 等多种几何原语的相交检测、最小距离计算。支持自碰撞检测、与点云障碍物碰撞检测。

⑤ 轨迹优化与时间参数化

CHOMP/STOMP/TrajOpt 梯度优化器平滑路径,IterativeParabolicSmoother 对路径加时间戳,保证关节速度/加速度/加加速度不超限。

⑥ 执行与动作管理

FollowJointTrajectory Action 对接 ros2_control 或厂商驱动。支持轨迹抢占、执行中动态替换、执行状态实时反馈。

⑦ 规划场景 / 障碍物管理

Planning Scene 支持 OctoMap 八叉地图、PointCloud2 点云、3D 实体物体导入。深度相机实时检测动态障碍物更新场景。

⑧ Pick & Place 抓取规划

MoveIt Grasping Pipeline:GPD/6-DoF GraspNet 检测候选抓取位姿 → 接近/提升/撤离轨迹规划 → 预抓取/抓取/后抓取三段式执行。

⑨ RViz 可视化交互

MoveIt! Motion Planning Rviz 插件:拖拽交互式标记设置目标位姿、碰撞场景管理、规划预览、轨迹回放、碰撞警告高亮。

3.1 运动规划器对比

规划器 算法类型 最优性 速度 适用场景
RRTConnect 采样双向扩展 非最优(可行解即可) 极快 一般场景首选,快速求可行路径
RRT* 渐进最优采样 渐近最优 慢(需迭代收敛) 有优化需求且时间充裕
PRM 概率路标(多查询) 渐近最优 预处理慢,查询快 静态环境多次查询场景
CHOMP 协变梯度下降优化 局部最优 快(初始路径需可用) 路径平滑优化,避障 + 最小化加加速度
STOMP 随机轨迹优化 局部最优 存在复杂约束场景,鲁棒性优于 CHOMP
A* / BIT* 图搜索 / 隐式图搜索 保证最优 随维度指数上升 低维(≤ 4D)或 lattice 离散化场景

四、典型应用场景

📦 场景一:3C 电子装配 SMT / 组装

消费电子产品生产线中,协作机械臂配合视觉系统完成元器件高精度插装、锁螺丝、点胶、焊接等任务。

  • 视觉定位:工业相机 + AprilTag/特征匹配获取工件 6D 位姿 → TF2 转换到机器人基坐标系
  • 高精度插装:MoveIt! + IKFast 解析解(亚毫秒级)规划柔顺插入路径
  • 力控装配:末端 6D 力/力矩传感器通过 ros2_control force_controller 实现主动柔顺装配策略
  • 节拍优化:轨迹参数化严格限制加加速度,保证节拍稳定在 3~5 秒/次

🤖 场景二:柔性工业抓取 无序分拣

料箱内零件散乱堆放(bin picking),3D 结构光相机拍摄点云,深度学习检测抓取姿态,MoveIt! 执行无碰抓取。

  • 3D 感知:Ensenso / 奥比中光 / 梅卡曼德 3D 相机发布 PointCloud2 点云话题
  • 抓取检测:GPD (Grasp Pose Detection) 在点云上生成若干候选抓取位姿并评分排序
  • 抓取规划:MoveIt! Pick Pipeline 依次验证候选抓取的可达性 + 接近/撤离无碰撞
  • 动态避障:点云障碍物实时注入 Planning Scene,规划时考虑点云禁区

🍳 场景三:餐饮与服务烹饪 炒菜 / 汉堡 / 咖啡

汉堡机、炒菜机器人、咖啡拉花等食品服务机器人,需要精确的轨迹复现、速度控制、多工具切换。

  • 示教与轨迹回放:手动拖动示教记录关键帧 → B 样条插值生成平滑轨迹 → 回放
  • 工具切换:MoveIt! 切换不同 end effector 规划组(锅铲 / 夹具 / 勺子),对应不同 IK 链
  • 工艺参数化:翻炒圆周运动 + 颠勺抛物运动参数化,菜品名称映射参数组合
  • 安全防碰撞:规划场景固定厨房灶台、油桶等静态障碍物,执行时动态碰撞检测

🧪 场景四:实验室自动化 生命科学 / 高通量

生命科学实验室中,机械臂替代人工完成移液、板架搬运、离心机上样、试剂分装等流程,实现 7×24 小时无人值守。

  • 精确定位:多相机手眼标定(Eye-in-Hand / Eye-to-Hand),获得精确的相机-基坐标系变换
  • 任务编排:BehaviorTree.CPP 行为树 / SMACH 状态机编排复杂多步骤实验流程
  • 多设备协同:通过 ROS Service 与酶标仪、离心机、PCR 仪等第三方设备联动
  • 数据追溯:rosbag 记录每次操作的关节轨迹、时间戳、视觉图像,满足审计合规

🏭 场景五:机床上下料 / 码垛 机加工 / 物流

数控机床自动上下料、仓库纸箱码垛是机械臂最经典的应用,要求高可靠性、长寿命、简单易用。

  • 标准动作模板:抓取→提升→直线移动→下降→释放等动作模板化,降低示教复杂度
  • 笛卡尔直线规划:MoveIt! Cartesian Path Planner 保证末端走严格直线,避免与机床干涉
  • 码垛模式:根据箱型尺寸自动生成 n 行 × m 列 × k 层码垛位姿序列
  • 碰撞安全:机床内部作为禁区,软件互锁保证机床门打开时机器人无法进入

五、完整应用示例:视觉引导抓取工作站

以下展示一个典型的 3D 视觉引导抓取工作站的完整架构与话题流,使用 UR5e + Realsense D435i + OnRobot RG2 夹爪:

realsense2_camera_node
发布 /camera/depth/color/points (PointCloud2)
→ 订阅
gpd_node
发布 /detect_grasps/clustered_grasps
pick_place_pipeline_node
调用 MoveGroup /plan 和 /execute Action
move_group
调用 OMPL 规划 / FCL 碰撞检测 / KDL IK
ur_robot_driver (scaled_joint_trajectory_controller)
RTDE 协议 → UR5e 控制柜

5.1 工作流程步骤

Step 1 场景构建:启动机器人驱动、MoveIt!、3D 相机节点。Planning Scene 加载工作台、料仓等静态碰撞体。
Step 2 3D 拍摄 + 抓取检测:相机拍摄料箱点云 → GPD 节点在 GPU 上运行 PointNet 检测候选抓取位姿(200ms)→ 返回 Top 10 抓取按质量排序。
Step 3 抓取验证与规划:依次验证候选抓取:IK 解存在? → 接近段(Approach)无碰撞? → 抓取段(Lift)无碰撞? → 撤离段无碰撞?找到第一个有效抓取。
Step 4 执行轨迹:MoveIt! 通过 FollowJointTrajectory Action 下发完整轨迹 → UR 驱动通过 RTDE 以 125Hz 实时下发关节目标 → 夹爪 Service 触发夹紧/松开。
Step 5 放置循环:机器人移动到放置位置 → 松开夹爪 → 回到 home 位姿 → 等待下一个料箱到位信号 → 循环。

六、基础代码实战(C++ / Python)

6.1 C++:MoveGroupInterface 规划到目标位姿

// C++ MoveIt2 示例:规划到目标位姿并执行
#include <moveit/move_group_interface/move_group_interface.h>
#include <rclcpp/rclcpp.hpp>
#include <geometry_msgs/msg/pose_stamped.hpp>

int main(int argc, char **argv) {
    rclcpp::init(argc, argv);
    auto node = rclcpp::Node::make_shared("pick_demo");

    // MoveGroup 绑定规划组(UR5e 的 manipulator 规划组)
    moveit::planning_interface::MoveGroupInterface move_group(node, "manipulator");
    move_group.setPlanningTime(5.0);   // 规划最长 5 秒
    move_group.setMaxVelocityScalingFactor(0.5);  // 速度 50%
    move_group.setMaxAccelerationScalingFactor(0.3);

    // 设置末端目标位姿(世界坐标系下,单位 m + 四元数)
    geometry_msgs::msg::PoseStamped target_pose;
    target_pose.header.frame_id = "base_link";
    target_pose.pose.position.x = 0.5;
    target_pose.pose.position.y = 0.2;
    target_pose.pose.position.z = 0.3;
    // 四元数:绕 Z 轴 0° 抓取姿态(WXYZ 顺序)
    target_pose.pose.orientation.w = 1.0;
    target_pose.pose.orientation.x = 0.0;
    target_pose.pose.orientation.y = 0.0;
    target_pose.pose.orientation.z = 0.0;
    move_group.setPoseTarget(target_pose);

    // 规划一条无碰撞轨迹
    moveit::planning_interface::MoveGroupInterface::Plan plan;
    auto success = (move_group.plan(plan) == moveit::core::MoveItErrorCode::SUCCESS);
    RCLCPP_INFO(node->get_logger(), "规划结果: %s", success ? "成功 ✓" : "失败 ✗");

    // 执行轨迹(阻塞直到完成)
    if (success) move_group.execute(plan);

    rclcpp::shutdown();
    return 0;
}

6.2 Python:笛卡尔直线规划 + 夹爪控制

# Python MoveIt2 示例:笛卡尔直线运动 + 夹爪开闭 Service
import rclpy
from rclpy.node import Node
from moveit.planning import MoveItPy
from geometry_msgs.msg import Pose
import sys

def main():
    rclpy.init()
    node = Node("cartesian_demo")

    # 初始化 MoveItPy,加载机器人描述与规划组配置
    robot = MoveItPy(node_name="moveit_helper")
    arm = robot.get_planning_component("manipulator")

    # 设置起始状态为当前关节位置
    arm.set_start_state_to_current_state()

    # 构造一系列笛卡尔空间目标点(每个点相距 5cm 向下,共 5 段直线)
    waypoints = []
    current_pose = arm.get_pose_target()
    for i in range(1, 6):
        p = Pose()
        p.position.x = current_pose.pose.position.x
        p.position.y = current_pose.pose.position.y
        p.position.z = current_pose.pose.position.z - 0.05 * i  # 每次下降 5cm
        p.orientation = current_pose.pose.orientation
        waypoints.append(p)

    # computeCartesianPath:按顺序走直线,返回 (轨迹, 完成率)
    (traj, fraction) = arm.compute_cartesian_path(waypoints, eef_step=0.01, jump_threshold=0.0)
    node.get_logger().info(f"笛卡尔路径完成率: {fraction*100:.1f}%")

    if fraction > 0.9:
        # 执行轨迹
        arm.execute(traj, controllers=["joint_trajectory_controller"])

        # 调用夹爪服务关闭(标准 GripperCommand Action)
        from control_msgs.action import GripperCommand
        grip = robot.get_action_client("/rg2_gripper/gripper_cmd", GripperCommand)
        goal = GripperCommand.Goal()
        goal.command.position = 0.0      # 0 = 完全闭合
        goal.command.max_effort = 40.0  # 最大夹紧力 40N
        grip.send_goal(goal).result()

        # 提升 10cm
        arm.set_start_state_to_current_state()
        p2 = arm.get_pose_target()
        p2.pose.position.z += 0.1
        arm.set_pose_target(p2)
        plan = arm.plan()
        if plan:
            arm.execute(plan)

    rclcpp.shutdown()

if __name__ == "__main__":
    main()

6.3 Launch 文件:一键启动 MoveIt2 + RViz + 驱动

# launch/ur5e_moveit_demo.launch.py:典型机械臂启动脚本
from launch import LaunchDescription
from launch_ros.actions import Node

def generate_launch_description():
    return LaunchDescription([
        # 1) 机器人状态发布器:根据关节角发布 TF 变换
        Node(
            package="robot_state_publisher",
            executable="robot_state_publisher",
            parameters=[{"robot_description": Command(["xacro ", urdf_path])}]
        ),
        # 2) ros2_control 控制器管理器 + 关节轨迹控制器
        Node(
            package="controller_manager",
            executable="ros2_control_node",
            parameters=[ur5e_controllers_yaml]
        ),
        # 3) MoveGroup 运动规划核心节点
        Node(
            package="moveit_ros_move_group",
            executable="move_group",
            parameters=[
                moveit_controllers_yaml,
                {"use_sim_time": use_sim_time},
                {"planning_plugin": "ompl_interface/OMPLPlanner"},
                {"request_adapters": "default_planner_request_adapters/AddTimeOptimalParameterization"}
            ]
        ),
        # 4) RViz + Motion Planning 交互插件
        Node(
            package="rviz2",
            executable="rviz2",
            arguments=["-d", rviz_config_path]
        ),
    ])

6.4 SRDF 片段:定义规划组与末端执行器

<!-- ur5e.srdf:MoveIt! 语义机器人描述,定义规划组 -->
<robot name="ur5e_robot">
  <!-- 6 轴机械臂规划组(链状:base_link → tool0) -->
  <group name="manipulator">
    <chain base_link="base_link" tip_link="tool0"/>
  </group>

  <!-- 夹爪规划组(2 指平行夹爪) -->
  <group name="gripper">
    <joint name="finger_joint1"/>
    <joint name="finger_joint2"/>
  </group>

  <!-- 末端执行器与规划组绑定 -->
  <end_effector
      name="rg2_gripper"
      parent_link="tool0"
      group="gripper"
      parent_group="manipulator"/>

  <!-- 禁用默认自碰撞检测的连杆对(允许接触的部分) -->
  <disable_collisions link1="forearm_link" link2="wrist_1_link" reason="Adjacent"/>

  <!-- 预设位姿(一键回 home) -->
  <group_state name="home" group="manipulator">
    <joint name="shoulder_pan_joint" value="0.0"/>
    <joint name="shoulder_lift_joint" value="-1.57"/>
    <joint name="elbow_joint" value="1.57"/>
    <joint name="wrist_1_joint" value="-1.57"/>
    <joint name="wrist_2_joint" value="0.0"/>
    <joint name="wrist_3_joint" value="0.0"/>
  </group_state>
</robot>

七、总结与选型建议

ROS + 机械臂的正确选型路径:

负载 & 工作半径:根据搬运工件重量与操作空间尺寸,先确定大致规格(3kg / 5kg / 10kg / 20kg)
是否需要力控:装配、打磨、抛光等接触任务 → 选内置关节扭矩传感器的 7 轴(Franka / iiwa / UR e-Series)
精度需求:电子装配 ±0.02mm → 选 ABB YuMi / UR e-Series;搬运 ±0.1mm 即可 → 国产高性价比
ROS 驱动:优先选择有官方 ROS/ROS2 Driver 的厂商(UR、Franka、KUKA、艾利特等),避免非官方驱动的维护坑
仿真先行:无论选哪家,先用 MoveIt! Setup Assistant 在 Gazebo 中跑通规划→执行闭环,再采购真实硬件
学习路线建议:
1️⃣ 仿真起步:UR5e + MoveIt2 + Gazebo 仿真环境,免费且功能完整,所有规划功能和真实臂 1:1
2️⃣ 掌握三 API:setPoseTarget/plan/execute 关节空间规划 + computeCartesianPath 笛卡尔直线 + GripperCommand 夹爪
3️⃣ 进阶视觉:接入 Realsense D435i,跑通 pointcloud_to_octomap → Planning Scene 动态障碍物注入
4️⃣ 真实硬件:采购入门级协作臂(UR3e / 艾利特 EC63 / DOBOT CR5),用官方 driver 无缝衔接