Discussion:
[Flightgear-devel] ADF bank error: anyone maths-types interested in a geometry problem?
David Megginson
2017-07-15 15:42:01 UTC
Permalink
Our ADF instrument is currently unrealistic, because it's unaffected by
aircraft attitude. In reality, since the ADF can detect direction in only
two dimensions (oriented with the aircraft), the apparent direction of the
NDB transmitted should change as the aircraft banks.

There's a nice layperson's explanation online here
<http://www.pprune.org/tech-log/234057-adf-dip-error.html#post2711405> (for
the example, the aircraft heading is 45° displaced from the bearing to the
NDB):

*"The ADF is a dumb gadget and just points at the beacon. If you're wings
level and the beacon is 45 degrees from the nose, it will point 45 degrees
off the index. But imagine you are in a 30 degree turn towards the beacon.
The relative bearing reduces.*

*"Can't imagine that, well now bank to 90 degrees. The relative bearing of
the beacon is now on the nose and you are apparently pointing straight at
it. *

*"Still not got it? Well, take your coffee mug off the coaster and place it
to the right of the desk. Pick up the coaster and hold it level above your
desk. This is your aircraft. Now pick up your biro and place it on the
coaster pointing at the coffee mug (the beacon). Now bank the coaster
towrds the mug while keeping the biro pointing at the mug. What happens?
You should notice the biro turning towards the nose of the aircraft and the
relative bearing reducing. Now expalin to your wife how you got the hot
drink ring on the desk."*

I'm willing to write the code, but I need help with the formula. The
*MagCompass::update* method in src/Instrumentation/mag-compass.cxx has
what I think is an applicable formula (if we replace magnetic dip with the
vertical angle to the NDB tower), but when I wrote the module 14 years ago,
I had a lot of help and basically copied the formula from elsewhere.

Here's the formula used for the mag compass:

/*
Formula for northernly turning error from
http://williams.best.vwh.net/compass/node4.html:

Hc: compass heading
psi: magnetic heading
theta: bank angle (right positive; should be phi here)
mu: dip angle (down positive)

Hc = atan2(sin(Hm)cos(theta)-tan(mu)sin(theta), cos(Hm))

This function changes the variable names to the more common psi
for the heading, theta for the pitch, and phi for the roll (and
target_deg for Hc). It also modifies the equation to
incorporate pitch as well as roll, as suggested by Chris
Metzler.
*/

The other option, of course, is just to approximate a needle swivel and not
worry about getting it right.


Thanks!


David
Thorsten Renk
2017-07-15 18:11:31 UTC
Permalink
Post by David Megginson
I'm willing to write the code, but I need help with the formula. The
*MagCompass::update* method in src/Instrumentation/mag-compass.cxx has
what I think is an applicable formula (if we replace magnetic dip with the
vertical angle to the NDB tower), but when I wrote the module 14 years ago,
I had a lot of help and basically copied the formula from elsewhere.
What is the input we have? 3d pointing vector to the Beacon? In aircraft
coordinates, world coordinates? 2d pointing vector? Bearing in aircraft
coordinates? Bearing in world coordinates?

It's not difficult to compute, I can walk you through, but the procedure
of choice depends a bit on what is available.

* Thorsten
David Megginson
2017-07-15 18:29:36 UTC
Permalink
Thanks, Thorsten. The ADF consists of two antennas that (combined) can
sense the direction from which an LF/MF transmission is coming. It's 2D,
referenced to the aircraft itself. When the aircraft is level, the
direction is (more or less) the same as the direction across the earth;
when the plane is banked or pitched, the system will still be trying to
detect the direct in 2D, but its 2D plane is no longer aligned with that of
the earth's surface (assuming a planar surface direction under the
airplane, perpendicular to gravity).

I'm in way over my head, math-wise.

D
Post by Thorsten Renk
Post by David Megginson
I'm willing to write the code, but I need help with the formula. The
*MagCompass::update* method in src/Instrumentation/mag-compass.cxx has
what I think is an applicable formula (if we replace magnetic dip with the
vertical angle to the NDB tower), but when I wrote the module 14 years ago,
I had a lot of help and basically copied the formula from elsewhere.
What is the input we have? 3d pointing vector to the Beacon? In aircraft
coordinates, world coordinates? 2d pointing vector? Bearing in aircraft
coordinates? Bearing in world coordinates?
It's not difficult to compute, I can walk you through, but the procedure
of choice depends a bit on what is available.
* Thorsten
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Flightgear-devel mailing list
https://lists.sourceforge.net/lists/listinfo/flightgear-devel
Thorsten Renk
2017-07-16 06:54:52 UTC
Permalink
Post by David Megginson
Thanks, Thorsten. The ADF consists of two antennas that (combined) can
sense the direction from which an LF/MF transmission is coming. It's 2D,
referenced to the aircraft itself. When the aircraft is level, the
direction is (more or less) the same as the direction across the earth;
when the plane is banked or pitched, the system will still be trying to
detect the direct in 2D, but its 2D plane is no longer aligned with that of
the earth's surface (assuming a planar surface direction under the
airplane, perpendicular to gravity).
I'm in way over my head, math-wise.
I understand the problem (it's actually also dependent on pitch, not only
roll...), I was just wondering what we have as starting point in the code.
But okay, here's one solution:

Step 1:

Say you have the aircraft in a reference orientation (heading 0 deg, pitch
0, roll 0). In this system, you can have the base vectors of the aircraft
coordinate system as

x = (1,0,0), y = (0,1,0) and z = (0,0,1)

If you change heading, pitch and roll, these are changed by Tait-Bryan
rotations - matrices which are functions by pitch, yaw and roll

https://en.wikipedia.org/wiki/Euler_angles#Tait.E2.80.93Bryan_angles

(for a code sample in Nasal, you can take a look at

https://sourceforge.net/p/fgspaceshuttledev/code/ci/development/tree/Nasal/rel_orbital.nas

but something tells me the FG C++ code has a suitable function available
already somewhere...). So we have a matrix M (pitch, yaw, roll)

The base vectors for an aircraft at different attitude are


x' = M * x, y' = M * y and z' = M * z

as the aircraft coordinate base vectors in a North/East/Up coordinate
system corresponding to the reference attitude, and these really should be
available as functions f(x, p, y, r) which take the vector x and the
attitude angles and spit out a new rotated vector.

Step 2:

Say we have a North/East/Up coordinate pointing vector v from aircraft to
the beacon available. The angle is determined in the aircraft (xy) plane,
so we need to project the vector into that plane.

h = v * z'

is the component of the pointing vector out of the plane, so we subtract
it.

v' = v - v*z'


Step 3:


The angle shown is now between the aircraft forward-pointing vector x' and
the projected pointing vector v', so we can normalize all vectors

v'' = normalize(v')
x'' = normalize(x')

and then use

sin(alpha) = x'' * v''

and voila - you have the angle as a function of heading, pitch and roll,
and if you do pitch and roll 0 you ought to get back to the original
result, if you do pitch = 0 you ought to go back to the example you quoted.

Anyway, that's how it'd be done using vectors (I might have missed a sign
somewhere on the way...)

* Thorsten
Thorsten Renk
2017-07-16 09:24:48 UTC
Permalink
Post by Thorsten Renk
and then use
sin(alpha) = x'' * v''
and voila - you have the angle
Sorry, that'd be cos(alpha) of course (I knew I had something wrong...)...
if they're the same vector, the product is 1 and the angle is 0 and that's
the cosine. In this case you need to inspect also y'' * v'' to get the
sign right.

* Thorsten
Edward d'Auvergne
2017-07-16 09:40:56 UTC
Permalink
On 16 July 2017 at 11:24, Thorsten Renk
Post by Thorsten Renk
Post by Thorsten Renk
and then use
sin(alpha) = x'' * v''
and voila - you have the angle
Sorry, that'd be cos(alpha) of course (I knew I had something wrong...)...
if they're the same vector, the product is 1 and the angle is 0 and that's
the cosine. In this case you need to inspect also y'' * v'' to get the sign
right.
And if you need a signed angle ;)

https://stackoverflow.com/questions/5188561/signed-angle-between-two-3d-vectors-with-same-origin-within-the-same-plane

Regards,

Edward
James Turner
2017-07-16 16:28:31 UTC
Permalink
and voila - you have the angle as a function of heading, pitch and roll, and if you do pitch and roll 0 you ought to get back to the original result, if you do pitch = 0 you ought to go back to the example you quoted.
Anyway, that's how it'd be done using vectors (I might have missed a sign somewhere on the way...)
Just catching up post holiday - we have named, higher level helpers for things like this in C++, eg converting between heading-pitch-roll, lat-lon-alt and similar orientations via quaternions.

So yes it can be done ‘raw’ using vectors and matrices but it’s much more maintainable, and less code, to use the standard helpers if they fit (sometimes they don’t)

Kind regards,
James
David Megginson
2017-07-16 21:27:44 UTC
Permalink
I think I'm out of my depth even using the helpers. In the past, I either
copied equations verbatim from online, or fudged errors well enough to get
by (or worked really, really hard at introductory spherical geometry to add
the first roads, etc. in TerraGear). I might just fake it for now, using an
bank-angle-indexed offset towards the nose when flying towards the station
and banking towards the station, towards the tail when flying towards the
station and banking away from the station, etc.


Cheers, David
Post by Thorsten Renk
and voila - you have the angle as a function of heading, pitch and roll,
and if you do pitch and roll 0 you ought to get back to the original
result, if you do pitch = 0 you ought to go back to the example you quoted.
Anyway, that's how it'd be done using vectors (I might have missed a sign
somewhere on the way...)
Just catching up post holiday - we have named, higher level helpers for
things like this in C++, eg converting between heading-pitch-roll,
lat-lon-alt and similar orientations via quaternions.
So yes it can be done ‘raw’ using vectors and matrices but it’s much more
maintainable, and less code, to use the standard helpers if they fit
(sometimes they don’t)
Kind regards,
James
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Flightgear-devel mailing list
https://lists.sourceforge.net/lists/listinfo/flightgear-devel
James Turner
2017-07-17 16:36:55 UTC
Permalink
I think I'm out of my depth even using the helpers. In the past, I either copied equations verbatim from online, or fudged errors well enough to get by (or worked really, really hard at introductory spherical geometry to add the first roads, etc. in TerraGear). I might just fake it for now, using an bank-angle-indexed offset towards the nose when flying towards the station and banking towards the station, towards the tail when flying towards the station and banking away from the station, etc.
Please don’t fake it - can you refer me to some documents on the detection system? What I’m guessing I can do is compute the cartesian-space direction from the transmitter to the receivers, work out the angles between the antenna axes/normal and hence derive a ‘correctly incorrect’ value for all possible aircraft orientations.

Kind regards,
James
David Megginson
2017-07-17 21:56:57 UTC
Permalink
Thanks! I've been getting some offline help as well (I'll let the person
out himself if he wants, but thanks to him either way). I'm going to take a
stab at this, and keep coming back with questions. I'm on vacation this
week, so I might be a bit slow, but I will be working on it.


Cheers, David
Post by David Megginson
I think I'm out of my depth even using the helpers. In the past, I either
copied equations verbatim from online, or fudged errors well enough to get
by (or worked really, really hard at introductory spherical geometry to add
the first roads, etc. in TerraGear). I might just fake it for now, using an
bank-angle-indexed offset towards the nose when flying towards the station
and banking towards the station, towards the tail when flying towards the
station and banking away from the station, etc.
Please don’t fake it - can you refer me to some documents on the detection
system? What I’m guessing I can do is compute the cartesian-space direction
from the transmitter to the receivers, work out the angles between the
antenna axes/normal and hence derive a ‘correctly incorrect’ value for all
possible aircraft orientations.
Kind regards,
James
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Flightgear-devel mailing list
https://lists.sourceforge.net/lists/listinfo/flightgear-devel
Loading...