Skip to content

Pose2D

Represents a single 2D pose: a planar position plus a heading angle.

Parameters

FieldTypeDescription
datanp.ndarray | list | tupleArray-like input of shape (3,): [x, y, theta], converted to a contiguous float32 array.

Raises

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

Attributes

AttributeTypeDescription
datanp.ndarrayDefensive copy of the underlying (3,) float32 array. Assigning a new value re-validates it the same way as construction.
shapetuple[int, ...]Always (3,).
ndimintAlways 1.
dtypenp.dtypeAlways float32.
sizeintAlways 3.

Methods

MethodDescription
to_numpy(copy=True)Returns the pose as np.ndarray. Pass copy=False for a reference to the internal array instead — faster, but mutating it mutates the Pose2D too.
copy()Returns a new Pose2D with an independent copy of the data.
Pose2D.coerce(value)Returns value unchanged if it's already a Pose2D; otherwise wraps an array-like into one. Raises TypeError for any other input.

Operators

OperationBehavior
p == otherTrue only if other is also a Pose2D with element-equal data. False for anything else.
len(p)Always 3.
np.asarray(p)Works directly via __array__. Always returns a copy; use to_numpy(copy=False) for a zero-copy view.
p + arrayNot implemented on Pose2D — Python falls back to NumPy's array coercion (__array__), so e.g. p + np.array([1.0, 1.0, 0.0]) returns a plain np.ndarray, not a Pose2D.
hash(p)Not supported — mutable via the data setter.

Visualization

datatypes.visualize(pose, entity_path=...) logs the pose's posed frame (X/Y axes rotated by theta, translated by [x, y]) alongside a labeled world-origin frame. Per-axis labels are omitted; only the world-origin frame is labeled "origin". Passing label="..." attaches a floating text label at the posed frame's translation.

Example

python
"""Demonstrates the Telekinesis Pose2D datatype."""

import time

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

from telekinesis import datatypes

def pose2d_example():
    """Demonstrate creation, access, visualization, update, NumPy translation, and serialization."""

    # ======================= Create ============================================
    pose = [1.0, 2.0, 0.5]
    pose2d = datatypes.Pose2D(pose)

    logger.info(f"Original Pose2D: {pose2d}")

    # ======================= Inspect ===========================================
    data = pose2d.data
    shape = pose2d.shape
    size = pose2d.size
    dtype = pose2d.dtype
    ndim = pose2d.ndim
    numpy_pose2d = pose2d.to_numpy()
    pose2d_copy = pose2d.copy()

    logger.info(f"shape={shape}, size={size}, ndim={ndim}, dtype={dtype}")
    logger.info(f"Underlying data: {data}")
    logger.info(f"NumPy array: {numpy_pose2d}")
    logger.info(f"Copy: {pose2d_copy}")

    # ======================= Visualize =========================================
    rr.init("pose2d_example", spawn=True)
    datatypes.visualize(pose2d, entity_path="/Pose2D", label="My Pose2D")

    # ======================= Update ============================================
    new_data = [3.0, 4.0, 1.0]
    pose2d.data = new_data
    logger.info(f"Updated Pose2D: {pose2d}")
    datatypes.visualize(pose2d, entity_path="/Pose2D/updated", label="Updated Pose2D")

    # ======================= Translate =========================================
    translated = pose2d + np.array([1.0, 1.0, 0.0])
    logger.info(f"Translated Pose2D: {translated}")

    # ======================= Serialize / Deserialize ===========================
    start = time.perf_counter()
    serialized = datatypes.serialize(pose2d)
    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 Pose2D: {deserialized}")
    logger.info(f"Round-trip successful: {deserialized.data == new_data}")
    logger.info(f"Serialization time: {serialization_ms:.3f} ms")
    logger.info(f"Deserialization time: {deserialization_ms:.3f} ms")


if __name__ == "__main__":
    pose2d_example()