CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pyquaternion

A fully featured, pythonic library for quaternion representation, manipulation, 3D animation and geometry.

Pending
Overview
Eval results
Files

advanced-math.mddocs/

Advanced Mathematics

Advanced mathematical operations including exponential/logarithm functions, Riemannian manifold operations, and distance metrics for quaternions.

Capabilities

Exponential and Logarithm Operations

Quaternion exponential and logarithm functions for advanced mathematical computations.

@classmethod
def exp(cls, q):
    """
    Quaternion exponential function.
    
    Computes exp(q) for any quaternion using the formula:
    exp(q) = exp(q.scalar) * (cos(|q.vector|) + (q.vector/|q.vector|) * sin(|q.vector|))
    
    Parameters:
        q: Quaternion, input quaternion argument
    
    Returns:
        Quaternion: exp(q)
        
    Note:
        Can compute exponential of any quaternion, not just unit quaternions.
        For pure imaginary quaternions, reduces to Euler's formula.
    """

@classmethod
def log(cls, q):
    """
    Quaternion natural logarithm.
    
    Computes log(q) using the formula:
    log(q) = log(|q|) + (q.vector/|q.vector|) * acos(q.scalar/|q|)
    
    Parameters:
        q: Quaternion, input quaternion (should be non-zero)
    
    Returns:
        Quaternion: log(q) = (log(|q|), v/|v| * acos(w/|q|))
                   For zero quaternion: (-inf, nan*vector)
                   For real quaternions: (log(|q|), [0,0,0])
    
    Note:
        Undefined for zero quaternion (returns -inf + nan*i + nan*j + nan*k).
        For real quaternions, returns real logarithm with zero vector part.
    """

Usage Examples:

from pyquaternion import Quaternion
import numpy as np

# Basic exponential and logarithm
q = Quaternion(1, 0.5, 0.3, 0.2)
exp_q = Quaternion.exp(q)
log_exp_q = Quaternion.log(exp_q)

print(f"Original: {q}")
print(f"exp(q): {exp_q}")
print(f"log(exp(q)): {log_exp_q}")  # Should approximately equal original

# Pure imaginary quaternion (like Euler's formula)
pure_imag = Quaternion(0, 1, 0, 0)  # i
exp_i = Quaternion.exp(pure_imag)
print(f"exp(i): {exp_i}")  # Should be cos(1) + i*sin(1)

# Real quaternion
real_q = Quaternion(2.0)  # Pure real
exp_real = Quaternion.exp(real_q)
log_real = Quaternion.log(real_q)
print(f"exp(2): {exp_real}")  # Should be (e^2, 0, 0, 0)
print(f"log(2): {log_real}")  # Should be (ln(2), 0, 0, 0)

# Zero and problematic cases
try:
    zero_q = Quaternion(0, 0, 0, 0)
    log_zero = Quaternion.log(zero_q)
    print(f"log(0): {log_zero}")  # (-inf, nan, nan, nan)
except:
    print("Zero quaternion logarithm handling")

Manifold Operations

Exponential and logarithm maps on the quaternion Riemannian manifold for advanced geometric computations.

@classmethod
def exp_map(cls, q, eta):
    """
    Quaternion exponential map on Riemannian manifold.
    
    Computes the endpoint of geodesic starting at q in direction eta,
    with length equal to magnitude of eta.
    
    Parameters:
        q: Quaternion, base point of exponential map
        eta: Quaternion, tangent vector argument (direction and magnitude)
    
    Returns:
        Quaternion: Endpoint quaternion p = q * exp(eta)
        
    Note:
        Important for integrating orientation variations (angular velocities).
        Projects quaternion tangent vectors onto the quaternion manifold.
    """

@classmethod
def sym_exp_map(cls, q, eta):
    """
    Quaternion symmetrized exponential map.
    
    Symmetric formulation analogous to exponential maps for 
    symmetric positive definite tensors.
    
    Parameters:
        q: Quaternion, base point
        eta: Quaternion, tangent vector argument
    
    Returns:
        Quaternion: p = sqrt(q) * exp(eta) * sqrt(q)
    """

@classmethod
def log_map(cls, q, p):
    """
    Quaternion logarithm map on Riemannian manifold.
    
    Finds tangent vector with length and direction given by
    the geodesic joining q and p.
    
    Parameters:
        q: Quaternion, base point where logarithm is computed
        p: Quaternion, target point
    
    Returns:
        Quaternion: Tangent vector from q to p
                   Formula: log(q^(-1) * p)
    """

@classmethod
def sym_log_map(cls, q, p):
    """
    Quaternion symmetrized logarithm map.
    
    Symmetric formulation for numerically stable gradient descent
    on the Riemannian quaternion manifold.
    
    Parameters:
        q: Quaternion, base point
        p: Quaternion, target point
    
    Returns:
        Quaternion: Symmetrized tangent vector
                   Formula: log(q^(-1/2) * p * q^(-1/2))
    """

Usage Examples:

# Manifold operations for trajectory planning
q_start = Quaternion(axis=[0, 0, 1], degrees=0)
q_end = Quaternion(axis=[0, 0, 1], degrees=90)

# Compute tangent vector from start to end
tangent_vec = Quaternion.log_map(q_start, q_end)
print(f"Tangent vector: {tangent_vec}")

# Move along geodesic using exponential map
fraction = 0.3  # 30% of the way
scaled_tangent = Quaternion(tangent_vec.elements * fraction)
intermediate = Quaternion.exp_map(q_start, scaled_tangent)
print(f"30% along geodesic: {intermediate}")

# Verify round-trip
reconstructed_end = Quaternion.exp_map(q_start, tangent_vec)
print(f"Original end: {q_end}")
print(f"Reconstructed: {reconstructed_end}")

# Symmetrized operations (more numerically stable)
sym_tangent = Quaternion.sym_log_map(q_start, q_end)
sym_intermediate = Quaternion.sym_exp_map(q_start, scaled_tangent)
print(f"Symmetric tangent: {sym_tangent}")
print(f"Symmetric intermediate: {sym_intermediate}")

Distance Metrics

Various distance measures between quaternions for similarity analysis and optimization.

@classmethod
def absolute_distance(cls, q0, q1):
    """
    Quaternion absolute distance accounting for sign ambiguity.
    
    Computes chord distance of shortest path connecting q0 to q1,
    accounting for the fact that q and -q represent the same rotation.
    
    Parameters:
        q0: Quaternion, first quaternion
        q1: Quaternion, second quaternion
    
    Returns:
        float: Positive chord distance, good indicator for rotation similarity
               Returns min(|q0 - q1|, |q0 + q1|)
               
    Note:
        Does not measure distance on hypersphere, but accounts for
        quaternion double-cover (q ≡ -q for rotations).
    """

@classmethod
def distance(cls, q0, q1):
    """
    Intrinsic geodesic distance between quaternions.
    
    Computes length of geodesic arc connecting q0 to q1 on the
    quaternion manifold.
    
    Parameters:
        q0: Quaternion, first quaternion
        q1: Quaternion, second quaternion
    
    Returns:
        float: Geodesic arc length
               Formula: |log_map(q0, q1).norm|
    """

@classmethod
def sym_distance(cls, q0, q1):
    """
    Symmetrized geodesic distance between quaternions.
    
    More numerically stable for iterative gradient descent on
    Riemannian quaternion manifold.
    
    Parameters:
        q0: Quaternion, first quaternion
        q1: Quaternion, second quaternion
    
    Returns:
        float: Symmetrized geodesic distance
        
    Note:
        Distance between q and -q equals π, making this less useful
        for rotation similarity when samples span angles > π/2.
    """

Usage Examples:

# Compare different distance metrics
q1 = Quaternion(axis=[1, 0, 0], degrees=30)
q2 = Quaternion(axis=[1, 0, 0], degrees=60)
q3 = Quaternion(axis=[0, 1, 0], degrees=30)  # Different axis

# Compute various distances
abs_dist_12 = Quaternion.absolute_distance(q1, q2)
abs_dist_13 = Quaternion.absolute_distance(q1, q3)

geo_dist_12 = Quaternion.distance(q1, q2)
geo_dist_13 = Quaternion.distance(q1, q3)

sym_dist_12 = Quaternion.sym_distance(q1, q2)
sym_dist_13 = Quaternion.sym_distance(q1, q3)

print("Distance comparison:")
print(f"q1 to q2 (same axis, 30° apart):")
print(f"  Absolute: {abs_dist_12:.4f}")
print(f"  Geodesic: {geo_dist_12:.4f}")
print(f"  Symmetric: {sym_dist_12:.4f}")

print(f"q1 to q3 (different axis, same angle):")
print(f"  Absolute: {abs_dist_13:.4f}")
print(f"  Geodesic: {geo_dist_13:.4f}")
print(f"  Symmetric: {sym_dist_13:.4f}")

# Demonstrate sign ambiguity handling
q_pos = Quaternion(1, 0, 0, 0)
q_neg = Quaternion(-1, 0, 0, 0)  # Same rotation, opposite quaternion

regular_dist = (q_pos - q_neg).norm  # Regular Euclidean distance
absolute_dist = Quaternion.absolute_distance(q_pos, q_neg)

print(f"\nSign ambiguity demonstration:")
print(f"q = {q_pos}")
print(f"-q = {q_neg}")
print(f"Regular Euclidean distance: {regular_dist:.4f}")
print(f"Absolute distance: {absolute_dist:.4f}")  # Should be ~0

Clustering and Optimization Applications

# Example: Quaternion averaging using distance metrics
def quaternion_mean_iterative(quaternions, max_iterations=100, tolerance=1e-6):
    """
    Compute quaternion mean using iterative optimization on manifold.
    """
    # Initialize with first quaternion
    mean_q = quaternions[0].normalised
    
    for iteration in range(max_iterations):
        # Compute tangent vectors to all quaternions
        tangent_sum = Quaternion(0, 0, 0, 0)
        
        for q in quaternions:
            tangent_vec = Quaternion.log_map(mean_q, q)
            tangent_sum += tangent_vec
        
        # Average tangent vector
        avg_tangent = Quaternion(tangent_sum.elements / len(quaternions))
        
        # Update mean using exponential map
        step_size = 0.5  # Learning rate
        scaled_tangent = Quaternion(avg_tangent.elements * step_size)
        new_mean = Quaternion.exp_map(mean_q, scaled_tangent)
        
        # Check convergence
        update_distance = Quaternion.distance(mean_q, new_mean)
        if update_distance < tolerance:
            break
            
        mean_q = new_mean.normalised
    
    return mean_q

# Usage
sample_quaternions = [
    Quaternion(axis=[1, 0, 0], degrees=10),
    Quaternion(axis=[1, 0, 0], degrees=20),
    Quaternion(axis=[1, 0, 0], degrees=15),
    Quaternion(axis=[1, 0, 0], degrees=12),
]

mean_quaternion = quaternion_mean_iterative(sample_quaternions)
print(f"Mean quaternion: {mean_quaternion}")
print(f"Mean angle: {mean_quaternion.degrees:.1f}°")

Install with Tessl CLI

npx tessl i tessl/pypi-pyquaternion

docs

advanced-math.md

basic-operations.md

construction.md

index.md

interpolation.md

rotation.md

tile.json