UR5机械臂从STL到URDF:sw2urdf导出与Gazebo仿真指南
2026/9/16 21:03:49 网站建设 项目流程

简介:面向ROS机器人开发者和仿真试验人员,资源包将UR5六轴工业机械臂的三维模型完整转换为URDF描述文件并打包,省去从零编写连杆、关节、质心及惯量参数的繁琐过程,解决CAD模型难以直接应用到Gazebo、Matlab等仿真环境的痛点。压缩包共13个文件,以7个STL网格文件提供三维几何可视化,搭配核心URDF模型、两个launch启动文件,以及yaml配置、xml描述和txt说明文件,总大小仅5.5MB,轻量且目录完整。目前已有549人学习下载,适合需要快速搭建UR5仿真平台,或进行运动规划与控制研究的机器人开发入门及进阶用户。借助包内现成的URDF与网格文件,可直接在ROS中加载UR5模型,开展关节驱动、碰撞检测、路径规划及控制算法验证等实验;同时可导入Matlab或Gazebo做动力学分析和系统验证,大幅节省建模与参数标定时间,提升研究效率。

1. 拿到 STL 后,为什么 UR5 要先转成 URDF 才能进仿真

很多人从 SolidWorks 导出 UR5 模型时,以为拿到.STL就算有了“机器人模型”。实际上在 Gazebo、MoveIt 或 CoppeliaSim 眼里,STL 只是一堆三角面片,没有关节轴、没有限位、没有惯性。UR5 是典型的六轴串联机械臂,运动学建模需要把 shoulder、elbow、wrist 分别定义成可旋转的 revolute joint,并且用坐标变换把 base_link 和六个连杆串起来,这些信息只能由 URDF 描述。ur5_sw2urdf.zip是 sw2urdf 插件导出的完整 ROS 功能包,URDF、STL、launch、关节映射都有,省掉手写 XML 的重复劳动。它更适合 ROS 1 的 Melodic/Noetic 环境,也适合把官方 UR5 参数与自己的三维模型做对拍,用来改夹具或验证算法。

2. 拆开 ur5_sw2urdf.zip:sw2urdf 导出包里到底装了什么

先用unzip打开,看一下 sw2urdf 导出的目录结构。绝大多数这类包会把可编译的 ROS 包直接展开在根目录:

unzip ur5_sw2urdf.zip -d ~/catkin_ws/src/ur5_sw2urdf

这条命令把压缩包解压到 catkin 工作空间的src下,路径和包名保持一致,后续catkin_make才能自动找到它。如果你只是临时看看模型,不解压到工作空间也可以,但后面加载 mesh 时会遇到package://路径找不到的问题。

2.1 包内文件清单

文件/目录作用
ur5_sw2urdf.urdf机器人结构描述,定义 6 个旋转关节和 7 个 link
meshes/base_link.STLLink1.STL等 7 个网格每个 link 对应的三角网格,visual 与 collision 共用
config/joint_names_ur5_sw2urdf.yaml关节名列表,ros_control/MoveIt 用它做关节映射
launch/display.launch启动 RViz 并发布 TF,用于静态检查模型
launch/gazebo.launch把 URDF 生成到 Gazebo 空世界中
CMakeLists.txtpackage.xmlcatkin 包的声明文件,缺少后 ROS 不识别这个包

STL 是三角面片,不包含颜色和材质。sw2urdf 默认把 SolidWorks 装配体的外观简化成纯几何,textures目录在导出时是给 DAE 路径准备的,对 STL 而言,只有在 URDF 的<visual>里手动指定<material>才有效。所以后面在 Gazebo 里看到的 UR5 往往是灰色,这正常,不影响运动学和碰撞。

2.2 joint_names 文件与关节命名规范

config/joint_names_ur5_sw2urdf.yaml的内容通常是这样:

# 来自 sw2urdf 导出的关节名清单 joint_names: - shoulder_pan_joint - shoulder_lift_joint - elbow_joint - wrist_1_joint - wrist_2_joint - wrist_3_joint

这个文件不参与 URDF 解析,而是给controller_managerur_modern_driver或 MoveIt 做关节组映射。如果你后续要接入 ROS-Industrial 的ur_description,注意那边的关节名是shoulder_panshoulder_lift,不带_joint后缀。要不要改,取决于你加载哪一套控制器。我这里更习惯保留 sw2urdf 的名字,因为 mesh 和 joint 一一对应,改名要同时改 URDF、yaml、controller 三处,容易漏。

2.3 launch 文件把模型一步步带起来

display.launch我一般放在 catkin 工作空间编译后直接跑:

cd ~/catkin_ws catkin_make source devel/setup.bash roslaunch ur5_sw2urdf display.launch

catkin_make编译整个工作空间,source让 ROS 找到新包,roslaunch启动 display.launch。launch 文件里最核心的内容是加载 URDF 和发布 TF:

<launch> <param name="robot_description" textfile="$(find ur5_sw2urdf)/urdf/ur5_sw2urdf.urdf"/> <node name="robot_state_publisher" pkg="robot_state_publisher" type="robot_state_publisher"/> <node name="joint_state_publisher_gui" pkg="joint_state_publisher_gui" type="joint_state_publisher_gui"/> <node name="rviz" pkg="rviz" type="rviz"/> </launch>

textfile把纯.urdf直接读到robot_description参数,不需要 xacro 预处理;robot_state_publisher根据关节角计算 TF;joint_state_publisher_gui提供滑块修改/joint_states。如果你把后缀改成.xacro,这里就要换成command="$(find xacro)/xacro ..."的写法,纯 URDF 用textfile更省事。

gazebo.launch是另一条链路。常见写法是:

<launch> <include file="$(find gazebo_ros)/launch/empty_world.launch"/> <param name="robot_description" textfile="$(find ur5_sw2urdf)/urdf/ur5_sw2urdf.urdf"/> <node name="spawn_model" pkg="gazebo_ros" type="spawn_model" args="-urdf -param robot_description -model ur5 -z 0.15"/> </launch>

注意spawn_model需要 gzserver 先启动,所以empty_world.launch要放在前面。-z 0.15是抬高机器人,避免 base_link 陷入地面。如果启动后看不到 UR5,先看rosnode list里有没有spawn_model,再用gzclient查看模型是否生成在世界原点附近。

2.4 为什么必须保留 package.xml 和 CMakeLists

package.xml声明包名、依赖和导出。sw2urdf 生成的版本通常只依赖roscppurdfgazebo_rosrobot_state_publisher。在纯仿真场景,你甚至可以不用catkin_make,直接source /opt/ros/noetic/setup.bashroslaunch绝对路径。但一旦要加载 mesh 依赖的package://路径,就必须让rospack find ur5_sw2urdf能找到这个包,所以保留这两个文件并正常catkin_make是兼容成本最低的方式。

3. 关节与连杆:URDF 如何把 STL 组织成六轴运动学模型

sw2urdf 导出的 URDF 不是简单的模型堆叠,它把 SolidWorks 装配体中的配合关系翻译成了关节约束。读懂这份 URDF,你才能确认 mesh 是不是装错位置、关节轴是不是反了。

3.1 从 URDF 里读运动链

打开.urdf看结构,典型父子关系是这样的:

link前置关节对应 UR5 结构
base_link-基座
Link1shoulder_pan_joint肩部旋转
Link2shoulder_lift_joint肩部俯仰
Link3elbow_joint大臂与小臂连接
Link4wrist_1_joint腕部旋转
Link5wrist_2_joint腕部俯仰
Link6wrist_3_joint末端旋转

在 URDF 中,存在<joint>意味着 child link 相对 parent link 有自由度。要检查运动链是否闭合,最简单的方法是跑一遍 ROS 自带工具:

rosrun urdf_tutorial urdf_to_graphiz ur5_sw2urdf.urdf

这会生成ur5_sw2urdf.gv.pdf,用 graphviz 打开后能直接看出关节树是否为线性链。UR5 就是一条base_link -> Link1 -> ... -> Link6的串联树,没有分支。如果多了分支,往往是 sw2urdf 把 SolidWorks 的固定约束当成子装配体导出了。

3.2 一个 revolute joint 怎么定义

sw2urdf 导出的六个关节基本都是 revolute。以 shoulder_pan 为例,URDF 中类似这样:

<joint name="shoulder_pan_joint" type="revolute"> <origin xyz="0 0 0.089159" rpy="0 0 0"/> <parent link="base_link"/> <child link="Link1"/> <axis xyz="0 0 1"/> <limit lower="-6.2832" upper="6.2832" effort="150.0" velocity="3.15"/> <dynamics damping="0.1" friction="0.0"/> </joint>

origin是 child 坐标系在 parent 坐标系中的位姿,xyz的 z 值0.089159就是 UR5 基座到肩部的高度;axis表示在 parent 坐标系下旋转轴的方向,revolute意味着只能绕这个轴转动。limit控制上下限,effort是最大力矩,velocity是最大转速,三个值都会参与仿真中的碰撞和限位计算。如果轴方向不对,最常见的原因是 SolidWorks 的配合坐标轴与 ROS 的右手系不一致,表现是 RViz 里关节转了但连杆往错误方向甩。

3.3 为什么用 STL,textures 去哪里了

sw2urdf 在导出时可以选择 DAE 或 STL。这里选的是 STL,意味着视觉和碰撞网格共用一套面片。STL 是纯几何,不保存 SolidWorks 的外观颜色,所以textures目录对 STL 渲染基本只是保留给材质系统用的占位。想在 Gazebo 里看到 UR5 本来的蓝色,就得在 URDF 中每个<link>加:

<visual> <geometry> <mesh filename="package://ur5_sw2urdf/meshes/Link1.STL"/> </geometry> <material name="ur_blue"> <color rgba="0.1 0.4 0.7 1.0"/> </material> </visual>

如果 collision 引用同一个 mesh,碰撞检测的计算量会比 DAE 小,因为 STL 三角片结构简单。缺点是没有纹理,真实感差,但对机械臂运动学验证影响不大。

3.4 用 UR5 标准 DH 参数反查 sw2urdf 运动学建模结果

UR5 的标准 DH 表是很多人做运动学建模时对表用的关键。常用参数如下:

jointa (m)alpha (rad)d (m)
shoulder_pan0pi/20.08916
shoulder_lift-0.42500
elbow-0.3922500
wrist_10pi/20.10915
wrist_20-pi/20.09465
wrist_3000.0823

URDF 里不直接写 DH 表,而是通过相邻两个 link 的<origin>平移和旋转隐式表达。用 sw2urdf 导出后,你可以把每个<origin>的 z 值对照 DH 的 d,把 x 值对照 a,把 rpy 的 x 分量对照 alpha,就能确认导出是否正确。UR5 前三个轴的alpha是正负 pi/2,这个方向反了会导致正运动学矩阵的旋转部分互为转置,控制算法在“看起来”没问题时突然反向。

4. 在 Gazebo 里让 UR5 动起来:补全控制器与验证运动学

sw2urdf 导出的 gazebo.launch 只负责把模型放进仿真世界,真正要让六个关节响应指令,还需要补控制器配置和 transmission 声明。

4.1 先补<gazebo>标签,否则模型和地面都在打滑

sw2urdf 直接导出的 URDF 只有结构和网格,Gazebo 能加载,但不会稳定。至少每个 link 要加摩擦和材质,比如 base_link:

<gazebo reference="base_link"> <mu1>1.0</mu1> <mu2>1.0</mu2> <kp>1000000.0</kp> <kd>100.0</kd> <selfCollide>false</selfCollide> <material>Gazebo/DarkGrey</material> </gazebo>

mu1/mu2是库仑摩擦系数,kp/kd是接触刚度和阻尼。全默认时接触阻尼太小,UR5 一压在台面就会像橡胶一样抖。selfCollide保留 false,UR5 模型的自碰撞阈值不好调,true 会导致相邻连杆碰撞抖动。

4.2 控制器选择:从关节状态到位置控制

纯 URDF 没有控制器接口。要在 Gazebo 里驱动六个关节,需要 URDF 里补 transmission 并在 config 中定义控制器。常用控制器类型:

控制器作用
joint_state_controller/JointStateController发布/joint_states,只读
position_controllers/JointGroupPositionController向关节发送位置指令
velocity_controllers/JointGroupVelocityController向关节发送速度指令
effort_controllers/JointEffortController向关节发送力矩指令

一个能直接用的控制器配置写进 yaml:

# config/ur5_control.yaml joint_state_controller: type: joint_state_controller/JointStateController publish_rate: 50 ur5_position_controller: type: position_controllers/JointGroupPositionController joints: - shoulder_pan_joint - shoulder_lift_joint - elbow_joint - wrist_1_joint - wrist_2_joint - wrist_3_joint

然后需要在 URDF 里为被控制的关节补<transmission>,否则 controller_manager 报no hardware interface

<transmission name="tran_shoulder_pan"> <type>transmission_interface/SimpleTransmission</type> <joint name="shoulder_pan_joint"> <hardwareInterface>PositionJointInterface</hardwareInterface> </joint> <actuator name="motor_shoulder_pan"> <mechanicalReduction>1</mechanicalReduction> </actuator> </transmission>

SimpleTransmission把 actuator 状态直接映射到 joint,mechanicalReduction=1意味着电机轴与关节轴 1:1。如果你的模型来自 SolidWorks 装配体,实际传动比是靠减速机实现的,URDF 里不写会得到“电机角度=关节角度”的假设,仿真动力学不准,但运动学验证没问题。

launch 文件里加载 yaml 并 spawn 控制器:

<rosparam file="$(find ur5_sw2urdf)/config/ur5_control.yaml" command="load"/> <node name="controller_spawner" pkg="controller_manager" type="spawner" args="joint_state_controller ur5_position_controller"/>

4.3 手动验证:把六个关节拉到目标角度

启动顺序是:

roslaunch ur5_sw2urdf gazebo.launch roslaunch ur5_sw2urdf controller.launch rosrun rqt_gui rqt_gui

或者用命令行发目标位置:

rostopic pub /ur5_position_controller/command std_msgs/Float64MultiArray "data: [0.0, -1.57, 1.57, 0.0, 0.0, 0.0]" --once

JointGroupPositionController接收的是std_msgs/Float64MultiArray,数据顺序对应 yaml 里 joints 的声明顺序。发送后观察 Gazebo 里第二、第三个关节是否同时转。如果只有一个关节动,说明 transmission 的 joint 名或控制器 joints 列表名对不上,rostopic echo查看 controller 输出的错误名即可定位。

4.4 TF 树和关节角验证

启动后不要急着让机械臂动,先查 TF:

rosrun rqt_tf_tree rqt_tf_tree

TF 树应该显示base_link -> Link1 -> Link2 -> Link3 -> Link4 -> Link5 -> Link6一条链,没有断点。然后在 RViz 添加 RobotModel 和 TF,把 Fixed Frame 设为 base_link。用joint_state_publisher_gui拖动滑块,检查 mesh 之间连接处是否发生“分离”。URDF 里<origin>的坐标如果与 STL 几何不一致,关节角为 0 时看起来是连接的,一转就分离,这就是连杆坐标系定义错了。

5. sw2urdf 转换复盘:最容易漏的 5 个细节

仿真跑通之后,回头再检查这几个点,比在 Gazebo 里肉眼试错快得多。

  1. meshes文件名是否全 ASCII。SolidWorks 导出的 STL 经常带中文或空格,Gazebo 的 ODE 对这类文件名解析会出现 failed to load mesh 但又不高亮报错。常见做法是所有 STL 重命名成Link1.STL这种短名,同时改 URDF 里的 filename。

  2. 单位一定是米。sw2urdf 的 configure 弹窗里MetersMillimeters选错,UR5 的 0.089159 m 高度会变成 89 mm 或反过来。Gazebo 里模型尺寸不对的典型症状是 base_link 陷进 ground 或整个机器人悬浮。

  3. <inertial>别用全零。SolidWorks 里如果没给材质密度,sw2urdf 导出的惯量矩阵可能都是 0,Gazebo 启动时会出现 failed to compute moment of inertia。常见做法是用官方 UR5 的惯量值替换,或者至少给每条连杆的ixx/iyy/izz设一个大于 0.01 的值,否则运动过程会异常扭转。

  4. CoppeliaSim 导入。URDF 不能直接拖进窗口,要用File -> Import -> URDF加载。加载前先把package://ur5_sw2urdf/...改成相对路径或绝对路径,因为 CoppeliaSim 不解析 ROS 的 package 命名。如果只是验证运动学,可以只保留 base_link 和 Link1-Link6 的层级,去掉 collision mesh,仿真速度会快很多。

  5. 每次转换后先做一次静态检查:

check_urdf ur5_sw2urdf.urdf rosrun urdf_tutorial urdf_to_graphiz ur5_sw2urdf.urdf

check_urdf会列出所有关节和父子关系;urdf_to_graphiz生成的 PDF 中,箭头方向就是驱动顺序。把 PDF 和 SolidWorks 装配树放在同一屏对一遍,往往一眼就能发现shoulder_liftwrist_2的 joint 轴正方向反了。这种问题在仿真里表现为前三个关节位姿吻合、第四个关节开始末端偏转,用运动学对表很难找,图检查最直接。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询