Transform3D

A transform between two 3D spaces, i.e. a pose.

From the point of view of the entity's coordinate system, all components are applied in the inverse order they are listed here. E.g. if both a translation and a max3x3 transform are present, the 3x3 matrix is applied first, followed by the translation.

Whenever you log this archetype, it will write all components, even if you do not explicitly set them. This means that if you first log a transform with only a translation, and then log one with only a rotation, it will be resolved to a transform with only a rotation.

Components components

Optional: Translation3D, RotationAxisAngle, RotationQuat, Scale3D, TransformMat3x3, TransformRelation, AxisLength

Shown in shown-in

Examples examples

Variety of 3D transforms variety-of-3d-transforms

"""Log different transforms between three arrows."""

from math import pi

import rerun as rr
from rerun.datatypes import Angle, RotationAxisAngle

rr.init("rerun_example_transform3d", spawn=True)

arrow = rr.Arrows3D(origins=[0, 0, 0], vectors=[0, 1, 0])

rr.log("base", arrow)

rr.log("base/translated", rr.Transform3D(translation=[1, 0, 0]))
rr.log("base/translated", arrow)

rr.log(
    "base/rotated_scaled",
    rr.Transform3D(
        rotation=RotationAxisAngle(axis=[0, 0, 1], angle=Angle(rad=pi / 4)),
        scale=2,
    ),
)
rr.log("base/rotated_scaled", arrow)

Transform hierarchy transform-hierarchy

"""Logs a transforms transform hierarchy."""

import numpy as np
import rerun as rr
import rerun.blueprint as rrb

rr.init("rerun_example_transform3d_hierarchy", spawn=True)

# One space with the sun in the center, and another one with the planet.
rr.send_blueprint(
    rrb.Horizontal(rrb.Spatial3DView(origin="sun"), rrb.Spatial3DView(origin="sun/planet", contents="sun/**"))
)

rr.set_time_seconds("sim_time", 0)

# Planetary motion is typically in the XY plane.
rr.log("/", rr.ViewCoordinates.RIGHT_HAND_Z_UP, static=True)

# Setup points, all are in the center of their own space:
# TODO(#1361): Should use spheres instead of points.
rr.log("sun", rr.Points3D([0.0, 0.0, 0.0], radii=1.0, colors=[255, 200, 10]))
rr.log("sun/planet", rr.Points3D([0.0, 0.0, 0.0], radii=0.4, colors=[40, 80, 200]))
rr.log("sun/planet/moon", rr.Points3D([0.0, 0.0, 0.0], radii=0.15, colors=[180, 180, 180]))

# Draw fixed paths where the planet & moon move.
d_planet = 6.0
d_moon = 3.0
angles = np.arange(0.0, 1.01, 0.01) * np.pi * 2
circle = np.array([np.sin(angles), np.cos(angles), angles * 0.0]).transpose()
rr.log("sun/planet_path", rr.LineStrips3D(circle * d_planet))
rr.log("sun/planet/moon_path", rr.LineStrips3D(circle * d_moon))

# Movement via transforms.
for i in range(0, 6 * 120):
    time = i / 120.0
    rr.set_time_seconds("sim_time", time)
    r_moon = time * 5.0
    r_planet = time * 2.0

    rr.log(
        "sun/planet",
        rr.Transform3D(
            translation=[np.sin(r_planet) * d_planet, np.cos(r_planet) * d_planet, 0.0],
            rotation=rr.RotationAxisAngle(axis=(1, 0, 0), degrees=20),
        ),
    )
    rr.log(
        "sun/planet/moon",
        rr.Transform3D(
            translation=[np.cos(r_moon) * d_moon, np.sin(r_moon) * d_moon, 0.0],
            from_parent=True,
        ),
    )