I know this question is definitely solved somewhere many times already, please enlighten me if you know of their existence, thanks.
Quick rundown: I want to compute
As I understand your question, you know the pitch and yaw of your device (from the magnetometer) and want to use this information to calculate the component of gravity along each of your (device) coordinate axes?
As a physicist I'm brought up with Euler angles instead of pitch-yaw-roll, but looking at http://en.wikipedia.org/wiki/Yaw,_pitch,_and_roll I would calculate this as follows:
Assume that your device is initially oriented along the global coordinate frame, so that gravity is gvec:={0,0,-g}
(in the local frame). Now we have to calculate the local coordinates of gvec as we go through the yaw-pitch-roll (yaw doesn't do anything as you mention).
To me this is easiest with rotation matrices: we have to change the sign of the angles since gvec
stays put. I'll do this with Mathematica because that's my hammer and this is a nail
yaw = RotationMatrix[-yawangle,{0,0,1}];
pitch = RotationMatrix[-pitchangle, {0,1,0}];
roll = RotationMatrix[-rollangle,{1,0,0}];
gvec={0,0,-g}
yaw.gvec
pitch.yaw.gvec
roll.pitch.yaw.gvec
The output is the local coordinates for gvec
before yaw, and after yaw, pitch, and roll (so last line below should be your answer):
{0,0,-g}
{0,0,-g}
{g Sin[pitchangle],0,-g Cos[pitchangle]}
{g Sin[pitchangle],-g Cos[pitchangle] Sin[rollangle],-g Cos[pitchangle] Cos[rollangle]}
I realize the posting is old but in case others are using it: In your last response you are indicating that you still see some deviation especially under larger angles. I experienced the same but it disappeared when I added a calibration routine to capture the accelerometer's reading on a flat surface and made all subsequent readings relative to the flat surface reading.
It is not easy to get gravity vector from acceleration sensor, you need another sensor like gyro (if available) to get the correct gravity part from Accelerometer readings.
regards Navigator
Thanks Janus! Your explanation kinda enlightened me regarding the rotation matrix. And the final line did solve my problem!
Now I just need to rework my free body diagrams to find out what I've did wrong... I already found that I should not have had a X-Y component of gravity, since gravity is orthonormal to the X-Y axis...
THanks again!
Edit: follow up on this, the last line: {g Sin[pitchangle],-g Cos[pitchangle] Sin[rollangle],-g Cos[pitchangle] Cos[rollangle]}
I've found instead of -g Cos[pitchangle] Sin[rollangle] Sin[roll] from my free body diagram more closely resembles the actual acceleration.
What I can't understand now is the last component -g Cos[pitchangle] Cos[rollangle] now it is perfect for small pitch and roll angles, and it works fine for either a pitch or roll angle while the other stays at 0, but a deviation becomes significant when both pitch and roll are no longer a small angle (say 40 degrees). Actually I also realised to achieve a 45 roll and 45 pitch on the nexus one, the phone would have a 0 Z axis reading, with X and Y both on 6.8ish acceleration. While the resulting formula from the rotation matrix multiplication at 45 roll and 45 pitch would be 0.5 gravity.
Is there something wrong with the orientation sensor output? or is this how pitch and roll are supposed to work?
Does anyone know how to account for this?
Thanks!
I wish I knew because I am also interested in this problem.
A good place to start researching is at http://www.diydrones.com/ . The folks over there have already solved this problem in the context of aircraft autopilots. There is a ton of high quality, open source code linked to from that site, as well as discussions of the math involved.