|
MoveIt是漏洞ROS生态里最常用的机械臂运动规划框架,几乎成了机器人抓取、漏洞避障实验的漏洞默认起点。但它的漏洞漏洞从来不是“能不能动”的问题,而是漏洞“你以为它动了,其实它根本没按你想的漏洞动”。 2023年,漏洞我在一个六轴协作臂的漏洞抓取demo里踩过坑。轨迹规划完成后,漏洞机械臂末端在笛卡尔空间里画出的漏洞路径,和Rviz里显示的漏洞那条平滑曲线差了将近两厘米。起初以为是漏洞标定误差,反复检查后发现问题出在MoveIt的漏洞碰撞检测默认配置上——它只用了自碰撞矩阵,没加载环境点云,漏洞于是漏洞规划器在真实障碍物面前“睁眼瞎”。更麻烦的是,MoveIt的规划场景(Planning Scene)更新是异步的,点云数据还没传完,规划器就已经开始算轨迹了。结果就是:屏幕上看起来避障完美,实际执行时直接撞上桌子边缘。 这类问题背后,是MoveIt架构里一个老生常谈的软肋:它把“感知”和“规划”解耦得太干净。感知模块负责往场景里塞物体,规划模块只管在场景快照上算路径。可现实世界的点云是流式的,带噪声的,有时还带延迟。MoveIt默认的碰撞检测用的是FCL(Flexible Collision Library),它对凸包和网格的处理效率还行,但当你把真实点云转成八叉树体素栅格塞进场景,FCL的查询性能会骤降,直接拖慢规划周期。更隐蔽的是,MoveIt的“接近传感器”机制并不成熟——它不像工业机器人控制器那样,能实时把力觉或激光测距数据融进轨迹修正里,而是靠“重规划”兜底。一旦重规划的触发条件设得太保守,机械臂就会在碰到障碍物前最后一刻才紧急刹车。 另一个经常被忽略的漏洞在运动学求解器上。MoveIt默认用KDL做逆解,但KDL对奇异点处理得很粗暴。有一次我让机械臂末端走一条经过奇异点附近的直线,规划器居然生成了关节速度突变的轨迹——末端在空间里匀速,但某个关节在零点几秒内转速从10%飙到90%。这种轨迹在仿真里看不出问题,真机上一跑,电机直接过流报警。后来换了TRAC-IK才缓解,但TRAC-IK也有自己的毛病:它偶尔会给出不连续的关节解,导致规划出的轨迹在关节空间里出现跳跃。 最让我头疼的是MoveIt的“规划请求适配器”机制。它默认会加一个“时间最优轨迹参数化”步骤,把路径点转成带时间戳的轨迹。但这个适配器对加速度约束的估计很保守,经常把原本0.8秒就能走完的路径拉伸到2秒以上。反过来,如果你手动关掉它,规划出的轨迹又可能因为加速度超限而让真机抖动。这种“要么慢得像蜗牛,要么抖得像筛子”的两难,本质上是因为MoveIt的轨迹约束检查是离线的——它只在规划完成后做一次验证,规划过程中根本不管关节加速度是否超限。 还有一个不算漏洞但很坑的设计:MoveIt的“当前状态”和“机器人状态”是两份独立数据。如果你在代码里用setJointGroupPositions改了目标姿态,但忘了调用setJointGroupPositions的返回值去更新规划场景里的“当前状态”,那么规划器会拿一个过期状态当起点。这种情况在长时间运行的程序里特别容易触发,尤其是当你用异步回调反复设置目标时,状态更新和规划请求之间的竞态条件会随机产生“规划失败”或“轨迹跳变”。 说了这么多,我不是想劝你别用MoveIt。它依然是开源社区里最完整的机械臂规划框架,光是不用自己写碰撞检测和运动学解算这点,就省了无数精力。但你要清楚它的边界:它适合做离线规划和低速、低精度的在线演示,不适合做需要实时力控、动态避障的工业级任务。如果你真要在生产环境用,至少得做三件事:把感知和规划放在同一线程里同步,强制刷新规划场景;用TRAC-IK或自研求解器替代KDL;关掉默认的时间优化适配器,自己写带加速度约束的轨迹生成。否则,那些藏在Rviz漂亮界面背后的漏洞,迟早会在真机运行的那天,以撞机或抖动的方式狠狠回敬你。 |