Hove wrote:I was able to do ready-reckoning from integrating the acceleration because I was working in the Earth frame, so vertical acceleration just needed g subtracting from it. So I didn't understand your comment until yesterday...

Yesterday, I converted all the code to work in the quad frame to fix all sorts of tricky problems caused by working in the Earth frame. And at that point, gravity is distributed across all the quad accelerometer axes, and as you say, ready reckoning isn't obviously possible. But, I've just realized this morning that I can rotate g from earth to quad axes, and can then subtract it from each accelerometer reading before integrating. Haven't tried it yet though - bit scared as it's a radical rework of the code moving the the quad frame!

What you're getting from the accelerometer is [earth's gravity + all linear acceleration] projected onto the sensor's axes - so in the quad frame.

You want the linear acceleration part of the sensor. So:

*total_acc_q = gravity_q + linear_acc_q; // _q means in quad frame.This is what the sensor is seeing*
=>

*linear_acc_q = total_acc_q - gravity_q;*
But gravity_q is:

*gravity_q = gravity_e * matrix_e_q;*
Where:

- gravity_e is gravity in earth frame - (0, 0, 1) - this is in my coord system where Z points upwards. Gravity acceleration points up.

- matrix_e_q is a rotation matrix that can bring a vector from earth frame to quad frame. It's literally the quad axes - its front, right and up vectors arranged in matrix form.

So:

*gravity_q = (0, 0, 1) * matrix_e_q;*
So we just need to find out matrix_e_q. But:

*matrix_e_q = matrix_q_e ^ (-1)*
Where matrix_q_e is literally earths axes arranged in matrix form. So we need 3 perpendicular vector to define earths frame.

You only have one now - acceleration at rest (gravity). You need another one - I use compass - and then you can fully define earth's frame.

I use this method:

When the quadcopter is at rest and on a flat surface, the accelerometers up axis should read the gravity vector in quad space (so gravity_q) - but since the quad is at rest and on a flat surface, gravity_q == gravity_e (I assume a calibrated sensor).

With a compass I have another vector in quad frame - compass_q. I assume compass_e == compass_q since I don't care about true magnetic north and with their cross product (gravity_e x compass_e) I get my 3rd vector. It's the code I posted few posts above.

With these 3 normalized vectors I have earths frame and I can keep it up-to-date using the gyro, the compass and the complimentary filter.

Once you have matrix_q_e, you also have matrix_e_q by inverting it. With these 2 you can move back and forth between earth and quad frame as you wish:

*vector_q = vector_e * matrix_e_q;*
and

*vector_e = vector_q * matrix_q_e;*
Hove wrote:
Interesting that you had 150Hz noise - my first peak (from an audio analyser app on my iPad) is around 30Hz, hence my need to keep dlpf down to 10Hz.

Must have something resonating. Your cutoff seems much better as the usable frequency out of the accelerometer should never exceed ~10Hz.

Hove wrote:
Temperature calibration between 2 points shouuld be fine. I did it with lots of intermediate points as I wasn't sure how linear it was, but it's a very approximation to linear, so 2 points should be fine.

I wish I knew what quaternions are - everyone raves about them, but my ignorance is forcing me to stay with matrices! Even my matrix maths had rotted badly in the last 25 years since school. I think I need to go back to maths school.

I treat quaternions a bit like black boxes - although they seem to be simple enough.

They represent a rotation - you can think about them as a different representation of an angle-axis pair.

Their advantages are:

- smaller than a matrix (4 floats vs 9 floats)

- faster multiplication (16 mul + 12 adds vs 27 mul + 18 adds)

- way faster inversion which is always defined (3 divisions vs a LOT of math)

- they can be interpolated while staying normalized- this is the main advantage.

I can send you some quaternion code or you could take a look at the Eigen library. Not sure if there are python ports though.

Cheers