Correct GPS altitude with the Cesium Terrain

Hi.
I try to correct the altitude of an aircraft flight measured with a GPS.
I can get the json data from my GPS.
I can get the sampleTerrain of Cesium for each point of the flight
I try now to correct the GPS data with the help of Cesium sampleTerrain but I don’t know how to do that. I’ve seen the API documentation but it doesn’t help me.

For example, I tried:

function updatePoints(pointOfInterests, points) {
var promise = Cesium.sampleTerrainMostDetailed(viewer.terrainProvider, 11, pointOfInterests);
return Cesium.when(promise, function (pointOfInterests) {
for (var key in pointOfInterests) {
var altitude = parseFloat(json[key][‘ALTITUDE’]);
var elevation = parseFloat(json[key][‘ELEVATION’]);
var ground = pointOfInterests[key].height.toFixed(2);
var deltaGround = (elevation - ground) ;
var nouvelleAltitude = (altitude - deltaGround);
pointOfInterests[key][‘height’] = nouvelleAltitude;
}
});
}

But how to use the pointOfInterests? Can anybody help?

Can you get MSL from your GPS?

Most GPS I know do that rather than AGL.

No need to correct the MSL altitudes for terrain elevation.

I think the immediate problem you’re having is that you’re using sampleTerrainMostDetailed but you’re passing it a level (11). That function does not need or allow a level parameter. Either remove that parameter or use sampleTerrain instead.

You’re right but unfotunately, we don’t record this data…

It’s just on the sample displayed that you have a sampleTerrainMostDetailed . Previously, I had tried with sampleTerrain and the level is a former piece of code.

Ok, I’ve found how to get the answer from the promise. Now I’ve got an array of values with an updated height. But when I build the path for my flight, the height is not used.

I checked by updating all the height to 0 and the helicopter is still to high… When I display the console, the actual height given is 60…

My question is: how to put my helicopter at the height I have calculated before? Cesium is acting as if only the longitude and latitude were used. the height remains unchanged.

Here’s a Sandcastle example of my interpretation of what you might be looking for. Hope it helps.

Scott

var viewer = new Cesium.Viewer(‘cesiumContainer’, {

terrainProvider: Cesium.createWorldTerrain()

});

function updatePoints(pointsOfInterest) {

var promise = Cesium.sampleTerrainMostDetailed(viewer.terrainProvider, pointsOfInterest);

Cesium.when(promise, function(updatedPositions) {

    

    // Add 600.0 meters to the height at each point

    var adjustedPoints = new Array(updatedPositions.length);

    for (var i = 0; i < updatedPositions.length; i++) {

        adjustedPoints[i] = Cesium.Cartesian3.fromRadians(

            updatedPositions[i].longitude,

            updatedPositions[i].latitude,

            updatedPositions[i].height + 600.0);

    }

    

    // Create SampledPositionProperty to supply entity position

    var p = new Cesium.SampledPositionProperty();

    for (var j = 0; j < updatedPositions.length; j++) {

        p.addSample(heloTimes[j], adjustedPoints[j]);

    }

    var availability = Cesium.TimeIntervalCollection.fromJulianDateArray({julianDates: [

        heloTimes[0],

        heloTimes[heloTimes.length-1]

    ]});

    // Create entity

    var entity = viewer.entities.add({

        name: heloName,

        position: p,

        path: {

            leadTime: 86400,

            trailTime: 86400,

            width: 3,

            material: new Cesium.PolylineOutlineMaterialProperty({

                color: Cesium.Color.DODGERBLUE,

                outlineColor: Cesium.Color.WHITE,

                outlineWidth: 2

            })

        }

    });

    var promise = viewer.zoomTo(entity);

    promise.then(function(result) {

        console.log(result); // "Stuff worked!"

    }, function(err) {

        console.log(err); // Error: "It broke"

    });

});

}

var heloName = ‘helo-1’;

var heloTimes = [

new Cesium.JulianDate.fromIso8601("2018-04-23T13:00:00Z"),

new Cesium.JulianDate.fromIso8601("2018-04-23T13:05:00Z"),

new Cesium.JulianDate.fromIso8601("2018-04-23T13:10:00Z"),

new Cesium.JulianDate.fromIso8601("2018-04-23T13:15:00Z"),

new Cesium.JulianDate.fromIso8601("2018-04-23T13:20:00Z"),

new Cesium.JulianDate.fromIso8601("2018-04-23T13:25:00Z"),

new Cesium.JulianDate.fromIso8601("2018-04-23T13:30:00Z"),

new Cesium.JulianDate.fromIso8601("2018-04-23T13:35:00Z"),

new Cesium.JulianDate.fromIso8601("2018-04-23T13:40:00Z"),

new Cesium.JulianDate.fromIso8601("2018-04-23T13:45:00Z"),

new Cesium.JulianDate.fromIso8601("2018-04-23T13:50:00Z"),

new Cesium.JulianDate.fromIso8601("2018-04-23T13:55:00Z"),

new Cesium.JulianDate.fromIso8601("2018-04-23T14:00:00Z"),

new Cesium.JulianDate.fromIso8601("2018-04-23T14:05:00Z"),

new Cesium.JulianDate.fromIso8601("2018-04-23T14:10:00Z"),

new Cesium.JulianDate.fromIso8601("2018-04-23T14:15:00Z")

];

var wayPoints = [

Cesium.Cartographic.fromDegrees(-75.595831, 40.039481),

Cesium.Cartographic.fromDegrees(-75.596690, 40.040845),

Cesium.Cartographic.fromDegrees(-75.598071, 40.040727),

Cesium.Cartographic.fromDegrees(-75.599266, 40.040929),

Cesium.Cartographic.fromDegrees(-75.605076, 40.041031),

Cesium.Cartographic.fromDegrees(-75.615736, 40.037679),

Cesium.Cartographic.fromDegrees(-75.617471, 40.038690),

Cesium.Cartographic.fromDegrees(-75.618650, 40.040087),

Cesium.Cartographic.fromDegrees(-75.624291, 40.044382),

Cesium.Cartographic.fromDegrees(-75.627222, 40.044786),

Cesium.Cartographic.fromDegrees(-75.629916, 40.047952),

Cesium.Cartographic.fromDegrees(-75.632611, 40.049922),

Cesium.Cartographic.fromDegrees(-75.633570, 40.050310),

Cesium.Cartographic.fromDegrees(-75.634581, 40.050343),

Cesium.Cartographic.fromDegrees(-75.635709, 40.049922)

];

var startTime = heloTimes[0];

var stopTime = heloTimes[heloTimes.length - 1];

stopTime = Cesium.JulianDate.addMinutes(startTime, 5.0 * wayPoints.length, stopTime);

viewer.clock.currentTime = startTime;

viewer.clock.startTime = startTime;

viewer.clock.stopTime = stopTime;

updatePoints(wayPoints);

``

I have an array of positions which have to be updated with sampleTerrainMost detailed().
How can I get the updated heights? As the function works asynchronously, I can't see, when the height is updated.

This is my example code:
  var viewer = new Cesium.Viewer('cesiumContainer');

  function updateHeights(terrainProvider, pos) {
    var promise = Cesium.sampleTerrainMostDetailed(terrainProvider, pos);
    return Cesium.when(promise, function(updatedPositions) {});
  }

  // set positions
  cartesianPositions = ;
  var pos_0 = new Cesium.Cartesian3.fromDegreesArray(
  [ 10.508325500022316, 52.304257301113736 ,
  10.508759700022322, 52.303278601113725 ,
  10.509402400022331, 52.301784501113723 ,
  10.51287090002238, 52.301337401113734 ,
  10.516386400022432, 52.300910801113716 ,
  10.51895480002247, 52.300596601113732 ,
  10.522445500022521, 52.300164401113719 ,
  10.526765200022584, 52.299623601113701 ,
  10.529596300022625, 52.299263501113721 ,
  10.532180900022665, 52.298943301113709 ,
  10.536308000022725, 52.298421501113701 ,
  10.539986700022776, 52.297954301113698 ,
  10.54427580002284, 52.297447701113697 ,
  10.548418800022903, 52.296937101113706 ,
  10.552820300022967, 52.296408801113699 ,
  10.556224400023016, 52.296309101113685 ,
  10.560392600023079, 52.296190301113704 ,
  10.564738800023143, 52.296083301113704 ,
  10.569483200023212, 52.295962501113699]);
  
  var pos_1 = new Cesium.Cartesian3.fromDegreesArray(
  [10.505707900022275, 52.301242101113729 ,
  10.505781600022276, 52.301223501113725 ,
  10.505803200022276, 52.301218201113727 ,
  10.505824500022277, 52.301213101113738 ]);
  
  // store positions in array "positions"
  cartesianPositions.push(pos_0);
  cartesianPositions.push(pos_1);
  positions = ;
  for (var i=0; i<cartesianPositions.length; i++)
  {
    var cartographicPositions = viewer.scene.globe.ellipsoid.cartesianArrayToCartographicArray(cartesianPositions[i]);
    positions.push(cartographicPositions);
  }

  // create terrainProvider
  var terrainProvider = Cesium.createWorldTerrain();
  for (var i=0; i<positions.length; i++)
  {
    for (var j=0; j<positions[i].length; j++)
      console.log("vorher", i,j, positions[i][j].height);

    // get updated positions
    updateHeights(terrainProvider, positions[i]);
    for (var j=0; j<positions[i].length; j++)
      console.log("nachher", i,j, positions[i][j].height);
  }

Because the sampleTerrainMostDetailed method is asynchronous, the only place you will see the updated heights is in the callback function for the promise. Modify the updateHeights method as shown below and you’ll see what I mean when you run your example in Sandcastle.

function updateHeights(terrainProvider, pos) {

var promise = Cesium.sampleTerrainMostDetailed(terrainProvider, pos);

return Cesium.when(promise, function (updatedPositions) {

    console.log('Positions updated!')

});

}

``

Scott

Meanwhile I fixed my problem in another way.
But Thanks a lot for the hint with the callback

Please share what you did so that others may learn from your experience.