ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

UR3机械臂模型从SolidWorks到URDF转换全流程详解

UR3机械臂模型从SolidWorks到URDF转换全流程详解

遇到的第一道坎:拿到了UR3模型却动不起来

做UR3机械臂相关项目,无论是ROS仿真、MoveIt运动规划,还是数字孪生可视化,几乎都逃不过同一个环节——把SolidWorks里的装配体模型转成URDF文件。CAD模型里零件还挂着一堆配合关系,坐标系默认习惯和ROS的约定又不一样,直接导出STL却忘了定义关节轴,结果就是模型在Rviz里散成一盘零件、关节完全不听使唤。

这篇文章就是把我实际转换UR3机械臂模型的完整过程拆给你看:从SW2URDF插件安装开始,到逐个关节标注坐标轴、设置关节限位、处理网格和惯性参数,再到Rviz和Gazebo里的验证修正,最后补上实战中容易踩的坑。整个过程不需要从零手写URDF,但你也别指望一键导出就能直接用,中间那几步手工调整才是决定成败的关键。

1. URDF承载的东西比看起来多得多

URDF本质是一个XML文件,但它不是简单的“零件清单”,它描述的是整棵运动学树——哪个零件是固定的、哪个关节绕着哪根轴转、转角范围是多少、零件质量分布如何、碰撞检测用什么样的简化形状。这些东西在SolidWorks装配体里并不是没有,而是以一种“隐式”的方式存在:装配体里的配合关系只是几何约束,URDF里每条joint都必须显式指定parent和child,并且给出joint坐标系相对parent坐标系的位姿。

UR3机械臂从结构上看再典型不过:6个旋转关节串成一条开链,从基座往上分别是肩关节、肘关节、腕部三个关节。关节数量不多,但腕部几个关节的中心点距离很近,坐标轴方向稍有偏差,后面做逆解的时候就容易出诡异结果。更麻烦的是,UR3模型在SolidWorks里很可能是一大堆零件的总装,有些供应商给的模型甚至连螺纹孔、波纹管保护套都画了进去,这些零件对运动学毫无贡献,却会让网格文件体积暴涨、仿真卡成幻灯片。

所以转换之前必须想清楚一件事:我们要的URDF不是“原封不动的3D展示模型”,而是“可以用来做运动学和动力学仿真的机器人描述”。这两个目标的诉求甚至有点冲突——视觉细节越丰富越好,但碰撞网格越简单越好、文件越小越好。理解了这个出发点,后面每一步做减法的时候就都不会犹豫了。

2. 转换前先把模型和工具准备好

2.1 工具清单

我用到的工具并不复杂,但每样都有不可替代的用途:

工具用途说明
SolidWorks 2016+模型处理与插件宿主版本太老可能装不上新插件
SW2URDF插件核心转换工具开源免费,直接从官方渠道下载
Ubuntu + ROS环境URDF验证与调试建议装在虚拟机或Docker里
check_urdf / gazebo语法检查、仿真验证ROS自带工具,后面会用到
MeshLab或Blender网格简化和格式修复STL/DAE的后期处理
文本编辑器手工微调URDF不要迷信图形化工具,关键数值要能自己改

SW2URDF插件是最重要的一环。它做的事情很直观:你在SolidWorks装配体里逐个创建参考坐标系,把每个关节的旋转轴对齐到Z轴,然后它就能按你标注的顺序生成URDF文件,同时把每个link的模型导出成STL或DAE格式。整个过程是半自动的,几何信息它帮你算,但“哪个零件属于哪个link”“关节轴朝哪边”这些语义信息需要你亲手标注。

2.2 模型减法:该删的零件别心疼

动手转换前,先花点时间整理SolidWorks里的模型。UR3模型里常见的“减分项”包括:装饰性螺钉螺母、线缆接头、波纹管、标签铭牌、轴承内部的滚珠和保持架。这些零件在CAD里画出来费功夫,但转成URDF只会增加负担——每个小零件都是一个独立的网格文件或实体,光是指派到正确的link就要多花不少时间。

建议做法是先在一个“简化配置”里把能压缩的零件隐藏或删除,再把同一段结构里相对固定的零件用“合并实体”或“另存为单一零件”的方式整合。比如基座部分如果由七八个零件装配而成,但它们之间没有相对运动,完全可以把它们合并成一个base_link的模型,减少后面标注时的干扰。这个步骤虽然不在转换流程之内,但对最终URDF的简洁程度影响极大。

2.3 关节树规划:动手前先画一棵树

不要一上来就打开插件乱点,先在纸上把UR3的关节树理清楚。UR3典型的关节链是:

  1. base_link → shoulder_link(绕基座垂直轴旋转,对应J1)
  2. shoulder_link → upper_arm_link(绕肩部水平轴旋转,对应J2)
  3. upper_arm_link → forearm_link(绕肘部水平轴旋转,对应J3)
  4. forearm_link → wrist_1_link(绕前臂轴线旋转,对应J4)
  5. wrist_1_link → wrist_2_link(绕腕部水平轴旋转,对应J5)
  6. wrist_2_link → wrist_3_link(绕末端法兰轴线旋转,对应J6)

每个关节都必须明确:旋转轴是哪个方向、关节坐标系原点在哪。URDF没有“装配树”里那些面和面的贴合关系,坐标系需要你自己用SolidWorks的参考坐标系功能逐一定义。这个规划越清晰,后面标注的时候就越少返工。

3. 核心实操:SW2URDF插件转换全流程

3.1 插件安装与激活

SW2URDF插件的安装不复杂,但有一个容易卡住的细节:从官方渠道下载的包解压后,里面不只是dll文件,还带配置文件和示例。安装时要先关闭SolidWorks,把解压出来的文件夹放到固定位置,再打开SolidWorks的“工具-插件”,勾选对应的add-in。有些版本要求你手动把dll文件注册到Windows注册表,这一步网上说法不一,实际操作时如果插件没有出现在列表里,多半是文件路径带了中文或者权限不够,用管理员身份运行SolidWorks就能解决。

装了插件以后,工具栏里会出现“Export to URDF”的入口,但这个按钮在装配体模式下才可用,零件模式下点了没反应。我第一次就栽在这个细节上,后来发现必须先打开装配体文件,才算真正激活了导出功能。

3.2 坐标系的建立:让Z轴对齐关节回转轴线

URDF的joint规则非常明确:关节坐标系的原点位于关节轴线上,Z轴与旋转轴重合,旋转的正方向遵循右手定则。SW2URDF插件的工作方式就是读取你预先建好的参考坐标系,把坐标系Z轴的方向当作关节轴的方向。

在SolidWorks里建立参考坐标系需要两步:先在圆柱表面或轴类零件的中心线上创建参考轴,然后基于这个轴建坐标系。对UR3的J1来说,就是基座正中心那条旋转轴线,坐标原点放在基座顶部平面附近;对J2来说,是连接基座和肩关节的那根水平销轴。

这一步最容易犯的错误:用零件的默认坐标系直接当关节坐标系。SolidWorks零件的默认坐标系是“前视基准面X水平、Y竖直、Z向外”,和关节轴八竿子打不着。如果直接用它导出,后面会出现关节旋转轴偏移甚至镜像的错误。正确做法是每个关节都新建专属坐标系,一个关节命名一个,比如j1_origin、j2_origin,这样后续在插件界面里选择时一目了然。

3.3 在插件界面里逐关节标注

打开SW2URDF的导出窗口,界面左边是两个列表:一个对应link,一个对应joint。你需要按顺序添加每个link,然后为每个link指定它在装配体里对应的SolidWorks零件(可以多选多个零件,它们会自动合并到同一个link下)。随后在joint列表里,选择type为revolute,设置parent和child,再指定对应的参考坐标系。

UR3的6个关节全是revolute类型,这一点很省事。每个joint都要设置极限范围,UR3官方给出的各关节角度范围很大,有些甚至超过±360°,但实际URDF里建议写官方标准值。如果不确定具体数值,可以先把范围设成-3.14到3.14这个常规值,仿真阶段再根据实际需求修正。扭矩和速度极限在纯运动学仿真里不发挥作用,但如果后面要接Gazebo做动力学仿真,这些值必须和实际伺服参数对上,否则机械臂会很早就“没力气”抬不起来了。

标注顺序我建议从基座一路往上走,和关节树的拓扑顺序保持一致。这样插件在生成时不容易出现parent指向未定义link的问题,后期检查也方便。

3.4 导出设置和惯性参数

所有关节标注完成后,窗口下方会列出每个link的质量属性。SW2URDF会从SolidWorks的材质和质量属性里自动读取质量、质心和惯性张量。这里有个很容易被忽略的问题:SolidWorks的默认单位是毫米和克,而URDF要求的是米和千克。插件理论上会做换算,但不同版本转换结果未必可靠,导出后一定要抽查。

我习惯在导出前给模型里的所有零件指定明确且真实的材质(铝、钢、塑料等),否则SolidWorks里有些零件的质量是默认的1克,惯性张量算出来毫无意义。URDF的惯性数据如果严重偏离实际,Gazebo里机械臂要么抖得像筛子、要么直接塌下去。

导出时网格格式我推荐这样选:可视化网格用DAE格式,因为可以保留颜色和材质,而且DAE是带纹理的三角网格,在Rviz里显示效果好;碰撞网格用STL格式并手动简化,因为碰撞检测不需要那么高的精度,面数越少仿真越快。SW2URDF生成的文件包括一个urdf目录和一个meshes目录,URDF里通过相对路径引用网格文件,所以两个目录要放在一起,不要单独挪动文件。

4. 导出后必须做的手工修整

4.1 先过语法检查这一关

生成URDF后第一步不是急着打开Rviz,而是先跑一遍检查工具。ROS环境里自带check_urdf命令:

check_urdf ur3.urdf

这个命令会逐条解析每个link和joint,打印机器人的关节树,同时报告有没有缺parent、坐标系没闭合之类的错误。如果看到ERROR级别信息,先不要继续往下走,把报错的行号记录下来逐条排查。

不过check_urdf只能检查格式正确性,检查不了“语义正确性”。比如关节轴方向反了、link原点偏了5公分,它都不会报错,因为从格式上看这些完全合法。所以语法检查通过只是第一关,后面还需要结合可视化来验证。

4.2 坐标系和旋转轴方向修正

我实测转换UR3模型时,最容易出问题的位置集中在腕部。UR3的J4和J6都绕前臂方向旋转,J5绕垂直于前臂的方向旋转,这三个关节轴的夹角在模型里常常因为基准面选择偏差而出现微小倾斜,视觉上看不出,但在运动学仿真的末端定位误差会被放大。

排查方法很简单:在Rviz里加载URDF,通过joint_state_publisher拖动J1滑块,观察整个机械臂是否只绕预期轴转动、转动方向是否正确。如果发现转动轴方向反了,直接把URDF里对应joint的axis的x/y/z分量取反即可,不需要回SolidWorks重新标注。如果发现joint原点位置不对,那就得回到SolidWorks里调整坐标系后再重新导出,硬改URDF里的origin数值也可以,但比改坐标轴麻烦,因为你得自己算平移量。

这类问题,我的经验是宁可在SolidWorks里多花十分钟确认坐标轴,也不要导出后在URDF里反复试凑。后者虽然见效果快,但很容易调出一个“看起来能动但数值很奇怪”的模型,后面做逆解验证时会坑自己。

4.3 网格文件瘦身

UR3模型在SolidWorks里原本可能有几万个面,直接导出的STL文件动辄几十MB。Rviz加载起来勉强能看,但Gazebo里做物理仿真的时候,每帧都要对碰撞网格做碰撞检测,面数越多计算量越大,仿真频率会被拖到几Hz,完全没法用。

所以导出后我为UR3模型做的另一件重要事情是简化碰撞网格。用MeshLab打开每个link的STL碰撞网格,做一次重网格化或二次简化,把面数压到一两千面以内。注意只简化碰撞网格,可视网格保留细节,因为视觉上用户还是希望看到一台像模像样的UR3。

如果碰撞网格的形状和真实结构偏差太大,后续做自碰撞检测时会有很多误报。UR3的连杆形状比较规整,大多数link可以用圆柱或长方体近似表示,直接在URDF的collision里替换成cylinder或box几何体,连网格文件都不用加载,效果还更好。Gazebo里常见的做法就是能用基本几何体碰撞模型,就不加载网格碰撞,性能提升非常明显。

4.4 补全Gazebo仿真所需标签

SW2URDF生成的文件默认包含运动学信息,但Gazebo物理仿真还需要transmission和gazebo标签。transmission把关节和执行器关联起来,对UR3的6个关节都要定义,它决定了Gazebo能不能通过驱动力矩控制关节。没有这个标签,Gazebo加载模型后关节会变成“自由铰链”,机械臂直接瘫在地上。

一个标准的transmission块长这样:

<transmission name="tran_j2"> <type>transmission_interface/SimpleTransmission</type> <joint name="j2" /> <actuator name="j2_motor"> <mechanicalReduction>1</mechanicalReduction> </actuator> </transmission>

此外,每个link的gazebo标签可以设置摩擦系数和材质,末端执行器如果带了吸盘或夹爪,还可以挂上额外的仿真插件。UR3这种轻型机械臂的关节摩擦参数不建议设太大,否则低速跟踪时会有明显抖动。

5. 验证环节:让模型写实又写意

5.1 Rviz可视化验证

URDF准备阶段最直观的验证工具就是Rviz,配合joint_state_publisher面板,可以手动拖动滑块控制每个关节。打开后重点看三件事:整体机械臂是不是从基座开始连续延伸,有没有零件悬空或穿插;每个关节拖动时,运动是否和真实UR3一致;所有模型有没有出现拉伸变形或坐标轴翻转。

常见的视觉得问题包括:零件颜色丢失、整体灰蒙蒙一片。DAE网格如果没带材质纹理,Rviz里就会显示成灰色。这可以在URDF的material标签里手工指定颜色,比如给UR3涂上标志性的红色:

<material name="ur3_red"> <color rgba="0.85 0.1 0.1 1.0" /> </material>

把视觉网格的材质指向这个material,模型立刻就有辨识度了。

5.2 Gazebo物理仿真验证

Rviz里能动,不代表Gazebo里也能正常。Gazebo验证主要考察两点:模型能不能稳定站住不塌陷、关节能不能在扭矩驱动下正常转动。

我遇到过最典型的问题是:UR3在Rviz里看起来一切正常,但Gazebo一加载就直接弹开或者惯性张量对角线元素出现NaN。这类问题九成出在惯性参数上。排查方法是逐个link检查它们的inertial标签,确认质量在合理范围(UR3整机大约十几公斤,单根连杆质量在0.5到4公斤之间),质心位置在零件几何中心附近,惯性张量的数值单位不是离谱的1e7。

如果懒得自己算惯性,有个取巧的办法:在SolidWorks里对每个link单独做质量评估,把质心和惯性张量抄出来再按单位换算填入URDF。SolidWorks算惯性的单位是千克·平方毫米,URDF是千克·平方米,注意换算倍率是1e-6。

5.3 结合MoveIt配置做最终校验

如果URDF最终要用于运动规划,建议再用MoveIt Setup Assistant重新加载一遍模型,生成规划组、配置自碰撞矩阵。这个工具能重新生成碰撞矩阵并标记出哪些link对永远不会碰撞,这本身就是一次对模型质量的软检测。如果模型里存在零件穿插,生成的碰撞矩阵会非常稀疏甚至报错。

另外,做一些简单的正运动学验证——把URDF加载到Python环境里,用urdfpy或者pybullet读取模型,随机给一组关节角,计算末端位置,再和UR3官方手册里的正解公式比对。20组随机值以内如果偏差都在毫米级以下,说明模型的运动学结构基本可靠了。

6. 常见问题与排查技巧实录

6.1 插件导出的STL文件无法保存

现象:点击导出后,提示保存成功,但meshes目录里只有DAE没有STL,或者STL文件是0字节。原因:旧版本SW2URDF在某些系统上调用SolidWorks另存STL的接口不稳定,特别是模型包含多个实体的时候。解决:不要依赖插件保存碰撞网格,先在SolidWorks里把每个link对应零件手动另存为STL,再整理到meshes目录下,然后在URDF里把collision的filename路径改一下就行。

6.2 关节轴反了

现象:Rviz里拖动关节滑块,机械臂确实动了,但运动方向和真实方向相反,比如J2应该往前摆,结果往后摆。原因:坐标系Z轴的方向建反了,或者参考轴的方向跟实际转动方向不满足右手定则。解决:最快修正方法是改URDF里的axis数值,将正负号整体取反。这种改动不用回SolidWorks,但一定要改完后在Rviz里重新验证。注意,两个坐标轴分量同时取反等于轴反向,如果只是把x和z对调,那是完全不同的错误,会变成旋转平面不对,需要回到SW修改坐标系重导。

6.3 模型加载后link位置全部错位

现象:URDF加载成功,但每个零件的位置都是乱的,整个机械臂像被拆散了一样。原因:joint里的origin值不正确。SW2URDF插件读取的参考坐标系和实际零件位置没有正确对应,通常是因为定义坐标系时没有和零件实体关联,而是建在了全局位置上。解决:回到SolidWorks,把每个关节的参考坐标系移到对应关节轴线上,并保证它和所关联零件之间有实体引用关系。如果只是个别joint位置错,也可以手工修改URDF里origin的xyz值,但前提是你清楚这组偏移量来自哪里。

6.4 单位问题导致惯性参数异常

现象:Gazebo里机械臂站不住,或者轻轻一碰就疯狂抖动。原因:惯性张量数值用了克·平方毫米,或者SolidWorks里的密度默认值不对,导致URDF里质量只有0.001kg。解决:检查每个link的mass数值,如果小于0.1kg大概率是单位换算问题。重新在SolidWorks里设置100%密度材质,再导出。确认m为单位、kg为单位之后,重新生成URDF。

6.5 模型太大导致Rviz卡顿

现象:Rviz拖动视角时帧率很低,Gazebo仿真频率只有3Hz。原因:可视化网格面数太多,或者碰撞网格没有做简化。解决:对每个link的网格文件做简化处理。可视化网格控制在1万面以内,碰撞网格用基本几何体或一千面以内的简化STL。UR3这种小型机械臂,整机所有网格加起来控制在3万面以内,仿真流畅度会好很多。

6.6 中文路径问题

现象:URDF里的mesh路径明明正确,但模型始终加载不出网格。原因:SolidWorks安装路径或工程文件夹包含中文,插件导出时写入的相对路径乱码。解决:统一用英文路径,把整个工程目录放到类似D:\ur3_project这种完全不含中文的路径下,这个习惯能避开奇奇怪怪的编码问题。

网格转换只是第一步,这还远远不够用

把UR3从SolidWorks转到URDF,本质上是从“设计表达”过渡到“计算表达”的过程。SolidWorks里每个零件只关心长什么样、怎么装配到一起,而URDF里每个link和joint的定义都在为仿真计算服务——坐标轴方向决定运动学计算的正负号,惯性参数决定动力学仿真的物理响应,碰撞网格决定规划时的安全边界。所以你会看到整个流程中反复出现两个动作:定义坐标轴、做网格简化。

从我经手的项目来看,UR3机械臂模型转换的难点从来不是软件操作本身,而是有没有把机械臂的运动学结构在动手之前彻底想清楚。只要关节树规划对了、坐标轴方向定义准了,导出URDF里的技术工作在半小时内就能完成;真正耗时的是后面一遍遍在仿真环境里调参、验证、修正的过程。

最后分享一个小技巧:转换后不要急着删除SolidWorks源文件,UR3这类6轴机械臂的模型后续如果要加末端工具、改腕部结构、生成新的碰撞模型,八成还要回到源文件里改。把原始装配体和生成出的URDF放在同一个工程目录里,用版本号管理起来,省下的返工时间远超当初做“模型减法”花的那点功夫。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进