简体   繁体   中英

How to rotate an rotation by an euler rotation in python?

What i want

  • Input: non-normalized axis rotation
  • Output: quaternion rotation, but additionally rotated by -90 degree y-axis (euler)

What i have

#!/usr/bin/env python3

#from math import radians, degrees, cos, sin, atan2, asin, pow, floor
#import numpy as np
from scipy.spatial.transform import Rotation

#r = Rotation.from_rotvec(rotation_by_axis).as_quat()
r = Rotation.from_quat([-0.0941422, 0.67905384, -0.2797612, 0.67212856]) # example
print("Input (as Euler): " + str(r.as_euler('xyz', degrees=True)))
print("Output (as Euler): " + str(r.apply([0, -90, 0])))

The result:

Input (as Euler): [-83.23902624  59.33323676 -98.88314731]
Output (as Euler): [-22.33941658 -74.31676511  45.58474405]

How to get the output [-83.23902624 -30.66676324 -98.88314731] instead?

Bad workaround

This works only sometimes (why?).

rotation = r.from_quat([rotation.x, rotation.y, rotation.z, rotation.w])
rotation = rotation.as_euler('xyz', degrees=True)
print(rotation)
rotation = r.from_euler('xyz', [rotation[0], rotation[1]-90, rotation[2]], degrees=True)
print(rotation.as_euler('xyz', degrees=True))
rotation = rotation.as_quat()

How to do it a better way?

Because sometimes i get wrong values:

[  -8.25897711  -16.54712028    -1.90525288]
[ 171.74102289  -73.45287972   178.09474712]

[  -7.18492129   22.22525264     0.44373851]
[  -7.18492129  -67.77474736     0.44373851]

[   7.52491766  -37.71896037   -40.86915413]
[-172.47508234  -52.28103963   139.13084587]

[  -1.79610826   37.83068221    31.20184248]
[  -1.79610826  -52.16931779    31.20184248]

[-113.5719734   -54.28744892   141.73007557]
[  66.4280266   -35.71255108   -38.26992443]

[ -83.23903078   59.33323752   -98.88315157]
[ -83.23903078  -30.66676248   -98.88315157]

[  -9.67960912   -7.23784945    13.56800885]
[ 170.32039088  -82.76215055  -166.43199115]

[  -6.21695895    5.66996884   -11.16152822]
[  -6.21695895  -84.33003116   -11.16152822]

[   0.            0.             0.        ]
[   0.          -90.             0.        ]

[   0.            0.             0.        ]
[   0.          -90.             0.        ]

Here wrong:

[  -8.25897711  -16.54712028    -1.90525288]
[ 171.74102289  -73.45287972   178.09474712]

Here okay:

[  -7.18492129   22.22525264     0.44373851]
[  -7.18492129  -67.77474736     0.44373851]

I require it for this: https://github.com/Arthur151/ROMP/issues/193#issuecomment-1156960708

apply is for applying a rotation to vectors; it won't work on, eg, Euler rotation angles, which aren't "mathematical" vectors: it doesn't make sense to add or scale them as triples of numbers.

To combine rotations, use * . So, eg, to rotate by an additional 20 degrees about a y-axis defined by the first rotation:

In [1]: import numpy as np

In [2]: np.set_printoptions(suppress=True) # don't show round-off

In [3]: from scipy.spatial.transform import Rotation

In [4]: def e(x,y,z): return Rotation.from_euler('xyz', [x,y,z], degrees=True)

In [5]: def s(r): return r.as_euler('xyz', degrees=True)

In [6]: display(s(e(0,20,0) * e(10,0,0)))
Out[6]: array([10., 20.,  0.])

However, in general this rotation won't just add to the y-component total rotation. This is because the additional rotation's axes are defined by the first rotation, but the total rotation includes everything combined:

In [7]: s(e(0,20,0) * e(0,0,10))
Out[7]: array([ 3.61644157, 19.68349808, 10.62758414])

Combining rotations as shown above is quite standard; eg, in a multi-jointed robot, to find the orientation of the final element, you'd use the "combining" technique shown above, with one rotation per joint, defined by the appropriate axes (eg, z for a "hip" yawing rotation, x for a "wrist" rolling rotation)

If you do need to manipulate Euler angles, your "bad workaround" is fine. Bear in mind that the middle rotation in Euler representations is normally limited to be under 90 degrees absolute value:

In [8]: s(e(0,135,0))
Out[8]: array([180.,  45., 180.])

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM