1

The goal is to find the location of a mobile unit from ground stations at known GPS locations, reporting ranges to the mobile unit that are fuzzy or have noise. To do this, I want the script to convert Latitude Longitude Altitude (LLA) taken from Google Maps into XYZ coordinates which can be used by the least square algorithm, and then return the XYZ guess/result back as LLA coordinates accurate on Google maps. The Lat and Lon appear to be fairly accurate when I run the script, but the altitude is incredibly wrong, and I have not been able to figure out why. I know the ECEF to LLA conversion is based of the alt, so if I could find out why it is so inaccurate, I may also be able to improve the lat/lon accuracy.

Does anyone know why the altitude is so wrong and how I can fix it?

# Hello World program in Python
import numpy
import pyproj

miles = 0

# Lat, Long, Alt in m above sea level, Range in m
coords = [
  (36.8932303,  -76.3019194,  2, 1609.3440006146922),
  (36.90476155,  -76.19754928, 5, 8257),
  (36.87400768,  -76.2566008,  3, 2962),
  (36.8762048,  -76.18793625,  7, 8836),
  (36.88499263,  -76.41727585,  4, 11000),
]

NumRefs = len(coords)

ecef = pyproj.Proj(proj='geocent', ellps='WGS84', datum='WGS84')
lla = pyproj.Proj(proj='latlong', ellps='WGS84', datum='WGS84')

def lla_to_ecef(lat, lon, alt):
    x, y, z = pyproj.transform(lla, ecef, lon, lat, alt, radians=False)
    return x, y, z

def ecef_to_lla(x, y, z):
    lon, lat, alt = pyproj.transform(ecef, lla, x, y, z, radians=False)
    return lat, lon, alt

RefLoc = numpy.zeros((NumRefs,3))
RefLoc = numpy.asmatrix(RefLoc)
Ranges = numpy.zeros((NumRefs,1))
Ranges = numpy.asmatrix(Ranges)

for x in range(0, NumRefs):
    Tmp = lla_to_ecef(coords[x][0],coords[x][1],coords[x][2])
    RefLoc[x,0] = Tmp[0]
    RefLoc[x,1] = Tmp[1]
    RefLoc[x,2] = Tmp[2]
    #print(ecef_to_lla(Tmp[0], Tmp[1], Tmp[2]))
    if miles == 0:
       Ranges[x] = coords[x][3]
    else:
       Ranges[x] = coords[x][3] * 1609.344

#code to help debug
#RefLoc = numpy.mat("-51.295,23.2089,9.9447;85.8527,-5.3422,83.4387;-30.0032,-29.6681,-42.8322;-60.6809,66.1657,51.44;-49.7832,17.0528,50.7458")
#Ranges = numpy.mat("99.1211;201.7909;60.5797;150.6262;138.0656")

H = numpy.zeros((NumRefs,4))
H = numpy.asmatrix(H)
for x in range(0, NumRefs):
    H[x,0] = 1
    H[x,1] = -2*RefLoc[x,0]
    H[x,2] = -2*RefLoc[x,1]
    H[x,3] = -2*RefLoc[x,2]

b = numpy.zeros((NumRefs,1))
b = numpy.asmatrix(b)
for x in range(0, NumRefs):
     b[x,0] = Ranges[x]**2 - RefLoc[x,0]**2 - RefLoc[x,1]**2 - RefLoc[x,2]**2 

xHat = numpy.linalg.inv(numpy.transpose(H)*H)*numpy.transpose(H)*b
xyzEst = [xHat[1],xHat[2],xHat[3]]
#print(xyzEst)

print(ecef_to_lla(xHat[1], xHat[2], xHat[3]))
  • Are you sure the lla to ecef conversion is using the altitude? Conventionally the conversion from ecef gives you a height above the spheroid (in this case WGS84) not a height above the geoid (aka, roughly speaking, mean seal level). The WGS84 spheroids is NOT the same as the geoid. The discrepancy can be (lo) hundreds of metres. – dmuir Jun 12 '18 at 15:02
  • Honestly I am confused. I know for some test data I had, 2-7 meters above sea level, and -38 meters from the geoid (?I think?) both provided terrible results by tens of thousands of meters, and I could not find any other elevations provided easily online. – Ross Kinard Jun 13 '18 at 01:49
  • I was able to rewrite the script in Matlab and use an optimizing function on it. It brought the data to -67 meters in altitude, which was close enough to align the lat lon within 10 meters. For what I am doing, that will work. I also used heigh above sea level for that, and may be part of the inaccuracy. If i had used the -38 meters there, i may have actually found I was on the money. I will look at it more later and see what i can do. – Ross Kinard Jun 13 '18 at 01:51

0 Answers0