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: http://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:

Loads more to come, I'll keep you guys posted.

Views: 6968

Comment by Yuan Gao on January 7, 2012 at 1:47pm

Bill, yes that's the case: "at least the code is much smaller and takes almost no time at all to execute on our 72MHz 32-bit flight controller".  We find the processor spends more time waiting for slow UART and I2C operations to complete.  This is unfortunately unavoidable, the on-board XBee has a max baud of 115200, and the on-board GPS limits I2C to 100kHz.

The UART and I2C libraries for Forebrain will probably be rewritten in the future to be non-blocking.

The truth is, at this point we're not too bothered about squeezing performance out of the chip at the moment, there will be a time for code optimisation, but right now we have plenty of other code to implement.

The Cortex-M3 does integer divisions at 2 to 12 clock cycles depending on relative sizes of operands, but unlike the dsPIC, it has no floating point processor so floating point operations are software.

Comment by William Premerlani on January 7, 2012 at 2:10pm

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,


Comment by Yuan Gao on January 7, 2012 at 2:48pm

Bill, I thank you for your concern, we are however well aware of the problem.

The time step of our implementation is 200Hz with accelerometer and magnetometer drift cancellation at 100Hz (probably will reduce this down to 50Hz).  We can go higher, however we're bottlenecked by the slow I2C bus running at 100kHz, we may explore dynamically switching I2C bus speeds, the bottleneck in the system is the GPS device.  We are using the ITG3200 gyro, which is specced up to 2000 degrees/second.

If we were to turn the GPS and wireless telemetry off, it would then be possible to push the I2C bus up to 400Hz, and potentially run the AHRS loop at 1kHz or higher.  However, whether this is necessary, or desirable remains to be explored.

Comment by William Premerlani on January 7, 2012 at 3:30pm

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,


Comment by Yuan Gao on January 7, 2012 at 3:51pm

Everything on our controller is hardware interrupt driven, however the limitations are on the ICs that are connected at the other end of the bus.  The GPS unit for example has a maximum I2C bus rate of 100kHz, and the XBee we use for telemetry has a maximum baud of 115200.  The bottlenecks are in the hardware abstraction functions which is currently implemented as a blocking write to the hardware FIFOs.

For example at 115200 baud, sending a 20 byte message to the XBee takes about 2ms.  At 100kHz, receiving a 20 byte message from the GPS takes a similar amount of time.

However, you are right, we can simply move the I2C operations out of the AHRS interrupt and into a lower priority interrupt and avoid needing to rewrite the hardware abstraction code altogether.  The hardware-assisted PWM and GPIO interrupts already occupy a higher priority than the AHRS loop to ensure accurate timing, the UART receive interrupt is lower than the AHRS but above the flight mode state machine to avoid dropped bytes, this can be lowered further once I restock on 0603 zero-ohm links to connect the hardware flow control lines.

But as I say, this is hardly necessary at the moment.  Our focus is on implementing the GPS waypoint navigation, and then on the next generation of airframes.

Comment by William Premerlani on January 7, 2012 at 3:52pm

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,


Comment by Yuan Gao on January 7, 2012 at 3:55pm

The gyro is specced to 2000 degrees/second, this does not mean we intend for the quad to be actually rotating at 2000 degrees/second.

Thank you kindly for your multiple links to your post on this topic.  I can assure you that we are well aware of the limitations of control systems and sensors, and we are giving consideration to any issues that may be caused caused by them when the quadcopter is operating within its designed parameters.

Comment by William Premerlani on January 7, 2012 at 4:00pm

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,


Comment by William Premerlani on January 7, 2012 at 4:48pm

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,


Comment by Henry Fletcher on January 7, 2012 at 5:03pm

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,



You need to be a member of DIY Drones to add comments!

Join DIY Drones

© 2017   Created by Chris Anderson.   Powered by

Badges  |  Report an Issue  |  Terms of Service