首页 / 资讯中心 / 文章详情

V-REP关节力矩控制与物理引擎参数调试实战指南

V-REP关节力矩控制与物理引擎参数调试实战指南 ★ FEATURED ARTICLE
V-REP这个系列的教程写到这里已经过了基础的建模、运动学、路径规划这些环节但说实话很多做机器人仿真的朋友卡住的地方不是怎么搭场景而是怎么让仿真里的关节“像真的电机一样干活”。尤其是关节力矩控制这块位置控制和速度控制文档里到处都是一说到力矩控制能讲清楚的不多能调出稳定表现的更少。再加上物理引擎属性这个老生常谈又很玄学的选项选哪个引擎、参数怎么配直接决定你仿出来的东西到底靠不靠谱。这篇文章就把这两块掰开揉碎聊清楚重点是实操层面怎么设、怎么调、怎么判断结果适合已经在V-REP里搭过简单模型的读者也适合那些刚想从位置控制往力矩控制过渡、又不知道怎么下手的朋友。聊力矩控制之前得先把V-REP里关节控制的一种基本关系理清楚不然很多人一上来就卡在“我设了力矩为啥不动”这种问题上。1. 关节力矩控制的前置认知三种控制模式怎么选1.1 位置、速度、力矩三种模式的本质区别V-REP里的关节动态控制本质上就三条路可走位置控制、速度控制、力矩控制。位置控制是默认模式也是大家最熟悉的——你给一个目标角度控制器通过PID把关节从当前角度拽到目标角度。速度控制类似给的是目标角速度。这两种模式都是“闭环控制”也就是说仿真器会不停读关节当前的位置/速度再根据误差去调整驱动力。力矩控制则完全是另一套逻辑。它不经过PID调节而是直接告诉关节电机“你现在给我输出多少力或力矩”相当于开环地给定一个驱动力。关节最后转不转、转多快完全取决于这个力和当前负载、摩擦力、重力这些外部作用力之间的博弈。我在V-REP里调试时最常碰到的情况是用户把关节设为力矩模式后给了一个1N·m的力矩结果关节纹丝不动就开始怀疑模型有问题。其实大概率是没搞明白这1N·m到底是抵抗重力还不够还是被Fmax限幅给吃了还是干脆物理引擎没启用。1.2 什么时候必须用力矩控制现实里用到力矩控制的地方恰恰是那些位置控制做不好的场景。典型的有这样几个第一个是力控抓取。夹爪夹住一个易碎物体如果只靠位置控制夹紧很容易把东西夹碎因为位置控制只看“到了没到”不看“出没出力”。力矩控制可以设定一个合适的夹持力让夹爪刚好稳住物体又不破坏它。第二个是关节拖动示教。协作机器人的那种“人拖着手臂走”的功能本质上就是让每个关节处于力矩模式并且给一个很小的目标力矩让人手一推关节就跟着走而不是像位置控制那样和你较劲。第三个是柔顺控制。关节在接触环境时需要一个“弹性”的状态比如打磨、装配这种场景下力矩控制是基础。第四个是平衡控制。倒立摆也好双足机器人也好要想在平衡点附近做微小调节位置控制反应慢且生硬力矩控制才能做到像真机一样的连续发力。所以判断标准很直接如果你关心的是“送到哪”用位置控制如果关心的是“出多大劲”用力矩控制。很多时候两种模式还会混着用比如运动时用位置模式接触后用力矩模式这在V-REP里通过切换控制模式就能实现不需要重新搭建模型。1.3 力矩控制为什么难上手搞清楚了概念不代表能跑通。V-REP里力矩控制难上手主要有三个原因。第一个原因是参数耦合。力矩输出上限Fmax、目标力矩值、物理引擎的迭代次数、阻尼系数这些参数相互影响。同一个模型Bullet引擎下表现正常换到ODE引擎可能直接飞掉。第二个原因是反馈少。位置控制有明确的“到达目标位置”这个结果力矩控制的结果体现在加速度和速度的变化上在graph里看数值比较抽象不利于判断对错。第三个原因是反直觉。很多人按直觉以为给了扭矩关节就会匀速转动但现实是有恒定力矩时关节是匀加速转动的速度会一直涨除非被阻尼或者Fmax限制住。这跟物理直觉一致但跟日常经验不一致所以初学时容易觉得“不对”。我建议刚开始练习时不要急着做复杂场景先在单关节模型上把力矩控制跑明白再看怎么扩展到多关节这也是这篇文章后面实操案例的思路。2. 在V-REP里把关节力矩控制跑起来2.1 关节动态属性里的关键开关打开任意一个关节的动态属性对话框里面有这么几个关键选项。首先是Motor enabled不勾这个关节就是个被动铰链整个力矩控制无从谈起。其次是Control loop enabled这个是区分控制模式的总开关关掉之后就是纯力矩/纯速度开环控制打开之后才能做位置控制。在V-REP旧版本和新版本CoppeliaSim里控制模式的选择会直接在动态属性里体现。你要用力矩控制就需要把控制模式切到Force/torque control同时设置好目标力矩。有个很容易被忽略的细节是切换模式以后关节仍然显示的是位置控制相关的UI参数但那些参数已经失效了真正生效的是Target force/Torque和最大力矩。我自己在操作中习惯用脚本统一处理而不是每次去点对话框。因为对话框改参数只对当前场景有效脚本才能把参数固化下来这也是长期做仿真项目的一个好习惯。2.2 target force、Fmax、实际输出力矩的区别这三个值必须分清不然调试时会被数值搞晕。Target force目标力矩是你“希望”电机输出的力矩值是设定值。Fmax最大力/力矩是电机的物理上限可以理解为真实世界里的电机扭矩极限。实际输出力矩则是物理引擎每步解算后真正施加到关节上的值它受限于Fmax同时受接触、摩擦、载荷影响不是你说多少就是多少。我在实际项目里常用一个简单的规则Fmax设为目标力矩的1.2到1.5倍以上。这样目标力矩不会轻易被Fmax截断你观察到的输出曲线也才能反映真实控制效果。如果把Fmax设得比目标力矩还小那么目标力矩永远达不到输出直接被限幅削平表现出来就是关节无力、动作缓慢。这里补一个实用的代码片段。在V-REP的embedded script里设置力矩控制只需要几行function sysCall_init() joint sim.getObjectHandle(Joint) sim.setJointMaxForce(joint, 5.0) -- 电机最大输出5N·m sim.setJointTargetForce(joint, 1.0, true) -- 目标力矩1N·m带符号 end第三个参数如果为true表示力矩带符号根据目标方向输出正负力矩如果为false则按绝对值输出方向由当前关节运动趋势决定。这个细节特别容易踩坑我调试夹爪时曾因为设了false导致夹爪往反方向使劲好一阵子没找到原因。2.3 从真实案例切入算一算单关节需要多大力矩才能保持水平力矩控制不在真空里用最终要落到具体负载上。这里用一个最简单也最有代表性的案例切入一根关节悬臂水平伸着关节需要输出多大力矩才能让悬臂保持不往下掉。设悬臂质量为m质心到关节轴距离为d重力加速度g9.8m/s²那么重力产生的力矩就是mgd。如果你要让悬臂保持水平且不考虑关节摩擦目标力矩就应当等于这个值以反方向输出。举个例子。悬臂质量2kg质心距离0.3m算下来重力力矩约为29.80.35.88N·m。那么目标力矩就该设成5.88N·m附近Fmax至少设成8N·m。这时候关节会有一个稳定的输出悬臂悬停不会下落。你仔细观察graph里的实际输出力矩曲线会发现它有微小的波动因为仿真里每一步的数值都在微调这是物理引擎解算的正常现象。这个例子极其重要它是理解力矩控制的基础力矩控制是做“力的平衡”而不是做“位置跟踪”。你把5.88设对了悬臂悬停给得少了悬臂下沉给得稍微大了悬臂会缓慢上抬直到被其他结构挡住或者达到一个新的平衡。这种微妙的物理反应正是力矩控制跟位置控制最大的不同。2.4 怎么把实际输出力矩读回来做分析很多人设完了力矩但是不知道怎么验证这时候要用sim.getJointForce这个API。它返回的是当前关节实际经历的力或力矩在动态模式下可以理解为电机的实际输出。配合graph模块把关节目标力矩和实际输出力矩画在同一个坐标系里就能很直观地看到限幅、滞后和震荡。读回数据的脚本一般长这样function sysCall_sensing() local applied sim.getJointForce(joint) local amplitude sim.getJointTargetForce(joint) local vel sim.getJointVelocity(joint) -- 然后按你需求把变量写到graph流里面 end注意一点sim.getJointForce返回的是一个向量还是标量在不同版本里有差异。旧版V-REP里返回的可能是关节轴方向的力矩值你也可以通过sim.getJointForce(joint, {0,0,0})这样带参数的形式拿到更完整的数据。用的时候要以你手头版本的API文档为准建议先在脚本里加一句打印确认返回值的形态再往下写逻辑。3. 物理引擎属性选型与参数调整的完整指南3.1 四种物理引擎的特点与差异V-REP的优势之一就是内置了多套物理引擎可以在不重写模型的情况下切换。但是引擎不是越多越好选错引擎经常会让结果千差万别。V-REP/CoppeliaSim里主要能选的引擎有Bullet、ODE、Vortex和Newton四种。Bullet是最常用的默认也是它特点是速度快、迭代参数直观适合大多数刚体动力学仿真。ODE在关节约束处理上表现不差处理速度也不错但是版本更新慢有些边缘碰撞问题处理得比较粗糙。Vortex是商业引擎物理精度最高摩擦、接触模型丰富适合对精度要求极高的工业级仿真但是需要授权。Newton在V-REP里的存在感不如前几个特点是对碰撞和堆叠比较稳定适合特定场景。我给一般用户的建议是没有特殊需求就老老实实先用Bullet把关节和力矩控制跑通再说。等你要做轮式机器人、履带、履带与地面附着这些对接触模型敏感的场景时再考虑Vortex。别一上来就迷信“越贵越好”仿真里90%的问题都不是引擎不够强而是参数没调对。3.2 仿真设置里的引擎属性和公共属性物理引擎属性分成两级一级是仿真设置里“全局”的引擎属性另一级是每个物体shape的“个体”引擎属性。很多人只调全局忽略了每个shape自己的摩擦系数、弹性系数这是导致仿真结果偏离预期的常见原因。以Bullet为例在Simulation settings对话框里可以设置约束求解迭代次数constraint solving iterations、时间步长time step、线性阻尼、角阻尼等全局参数。迭代次数越高仿真越不容易抖动但计算也越慢。时间步长越小结果越精确代价同样是性能。这两个参数的合理组合决定了整个仿真的稳定性和速度。每个shape的引擎属性里最需要注意的是摩擦系数。V-REP里物体接触时的摩擦力强度很多情况下不是全局设置的而是shape属性里的值在起主要作用。比如我做双足机器人时脚底与地面的摩擦系数设太低机器人一直打滑全局参数怎么调都没用最后修改脚底shape的摩擦系数才解决。3.3 时间步长、迭代次数、阻尼的组合策略这三组参数在综合起作用。物理引擎每仿真一步都要解一遍约束方程迭代次数就是约束求解器最多重复计算的次数。时间步长则是两步之间的物理时间间隔。如果你步长太大物体单步位移过大碰撞检测容易漏也就是俗称的“穿透”。如果迭代次数太少约束解算得不够收敛物体就像在“发抖”。我的经验是做关节力矩控制时间步长默认的50毫秒对应50Hz控制频率其实偏低你可以第一步先缩到20毫秒也就是50Hz不行再缩到10毫秒甚至5毫秒。迭代次数Bullet默认的值通常够用但如果关节连接处出现抖动优先把迭代次数往上调而不是继续调阻尼。阻尼这块也要小心。线性阻尼和角阻尼能抑制运动但用多了会让运动看起来“发黏”。力矩控制的本质是力的交互阻尼过高会让关节响应迟钝你给的力矩像打在棉花上。所以调阻尼应该是辅助手段而不是主要手段优先保证步长和迭代合理阻尼只做细微修正。3.4 引擎属性对关节力矩控制的隐藏影响很多人不知道同一个关节目标力矩换一个物理引擎结果完全可能不一样。原因在于各引擎对关节约束的处理方式不同尤其是摩擦力、阻尼这些隐式参数各引擎的默认值差异很大。Bullet在默认参数下关节的电机输出会比较“脆”目标力矩变化能很快反映到关节运动上。ODE的关节约束相对硬一些力矩加到关节上以后表现出的响应没有Bullet那么灵敏。Vortex因为模型更精细同一个目标力矩在低速和高速下的表现会有微妙差别更适合以后做高保真控制算法验证。这提醒我们一件事在V-REP里做力矩控制结论一定不能脱离引擎属性单独看。你这个力矩增益调得“刚好合适”很可能只是刚好适配了某个引擎、某组参数。想要结论稳健至少要在两种引擎下各跑一遍看看差异在可接受范围里才算数。这也是我在给客户做仿真评估时比较坚持的一条原则。4. 实操案例从零搭一个关节力矩斜坡测试台4.1 场景搭建思路理论说再多不如亲手搭一个例子。我这里给出一个非常简洁但信息量足够的测试台一个基座一个旋转关节一根悬臂连杆。基座固定在世界的原点关节安装在基座顶端连杆通过关节连接初始状态让连杆水平伸出。场景的关键是连杆和关节之间要建立正确的父子关系关节是连杆的父对象。在V-REP里如果你把父子关系搞反了整个链会乱套力矩控制也没法正常工作。搭建好以后先把连杆的mass和inertia数据确认一遍。如果你是用V-REP自带的正方体/圆柱体形状它会自动计算质量和惯性。如果是从外部CAD导入的模型必须手动检查形状的密度、质量不然算出来的重力矩会错。4.2 参数配置清单参数配置直接给一个可复现的清单方便大家对照着设。关节的电机最大力矩Fmax按前面算的留出余量设成10N·m。目标力矩设成力矩斜坡从0开始逐渐增加方便观察关节从静止到运动的临界点。连杆质量设成2kg质心到关节轴0.3m这样理论上重力矩是5.88N·m临界目标力矩应该在这个值附近。物理引擎用Bullet时间步长设成20ms约束求解迭代次数按默认或者稍微调高一点建议设成100。整个仿真时长设成5秒方便采样足够多的数据点。从这里能看出来一个规律把“理论上应该发生什么”先算清楚再去看仿真输出去印证。否则你连自己做出来的结果是对是错都判断不了。4.3 用脚本实现力矩斜坡与数据记录脚本逻辑很清晰每仿真步目标力矩从0开始按每秒增加2N·m的速度往上加然后记录当前时间、目标力矩、实际输出力矩、关节位置和关节速度。function sysCall_init() joint sim.getObjectHandle(Revolute_joint) sim.setJointMaxForce(joint, 10.0) sim.setJointTargetForce(joint, 0, true) dataFile io.open(torque_ramp_log.txt, w) dataFile:write(time target actual position velocity\n) end function sysCall_sensing() local t sim.getSimulationTime() local target 2.0 * t -- 目标力矩不超过Fmax if target 8.0 then target 8.0 end sim.setJointTargetForce(joint, target, true) local actual sim.getJointForce(joint) local pos sim.getJointPosition(joint) local vel sim.getJointVelocity(joint) dataFile:write(string.format(%.4f %.4f %.4f %.4f %.4f\n, t, target, actual, pos, vel)) end function sysCall_cleanup() dataFile:close() end注意sysCall_sensing里写文件可能会影响仿真实时性但因为我们关心的是数据统计不是实时性所以完全没问题。如果你关心和控制频率相关的表现就把数据记录放到后处理不要在每个仿真步都做IO操作。4.4 结果怎么看、怎么判断物理引擎行为正常仿真跑完以后把torque_ramp_log.txt拖到绘图工具里画曲线。你会看到典型的过程目标力矩线性增加实际输出力矩也跟随升高但在目标力矩超过重力矩之前连杆基本不动速度和位置都趋近于0。等目标力矩逼近5.88N·m时连杆开始缓慢转动速度从0往上爬。这个临界点出现的时间就是你判断仿真是否“符合物理直觉”的关键。如果临界点在3N·m就出现了说明你的连杆质量或者重力方向没设对。如果一直到8N·m连杆还静止不动说明要么Fmax被限幅要么阻尼系数过大了。有个容易被忽视的点是仿真里的关节即使不做力矩控制也有默认的电机和摩擦特性。你在每一步设目标力矩之前最好先确认关节没有开启位置控制模式否则前面的力矩设置会被位置PID覆盖表现出来的行为就会很奇怪。这类问题排查起来很浪费时间我一般在搭建模型初期就把关节控制模式梳理清楚再也不会在复现时产生这种混乱。5. 常见问题与避坑经验5.1 关节力矩控制排错速查表我把这几年被人问得最多的问题整理成一张表每个问题的排查思路都按优先级排好照着顺序查基本都能找到原因。问题现象首要排查点次要排查点处理建议设了目标力矩但关节不动Motor是否勾选、控制模式是否切到力矩模式Fmax是否小于目标力矩用脚本强制设置模式并打印目标力矩确认关节运动方向相反target force的signed参数是否设置正确连杆的建模方向是否跟期望运动方向一致把signed改为false或取反关节出现高频抖动时间步长是否过大约束迭代次数不足减小步长到10ms迭代次数调到100以上实际输出力矩始终达不到目标Fmax限幅了阻尼参数被调得过高提高Fmax到目标力矩的1.5倍并降低阻尼同一套参数换引擎后表现差异大引擎的隐式物理属性不同各引擎默认参数不一致按引擎分别调参不要追求同一套参数通吃目标力矩已经很大但速度还是上不去角阻尼过大关节处的摩擦被默认开启调低角阻尼或关闭关节阻尼这张表不是万能的但覆盖了80%新手常踩的坑。遇到没有列出的问题建议第一个动作永远是打印输出。你完全可以把目标力矩、实际输出、关节速度、位置这四组数据全部打印出来观察是哪一步出了问题。仿真调试跟代码调试一样不要靠猜要靠数据。5.2 我建议的引擎属性初始模板最后分享一套我常用在关节机器人仿真上的初始参数模板。这套模板不一定最优但能让绝大多数场景先稳定跑起来再做微调。Bullet引擎下时间步长20ms迭代次数100线性阻尼0.1角阻尼0.05。关节的Fmax设为关节理论最大负载的1.5倍。如果目标力矩需要考虑重力补偿优先用脚本计算不要在对话框里手填静态值因为负载一变化静态值就废了。ODE引擎下建议把global erp设得比默认值略低global cfm略高一点这样关节约束会更软不容易弹开。Vortex下尽量开启自动摩擦模型但要把每个接触物体的摩擦系数过一遍不然会出现一件“摩擦力过大机器人立定不动”的怪事。另外一个小建议一个模型持续调了很久还是不稳定别硬扛直接把物理引擎换掉试试。换引擎这一步往往比调几十个参数还快见效。V-REP对多引擎的支持本身就是很大的优势好好利用它不要让它变成劣势。5.3 关于“仿真里的力矩控制”与“真实机器人力矩控制”的差别写到这里我想多说一句。很多人做仿真久了会觉得仿真里的力矩控制参数能直接迁移到真机上这是很危险的假设。仿真里的电机是理想模型没有电流环延迟没有摩擦非线性没有温度漂移这些在V-REP里要么被简化要么被忽略。我做的真实力矩控制项目里同样的目标力矩真机上会发生明显的抖动和响应滞后因为真实电机有惯性负载、减速器背隙、连接件弹性这些仿真里很难精确建出来的东西。仿真里建模的目标是验证你的算法逻辑、计算力的大小、观察运动的趋势而不是复刻真机的每一个细节。所以我的习惯是仿真结果要有“物理正确性余量”仿真里留了10%余量的力矩值到真机上要留30%以上。这样算法迁移时才不会因为一点细节差异就崩掉。这也算是我做多年机器人项目积累下来的一个实在经验。
阅读完成 · 觉得有帮助?
咨询建站