news 2026/9/16 16:50:18

Rerun segment_url 完全指南:在 DataFusion 数据表中生成可点击的 Viewer 段链接

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Rerun segment_url 完全指南:在 DataFusion 数据表中生成可点击的 Viewer 段链接

Rerun segment_url 完全指南:在 DataFusion 数据表中生成可点击的 Viewer 段链接

【免费下载链接】rerunVisualize, query, and stream to train on multimodal robotics data.项目地址: https://gitcode.com/GitHub_Trending/re/rerun

Rerun 提供 DataFusion 工具函数segment_url,可在 Catalog 数据集上按行批量生成可直接在 Viewer 中点击打开的 Rerun URL——每条 URL 都能精确定位到某个 segment,并可选地设置时间游标位置、时间范围选中状态或实体选中状态。本文基于当前仓库的官方 howto 文档 docs/content/howto/query-and-transform/segment_url.md 展开,结合其配套示例代码、Python 封装与 Rust 底层实现,讲解如何从零搭建环境、生成基础 URL,以及如何组合时间与选择条件,帮助你在数据表(DataFrame)分析场景中快速落地"从数据行直达 Viewer 视图"的工作流。

背景:segment URL 的结构与可点击原理

在深入 API 之前,先理解segment_url生成的 URL 是什么。Rerun 使用自己的 URL scheme 来跨网络访问信息,支持rerun+http://rerun+https://以及rerun://rerun://rerun+https://的别名),底层基于 gRPC 协议,见 crates/store/re_uri/src/lib.rs。

一条典型的 segment URL 形如:

rerun+http://localhost:51234/dataset/<DATASET_ID>?segment_id=<SEGMENT_ID_1>#selection=/camera/rgb&when=real_time@2023-11-14T22:13:20Z

它的三个组成部分对应不同的语义(源码见 crates/store/re_uri/src/endpoints/dataset.rs):

组成部分示例作用
查询参数?segment_id=...?segment_id=abc123指定要打开哪个 segment
片段#selection=...#selection=/camera/rgb指定 Viewer 打开后选中哪个实体路径(可含实例索引与组件名)
片段#when=...#when=real_time@2023-11-14T22:13:20Z指定激活哪条时间线并把时间游标移动到某个值
片段#time_selection=...#time_selection=real_time@2023-11-14T22:13:20Z..2023-11-14T22:13:20.5Z指定要选中的时间范围

其中#fragmentFragment结构体建模,包含selectionwhentime_selection三个可选字段(见 crates/store/re_uri/src/fragment.rs)。多个片段之间用&连接,输出顺序固定为selectionwhentime_selection(见 fragment.rs),这正是本文后面各类输出示例中片段顺序的来源。

提示:本地运行的 Rerun 实例通常没有配置 TLS,因此本地环境使用rerun+http://scheme,这意味着底层连接不加密;生产/远程环境应使用rerun+https://

环境准备:加载数据集并创建段元数据表

segment_url工作在 Catalog 体系之上,因此首先需要启动一个本地 Catalog 服务器、加载示例数据,并构造一张带段元数据的表。配套的完整示例代码位于 docs/snippets/all/howto/query-and-transform/segment_url.py,下面是其 setup 部分:

from __future__ import annotations from datetime import datetime, timedelta from pathlib import Path import pyarrow as pa from datafusion import lit import rerun as rr from rerun.utilities.datafusion.functions.url_generation import segment_url sample_5_path = ( Path(__file__).parents[5] / "tests" / "assets" / "rrd" / "sample_5" ) server = rr.server.Server(datasets={"sample_dataset": sample_5_path}) client = server.client() dataset = client.get_dataset(name="sample_dataset") # Pick 3 deterministic segment IDs and create a view filtered to them segment_ids = sorted(dataset.segment_ids())[:3] view = dataset.filter_segments(segment_ids) # Build a synthetic metadata table keyed by rerun_segment_id base_time = datetime(2023, 11, 14, 22, 13, 20) event_times = [base_time + timedelta(seconds=i) for i in range(3)] meta = pa.record_batch( { "rerun_segment_id": segment_ids, "event_time": pa.array(event_times, type=pa.timestamp("ns")), "range_start": pa.array(event_times, type=pa.timestamp("ns")), "range_end": pa.array( [t + timedelta(milliseconds=500) for t in event_times], type=pa.timestamp("ns"), ), "entity_path": [ "/camera/rgb", "/observation/joint_positions", "/observation/gripper_state", ], }, ) ctx = client.ctx meta_df = ctx.from_arrow(meta)

关键点说明:

  • rr.server.Server(datasets={"sample_dataset": sample_5_path})启动一个本地 Catalog 服务器,并把仓库自带的测试数据sample_5(位于 tests/assets/rrd/sample_5)注册为名为sample_dataset的数据集;
  • dataset.segment_ids()返回数据集内全部 segment ID(底层实现见 rerun_py/src/catalog/dataset_entry.rs),这里取前 3 个保证输出可复现;
  • dataset.filter_segments(segment_ids)得到一个只包含这 3 个 segment 的DatasetView(实现见 dataset_entry.rs),后续所有segment_table()均基于该视图;
  • 元数据表meta是一张普通的 Arrow RecordBatch,以rerun_segment_id为主键,携带事件时间、时间范围起止、实体路径等列,通过view.segment_table(join_meta=meta_df)与段表按rerun_segment_id关联;
  • 元数据中的时间列使用pa.timestamp("ns")(纳秒精度),这与 Rerun 内部对 timestamp 的处理一致。

基础用法:生成最简单的段 URL

不传任何额外参数时,segment_url(dataset)只为每一行生成打开对应 segment 的基础 URL。此时函数会自动使用名为rerun_segment_id的列作为 segment ID 来源:

basic = view.segment_table().select("rerun_segment_id").sort("rerun_segment_id") basic = basic.with_column("url", segment_url(dataset)) for url in basic.select("url").to_pydict()["url"]: print(url)

输出:

rerun+http://localhost:51234/dataset/<DATASET_ID>?segment_id=<SEGMENT_ID_1> rerun+http://localhost:51234/dataset/<DATASET_ID>?segment_id=<SEGMENT_ID_2> rerun+http://localhost:51234/dataset/<DATASET_ID>?segment_id=<SEGMENT_ID_3>

这里<DATASET_ID>是数据集的 Tuid 标识,<SEGMENT_ID_*>是具体段的 ID。URL 中不包含任何#fragment,意味着 Viewer 打开后停留在段默认视图。

指定时间游标位置

在需要把 Viewer 直接定位到某个时刻时,传入timestamptimeline_name

ts = view.segment_table(join_meta=meta_df).select( "rerun_segment_id", "event_time" ) ts = ts.sort("rerun_segment_id") ts = ts.with_column( "url", segment_url(dataset, timestamp="event_time", timeline_name="real_time"), ) for url in ts.select("url").to_pydict()["url"]: print(url)

输出:

rerun+http://localhost:51234/dataset/<DATASET_ID>?segment_id=<SEGMENT_ID_1>#when=real_time@2023-11-14T22:13:20Z rerun+http://localhost:51234/dataset/<DATASET_ID>?segment_id=<SEGMENT_ID_2>#when=real_time@2023-11-14T22:13:21Z rerun+http://localhost:51234/dataset/<DATASET_ID>?segment_id=<SEGMENT_ID_3>#when=real_time@2023-11-14T22:13:22Z

参数语义:

  • timestamp若为字符串,会被解释为列名;也可以传入任意 DataFusion 表达式(包括字面量);
  • timeline_name指定 Viewer 要激活的时间线名称。timestamp传入而timeline_name省略时,timeline_name默认取timestamp参数的值——从 Python 封装的实现可见(url_generation.py)——因此示例中即使不写timeline_name="real_time",结果也会是#when=event_time@...

值得注意的是,when片段中的时间格式会随时间类型变化:

  • timestamp 时间线输出 ISO 8601 格式,如2023-11-14T22:13:20Z
  • 序列(sequence)时间线输出整数刻度值。仓库的端到端测试对此有直接验证(rerun_py/tests/e2e_redap_tests/test_datafusion_utils.py):使用 Int64 列my_seq作为 timestamp 时,输出为#when=my_seq@10#when=my_seq@20等。

选择时间范围

传入time_range_starttime_range_end(必须成对出现),并配合timeline_name,可生成指定时间范围选中状态的 URL:

tr = view.segment_table(join_meta=meta_df).select( "rerun_segment_id", "range_start", "range_end" ) tr = tr.sort("rerun_segment_id") tr = tr.with_column( "url", segment_url( dataset, time_range_start="range_start", time_range_end="range_end", timeline_name="real_time", ), ) for url in tr.select("url").to_pydict()["url"]: print(url)

输出:

rerun+http://localhost:51234/dataset/<DATASET_ID>?segment_id=<SEGMENT_ID_1>#time_selection=real_time@2023-11-14T22:13:20Z..2023-11-14T22:13:20.5Z rerun+http://localhost:51234/dataset/<DATASET_ID>?segment_id=<SEGMENT_ID_2>#time_selection=real_time@2023-11-14T22:13:21Z..2023-11-14T22:13:21.5Z rerun+http://localhost:51234/dataset/<DATASET_ID>?segment_id=<SEGMENT_ID_3>#time_selection=real_time@2023-11-14T22:13:22Z..2023-11-14T22:13:22.5Z

时间范围在 fragment 中表达为time_selection=<timeline>@<start>..<end>。与timestamp一样,起止两个参数既可以传列名,也可以传 DataFusion 表达式。底层实现会把起止时间构造成TimeSelection(含TimelineAbsoluteTimeRange),见 segment_url_udf.rs。

约束规则(Python 侧与 Rust 侧双重校验):

  • time_range_starttime_range_end必须同时提供或同时省略,否则抛出ValueError(Python 侧校验见 url_generation.py;Rust 侧 plan 期校验见 segment_url_udf.rs);
  • 只要涉及时间(timestamp或时间范围),就必须提供timeline_name,否则报错(Rust 侧校验见 segment_url_udf.rs)。

选择实体

selection参数用于指定 Viewer 打开后要选中的实体路径、实例和/或组件。值为字符串,使用实体路径语法,可选地在方括号中追加实例索引,并用冒号追加组件名,例如:

  • /world/points—— 选中实体路径;
  • /world/points[#42]—— 选中第 42 个实例;
  • /world/points:Color—— 选中该实体上的 Color 组件;
  • /world/points[#42]:Color—— 两者同时指定。

示例:

sel = view.segment_table(join_meta=meta_df).select( "rerun_segment_id", "entity_path" ) sel = sel.sort("rerun_segment_id") sel = sel.with_column("url", segment_url(dataset, selection="entity_path")) for url in sel.select("url").to_pydict()["url"]: print(url)

输出:

rerun+http://localhost:51234/dataset/<DATASET_ID>?segment_id=<SEGMENT_ID_1>#selection=/camera/rgb rerun+http://localhost:51234/dataset/<DATASET_ID>?segment_id=<SEGMENT_ID_2>#selection=/observation/joint_positions rerun+http://localhost:51234/dataset/<DATASET_ID>?segment_id=<SEGMENT_ID_3>#selection=/observation/gripper_state

底层会把该字符串解析为DataPath并写入Fragment.selection(见 segment_url_udf.rs);若解析失败(字符串不符合实体路径语法),查询执行期会返回错误信息,例如segment_url: failed to parse selection '...': ...

组合使用:时间游标 + 时间范围 + 实体选择

上述三类特性可以同时使用,生成的 URL 会包含所有被指定的 fragment,并按selectionwhentime_selection的顺序排列:

combined = view.segment_table(join_meta=meta_df).select( "rerun_segment_id", "event_time", "range_start", "range_end", "entity_path" ) combined = combined.sort("rerun_segment_id") combined = combined.with_column( "url", segment_url( dataset, timestamp="event_time", timeline_name="real_time", time_range_start="range_start", time_range_end="range_end", selection="entity_path", ), ) for url in combined.select("url").to_pydict()["url"]: print(url)

输出:

rerun+http://localhost:51234/dataset/<DATASET_ID>?segment_id=<SEGMENT_ID_1>#selection=/camera/rgb&when=real_time@2023-11-14T22:13:20Z&time_selection=real_time@2023-11-14T22:13:20Z..2023-11-14T22:13:20.5Z rerun+http://localhost:51234/dataset/<DATASET_ID>?segment_id=<SEGMENT_ID_2>#selection=/observation/joint_positions&when=real_time@2023-11-14T22:13:21Z&time_selection=real_time@2023-11-14T22:13:21Z..2023-11-14T22:13:21.5Z rerun+http://localhost:51234/dataset/<DATASET_ID>?segment_id=<SEGMENT_ID_3>#selection=/observation/gripper_state&when=real_time@2023-11-14T22:13:22Z&time_selection=real_time@2023-11-14T22:13:22Z..2023-11-14T22:13:22.5Z

使用 DataFusion 表达式

所有接受列名字符串的参数都同样接受任意 DataFusion 表达式。当你想给所有行提供常量值时,用lit()最方便;也可以构建更复杂的表达式:

expr = view.segment_table(join_meta=meta_df).select( "rerun_segment_id", "event_time" ) expr = expr.sort("rerun_segment_id") expr = expr.with_column( "url", segment_url( dataset, timestamp="event_time", timeline_name="real_time", selection=lit("/camera/rgb"), ), ) for url in expr.select("url").to_pydict()["url"]: print(url)

输出(注意所有行的selection都固定为/camera/rgb):

rerun+http://localhost:51234/dataset/<DATASET_ID>?segment_id=<SEGMENT_ID_1>#selection=/camera/rgb&when=real_time@2023-11-14T22:13:20Z rerun+http://localhost:51234/dataset/<DATASET_ID>?segment_id=<SEGMENT_ID_2>#selection=/camera/rgb&when=real_time@2023-11-14T22:13:21Z rerun+http://localhost:51234/dataset/<DATASET_ID>?segment_id=<SEGMENT_ID_3>#selection=/camera/rgb&when=real_time@2023-11-14T22:13:22Z

表达式同样适用于segment_id:仓库测试中有用segment_id=lit(segment_id)把多行绑定到同一个段 ID 的用例(test_datafusion_utils.py)。

参数速查表

segment_url的完整签名来自 Python 封装 url_generation.py:

参数类型默认行为说明
datasetDatasetEntry必填目标 Rerun 数据集,用于提取 Catalog origin 与数据集 ID
segment_idstr \| Expr \| None使用列rerun_segment_id段 ID 的来源列或表达式
timestampstr \| Expr \| None设置#when时间游标;字符串视为列名
timeline_namestr \| None缺省时取timestamp的值时间线名称;涉及时间参数时必填
time_range_startstr \| Expr \| None时间范围起点,须与time_range_end成对
time_range_endstr \| Expr \| None时间范围终点,须与time_range_start成对
selectionstr \| Expr \| None实体路径(可含[#instance]:Component

需要注意segment_url是一个 Rerun 定制的 DataFusion 标量 UDF,使用前需要环境已安装datafusion依赖;若缺失,调用时会抛出RerunMissingDependencyError(单元测试覆盖了该场景,见 rerun_py/tests/unit/test_utilities_datafusion.py)。

底层原理:从 Python 表达式到 Rust UDF

了解调用链有助于排查问题。整个流程分三层:

  1. Python 封装层url_generation.py:把参数规范化——字符串转col()、默认列名、lit()生成 origin 与 entry_id 标量——然后构造 8 个入参调用 Rust 侧注册的SegmentUrlUdfInternal(origin, entry_id, segment_id, ts_expr, timeline_expr, range_start_expr, range_end_expr, selection_expr)

  2. FFI 桥接层segment_url_udf.rs:通过datafusion_ffiFFI_ScalarUDF把 Rust 实现的ScalarUDF包装成 PyCapsule 暴露给 Python 的ScalarUDF.from_pycapsule

  3. Rust 执行层segment_url_udf.rs:这是核心。它做了两件事:

    • Plan 期类型校验return_type,L72-L166):固定要求 8 个入参;origin/segment_id/selection 需可转换为 Utf8;entry_id 必须是FixedSizeBinary(16)(即 Tuid);timestamp 与时间范围必须是受支持的 Arrow 时间类型或 Null;时间范围起止必须同为 Null 或同非 Null;涉及时间时 timeline 必须非 Null。
    • 执行期逐行生成 URLinvoke_with_args,L168-L340):对每行把segment_id解析为SegmentId,时间信息解析为(TimelineName, TimeCell),范围构造成TimeSelection,选择构造成DataPath,最终组装为DatasetUri { origin, dataset_id, resource: Segments, segment_id, fragment }并序列化(URI 组装逻辑见 crates/store/re_uri/src/endpoints/dataset.rs)。

    UDF 的签名使用Signature::any(8)(L58),原因在于参数中存在可选项和多类型列,用one_of描述会导致组合爆炸,因此改为在执行期自查类型(L50-L58 的注释对此有说明)。

边界行为与注意事项

  • Null 行:若某行的 segment ID 为 Null,该行 URL 输出 Null(L262-L265);若时间、时间范围或 selection 列为 Null,对应片段会被省略而不是报错。仓库测试中None行都只输出不带对应 fragment 的 URL(见 test_datafusion_utils.py 等用例)。
  • 时间单位:timestamp 与范围列既支持pa.timestamp("ns"),也支持 Int64(作为序列刻度),执行时统一 cast 为 Int64 后按TimeType解释(L213-L250)。
  • timeline 约束:只用时间范围而不用timestamp时,timeline_name不会自动推断(默认值逻辑只针对timestamp),必须显式传入(url_generation.py)。
  • 行数一致性:UDF 会校验所有数组参数的行数要么为 1(标量展开)要么一致,否则报执行期错误(segment_url_udf.rs)。
  • 测试验证:端到端测试覆盖了简单 URL、timestamp、时间范围、selection 及其组合,并用占位符替换动态 origin 与数据集 ID 后进行快照比对(辅助函数见 rerun_py/tests/e2e_redap_tests/_helpers.py),可作为你验证本地输出格式的参考。
  • 更轻量的替代:如果不走 DataFusion,也可以直接用dataset.segment_url(segment_id, timeline, start, end)方法生成单条 URL(签名与时间类型推断见 rerun_py/src/catalog/dataset_entry.rs),适合逐条构造链接的场景。

小结

segment_url把"在数据表中找到感兴趣的行"与"在 Viewer 中定位到对应画面"无缝衔接起来:基础用法一行代码即可为整列 segment 生成可点击链接;搭配timestamptime_range_start/time_range_endselection,还能精确控制 Viewer 打开后的时间游标、时间范围选中与实体选中状态;所有参数均支持 DataFusion 表达式,便于用lit()注入常量或构建复杂逻辑。理解其背后的DatasetUri/Fragment结构与三层调用链,能帮助你在机器人多模态数据、传感器日志等场景中高效调试和验证所生成的链接是否符合预期。

【免费下载链接】rerunVisualize, query, and stream to train on multimodal robotics data.项目地址: https://gitcode.com/GitHub_Trending/re/rerun

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/16 16:50:16

从tfevents看恶意代码检测平台:TensorFlow与Flask全栈构建

简介&#xff1a;一款面向恶意代码检测与分类的本科毕业设计平台&#xff0c;适合信息安全、计算机等相关专业学生用于毕业设计或课程设计参考。项目采用网络应用与机器学习模型结合的方式&#xff0c;覆盖数据展示、样本管理和分类识别等模块&#xff0c;从样本上传到检测结果…

作者头像 李华
网站建设 2026/9/16 16:48:48

19828端口的钥匙:LLM Wiki API Token生成、校验与安全最佳实践

19828端口的钥匙&#xff1a;LLM Wiki API Token生成、校验与安全最佳实践 【免费下载链接】llm_wiki LLM Wiki is a cross-platform desktop application that turns your documents into an organized, interlinked knowledge base — automatically. Instead of traditional…

作者头像 李华
网站建设 2026/9/16 16:47:20

路面谱生成与ADAMS导入:PSD建模到车辆仿真全流程

简介&#xff1a;面向车辆工程、道路工程与多体动力学仿真领域的研究人员和工程师&#xff0c;一份MATLAB脚本资源旨在生成路面粗糙度功率谱密度数据&#xff0c;并转换为Adams可识别的文件格式&#xff0c;弥补车辆动力学仿真中真实路面输入缺乏的短板。压缩包为rar格式&#…

作者头像 李华
网站建设 2026/9/16 16:47:17

基于SpringBoot+Vue的健身房管理系统开发实践

1. 项目概述金帝豪斯健身房管理系统是一个典型的B/S架构企业级应用&#xff0c;采用前后端分离技术栈实现。作为毕业设计选题&#xff0c;它完美融合了Java后端开发、前端框架应用和数据库设计三大核心技能点&#xff0c;同时具备商业项目的基本特征。我在实际开发过程中发现&a…

作者头像 李华
网站建设 2026/9/16 16:46:44

大语言模型学习路径与核心资源指南

1. 大语言模型学习路径概述作为一名从传统NLP转向大语言模型开发的工程师&#xff0c;我深刻理解初学者面对海量资源时的选择困难。大语言模型领域的发展速度令人咋舌&#xff0c;去年刚掌握的技术今年可能就已过时。但核心原理和底层思维是相通的&#xff0c;关键在于建立正确…

作者头像 李华