I’ve said before that flying is hard.

This post explains the issues Andrew_Stacey and I faced in building a flight code library, and the decisions we made, and how it works.

Issue – not enough controls

A plane can turn in 3 directions, as shown below.

And it has different controls for each of them

• yaw – vertical tail rudder and wing flaps (ailerons)
• pitch – horizontal tail flaps (elevators)
• roll – wing flaps (ailerons)

Typically, we will want to fly using either

• a joystick, which has two directions, up-down and left-right, or
• by tilting the iPad, again up-down and left-right

I’m sure you see the problem there. We’re one direction short.

We noticed, however, that the wing flaps on a plane not only control roll, but affect yaw too. So we can perhaps use one control to manage two directions.

Logically, pitch, which moves the plane nose up and down, matches an up and down joystick (or tilt) movement, so that’s easy. Note that is a rotation on the x axis.

So that leaves left-right movement to handle roll and yaw. And this is where we face another decision.

Issue – should rotation be fixed or incremental?

Let’s take roll for example. Suppose you slide the joystick all the way to the left. We can make the plane react in two ways.

Fixed

The roll is directly connected to the joystick position. So we can set a maximum roll angle, eg 90 degrees either way, and if you slide the joystick halfway, we rotate 45 degrees, and if you slide all the way, we rotate 90 degrees.

This makes the plane very responsive (although maybe too responsive, because your finger can move faster than a plane can roll in real life). It also makes it easy to return to level flight by returning the joystick to the middle.

However, there is no way to do a complete 360 degree roll, because you’re restricted to 90 degrees.

Incremental

The roll is incremental, so the roll angle is adjusted by a small amount if you slide the joystick left or right.

In other words, the joystick movement doesn’t tell you exactly where to go, but what to add to the existing rotation. This gives you much more control over the responsiveness of the plane.

It does have one small problem, though, which is especially important for the roll direction. After you’ve rolled about, you will almost certainly want to return to a level position. You can do this yourself, by tipping left and right until the plane is level, but it probably won’t be exactly level, and it would be nice if, when you took your hand off the joystick, that the plane levelled itself exactly.

Unfortunately, this is not easy when you’re working with quaternions, because it means finding out what roll angle you’re at, so you can reverse it. You can (sort of) extract the roll angle from a quaternion, but it could suffer from gimbal lock, because it will be a Euler angle. It’s much better to try and solve the problem using quaternions.

What we did

There is no perfect solution, so we’ve provided both options. You can define any of pitch, yaw and roll to be fixed or incremental. The default is that yaw is incremental, and pitch and roll are fixed (maximum 90 degrees).

The library also provides the option to have the plane level (both roll and pitch) itself if you take your finger off the joystick. This doesn’t work for iPad tilt, though, because there is no way to tell the program you have stopped tilting.

You can change the defaults, but we do recommend leaving yaw as incremental, because it doesn’t make sense to restrict the amount of left or right turning of a plane.

Under the bonnet, inside the Flight class, we’ve also kept the yaw value in a separate quaternion from pitch and roll. This is so that we can level the pitch and roll – but not yaw – when players take their hands off the controls. It is much easier to reverse a whole quaternion than part of it (by extracting angles, as explained above).

This is not a perfect solution, because by using two quaternions, we are no longer moving in all three directions simultaneously, but it doesn’t really matter, for what we need.

We found the plane may not roll straight back every time, but may do a strange little loop back the way it came. This is because if you push the joystick down at the same time as rolling, the pitch you are adding pushes sideways instead of up (because the plane is pointing sideways). Later, when the plane levels, the program reverses all the pitch, and undoes some of this, creating a strange effect. However, Andrew seems to have solved it with some math wizardry.

Feature – returning to a level position

As I said above, the library provides the option to return the plane to level flight when you stop turning (take your finger off the joystick). It does this by setting a target of level flight for the quaternion holding pitch and roll rotation, and then interpolating towards it from the current rotation over a period of seconds.

There is no on or off switch for this interpolation – it continually tries to roll back to level, so the instant you stop turning, it will take effect.

Other features of the library

I’ve added in an extremely simple controls for handling tilt, and a radar screen, for when you include other aircraft. (I found it very difficult to get the little dots in the right place, because I’m not good at visualising this stuff).

If you know how to use quaternions, you’ll also find Andrew’s library is packed full of goodies, and he’s extended the vector class so you can do multiplications and other operations which normally aren’t possible.

I’m going to leave to Andrew to document all the things you can do with it (the main reason being I don’t understand most of it).