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.

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,
        ),
    )