Wrench3D
Represents a 3D wrench: a force plus a torque.
Parameters
| Field | Type | Description |
|---|---|---|
data | np.ndarray | list | tuple | Array-like input of shape (6,): [fx, fy, fz, tx, ty, tz], converted to a contiguous float32 array. |
Raises
| Exception | Condition |
|---|---|
TypeError | data can't be converted to float32 (e.g. non-numeric elements) |
ValueError | data is not rank-1, or its shape isn't (6,) |
ValueError | data contains a non-finite value (NaN/Inf) |
Attributes
| Attribute | Type | Description |
|---|---|---|
data | np.ndarray | Defensive copy of the underlying (6,) float32 array. Assigning a new value re-validates it the same way as construction. |
shape | tuple[int, ...] | Always (6,). |
ndim | int | Always 1. |
dtype | np.dtype | Always float32. |
size | int | Always 6. |
Methods
| Method | Description |
|---|---|
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
| Operation | Behavior |
|---|---|
w == other | True 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()
