95 lines
3.3 KiB
Python
95 lines
3.3 KiB
Python
from .Direction import *
|
|
from .Quaternion import *
|
|
|
|
class SwingTwist:
|
|
"""A rotation using swing and twist angle components"""
|
|
def __init__(self, swing: Direction, twist: Angle):
|
|
## Swing component of the rotation
|
|
self.swing = swing
|
|
## The twist component of the rotation
|
|
self.twist = twist
|
|
|
|
@staticmethod
|
|
def Degrees(horizontal: float, vertical: float, twist: float):
|
|
horizontal_angle = Angle.Degrees(horizontal)
|
|
vertical_angle = Angle.Degrees(vertical)
|
|
twist_angle = Angle.Degrees(twist)
|
|
|
|
deg90 = Angle.Degrees(90)
|
|
deg180 = Angle.Degrees(180)
|
|
if vertical_angle > deg90 or vertical_angle < -deg90:
|
|
horizontal_angle += deg180
|
|
vertical_angle = deg180 - vertical_angle
|
|
twist_angle += deg180
|
|
|
|
direction = Direction(horizontal_angle, vertical_angle)
|
|
swing_twist = SwingTwist(direction, twist_angle)
|
|
return swing_twist
|
|
@staticmethod
|
|
def Radians(horizontal: float, vertical: float, twist: float):
|
|
horizontal_angle = Angle.Radians(horizontal)
|
|
vertical_angle = Angle.Radians(vertical)
|
|
twist_angle = Angle.Radians(twist)
|
|
|
|
deg90 = Angle.Radians(math.pi / 2)
|
|
deg180 = Angle.Radians(math.pi)
|
|
if vertical_angle > deg90 or vertical_angle < -deg90:
|
|
horizontal_angle += deg180
|
|
vertical_angle = deg180 - vertical_angle
|
|
twist_angle += deg180
|
|
|
|
direction = Direction(horizontal_angle, vertical_angle)
|
|
swing_twist = SwingTwist(direction, twist_angle)
|
|
return swing_twist
|
|
|
|
def ToQuaternion(self) -> Quaternion:
|
|
"""Convert the SwingTwist rotation to a Quaternion"""
|
|
q = Quaternion.FromAngles(
|
|
-self.swing.vertical,
|
|
self.swing.horizontal,
|
|
self.twist
|
|
)
|
|
return q
|
|
@staticmethod
|
|
def FromQuaternion(q: Quaternion):
|
|
angles = Quaternion.ToAngles(q)
|
|
# direction = Direction(angles[0], angles[1])
|
|
# r: SwingTwist = SwingTwist(direction, angles[2])
|
|
r = SwingTwist.Degrees(
|
|
angles[0].InDegrees(),
|
|
angles[1].InDegrees(),
|
|
angles[2].InDegrees()
|
|
)
|
|
return r
|
|
|
|
def FromAngleAxis(angle: Angle, axis: Direction):
|
|
vectorAxis: Vector3 = axis.ToVector3();
|
|
q: Quaternion = Quaternion.FromAngleAxis(angle, vectorAxis);
|
|
return SwingTwist.FromQuaternion(q)
|
|
|
|
|
|
def __eq__(self, other) -> bool:
|
|
"""! Check if this orientation is equal to the given orientation
|
|
@param other The orientation to check against
|
|
@return true if it is identical to the given orientation
|
|
@note This uses float comparison to check equality which may have strange
|
|
effects. Equality on floats should be avoided.
|
|
"""
|
|
return (
|
|
self.swing == other.swing and
|
|
self.twist == other.twist
|
|
)
|
|
def isclose(self, other, rel_tol=1e-9, abs_tol=1e-8):
|
|
return (
|
|
self.swing.isclose(other.swing, rel_tol, abs_tol) and
|
|
Angle.isclose(self.twist, other.twist, rel_tol=rel_tol, abs_tol=abs_tol)
|
|
)
|
|
|
|
|
|
@staticmethod
|
|
def Angle(r1, r2) -> Angle:
|
|
q1: Quaternion = r1.ToQuaternion()
|
|
q2: Quaternion = r2.ToQuaternion()
|
|
angle: float = Quaternion.Angle(q1, q2)
|
|
return angle
|
|
|