第3章 几何与可视化

标签 · 导入外部模型 · 颜色与纹理

好,咱们直接进入正题。URDF 里怎么让机器人「看起来像那么回事」?说白了就靠三个东西:<geometry> 定义形状,<mesh> 把外部模型拽进来,<material> 给皮肤上色。我刚开始做机器人仿真时,觉得随便画个方块就能跑,后来发现——嗯,视觉上太丑,连调试心情都受影响。这一章我把压箱底的经验翻出来,咱们一次聊透。

几何与可视化 <geometry> 基本体 box / cylinder / sphere <mesh> 外部模型 STL / Collada (DAE) <material> 颜色纹理 rgba / texture 可视化 + 碰撞检测双用途

3.1 <geometry> 标签:搭积木的基础

你想想看,URDF 里的每个 link 都得有个形状,不然仿真器里就是一团空气。<geometry> 支持三种原生体:box、cylinder、sphere。我个人习惯在原型阶段全用基本体,快,而且不容易出 bug。

<link name="base_link">
    <visual>
        <geometry>
            <box size="0.4 0.3 0.1" />
        </geometry>
    </visual>
</link>

box 的 size 是 xyz 半边长(注意是全长,不是半长)。cylinder 要指定 radius 和 length,sphere 只一个 radius。我在项目里遇到过一个问题:圆柱的 length 写成了直径,结果 Gazebo 里轮子直接陷进地面一半…… 所以记得,length 是高度,不是直径。

💡 我的小习惯: 基本体做碰撞检测时,尽量用 <cylinder> 代替 <box> 做轮子,因为圆柱的碰撞计算更稳定,不容易卡地形。

3.2 <mesh> 导入外部模型:让机器人有灵魂

基本体太单调?那就上 <mesh>。你可以把 SolidWorks、Blender 导出的 STL 或 Collada(.dae)文件塞进来。我一般用 STL 做碰撞,用 DAE 做可视化(因为 DAE 自带颜色)。

<link name="arm_link">
    <visual>
        <geometry>
            <mesh filename="package://my_robot/meshes/arm.dae" scale="1.0 1.0 1.0" />
        </geometry>
    </visual>
</link>

注意 filename 的路径写法。我推荐用 package:// 形式,这样不管你的包放在哪,ROS 都能找到。曾经有个同事直接把路径写进去,结果换台电脑模型全红…… 嗯,后来他老老实实改成了 package 路径。

格式优点缺点
STL (.stl)通用、轻量、碰撞稳定无颜色信息,二进制/ASCII混用
Collada (.dae)支持颜色、纹理、材质文件较大,有时导入会丢材质
OBJ (.obj)带纹理坐标,可读性好URDF 官方不直接支持,需转DAE
⚠️ 我曾经踩过的坑: 用 Blender 导出 DAE 时,记得把「变换」里的缩放应用掉(Ctrl+A)。否则 URDF 里模型可能歪七扭八,scale 调半天都对不上。

3.3 <material> 颜色与纹理:给机器人穿衣服

光有形状还不够,颜色对了才能一眼认出零件。<material> 可以定义在 link 内部,也可以单独拎出来作为全局资源。我通常把常用颜色放在 URDF 顶部,像调色板一样。

<material name="blue_metal">
    <color rgba="0.2 0.4 0.9 1.0" />
</material>

<link name="chassis">
    <visual>
        <geometry>
            <box size="0.5 0.4 0.2" />
        </geometry>
        <material name="blue_metal" />
    </visual>
</link>

rgba 四个值范围 0~1,不是 0~255。我见过有人写 rgba="255 0 0 1",结果 Gazebo 里一片惨白…… 记住,0~1 归一化。

📌 纹理贴图怎么搞? 虽然 URDF 标准里 <material> 支持 <texture>,但 Gazebo 和 Rviz 的支持程度不一样。我个人的经验是:用 DAE 模型自带的纹理最稳,或者直接在模型文件里引用图片。如果你非要在 URDF 里写纹理,记得用 filename 属性指向 png/jpg。

再说一个细节:<material> 可以被子 link 继承吗?不行。每个 link 的 visual 都得显式指定 material。我一开始也以为会像 CSS 一样层叠,结果…… 机器人一半身子是透明的。所以,每个 visual 块都老老实实加上 <material> 吧。

3.4 可视化与碰撞的几何分离

这是很多新手忽略的点。URDF 里 <visual> 和 <collision> 可以完全不同。比如你有一个精细的 DAE 模型做视觉,但碰撞用一个简单的圆柱体,性能会好很多。

<link name="head">
    <visual>
        <geometry>
            <mesh filename="package://bot/meshes/head.dae" />
        </geometry>
    </visual>
    <collision>
        <geometry>
            <sphere radius="0.15" />
        </geometry>
    </collision>
</link>

我做过一个机械臂项目,视觉模型有 2 万面,碰撞用 6 个球体包络,仿真速度直接翻倍。你想想看,何必让物理引擎去算那些螺丝孔的碰撞呢?

🔧 避坑指南: 碰撞几何的原点一定要和视觉几何对齐。我曾经偷懒,碰撞球体没平移,结果机械臂还没碰到东西就弹开了…… 调试了半小时才发现是碰撞体位置偏了 5 厘米。