add option to normalize quaternions
This commit is contained in:
parent
c8e5e9e34a
commit
23d2337fb2
|
@ -751,6 +751,7 @@ class Rotation:
|
|||
@staticmethod
|
||||
def from_quaternion(q: Union[Sequence[FloatSequence], np.ndarray],
|
||||
accept_homomorph: bool = False,
|
||||
normalize: bool = False,
|
||||
P: Literal[1, -1] = -1) -> 'Rotation':
|
||||
"""
|
||||
Initialize from quaternion.
|
||||
|
@ -762,6 +763,8 @@ class Rotation:
|
|||
accept_homomorph : bool, optional
|
||||
Allow homomorphic variants, i.e. q_0 < 0 (negative real hemisphere).
|
||||
Defaults to False.
|
||||
normalize: bool, optional
|
||||
Allow ǀqǀ ≠ 1. Defaults to False.
|
||||
P : int ∈ {-1,1}, optional
|
||||
Sign convention. Defaults to -1.
|
||||
|
||||
|
@ -773,12 +776,14 @@ class Rotation:
|
|||
raise ValueError('P ∉ {-1,1}')
|
||||
|
||||
qu[...,1:4] *= -P
|
||||
|
||||
if accept_homomorph:
|
||||
qu[qu[...,0] < 0.0] *= -1
|
||||
else:
|
||||
if np.any(qu[...,0] < 0.0):
|
||||
raise ValueError('quaternion with negative first (real) component')
|
||||
if not np.all(np.isclose(np.linalg.norm(qu,axis=-1), 1.0,rtol=0.0)):
|
||||
elif np.any(qu[...,0] < 0.0):
|
||||
raise ValueError('quaternion with negative first (real) component')
|
||||
if normalize:
|
||||
qu /= np.linalg.norm(qu,axis=-1,keepdims=True)
|
||||
elif not np.all(np.isclose(np.linalg.norm(qu,axis=-1), 1.0,rtol=1e-8)):
|
||||
raise ValueError('quaternion is not of unit length')
|
||||
|
||||
return Rotation(qu)
|
||||
|
|
|
@ -760,11 +760,12 @@ class TestRotation:
|
|||
|
||||
@pytest.mark.parametrize('P',[1,-1])
|
||||
@pytest.mark.parametrize('accept_homomorph',[True,False])
|
||||
def test_quaternion(self,set_of_rotations,P,accept_homomorph):
|
||||
c = np.array([1,P*-1,P*-1,P*-1]) * (-1 if accept_homomorph else 1)
|
||||
@pytest.mark.parametrize('normalize',[True,False])
|
||||
def test_quaternion(self,set_of_rotations,P,accept_homomorph,normalize):
|
||||
c = np.array([1,P*-1,P*-1,P*-1]) * (-1 if accept_homomorph else 1) * (0.9 if normalize else 1.0)
|
||||
for rot in set_of_rotations:
|
||||
m = rot.as_cubochoric()
|
||||
o = Rotation.from_quaternion(rot.as_quaternion()*c,accept_homomorph,P).as_cubochoric()
|
||||
o = Rotation.from_quaternion(rot.as_quaternion()*c,accept_homomorph,normalize,P).as_cubochoric()
|
||||
ok = np.allclose(m,o,atol=atol)
|
||||
if np.count_nonzero(np.isclose(np.abs(o),np.pi**(2./3.)*.5)):
|
||||
ok |= np.allclose(m*-1.,o,atol=atol)
|
||||
|
|
Loading…
Reference in New Issue