Skip to content

Poses3D

SUMMARY

A batch of positions and orientations in 3D space.

python
from telekinesis import datatypes
poses = datatypes.Poses3D([[1.0, 2.0, 3.0, 0.0, 0.0, 90.0], [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]])
API Reference
Complete API documentation for Poses3D, including parameters, attributes, and methods.
View Reference →

Parameters

ParameterTypeDefaultDescription
datanp.ndarray | list | tupleRequired3D poses with shape (N, 6), with one [x, y, z, roll, pitch, yaw] row per pose. Rotation uses Euler XYZ angles in degrees.

Raises

ExceptionCondition
TypeErrordata can't be converted to float32 (e.g. non-numeric elements)
ValueErrordata is not rank-2, or its last axis isn't length 6
ValueErrordata contains a non-finite value (NaN/Inf)

Attributes

AttributeTypeDescription
datanp.ndarrayDefensive copy of the underlying (N, 6) float32 array. Assigning a new value re-validates it the same way as construction.
shapetuple[int, ...](N, 6), where N is the batch size.
ndimintAlways 2.
dtypenp.dtypeAlways float32.
sizeintN * 6.
positionsnp.ndarrayPositions, shape (N, 3) — a copy of data[:, 0:3].
orientationsnp.ndarrayEuler XYZ orientations in degrees, shape (N, 3) — a copy of data[:, 3:6].

Methods

MethodTypeDescription
Poses3D.coerce(value)Poses3DConverts array-like data into a Poses3D. Accepts an (N, 6) array-like, one [x, y, z, roll, pitch, yaw] row per pose, checked the same way as the constructor. If value is already a Poses3D, it is returned unchanged.
Poses3D.from_quat(poses)Poses3DBuilds a Poses3D from quaternion-encoded poses (shape (N, 7)), each row [x, y, z, qw, qx, qy, qz] — position followed by a scalar-first quaternion — stored as the native degree-based Euler orientation. The input must be a 2D array with a 4-element quaternion per row.
Poses3D.from_euler(poses, degrees=True)Poses3DBuilds a Poses3D from Euler-XYZ-encoded poses (shape (N, 6)), each row [x, y, z, roll, pitch, yaw]. degrees selects whether the input rotations are given in degrees (default) or radians; either way they're stored as degrees. The input must be a 2D array with a 3-element rotation part per row.
Poses3D.from_rotvec(poses)Poses3DBuilds a Poses3D from rotation-vector-encoded poses (shape (N, 6)), each row [x, y, z, rx, ry, rz] — position followed by an axis-angle rotation vector. The input must be a 2D array with a 3-element rotation part per row.
to_numpy(copy=True)np.ndarrayReturns the poses' coordinates as a plain array. With the default copy=True you get an independent copy; pass copy=False to get a direct reference to the internal array instead, so mutating it also mutates the Poses3D.
copy()Poses3DReturns a new, independent Poses3D with the same data.

Representations

RepresentationMethodResult
Quaternionas_quat()(N, 7) float32, each row [x, y, z, qw, qx, qy, qz] — that pose's position, followed by a scalar-first quaternion equivalent to its Euler XYZ orientation.
Euler XYZas_euler(degrees=True)(N, 6) float32, each row [x, y, z, roll, pitch, yaw]. degrees=True (default, this batch's native representation) or degrees=False for radians. Always an independent copy.
Rotation vectoras_rotvec()(N, 6) float32, each row [x, y, z, rx, ry, rz] — position, followed by a rotation vector (axis-angle, magnitude = angle in radians).

Operators

OperationBehavior
p == otherTrue only if other is also a Poses3D with element-equal data (same N, same values). False for anything else.
len(p)The batch size N (length of the first axis).
poses[i]Returns a Pose3D for an integer index (negative indices supported). Raises IndexError if out of range.
poses[a:b] / poses[mask]Returns a new Poses3D holding the matched rows, for a slice or a boolean np.ndarray mask. Any other index type raises TypeError.
for p in posesIterates via __getitem__ (the old-style sequence protocol), yielding one Pose3D per row in order.
np.asarray(p) / np.reshape(p, ...)Returns a copy of data as an np.ndarray; NumPy functions accept a Poses3D directly.

Visualization

python
import rerun as rr

# Your code block
# ....

rr.init("poses3d_example", spawn=True)
datatypes.visualize(poses, entity_path="/poses", label="Poses3D")

Example

python
"""Demonstrates the Telekinesis Poses3D datatype."""

import time

import numpy as np
import rerun as rr
from loguru import logger

from telekinesis import datatypes


def poses3d_example():
    """Demonstrate creation, inspection, operations, visualization, and serialization."""

    # ======================= Create ============================================
    poses_data = [[0.5, 0.2, 0.5, 0.0, 60.0, 90.0], [0.1, 0.2, 0.3, 0.0, 0.0, 90.0]]
    poses3d = datatypes.Poses3D(poses_data)
    logger.info(f"Created Poses3D: {poses3d}")

    poses3d_from_quat = datatypes.Poses3D.from_quat(
        [
            [0.5, 0.2, 0.8, 0.0, 0.0, 0.3826834, 0.9238795],
            [0.1, 0.2, 0.3, 0.0, 0.0, 0.0, 1.0],
        ]
    )
    logger.info(f"Poses3D created from quaternion: {poses3d_from_quat}")

    poses3d_from_euler = datatypes.Poses3D.from_euler(
        [
            [0.5, 0.2, 0.8, np.radians(30), np.radians(45), np.radians(60)],
            [0.1, 0.2, 0.3, 0.0, 0.0, 0.0],
        ],
        degrees=False,
    )
    logger.info(f"Poses3D created from radians: {poses3d_from_euler}")

    poses3d_from_rotvec = datatypes.Poses3D.from_rotvec(
        [
            [0.5, 0.2, 0.8, 0.0, 0.0, np.pi / 2],
            [0.1, 0.2, 0.3, 0.0, 0.0, 0.0],
        ]
    )
    logger.info(f"Poses3D created from rotation vector: {poses3d_from_rotvec}")

    # ======================= Inspect ===========================================
    logger.info(f"data={poses3d.data}")
    logger.info(f"shape={poses3d.shape}")
    logger.info(f"ndim={poses3d.ndim}")
    logger.info(f"dtype={poses3d.dtype}")
    logger.info(f"size={poses3d.size}")
    logger.info(f"positions={poses3d.positions}")
    logger.info(f"orientations={poses3d.orientations}")

    # ======================= Operations =========================================
    poses3d.data = [[0.1, 0.2, 0.3, 0.0, 0.0, 90.0], [0.4, 0.5, 0.6, 0.0, 0.0, 45.0]]
    logger.info(f"Updated Poses3D: {poses3d}")

    poses3d_copy = poses3d.copy()
    logger.info(f"Copied Poses3D: {poses3d_copy}")

    poses3d_numpy = poses3d.to_numpy(copy=True)
    logger.info(f"NumPy Poses3D: {poses3d_numpy}")

    poses3d_quat = poses3d.as_quat()
    logger.info(f"Poses3D as quaternion: {poses3d_quat}")

    poses3d_euler_deg = poses3d.as_euler(degrees=True)
    logger.info(f"Poses3D as Euler degrees: {poses3d_euler_deg}")

    poses3d_euler_rad = poses3d.as_euler(degrees=False)
    logger.info(f"Poses3D as Euler radians: {poses3d_euler_rad}")

    poses3d_rotvec = poses3d.as_rotvec()
    logger.info(f"Poses3D as rotation vector: {poses3d_rotvec}")

    first_pose3d = poses3d[0]
    logger.info(f"First Pose3D via indexing: {first_pose3d}")

    poses3d_subset = poses3d[0:1]
    logger.info(f"Poses3D subset via slicing: {poses3d_subset}")

    reshaped = np.reshape(poses3d, (2, 6))
    logger.info(f"Poses3D with np.reshape: {reshaped}")

    # ======================= Visualize =========================================
    rr.init("poses3d_example", spawn=True)
    datatypes.visualize(poses3d, entity_path="/poses3d", label=["Poses3D 0", "Poses3D 1"])

    # ======================= Serialize / Deserialize ===========================
    start = time.perf_counter()
    serialized = datatypes.serialize(poses3d)
    serialization_ms = (time.perf_counter() - start) * 1000

    start = time.perf_counter()
    deserialized = datatypes.deserialize(serialized)["param_0"]
    deserialization_ms = (time.perf_counter() - start) * 1000

    logger.info(f"Deserialized Poses3D: {deserialized}")
    logger.info(f"Round-trip successful: {poses3d == deserialized}")
    logger.info(f"Serialization time: {serialization_ms:.3f} ms")
    logger.info(f"Deserialization time: {deserialization_ms:.3f} ms")


if __name__ == "__main__":
    poses3d_example()