I am looking for a way of returning an euler angle that has been rotated by a quaternion.
I understand that extracting pitch roll and yaw from a quaternion is problematic at best, but if I could then I would simply add its values to my own in order to get the resulting euler angle.
I could also convert my euler angle to a quaternion and then combine the two but then I would be left with a quaternion that I cant convert into an euler.
I admit I struggle with quaternions at the best of times so any help will be well received.
For clarity I only need to return an euler angle, all other calculations can be done with quaternions if required.
I am using Bullet Physics, Direct X, C++
Thanks.
You can't combine Euler angles with Euler angles or Euler angles with quaternion directly.
You should convert the rotation into representation allowing transformation composition. It is rotation matrix or quaternion.
After combine of rotations convert back into Euler angles.
P.S. Euler angles is not useful representation of rotation at all. It only can be used for manual input of rotations.
It's possible to convert back and forth but you need to respect the order you are applying your different Euler angle or you will get some nasty result.
I didn'try it my self and as said minorlogic is better to stick to rotation matrix/quaternions.
here is a nice link
https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles
where q0,q1,q2,q3 stands for w,x,y,z
On this site they suppose that
where the airplane first does yaw turn during taxiing onto the runway, then pitches during take-off, and finally rolls in the air.
Related
According to OpenCV's documentation, solvePnp will return the rotation vector of the object pose from 3D-2D point correspondes. To obtain the rotation matrix, we can use Rodrigues method to convert the rotation vector to rotation matrix. According to OpenCV documentation, we can find theta using the following:
theta = norm(r)
But I thought norm(r) will find the magnitude of the vector r? If that's the case how can we find the angle from the magnitude of the vector r? Correct me if I am wrong. Thank you.
Given a rotation vector r, its length (in Python, numpy.linalg.norm(r)) is the angle of rotation around the axis whose direction is the vector's one. The sense of the rotation obeys the "right hand rule": if your right hand makes a thumbs-up sign, with the thumb pointing as the vector, the other fingers wrap the vectors as the rotation (equivalently, it's the sense of rotation that makes an ordinary screw advance when its tip points as the vector).
The same rotation can be expressed as a 3x3 matrix, or as a triple of (Euler) angles or rotation about up to 3 orthogonal axes. There are ordinarily many different triples of Euler angles that represent the same rotation. Consult a textbook, or Wikipedia, for details.
This is a small background and introduction to the problem:
I have some functionality in my motion- and location-based iOS app, which needs a rotation matrix as an input. Some graphical output is dependent on this matrix. With every movement of the device, graphical output is changed. This is a part of the code which makes that:
[motionManager startDeviceMotionUpdatesUsingReferenceFrame:CMAttitudeReferenceFrameXTrueNorthZVertical
toQueue:motionQueue
withHandler:
^(CMDeviceMotion* motion, NSError* error){
//get and process matrix data
}
In this structure only 4 frames are available:
XArbitraryZVertical
XArbitraryCorrectedZVertical
XMagneticNorthZVertical
XTrueNorthZVertical
I need to have another reference, f.e. gyroscope value instead of North and these frames can not offer me exactly what I want.
In order to reach my goal, I use next structure:
[motionManager startDeviceMotionUpdatesUsingReferenceFrame:CMAttitudeReferenceFrameXArbitraryCorrectedZVertical
toQueue:motionQueue
withHandler:
^(CMDeviceMotion* motion, NSError* error){
//get Euler angles and transform it to rotation matrix
}
You may ask me, why I do not use built in rotation matrix? The answer is simple. I need to make some kind of own reference frame and I can make this via putting inside modified values of angles.
The problem:
In order to get rotation matrix from Euler angles we need to make matrix for each angle and after that multiply them. For 3D case we will have matrix for each axis (3 of them). After that we multiply matrixes. The problem is that the output is dependent on the order of multiplication. XYZ is not equal to ZYX. Wikipedia tells me, that there are 12 variants and I do not know which one is the right one for iOS implementation. I need to know in which order I need to multiply them. In addition, I need to know which angles represents X, Y, Z. For example, X - roll, Y - pitch, Z - yaw.
Actually, this problem was solved by Apple years ago, but I do not have access to .m-files and I do not know which order of multiplication is the right one for iOS device.
Similar question was published here, but order from that math example in the solution does not work for me.
Regarding: Which angles relate to which axis.
See this:
link:https://developer.apple.com/documentation/coremotion/getting_processed_device-motion_data/understanding_reference_frames_and_device_attitude
Regarding rotation order for calculating rotation matrix & Euler angles (Pitch, Roll, Yaw)
Short Answer: ZXY is the rotation order on iOS.
I kept searching for this answer too. Got tired. Not sure why this is not documented somewhere easy to lookup. I decided to collect empirical data and test out which rotation order best matches the values. My values are below.
Methodology:
Wrote a small iPhone App to return quaternion values & corresponding pitch, roll, yaw angles
Computed pitch, roll, yaw values from the quaternions for various rotation orders (XYZ, XZY, YZX, YXZ, ZYX, ZXY)
Calculated RMS error with respect to the pitch, yaw, roll values reported by iOS device motion. Identified the orientation with the least error.
Results:
Rotation orders: ZYX & ZXY both returned values very close to the iOS reported values. However, the Error on ZXY was ~46-597X lower than ZXY for every case. Hence I believe ZXY is the rotation order.
I've been playing around with both Matlab & Apples documentation in regards to CMRotationMatrix for weeks.
I've found that I could easily re-create CMRotationMatrix by calculating it with Roll, Yaw & Pitch.
However, I've found no resources/documentation on how to create a Rotation Matrix from XYZ rotations from either gravity or userAcceleration.
All I found was how they create a 4x4 matrix in their VideoSnake demo.
So my question is, does anyone have any input of how to create a 3x3 matrix from XYZ rotations?
To begin with rotation matrix has vast applications in Physics, Geometry and Computer Graphics according to Wikipedia. Now looking at it from this angle in relation to your question where you made mention of gravity and userAcceleration we are seeing a synergy between principles in relation to physics where we can make mention of spacecraft exploration which depends 100 percent on gravity.
Now getting to the meat of the matter on XYZ rotations in relation to Rotation Matrix there is an abstract figure which is denoted on the origin point of the XYZ axes without any specifics to a particular angle as a starting point.
Now this is the part you have to understand, since we are using abstract and arbitrary figures we need to convert this XYZ axis point into direction vectors which can then be understood in real life world coordinates.
Only then we will be able to synergistically relate Rotation Matrix and XYZ coordinate points
Now to conclude
The essence of using this direction vector is to convert the direction into equivalent direction in cognisance with the rotation matrix which can then be effectively utilised and expressed on the platform-local coordinates
I am have been using solvepnp() for the calculation of the rotation and translation matrix. But the euler angles calculated from the obtained rotation matrix gave very erratic values. Trying to find the problem, I had a set of 2D projection points for my marker and kept the other parameters of solvepnp() constant.
Eg values:
2D points
[219.67473, 242.78395; 363.4151, 238.61298; 503.04855, 234.56117; 501.70917, 628.16742; 500.58069, 959.78564; 383.1756, 972.02679; 262.8746, 984.56982; 243.17044, 646.22925]
The euler angle theta(x) calculated from the output rotation matrix of solvepnp() was -26.4877
Next, I incremented only the x value of the first point(i.e 219.67473) by 0.1 to check the variation of the theta(x) euler angle (keeping the remaining points and the other parameters constant) and ran the solvepnp() again .For that very small change,I had values which were decreasing from -19 degree, -18 degree (for x coord = 223.074) then suddenly jump to 27 degree for a while (for x coord = 223.174 to 226.974) then come down to 1.3 degree (for x coord = 227.074).
I cannot understand this behaviour at all.Could somebody please explain?
My euler angle calculation from the rotation matrix uses this procedure.
Try Rodrigues() for conversion between rotation matrix and rotation vector to make sure everything is clean and right. Non RANSAC version can be very sensitive to outliers that create a huge error in the parameters and thus bias a solution. Using RANSAC version of solvePnP may make it more stable to outliers. For example, adding too much to one of the points coordinates will eventually make it an outlier and it won’t influence a solution after that.
If everything fails, write a series unit tests: create an artificial set of points in 3D (possibly non planar), apply a simple translation first, in second variant apply rotation only, and in a third test apply both. Project using your camera matrix and then plug in your 2D, 3D points and projection matrix into your code to find the pose. If the result deviates from the inverse of the translations and rotations your applied to the points look for the bug in feeding parameters to PnP.
It seems the coordinate systems are different.OpenCV uses right-hand coordinate-system Y-pointing downwards. At nghiaho.com it says the calculations are based on this and if you look at the axis they don't seem to match. I guess you are using Rodrigues for matrix computation? Try comparing rotation vectors as well.
I’m working on an iOS augmented reality application.
It is location-based, not marker-based.
I use the GPS, compass and accelerometers to get latitude, longitude, altitude and the 3 euler angles: yaw, pitch and roll. I know using NSLog() that those 6 variables contain valid data.
My application shows some 3d objects over the camera view.
It works fine as long as I use everything but the roll angle.
If I add that third angle, the rotation applied to my opengl world is not good. I do it that way in the main OpenGL draw method
glRotatef(pitch, 1, 0, 0);
glRotatef(yaw, 0, 1, 0);
//glRotatef(roll, 0, 0, 1);
I think there is something wrong with this approach but am certainly not a specialist. Maybe I should create some sort of unique rotation matrix rather than 3 different ones?
Maybe that’s not possible easily? After all most desktop video games, FPS and the like, just let the user change the yaw and the pitch using the mouse, so only 2 angles, not 3. But unlike the mouse, which is a 2d device, a phone used for augmented reality can move in any angles.
But then again, all AR tutorials I have seen online couldn’t handle ‘roll’ properly. ‘Rolling’ your phone would either completely mess AR stuff up or do nothing at all, using some roll-compensation strategies.
So my question is, assuming I have my 3 Euler angles using the phone sensors, how should I apply them to my 3d opengl view?
I think you're likely talking about gimbal lock.
The essence of the problem is that if you rotate with Eulers then there's always a sequence to it. For example, you rotate around x, then around y, then z. But then one axis can always becomes ambiguous because a preceding can move it onto a different axis.
Suppose the rotation were 0 degrees around x, 90 degrees around y, then 20 degrees around z. So you do the x rotation and nothing has changed. You do the y rotation and everything moves 90 degrees. But now you've moved the z axis onto where the x axis was previously. So the z rotation will appear to be around x.
No matter what most people's instincts tell them, there's no way to avoid the problem. The kneejerk reaction is that you'll always rotate around the global axes rather than the local one. That doesn't resolve the problem, it just reverses the order. The z rotation could then the y rotation — which has already occurred — into an x rotation.
You're right that you should aim to create a unique description of rotation separated from measuring angles.
For augmented reality it's actually not all that difficult.
The accelerometer tells you which way down is. The compass tells you which way north is. The two may not be orthogonal though — the compass reading should vary from being exactly at a right angle to the floor on the equator to being exactly parallel to the accelerometer at the poles.
So:
just accept the accelerometer vector as down;
get the cross product of down and the compass vector to get your side vector — it should point along a line of longitude;
then get the cross product of your side vector and your down vector to get a north vector that is suitably perpendicular.
You could equally use the dot product to remove that portion of the compass vector that is in the direction of gravity and cross product from there.
You'll want to normalise everything.
That gives you three basis vectors, so just put them directly into a matrix. No further work required.