bugfix and further test
This commit is contained in:
parent
3dc90ddb94
commit
b200894a40
|
@ -534,13 +534,13 @@ class Rotation:
|
||||||
def qu2om(qu):
|
def qu2om(qu):
|
||||||
qq = qu[...,0:1]**2-(qu[...,1:2]**2 + qu[...,2:3]**2 + qu[...,3:4]**2)
|
qq = qu[...,0:1]**2-(qu[...,1:2]**2 + qu[...,2:3]**2 + qu[...,3:4]**2)
|
||||||
om = np.block([qq + 2.0*qu[...,1:2]**2,
|
om = np.block([qq + 2.0*qu[...,1:2]**2,
|
||||||
2.0*(qu[...,2:3]*qu[...,1:2]+_P*qu[...,0:1]*qu[...,3:4]),
|
2.0*(qu[...,2:3]*qu[...,1:2]-_P*qu[...,0:1]*qu[...,3:4]),
|
||||||
2.0*(qu[...,3:4]*qu[...,1:2]-_P*qu[...,0:1]*qu[...,2:3]),
|
2.0*(qu[...,3:4]*qu[...,1:2]+_P*qu[...,0:1]*qu[...,2:3]),
|
||||||
2.0*(qu[...,1:2]*qu[...,2:3]-_P*qu[...,0:1]*qu[...,3:4]),
|
2.0*(qu[...,1:2]*qu[...,2:3]+_P*qu[...,0:1]*qu[...,3:4]),
|
||||||
qq + 2.0*qu[...,2:3]**2,
|
qq + 2.0*qu[...,2:3]**2,
|
||||||
2.0*(qu[...,3:4]*qu[...,2:3]+_P*qu[...,0:1]*qu[...,1:2]),
|
2.0*(qu[...,3:4]*qu[...,2:3]-_P*qu[...,0:1]*qu[...,1:2]),
|
||||||
2.0*(qu[...,1:2]*qu[...,3:4]+_P*qu[...,0:1]*qu[...,2:3]),
|
2.0*(qu[...,1:2]*qu[...,3:4]-_P*qu[...,0:1]*qu[...,2:3]),
|
||||||
2.0*(qu[...,2:3]*qu[...,3:4]-_P*qu[...,0:1]*qu[...,1:2]),
|
2.0*(qu[...,2:3]*qu[...,3:4]+_P*qu[...,0:1]*qu[...,1:2]),
|
||||||
qq + 2.0*qu[...,3:4]**2,
|
qq + 2.0*qu[...,3:4]**2,
|
||||||
]).reshape(qu.shape[:-1]+(3,3))
|
]).reshape(qu.shape[:-1]+(3,3))
|
||||||
return om
|
return om
|
||||||
|
@ -626,9 +626,31 @@ class Rotation:
|
||||||
"""
|
"""
|
||||||
Rotation matrix to quaternion.
|
Rotation matrix to quaternion.
|
||||||
|
|
||||||
The original formulation (direct conversion) had (numerical?) issues
|
This formulation is from www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion.
|
||||||
|
The original formulation had issues.
|
||||||
"""
|
"""
|
||||||
return Rotation.eu2qu(Rotation.om2eu(om))
|
def x(a):
|
||||||
|
trace = a[0,0] + a[1,1] + a[2,2]
|
||||||
|
if trace > 0:
|
||||||
|
s = 0.5 / np.sqrt(trace+ 1.0)
|
||||||
|
qu = np.array([0.25 / s,( a[2,1] - a[1,2] ) * s,( a[0,2] - a[2,0] ) * s,( a[1,0] - a[0,1] ) * s])
|
||||||
|
else:
|
||||||
|
if ( a[0,0] > a[1,1] and a[0,0] > a[2,2] ):
|
||||||
|
s = 2.0 * np.sqrt( 1.0 + a[0,0] - a[1,1] - a[2,2])
|
||||||
|
qu = np.array([ (a[2,1] - a[1,2]) / s,0.25 * s,(a[0,1] + a[1,0]) / s,(a[0,2] + a[2,0]) / s])
|
||||||
|
elif (a[1,1] > a[2,2]):
|
||||||
|
s = 2.0 * np.sqrt( 1.0 + a[1,1] - a[0,0] - a[2,2])
|
||||||
|
qu = np.array([ (a[0,2] - a[2,0]) / s,(a[0,1] + a[1,0]) / s,0.25 * s,(a[1,2] + a[2,1]) / s])
|
||||||
|
else:
|
||||||
|
s = 2.0 * np.sqrt( 1.0 + a[2,2] - a[0,0] - a[1,1] )
|
||||||
|
qu = np.array([ (a[1,0] - a[0,1]) / s,(a[0,2] + a[2,0]) / s,(a[1,2] + a[2,1]) / s,0.25 * s])
|
||||||
|
return qu
|
||||||
|
if len(om.shape) > 2:
|
||||||
|
om_ = om.reshape(-1,3,3)
|
||||||
|
qu = np.array([x(o) for o in om_]).reshape(om.shape[:-2]+(4,))
|
||||||
|
else:
|
||||||
|
qu = x(om)
|
||||||
|
return qu*np.array([1,_P,_P,_P])
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def om2eu(om):
|
def om2eu(om):
|
||||||
|
@ -649,7 +671,6 @@ class Rotation:
|
||||||
eu = np.where(eu<0, (eu+2.0*np.pi)%np.array([2.0*np.pi,np.pi,2.0*np.pi]),eu)
|
eu = np.where(eu<0, (eu+2.0*np.pi)%np.array([2.0*np.pi,np.pi,2.0*np.pi]),eu)
|
||||||
return eu
|
return eu
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def om2ax(om):
|
def om2ax(om):
|
||||||
"""Rotation matrix to axis angle pair."""
|
"""Rotation matrix to axis angle pair."""
|
||||||
|
@ -672,7 +693,6 @@ class Rotation:
|
||||||
ax[np.abs(ax[...,3])<1.e-6] = [ 0.0, 0.0, 1.0, 0.0]
|
ax[np.abs(ax[...,3])<1.e-6] = [ 0.0, 0.0, 1.0, 0.0]
|
||||||
return ax
|
return ax
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def om2ro(om):
|
def om2ro(om):
|
||||||
"""Rotation matrix to Rodrigues-Frank vector."""
|
"""Rotation matrix to Rodrigues-Frank vector."""
|
||||||
|
@ -703,7 +723,6 @@ class Rotation:
|
||||||
qu[qu[...,0]<0.0]*=-1
|
qu[qu[...,0]<0.0]*=-1
|
||||||
return qu
|
return qu
|
||||||
|
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def eu2om(eu):
|
def eu2om(eu):
|
||||||
"""Bunge-Euler angles to rotation matrix."""
|
"""Bunge-Euler angles to rotation matrix."""
|
||||||
|
|
|
@ -112,6 +112,23 @@ def qu2ho(qu):
|
||||||
|
|
||||||
|
|
||||||
#---------- Rotation matrix ----------
|
#---------- Rotation matrix ----------
|
||||||
|
def om2qu(a):
|
||||||
|
trace = a[0,0] + a[1,1] + a[2,2]
|
||||||
|
if trace > 0:
|
||||||
|
s = 0.5 / np.sqrt(trace+ 1.0)
|
||||||
|
qu = np.array([0.25 / s,( a[2,1] - a[1,2] ) * s,( a[0,2] - a[2,0] ) * s,( a[1,0] - a[0,1] ) * s])
|
||||||
|
else:
|
||||||
|
if ( a[0,0] > a[1,1] and a[0,0] > a[2,2] ):
|
||||||
|
s = 2.0 * np.sqrt( 1.0 + a[0,0] - a[1,1] - a[2,2])
|
||||||
|
qu = np.array([ (a[2,1] - a[1,2]) / s,0.25 * s,(a[0,1] + a[1,0]) / s,(a[0,2] + a[2,0]) / s])
|
||||||
|
elif (a[1,1] > a[2,2]):
|
||||||
|
s = 2.0 * np.sqrt( 1.0 + a[1,1] - a[0,0] - a[2,2])
|
||||||
|
qu = np.array([ (a[0,2] - a[2,0]) / s,(a[0,1] + a[1,0]) / s,0.25 * s,(a[1,2] + a[2,1]) / s])
|
||||||
|
else:
|
||||||
|
s = 2.0 * np.sqrt( 1.0 + a[2,2] - a[0,0] - a[1,1] )
|
||||||
|
qu = np.array([ (a[1,0] - a[0,1]) / s,(a[0,2] + a[2,0]) / s,(a[1,2] + a[2,1]) / s,0.25 * s])
|
||||||
|
return qu
|
||||||
|
|
||||||
def om2eu(om):
|
def om2eu(om):
|
||||||
"""Rotation matrix to Bunge-Euler angles."""
|
"""Rotation matrix to Bunge-Euler angles."""
|
||||||
if not np.isclose(np.abs(om[2,2]),1.0,1.e-4):
|
if not np.isclose(np.abs(om[2,2]),1.0,1.e-4):
|
||||||
|
|
|
@ -196,7 +196,8 @@ class TestRotation:
|
||||||
assert np.allclose(single(q),c) and np.allclose(single(q),vectorized(q))
|
assert np.allclose(single(q),c) and np.allclose(single(q),vectorized(q))
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.parametrize('vectorized, single',[(Rotation.om2eu,rotation_conversion.om2eu),
|
@pytest.mark.parametrize('vectorized, single',[(Rotation.om2qu,rotation_conversion.om2qu),
|
||||||
|
(Rotation.om2eu,rotation_conversion.om2eu),
|
||||||
(Rotation.om2ax,rotation_conversion.om2ax)])
|
(Rotation.om2ax,rotation_conversion.om2ax)])
|
||||||
def test_matrix_vectorization(self,default,vectorized,single):
|
def test_matrix_vectorization(self,default,vectorized,single):
|
||||||
om = np.array([rot.as_matrix() for rot in default])
|
om = np.array([rot.as_matrix() for rot in default])
|
||||||
|
|
Loading…
Reference in New Issue