机械臂怎么自己避障抓东西?四步拆解 MoveIt
统计 阅读时间大约10分钟(3614字)

15小时前 机械臂怎么自己避障抓东西?四步拆解 MoveIt

来源:豆包
出品:机器人技术笔记你坐在桌前写东西,右手想去拿旁边的水杯。杯子前面有键盘,旁边放着手机,杯柄还朝着一个不算顺手的方向。你几乎不用认真思考,手会自然绕过桌面上的...

出品:机器人技术笔记

你坐在桌前写东西,右手想去拿旁边的水杯。杯子前面有键盘,旁边放着手机,杯柄还朝着一个不算顺手的方向。你几乎不用认真思考,手会自然绕过桌面上的东西,从一个不容易碰倒杯子的角度伸过去,手指停在合适的位置,再把杯子拿起来。

对人来说,这只是一个很小的生活动作。对机械臂来说,它已经是一串麻烦的工程问题。

杯子的位置只是空间里的一个目标。机械臂真正能控制的是每个关节怎么转,夹爪用什么姿态靠近,中间要避开什么,规划出来的路线能不能被底层控制器平滑执行。桌面、杯子、键盘、相机支架这些东西,在人眼里是常识,在机器人系统里都要被建模、计算和检查。

MoveIt(ROS 生态里的机械臂运动规划框架)主要处理的,就是这一段从目标位姿到可执行轨迹的过程。

这篇文章不从配置文件讲起。我们先沿着一个最朴素的问题往下走:机械臂为什么能从去拿那个杯子,变成每个关节该怎么动。

把这条主线拆开,大致就是四步:运动学求解、运动规划、碰撞检测、轨迹处理。

第一步,先问夹爪到底能不能到

机械臂抓杯子的第一步,通常要先回答一个更基础的问题:夹爪想去那个位置,关节应该怎么摆。

这就是运动学问题。正运动学 FK(Forward Kinematics,正运动学)是从关节角算末端位姿,逆运动学 IK(Inverse Kinematics,逆运动学)则反过来,从末端位姿算关节角。比如视觉系统识别出杯子在桌面上的位置,希望夹爪从杯子上方靠近,并让开口方向和杯身方向对齐,这时候 MoveIt 就需要把这个末端目标转换成一组关节角。

这一步容易被初学者低估,因为看起来只是数学转换。可在真实工程里,IK 从来不是输入目标点、吐出答案这么简单。目标可能超出工作空间,位置能到但姿态到不了,同一个末端位姿可能对应多组关节解,还有些解虽然数学上成立,却接近关节限位或奇异位形,放到真机上会很别扭。

所以运动学求解真正回答的是一组工程问题:这个目标位姿能不能到,哪一组关节角更适合当前姿态,会不会靠近限位,会不会让后续规划变难。

MoveIt 里可以配置不同的运动学插件,比如默认常见的 KDL,也有人会用 TRAC-IK 或 IKFast。入门阶段不必先陷进求解器细节里。你先记住一件事:如果 IK 求不出合理解,后面的规划、避障和执行就没有入口。

这也是很多抓取失败的第一层原因。看上去像是机械臂绕大圈,实际上是目标位姿给得太苛刻,夹爪靠近方向不合适,或者相机标定误差让杯子位置偏到了一个机械臂难受的地方。

第二步,在关节空间里找一条能走的路

有了目标关节角以后,接下来才轮到运动规划。

这个环节要解决的问题是:机械臂从当前关节状态出发,怎么走到目标关节状态。注意这里说的走,不是让每个关节从起点匀速插值到终点。对一个 6 轴机械臂来说,它的状态可以看成 6 维关节空间里的一个点;7 轴机械臂则是 7 维。机械臂运动,本质上是在这个高维空间里找一条路径。

最直观的办法当然是插值。当前关节角是起点,目标关节角是终点,把中间点一点点补出来,看起来就有了一条路。问题是,这条路中间可能会扫到桌面,也可能让前臂撞上相机支架,还可能经过一个特别扭的姿态。

所以规划器真正要找的,是一条满足约束的可行路径,而不只是屏幕上看起来顺的线。

这里的可行,至少包括几件事:关节不能超过限位,路径中间不能碰撞,目标状态要满足任务约束,姿态不能过分接近危险区域,最好还不要绕出一条让控制器难受的奇怪路线。

MoveIt 常用 OMPL(Open Motion Planning Library,开放运动规划库)作为主要规划库。OMPL 里有 RRT、RRTConnect、PRM 等采样式运动规划算法。你可以把它们理解成在高维关节空间里不断试探一些中间姿态,把能通过的姿态连起来,逐步找到从起点到终点的通路。

这个比喻容易讲成迷宫,但更准确一点说,它是在关节角组成的空间里找路。每一个点都是机械臂的一种姿态,每一条连接都对应机械臂从一种姿态移动到另一种姿态的过程。

工程上常见的 RRTConnect 速度比较快,适合很多点到点规划场景。工业机器人场景里,也会用 Pilz 这类更接近传统机器人编程习惯的规划方式,比如 PTP、LIN、CIRC。优化式规划器则更关心轨迹质量,比如更平滑、离障碍物更远、运动更自然。

但刚学 MoveIt 时,不要急着比较每个规划器谁更高级。先理解规划器的职责:它负责在约束条件下找路。至于这条路能不能安全通过,还要交给碰撞检测反复判断。

第三步,路能不能走通还取决于环境

机械臂规划路径时,不能只看目标能不能到,还要看路上会不会撞。

这就是碰撞检测。它可以分成两类:一类是自碰撞,也就是机械臂自己和自己干涉;另一类是环境碰撞,也就是机械臂和桌面、工装、支架、障碍物发生干涉。抓取任务还会多一层变化:杯子在被抓住之前是环境物体,被抓住之后会变成附着在末端上的物体。

MoveIt 里这些信息通常由 Planning Scene 维护。你可以把它理解成 MoveIt 用来做规划检查的当前场景。里面有机器人当前关节状态、机器人自身碰撞模型、环境障碍物、允许碰撞矩阵,以及被夹爪抓住以后附着在末端的物体。

拿桌面抓杯子来说,MoveIt 不能只知道杯子在哪里。它还要知道桌面在哪里,旁边的支架在哪里,夹爪抓住杯子以后杯子会不会撞到盒子。如果这些信息没进 Planning Scene,规划器可能找到一条数学上很漂亮、现实里会直接撞上去的路径。

这里有一个特别容易被忽略的细节:抓取前后,碰撞关系会变。

夹爪没闭合时,杯子是环境中的目标物体,夹爪和杯子碰撞不一定被允许。夹爪抓住杯子后,杯子变成 attached object,也就是附着物体。此时夹爪和杯子之间的接触应该允许,但杯子和桌子、杯子和障碍物之间的碰撞仍然不能允许。Allowed Collision Matrix(允许碰撞矩阵)就是用来表达这类关系的。

对工程调试来说,碰撞检测最麻烦的地方往往不在算法,而在模型。

URDF 里的 collision geometry 如果做得太大,MoveIt 会过于保守,明明能穿过去的姿态也被判成碰撞。碰撞体做得太小,仿真里看起来安全,真机上可能擦边。环境障碍物没有正确加入 Planning Scene,规划器就不知道那里不能走。相机坐标系和机械臂基座坐标系没标定好,杯子和障碍物的位置会整体偏移,后面所有判断都会跟着偏。

第四步,路径还要变成真机能执行的轨迹

规划器找到路径以后,事情还没结束。

因为路径通常只是一串空间里的状态点。比如第一个点每个关节是多少角度,第二个点每个关节是多少角度,第三个点每个关节是多少角度。真实机械臂不能只靠这些点直接动起来,底层控制器需要的是带时间、速度和加速度约束的轨迹。

这一步就是轨迹处理,其中很关键的是时间参数化。

简单说,时间参数化就是给规划出来的路径加上时间轴。原来路径只告诉机器人要经过哪些姿态,处理之后的轨迹会告诉机器人第 0 秒在哪里,第 0.5 秒在哪里,第 1 秒在哪里,每个时刻的速度和加速度应该是多少。

这听起来像后处理,但它决定了规划结果能不能真正落到物理系统上。

速度限制没处理好,机器人可能动得太猛;加速度限制没处理好,关节可能突然抖一下;轨迹时间分配不合理,控制器可能跟不上;路径在 RViz 里看着顺,真机执行时却可能报警、超差、跟踪误差变大。

在 ROS 体系里,常见链路是 MoveIt 生成轨迹,通过 FollowJointTrajectory action 发给控制器,joint_trajectory_controller 接收轨迹,再通过 ros2_control 和硬件接口把命令传到驱动器和电机。这里要注意,MoveIt 通常不直接驱动电机。它负责规划和轨迹生成,底层控制器负责轨迹跟踪,硬件驱动负责和电机通信。

把四步串起来看一次抓取

现在我们把这四步放回桌面抓杯子的任务里。

视觉系统先识别杯子位置,并生成一个抓取位姿。这个位姿通常包括夹爪应该到哪里、从哪个方向靠近、离杯子多远开始闭合。它看起来只是一个目标,但对 MoveIt 来说,这是后续所有计算的入口。

第一步,运动学求解。MoveIt 根据抓取位姿做 IK,判断机械臂能不能以这个姿态到达杯子附近。如果求不出来,可能是杯子太远,也可能是夹爪靠近方向不合适,还可能是视觉给出的位姿有偏差。

第二步,运动规划。规划器从当前关节状态出发,在关节空间里搜索一条到达目标状态的路径。它不能只做简单插值,因为中间姿态可能撞桌面、扫支架,或者让机械臂接近不舒服的区域。

第三步,碰撞检测。规划器每试探一些候选状态,就要让碰撞检测判断这些状态和路径是否安全。Planning Scene 里的机器人模型、障碍物、附着物体和允许碰撞关系,都会影响这些判断。

第四步,轨迹处理。找到路径以后,MoveIt 给这条路径加上时间、速度和加速度信息,变成控制器能执行的 JointTrajectory。随后轨迹被发给底层控制器,机械臂才真正开始动。

这四步配合起来,机械臂才有了看起来会自己避障抓东西的能力。视觉给出目标,运动学把目标位姿变成关节解,规划器寻找路径,碰撞检测排除危险状态,轨迹处理生成可执行命令,最后交给底层控制器完成动作。

这也是 MoveIt 最值得入门者先理解的地方:它的价值不止于让机械臂看起来会动,更在于让机械臂在复杂环境里尽可能安全、可控、可复用地动起来。

工程里,先拆链路再选工具

不过到了真实项目里,不一定非要把完整 MoveIt 全套搬进去。

更准确地说,MoveIt 是一套集成框架。它把运动学插件、OMPL 这类规划库、碰撞检测、Planning Scene、轨迹处理、控制器接口和 RViz 可视化工具串到 ROS 体系里,让你能用一套相对统一的方式完成机械臂运动规划。这个集成对学习、验证和中等复杂度项目很有价值,但它也会带来配置复杂度、依赖重量和系统边界变宽的问题。

如果你的项目只是一个很固定的点到点搬运动作,环境也比较简单,完整 MoveIt 可能偏重。你可以直接调用其中某一类底层能力,比如单独使用采样式规划库、单独接一个碰撞检测模块,或者只保留轨迹时间参数化工具。再轻一点的项目,甚至可以自己写一部分逻辑:固定几个中间路点,手写限位检查和避障规则,再接底层控制器。

现在有 AI 辅助写代码以后,这类轻量模块更容易搭出来。但这里要踩一脚刹车:AI 可以帮你写样板代码、接口胶水和一部分几何判断,不能替你验证安全边界。机械臂会动以后,真正要负责的是你对模型、限位、速度、碰撞关系和急停策略的检查。

所以我更建议把 MoveIt 当成一个参照系,而不是唯一答案。

先用 MoveIt 学清楚一套成熟运动规划链路应该包含哪些环节,再根据项目复杂度做取舍:能直接用完整 MoveIt,就别重复造轮子;如果完整框架太重,就拆出你需要的开源库和接口;如果任务足够窄,也可以手写一部分规划逻辑,组合出适合自己项目的运动规划方式。

推荐阅读
{{item.author_display_name}}
{{item.author_display_name}}
{{item.author_user_occu}}
{{item.author_user_sign}}
×
右键可直接复制图片
×