How to Extract & Render GPX files From GoPro to Cesium

CesiumJS is an open-source JavaScript library for creating 3D globes and maps. CesiumJS is an easy-to-integrate and uses the library to create interactive web apps having cross-browser compatibility. This library is used by developers across industries, from aerospace to gaming to smart cities and smart 3d drone data inspection in GIS (Geographic Information System) Mapping systems. In this blog, we are going to discuss how to extract and render GPX files from GoPro to cesium.

Cesium inherits the standard WGS84 globe and other recognized models for geospatial visualization and modification.

Some of the supported standard 3D models in CesiumJS include:

  • 3D Tileset
  • Pointcloud
  • KML/KMZ
  • Flight Paths (SRT / GPX / MOV)
  • Ortho Map
  • 360 Panorama

GPX file

A GPX file is a GPS data file saved in the GPS Exchange format, an open standard used by many GPS programs. It contains longitude and latitude location data, including waypoints, routes, and tracks. GPX files are saved in XML format, which allows GPS data to be more easily imported and read by multiple programs and web services. 

A Typical GPX File Consists of The Following Tags:

    <?xml version="1.0" encoding="UTF-8"?>
<gpx xmlns="" version=""   >
      <trk>
            <name>TrackName.mp4</name>
            <desc>30 fps - GPS (Lat., Long., Alt., 2D speed, 3D speed)   [deg,deg,m,m/s,m/s]</desc>
            <src>GoPro Max</src>
          <trkseg>
              <trkpt lat="-19.3382103" lon="146.8317091">
                  <ele>21.986</ele>
               <time>2022-06-02T05:00:42.456Z</time>
                 <fix>3d</fix>
                 <hdop>126</hdop>
                 <cmt>altitude system: MSLV; 2dSpeed: 1.221; 3dSpeed: 1.18</cmt>
               </trkpt>
            <trkpt lat="-19.5382103" lon="146.8327099">
                <ele>21.986</ele>
                <time>2022-06-02T05:00:42.675Z</time>
                <fix>3d</fix>
                <hdop>126</hdop>
                <cmt>altitude system: MSLV; 2dSpeed: 1.221; 3dSpeed: 1.18</cmt>
            </trkpt>
                                              .
                                              .
                                              .
        </trkseg>
   </trk>
</gpx>

GPX Files Store 3 Types of Data:

  • Waypoint:

    Includes GPS coordinates of a point. It may also include other descriptive information.

  • Route:

    Includes a list of track points, which are waypoints for a turn or stage points, that lead to a destination.

  • Track:

    Includes a list of points that describe a path.

 

Loading GPX file in Cesium Viewer:

  1. Parse the gpx file manually or using a package (i.e gpxparser
  2. Parsing gpx file using gpxparser will provide arrays of Waypoints, Routes, and Track.
  3. Track array contains the track points and related metadata.

 

gpxParser {xmlSource: document, metadata: {...}, waypoints: Array(0), tracks: Array(1), routes: Array(0)}
metadata: {name: null, desc: null, time: '2022-06-07T02:46:33.105000Z', author: {...}}
routes: []
tracks: Array(1)
0:
cmt: null
desc: null
distance: {total: 2453.623233993939, cumul: Array(4973)}
elevation: {max: 14.847, min: 10.595, pos: 43.026999999999845, neg: 42.82799999999983, avg: 12.706296802734744}
link: {}
name: "gopro7-track"
number: null
points: Array(4973)
[0 ... 99]
0:
ele: 11.207
lat: -18.2547778
lon: 146.0103143
time: Tue Jun 07 2022 07:46:33 GMT+0500 (Pakistan Standard Time) {}
  1. Sort the points array with reference to the time attribute.
  2.  Iterate over the track points and maintain an array of Cartesian from longitude, latitude, and elevation attributes to Cartesian3 using Cesium.Cartesian3.fromDegrees();
  3. Maintain a separate array for timestamps, Cartesians, and Cartographic.
  4. Pass array of Cartesian and Timestamps along with video file URL to create a visual path using polyline entity.
  5. Add the entity to Cesium Viewer.

 

Looking for Cesium Development Team?

Share the details of your request and we will provide you with a full-cycle team under one roof.

Get an Estimate

 

 

function CreateFlightPath(params) {
   // create the cesium polyline entity - temp ? here or just store data and create dynamically later
   let entity = {
       id: Cesium.createGuid(),  
       polyline: {
           positions: params.positions,
           width: 4,
           outlineWidth: 1.0,
           material: new Cesium.ColorMaterialProperty(Cesium.Color.RED.withAlpha(0.7)),
           distanceDisplayCondition: new Cesium.DistanceDisplayCondition(0.0, 50000),
       },
       timestamps: params.timeStamps, // store video timestamp in millisecs at each vert -- TEMP whether to include at this level, or have the called add that in as needed
       Type: "flightPath",
       linkedVideo: params.videoFilename
   };
   return entity;
}

let readSuccess = (response) => {
   let gpx = new gpxParser();
   let timestampsMS = [];
   let tempTimeStamp = [];
   let lastVert = undefined;
   let pathVertsCartesian = [];
   let pathVertsCarto = [];
   let viewRays = [];


   gpx.parse(response.data);       //parsing gpx file
   _.sortBy(gpx.tracks[0].points, [function (item) {
       return item.time;        //sorting on the basis of time
   }]);

   for (let i = 0; i < gpx.tracks[0].points.length; i++) {  
   /* calculating time difference between two consecutive points */
 tempTimeStamp.push(moment(gpx.tracks[0].points[i].time).valueOf() - moment(gpx.tracks[0].points[0].time).valueOf());
   }
   for (let i = 0; i < gpx.tracks[0].points.length - 1; i++) {   //maintaining cartesian points
       let thisVert = Cesium.Cartesian3.fromDegrees(gpx.tracks[0].points[i].lon, gpx.tracks[0].points[i].lat, gpx.tracks[0].points[i].ele)

if ((lastVert === undefined) || (Cesium.Cartesian3.distance(thisVert, lastVert) >= minDistance)) {
           lastVert = thisVert;
           let tempCarto = Cesium.Cartographic.fromDegrees(gpx.tracks[0].points[i].lon, gpx.tracks[0].points[i].lat, gpx.tracks[0].points[i].ele);
           pathVertsCarto.push(tempCarto);
           pathVertsCartesian.push(Cesium.Cartographic.toCartesian(tempCarto));
           timestampsMS.push(tempTimeStamp[i]);
       }
   }

let params = {
       positions: pathVertsCartesian,
       timeStamps: timestampsMS,
       videoFilename: videoFilename,
   };
   let entity = CreateFlightPath(params);   //calling function to create visual path
   entity = window.viewer.entities.add(entity);   //adding the entity to viewer
   return {entity};
}

End Result:

GPX files

Share this article

Leave a comment