0

I am looking for a written method to calculate ECEF coordinates from lat,lon and height data. I have found this java method but my coding skills does not allow me to transfer this to swift.

        private final double a = 6378137; // radius
        private final double e = 8.1819190842622e-2;  // eccentricity

        private final double asq = Math.pow(a,2);
        private final double esq = Math.pow(e,2);

        private double[] ecef2lla(double[] ecef){
          double x = ecef[0];
          double y = ecef[1];
          double z = ecef[2];

          double b = Math.sqrt( asq * (1-esq) );
          double bsq = Math.pow(b,2);
          double ep = Math.sqrt( (asq - bsq)/bsq);
          double p = Math.sqrt( Math.pow(x,2) + Math.pow(y,2) );
          double th = Math.atan2(a*z, b*p);

          double lon = Math.atan2(y,x);
          double lat = Math.atan2( (z + Math.pow(ep,2)*b*Math.pow(Math.sin(th),3) ), (p - esq*a*Math.pow(Math.cos(th),3)) );
          double N = a/( Math.sqrt(1-esq*Math.pow(Math.sin(lat),2)) );
          double alt = p / Math.cos(lat) - N;

          // mod lat to 0-2pi
          lon = lon % (2*Math.PI);

          // correction for altitude near poles left out.

          double[] ret = {lat, lon, alt};

          return ret;
        }

Thanks for you kind help.

Koray Birand
  • 1,956
  • 17
  • 22

2 Answers2

1

This is a direct translation, (except for a small correction to the % output):

let a:Double = 6378137 // radius
let e:Double = 8.1819190842622e-2  // eccentricity

let asq = pow(a,2)
let esq = pow(e,2)

func ecef2lla(ecef:[Double]) -> [Double] {
    let x = ecef[0]
    let y = ecef[1]
    let z = ecef[2]

    let b = sqrt( asq * (1-esq) )
    let bsq = pow(b,2)
    let ep = sqrt( (asq - bsq)/bsq)
    let p = sqrt( pow(x,2) + pow(y,2) )
    let th = atan2(a*z, b*p)

    var lon = atan2(y,x)
    let lat = atan2( (z + pow(ep,2)*b*pow(sin(th),3) ), (p - esq*a*pow(cos(th),3)) )
    let N = a/( sqrt(1-esq*pow(sin(lat),2)) )
    let alt = p / cos(lat) - N

    // mod lat to 0-2pi
    lon = lon % (2*M_PI)
    if lon < 0 {
        lon += 2*M_PI
    }

    // correction for altitude near poles left out.

    let ret = [lat, lon, alt]

    return ret
}

For the reverse function, look at this answer: ECEF to LLA in Python

Translating to Swift:

func lla2ecef(lat lat: Double, lon: Double, alt: Double) -> [Double] {
// see http://www.mathworks.de/help/toolbox/aeroblks/llatoecefposition.html

    let rad = 6378137.0        // Radius of the Earth (in meters)
    let f = 1.0/298.257223563  // Flattening factor WGS84 Model
    let cosLat = cos(lat)
    let sinLat = sin(lat)
    let FF     = pow((1.0-f), 2)
    let C      = 1/sqrt(pow(cosLat, 2) + FF * pow(sinLat,2))
    let S      = C * FF

    let x = (rad * C + alt)*cosLat * cos(lon)
    let y = (rad * C + alt)*cosLat * sin(lon)
    let z = (rad * S + alt)*sinLat

    return [x, y, z]
}

lla2ecef(lat: 42.0 / 180.0 * M_PI, lon: 28.0 / 180.0 * M_PI, alt: 0.0)
Community
  • 1
  • 1
vacawama
  • 150,663
  • 30
  • 266
  • 294
  • It is working !!! But I need the opposite calculation... LAT LON HEIGHT to ECEF :(( – Koray Birand Mar 04 '16 at 00:23
  • Sorry It is not calculating correct also for ecef to lat lon height. – Koray Birand Mar 04 '16 at 00:29
  • What part isn't correct? I just made a fix to `lon`. – vacawama Mar 04 '16 at 00:30
  • for ecef2lla([4191,2228,0]) the result should be [42,28,0] but instead I am getting [3.141592653589793, 0.4886188546466224, -6382883.416016323] you can also check from : http://www.oc.nps.edu/oc2902w/coord/llhxyz.htm But I as said I need the opposite calculation – Koray Birand Mar 04 '16 at 00:35
  • 1
    It works, but unlike the website, this function is using meters instead of kilometers and it is using radians instead of degrees. `ecef2lla([4191000,2228000,0]) = [0, 0.4886188546466224, -1631720.98367779]` and 0.4886 * 180.0 / 3.1416 = 27.99 degrees. – vacawama Mar 04 '16 at 02:01
  • aaahh sorry. Can you also help me for the opposite calculation. – Koray Birand Mar 04 '16 at 02:04
  • Go ahead and post your function as an answer. You are allowed to answer your own question on Stack Overflow. Compare yours to mine. – vacawama Mar 04 '16 at 02:56
1
func toECEF(lat:Double,lon:Double, h: Double) -> [Double]{

   let a : Double = 6378137 // radius
   let e : Double = 8.1819190842622e-2  // eccentricity



    let lat = lat / 180 * M_PI
    let lon = lon / 180 * M_PI
    let h = h

    let e2 = pow(e, 2)

    let slat = sin(lat)
    let clat = cos(lat)

    let N = a / sqrt(1-e2 * slat * slat)

    let x = (N + h) * clat * cos(lon)
    let y = (N + h) * clat * sin(lon)
    let z = (N * (1 - e2) + h) * slat

    return [x,y,z]

}

toECEF(42, lon: 28, h: 0)

Result: [4191342.320476103, 2228582.38702054, 4245611.943048043]

Koray Birand
  • 1,956
  • 17
  • 22