Migrating from 0.23 to 0.24

Changed timeline navigation keyboard shortcut changed-timeline-navigation-keyboard-shortcut

To accommodate the new tree keyboard navigation feature, the timeline navigation is changed as follows:

  • go to previous/next frame is ctrl-left/right (cmd on Mac) arrow (previously no modifier was needed)
  • go to beginning/end of timeline is alt-left/right (previously the ctrl/cmd modifier was used)

Previously deprecated, now removed previously-deprecated-now-removed

Scalar, SeriesLine, SeriesPoint archetypes scalar-seriesline-seriespoint-archetypes

Have been removed in favor of Scalars, SeriesLines, SeriesPoints respectively.

Micro-batcher default flushing duration increased from 8ms to 200ms for memory & file recording streams microbatcher-default-flushing-duration-increased-from-8ms-to-200ms-for-memory--file-recording-streams

RERUN_FLUSH_TICK_SECS previously always defaulted to 8ms when left unspecified. This now only applies to recording streams that use a GRPC connection, all others default to 200ms.

You can learn more about micro-batching in our dedicated documentation page.

Combining InstancePoses3D with orientations in Boxes3D/Ellipsoids3D/Capsules3D behaves differently in some cases now combining-instanceposes3d-with-orientations-in-boxes3dellipsoids3dcapsules3d-behaves-differently-in-some-cases-now

Previously, Boxes3D/Ellipsoids3D/Capsules3D all mirrored some transform components from InstancePoses3D. However, now that all components have distinct archetype-tags from the transform components in InstancePoses3D, form a separate transform that is applied prior to InstancePoses3D.

I.e. transform resolve order was previously:

final = `Transform3D` * … * `Transform3D` * ([Box3D or `InstancePoses3D].quaternion * [Box3D or `InstancePoses3D].rotation_axis_angle * [Box3D or `InstancePoses3D].centers/translations)

And is now

final = `Transform3D` * … * `Transform3D` * InstancePoses3D * (Box3D.quaternion * Box3D.rotation_axis_angle * Box3D.centers)

As a concrete example, if you previously scaled boxes/ellipsoids/capsules using InstancePoses3D they would be scaled relative to the individual box centers. Now instead they are scaled relative to the entity's center.

serve_web is now deprecated in Rust and Python serveweb-is-now-deprecated-in-rust-and-python

serve_web will be removed in a future release but is still available for now. Instead prefer an explicit combination of serve_grpc and serve_web_viewer:

"""Demonstrates how to log data to a gRPC server and connect the web viewer to it."""

import time

import rerun as rr

rr.init("rerun_example_serve_web_viewer")
# Start a gRPC server and use it as log sink.
server_uri = rr.serve_grpc()

# Connect the web viewer to the gRPC server and open it in the browser
rr.serve_web_viewer(connect_to=server_uri)

# Log some data to the gRPC server.
rr.log("data", rr.Boxes3D(half_sizes=[2.0, 2.0, 1.0]))

# Keep server running. If we cancel it too early, data may never arrive in the browser.
try:
    while True:
        time.sleep(1)
except KeyboardInterrupt:
    print("\nShutting down server...")

Rust's even older serve (deprecated since 0.20) has been removed entirely now.

Component descriptors component-descriptors

One limitation that we previously had with our data model was that it was only possible to use any Component once per entity path. This severely effected the design and flexbility of our archetypes. The underlying reason for this was that the our internal datastructures used the component's type names (previously also referred to as ComponentName) to index into the data. This release changes how components are identified within the viewer and within our APIs: Instead of specifying the component's type name, components are now referenced by a new syntax that consists of the (short) archetype name + the archetype field name separated by a colon (:).

As an example, Points3D:positions refers to the positions component in the rerun.archetypes.Points3D archetype. (Previously, it would only be identified by its component type, i.e. rerun.components.Position3D.) For custom data, such as AnyValues, it is possible to omit the archetype part of this syntax and only specify the field name.

To View.select columns in dataframe queries, we additionally need to specify the entity that a component belongs to. Starting with this release, this is achieved by adding the entity_path as a prefix to the component identifier, for example: /helix/structure/left:Points3D:positions. In general, the syntax for uniquely identifying a component in recording then becomes:

<entity_path>:[<archetype>:]<field>

Custom data custom-data

Internally we use, what we call a ComponentDescriptor to describe the structure and semantics of a component. Conceptually, it looks like the following:

struct ComponentDescriptor {
  archetype:      Option, // e.g. `rerun.archetypes.Points3D
  component:      String,         // e.g. `Points3D:positions`
  component_type: Option, // e.g. `rerun.components.Position3D
}

Custom data can still use simple field names such as confidences, but it is advised to supply a full ComponentDescriptor, if possible. For this we also provide a new AnyValues.with_field method.

Changes changes

When logging data to Rerun using the builtin archetypes no changes to user code should be required. There is also migration code in place so that you can open .rrd files that were created with v0.23. Recordings from v0.22 can also be loaded, but need to be migrated using the migration tool from v0.23 first.

These changes are reflected in various parts of the Rerun viewer:

  • It is now possible to log arbitrary overlapping archetypes on a single entity path. It is also now possible to re-use the same component type for different fields of the same archetype.
  • The selection panel UI comes with a revamped display of archetypes that uses the new syntax to show the ComponentDescriptor for each component.
  • The new :-based syntax needs to be used when referring to components in the dataframe API and in the dataframe view.
  • Changed the interpretation of blueprint.datatypes.ComponentColumnSelector to use the new component identifier.
  • Indicator components have been removed entirely. The viewer now instead decides which views & visualizers to activate based on archetype information of components.

Blueprint component defaults

Blueprint component defaults were previously applied to component types. They are now instead, applies to archetype fields, i.e. what is now just called component (e.g. GraphNodes:positions).

In practice this means that component defaults are now limited to a single archetype, making them a lot more useful!

Limitations & breaking changes limitations--breaking-changes

  • In some cases, it is not possible to migrate previous blueprints, but only if they were saved from the viewer via the UI.
  • Currently, only Rerun-builtin components are picked up by the visualizers and therefore shown in the views (except for the dataframe view which shows all components).
  • In v0.23, the LeRobot dataloader logged incomplete ComponentDescriptors for robot observations and actions. To fix this, load the dataset in v0.24 and resave your episodes to .rrd (v0.24 now supports saving all selected recordings).
  • Overriding visualizers to reinterpret data (e.g. show a point-cloud for mesh vertices) is no longer possible, since visualizers now match for : instead of component type name. This will be addressed in the future with blueprint-driven overrides that will allow to remap data to arbitrary archetypes.
  • VisualizerOverrides are now limited to time series views, and stop to be supported for general views, such as the spatial views.
  • The markers component on SeriesPoints is now marked as required, to avoid accidentally logging an archetype without any associated data. In Python, when no component is supplied we automatically set the markers shape to Circle to avoid breaking user code.

Dataframe API: View.select_static is deprecated dataframe-api-viewselectstatic-is-deprecated

The dataframe API was originally introduced with the View.select_static() variant of View.select() used when the view only contains static columns. In such cases, select() would yield no row as no data is logged at any index value (by definition of static-only content). Instead, select_static() would force the generation of a single, index-less row populated with the static data.

The same behavior can now be achieved by using Recording.view(index=None, content=...).