ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Rerun 机器人 URDF 加载与关节动画实战:用 UrdfTree 驱动 3D 可视化

2026/9/16 19:56:43 拓冰建站 浏览量
Rerun 机器人 URDF 加载与关节动画实战:用 UrdfTree 驱动 3D 可视化 Rerun 机器人 URDF 加载与关节动画实战用 UrdfTree 驱动 3D 可视化【免费下载链接】rerunVisualize, query, and stream to train on multimodal robotics data.项目地址: https://gitcode.com/GitHub_Trending/re/rerun导读本篇文章基于 Rerun 仓库中的animated_urdf示例示例说明、示例主程序完整讲解如何将一个 URDFUnified Robot Description Format统一机器人描述格式机械臂模型加载进 Rerun并在时间轴上通过关节角度驱动各关节持续运动。读完本文你将掌握「一次性记录静态 URDF 资源 → 用UrdfTree解析模型结构 → 按时间步计算并写入关节变换」这一套可直接复用的机器人数据可视化流程同时了解其底层 Python 绑定与 Rust 实现原理。一、要解决什么问题给静态 URDF 加上“时间轴”URDF 是 ROS 生态中最常见的机器人模型描述格式它用link描述刚体部件含 mesh/几何体用joint描述部件间的运动副旋转、平移等。但 URDF 本身只描述模型的静态结构——它不包含任何随时间变化的关节角度数据。Rerun 的核心数据模型是「实体entity 时间轴timeline」因此一个自然的方案是将 URDF 的几何与静态变换作为一次性资源记录只写一次不随时间变化将关节角度作为动态数据每个时间步写入一条新的Transform3D由 Rerun Viewer 在时间轴上重放形成机械臂动画。animated_urdf示例演示的正是这条完整链路其 README 将核心步骤概括为三点将 URDF 文件作为静态资源加载并记录使用UrdfTree解析 URDF 结构通过记录动态变换来驱动关节动画。import rerun as rr from rerun.urdf import UrdfTree # 1. 将 URDF 文件作为静态资源记录一次 rec.log_file_from_path(urdf_path, staticTrue) # 2. 把 URDF 树结构载入内存 urdf_tree UrdfTree.from_file_path(urdf_path) # 3. 通过记录变换来驱动关节 for joint in urdf_tree.joints(): if joint.joint_type revolute: # compute_transform 根据关节原点与当前角度 # 计算出可直接记录、且帧名已设置好的完整变换 transform joint.compute_transform(angle) rec.log(transforms, transform)小提示示例 README 中的导入语句写作import rerun.urdf import UrdfTree正确的写法为from rerun.urdf import UrdfTree与 animated_urdf.py 中的用法一致。二、第一步用log_file_from_path记录静态 URDFRerun 支持直接加载.urdf文件并将其内容几何体 静态关节变换作为实体写入当前 recording。在示例中# Log the URDF file once rec.log_file_from_path(urdf_path)关键点在于“只记录一次”示例主循环中没有任何对几何体的重复写入几何数据因此天然成为静态资源不会随动画时间轴变化。README 中给出的staticTrue是显式声明“该实体为静态”的写法二者效果一致——核心诉求都是把 URDF 的几何与默认姿态固定下来把动态性全部留给关节变换。示例使用的模型是 SO-ARM100 机械臂URDF 文件位于 examples/rust/animated_urdf/data/so100.urdf仓库中通过 Git LFS 托管。从 Rust 实现urdf_tree.rs可以看到加载时除了解析link/joint还会记录 URDF 文件所在目录urdf_dir用于解析.stl/.dae等 mesh 文件的相对路径——因此移动 URDF 文件时请连同其 mesh 目录一起迁移。记录时自动生成的实体路径从 urdf_tree.rs 的实现可以看到URDF 被记录为以下实体结构实体路径含义{robot_name}或{prefix}/{robot_name}机器人根实体{root}/visual_geometries/...所有视觉几何体mesh/box/cylinder/capsule/sphere便于整体开关显隐{root}/collision_geometries/...所有碰撞几何体与视觉几何分离存储tf_static默认静态关节变换统一写入的实体路径几何类型到路径段的映射定义在geometry_type_name()urdf_tree.rs依次为mesh、box、cylinder、capsule、sphere。视觉与碰撞几何分离的设计正是为了让使用者能在 Viewer 中一键隐藏碰撞体示例的 blueprint 就是这么做的见下文。三、第二步用UrdfTree解析模型结构UrdfTree把整个 URDF 模型读入内存并提供统一的查询接口urdf_tree UrdfTree.from_file_path(urdf_path)从 Python 绑定urdf.rs可以看出from_file_path实际接受三个可选参数参数类型作用entity_path_prefixstr给机器人实体路径加前缀多机器人共存时隔离实体树frame_prefixstr关键字参数给所有坐标系帧 ID 加前缀如left/→left/basestatic_transform_entity_pathstr关键字参数自定义静态变换写入的实体路径默认tf_staticUrdfTree核心 API结合 urdf.rs 与 类型声明UrdfTree提供以下能力nameURDFrobot名称root_link()返回根linkjoints()遍历全部关节get_joint_by_name(name)按名字查关节get_joint_child(joint)取某关节的子 link动画中常用于按关节定位部件get_link_by_name(name)按名字查 linkget_visual_geometry_paths(link)/get_collision_geometry_paths(link)取某 link 的视觉/碰撞几何实体路径用于改颜色、控制显隐log(recording)把整棵机器人几何 静态变换一次性写入 recordingstream(...)以惰性流方式产出该模型的所有 chunk供批量管道使用。UrdfJoint属性一览每个关节urdf.rs暴露如下属性几乎完整对应 URDFjoint的语义属性说明name关节名joint_type关节类型取值见下方表格parent_link/child_link父/子 link 名axis关节轴(x, y, z)origin_xyz/origin_rpy关节原点平移米与旋转rpy 弧度limit_lower/limit_upper关节行程下限/上限角度制关节为弧度limit_effort/limit_velocity力/速度限制mimicmimic标签联动关节含joint/multiplier/offset子属性joint_type与 URDF 规范的映射urdf.rs为joint_typeURDF 类型变换计算支持revolute有限角度旋转关节✅ 按角度弧度驱动continuous无限旋转关节✅ 按角度弧度驱动prismatic平移关节✅ 按距离米驱动fixed固定关节无自由度floating/planar/spherical浮动/平面/球关节❌compute_transform会抛NotImplementedError后三种类型在compute_transform中不被支持对应 Rust 侧 joint_transform.rs 的UnsupportedJointType错误动画时应只针对revolute/continuous/prismatic关节写入动态角度。四、第三步compute_transform生成可记录变换这是整个示例的核心 APItransform joint.compute_transform(angle, clampTrue) rec.log(transforms, transform)从 urdf.rs 可以看到compute_transform(value, clampFalse)会计算并返回一个包含以下字段的字典quaternion_xyzw旋转四元数(x, y, z, w)translation平移(x, y, z)parent_frame/child_frame已经设置好的父子坐标系帧名若配置了frame_prefix会自动拼接前缀warning可选警告信息。其底层 Rust 实现在 joint_transform.rscompute_joint_transform会综合关节原点origin与当前关节值输出一个带帧名关系的Transform3D。这正是 README 中强调的“compute_transform 给你一个完整可记录、由关节原点与当前角度算出、且帧名已设置好的变换”。Rerun 通过 Transform3D 的父子帧关系自动维护运动学链你只需要为每个动态关节写一条变换其余全靠帧名连接。clamp参数的行为clampTrue超出[limit_lower, limit_upper]的关节值会被截断到边界同时产生一条 warning在绑定层以warning字段暴露底层通过re_log::warn!输出clampFalse默认越界值按原样参与计算不产生警告。示例的_fake_angleanimated_urdf.py本身就是按limit_lower/limit_upper生成正弦振荡角度因此配合clampTrue使用是安全的def _fake_angle(joint, step, joint_index, phase): 在关节行程限制内生成平滑振荡角度。 sin_value math.sin(step * (0.02 joint_index / 100.0) phase) return joint.limit_lower (sin_value 1.0) / 3.0 * (joint.limit_upper - joint.limit_lower)实际项目中这里的角度应替换为真实测量值如电机编码器读数、仿真输出示例只是用正弦函数模拟。五、完整示例从记录到动画的完整流程将前三步串起来并加入时间轴推进、蓝图blueprint与关节联动颜色得到示例的完整主体逻辑animated_urdf.pyduration 0.0 rec rr.script_setup(args, rerun_example_animated_urdf) rec.set_time(TIMELINE, durationduration) # 1. 一次性记录 URDF 几何与静态变换 rec.log_file_from_path(urdf_path) # 2. 载入 URDF 树 urdf_tree rr.urdf.UrdfTree.from_file_path(urdf_path) # 3. 蓝图3D 视图中默认隐藏碰撞几何 blueprint rrb.Grid( rrb.Spatial3DView( nameAnimated URDF, overrides{so_arm100/collision_geometries: rrb.EntityBehavior(visibleFalse)}, ) ) rec.send_blueprint(blueprint) # 4. 动画主循环 for step in range(10000): for joint_index, joint in enumerate(urdf_tree.joints()): if joint.joint_type revolute: dynamic_angle _fake_angle(joint, step, joint_index, phase0.0) transform joint.compute_transform(dynamic_angle, clampTrue) rec.log(transforms, transform) # 进阶按关节角度动态改变 jaw link 的视觉网格颜色 link urdf_tree.get_joint_child(joint) if link.name jaw: for visual_path in urdf_tree.get_visual_geometry_paths(link): normalized_angle (dynamic_angle - joint.limit_lower) / ( joint.limit_upper - joint.limit_lower ) rgba [1.0 - normalized_angle, normalized_angle, 0, 0.5] rec.log(visual_path, rr.Asset3D.from_fields(albedo_factorrgba)) duration 0.03 rec.set_time(TIMELINE, durationduration)值得注意的几个设计点时间轴以example_time为时间轴每步推进0.03秒几何只记录一次变换按帧写入蓝图控制利用第一节提到的“视觉/碰撞几何分离”实体结构通过 blueprint 的EntityBehavior(visibleFalse)默认隐藏collision_geometries按 link 定位部件get_joint_child(joint)拿到子 link再通过get_visual_geometry_paths(link)精确改写某个部件的视觉属性这里是按归一化关节角给jaw上色。运行方式示例的入口与依赖配置在 pyproject.toml依赖仅rerun-sdk注册了控制台入口animated_urdf animated_urdf:main脚本 docstring 给出的运行方式为python -m animated_urdf。脚本支持 Rerun 标准的rr.script_add_args通用参数并额外提供参数作用--dual同时加载两份相同的 URDF双机械臂演示帧前缀区分左右六、进阶双机械臂与frame_prefix示例的--dual模式animated_urdf.py展示了多机器人场景的标准做法——用前缀隔离命名空间left rr.urdf.UrdfTree.from_file_path(urdf_path, entity_path_prefixleft, frame_prefixleft/) right rr.urdf.UrdfTree.from_file_path(urdf_path, entity_path_prefixright, frame_prefixright/) # 一次性写入两台机器人的几何与静态变换 left.log_urdf_to_recording() right.log_urdf_to_recording() # 水平错开两个机械臂 rec.log(left, rr.Transform3D(translation[-0.2, 0, 0]), staticTrue) rec.log(right, rr.Transform3D(translation[ 0.2, 0, 0]), staticTrue)这里两个参数的分工非常清晰entity_path_prefix让两台机器人的实体树互不干扰left/so_arm100/...与right/so_arm100/...frame_prefix让坐标系帧 ID唯一left/base、right/base…避免两套相同的帧名在帧图中冲突。该前缀最终由 urdf.rs 的apply_prefix拼接到compute_transform返回的parent_frame/child_frame上。动画时左右臂分别用不同相位phase0.0与phase2.0驱动形成对称摆动效果。这种「前缀 复用同一份 URDF」的模式可直接推广到任意多机器人的数字孪生场景。七、底层原理Python API 背后的 Rust 链路整个rerun.urdf模块并非纯 Python 实现而是通过 PyO3 直接封装 Rust 侧re_importercrate 的UrdfTree见 urdf.rs 的use re_sdk::external::re_importer::{UrdfTree, ...}Python: rerun.urdf.UrdfTree │ PyO3 绑定rerun_py/src/urdf.rs ▼ Rust: re_importer::UrdfTreecrates/data_flow/re_importer/src/importer_urdf/urdf_tree.rs │ ├─ urdf_rs::read_file() 解析 XML ├─ 构建 links / joints / children / materials 索引 └─ 记录 urdf_dir 以便解析 mesh 相对路径 ▼ 关节变换importer_urdf/joint_transform.rs → Transform3D含帧名、四元数、平移这一架构带来的直接好处解析与索引在 Rust 侧一次性完成Python 层只是薄封装遍历joints()、get_joint_by_name()等查询都基于内存中的 HashMap 索引变换计算与 Rerun 数据格式零距离compute_transform直接产出带parent_frame/child_frame的Transform3D与 Viewer 的帧图机制无缝衔接无需手动换算旋转矩阵绑定层还暴露了面向批处理的compute_transform_columns一次算多组值与compute_joint_transform_batches按 joint 名数组批量计算为大规模/流式场景配合stream()惰性管道预留了接口。八、总结一套可复用的机器人可视化范式animated_urdf示例给出一套可直接套用的范式静态归静态几何体、材质、默认姿态通过log_file_from_path或UrdfTree.log_urdf_to_recording()只写一次动态归动态关节角作为时间序列数据每个时间步用compute_transform(angle, clampTrue)生成带帧名的Transform3D写入命名空间靠前缀多机器人用entity_path_prefix隔离实体、用frame_prefix隔离帧 ID细节控制靠路径借助get_visual_geometry_paths/get_collision_geometry_paths按 link 精准操作部件属性。无论你接下来要接入的是真实机械臂的编码器数据、仿真器的关节状态还是 ROS 的/joint_states话题都可以用这套流程在 Rerun 中快速得到带时间轴的 3D 机器人动画。想深入源码建议从 urdf_tree.rs、joint_transform.rs 与 urdf.rs 三处入手。【免费下载链接】rerunVisualize, query, and stream to train on multimodal robotics data.项目地址: https://gitcode.com/GitHub_Trending/re/rerun创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考