Skip to content

Wrench3D

Represents a 3D wrench: a force plus a torque.

Parameters

FieldTypeDescription
datanp.ndarray | list | tupleArray-like input of shape (6,): [fx, fy, fz, tx, ty, tz], 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 (6,)
ValueErrordata contains a non-finite value (NaN/Inf)

Attributes

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

Methods

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

Operators

OperationBehavior
w == otherTrue only if other is also a Wrench3D with element-equal data. False for anything else.
len(w)Always 6.
np.asarray(w)Works directly via __array__. Always returns a copy; use to_numpy(copy=False) for a zero-copy view.
hash(w)Not supported — mutable via the data setter.

Visualization

datatypes.visualize(wrench, entity_path=...) logs a static world-origin frame (labeled "origin"), a cyan force arrow labeled "f" from the origin, and a magenta torque arrow labeled "τ" from the origin. Passing label="..." attaches a floating text label at the static origin frame.

Example

python
"""Demonstrates the Telekinesis Wrench3D datatype."""

import time

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

from telekinesis import datatypes

def wrench3d_example():
    """Demonstrate creation, access, visualization, update, NumPy interop, and serialization."""

    # ======================= Create ============================================
    values = np.array([1.0, 0.0, 0.0, 0.0, 0.0, 0.5], dtype=np.float32)
    wrench3d = datatypes.Wrench3D(values)

    logger.info(f"Input values: {values}")
    logger.info(f"Created Wrench3D: {wrench3d}")

    # ======================= Inspect ===========================================
    data = wrench3d.data
    shape = wrench3d.shape
    size = wrench3d.size
    dtype = wrench3d.dtype
    ndim = wrench3d.ndim
    numpy_array = wrench3d.to_numpy()
    wrench3d_copy = wrench3d.copy()

    logger.info(f"shape={shape}, size={size}, ndim={ndim}, dtype={dtype}")
    logger.info(f"Wrench3D data: {data}")
    logger.info(f"NumPy array: {numpy_array}")
    logger.info(f"Copied Wrench3D: {wrench3d_copy}")

    # ======================= Visualize =========================================
    rr.init("wrench3d_example", spawn=True)
    datatypes.visualize(wrench3d, entity_path="/Wrench3D", label="Original Wrench3D")

    # ======================= Update ============================================
    wrench3d.data = np.array([0.0, 2.0, 0.0, 0.0, 0.0, 1.5], dtype=np.float32)

    logger.info(f"Updated Wrench3D: {wrench3d}")
    datatypes.visualize(wrench3d, entity_path="/Wrench3D/updated", label="Updated Wrench3D")

    # ======================= NumPy Interop =====================================
    force = numpy_array[:3]
    torque = numpy_array[3:]
    force_magnitude = np.linalg.norm(force)
    torque_magnitude = np.linalg.norm(torque)

    logger.info(f"Force (fx, fy, fz): {force}")
    logger.info(f"Torque (tx, ty, tz): {torque}")
    logger.info(f"force_magnitude={force_magnitude}, torque_magnitude={torque_magnitude}")

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


if __name__ == "__main__":
    wrench3d_example()