Rerun 加载与驱动 URDF 机器人模型实战:内置导入器、命名帧 Transform3D 与 rr.urdf 工具
【免费下载链接】rerunVisualize, query, and stream to train on multimodal robotics data.项目地址: https://gitcode.com/GitHub_Trending/re/rerun
Rerun 针对 ROS 生态中最常见的机器人描述格式 URDF(Unified Robot Description Format)内置了一个文件导入器:只要把.urdf文件交给日志 API(Python / Rust / C++ 的log_file_from_path),它就会自动解析网格引用、加载几何体为 Rerun 实体、并为每个 link 生成带 frame ID 的关节变换。读完本文你将掌握:URDF 导入器在底层做了什么、如何在运行时用命名帧的Transform3D驱动关节运动、如何用rr.urdf.UrdfTree访问关节/连杆结构并计算关节变换,以及如何把 URDF 合并进一个已经打开的录制(例如 ROS 2 MCAP)中。
内置 URDF 导入器与一次导入背后发生的事情
Rerun 内置了面向 URDF 的UrdfImporter(导入器名称为rerun.importers.Urdf),实现在 crates/data_flow/re_importer/src/importer_urdf/mod.rs。在导入器框架中,所有导入器都会被无条件通知待打开的文件路径,URDF 导入器通过检查扩展名(不区分大小写的urdf)决定是否接手该文件,不匹配则返回ImporterError::Incompatible。这与 导入器总览 中描述的内置/外部/自定义三类导入器机制一致。
在 Rerun 中使用 URDF 非常简单——只需用日志 API 加载文件,导入器会自动完成三件事:
- 解析网格(mesh)的路径引用并加载它们;
- 把网格与基本几何体(box、cylinder、capsule、sphere)作为 Rerun 实体加载;
- 加载各 link 的关节变换(joint transforms)以及对应的 frame ID。
实体路径布局
从 urdf_tree.rs 中UrdfLogPaths::new的源码可以看到模型被组织到几个固定的实体路径下(entity_path_prefix可选):
| 内容 | 默认实体路径 | 说明 |
|---|---|---|
| 机器人根坐标系 | {robot_name}(可加前缀) | 由CoordinateFrame标记,值为 root link 的 frame ID |
| 视觉几何体 | {prefix}{robot_name}/visual_geometries/{link}/{visual_name} | 便于整体切换视觉几何体显隐 |
| 碰撞几何体 | {prefix}{robot_name}/collision_geometries/{geometry_type}/{link}/{collision_name} | 按几何类型分目录,可单独隐藏某类碰撞体(如只隐藏 mesh 保留基本体) |
| 静态关节变换 | /tf_static | 所有默认变换集中到同一个实体路径,且不受entity_path_prefix影响 |
所有静态关节变换会被合并为一个 chunk 批量写入/tf_static(见emit_static_transforms_batch)。源码注释明确说明“对 URDF 总是以 static 方式写入”,这样用户后续可以在任意自己选择的变换实体上覆盖它们。
网格资源如何被解析
load_ros_resource支持四种资源寻址方式:
- 相对路径:相对
.urdf文件所在目录解析; file://协议:直接读取本地绝对路径;package://协议:在ROS_PACKAGE_PATH(ROS 1)和AMENT_PREFIX_PATH(ROS 2)中查找<entry>/pkg_name或<entry>/share/pkg_name,适用于 ROS 包内引用的网格(见resolve_package_uri);http(s)://协议:通过 HTTP 下载网格,连接超时 30 秒,且单次下载有 512 MiB 的内存保护上限(MAX_MESH_DOWNLOAD_SIZE)。
对于无法解析的网格资源,导入不会整体失败:错误会被收集并按原因汇总、去重后以警告形式输出(例如“Could not resolve package URI…”),其余 link、joint 与几何体照常导入。这一点有端到端测试佐证:test_urdf_importer.rs 中的test_urdf_importer_dangling_mesh专门验证“网格无法加载时其余实体仍然全部产出,且不会发出任何Asset3D”。另外在 WebAssembly 目标上,ROS 资源加载不可用(返回UnsupportedInWasm)。
几何体与材质的映射
emit_geometry给出了 URDF 几何类型到 Rerun 原语/资产的映射关系:
| URDF 几何 | Rerun 输出 |
|---|---|
mesh | Asset3D(按扩展名猜测 MediaType),支持albedo_factor |
box | Boxes3D,带颜色 |
cylinder | Cylinders3D(URDF 与 Rerun 都以 Z 为主轴) |
capsule | Capsules3D(同上) |
sphere | Ellipsoids3D,带颜色 |
材质处理上,优先使用 visual 内联定义的 color/texture,否则回退到按名称查找全局<material>;未指定颜色时回退为白色。纹理(texture)目前未支持,会输出一次性警告(源码中的warn_once!("Material texture not supported"))。碰撞几何体不携带材质,统一按白色渲染。
用命名帧的 Transform3D 更新关节
模型加载完成后,关节的驱动方式是通过发送[Transform3D](https://link.gitcode.com/i/45e8ba7e4c8c00777da1c66c744bf20a)完成的,关键要求是:必须显式设置parent_frame和child_frame为每个关节对应的 frame ID(URDF 中即 parent link 与 child link 的名字)。
版本提示(≥ 0.28 的行为变化)0.28 之前的版本要求使用“隐式 frame ID”,即把每个关节的变换分别发送到特定实体路径上。该方案已被命名 frame ID取代,这与 ROS 的 TF 语义更一致,并且允许你在一个实体(例如示例中的
transforms实体)上发送全部关节的变换更新。
下面是一个最小可运行的加载并更新关节的 Python 示例,来自文档配套片段 docs/snippets/all/howto/load_urdf.py:
from pathlib import Path import rerun as rr from rerun import RecordingStream with RecordingStream("rerun_example_load_urdf") as rec: rec.spawn() # `log_file_from_path` 会自动调用内置的 URDF 导入器。 urdf_path = Path(__file__).parent / "minimal.urdf" rec.log_file_from_path(urdf_path, static=True) # 可选的 flush:确保 URDF 加载完成后再继续后续日志。 rec.flush() # 后续在日志代码中,用 Transform3D 更新关节。 joint_axis = [0, 0, 1] # 取自 URDF joint_angle = 1.216 # 弧度 origin_xyz = [0, 0, 0.1] # 取自 URDF # 务必保证 parent_frame / child_frame 与 URDF 中关节的 frame ID 一致。 rec.log( "transforms", rr.Transform3D( rotation=rr.RotationAxisAngle(axis=joint_axis, angle=joint_angle), translation=origin_xyz, parent_frame="base_link", child_frame="child_link", ), )Rust 与 C++ SDK 同样通过RecordingStream::log_file_from_path触发同一套内置导入器,之后也以Transform3D(含parent_frame/child_frame)更新关节。
完整动画示例:animated_urdf
文档推荐了两个可直接运行的动画示例:
- Python 版 animated_urdf:
python -m animated_urdf - Rust 版 animated_urdf:加载并驱动同一份
so100.urdf机械臂
以 Python 版为例,它的核心循环展示了几种典型用法:
- 一次性加载模型:
rec.log_file_from_path(urdf_path),然后用rr.urdf.UrdfTree.from_file_path(urdf_path)把 URDF 结构读入内存; - 隐藏碰撞几何体:通过 blueprint 对
so_arm100/collision_geometries设置rrb.EntityBehavior(visible=False),这正是前文实体路径布局中“视觉/碰撞分离”设计的目的; - 逐关节驱动:对每个
revolute关节用joint.compute_transform(angle, clamp=True)计算变换并rec.log("transforms", transform)——compute_transform会自动填好 frame ID,无需手动指定; - 运行期修改材质:通过
urdf_tree.get_joint_child(joint)拿到关节的子 link,再对get_visual_geometry_paths(link)返回的每个视觉几何体路径,用rr.Asset3D.from_fields(albedo_factor=rgba)按关节角度动态改颜色/透明度(示例中“jaw”关节的夹爪颜色随角度从红渐变到绿); - 假关节角度:
_fake_angle使用joint.limit_lower/joint.limit_upper生成在限位内振荡的正弦角,模拟真实测量数据。
Python URDF 工具:rr.urdf
除了导入器,Rerun 还在 Python 侧提供了 rerun_py/rerun_sdk/rerun/urdf.py 模块(即rr.urdf),可作为yourdfpy、pytransform3d等第三方包之外的轻量替代。它的底层是rerun_bindings中暴露的_UrdfTreeInternal/_UrdfJointInternal等原生绑定,再封装为符合 Rerun 日志语义的高层 API。
UrdfTree:加载并访问模型结构
urdf_tree = rr.urdf.UrdfTree.from_file_path("robot.urdf", entity_path_prefix=None) # 访问属性 robot_name = urdf_tree.name root_link = urdf_tree.root_link() joints = urdf_tree.joints() # 按名字查找 urdf_tree.get_joint_by_name("shoulder") urdf_tree.get_link_by_name("base_link") # 获取某个 link 的视觉/碰撞几何体实体路径, # 可用于运行期修改颜色/透明度: for visual_path in urdf_tree.get_visual_geometry_paths("gripper"): rec.log(visual_path, rr.Asset3D.from_fields(albedo_factor=[255, 0, 0, 100]), static=True)UrdfTree.from_file_path的完整签名还支持三个配置参数(源码见 urdf.py):
| 参数 | 作用 |
|---|---|
entity_path_prefix | 可选,给几何体实体路径加前缀 |
frame_prefix | 可选,给所有 frame ID 加前缀,用于多次加载同一份 URDF |
static_transform_entity_path | 可选,静态变换写入的实体路径,默认/tf_static;不受entity_path_prefix影响 |
UrdfTree还提供get_joint_child(joint)(取关节子 link)、log_urdf_to_recording()(把完整模型——几何体 + 静态变换——写入录制,是log_file_from_path在需要frame_prefix等额外配置时的替代方案)、stream()(实验性的惰性 chunk 流)等接口。
多机器人场景:frame prefix
当需要把同一份 URDF 加载多次(例如双臂设置)时,用frame_prefix让每份实例的 frame ID 唯一,用entity_path_prefix在实体树中隔离几何体,然后通过log_urdf_to_recording()写入带前缀 frame ID 的模型:
left = rr.urdf.UrdfTree.from_file_path("robot.urdf", entity_path_prefix="left", frame_prefix="left/") right = rr.urdf.UrdfTree.from_file_path("robot.urdf", entity_path_prefix="right", frame_prefix="right/") left.log_urdf_to_recording() right.log_urdf_to_recording()之后通过joint.compute_transform()计算出的变换会自动带上前缀 frame ID(例如"left/base"、"right/shoulder")。这正是 animated_urdf 示例中--dual模式的实现方式:左右臂分别以left/、right/前缀加载,再各自rec.log("left", rr.Transform3D(translation=[-0.2, 0, 0]), static=True)平移错开位置。
UrdfJoint:读取关节属性并计算变换
每个关节都暴露了来自 URDF 文件的属性:
namejoint_type(如revolute、continuous、prismatic、fixed)parent_link、child_linkaxis、origin_xyz、origin_rpylimit_lower、limit_upper、limit_effort、limit_velocitymimic:若该关节带<mimic>标签,返回UrdfMimic(含joint、multiplier、offset,语义为value = multiplier * driver_value + offset),否则为None
用compute_transform()得到Transform3D,其parent_frame与child_frame已自动设置好:
# 对 revolute / continuous 关节传入弧度角 # 对 prismatic 关节传入平移距离(米) transform = joint.compute_transform(angle) rec.log("transforms", transform)compute_transform(value, clamp=True)的行为细节对应底层实现 joint_transform.rs:revolute 关节在值超出[limit_lower, limit_upper]时会被钳制(clamp)并产生一条警告(clamp=False时不做钳制、不警告);continuous 关节没有限位因此不检查;变换由 origin 姿态与绕关节轴axis的动态旋转(轴角)组合而成,prismatic 关节则在 origin 平移基础上叠加沿轴的位移。
此外UrdfJoint还提供面向批量数据的两组方法:
compute_transform_columns(values, clamp=True):对同一关节的多个值批量计算,返回列式(columnar)数据,可直接配合rerun.send_columns使用,适合一次性发送整段关节轨迹;UrdfTree.compute_joint_transform_batches(names, values, clamp=False):接收 ArrowListArray(关节名 + 关节值,按行成对),输出包含translation、quaternion、parent_frame、child_frame的ListArray,源码注释说明这是为 lens(查询/变换流水线)设计的辅助接口——下游通常再接一个把每个 batch 展开成最终Transform3D行的 lens。
把 URDF 加载进已有的录制
如果 Rerun 中已经打开了一个带变换的录制,想往里追加 URDF,可以通过拖拽文件进 Viewer,或使用菜单中的“Import into current recording”实现。
一个典型场景:加载 ROS 2 的.mcap文件时,TF 消息会被自动翻译为 Rerun 的Transform3D,但示例 MCAP 的变换树中会缺失一些连接(Viewer 中会以错误形式提示这些缺失的静态变换)。这些缺失的静态变换往往存放在与 MCAP 分离的 URDF 模型里。此时只需把对应的 URDF 文件直接拖入已加载 MCAP 的 Viewer 窗口,缺失的静态 link 就会补上,变换树随之闭合。
参考与进一步阅读
- 三种语言统一的文件入口:Python
rerun.log_file_from_path、RustRecordingStream::log_file_from_path、C++RecordingStream::log_file_from_path; - 导入器框架总览:了解内置/外部/自定义三类导入器及扩展方式;
- Transform3D 原型参考:
parent_frame/child_frame/旋转/平移的完整字段说明; - Rust 端导入器实现 与 URDF 树构造、关节变换计算;
- 导入器端到端测试:验证网格悬空(dangling mesh)时导入仍能容错完成;
- 配套片段资源:load_urdf.py 与 minimal.urdf(仓库中以 Git LFS 指针形式存储);
- 完整动画示例:Python animated_urdf 与 Rust animated_urdf。
【免费下载链接】rerunVisualize, query, and stream to train on multimodal robotics data.项目地址: https://gitcode.com/GitHub_Trending/re/rerun
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考