Movement On Sphere Surface

Started by
9 comments, last by homogenized 15 years, 3 months ago
I'm having difficulty solving a problem in the project I'm working on and was looking for a little help. I have a sphere (Earth) which I can add surface objects to with a given Latitude/Longitude. I'm adding an airplane object at any given Lat/Long, and want it to move with a constant speed towards a destination Latitude/Longitude. So given Speed, Current Location and Destination, how would I calculate the airplane's new Lat/Long each frame update so that it moves in the right direction at a constant speed? Any help is greatly appreciated.
Advertisement
You should store your velocity as a vector with units of degrees/second. The first component represents latitudinal speed, the second longitudinal. Then it breaks down to (hopefully) familiar territory: position2 = position1 + velocity * Δt
We''re sorry, but you don''t have the clearance to read this post. Please exit your browser at this time. (Code 23)
You could use quaternion slerp. That should give you a smooth interpolation over the surface of a sphere. Store the position of the source and destination points as quaternions and slerp between them.
Quote:Original post by erissian
You should store your velocity as a vector with units of degrees/second. The first component represents latitudinal speed, the second longitudinal. Then it breaks down to (hopefully) familiar territory: position2 = position1 + velocity * Δt

I almost have this working, but I'm not calculating "a vector with units of degrees/second" properly (my current bad calculation has them flying more slowly around the poles, and quickly at the equator) -- could you go into more detail on how I would calculate this, given that I'm working only with Current & Target Longitude/Latitude and Speed?

My current understanding of this method is that it would work on a flattened map, but on the sphere one degree of Latitude or Longitude can be wildly different distances depending on where you are.

Thank you both for the replies.
That's because the lines of longitude are closer at the poles, where lines of latitude are equidistant. You will need to factor in the distance from the axis for that particular component, when changing from angular coordinates to rectilinear position.
We''re sorry, but you don''t have the clearance to read this post. Please exit your browser at this time. (Code 23)
What I would do:

quick and dirty:
pseudocode
vec3 airplane_pos=position from spherical coords(airplaneLatitude, airplaneLongitude);
vec3 target_pos=position from spherical coords(targetLatitude, targetLongitude);
vec3 delta=(target_pos-airplane_pos)
vec3 vel=Normalized(delta-delta*DotProd(Normalized(airplane_pos)))*speed;/// project the delta to be tangent to sphere, normalize, and multiply by speed.
airplane_pos+=vel*dt;
airplaneLatitude = latitude from position(airplane_pos)
airplaneLongitude = longitude from position(airplane_pos)


neat and mathy: find dPos/dLatitude and same for longitude, then from dPos/dt=(dPos/dLatitude) * (dLatitude/dt) + (dPos/dLongitude) * (dLongitude/dt) , solve for dLatitude/dt and dLongitude/dt (easy because those 2 dPos vectors are orthogonal), and use those to update latitude and longitude. Could work worse than above "quick and dirty" in practice. If you want I can write derivations for the neat method.
Quote:Original post by Dmytry
pseudocode
vec3 airplane_pos=position from spherical coords(airplaneLatitude, airplaneLongitude);
vec3 target_pos=position from spherical coords(targetLatitude, targetLongitude);
vec3 delta=(target_pos-airplane_pos)
vec3 vel=Normalized(delta-delta*DotProd(Normalized(airplane_pos)))*speed;/// project the delta to be tangent to sphere, normalize, and multiply by speed.
airplane_pos+=vel*dt;
airplaneLatitude = latitude from position(airplane_pos)
airplaneLongitude = longitude from position(airplane_pos)


Okay, I've been trying to do this for the past day and have made some progress, but am currently stuck.

I'm using this to convert from Lat/Long to spherical coordinates (on my Geographic Position object):
            /// <summary>            /// Convert a geographical position to a point on a 3D sphere with given radius.            /// </summary>            public Vector3D ToSphere(Double radius)            {                Double longitudeRad = Longitude * Math.PI / 180d;                Double latitudeRad = Latitude * Math.PI / 180d;                Double y = radius * Math.Sin(latitudeRad);                Double r2 = radius * Math.Cos(latitudeRad);                Double x = r2 * Math.Cos(longitudeRad);                Double z = r2 * Math.Sin(longitudeRad);                return new Vector3D(x, y, z);            }

But I've had trouble finding/creating a method for converting from spherical coordinates back into Longitude/Latitude that I could get to work properly. Could anyone give me a push in the right direction with some pseudo-code?

The only other thing I've had trouble understanding is:
Quote:vec3 vel=Normalized(delta-delta*DotProd(Normalized(airplane_pos)))*speed;/// project the delta to be tangent to sphere, normalize, and multiply by speed.

I'm not exactly sure what's being done in this single line, and I'm afraid I'm not converting it correctly to code. Would it be possible to break it down by a step or two? My 3D math is pretty weak, and experience with this type of problem is zero.

I appreciate the responses and patience.
Lat/long is spherical polar coordinates. I think what you mean is you lack the transform from Cartesian (XYZ) coordinates to lat/long,

Now, that depends what your XYZ axes are (which one is 'up') but as your spherical->cartesian transforms are:

y = r sin lat
x = r cos lat cos long
z = r cos lat sin long

I can infer that the inverse should be

lat = sin-1 y/r
long = tan-1 z/x
Sounds like you've found what you need, but I would like to recommend the following book. It covers this subject quite well, but in a very general way:

Modern Differential Geometry of Curves and Surfaces with Mathematica

I have the second edition, but I can only assume that the third edition would be better.
That worked perfectly, thank you.

The resulting C# for anyone in the future wanting a method to convert back and forth between Cartesian Coordinates and Longitude / Latitude Spherical Coordinates:

(This assumes a radius of 1. GeoPosition is just an object holding lat/long coordinates.)
static Vector3D ConvertGeoToCart(GeoPosition geoPosition){    double longitudeRad = DegreeToRadian(geoPosition.Longitude);    double latitudeRad = DegreeToRadian(geoPosition.Latitude);    double y = Math.Sin(latitudeRad);    double r2 = Math.Cos(latitudeRad);    double x = r2 * Math.Cos(longitudeRad);    double z = r2 * Math.Sin(longitudeRad);    return new Vector3D(x, y, z);}static GeoPosition ConvertCartToGeo(Vector3D position){    double latitude = Math.Asin(position.Y);    double longitude = Math.Atan2(position.Z , position.X);    return new GeoPosition(RadianToDegree(latitude), RadianToDegree(longitude));}static double DegreeToRadian(double degree){    return degree * Math.PI / 180.0;}static double RadianToDegree(double radian){    return radian / Math.PI * 180.0;}

This topic is closed to new replies.

Advertisement