Rerun RecordingInfo 详解:记录级属性的定义、字段语义与多语言写入方式
【免费下载链接】rerunVisualize, query, and stream to train on multimodal robotics data.项目地址: https://gitcode.com/GitHub_Trending/re/rerun
RecordingInfo是 Rerun 类型系统中一个状态为 stable 的 Archetype,用于描述一条 recording(录制/采集会话)自身的元属性,包含可选的start_time与name两个字段。在 Rerun 的 properties 机制中,它作为内建属性被自动存入保留实体路径/__properties,并可作为 segment 表的列用于过滤、排序与数据表查询。读完本篇,你将能够理解该 archetype 的字段定义与生成机制,掌握 Rust / Python / C++ 三种 SDK 下写入录制名称、覆盖起始时间、附加自定义属性的完整写法,并从源码层面看清send_recording_name等便捷 API 是如何落到RecordingInfo的 partial 更新上的。
RecordingInfo 是什么:archetype 定义与字段语义
根据类型定义源文件 recording_info.def.rs,RecordingInfo的注释原文是 "A list of properties associated with a recording.",并带有如下关键标注:
#[rerun(state = "stable")]:API 已稳定,可用于生产数据管线;#[rerun(visualizer_none)]:它不是可视化数据,不参与任何 visualizer 的渲染,仅作为数据/元数据存在;- 两个字段均为
#[rerun(optional)],即没有任何必填组件。
字段语义如下:
| 字段 | 组件类型 | 必填性 | 说明 |
|---|---|---|---|
start_time | Timestamp | 可选 | 录制开始时间。应当是绝对时间,即相对于 Unix Epoch 的时间戳(纳秒级) |
name | Name | 可选 | 用户自定义的录制名称,用于区分不同 episode/会话 |
从 recording_info.rs 的生成代码可以确认组件构成:NUM_COMPONENTS: usize = 2,其中 0 个必填、0 个推荐、2 个可选;archetype 全名为rerun.archetypes.RecordingInfo,两个组件描述符分别为RecordingInfo:start_time(组件类型rerun.components.Timestamp)与RecordingInfo:name(组件类型rerun.components.Name)。由于全部字段可选,RecordingInfo::new()返回的两个字段均为None,这意味着它既可以整体记录,也可以通过 partial 更新只写其中一个字段——这正是 SDK 便捷 API 的工作方式,后文会展开。
写入录制属性:Rust / Python / C++ 完整示例
官方示例concepts/recording_properties展示了三种语言下设置录制属性的完整流程,核心模式一致:设置名称、覆盖起始时间、附加基于现有 archetype 的自定义属性、附加基于任意数据的自定义属性,最后演示属性(含名称)可被随时覆盖。
Rust
来源:recording_properties.rs
fn main() -> Result<(), Box<dyn std::error::Error>> { let rec = rerun::RecordingStreamBuilder::new( "rerun_example_recording_properties", ) .spawn()?; // 录制可以有可选名称 rec.send_recording_name("My recording")?; // 起始时间会被自动设置,但随时可以覆盖 rec.send_recording_start_time(1742539110661000000)?; // 使用现有 Rerun 类型,为录制添加用户自定义属性 rec.send_property( "camera_left", &rerun::archetypes::Points3D::new([[1.0, 0.1, 1.0]]), )?; let other = rerun::AnyValues::default() .with_component_from_data( "confidences", Arc::new(arrow::array::Float64Array::from(vec![0.3, 0.4, 0.5, 0.6])), ) .with_component_from_data( "traffic", Arc::new(arrow::array::StringArray::from(vec!["low"])), ) .with_component_from_data( "weather", Arc::new(arrow::array::StringArray::from(vec!["sunny"])), ); // 再添加一个属性,这次是用户自定义数据 rec.send_property("situation", &other)?; // 属性(包括名称)随时可以被覆盖 rec.send_recording_name("My episode")?; Ok(()) }要点说明:
send_recording_start_time接收impl Into<Timestamp>,示例中的1742539110661000000是纳秒级绝对时间戳;send_property(name, value)中value可以是任意实现了AsComponents的类型(archetype、AnyValues等),因此属性值不受限于RecordingInfo的两个内建字段;- 名称可以多次发送,后发覆盖先发,示例末尾把 "My recording" 改成了 "My episode"。
Python
来源:recording_properties.py
import rerun as rr rec = rr.RecordingStream("rerun_example_recording_properties") rec.spawn() # 覆盖上方设置的名称 rec.send_recording_name("My recording") # 起始时间会被自动设置,但随时可以覆盖 rec.send_recording_start_time_nanos(1742539110661000000) # 使用现有 Rerun 类型,为录制添加用户自定义属性 rec.send_property( "camera_left", rr.archetypes.Points3D([[1.0, 0.1, 1.0]]), ) # 再添加一个属性,这次是用户自定义数据 rec.send_property( "situation", rr.AnyValues( confidences=[0.3, 0.4, 0.5, 0.6], traffic="low", weather="sunny", ), ) # 属性(包括名称)随时可以被覆盖 rec.send_recording_name("My episode")注意 Python 的起始时间 API 显式命名为send_recording_start_time_nanos,单位语义(纳秒)直接体现在函数名中。
C++
来源:recording_properties.cpp。C++ 侧没有AnyValues风格的便捷封装,自定义数据需通过 Arrow 构造ComponentBatch后传入send_property:
const auto rec = rerun::RecordingStream("rerun_example_recording_properties"); rec.spawn().exit_on_failure(); rec.send_recording_name("My recording"); rec.send_recording_start_time_nanos(1742539110661000000); auto points = rerun::Points3D({{1.0f, 0.1f, 1.0f}}); rec.send_property("camera_left", points); // 自定义数据:用 Arrow builder 构造组件数组 arrow::DoubleBuilder confidences_builder; ARROW_RETURN_NOT_OK(confidences_builder.AppendValues({0.3, 0.4, 0.5, 0.6})); ARROW_RETURN_NOT_OK(confidences_builder.Finish(&arrow_array)); auto confidences = rerun::ComponentBatch::from_arrow_array( std::move(arrow_array), "confidences"); // ... traffic / weather 同理构造后: rec.send_property("situation", confidences, traffic, weather); rec.send_recording_name("My episode");源码剖析:send_recording_name 如何落到 RecordingInfo
Rust SDK 中三个便捷 API 的实现位于 recording_stream.rs:
/// Sends a property to the recording. pub fn send_property<AS: ?Sized + AsComponents>( &self, name: impl Into<String>, values: &AS, ) -> RecordingStreamResult<()> { let sub_path = EntityPath::from(name.into()); self.log_static(EntityPath::properties().join(&sub_path), values) } /// Sends the name of the recording. pub fn send_recording_name(&self, name: impl Into<String>) -> RecordingStreamResult<()> { let update = RecordingInfo::update_fields().with_name(name.into()); self.log_static(EntityPath::properties(), &update) } /// Sends the start time of the recording. pub fn send_recording_start_time( &self, timestamp: impl Into<Timestamp>, ) -> RecordingStreamResult<()> { let update = RecordingInfo::update_fields().with_start_time(timestamp.into()); self.log_static(EntityPath::properties(), &update) }从源码结构可以读出三层信息:
- 静态(static)语义:三个 API 都走
log_static,即数据不关联时间轴。这与 properties 的语义一致——属性描述整条录制而非某个时刻,相关概念文档见 properties-and-segments.md。 - partial 更新机制:
send_recording_name内部先调用RecordingInfo::update_fields()(返回所有字段为None的实例),再只with_name(...)。由于该 archetype 没有必填组件,这条行只会携带RecordingInfo:name一个组件,不会把start_time清空。这也解释了为什么"名称与起始时间可以分别、反复覆盖而互不干扰"。 - 保留实体路径:内建属性直接记录在
EntityPath::properties()(即/__properties)下,自定义属性则拼接为/__properties/<name>。文档同时明确不建议直接往该路径写数据,应通过send_property/send_recording_name等 API 完成。
另外,properties-and-segments.md 说明start_time会被 Rerun 自动填充——即不手动调用send_recording_start_time时该字段也有值,手动调用属于"覆盖"而非"首次设置"。
展示与查询:DataframeView 与 segment 表
按参考文档,RecordingInfo可以在 DataframeView 中展示。更实际的消费路径有两条:
- 数据表(dataframe)查询:属性默认被排除在实体过滤之外,显式包含
/__properties/**后即可查询,属性列名遵循property:$property_name:$Archetype:$field规则;内建属性省略$property_name段,因此RecordingInfo的两个字段呈现为property:RecordingInfo:name与property:RecordingInfo:start_time。 - catalog 的 segment 表:录制注册进数据集后,每个属性成为 segment 表的一列(每行一个录制)。由于 segment 表是 DataFusion DataFrame,可以直接用标准 DataFrame 操作按属性值过滤,例如按
property:RecordingInfo:name筛选特定会话。从查询输出示例可见,列元数据中还带有archetype: RecordingInfo、component: RecordingInfo:name、entity_path: /__properties等信息,与上文ComponentDescriptor的定义一一对应。
生成机制与类型定义
RecordingInfo属于 Rerun 类型系统的多语言绑定来源之一:定义文件 recording_info.def.rs 本身不可执行,由re_types_builder解析后生成 Rust(recording_info.rs 顶部即标注 "DO NOT EDIT! This file was auto-generated...")、Python 与 C++ 三侧绑定,参考文档页(即 recording_info.md)本身也是由 website.rs 自动生成。因此当你看到文档、API 与源码之间的字段说明时,它们都以同一个.def.rs为唯一事实来源;修改字段语义需要改定义文件并重新生成绑定,而不能手改生成物。
在 Rust 侧直接使用 archetype(而非便捷 API)时,生成的构造函数还提供:
RecordingInfo::new()/update_fields():全None的起点,适合只写单个字段;with_start_time(impl Into<Timestamp>)/with_name(impl Into<Name>):链式设置单值;with_many_start_time/with_many_name:一次打包多个值,配合columns()分片,适合列式批量写入;clear_fields():用空 Arrow 数组显式清空各字段。
小结
RecordingInfo是一个 0 必填、2 可选组件的 stable archetype,字段start_time(绝对 Unix 纳秒时间戳)与name(用户命名)均为可选;- 写入入口为各语言 SDK 的
send_recording_name/send_recording_start_time(_nanos),底层是"对/__properties下的RecordingInfo做 static 的 partial 更新";自定义属性走send_property,值可以是任意 archetype 或AnyValues自定义数据; start_time由 Rerun 自动填充、可随时覆盖;所有属性在数据表查询与 catalog segment 表中以property:RecordingInfo:*列名暴露,可直接用于过滤与分析。
【免费下载链接】rerunVisualize, query, and stream to train on multimodal robotics data.项目地址: https://gitcode.com/GitHub_Trending/re/rerun
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考