Search code examples
geolocationgiscesiumjswgs84

WGS84 to MSL and opposite


I am using Cesium to create point in a map. The point will be then flyable with a drone.

I have the following problem,

1) The user set a point altitude to 20 meters in a 2D flat map. 2) The point need to be create at the real world location (long/lat) + 20 meters (altitude). 3) The point will be visible on a 3D map, so at the location (long/lat) + 20 meters (altitude).

Exemple:

Now, from what I understand, Cesium altitude is using WSG84, and my server (that I have no control on) is using MSL.

from what I have seen on Internet I require a geoID to compute the calculation between a WSG84 point and MSL.

it is a straightforward procedure to subtract an interpolated geoid height, N, from a GPS ellipsoidal height, h, to obtain an orthometric height or a height above mean sea level (AMSL), H: H = h - N

I found for example this lib.

I have 3 questions about those procedure =>

1) Is everything I say correct ? am I going the right path ? 2) In the app, there is a flight tracking mode where a user can track a drone flying, but the coordinate come from the server in MSL, I get an update every 100ms, with all those additional calculation, will this part be a problem ? 2) Cesium is of course not 100% accurate, and I believe also that whatever geoID I use (for Japan region) will probably not be that accurate too. What average marge of error is to be expected ?

Thank you


Solution

  • I update this post cause I never replied if anyone was interested =>

    import { Injectable, NgZone } from '@angular/core';
    import { Cartographic } from 'src/app/shared/models/navigation.models';
    import { Observable } from 'rxjs';
    
    @Injectable({
      providedIn: 'root'
    })
    export class AltimeterService {
      terrainProvider = new Cesium.createWorldTerrain();
    
      constructor(private ngZone: NgZone) { }
    
      getElevation(pos: Cartographic): Observable<number> {
        return new Observable<number>(observer => {
          this.ngZone.run(() => {
            const promise = Cesium.sampleTerrainMostDetailed(this.terrainProvider, [new Cesium.Cartographic(pos.longitude, pos.latitude, 0)]);
            Cesium.when(promise, (updatedPositions) => {
              this.ngZone.run(() => {
                observer.next(updatedPositions[0].height);
                observer.complete();
              });
            });
          });
        });
      }
    
      getElevations(pos: Array<Cartographic>): Observable<Array<number>> {
        return new Observable<Array<number>>(observer => {
          this.ngZone.run(() => {
            const copy = new Array<Cartographic>();
            pos.forEach((p) => copy.push(new Cesium.Cartographic(p.longitude, p.latitude, 0)));
    
            const promise = Cesium.sampleTerrainMostDetailed(this.terrainProvider, copy);
            Cesium.when(promise, (updatedPositions) => {
              this.ngZone.run(() => {
                const elevations = new Array<number>();
                updatedPositions.forEach((p) => elevations.push(p.height));
                observer.next(elevations);
                observer.complete();
              });
            });
          });
        });
      }
    }
    

    This will get the altitude of a point on the map using Cesium World Terrain. this will be WSG84 value of the altitude at point long/lat

    I then pass the value to the server in GOLang that use this package to get the geoID altitude for the given long/ lat

    // ConvertGPSElevationToMSL convert gps to msl elevation
    // use geolocation package by garrettsickles to get the undulation or geoid from lat and lon
    func ConvertGPSElevationToMSL(gpsElevation float32, lat, lon float64) float32 {
        return gpsElevation - getGeoID(lat, lon) // geoid - gps elevation
    }
    
    // ConvertMSLToGPSElevation convert msl to gps elevation
    // use geolocation package by garrettsickles to get the undulation or geoid from lat and lon
    func ConvertMSLToGPSElevation(msl float32, lat, lon float64) float32 {
        return getGeoID(lat, lon) + msl // should be geoID - the msl (mean sea level)
    }