Sign in to follow this  
budipro

Converting geo coordinate into cartesian coordinate

Recommended Posts

Hi all, I would like to know whether my code to convert a geo coordinate into cartesian coordinate is correct:
public static Vector3 GetCartesian(AirPoint p)
{
   Vector3 ret = new Vector3();

   double lat_rad = p.m_Lat * m_deg2rad;
   double rad = (m_eqRadius + p.m_Alt) * m_scale;
   double proj = rad * Math.Cos( lat_rad );
   double lon = (p.m_Lng - m_upperleftlon) * m_deg2rad;

   ret.X = (float)(rad * Math.Sin(-lat_rad));
   ret.Z = (float)(proj * Math.Sin(lon));
   ret.Y = (float)(proj * Math.Cos(lon));
		
   return ret;
}
AirPoint is a class consisting latitude, longitude, and altitude in meter. m_deg2rad is a factor to change a degree into radian. m_eqRadius is earth radius in meter. m_scale is my world scale, i.e. 1 unit cartesian coordinate / 100 meter I wonder whether this is correct, cause when I fly an aircraft along the spherical surface of the earth, using this conversion (from airpoint to cartesian), my aircraft is jumping up and down (vibrating in place). Though I'm not really sure either if this conversion is the cause. Thanks a lot.

Share this post


Link to post
Share on other sites
I'm not into any of that mumbo jumbo you just said ;)

I'm not sure what it could be, sure it could be the sin/cos functions getting improper data, but then you should get even more strange effects, as being in the middle of the earth or jumping all around space.

So a pure guess, what values are you working with 1.0, 10.0, 1000.0, 10000000.0?
As you say it is vibrating it is likely that is caused by the loss of precision caused by floating point values.

Share this post


Link to post
Share on other sites
I guess it's a floating point precision problem.
Try to compute the modelview matrix completely in double precision.
Don't use OpenGL for that. It can only do float.
Also, your GetCartesian routine (which looks OK at first sight) must be changed t double output.

Share this post


Link to post
Share on other sites
I use Direct3D. It only supports float, right?

I also suspect that this is a point precision problem. But when I tried to calculate the length of my aircraft coordinate (sqrt(x*x + y*y + z*z)) in double precision, and compare it with the value on the previous frame (my aircraft flies with constant altitude), the difference is not too significant. It's around 0.001 to 0.003, which is 10-30 cm if I use 1:100 scale. While my aircraft size is around 10 meters or more.

I'm confused. Is there anything I miss about moving along a spherical surface?

What I do now is just convert my geo coordinate into cartesian every frame. It's a client-server system, so I get the geo coordinate from server, which I think the calculation is already correct.

Share this post


Link to post
Share on other sites
Quote:
Original post by budipro
I use Direct3D. It only supports float, right?

I also suspect that this is a point precision problem. But when I tried to calculate the length of my aircraft coordinate (sqrt(x*x + y*y + z*z)) in double precision, and compare it with the value on the previous frame (my aircraft flies with constant altitude), the difference is not too significant. It's around 0.001 to 0.003, which is 10-30 cm if I use 1:100 scale. While my aircraft size is around 10 meters or more.


You don't mean to say your aircraft is 10m long? And not 10m high I would hope... a normal aircraft I guess is about 1m high (without landing gears etc)?

Which would make 10-30cm reeeeaaaallly much, I mean, if it was 1cm it would still be much. Or did I misunderstand you with the scale.

I'm betting that you work with too high values, as when taking the distance from the center of the earth you suddenly get enormous heights, which don't work well with floats... what is the altitude you are working with?

Share this post


Link to post
Share on other sites
The height is 5 m or more. If it is significant, then what should I do?

Yes, I make the center of the earth on (0, 0, 0), which makes a coordinate on the earth surface will be thousands units. You mean I am not allowed to have this great value? My current world scale is 1 unit coordinate = 100 m. Do I need to take this smaller?

Share this post


Link to post
Share on other sites
The radius of Earth is r=6378000m. Floats support 7-8 correct digits.
This means, that the smallest height increase from r to r+eps is of the order of eps=10cm.
So this is what you've observed when comparing double to float.
It's not that much, but when you are moving around, the camera will always jiggle around
(true position) + eps*(some random value between -1 and 1).

How much is the camera jumping? If the jumps are of the order of 10cm, then it's floating point imprecision.

Share this post


Link to post
Share on other sites
Sorry, what is eps?

And what do you mean by 'camera jumping'?

In my case, the aircraft is vibrating, well, it can be said 'jumping', up and down. If I point my camera to follow the aircraft, of course the camera will be 'jumping', too.

As I have analyzed, the difference in coordinate vector length per frame is around 10-30 cm.

How to solve this imprecision?

Share this post


Link to post
Share on other sites
I am currently about to deal with the same problem.

Concerning the 10cm problem: When you run the engine at 100FPS, all these small 10ms-timesteps are "rasterized" into the 10cm precision steps. That's the problem.

Even if you use double precision, this won't make it much better. And from my own experience: it's pretty ugly to cast from engine's-double to D3D's-single every time, so it'd be desirable to have it all in single-precision.


So, my idea was to split up the geo-coordinate into two vectors: the reference vector and the offset vector (both are 3rd dimension vectors).

The reference-vector is a cartesian coordinate, where one unit equals the earth-radius. The reference vector always lies on sea-level, e.g. has a length of 1.

The offset-vector is a cartesian coordinate, where one unit equals the physics-unit, e.g. in feet, i.e. has a high precision.

Now all the physics calculations are done using the offset-vector. The refernence remains static.

When the offset-vector becomes so large, that you have to take earth-curvature into accound (e.g. 50 kilometers), you reset the geo-coordinate:
-convert offset from feet- to earth-radius-units: offset2 = offset * feetEarthRatio
-add this one to the reference-vector: reference += offset2
-reset offset: offset.zerovector()

You can combine this reset-procedure with terrain-reloading.

So what you basically do: you put small portions of curved earth into a linear system, and when you leave this small portion due to imprecision, you go into the next linear system.

I am currently about to implement a flight-simulator this way as an indi-developer.


P.S.: (edit)
I forgot, that when you add the offset-vector to the reference-vector, that you have to rotate the offset-vector in such a way, that the offset's up-vector equals the earth's normal-vector.

Share this post


Link to post
Share on other sites
Quote:

So, my idea was to split up the geo-coordinate into two vectors: the reference vector and the offset vector (both are 3rd dimension vectors).


Thanks for the idea. But sorry, I don't quite understand how to split up the geo-coordinate into the two vectors you mentioned. Does it not have the same imprecision problem during the calculation? (I reckon I'll be using the same method to get the cartesian coordinate, then normalize it, and split it into the vectors you mentioned, or is there other way, or am I wrong in my interpretation?)

In my case, I only get the geo-coordinate from server, I don't need to do any physics at all, I just need to draw the aircraft on this coordinate.

Share this post


Link to post
Share on other sites
It's seem I mis-interpreted your problem. Then my solution (or idea) is irrelevant to you.

Is it maybe a refresh-rate-problem of the server-client connection?

You could try to send "cartesian change-in-position" coordinates ("delta-position") with per-foot-resolution through the network and every second or so, you update the geo-coordinate.

Example:

Package 1:
GeoPosition = GeoPositon + Package.change_in_feet * feetEarthRatio

Package 2:
GeoPosition = GeoPosition + Package.change_in_feet * feetEarthRatio

.
.
.

Package n:
GeoPosition += Package.change_in_feet * feetEarthRatio

Package n+1 after one second:
GeoPosition = Package.AbsolutionServerGeoCoordinate


I have no idea wether this works or wether someone is able to understand this. The idea is, that when there is just addition of delta-values and no rounding (instead of rounding when converting from geo- to cartesian-coordinates), there will we no rounding errors and precision loss.

I admit that I probably don't understand what the problem is, since I don't know the project. If this is the case, save your time and simply ignore me :)

Share this post


Link to post
Share on other sites
Finally solved the problem.

Yes, it was caused by float imprecision. Syranide was right, my coordinate is too big. So, instead of putting my (0, 0, 0) on the center of the earth, I move it near the earth surface to get coordinates with lower values. This solved the vibrating problem and my aircraft flies smoothly now.

Thanks very much for all of you guys.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this