# -----------------------------------------------------------------------------
# This file was autogenerated by symforce from template:
# ops/CLASS/lie_group_ops.py.jinja
# Do NOT modify by hand.
# -----------------------------------------------------------------------------
# ruff: noqa: PLR0915, F401, PLW0211, PLR0914
import math
import typing as T
import numpy
import sym
[docs]class LieGroupOps(object):
"""
Python LieGroupOps implementation for :py:class:`symforce.geo.rot3.Rot3`.
"""
[docs] @staticmethod
def from_tangent(vec, epsilon):
# type: (numpy.ndarray, float) -> sym.Rot3
# Total ops: 15
# Input arrays
if vec.shape == (3,):
vec = vec.reshape((3, 1))
elif vec.shape != (3, 1):
raise IndexError(
"vec is expected to have shape (3, 1) or (3,); instead had shape {}".format(
vec.shape
)
)
# Intermediate terms (3)
_tmp0 = math.sqrt(epsilon**2 + vec[0, 0] ** 2 + vec[1, 0] ** 2 + vec[2, 0] ** 2)
_tmp1 = (1.0 / 2.0) * _tmp0
_tmp2 = math.sin(_tmp1) / _tmp0
# Output terms
_res = [0.0] * 4
_res[0] = _tmp2 * vec[0, 0]
_res[1] = _tmp2 * vec[1, 0]
_res[2] = _tmp2 * vec[2, 0]
_res[3] = math.cos(_tmp1)
return sym.Rot3.from_storage(_res)
[docs] @staticmethod
def to_tangent(a, epsilon):
# type: (sym.Rot3, float) -> numpy.ndarray
# Total ops: 17
# Input arrays
_a = a.data
# Intermediate terms (2)
_tmp0 = min(abs(_a[3]), 1 - epsilon)
_tmp1 = (
2
* (2 * min(0, (0.0 if _a[3] == 0 else math.copysign(1, _a[3]))) + 1)
* math.acos(_tmp0)
/ math.sqrt(1 - _tmp0**2)
)
# Output terms
_res = numpy.zeros(3)
_res[0] = _a[0] * _tmp1
_res[1] = _a[1] * _tmp1
_res[2] = _a[2] * _tmp1
return _res
[docs] @staticmethod
def retract(a, vec, epsilon):
# type: (sym.Rot3, numpy.ndarray, float) -> sym.Rot3
# Total ops: 45
# Input arrays
_a = a.data
if vec.shape == (3,):
vec = vec.reshape((3, 1))
elif vec.shape != (3, 1):
raise IndexError(
"vec is expected to have shape (3, 1) or (3,); instead had shape {}".format(
vec.shape
)
)
# Intermediate terms (9)
_tmp0 = math.sqrt(epsilon**2 + vec[0, 0] ** 2 + vec[1, 0] ** 2 + vec[2, 0] ** 2)
_tmp1 = (1.0 / 2.0) * _tmp0
_tmp2 = math.sin(_tmp1) / _tmp0
_tmp3 = _tmp2 * vec[2, 0]
_tmp4 = _a[2] * _tmp2
_tmp5 = _a[3] * _tmp2
_tmp6 = math.cos(_tmp1)
_tmp7 = _a[0] * _tmp2
_tmp8 = _a[1] * _tmp2
# Output terms
_res = [0.0] * 4
_res[0] = _a[0] * _tmp6 + _a[1] * _tmp3 - _tmp4 * vec[1, 0] + _tmp5 * vec[0, 0]
_res[1] = -_a[0] * _tmp3 + _a[1] * _tmp6 + _tmp4 * vec[0, 0] + _tmp5 * vec[1, 0]
_res[2] = _a[2] * _tmp6 + _tmp5 * vec[2, 0] + _tmp7 * vec[1, 0] - _tmp8 * vec[0, 0]
_res[3] = -_a[2] * _tmp3 + _a[3] * _tmp6 - _tmp7 * vec[0, 0] - _tmp8 * vec[1, 0]
return sym.Rot3.from_storage(_res)
[docs] @staticmethod
def local_coordinates(a, b, epsilon):
# type: (sym.Rot3, sym.Rot3, float) -> numpy.ndarray
# Total ops: 45
# Input arrays
_a = a.data
_b = b.data
# Intermediate terms (3)
_tmp0 = _a[0] * _b[0] + _a[1] * _b[1] + _a[2] * _b[2] + _a[3] * _b[3]
_tmp1 = min(abs(_tmp0), 1 - epsilon)
_tmp2 = (
2
* (2 * min(0, (0.0 if _tmp0 == 0 else math.copysign(1, _tmp0))) + 1)
* math.acos(_tmp1)
/ math.sqrt(1 - _tmp1**2)
)
# Output terms
_res = numpy.zeros(3)
_res[0] = _tmp2 * (-_a[0] * _b[3] - _a[1] * _b[2] + _a[2] * _b[1] + _a[3] * _b[0])
_res[1] = _tmp2 * (_a[0] * _b[2] - _a[1] * _b[3] - _a[2] * _b[0] + _a[3] * _b[1])
_res[2] = _tmp2 * (-_a[0] * _b[1] + _a[1] * _b[0] - _a[2] * _b[3] + _a[3] * _b[2])
return _res
[docs] @staticmethod
def interpolate(a, b, alpha, epsilon):
# type: (sym.Rot3, sym.Rot3, float, float) -> sym.Rot3
# Total ops: 99
# Input arrays
_a = a.data
_b = b.data
# Intermediate terms (18)
_tmp0 = -_a[0] * _b[3] - _a[1] * _b[2] + _a[2] * _b[1] + _a[3] * _b[0]
_tmp1 = _a[0] * _b[0] + _a[1] * _b[1] + _a[2] * _b[2] + _a[3] * _b[3]
_tmp2 = min(abs(_tmp1), 1 - epsilon)
_tmp3 = 1 - _tmp2**2
_tmp4 = 2 * min(0, (0.0 if _tmp1 == 0 else math.copysign(1, _tmp1))) + 1
_tmp5 = -_a[0] * _b[1] + _a[1] * _b[0] - _a[2] * _b[3] + _a[3] * _b[2]
_tmp6 = math.acos(_tmp2)
_tmp7 = 4 * _tmp4**2 * _tmp6**2 * alpha**2 / _tmp3
_tmp8 = _a[0] * _b[2] - _a[1] * _b[3] - _a[2] * _b[0] + _a[3] * _b[1]
_tmp9 = math.sqrt(_tmp0**2 * _tmp7 + _tmp5**2 * _tmp7 + _tmp7 * _tmp8**2 + epsilon**2)
_tmp10 = (1.0 / 2.0) * _tmp9
_tmp11 = 2 * _tmp4 * _tmp6 * alpha * math.sin(_tmp10) / (math.sqrt(_tmp3) * _tmp9)
_tmp12 = _a[3] * _tmp11
_tmp13 = _a[1] * _tmp11
_tmp14 = math.cos(_tmp10)
_tmp15 = _tmp11 * _tmp8
_tmp16 = _tmp0 * _tmp11
_tmp17 = _tmp11 * _tmp5
# Output terms
_res = [0.0] * 4
_res[0] = _a[0] * _tmp14 - _a[2] * _tmp15 + _tmp0 * _tmp12 + _tmp13 * _tmp5
_res[1] = -_a[0] * _tmp17 + _a[1] * _tmp14 + _a[2] * _tmp16 + _tmp12 * _tmp8
_res[2] = _a[0] * _tmp15 + _a[2] * _tmp14 - _tmp0 * _tmp13 + _tmp12 * _tmp5
_res[3] = -_a[0] * _tmp16 - _a[2] * _tmp17 + _a[3] * _tmp14 - _tmp13 * _tmp8
return sym.Rot3.from_storage(_res)