This release has some awesome new features. Most of the updates are focused on improving the AHRS. There is a better calibration system (mentioned in the last blog post) and there are some small changes to the Firetail firmware that also improve AHRS accuracy.

This new version should really improve attitude and heading indication a lot.

On top of that, vertical speed indication will be improved because having a better attitude estimation means having a better vertical acceleration estimate.

There is also a new radio configuration tool. This allows you to change settings on your RFD900 or compatible radio. RFDesign also provides a configuration tool, but this is probably more convenient for a lot of people.

The only other thing worth mentioning is that the Firetail firmware now uses all 6 servo channels. So landing gear and flaps can be used. In the future, I’m thinking about making one of these channels an optional mode switch so that the autopilot can be turned on and off without telemetry.

Just thought I’d post something about an exciting new AHRS calibration feature that will be in the next release of FLStation.


This user interface shows scatter plots of raw magnetometer samples. This allows you to visualise the data that is being collected which means more awareness of any issues in the readings (not enough data collected, strange spikes from interference and so on). The culling feature trims off a percentage of readings. Selecting 5.0 will remove the top 5% longest measurements. So if you’ve got any strange spikes, they can be removed.

Clicking the calibrate button generates new bias and gain settings that can be uploaded to the aircraft.

The new calibration technique will seriously improve the accuracy of the AHRS, especially the magnetometers. Having deadly accurate heading data is exciting because it enables so many possibilities (automatic take-off and landing in particular).


FLStation version 0.6.57 is now available for download.

New GCS features include

  • A terminal to access to the flight controller (or any other serial device) via USB. The flight controller firmware doesn’t do much with the terminal yet, but future versions will allow users to modify radio settings, upload encryption keys and so on through the terminal interface.
  • Log files can be exported to comma separated value (CSV) files. CSV files can be opened with spread sheet software and GNUPlot for in-depth analysis.
  • A minimum throttle setting. If there is a tail wind, the autopilot will reduce the throttle to maintain the selected ground speed. If the wind is strong enough, the aircraft could stall and fall out of the sky. The minimum throttle setting prevents the auto-throttle from slowing the motor to dangerously low speeds.
  • A plethora of minor bug fixes and optimisations.

The new Firetail firmware included in this release features

  • Improved fuzzy logic curves for auto-throttle, plus the minimum throttle setting.
  • Position estimation. Previously the position + ground speed was taken directly from the GPS. Most GPS devices are quite slow. The Adafruit Ultimate GPS operates at 10Hz max, but the main control loop runs at 50Hz. The purpose of the position estimator is to update the position of the aircraft at a 50Hz rate using¬† ‘dead reckoning’. This also means that slower GPS devices could be used without any noticeable performance issues.
  • A bug involving the pitch to bank ratio, for turn coordination, has been fixed. It used a sin function instead of tan.
  • The terminal thingy

Our plane got stuck in a tree in the snowy mountains today. I’m hoping the wind blows the plane out of the tree and someone will find this website and return it. If you have found it, please contact me.

It looks like this, but all smashed up and without the decals

We went out to get some aerial footage of the scenery and to mess around with the autopilot some more. Basically immediately after take off the plane went in front of the sun. During that brief moment when I was blinded by the light, the aircraft rolled onto its back and ended up crashing into a tree. It was stuck very high up and it was too difficult to climb. We threw sticks and stones at it until our arms were too sore to continue. When we left it was still stuck in the tree and the ESC was still beeping.

Luckily the camera broke off on impact and fell to the ground. It survived without any damage and we’ve now got the crash footage to cry over. Still, the electronics that we’ve lost are entirely custom made and are of great value to me. So if you’ve found this plane, please let me know!!


Update: I managed to retrieve the plane. I attached fishing line to a nicely sized weight and threw it over the branch. Then I tied a rope to the fishing line and pulled the rope up over the branch. We had very little length left over from the 35m long rope, so I estimate the branch was probably 15-16m high. I managed to break off the branch and get back all the electronics. The whole process took about 5mins.

After two nights stuck up in a tree, I expected some corrosion on the circuit boards, but it was all fine. No damage at all.

It seems FlightGear doesn’t lie. It works in the sim and now we’ve flown it in real life. Pitch & roll stabilised mode worked brilliantly. Flying in this mode is very low stress and easy. We also tried heading & altitude control, but had some difficulties. This is mainly due to issues with the altimeter/barometer and magnetometers. The LPS331 altimeter is very noisy which makes it hard to derive vertical speed and the magnetometers . . I don’t know what happened there. But the heading was all over the place.

FLStation 0.5.0 is now available for download.


This release has a muchly improved flight display user interface. It also has vertical speed control, fuzzy PID control for auto-throttle and various other cool things.

One important note about the auto-throttle – it uses ground speed only. And since it’s quite possible that the aircraft could have a strong tail wind, it will never fully cut the throttle to slow down the ground speed. It will reduce the throttle, but it won’t ever cut it off (unless the aircraft is also commanded to descend). It should not cause the aircraft to approach a dangerously low air speed.

I’m also putting together a Phantom FX-61. I had ordered a Bixler2, but ended up getting this instead. It’s a much better craft for this type of thing.

Basic layout of the avionics gear.

Basic layout of the avionics gear.

The avionics is mounted onto a stiffened balsa board which is adhered on with lots of anti-vibration jelly. The actual firetail board and other components are also attached with anti-vibration jelly. Despite this, the LSM303 accelerometer still gets messed up when the motor is running. I’ve put an ADXL345 breakout board in this plane as well, and fusing the these two accelerometers seems to get rid of the vibration problems altogether. The mems sensors aren’t properly aligned with the airframe yet either. This photo shows how crooked they are.

The battery is also too small for this model. It’s a 3S 2200mAh battery. The recommended battery is 4500mAh, so that’s something I’ll need to upgrade soon too. Even with this battery I expect flight times of about 10mins. Maximum current draw is about 16 amps (nearly 200W).

This model is supposed to take a huge battery and stacks of gear. Even with the tiny little firetail board and 2200 mAh battery shoved all the way forward, it isn’t enough to get the C of G right. So I had to glue about 40g of lead into the nose.

Dipole antennas make it look like an insect. It's an unintentional, but awesome look I reckon.

Dipole antennas make it look like an insect. It’s an unintentional, but awesome look I reckon.

Calibrating magnetometers is critically important. Without a good mag cal, you’ll get rubbish out of your magnetometers. Fortunately it isn’t that hard to do a basic calibration.

First of all, here are some scatter plots of raw magnetometer data. The sensor I used to create these was an LSM303.

lsm303 magnetometer scatter plot xy axis lsm303 magnetometer scatter plot xz axis lsm303 magnetometer scatter plot yz axis  lsm303 magnetometer scatter plot 3d view

These scatter plots show both hard iron (or bias) and soft iron errors. An ideal plot is circular and is centred on the chart. Hard iron errors cause the measurements to be off centre. Soft iron errors cause the shape to be elliptical rather than circular.

To remove these errors, you need data. Lots of data. So get your magnetometer and move it around until you’ve got a few thousand samples in as many different orientations as possible.

Hard iron errors are the simplest to remove. Find the maximum and minimum measurements for each axis and average them. This gives the amount of offset for each axis. Every time you take a reading from your magnetometers, you should subtract this offset from each axis.

raw_values[i].x() -= (min_x + max_x)/2.0;
raw_values[i].y() -= (min_y + max_y)/2.0;
raw_values[i].z() -= (min_z + max_z)/2.0;


Soft iron errors are slightly harder to remove. There are some more advanced techniques that involve calculating rotation matrices and bla bla, but it’s computationally expensive (for my brain) and simply scaling each axis to remove the elliptical shape works quite well too.

First the hard iron errors are removed from the maximums and minimum magnetometer vectors. These minimum and maximum vectors are the same as the ones being used to correct for hard iron errors.

imu::Vector<3> vmax;
vmax.x() = max_x - ((min_x + max_x)/2.0);
vmax.y() = max_y - ((min_y + max_y)/2.0);
vmax.z() = max_z - ((min_z + max_z)/2.0);

imu::Vector<3> vmin;
vmin.x() = min_x - ((min_x + max_x)/2.0);
vmin.y() = min_y - ((min_y + max_y)/2.0);
vmin.z() = min_z - ((min_z + max_z)/2.0);

The average distance from the centre is now calculated. We want to know how far from the centre, so the negative values are inverted.

imu::Vector<3> avgs;
avgs = vmax + (vmin*-1); //multiply by -1 to make negative values positive
avgs = avgs / 2.0;

The components are now averaged out
float avg_rad = avgs.x() + avgs.y() + avgs.z();
avg_rad /= 3.0;

Finally calculate the scale factor by dividing average radius by average value for that axis.
float x_scale = (avg_rad/avgs.x());
float y_scale = (avg_rad/avgs.y());
float z_scale = (avg_rad/avgs.z());

With these scale values we can correct for soft iron errors by multiplying them with the relevant magnetometer axis reading. Here’s an example

imu::Vector<3> mag_reading =;

mag_reading.x() -= (min_x + max_x)/2.0;
mag_reading.y() -= (min_y + max_y)/2.0;
mag_reading.z() -= (min_z + max_z)/2.0;

mag_reading.x() *= x_scale;
mag_reading.y() *= y_scale;
mag_reading.z() *= z_scale;


Here are the results using this technique.

cal_3d cal_3d-2 cal_xy cal_xz cal_yz

It doesn’t use any matrix maths and the magnetometers are now quite accurate. In fact, using a map I can’t see any errors. Without any proper test equipment, I’d guess that it’s good to +/- 2 degrees.