news 2026/9/16 22:58:59

Rerun Vector2D 组件深度解析:2D 向量数据模型、Arrow 编码与 Arrows2D 可视化

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Rerun Vector2D 组件深度解析:2D 向量数据模型、Arrow 编码与 Arrows2D 可视化

Rerun Vector2D 组件深度解析:2D 向量数据模型、Arrow 编码与 Arrows2D 可视化

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

Vector2D是 Rerun 数据模型中用于表示二维空间向量的核心组件(Component),也是Arrows2D图元(Archetype)唯一必需的组成部分。本文以仓库中 组件参考文档 为主体,结合 Rust / Python 两套 SDK 的源码实现,完整讲解Vector2D的语义定义、底层Vec2D编码、Arrow 内存布局、跨语言 API 用法及其在Arrows2D可视化链路中的角色,帮助你在日志机器人运动学、光流、速度场等二维矢量数据时正确选型与使用。

Vector2D 是什么:一个"稳定"的二维向量组件

在 Rerun 的类型体系中,组件(Component)是附着在实体(Entity)上的最小语义单元,而Vector2D的定位非常单纯——一个处于 2D 空间中的向量("A vector in 2D space.")。它与同样表示二维数据的Position2D(位置点)的关键区别在于语义:位置描述"在哪",向量描述"朝哪个方向、多长"。

从仓库中的类型定义源文件可以看到该组件的"官方契约":

// crates/build/re_type_definitions/rerun/components/vector2d.def.rs /// A vector in 2D space. #[rerun::rerun_type] #[rerun(state = "stable")] #[rust(derive(Default, Copy, PartialEq, bytemuck::Pod, bytemuck::Zeroable))] #[rust(repr = "transparent")] pub struct Vector2D { pub vector: rerun::encodings::Vec2D, }

这段代码本身不是可执行的 Rust 代码,而是 Rerun 的类型定义 DSL(位于crates/build/re_type_definitions/下),由re_types_builder解析后统一生成 Rust、Python 与 C++ 三套 SDK 的绑定代码。其中值得注意的两个标记:

  • state = "stable":表明该组件处于稳定状态,其名称与内存布局受版本兼容性保障,可以放心用于长期存储的数据;
  • repr = "transparent":生成的结构体是底层编码类型Vec2D的透明包装(transparent wrapper),零额外内存开销。

Rerun 编码:Vec2D 与透明包装结构

文档中明确列出Vector2D的 Rerun 编码(encoding)为Vec2D。编码(Encoding)是比组件更低一层的原始数据类型描述,它直接对应 Arrow 的内存表示,并且被多个组件复用(例如Position2D同样基于二维浮点编码)。

Rust 端生成的组件结构体如下:

// crates/store/re_sdk_types/src/components/vector2d.rs #[repr(transparent)] pub struct Vector2D(pub crate::encodings::Vec2D); impl ::re_types_core::WrapperComponent for Vector2D { type Encoding = crate::encodings::Vec2D; #[inline] fn name() -> ComponentType { "rerun.components.Vector2D".into() } }

而编码Vec2D的实现(crates/store/re_sdk_types/src/encodings/vec2d.rs)本质就是一个[f32; 2]的强类型包装:

#[repr(C)] pub struct Vec2D(pub [f32; 2usize]);

同时提供了便捷的类型互转:

impl From<[f32; 2usize]> for Vec2D { fn from(xy: [f32; 2usize]) -> Self { Self(xy) } } impl From<Vec2D> for [f32; 2usize] { fn from(value: Vec2D) -> Self { value.0 } }

Python 端的结构完全对应:Vector2D类直接继承encodings.Vec2D并混入ComponentMixin,本身不新增字段(见 rerun_py/rerun_sdk/rerun/components/vector2d.py):

class Vector2D(encodings.Vec2D, ComponentMixin): """**Component**: A vector in 2D space.""" class Vector2DBatch(encodings.Vec2DBatch, ComponentBatchMixin): _COMPONENT_TYPE: str = "rerun.components.Vector2D"

实用的扩展实现

在 crates/store/re_sdk_types/src/components/vector2d_ext.rs 中,Rust 端还提供了两个常用常量与外部数学库的互操作:

impl Vector2D { /// The zero vector, i.e. the additive identity. pub const ZERO: Self = Self(crate::encodings::Vec2D::ZERO); /// `[1, 1]`, i.e. the multiplicative identity. pub const ONE: Self = Self(crate::encodings::Vec2D::ONE); } #[cfg(feature = "glam")] impl From<Vector2D> for glam::Vec2 { /* ... */ } #[cfg(feature = "mint")] impl From<Vector2D> for mint::Vector2<f32> { /* ... */ }

这意味着当你的应用已经基于glamVec2)或mintVector2<f32>)做向量运算时,可以直接通过From转换轻松接入 Rerun 的日志管线,无需手写逐元素拷贝。

Arrow 数据类型:FixedSizeList(2 × Float32)

Vector2D在 Arrow 层面的数据布局是文档中给出的核心事实:

FixedSizeList(2 x non-null Float32)

即:外层是长度为 2 的定长列表FixedSizeList,元素不可为 null),内层是两个非空Float32。这一布局在三个层面都有源码印证:

Rust 端(crates/store/re_sdk_types/src/encodings/vec2d.rs):

impl ::re_types_core::ArrowDataType for Vec2D { fn arrow_data_type() -> arrow::datatypes::DataType { DataType::FixedSizeList( std::sync::Arc::new(Field::new("item", DataType::Float32, false)), 2, ) } }

序列化(ToArrow)时先展平为[f32; 2]的连续数组再构造FixedSizeListArray;反序列化(FromArrow)时校验value_length() == 2,并通过bytemuck::try_cast_slice把底层Float32Array的连续缓冲区直接重解释为[[f32; 2]]切片——这正是选择定长列表而非可变长度列表的原因:定长 + 无 null 使得每个向量恰好 8 字节,可以按元素零拷贝访问

Python 端(rerun_py/rerun_sdk/rerun/encodings/vec2d.py):

class Vec2DBatch(BaseBatch[Vec2DArrayLike]): _ARROW_DATATYPE = pa.list_(pa.field("item", pa.float32(), nullable=False, metadata={}), 2)

而输入数据在 vec2d_ext.py 中经由flat_np_float32_array_from_array_like(data, 2)(见 rerun_py/rerun_sdk/rerun/_validators.py)统一转成维度为 2 的扁平 float32 numpy 数组,再包成pa.FixedSizeListArray

@staticmethod def native_to_pa_array_override(data: Vec2DArrayLike, data_type: pa.DataType) -> pa.Array: points = flat_np_float32_array_from_array_like(data, 2) return pa.FixedSizeListArray.from_arrays(points, type=data_type)

因此 Python 侧你可以传入[[1.0, 2.0], [3.0, 4.0]]np.array(...)等任意可转为(N, 2)float32 数组的对象,SDK 会统一校验并转换。

使用场景:作为 Arrows2D 的必选向量

Vector2D组件当前唯一的直接消费者是Arrows2D图元——用于绘制一批带可选颜色、半径、标签的二维箭头。从类型定义看(crates/build/re_type_definitions/rerun/archetypes/arrows2d.def.rs),vectorsArrows2D唯一的**必需(required)**字段:

pub struct Arrows2D { /// All the vectors for each arrow in the batch. #[rerun(required)] pub vectors: Vec<rerun::components::Vector2D>, /// All the origin (base) positions for each arrow in the batch. /// If no origins are set, (0, 0) is used as the origin for each arrow. #[rerun(recommended)] pub origins: Option<Vec<rerun::components::Position2D>>, /// Optional radii for the arrows. #[rerun(optional)] pub radii: Option<Vec<rerun::components::Radius>>, // ... colors / labels / show_labels / draw_order / class_ids ... }

理解"必需"的含义很重要:Arrows2D图元本身还带有originsradiicolorslabelsdraw_orderclass_ids等字段,但它们全部可选——去掉任何一个,剩下的箭头依然能渲染;唯独删掉vectors后,Arrows2D就不再有意义。因此Vector2D是二维箭头可视化的数据基石,其余字段只是修饰。

可视化侧的印证

在渲染端,Arrows2DVisualizer(crates/views/re_view_spatial/src/visualizers/arrows2d.rs)通过查询信息明确把Vector2D声明为单必需组件:

impl VisualizerSystem for Arrows2DVisualizer { fn visualizer_query_info(&self, _app_options: &re_viewer_context::AppOptions) -> VisualizerQueryInfo { VisualizerQueryInfo::single_required_component::<Vector2D>( &Arrows2D::descriptor_vectors(), &Arrows2D::all_components(), ) // ... } }

即:只要某个实体上存在rerun.components.Vector2D组件批次,空间视图(Spatial 2D / 3D,3D 时需在投影下)就会自动启用Arrows2DVisualizer来渲染这批向量。从源码结构看,vectors的语义与文档定义("All the vectors for each arrow in the batch")完全一致——每个Vector2D对应批量中的一根箭头。

各语言实战用法

Python

import rerun as rr rr.init("rerun_example_arrow2d") rr.spawn() rr.log( "arrows", rr.Arrows2D( vectors=[[1.0, 0.0], [0.0, -1.0], [-0.7, 0.7]], origins=[[0.25, 0.0], [0.25, 0.0], [-0.1, -0.1]], radii=0.025, colors=[[255, 0, 0], [0, 255, 0], [127, 0, 255]], labels=["right", "up", "left-down"], ), )

Rust

use rerun::{Arrows2D, RecordingStreamBuilder}; fn main() -> Result<(), Box<dyn std::error::Error>> { let rec = rerun::RecordingStreamBuilder::new("rerun_example_arrow2d").spawn()?; rec.log( "arrows", &Arrows2D::from_vectors([[1.0, 0.0], [0.0, -1.0], [-0.7, 0.7]]) .with_radii([0.025]) .with_origins([[0.25, 0.0], [0.25, 0.0], [-0.1, -0.1]]) .with_colors([[255, 0, 0], [0, 255, 0], [127, 0, 255]]) .with_labels(["right", "up", "left-down"]), )?; Ok(()) }

以上 Rust 示例直接取自 crates/store/re_sdk_types/src/archetypes/arrows2d.rs 中生成的文档注释。可以看出:

  • from_vectors(...)接受数组字面量,内部逐个Into<Vector2D>转换(Vector2D实现了From<T: Into<Vec2D>>,而Vec2D又实现了From<[f32; 2]>);
  • 未指定origins时默认以(0, 0)为起点;
  • radii的渲染语义为:箭杆按radius = 0.5 * radius绘制成线,箭头按height = 2.0 * radiusradius = 1.0 * radius绘制;
  • labels只有一个时会显示在实体中心,多个时每个实例各显示一个。

类型生成链路与兼容性保证

Vector2D的代码并非手写,而是由构建期工具链驱动:

  1. 类型契约定义在 crates/build/re_type_definitions/rerun/components/vector2d.def.rs(DSL 源);
  2. crates/build/re_types_builder/src/codegen/rust/api.rs依据 DSL 生成 Rust 绑定(即 crates/store/re_sdk_types/src/components/vector2d.rs,文件头注明 "DO NOT EDIT! This file was auto-generated");
  3. 生成代码在re_sdk_types的 components/mod.rs 与 reflection/mod.rs 中统一注册(组件名rerun.components.Vector2D),供日志与查询反射系统使用。

state = "stable"意味着该组件名与 Arrow 布局属于稳定接口。对于需要长期落盘(.rrd/ Parquet)或跨语言交换的 2D 向量数据,可以放心依赖这一布局:FixedSizeList(2 x non-null Float32)既能被 Arrow 生态广泛支持,又因为定长无 null 而保持紧凑(每向量 8 字节)。

小结

  • Vector2D是 Rerun 中表示 2D 向量的稳定组件,编码为Vec2D,Arrow 布局为FixedSizeList(2 × non-null Float32)
  • 它在 Rust 端是#[repr(transparent)]的零开销包装,在 Python 端是encodings.Vec2D的直接子类,语义与内存表示完全统一;
  • 目前唯一使用方是Arrows2D图元的必选字段vectors,用于批量绘制二维箭头(可配合originsradiicolorslabels等可选字段);
  • 相关定义与实现可在仓库中直接追溯:组件参考文档、编码文档、类型 DSL 源、Rust 生成代码、Python 组件绑定、渲染可视化器。

【免费下载链接】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 22:58:53

Claude AI图表生成功能详解与应用实践

1. Claude图表生成功能概述Claude作为新一代AI助手&#xff0c;其图表生成能力正在成为数据分析师、产品经理和内容创作者的高效工具。不同于传统图表工具需要手动输入数据、调整参数&#xff0c;Claude通过自然语言交互即可快速生成各类可视化图表。我在实际使用中发现&#x…

作者头像 李华
网站建设 2026/9/16 22:58:31

Unstract 前端 antd → shadcn 迁移:shim 兼容层约定与实践指南

Unstract 前端 antd → shadcn 迁移&#xff1a;shim 兼容层约定与实践指南 【免费下载链接】unstract LLM-Driven Extraction of Unstructured Data — Built for API Deployments & ETL Pipeline Workflows 项目地址: https://gitcode.com/GitHub_Trending/un/unstract…

作者头像 李华
网站建设 2026/9/16 22:53:29

当标题只有一串“1”:如何从无效输入到完整内容创作

收需求的时候&#xff0c;我盯着标题栏里那一长串“1”。屏幕上没有正文&#xff0c;没有关键词&#xff0c;没有摘要&#xff0c;甚至连一个多余的空格都没有&#xff0c;只有一行望不到头的数字“1”安安静静地躺在那里。说实话&#xff0c;第一反应是“这是不是表单出错了”…

作者头像 李华
网站建设 2026/9/16 22:53:03

Git不追踪空目录怎么办?.gitkeep占位文件原理、用法与最佳实践

你肯定遇到过这种场面&#xff1a;本地项目里新建了一个uploads目录&#xff0c;图片传上去跑得好好的&#xff0c;git push完&#xff0c;同事一clone&#xff0c;上传功能直接报错&#xff0c;打开文件树一看——uploads目录根本没拉下来。这不是同事操作失误&#xff0c;也不…

作者头像 李华
网站建设 2026/9/16 22:52:54

Docker多阶段构建实战:从1GB镜像到几十MB的优化指南

说实话&#xff0c;我第一次在团队看到同事上传的镜像时&#xff0c;差点没绷住。一个内部小工具&#xff0c;代码量不到两千行&#xff0c;打出来的镜像 1.2GB。问了下 Dockerfile 内容&#xff0c;果然还是老套路&#xff1a;FROM ubuntu&#xff0c;装一堆编译依赖&#xff…

作者头像 李华
网站建设 2026/9/16 22:51:32

用Inno Setup将MySQL、JDK和Spring Boot JAR打包成一键安装包

做Java桌面应用或者内部系统交付的时候&#xff0c;我猜不少人都被“部署环境”折磨过。客户电脑上没有JDK&#xff0c;要么自己手动下一个&#xff0c;要么让客户装&#xff1b;MySQL更麻烦&#xff0c;安装包一步步点&#xff0c;root密码、字符集、端口&#xff0c;稍不注意…

作者头像 李华