mcpField
R
rerun-blueprint

rerun-blueprint

github.com/rerun-io数据与数据库11.7k132 次安装今天更新
代码仓库

关于 rerun-blueprint

rerun-blueprint 是配置 Rerun 录制和表格展示方式的技能,面向构建或调整 Rerun 视图的用户。它指导读取数据、设计布局,并通过截图迭代蓝图。

主要功能

  1. 01配置录制视图与布局
  2. 02设置表格列、筛选器和卡片
  3. 03依据实体与原型选择视图
  4. 04组织视图并设置内容范围
  5. 05通过截图迭代蓝图

适用场景

  1. 01为录制数据设计多视图布局
  2. 02调整数据集表格列与行筛选
  3. 03排查空间视图为空或布局异常

MCP 相关

配合 viewer MCP,通过 rerun_get_blueprint 读取蓝图、rerun_set_blueprint 写入蓝图,也可读取表格架构并更新表格配置。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/rerun-io/rerun --skill rerun-blueprint

安装后在 Claude Code 中输入/rerun-blueprint确认已加载。

详细介绍

Rerun 蓝图

要更改查看器的外观,请更改蓝图。 录制内容的布局、视图及其属性,以及表格的列、行筛选器和卡片,都是如此。不要通过点击查看器菜单来完成这些操作。使用查看器 MCP 时,请通过 rerun_get_blueprint 和 rerun_set_blueprint 读取和写入蓝图,而不是使用底层点击工具。

蓝图决定如何显示录制内容,而录制内容决定有哪些数据。读取数据,设计初始布局,然后根据截图反复调整,直到一目了然。构造函数可以自行探索(dir(rrb)、help(rrb.Spatial3DView));本技能会介绍无法靠猜测得知的内容。导入方式为 import rerun.blueprint as rrb。

表格

数据集的分段表和目录表格各有自己的表格蓝图,与录制内容的蓝图分开。它决定显示哪些列、列的顺序和名称、行筛选条件,以及行是以表格还是卡片形式显示。若要美化表格、隐藏列或筛选行,请编写此蓝图。

以下示例隐藏两列,并将另外三列排在最前面。列出的列会排在前面,其余列保持默认顺序和可见性:

blueprint = rrb.TableBlueprint(
    table_layout=rrb.table.TableLayout(
        columns=[
            rrb.table.Column("recording link"),
            rrb.table.Column("property:episode:current_task", name="Task"),
            rrb.table.Column("property:episode:success"),
            rrb.table.Column("property:episode:ext1_cam_serial", visible=False),
            rrb.table.Column("property:episode:ext2_cam_serial", visible=False),
        ],
    ),
)
blueprint.save("my_app", path)
dataset.register_blueprint(path.as_uri(), segment_table=True)

Column 接受表格中的列名,例如 property:episode:uuid,而不是列标题。注册后,它会成为所有打开此表格的用户所使用的默认设置,并且服务器必须能够读取 path。

行筛选器是 SQL 表达式,每个字符串对应一个表达式,且一行必须满足所有表达式:rrb.TableBlueprint(filters=["\"task\" ILIKE '%pick%'", '"duration" > 10'])。列名使用双引号,字符串使用单引号;列表列可使用 any_match("column", x -> …)。

使用查看器 MCP 时,可直接更改屏幕上的表格:rerun_get_table_schema 会列出列名,使用 {"table": {}} 调用 rerun_get_blueprint 可读取表格蓝图,使用 {"table": {}} 调用 rerun_set_blueprint 可替换表格蓝图。若筛选器无效,rerun_set_blueprint 会返回错误。列条目位于 /table/layouts/table/columns/<column name>;名称中的每个 : 和空格都要分别转义为 \: 和 \ ,在 JSON 中写作 \\: 和 \\ 。MCP 文档提供了一个完整的 JSON 示例。有关完整的 Python API(包括卡片和分段预览),请参阅配置表格布局和分段预览。

1. 读取数据

首先枚举每个 (entity_path, archetype) 对;archetype 决定视图,entity path 则限定其作用范围。对于数据集(参见 rerun-catalog-queries):

for c in dataset.schema().component_columns():
    print(c.entity_path, c.archetype, c.component_name)

对于本地录制内容,使用 RrdReader 流式读取,并从每个数据块中读取 entity_path 和 archetype(参见 rerun-chunk-processing)。

仅凭数据集架构无法列出视图中可显示的所有实体。资源是静态数据,例如 URDF 机器人网格;查看器会将其应用于每个分段,但它们不会出现在分段实体中。如果 rerun_get_dataset_schema 在 entities 旁列出了 asset_ids,请调用 rerun_get_dataset_assets_schema 获取每个资源中的实体,并在选择 2D 或 3D 视图或预览之前读取这些实体。例如,asset_ids: ["urdf-model-left", "urdf-model-right"] 表示机器人模型可以放入 Spatial3DView 中。

2. 将原型映射到视图

原型系列视图
Points2D、Image、EncodedImage、Boxes2D、LineStrips2D、Pinhole 投影Spatial2DView
Points3D、Mesh3D、Boxes3D、LineStrips3D、Transform3D、Asset3DSpatial3DView
Scalars、SeriesLines、SeriesPointsTimeSeriesView
TextLog / TextDocument / BarChartTextLogView / TextDocumentView / BarChartView
Tensor、DepthImage(热力图)TensorView
GeoPoints、GeoLineStringsMapView
GraphNodes、GraphEdgesGraphView
表格 / 目录数据DataframeView

Asset3D 和 URDF 网格等资源实体应放在 Spatial3DView 中。

3. 将实体分组到视图中

此步骤只需决定哪些实体共用一个视图。大小和位置是在截图循环中凭直觉调整的细节,无需预先制定规则。

  • 按共享路径前缀分组。 具有共同前缀的实体通常属于同一个视图。不要为每个实体都单独设置一个窗格:数十个原始消息实体应放在同一个 DataframeView 中,或者省略,而不是每个都占一个窗格。
  • 每个空间视图使用一个空间坐标系。 整个 Transform3D 树放在同一个 Spatial3DView 中,并以共同祖先为根;Pinhole 摄像头则使用以摄像头为根的独立 Spatial2DView,这样图像就会继承投影。
  • 合并标量。 前缀下有多个 Scalars 时,使用一个覆盖该前缀的 TimeSeriesView,而不是每个标量都单独设置一个。仅当数值范围相互冲突时才拆分。
  • column_shares/row_shares 是容器子项的相对权重,默认相等。根据截图调整它们。

4. 构建视图

容器(Grid、Horizontal、Vertical、Tabs)用于容纳视图。对于扁平集合,默认使用 Grid;只有在有意拆分时才使用其他容器;对于争用同一位置的备选项(左侧 / 右侧 / 深度摄像头),使用 Tabs。始终显式设置 origin 和 name——origin 默认值为 /,这会将整棵树都放进一个视图(这通常是内容变成难以辨认的一团的原因)。

blueprint = rrb.Blueprint(
    rrb.Horizontal(
        rrb.Spatial3DView(origin="/world", name="Scene"),
        rrb.Vertical(
            rrb.Spatial2DView(origin="/world/camera", name="Camera"),
            rrb.TimeSeriesView(origin="/sensors", name="Sensors"),
        ),
        column_shares=[3, 2],
    ),
    rrb.TextLogView(origin="/logs", name="Logs"),
    collapse_panels=True,
)

contents 默认为 "$origin/**"。使用包含 / 排除规则限定视图范围,例如 contents=["+ $origin/**", "- $origin/internal/**"]。不带前缀的规则行表示包含;/** 是唯一的通配符(匹配子树)。优先采用最具体的规则;若规则具体程度相同,则采用最后一条;未匹配的路径会被排除。

坐标系。 空间视图只会渲染能够相对于目标坐标系定位的实体。记录在实体上的 Transform3D/Pinhole 会沿树向下组合,因此只需设置 origin。但命名坐标系(CoordinateFrame(frame=...),常见于 ROS/MCAP)位于单独的坐标系图中——通过 spatial_information=rrb.SpatialInformation(target_frame="<frame>") 将视图指向数据所在的坐标系。若 3D 视图为空,并出现 "No transform path from <frame>…" 错误,就说明存在此问题:如果 tf 树从未实例化,origin="/" 会指向根节点 tf#/,而它与任何内容都没有连接。读取 CoordinateFrame:frame 的值,将目标设为主要 3D 内容所在的坐标系,并排除位于未连接坐标系中的实体。

5. 根据截图迭代

启动查看器并加载一次录制,然后将蓝图重新发送到同一个查看器;每次发送并截图都是一次成本低廉的迭代。渲染、查看、修改。

蓝图通过存储身份与数据绑定,应用 ID 和录制 ID 缺一不可。已加载的 .rrd 保留其自身身份,因此请使用 .rrd 的值构建数据流(两者都要设置;否则 recording_id 会默认为随机值)。任一项不匹配,查看器都会将蓝图和数据视为不同的录制,并且不会应用蓝图。

import time
import rerun as rr
import rerun.blueprint as rrb
from rerun.chunk import RrdReader
from rerun.experimental import ViewerClient

store = RrdReader("segment.rrd").recordings()[0]  # the rrd's application id + recording id

with ViewerClient.spawn(headless=True, port=9879) as viewer:
    rec = rr.RecordingStream(store.application_id, recording_id=store.recording_id)
    rec.connect_grpc(url=viewer.url)
    rec.log_file_from_path("segment.rrd")

    def shot(blueprint, path):
        rec.send_blueprint(blueprint, make_active=True, make_default=True)
        time.sleep(2)  # let the import finish and a frame render; bump if a view is blank
        viewer.save_screenshot(path)  # view_id=view.id for a single view

    shot(blueprint_v1, "bp_v1.png")
    # Read bp_v1.png, revise, send the next one into the same viewer.
    shot(blueprint_v2, "bp_v2.png")

若要改为将完成的蓝图直接烘焙进去,请将 default_blueprint= 传给 rr.init / spawn / connect_grpc / save,或将 blueprint= 传给 notebook_show。

注意事项

  • DataframeView 在没有查询时会显示“Unknown timeline”: query=rrb.archetypes.DataframeQuery(timeline="<timeline>", apply_latest_at=True)。
  • 视图返回空白?导入可能尚未完成(延长等待时间),或者游标停在数据之前(添加 rrb.TimePanel(play_state=rrb.components.PlayState.Following))。
  • rrb 视图和 ViewerClient(rerun.experimental)不稳定。如果构造函数参数被拒绝,请查看 help()。

另请参阅

  • rerun-data-model — 实体、原型、时间线。
  • rerun-catalog-queries — 枚举数据集中的实体。

评论

支持 Markdown