geometry¶
- wrenfold.geometry.inverse_left_jacobian_of_so3(w: wrenfold.sym.MatrixExpr, epsilon: wrenfold.sym.Expr | None) wrenfold.sym.MatrixExpr ¶
Compute the inverse of the left jacobian of SO(3). Given a rotation vector
w
, this method computes the 3x3 derivative:\[\mathbf{J}_l^{-1} = \frac{ \partial \left(\text{log}\left( \text{exp}\left(\delta\mathbf{x}\right) \cdot \text{exp}\left(\mathbf{w}\right)\right) - \mathbf{w}\right) } {\partial \delta\mathbf{x}} \biggr\rvert_{\delta\mathbf{x} = 0}\]Where
exp(...)
maps from a rotation vector to a quaternion, andlog(...)
maps from a quaternion to a rotation vector.- Parameters:
w – 3x1 rotation vector, in radians.
epsilon – If provided,
epsilon
specifies the threshold below which a small-angle approximation is used. A conditional will be inserted usingwrenfold.sym.where()
to switch between the normal and small-angle code paths. This value should be positive.
- Returns:
The 3x3 inverse left jacobian of SO(3).
References
- wrenfold.geometry.left_jacobian_of_so3(w: wrenfold.sym.MatrixExpr, epsilon: wrenfold.sym.Expr | None) wrenfold.sym.MatrixExpr ¶
Compute the left jacobian of SO(3). Given a rotation vector
w
, this method computes the 3x3 derivative:\[\mathbf{J}_l = \frac{ \partial \text{log}\left( \text{exp}\left(\mathbf{w} + \delta\mathbf{w}\right) \cdot \text{exp}\left(\mathbf{w}\right)^T\right) } {\partial \delta\mathbf{w}} \biggr\rvert_{\delta\mathbf{w} = 0}\]Where
exp(...)
maps from a rotation vector to a quaternion, andlog(...)
maps from a quaternion to a rotation vector.This matrix has a secondary interpretation, as the integral:
\[\mathbf{J}_l = \int_{0}^{1} \text{exp}\left(\alpha \cdot \mathbf{w}\right) \,d\alpha\]Tip
The right jacobian can be obtained by transposing the left jacobian.
- Parameters:
w – 3x1 rotation vector, in radians.
epsilon – If provided,
epsilon
specifies the threshold below which a small-angle approximation is used. A conditional will be inserted usingwrenfold.sym.where()
to switch between the normal and small-angle code paths. This value should be positive.
- Returns:
The 3x3 left jacobian of SO(3).
References
- class wrenfold.geometry.Quaternion¶
A quaternion class used to represent 3D rotations and orientations.
- __eq__(self: wrenfold.geometry.Quaternion, other: wrenfold.geometry.Quaternion) bool ¶
Check for strict equality. This is not the same as mathematical equivalence.
- __hash__(self: wrenfold.geometry.Quaternion) int ¶
Compute hash.
- __init__(*args, **kwargs)¶
Overloaded function.
__init__(self: wrenfold.geometry.Quaternion, w: wrenfold.sym.Expr, x: wrenfold.sym.Expr, y: wrenfold.sym.Expr, z: wrenfold.sym.Expr) -> None
Construct a quaternion from scalar expressions in
[w,x,y,z]
order.- Parameters:
w – The scalar component of the quaternion.
x – Vector element multiplied by basis vector \(\mathbf{i}\).
y – Vector element multiplied by basis vector \(\mathbf{j}\).
z – Vector element multiplied by basis vector \(\mathbf{k}\).
Caution
Quaternion
will not normalize after construction. It is expected that the user will pass normalized components, or invokewrenfold.sym.Quaternion.normalized()
.Examples
>>> w, x, y, z = sym.symbols('w, x, y, z') >>> q = geometry.Quaternion(w, x, y, z) >>> q Quaternion(w, x, y, z) >>> q.x x
__init__(self: wrenfold.geometry.Quaternion) -> None
Construct the identity quaternion.
Examples
>>> geometry.Quaternion() Quaternion(1, 0, 0, 0)
- __mul__(self: wrenfold.geometry.Quaternion, arg0: wrenfold.geometry.Quaternion) wrenfold.geometry.Quaternion ¶
- conjugate(self: wrenfold.geometry.Quaternion) wrenfold.geometry.Quaternion ¶
Compute the quaternion conjugate. Given the quaternion:
\[\mathbf{q} = q_w + q_x\cdot\mathbf{i} + q_y\cdot\mathbf{j} + q_z\cdot\mathbf{k}\]The conjugate is defined as:
\[\bar{\mathbf{q}} = q_w - q_x\cdot\mathbf{i} - q_y\cdot\mathbf{j} - q_z\cdot\mathbf{k}\]If \(\mathbf{q}\) is normalized, then \(\mathbf{q}\cdot\bar{\mathbf{q}}\) is the identity element.
- Returns:
Conjugated quaternion, where the signs of the
[x, y, z]
components have been flipped.
Examples
>>> w, x, y, z = sym.symbols('w, x, y, z') >>> q = geometry.Quaternion(w, x, y, z) >>> q * q.conjugate() Quaternion(w**2 + x**2 + y**2 + z**2, 0, 0, 0) >>> q = geometry.Quaternion(0, 1, 1, 0).normalized() >>> q.conjugate() * q Quaternion(1, 0, 0, 0)
- eval(self: wrenfold.geometry.Quaternion) numpy.ndarray ¶
Invoke
wrenfold.sym.Expr.eval()
on every element of the quaternion, and return a numpy array.- Returns:
4-element numpy array in
[w, x, y, z]
(scalar-first) order.
Examples
>>> geometry.Quaternion().eval() array([1., 0., 0., 0.])
- static from_angle_axis(*args, **kwargs)¶
Overloaded function.
from_angle_axis(angle: wrenfold.sym.Expr, vx: wrenfold.sym.Expr, vy: wrenfold.sym.Expr, vz: wrenfold.sym.Expr) -> wrenfold.geometry.Quaternion
Construct quaternion from an angle and normalized axis. This function constructs the quaternion:
\[\mathbf{q} = \cos{\frac{\theta}{2}} + v_x \cdot \sin{\frac{\theta}{2}} \cdot \mathbf{i} + v_y \cdot \sin{\frac{\theta}{2}} \cdot \mathbf{j} + v_z \cdot \sin{\frac{\theta}{2}} \cdot \mathbf{k}\]Caution
The resulting quaternion only represents a rotation if the axis
[vx, vy, vz]
is normalized.- Parameters:
angle – Rotation angle in radians.
vx – X component of the rotation axis.
vy – Y component of the rotation axis.
vz – Z component of the rotation axis.
- Returns:
A unit-norm quaternion representing the rotation about vector
[vx, vy, vz]
byangle
radians.
Examples
>>> angle, x, y, z = sym.symbols('angle, x, y, z') >>> geometry.Quaternion.from_angle_axis(angle, x, y, z) Quaternion(cos(angle/2), x*sin(angle/2), y*sin(angle/2), z*sin(angle/2))
from_angle_axis(angle: wrenfold.sym.Expr, axis: wrenfold.sym.MatrixExpr) -> wrenfold.geometry.Quaternion
Overload of
from_angle_axis
that acceptssym.MatrixExpr
for the axis.
- static from_rotation_matrix(R: wrenfold.sym.MatrixExpr) wrenfold.geometry.Quaternion ¶
Construct a quaternion from a rotation matrix. This function uses Sheppard’s method, as documented in section 3.3 of A Survey on the Computation of Quaternions from Rotation Matrices, Sarabandi and Thomas.
Caution
This operation is only valid if
R
is a valid member of SO(3).- Parameters:
R – 3x3 rotation matrix.
- Returns:
A unit-norm quaternion corresponding to the rotation matrix.
- static from_rotation_vector(*args, **kwargs)¶
Overloaded function.
from_rotation_vector(x: wrenfold.sym.Expr, y: wrenfold.sym.Expr, z: wrenfold.sym.Expr, epsilon: Optional[wrenfold.sym.Expr]) -> wrenfold.geometry.Quaternion
Construct quaternion from a rotation vector. A rotation vector (sometimes referred to as “Rodrigues parameters”) is parallel to the axis of rotation, and has a norm equal to the angle of rotation in radians.
Caution
This method encounters a singularity when the norm of
[x, y, z]
is zero. Refer to the note for argumentepsilon
on how this is handled.- Parameters:
x – X component of the vector, in radians.
y – Y component of the vector, in radians.
z – Z component of the vector, in radians.
epsilon – If provided,
epsilon
specifies the threshold below which a small-angle approximation is used. A conditional will be inserted usingwrenfold.sym.where()
to switch between the normal and small-angle code paths. This value should be positive.
- Returns:
A unit-norm quaternion representing the rotation vector
[x, y, z]
.
Examples
>>> geometry.Quaternion.from_rotation_vector(sym.pi, 0, 0, epsilon=None) Quaternion(0, 1, 0, 0)
from_rotation_vector(v: wrenfold.sym.MatrixExpr, epsilon: Optional[wrenfold.sym.Expr]) -> wrenfold.geometry.Quaternion
Overload of
from_rotation_vector
that acceptssym.MatrixExpr
.
- static from_wxyz(*args, **kwargs)¶
Overloaded function.
from_wxyz(wxyz: wrenfold.sym.MatrixExpr) -> wrenfold.geometry.Quaternion
Create a quaternion from a 4-element column vector in order
[w, x, y, z]
(scalar first).- Parameters:
wxyz – 4x1
sym.MatrixExpr
- Returns:
Quaternion instance.
from_wxyz(wxyz: Iterable) -> wrenfold.geometry.Quaternion
Overload of
wrenfold.geometry.Quaternion.from_wxyz()
that accepts Iterable[sym.Expr].
- static from_x_angle(angle: wrenfold.sym.Expr) wrenfold.geometry.Quaternion ¶
Construct quaternion that rotates about the x-axis by the specified angle.
- Parameters:
angle – Angle in radians.
- Returns:
A unit-norm quaternion representing a rotation about the x-axis.
- static from_xyzw(*args, **kwargs)¶
Overloaded function.
from_xyzw(xyzw: wrenfold.sym.MatrixExpr) -> wrenfold.geometry.Quaternion
Create a quaternion from a 4-element column vector in order
[x, y, z, w]
(scalar last).- Parameters:
xyzw – 4x1
sym.MatrixExpr
- Returns:
Quaternion instance.
from_xyzw(xyzw: Iterable) -> wrenfold.geometry.Quaternion
Overload of
wrenfold.geometry.Quaternion.from_xyzw()
that accepts Iterable[sym.Expr].
- static from_y_angle(angle: wrenfold.sym.Expr) wrenfold.geometry.Quaternion ¶
Construct quaternion that rotates about the y-axis by the specified angle.
- Parameters:
angle – Angle in radians.
- Returns:
A unit-norm quaternion representing a rotation about the y-axis.
- static from_z_angle(angle: wrenfold.sym.Expr) wrenfold.geometry.Quaternion ¶
Construct quaternion that rotates about the z-axis by the specified angle.
- Parameters:
angle – Angle in radians.
- Returns:
A unit-norm quaternion representing a rotation about the z-axis.
- inverse(self: wrenfold.geometry.Quaternion) wrenfold.geometry.Quaternion ¶
Compute the quaternion inverse. Given the quaternion:
\[\mathbf{q} = q_w + q_x\cdot\mathbf{i} + q_y\cdot\mathbf{j} + q_z\cdot\mathbf{k}\]The inverse is defined as:
\[\mathbf{q}^{-1} = \frac{q_w}{\lvert q \rvert^2} - \frac{q_x}{\lvert q \rvert^2}\cdot\mathbf{i} - \frac{q_y}{\lvert q \rvert^2}\cdot\mathbf{j} - \frac{q_z}{\lvert q \rvert^2}\cdot\mathbf{k}\]And \(\mathbf{q}\cdot\mathbf{q}^{-1}\) is the identity element.
- Returns:
Inverted quaternion, where the signs of the
[x, y, z]
components have been flipped and the all components are divided by the squared norm.
Examples
>>> q = geometry.Quaternion(4, 2, 1, -3) >>> q * q.inverse() Quaternion(1, 0, 0, 0)
- is_identical_to(*args, **kwargs)¶
Overloaded function.
is_identical_to(self: wrenfold.geometry.Quaternion, other: wrenfold.geometry.Quaternion) -> bool
Check for strict equality. This is not the same as mathematical equivalence.
is_identical_to(self: wrenfold.geometry.Quaternion, other: wrenfold.geometry.Quaternion) -> bool
Test if two quaternions have identical expression trees.
- norm(self: wrenfold.geometry.Quaternion) wrenfold.sym.Expr ¶
The L2 norm of
self
.- Returns:
Scalar-valued expression
sqrt(w**2 + x**2 + y**2 + z**2)
.
Examples
>>> w, x, y, z = sym.symbols('w, x, y, z') >>> geometry.Quaternion(w, x, y, z).norm() (w**2 + x**2 + y**2 + z**2)**(1/2)
- normalized(self: wrenfold.geometry.Quaternion) wrenfold.geometry.Quaternion ¶
Create a new quaternion by dividing every element of
self
byself.norm()
.- Returns:
Quaternion with unit norm.
Examples
>>> w, x, y, z = sym.symbols('w, x, y, z') >>> q = geometry.Quaternion(w, x, y, z) >>> norm = q.norm() >>> q.normalized().subs(norm, sym.symbols('q_n')) Quaternion(w/q_n, x/q_n, y/q_n, z/q_n) >>> geometry.Quaternion(0, 1, 1, 0).normalized() Quaternion(0, 2**(1/2)/2, 2**(1/2)/2, 0)
- right_local_coordinates_derivative(self: wrenfold.geometry.Quaternion) wrenfold.sym.MatrixExpr ¶
Compute the 3x4 derivative:
\[\frac{\partial \text{log}\left(\bar{\mathbf{q}} \cdot \left(\mathbf{q} + \delta\mathbf{q}\right) \right)}{\partial \delta\mathbf{q}}\biggr\rvert_{\delta\mathbf{q} = 0}\]Where
log(...)
converts a quaternion to a rotation vector, anddq
is an additive perturbation toself
. The derivative of the rotation vector is taken with respect to the four quaternion elements (ordered[w, x, y, z]
).- Returns:
3x4 jacobian of
d(log(self^T * (self + dq)) / dq
evaluated atdq = 0
.
Examples
>>> w, x, y, z = sym.symbols('w, x, y, z') >>> geometry.Quaternion(w, x, y, z).right_retract_derivative() [[-2*x, 2*w, 2*z, -2*y], [-2*y, -2*z, 2*w, 2*x], [-2*z, 2*y, -2*x, 2*w]]
- right_retract_derivative(self: wrenfold.geometry.Quaternion) wrenfold.sym.MatrixExpr ¶
Compute the 4x3 derivative of this quaternion with respect to a right-multiplied tangent-space perturbation. This is the derivative:
\[\frac{\partial \left[\mathbf{q} \cdot \text{exp}\left(\mathbf{v}\right)\right]} {\partial \mathbf{v}} \biggr\rvert_{\mathbf{v} = 0}\]Where
exp(...)
maps from a rotation vector to a quaternion. The derivatives of the four quaternion elements (ordered[w, x, y, z]
) are computed with respect to the three elements ofv
, linearized aboutv = 0
.- Returns:
4x3 jacobian
d(self * exp(v)) / dv
evaluated atv = 0
.
Examples
>>> w, x, y, z = sym.symbols('w, x, y, z') >>> geometry.Quaternion(w, x, y, z).right_retract_derivative() [[-x/2, -y/2, -z/2], [w/2, -z/2, y/2], [z/2, w/2, -x/2], [-y/2, x/2, w/2]]
- squared_norm(self: wrenfold.geometry.Quaternion) wrenfold.sym.Expr ¶
The sum of squared elements of
self
, or the squared L2 norm.- Returns:
Scalar-valued expression
w**2 + x**2 + y**2 + z**2
.
Examples
>>> w, x, y, z = sym.symbols('w, x, y, z') >>> geometry.Quaternion(w, x, y, z).squared_norm() w**2 + x**2 + y**2 + z**2
- subs(self: wrenfold.geometry.Quaternion, target: wrenfold.sym.Expr, replacement: wrenfold.sym.Expr) wrenfold.geometry.Quaternion ¶
Invoke
wrenfold.sym.Expr.subs()
on every element of the quaternion.
- to_angle_axis(self: wrenfold.geometry.Quaternion, epsilon: wrenfold.sym.Expr | None = 0) tuple[wrenfold.sym.Expr, wrenfold.sym.MatrixExpr] ¶
Recover a rotation angle and axis from a unit-norm quaternion. The method used is documented in Quaternion Computation, Neil Dantum, equation 19.
If the quaternion is near identity, recovering the normalized axis of rotation entails a division by zero. If the norm of the vector component of the quaternion falls below
epsilon
, the division is skipped and a constant value of[0, 0, 0]
is used instead.Caution
This operation is only valid if
self
is normalized.- Parameters:
epsilon – If specified, a conditional branch is inserted to handle the singularity for quaternions near identity. This value should be positive.
- Returns:
Angle in radians, converted into range
[0, pi]
. wrenfold.sym.MatrixExpr: Normalized axis of rotation.- Return type:
- to_list(self: wrenfold.geometry.Quaternion) list ¶
Convert to list in
[w, x, y, z]
(scalar first) order.
- to_rotation_matrix(self: wrenfold.geometry.Quaternion) wrenfold.sym.MatrixExpr ¶
Convert quaternion to an element of SO(3), the group of rotation matrices.
Caution
The result of this operation is only well defined if
self
is a normalized quaternion.- Returns:
A 3x3 rotation matrix.
- Return type:
Examples
>>> geometry.Quaternion().to_rotation_matrix() [[1, 0, 0], [0, 1, 0], [0, 0, 1]] >>> geometry.Quaternion(0, 1, 1, 0).normalized().to_rotation_matrix() [[0, 1, 0], [1, 0, 0], [0, 0, -1]]
References
- to_rotation_vector(self: wrenfold.geometry.Quaternion, epsilon: wrenfold.sym.Expr | None = 0, use_atan2: bool = True) wrenfold.sym.MatrixExpr ¶
Recover a rotation vector from a unit-norm quaternion. The following formula is used:
\[\mathbf{v} = \frac{2}{\lvert \mathbf{q}_v \rvert} \cdot \text{atan2}\left(\lvert \mathbf{q}_v \rvert, \text{abs}\left(q_w\right)\right) \cdot \text{sign}\left(q_w\right) \cdot \mathbf{q}_v\]Where \(\mathbf{q}_v\) is the vector component of the quaternion.
Caution
This operation is only valid if
self
is normalized.- Parameters:
epsilon – If provided,
epsilon
specifies the threshold below which a small-angle approximation is used. A conditional will be inserted usingwrenfold.sym.where()
to switch between the normal and small-angle code paths. This value should be positive.use_atan2 – Defaults to true. If false, an implementation that uses arccos is used instead. This may produce faster code.
- Returns:
3x1 matrix expression for the rotation vector.
- to_vector_wxyz(self: wrenfold.geometry.Quaternion) wrenfold.sym.MatrixExpr ¶
Convert to a 4x1 vector in
[w, x, y, z]
(scalar-first) order.
- to_vector_xyzw(self: wrenfold.geometry.Quaternion) wrenfold.sym.MatrixExpr ¶
Convert to a 4x1 vector in
[x, y, z, w]
(scalar-last) order.
- property w¶
Access scalar element of quaternion.
- static with_name(name: str) wrenfold.geometry.Quaternion ¶
Create a quaternion filled with
variable
expressions, prefixed with the provided name.- Parameters:
name – Name prefix to prepend to the quaternion elements.
- Returns:
Quaternion instance.
Examples
>>> geometry.Quaternion.with_name('foo') Quaternion(foo_w, foo_x, foo_y, foo_z)
- property x¶
Access i coefficient of quaternion.
- property y¶
Access j coefficient of quaternion.
- property z¶
Access k coefficient of quaternion.