We've recently made the move from the old clunky DCM implementation to a new Quaternion approach, and it seems to perform better, or at least the code is much smaller and takes almost no time at all to execute on our 72MHz 32-bit flight controller. I'll be writing an article on the Quaternion method as part of our series on Engineering Insights.
We've also added MAVLink support, and full integration with QGroundControl GCS. This helps greatly with debugging, and of course enables waypoint flying. The ROFL quadcopter kits have GPS built-in, and wireless versions that include an integrated XBee module are available.
As always, more videos on our youtube channel: https://www.youtube.com/user/UAirLtd
And the kits are still on sale! http://www.universalair.co.uk/catalog/rofl
Still to come: waypoint flying, and FPV: The flight controller GPS code just needs a bit of tuning, and we'll have the thing flying autonomously in no time. The full-range of waypoint options in QGroudControl are supported, including waypoint tolerances, and yaw angles. (See image below):
Tuning the quad is also possible over QGroundControl, this is a massive improvement in useability over our previous custom solution:

Comments
This is a good discussion! I have been following it closely :) I can always learn a thing or two about hardware interfacing! I wrote much of the DCM code and the quaternion implementation we are now using, and I have already had it scruntinized by two of my colleagues here at Cambridge. Both of them are control specialists and looked rather disparagingly at my linear approximations!
I responded rather witheringly that if their more complex and capable code was ready, I wouldn't have had to write this code to fly the airframes I have designed in the first place! I guess it's just a question of time, at Universal Air we have an astonishingly fast development rate. It's crucial to be aware of the limitations I agree, but right now if any of my airframes are rotating too fast for my algorithm to keep up, it's more likely that I've just flown into a tree by mistake and lost a prop or two!
For anyone reading these comments and working out what to take away from it about the DCM and Quaternion systems I'd like to reiterate some of the points already made:
The DCM is a 9x9 matrix
The Quaternion is a 4x1 vector.
They are both useful for different things BUT express the SAME information, you can derive one from the other.
They both state the relative rotation between one coordinate frame, and another.
The DCM is easy to visualise, depending on which way you have it set up, the rows are the unit vectors of coordinate system A in coordinate system B, and the columns are the unit vectors of coordinate system B in coordinate system A.
The DCM is great for doing dot and cross products with other vectors provided by other sensors.
The Quaternion stores all the information in less variables and takes less updates.
NEITHER suffer from gimbal lock. This is a problem associated with the EULER angle system only (but can be avoided).
In a flight computer both are essentially an integration of the gyro signals. Remember, gyros give rotational speeds, the DCM/ Quaternion expresses rotational position (angles). Speed integrated = Position.
This integration can be done in a number of different ways, some are more accurate than others, typically extracting more accuracy requires more processor time.
Bill, feel free to add anything to that list that you think might be helpful to others reading this. More point in us telling other people things that might be useful to them, rather than each other things we already know, heh heh. Though one thing could be useful...do you know of a list of useful papers/sources around this subject? I have read quite a few now and thought it'd be beneficial if I posted a little list of the best, if one doesn't already exist!
Best wishes,
Henry
Hi Henry and Yuan,
One more question, and then I will try my best to not ask any more questions or make any more comments...
Perhaps I misunderstood your statement "the old clunky DCM implementation".
Did you mean that using a direction-cosine-matrix for autopilot computations is inherently clunky? If so, I strongly disagree.
Or perhaps did you mean that your implementation of DCM was clunky? If so, I cannot argue the point.
Best regards,
Bill
Hi Yuan,
Hardware interrupts are nice to have. They should allow you structure your code so that there are no blocking operations anywhere. Blocking operations are a bad idea. They can cause code at that interrupt priority or lower to lock up, and they waste CPU cycles.
Best regards,
Bill
Hi Yuan,
Another question about the gyros...are you doing anything about the calibration error? The spec sheet on the ITG3200 lists a gain variation of 6%. At 2000 degrees/second, this is an error of 120 degree/second, so there could be an accumulated error of 120 degrees in 1 second, unless you either manually calibrate the gyros, or use some sort of in-flight gyro auto calibration technique.
Best regards,
Bill
Hi Yuan,
Regarding your implementation time step of 200 Hz, that is nice to hear. However, although that would be fine for 500 degree/second gyros, it is right on the edge for 2000 degree/second gyros...With a time step of 200 Hz, and a rotation rate of 2000 degrees/second, the amount of rotation per time step is 10 degrees, or 0.175 radians, which is large enough to violate the assumption of a small rotation that is made in the quaternion update equation. 10 degrees is a finite rotation, it is not an infinitesimal. The linear approximation error at 2000 degrees per second is about 1.5%, or about 30 degrees/second, which will give you a net error of 180 degrees in 6 seconds of rotation at that rate.
Regarding your GPS, I2C, and wireless telemetry bottleneck, you have my sympathy. I am surprised your 72 MHz, 32 bit controller cannot eliminate those bottlenecks with hardware support.
The MatrixPilot team is using a 16 bit PIC controller that has hardware support for serial ports, I2C, SPI, and A/D. Everything is interrupt driven, with most of the work for those devices being done by the hardware. As a result, we can run the serial ports, I2C, and SPI at their maximum rates, and the A/D convertor at 8000 samples per second per channel, and still have only 10% CPU load.
Best regards,
Bill
Hi Henry and Yuan,
Just to be clear....I admire your work, and you are to be congratulated on implementing a quaternion approach, and I would enjoy having a technical discussion with you...
There is another effect that I would like to discuss with you...
The published literature on both direction cosine matrix updating and quaternion updating make an approximation that the rotation in an update step is small. This leads to an update that is linear in the gyro signals. However, the update is really nonlinear in the gyro signals for a finite rotation.
Through testing that I did by spinning a UAVDevBoard on a record player turntable at rotation rates up to 468 degrees per second (78 RPM), I found that there is a measurable error introduced by the small rotation approximation, proportional to the square of the rotation rate, that can be quite large at 468 RPM. I realized that in order to get high performance at sustained high rotation rates, I had three choices:
1. Increase the calculation rate. (Reduce the time step.)
2. Use the nonlinear representation of the incremental rotation.
3. Perform an adjustment based on the square or the rotation rate.
The third choice was the easiest way for me to revise the existing code, so that is the method I used. Testing showed that it did a nice job of compensating for the error. Here is the code for the adjustment in MatrixPilot.
If I were starting all over again, I would probably go with the exact equation for a finite rotation, and will probably do that some day, especially if we ever raise the range of the gyros to 2000 degrees/second.
My question for you is whether you are using an exact equation for rotation update, and if you are not, whether you are using any sort of adjustment for approximation error at high rotation rate?
Also, what is the time step of your implementation? The error is proportional to the square of the time step, so if you are using a very short time step, such as 5 milliseconds, you would not have much error at 500 degrees per second, but if it were around 25 milliseconds, there would be an appreciable error at 500 degrees per second.
Best regards,
Bill
Hi Yuan,
I think you just supported a point I was trying to make: the CPU loading of doing the renormalization step can be miniscule in the implementation. But if you really want to squeeze all the performance that you can, why are you not using a first order Taylor's expansion for the renormalization? It also eliminates a division.
Just out of curiosity, how does your hardware do a divide? On the PIC, divides require 17 CPU cycles, so I avoid them as much as possible, though lately we have been using them more liberally. Even so, CPU loading in MatrixPilot is around 10% for all computations, including A/D conversion and communications.
Do you do anything about compensating for gyro gain error during fast, sustained rotations? For example, a gyro gain error of 5% will produce an error of 18 degrees in 1 turn, and an error of 180 degrees in 10 turns. This can be a killer during acrobatics.
Best regards,
Bill
Hi Henry,
DCM and quaternion representations are equivalent. You can transform between the two in either direction. Some computations work best with DCM, some with quaternions. In the present version of MatrixPilot, I actually use both, starting with a DCM representation, and computing quaternions whenever I need them. The DCM computations in MatrixPilot presently consume less than 1% of the CPU processing power.
But the core representation of the attitude is just the "tip of the iceberg" in an autopilot. There are lots of other computations that need to be done, and effects to be taken into account, such as:
Wind estimation.
Gyro gains that are off-nominal.
Magnetometer misalignment.
Magnetometer offsets.
Dead reckoning.
And, in my opinion, the above computations are best done with a direction cosine matrix representation of attitude. It makes the theory easy to understand, and it simplifies the implementation.
I do agree that updating a quaternion is slightly computationally more efficient than updating a direction cosine matrix, but I take exception to the characterization of DCM as "clunky".
Best regards,
Bill Premerlani
Hi Henry and Yuan Gao,
Regarding the square-root operation, I am surprised that you are wasting CPU cycles computing clunky square roots when you do not need to. It is not necessary to compute square roots for the renormalization step in either DCM or quaternion computation methods. For example, in MatrixPilot, neither a square root operation nor a division is required in the renormalization step. Take a look at the MatrixPilot code. The only arithmetic that is used is multiplications and additions in a Taylor's expansion for the reciprocal of the square root. The Taylor's expansion works because the magnitudes of the rows and columns of the computed direction cosine matrix never drift far from the correct values, so the renormalization adjustments are always small.
Best regards,
Bill Premerlani
-
1
-
2
-
3
of 3 Next