3D transformations for Python with comprehensive rotation representations, coordinate conversions, and visualization tools
—
Trajectories in three dimensions (SE(3)) providing batch operations on poses or transformations that are 400 to 1000 times faster than individual conversions. This module handles sequences of transformations using various representations including dual quaternions, position-quaternions, and exponential coordinates.
Core batch operations for transformation matrices including inversion and concatenation.
def invert_transforms(A2B):
"""
Invert transformation matrices.
Parameters:
- A2B: array-like, shape (..., 4, 4) - transformation matrices
Returns:
- B2A: array, shape (..., 4, 4) - inverted transformations
"""
def concat_one_to_many(A2B, B2C):
"""
Concatenate one transformation with many transformations.
Parameters:
- A2B: array-like, shape (4, 4) - single transformation
- B2C: array-like, shape (..., 4, 4) - multiple transformations
Returns:
- A2C: array, shape (..., 4, 4) - concatenated transformations
"""
def concat_many_to_one(A2B, B2C):
"""
Concatenate many transformations with one transformation.
Parameters:
- A2B: array-like, shape (..., 4, 4) - multiple transformations
- B2C: array-like, shape (4, 4) - single transformation
Returns:
- A2C: array, shape (..., 4, 4) - concatenated transformations
"""
def concat_many_to_many(A2B, B2C):
"""
Concatenate corresponding pairs of transformations.
Parameters:
- A2B: array-like, shape (..., 4, 4) - first transformations
- B2C: array-like, shape (..., 4, 4) - second transformations
Returns:
- A2C: array, shape (..., 4, 4) - concatenated transformations
"""
def concat_dynamic(A2B, B2C):
"""
Dynamically concatenate transformations with broadcasting.
Parameters:
- A2B: array-like, shape (..., 4, 4) - first transformations
- B2C: array-like, shape (..., 4, 4) - second transformations
Returns:
- A2C: array, shape (..., 4, 4) - concatenated transformations
"""Operations for position-quaternion representation combining translation and rotation.
def transforms_from_pqs(pqs):
"""
Convert position-quaternions to transformation matrices.
Parameters:
- pqs: array-like, shape (..., 7) - position-quaternions [x, y, z, qw, qx, qy, qz]
Returns:
- transforms: array, shape (..., 4, 4) - transformation matrices
"""
def pqs_from_transforms(transforms):
"""
Convert transformation matrices to position-quaternions.
Parameters:
- transforms: array-like, shape (..., 4, 4) - transformation matrices
Returns:
- pqs: array, shape (..., 7) - position-quaternions [x, y, z, qw, qx, qy, qz]
"""Dual quaternion representation for efficient transformation operations and interpolation.
def dual_quaternions_from_pqs(pqs):
"""
Convert position-quaternions to dual quaternions.
Parameters:
- pqs: array-like, shape (..., 7) - position-quaternions
Returns:
- dqs: array, shape (..., 8) - dual quaternions
"""
def dual_quaternions_from_transforms(transforms):
"""
Convert transformation matrices to dual quaternions.
Parameters:
- transforms: array-like, shape (..., 4, 4) - transformation matrices
Returns:
- dqs: array, shape (..., 8) - dual quaternions
"""
def pqs_from_dual_quaternions(dqs):
"""
Convert dual quaternions to position-quaternions.
Parameters:
- dqs: array-like, shape (..., 8) - dual quaternions
Returns:
- pqs: array, shape (..., 7) - position-quaternions
"""
def transforms_from_dual_quaternions(dqs):
"""
Convert dual quaternions to transformation matrices.
Parameters:
- dqs: array-like, shape (..., 8) - dual quaternions
Returns:
- transforms: array, shape (..., 4, 4) - transformation matrices
"""
def batch_concatenate_dual_quaternions(dq1, dq2):
"""
Concatenate dual quaternions.
Parameters:
- dq1: array-like, shape (..., 8) - first dual quaternions
- dq2: array-like, shape (..., 8) - second dual quaternions
Returns:
- dq_result: array, shape (..., 8) - concatenated dual quaternions
"""
def batch_dq_conj(dqs):
"""
Compute dual quaternion conjugates.
Parameters:
- dqs: array-like, shape (..., 8) - dual quaternions
Returns:
- dq_conj: array, shape (..., 8) - conjugated dual quaternions
"""
def batch_dq_q_conj(dqs):
"""
Compute quaternion part conjugates of dual quaternions.
Parameters:
- dqs: array-like, shape (..., 8) - dual quaternions
Returns:
- dq_q_conj: array, shape (..., 8) - quaternion-conjugated dual quaternions
"""
def batch_dq_prod_vector(dqs, vectors):
"""
Apply dual quaternions to transform vectors.
Parameters:
- dqs: array-like, shape (..., 8) - dual quaternions
- vectors: array-like, shape (..., 3) - vectors to transform
Returns:
- transformed: array, shape (..., 3) - transformed vectors
"""
def dual_quaternions_power(dqs, t):
"""
Raise dual quaternions to a power.
Parameters:
- dqs: array-like, shape (..., 8) - dual quaternions
- t: array-like, shape (...,) - power values
Returns:
- dq_power: array, shape (..., 8) - powered dual quaternions
"""
def dual_quaternions_sclerp(start, end, t):
"""
Screw linear interpolation between dual quaternions.
Parameters:
- start: array-like, shape (..., 8) - start dual quaternions
- end: array-like, shape (..., 8) - end dual quaternions
- t: array-like, shape (...,) - interpolation parameters [0, 1]
Returns:
- interpolated: array, shape (..., 8) - interpolated dual quaternions
"""Operations using screw theory for representing transformations and motions.
def dual_quaternions_from_screw_parameters(S, theta):
"""
Convert screw parameters to dual quaternions.
Parameters:
- S: array-like, shape (..., 6) - screw axes [omega, v]
- theta: array-like, shape (...,) - screw angles
Returns:
- dqs: array, shape (..., 8) - dual quaternions
"""
def screw_parameters_from_dual_quaternions(dqs):
"""
Convert dual quaternions to screw parameters.
Parameters:
- dqs: array-like, shape (..., 8) - dual quaternions
Returns:
- S: array, shape (..., 6) - screw axes
- theta: array, shape (...,) - screw angles
"""
def transforms_from_exponential_coordinates(Stheta):
"""
Convert exponential coordinates to transformation matrices.
Parameters:
- Stheta: array-like, shape (..., 6) - exponential coordinates [omega*theta, v*theta]
Returns:
- transforms: array, shape (..., 4, 4) - transformation matrices
"""
def exponential_coordinates_from_transforms(transforms):
"""
Convert transformation matrices to exponential coordinates.
Parameters:
- transforms: array-like, shape (..., 4, 4) - transformation matrices
Returns:
- Stheta: array, shape (..., 6) - exponential coordinates
"""
def mirror_screw_axis_direction(S):
"""
Mirror screw axis direction.
Parameters:
- S: array-like, shape (..., 6) - screw axes
Returns:
- S_mirrored: array, shape (..., 6) - mirrored screw axes
"""Tools for generating random trajectories and plotting trajectory paths.
def random_trajectories(n_steps, n_trajectories=1, **kwargs):
"""
Generate random trajectories.
Parameters:
- n_steps: int - number of steps in each trajectory
- n_trajectories: int - number of trajectories to generate
- **kwargs: additional parameters for trajectory generation
Returns:
- trajectories: array, shape (n_trajectories, n_steps, 4, 4) - random trajectories
"""
def plot_trajectory(P=None, show_direction=True, **kwargs):
"""
Plot 3D trajectory.
Parameters:
- P: array-like, shape (n_steps, 3) - trajectory positions
- show_direction: bool - whether to show trajectory direction
- **kwargs: additional plotting parameters
Returns:
- artists: list - matplotlib artists for the trajectory
"""import numpy as np
from pytransform3d.trajectories import (
transforms_from_pqs,
invert_transforms,
concat_many_to_many
)
# Create trajectory as position-quaternions
n_steps = 100
pqs = np.zeros((n_steps, 7))
pqs[:, :3] = np.random.rand(n_steps, 3) # positions
pqs[:, 3] = 1.0 # quaternion w component
# Convert to transformation matrices
transforms = transforms_from_pqs(pqs)
print(transforms.shape) # (100, 4, 4)
# Compute inverse transformations
inv_transforms = invert_transforms(transforms)
# Chain transformations
base_transforms = np.eye(4).reshape(1, 4, 4).repeat(n_steps, axis=0)
final_transforms = concat_many_to_many(base_transforms, transforms)import numpy as np
from pytransform3d.trajectories import (
dual_quaternions_from_pqs,
dual_quaternions_sclerp,
pqs_from_dual_quaternions
)
# Start and end poses
start_pq = np.array([0, 0, 0, 1, 0, 0, 0]) # origin
end_pq = np.array([1, 1, 1, 0.707, 0, 0, 0.707]) # translated and rotated
# Convert to dual quaternions
start_dq = dual_quaternions_from_pqs(start_pq)
end_dq = dual_quaternions_from_pqs(end_pq)
# Interpolate using screw linear interpolation
t_values = np.linspace(0, 1, 50)
interpolated_dqs = dual_quaternions_sclerp(
np.broadcast_to(start_dq, (50, 8)),
np.broadcast_to(end_dq, (50, 8)),
t_values
)
# Convert back to position-quaternions
interpolated_pqs = pqs_from_dual_quaternions(interpolated_dqs)import numpy as np
import matplotlib.pyplot as plt
from pytransform3d.trajectories import plot_trajectory
# Generate spiral trajectory
t = np.linspace(0, 4*np.pi, 100)
positions = np.column_stack([
np.cos(t),
np.sin(t),
t / (4*np.pi)
])
# Plot trajectory
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
plot_trajectory(positions, show_direction=True, ax=ax)
plt.show()Install with Tessl CLI
npx tessl i tessl/pypi-pytransform3d