问题:为什么同一台机械臂算出两套力矩?
项目是一台六轴协作机械臂,需要在低速拖动模式下做重力补偿。旧系统用一套厂商提供的动力学接口,新控制程序改用Pinocchio。机械臂抬起大臂后,两个系统在肩关节给出的补偿力矩差距很明显:方向一致,但Pinocchio的数值接近另一套结果的两倍。
现场第一反应是拿Pinocchio和旧库做性能、精度对比,但这种比法太粗。逆动力学只要输入模型不同,算法再正确也会给出不同答案。我们把问题拆成三个可验证环节:姿态q是否一致、重力方向是否一致、惯量参数是否一致。
做Pinocchio对比时,别只比运行速度,更该比模型假设、坐标定义和输出能否接进控制器。本文复盘一次六轴机械臂重力补偿异常:同一姿态下,Pinocchio结果几乎比旧工具链大一倍,最后问题并不在动力学算法本身。
项目是一台六轴协作机械臂,需要在低速拖动模式下做重力补偿。旧系统用一套厂商提供的动力学接口,新控制程序改用Pinocchio。机械臂抬起大臂后,两个系统在肩关节给出的补偿力矩差距很明显:方向一致,但Pinocchio的数值接近另一套结果的两倍。
现场第一反应是拿Pinocchio和旧库做性能、精度对比,但这种比法太粗。逆动力学只要输入模型不同,算法再正确也会给出不同答案。我们把问题拆成三个可验证环节:姿态q是否一致、重力方向是否一致、惯量参数是否一致。
公平对比至少固定四件事:同一份关节角,统一为弧度;同一基座坐标系;速度和加速度都置零;使用完全相同的质量、质心和惯量参数。这样调用逆动力学,比较的才是实现与数值结果,而不是两份机器人模型。
我们先拿两关节平面模型做缩小测试。第一根杆长0.4米、第二根0.3米,两个关节静止,只比较重力项。这个模型没有传感器偏置、减速器摩擦和控制器滤波,结果两边基本一致。它说明Pinocchio的计算链没问题,差异藏在完整URDF或坐标转换里。
问题出在CAD导出的URDF。旧系统采用的是连杆本体坐标下的惯量,厂商接口内部又做了一次质心偏移处理;新URDF里惯量已经通过inertial标签的origin表达在质心处。团队为了“保持一致”,又在导入后手工平移了一遍惯量,等于重复应用了平行轴定理。
这个错误不会让程序报错,也不会让末端运动学异常,因为正运动学根本不用惯量。只有在大臂抬起、质量分布离关节较远时,力矩差异才变得醒目。删掉那段二次修正后,肩关节的重力项回到合理范围,和旧接口的差异只剩参数标定与摩擦补偿。
若目标是快速批量计算、优化或全身控制,Pinocchio的优势通常在于完整的刚体动力学算法和高效的数据结构;如果只做基础链式运动学,已有工具链未必需要迁移。厂商SDK的价值则在于它可能包含减速器、摩擦、电机侧力矩和标定补偿,这些并非通用刚体库的职责。
所以本案最终没有用Pinocchio替代厂商SDK,而是分层使用:Pinocchio负责预测重力和惯性项,SDK负责读取状态、下发命令及保留设备相关补偿。把两个工具硬做一对一替代,往往会忽略它们原本解决的问题并不相同。
以后每次改URDF,我们都先跑静态重力测试:选三组有代表性的姿态,令v和a为零,记录rnea输出;再跑随机姿态下的正运动学,核对TCP位置;最后才接控制器。这样能把模型问题拦在仿真阶段,而不是等真实机械臂抖动后再查。
另一个习惯是保存输入快照。一次有效对比必须能复现q、v、a、重力、URDF版本和末端frame名称。只截图一组力矩曲线没有意义,尤其多人协作时,大家口中的“同一模型”很可能不是同一个提交版本。