用 Rerun 的 3D 原语构建实时模拟时钟:Rust 示例逐行拆解

发布时间:2026/9/17 14:30:00

用 Rerun 的 3D 原语构建实时模拟时钟:Rust 示例逐行拆解 用 Rerun 的 3D 原语构建实时模拟时钟Rust 示例逐行拆解【免费下载链接】rerunVisualize, query, and stream to train on multimodal robotics data.项目地址: https://gitcode.com/GitHub_Trending/re/rerun本篇技术指南以 examples/rust/clock 示例为主体讲解如何仅用 Rerun SDK 的Boxes3D、Points3D、Arrows3D三种原语搭建一个带时针、分针、秒针的模拟时钟并沿 Rerun 时间轴timeline实时动画。读完本文你将掌握log_static与log的用法差异、如何通过set_duration_secs驱动时间轴、如何用RerunArgs控制数据去向以及为什么这个示例同时是大量小事件场景下的绝佳基准测试。示例概览一个模拟时钟能教会你什么该示例位于仓库的 examples/rust/clock官方 README 用一句话概括了它的本质An example visualizing an analog clock with hour, minute and seconds hands using Rerun Arrow3D primitives.使用 Rerun Arrow3D 原语可视化带时针、分针、秒针的模拟时钟。尽管视觉上只是一个时钟它在教学上覆盖了 Rerun SDK 的三类核心能力静态场景声明——用ViewCoordinates声明坐标系、用Boxes3D声明时钟表盘这些只在时间轴 0 处记录一次之后不再变化逐帧动态数据——每根指针的端点用Points3D、指针本身用Arrows3D每帧每个时间步都重新记录时间轴驱动——通过set_duration_secs把sim_time推进到当前步数对应的秒数让 Viewer 能以真实时间轴播放动画。源码注释还点明了它的另一重身份This is a great benchmark for many small events.这是大量小事件场景的绝佳基准。因为每一帧都会产生 6 条 log 记录3 根指针 × 2 条端点 箭头默认跑 10000 步就是约 6 万个小数据事件非常适合压测 SDK 的日志管线与 Viewer 的更新性能。快速运行一条命令启动示例的依赖与构建方式非常轻量README 给出的启动命令只有一行cargo run --release在仓库根目录执行后程序会编译clockcrate启动一个新的 Rerun Viewer 进程并把时钟数据实时送入其中。也可以通过 cargo 的-p参数在任意目录下精确定位到该 crate源码头部注释同样给出了这条用法cargo run -p clock --release -- --help--help会打印出该程序支持的完整命令行参数具体清单见下文命令行参数一节。依赖构成examples/rust/clock/Cargo.toml 揭示了示例的依赖面非常精简[dependencies] rerun { path ../../../crates/top/rerun, features [web_viewer, clap, log_setup] } anyhow.workspace true clap { workspace true, features [derive] }值得注意的几点rerun走 path 依赖直接指向仓库内的 crates/top/rerun因此必须在本仓库内编译运行启用了三个 featureweb_viewer支持--serve启动网页版 Viewer、clap复用 SDK 内置的RerunArgs命令行参数解析、log_setup提供re_log::setup_logging()初始化日志edition 2024、rust-version 1.96对 Rust 工具链版本有要求主程序使用clapderive 宏来定义参数结构体。程序入口与参数结构src/main.rs 的入口部分展示了一个典型的 Rerun Rust 应用骨架#[derive(Debug, clap::Parser)] #[clap(author, version, about)] struct Args { #[command(flatten)] rerun: rerun::clap::RerunArgs, #[clap(long, default_value 10000)] steps: usize, } fn main() - anyhow::Result() { re_log::setup_logging(); use clap::Parser as _; let args Args::parse(); let (rec, _serve_guard) args.rerun.init(rerun_example_clock)?; run(rec, args) }其中args.rerun.init(rerun_example_clock)是核心一行它以rerun_example_clock作为 Application ID 创建 RecordingStream并根据命令行参数决定数据流向。init返回的_serve_guard在 web 模式下需要存活才能持续提供网页服务因此用_前缀接收并保活到 main 结束。命令行参数RerunArgs 全解析rerun::clap::RerunArgs定义于 crates/top/rerun/src/clap.rs它是一组开箱即用的 CLI 参数任何 Rerun 应用都能通过#[command(flatten)]直接复用。结合 clap.rs 的源码注释参数清单如下参数默认值作用--spawntrue启动一个新的 Rerun Viewer 进程并实时喂入数据--save PATH无将数据保存为.rrd文件而非立即可视化-o, --stdoutfalse把日志数据写到标准输出便于管道传给 Rerun Viewer--connect [URL]rerunhttp://127.0.0.1:9876/proxy连接远程 Rerun viewerscheme 必须是rerun://、rerunhttp://或rerunhttps://路径名必须是/proxy--servefalse启动基于网页的 Rerun Viewer需要web_viewerfeature--server-memory-limit LIMIT25%gRPC 服务器内存上限如16GB或50%达到上限后丢弃最旧数据用于缓冲以便迟到的 viewer 补看--newest-firstfalse新客户端连接时优先回放最新数据--bind IP0.0.0.0gRPC 服务器绑定的 IP 地址示例自身额外定义了--steps参数默认10000控制模拟时钟总共走的步数帧数。Args结构体还透传了 clap 自带的--help、--version等能力。静态场景坐标系与表盘时钟的表盘是静态的在整个动画过程中只记录一次因此使用log_static——它把数据关联到时间轴的初始状态时间 0与随时间变化的动态数据区分开rec.log_static(world, rerun::ViewCoordinates::RIGHT_HAND_Y_UP())?; rec.log_static( world/frame, rerun::Boxes3D::from_half_sizes([(LENGTH_S, LENGTH_S, 1.0)]), )?;ViewCoordinates声明坐标系统ViewCoordinates::RIGHT_HAND_Y_UP()声明场景采用右手坐标系、Y 轴朝上——这是 3D 可视化的惯例约定。通过把该组件 log 到world实体Viewer 会据此确定默认相机姿态与坐标系语义避免出现表盘躺在地上之类的视角错位。Boxes3D用半尺寸定义方形表盘Boxes3D::from_half_sizes([(LENGTH_S, LENGTH_S, 1.0)])创建了一个三维盒子LENGTH_S 20.0因此表盘是一个40.0 × 40.0 × 2.0的薄板。Rerun 的 3D 盒子原语使用**半尺寸half-sizes**定义即每个维度只给出一半长度盒子中心位于实体原点(0, 0, 0)。从源码结构看log_static的static语义与log的关键区别在于static 数据只与实体路径绑定不受时间步影响而后续指针的每一帧数据都属于某个具体时间点。两者可以共存于同一实体层级这里是world下由 Rerun 的时间轴机制统一组织。动态指针Points3D Arrows3D 的组合三根指针由统一的log_hand函数生成每一帧被调用 3 次秒针、分针、时针fn log_hand( rec: rerun::RecordingStream, name: str, step: usize, angle: f32, length: f32, width: f32, blue: u8, ) - anyhow::Result() { let pos tip(angle * TAU, length); let color color(angle, blue); rec.set_duration_secs(sim_time, step as f64); rec.log( format!(world/{name}_pt), rerun::Points3D::new([pos]).with_colors([color]), )?; rec.log( format!(world/{name}_hand), rerun::Arrows3D::from_vectors([pos]) .with_origins([(0.0, 0.0, 0.0)]) .with_colors([color]) .with_radii([width * 0.5]), )?; Ok(()) }指针尖端的坐标计算指针端点的位置由辅助函数tip计算fn tip(angle: f32, length: f32) - [f32; 3] { [length * angle.sin(), length * angle.cos(), 0.0] }传入的angle是归一化比例0.0 ~ 1.0乘以TAU即2π后得到弧度角指针长度作为半径把端点投影到 XZ 平面Z 恒为 0即表盘平面。各指针在 main.rs 中的角度由步数取模得出for step in 0..args.steps { log_hand(rec, seconds, step, (step % 60) as f32 / 60.0, LENGTH_S, WIDTH_S, 0)?; log_hand(rec, minutes, step, (step % 3600) as f32 / 3600.0, LENGTH_M, WIDTH_M, 128)?; log_hand(rec, hours, step, (step % 43200) as f32 / 43200.0, LENGTH_H, WIDTH_H, 255)?; }秒针步数对 60 取模 → 60 步走完一圈长度LENGTH_S 20.0表盘半径宽度WIDTH_S 0.25分针步数对 3600 取模 → 3600 步一圈对应 60 秒 × 60 帧/秒长度10.0宽度0.4时针步数对 43200 取模 → 43200 步一圈12 小时 × 3600长度4.0宽度0.6。长度与宽度常量定义在 main.rs三根指针呈明显的内外层次保证在表盘上互不遮挡、视觉可区分。指针的两种呈现点与箭头每根指针同时记录了两个实体world/{name}_pt用Points3D::new([pos]).with_colors([color])在指针尖端画一个彩色点充当指针端点标记world/{name}_hand用Arrows3D::from_vectors([pos])从原点(0, 0, 0)指向pos画一根箭头with_radii([width * 0.5])把箭头半径设为指针宽度的一半视觉上即指针杆。动态配色的实现color辅助函数让指针颜色随时间角度平滑变化fn color(angle: f32, blue: u8) - rerun::Color { let c (angle * 255.0) as u8; rerun::Color::from_unmultiplied_rgba(255 - c, c, blue, u8::max(128, blue)) }R、G 通道随角度在255→0与0→255之间渐变形成冷暖色过渡B 通道由调用方传入秒针0、分针128、时针255用于区分三根指针Alpha 取max(128, blue)保证半透明可见。时间轴驱动set_duration_secs 让动画流动整个动画的灵魂在于 main.rs 这一行rec.set_duration_secs(sim_time, step as f64);它做了两件事声明/推进一个名为sim_time的时间轴timeline把该时间轴的当前值设置为step秒。之后的rec.log(...)调用会把数据自动关联到sim_time step这一时刻。于是 Viewer 中会出现一条可拖拽/可播放的时间轴步进即可看到秒针绕表盘旋转Rerun 还会自动为sim_time推断出单调递增的时序支持连续播放与逐帧跳转。这正是 Rerun 数据模型的核心思想每个实体 每条时间轴 一组按时间索引的组件序列。静态数据用log_static挂在时间 0动态数据用log 时间轴推进二者互不干扰。作为基准测试的价值大量小事件场景源码头部注释明确写道This is a great benchmark for many small events.从数据结构看这一点不难理解默认steps 10000每步产生6 条 log秒/分/时针 × 端点 箭头总计约 6 万个Points3D/Arrows3D小数据事件在短时间内灌入 SDK 的日志管线这些事件体积极小单点、单向量、单颜色考验的是 Rerun 在海量小消息下的编码、缓冲、传输与 Viewer 端更新吞吐而非大数据块的写入性能。因此你可以用--steps调节事件总量配合--spawn / --save / --connect / --serve等数据通道快速实测不同环节的吞吐差异。例如# 1 万步直接可视化 cargo run --release # 100 万步把数据存成 rrd 文件验证大批量落盘性能 cargo run -p clock --release -- --steps 1000000 --save clock.rrd # 连接远程 viewer如局域网内的另一台机器 cargo run -p clock --release -- --connect rerunhttp://192.168.1.100:9876/proxy小结通过 examples/rust/clock 这个不到 100 行的示例可以完整走通 Rerun Rust SDK 的核心工作流RerunArgs::init(application_id)一键完成 RecordingStream 初始化并根据--spawn/--save/--stdout/--connect/--serve等参数自动决定数据去向log_static记录不随时间变化的场景坐标系、表盘logset_duration_secs把逐帧动态数据挂到sim_time时间轴上形成可播放动画Boxes3D/Points3D/Arrows3D三种原语足以组合出具备真实空间语义的 3D 场景。它是理解 Rerun实体-组件-时间轴数据模型的最小完整样例也是验证大量小事件吞吐的现成基准。以此为起点可以继续研读 examples/rust 下其他示例如 dna、log_file掌握更多原语与交互模式。【免费下载链接】rerunVisualize, query, and stream to train on multimodal robotics data.项目地址: https://gitcode.com/GitHub_Trending/re/rerun创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
延伸阅读

更多相关文章

2026/9/17 14:30:00

MySQL 8.0备份实战:XtraBackup 8.0安装与恢复全指南

我见过很多DBA和运维朋友,一备份MySQL就下意识敲mysqldump,等数据量上了500GB,备份时间从半小时变成五六个小时,恢复更是遥遥无期,这时候才开始着急找方案。其实在MySQL 8.0时代,最该优先考虑的备份工具就是…

2026/9/17 14:30:00

通信交换技术本质:电路、报文与分组的工程抉择

1. 这不是教科书里的概念图,而是我亲手画了7版才搞懂的通信底层逻辑“图解数据交换技术——电路交换、报文交换、分组交换”,光看标题,很多人第一反应是:又来背网络层协议了?课本上那三张并排的示意图,箭头…

2026/9/17 14:30:00

球体导热理论与工程实践:从控制方程到数值求解

1. 球体导热问题概述球体导热是工程传热学中的经典问题,在核反应堆燃料球、相变储热材料、化工催化剂颗粒等领域具有广泛应用。与平板和圆柱体导热不同,球体导热具有独特的几何特性——温度场仅沿径向变化,这使得三维问题可以简化为仅与半径相…

2026/9/17 15:30:08

i.MX6 eglfs Qt触摸屏无响应:input到QPA全链路排查

简介:本资源为嵌入式Linux下解决Qt应用程序不响应触摸屏问题的技术文章,面向从事工控机、嵌入式Qt与tslib底层开发的工程师及进阶学习者。内容针对USB触摸屏断开后重新接入时,Qt程序无法自动恢复触摸响应的常见缺陷,从Qt5.4.1的QT…

2026/9/17 15:30:08

管道机器人手臂结构设计三重绞杀与绛重优化

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/17 15:25:07

射频同轴电缆衰减全解析:从电磁损耗原理到系统链路预算

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/16 12:52:37

拯救者Y7000黑屏故障排查与维修实战指南

1. 项目概述:一台黑屏的拯救者Y7000,到底卡在哪一步? 联想拯救者Y7000系列笔记本,从2018年第一代搭载i5-8300H开始,到后来的i7-9750H、i7-10750H、i5-11400H,再到2023年款的R7-7840HS,它始终是学…

2026/9/17 0:03:13

WiFi密码安全测试:从原理到实战的字典暴力破解指南

1. 写在前面:我为什么要研究WiFi密码这件事先交代一下背景。我身边有不少朋友,家里的WiFi密码常年是"12345678"或者"88888888",问就是"好记"。直到有一次,隔壁邻居蹭网蹭到我家路由器后台都进不去&…

2026/9/17 0:03:13

redis-py服务控制与监控函数实战:从ping到slowlog的巡检指南

我用 redis-py 写了快五年的业务代码,坦白说,真正让我觉得这个客户端“像一个成熟工具箱”的,不是 get/set 那套基本操作,而是它那批专门做服务控制与状态监控的辅助函数。日常开发里,大家把redis.Redis(host..., deco…

2026/9/17 0:03:13

SpringBoot+Vue3实现中小企业设备管理系统开发实践

1. 项目概述与核心价值中小企业设备管理系统是制造业、服务业等领域的基础信息化工具。传统设备管理往往依赖Excel表格或纸质记录,存在数据孤岛、流程混乱、维护成本高等痛点。这套基于Java SpringBootVue3MyBatis的技术方案,通过前后端分离架构实现了设…

2026/9/16 22:55:57

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/16 22:56:09

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/16 22:56:16

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码