#!/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?
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, e.g., 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, e.g., 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; e.g., 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 (e.g., 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.])