While away from a joystick-enabled system over the weekend, I decided
to start hacking at the Nasal/AI integration.  What I *really* wanted
to make work was carrier landings, which required getting velocity
information from the AI models.  But this required work on the YASim
gear model to understand the moving objects and to calculate per-gear
forces.  But *this* required an unambiguous transformation between the
YASim coordinate system and the terrain one.  For historical reasons
(I'll get to that in a second) YASim has always used its own WGS84
approximation, which isn't quite identical to the SimGear one.

So basically, I had to get the two datums to agree.  This turned out
to be, er, interesting.  The reason YASim has its own code is that it
does its work in a global cartesian frame.  Each frame, the
coordinates get exported from XYZ to lat/lon/alt, and imported back if
anything changes.  That transformation *has* to be symmetric.  If it's
not, the FDM will see the precision error as a space warp and get
confused.  SimGear has a sgGeodToCart() function, but no
sgCartToGeod() equivalent.  So I rolled my own; the altitude handling
wasn't quite correct, but at least it was symmetric.  Since nothing
outside of YASim ever saw the funny XYZ coordinates, things worked
fine.  Until now, when I need to make the funny XYZ coordinates agree
with the scenery objects' coordinate system.

To make a long story short: I wrote an implementation of
sgCartToGeod() that I'm pretty proud of.  But I got hung up over some
existing bugs in sgGeodToCart() and the related functions, so I
rewrote those too.  This is obviously the kind of "big change" that
shouldn't be checked in without code review, so here's the argument:

Problems with the existing LaRC code:

+ It's slightly wrong.  I don't quite know when it happened, but the
  sg_geodesy files have incorrect numbers for the WGS84 equatorial
  radius.  This number is part of the standard, it *really* shouldn't
  vary.  Asking for, say, the cartesian equivalent of 0 lat, 0 lon, 0
  alt gives a vector that is off by about a meter.  And frustratingly,
  I can't fix it; there are some other derived quantities that appear
  as magic numbers in the code.  But the derivations don't match the
  comments.  Simply fixing the radius number breaks the functions in
  ways I don't understand, because:

+ It's opaque.  Lots of trig functions; lots of greek variable names;
  no explanatory inline comments; no description of the algorithm.
  It looks like someone typed the code in out of a book.  That's
  fine, if you get it right.  But it makes maintenance really hard.

+ It's missing sgCartToGeod(), which is a firm requirement for me.
  You can approximate this with sgGeodToGeoc/sgPolarToCart3D (lots of
  existing code does), but that isn't symmetric -- running the two
  functions as a cycle, the numbers come out off by 1-4 meters, which
  isn't good enough for YASim to use for terrain intersections.

Advantages of the new code:

+ It seems to be correct.  At points on the equator and at the poles,
  it matches the WGS84 standard exactly, where the old code is off by
  about a meter.  In a test with randomly selected points, it matches
  the old code to within about a meter, which is reasonably strong
  evidence that I've got it right.

+ It is, hopefully, easier to understand.  There is significantly less
  actual code in the new implementaiton, and I've tried to explain
  what I'm doing.  I won't say it isn't opaque (this stuff is a little
  brain-twisty to begin with), but I've honestly tried to make it
  readable.

+ It includes sgCartToGeod().  This is the fun part.  The
  implementation is a recursion relation that is symmetric with
  sgGeodToCart() and accurate all the way down to the precision of a
  IEEE double (about 6 nanometers for points on the surface).  It's
  not terribly fast (something like 4000 CPU cycles, about 6x slower
  than my implementation of sgGeodToCart), but is only called a few
  times per frame in typical usage.  A quick inspection turned up
  several places in the code where the existing API was being used to
  emulate this function; replacing them with this function made things
  cleaner and simpler.

Anyway, anyone who is interested should grab the update at:

  http://www.plausible.org/andy/new_geodesy.tar.gz

The new code is in sg_geodesy.*, the other files are just minor API
fixups (mostly because sg_geodesy.hxx no longer includes polar3d.hxx)
It appears to work for me with no change of functionality.  I won't
bother checking it in until I finish the YASim gear work which
requires it.  Yell if you think something is wrong.

Andy


_______________________________________________
Flightgear-devel mailing list
[EMAIL PROTECTED]
http://mail.flightgear.org/mailman/listinfo/flightgear-devel

Reply via email to