Skip to content

Record GPS Position Log

In this guide you will learn how to play back a previously recorded GPS position log, using DataSource on an interactive map, and use this as input to record a GPS position log using DataSourceRecorder. Prior to recording, the sensor data types to be recorded are selected and their availability is validated. A frame per second (FPS) counter is also displayed.

GPS Log Data Source

QML data source GPS position playback and record example

First, get an API key token, see the Getting Started guide.

Qt should be installed to continue.

The Maps SDK for Qt should be installed, see the Setup Maps SDK for Qt guide.

Overview

RecordGPSPositionLog demonstrates how easy it is to record a GPS position log using a previously recorded GPS position log file as input, so that GPS log recording can be demonstrated on a desktop computer as well. Typically, the GPS log data source is the GPS sensor on a device, such as a phone.
The previously recorded GPS log input can be a *.nmea file, which can also be generated using free web-based nmea generator tools.
This example generates a *.gm file, intended for debugging.
Prior to recording, the sensor data types to be recorded are selected interactively by the user, then their availability is validated, and the unavailable sensor data sources are deselected automatically.

How it works

In Qt, go to the File menu and select Open File or Project…

then browse to the RecordGPSPositionLog example folder and open RecordGPSPositionLog.pro

You may want to have a look at Setting your API Key to see how to open and configure a project and set your API Key.

In main.qml, in the Component.onCompleted: block, the datasource is set by specifying the filename of a previously recorded (or web-generated) [GPS] position log, strasbourg.nmea in this case:

1ServicesManager.dataSource.playbackFile = Qt.resolvedUrl("strasbourg.nmea");
2ServicesManager.dataSource.type = DataSource.Type.Playback;

This implies that the strasbourg.nmea data file is located in the project directory of this example, and configured in the qml.qrc file, so that Qt.resolvedUrl() can find it.

Additionally, the following options are set for the GPS log data source recorder:

1ServicesManager.dataSourceRecorder.chunkDurationMinutes = 1;
2ServicesManager.dataSourceRecorder.continuousRecording = true;
3ServicesManager.dataSourceRecorder.deleteOlderThanKeepMin = false;
4ServicesManager.dataSourceRecorder.keepMinMinutes = 60;
5ServicesManager.dataSourceRecorder.dataSourceTypesToRecord = DataSourceRecorder.Position;
The minimum size of a GPS log is 1 minute, set in chunkDurationMinutes; the keepMinMinutes setting specifies the size of the moving window of recorded GPS log data to keep, implying that data older than this amount of time, in minutes, is deleted.
The deleteOlderThanKeepMin flag set to false indicates that no data shall be deleted, all recorded GPS log data is kept. This may be useful for testing purposes.
Position is the raw location (GPS) sensor data, and is always on for navigation, as recording a GPS position log without position makes no sense. ImprovedPosition is the map-matched computed position, for example, placing the actual position on a nearby road. Multiple data sources / sensors can be selected by OR-ing them together using the | bitwise operator.

The content type that will be downloaded upon demand is also specified:

let updater = ServicesManager.contentUpdater(ContentItem.Type.RoadMap);

The MapView displaying the interactive map has 4 buttons:

Start / Stop recording and Faster / Slower playback in the top left corner;
Playback - switch to live / Live - switch to playback in the lower left corner; and
Follow position in the lower right corner.

Select source and sensors

 1CheckBox {
 2    id: checkBattery
 3    enabled: !ServicesManager.dataSourceRecorder.active
 4    checked: false
 5    indicator.width: 18
 6    indicator.height: 18
 7    text: qsTr("Battery")
 8}
 9CheckBox {
10    id: checkCompass
11    enabled: !ServicesManager.dataSourceRecorder.active
12    checked: false
13    indicator.width: 18
14    indicator.height: 18
15    text: qsTr("Compass")
16}
17CheckBox {
18    id: checkImprovedPosition
19    enabled: !ServicesManager.dataSourceRecorder.active
20    checked: true
21    indicator.width: 18
22    indicator.height: 18
23    text: qsTr("ImprovedPosition") //calculated, map-matched position
24}

Additionally, on the right margin, checkboxes for sensors that can be selected to be recorded are displayed. The user can select any or all of these. The Position sensor checkbox is not enabled because that is the location (GPS) sensor, which is always recorded in a position (GPS) log.

QML data source GPS position playback and record example
 1Button {
 2    id: livePlaybackButton
 3    enabled: !ServicesManager.dataSourceRecorder.active
 4    anchors.left: parent.left
 5    anchors.bottom: parent.bottom
 6    text: ServicesManager.dataSource.type === DataSource.Type.Live
 7          ? "Live - switch to playback" : "Playback - switch to live"
 8    background: Rectangle {
 9        opacity: parent.hovered ? 1 : 0.5
10        color: enabled ? parent.down ? "#aa00aa" :
11                                       (parent.hovered ? "#0000ff" : "#2000ff") : "#aaaaaa"
12    }
13    palette { buttonText: "#ffffff"; }
14    onClicked: {
15        ServicesManager.dataSource.type =
16                ServicesManager.dataSource.type === DataSource.Type.Live
17                ? DataSource.Type.Playback : DataSource.Type.Live;
18    }
19}

The button to switch between live and playback input data source sets the ServicesManager.dataSource.type qml property to either DataSource.Type.Playback or DataSource.Type.Live

The Live/Playback data source must be selected before recording starts. In a real on the road navigation, the Live data source is selected for GPS log recording. To demonstrate GPS log recording functionality on a desktop computer, a playback data source (.nmea file included in this example) is used, so Playback is selected.

Start recording

 1Button {
 2    id: startStopButton
 3    text: ServicesManager.dataSourceRecorder.active
 4          ? "Stop recording" : "Start recording"
 5    background: Rectangle {
 6        opacity: parent.hovered ? 1 : 0.5
 7        color: enabled ? parent.down ? "#aa00aa" :
 8                                       (parent.hovered ? "#0000ff" : "#2000ff") : "#aaaaaa"
 9    }
10    palette { buttonText: "#ffffff"; }
11    onClicked: {
12        //validate available data types only if switching recording to on
13        if (!ServicesManager.dataSourceRecorder.active) {
14            //position (raw GPS sensor input) is always recorded
15            ServicesManager.dataSourceRecorder.dataSourceTypesToRecord = DataSourceRecorder.Position
16                    | (checkAcceleration.checked ? DataSourceRecorder.Acceleration : 0)
17                    | (checkBattery.checked ? DataSourceRecorder.Battery : 0)
18                    | (checkCamera.checked ? DataSourceRecorder.Camera : 0)
19                    | (checkCompass.checked ? DataSourceRecorder.Compass : 0)
20                    | (checkMagneticField.checked ? DataSourceRecorder.MagneticField : 0)
21                    | (checkOrientation.checked ? DataSourceRecorder.Orientation : 0)
22                    | (checkImprovedPosition.checked ? DataSourceRecorder.ImprovedPosition : 0)
23                    | (checkTemperature.checked ? DataSourceRecorder.Temperature : 0);
24            //clear checkboxes of unavailable datatypes, as those can not be recorded
25            if (!ServicesManager.dataSourceRecorder.isDataTypeAvailable(DataSourceRecorder.Acceleration))
26                checkAcceleration.checked = false;
27            if (!ServicesManager.dataSourceRecorder.isDataTypeAvailable(DataSourceRecorder.Battery))
28                checkBattery.checked = false;
29            if (!ServicesManager.dataSourceRecorder.isDataTypeAvailable(DataSourceRecorder.Camera))
30                checkCamera.checked = false;
31            if (!ServicesManager.dataSourceRecorder.isDataTypeAvailable(DataSourceRecorder.Compass))
32                checkCompass.checked = false;
33            if (!ServicesManager.dataSourceRecorder.isDataTypeAvailable(DataSourceRecorder.MagneticField))
34                checkMagneticField.checked = false;
35            if (!ServicesManager.dataSourceRecorder.isDataTypeAvailable(DataSourceRecorder.Orientation))
36                checkOrientation.checked = false;
37            if (!ServicesManager.dataSourceRecorder.isDataTypeAvailable(DataSourceRecorder.ImprovedPosition))
38                checkImprovedPosition.checked = false;
39            if (!ServicesManager.dataSourceRecorder.isDataTypeAvailable(DataSourceRecorder.Temperature))
40                checkTemperature.checked = false;
41        }
42        //start/stop recording position (GPS) log
43        ServicesManager.dataSourceRecorder.active = !ServicesManager.dataSourceRecorder.active;
44    }
45}

Then click Follow position so the camera follows the green position arrow, and click Start recording to start the GPS logger.

Before recording actually starts, the sensors for the selected checkboxes are validated to verify their availability. Those sensors that are not available for recording on the current device, are automatically unchecked.

The available sensors from the user selected list of sensors are then OR-ed together in an int bitfield which is then set into the ServicesManager.dataSourceRecorder.dataSourceTypesToRecord property.

The checkboxes are disabled while recording is active because it is not possible to change the recorded datasources while recording. To do that, stop recording first, then select the desired datasources.

Recording is started by setting the ServicesManager.dataSourceRecorder.active property to true, and is stopped by setting this property to false. While recording is active, it is not possible to change data sources (live/playback) or recorded data types, so those controls are disabled. The live/playback button is enabled/disabled using its id and the enabled property: livePlaybackButton.enabled

Follow position

QML data source GPS position playback and record example
 1Button {
 2    anchors.right: parent.right
 3    anchors.bottom: parent.bottom
 4    text: qsTr("Follow position")
 5    enabled: !mapView.followingPosition
 6    background: Rectangle {
 7        opacity: parent.hovered ? 1 : 0.5
 8        color: enabled ? parent.down ? "#aa00aa" :
 9                                       (parent.hovered ? "#0000ff" : "#2000ff") : "#aaaaaa"
10    }
11    palette { buttonText: "#ffffff"; }
12    onClicked: mapView.followingPosition = true
13}

The follow position button is enabled only if the camera is not already following the green position arrow on the map.

Follow position means that the camera flies to the position of the green arrow and then follows the simulated position arrow. This is necessary, as the arrow is likely to be located elsewhere on the map, not at the current location of the camera.

The green position arrow plays back the previously recorded positions on the map, from the data source specified above.

If the map is panned/dragged to one side, the camera no longer follows the green position arrow, and the Follow position button is activated again, so it can be clicked to resume following the position arrow.

Playback speed

QML data source GPS position playback and record example
 1Button {
 2    text: ServicesManager.dataSource.playbackSpeedMultiplier == 9
 3          ? "Slower playback" : "Faster playback"
 4    background: Rectangle {
 5        opacity: parent.hovered ? 1 : 0.5
 6        color: enabled ? parent.down ? "#aa00aa" :
 7                                       (parent.hovered ? "#0000ff" : "#2000ff") : "#aaaaaa"
 8    }
 9    palette { buttonText: "#ffffff"; }
10    onClicked: {
11        ServicesManager.dataSource.playbackSpeedMultiplier =
12                ServicesManager.dataSource.playbackSpeedMultiplier == 9 ? 1 : 9;
13    }
14}

The faster/slower playback button toggles the playback speed between 1x (normal) and 9x (visibly fast).

Next, click Faster playback to see that the simulation runs faster.

QML data source GPS position playback and record example

Click Slower playback to see that the simulation runs again at normal speed.

Stop and save recording

QML data source GPS position playback and record example

Click Stop recording after at least 1 minute elapsed after Start recording was clicked, or after the playback ends, to save the recorded GPS log. Recordings shorter than 1 minute are not saved.

The GPS log file has a .gm extension and is saved in this directory: ~/.local/share/APPNAME/ where APPNAME in this case is the name of this example, RecordGPSPositionLog The .gm file can be used as playback input just like an .nmea GPS log file.

Implementation details

The MapView interactive map has these settings for display and user touch input:

 1id: mapView
 2anchors.fill: parent
 3viewAngle: 25
 4zoomLevel: 69
 5viewPerspective: MapView.ViewPerspective.View3D
 6buildingsVisibility: MapView.BuildingsVisibility.Show3D
 7detailsQualityLevel: MapView.DetailsQualityLevel.Medium
 8gestures: MapView.Gesture.Pan
 9    | MapView.Gesture.PanEnableVelocity
10    | MapView.Gesture.Pinch
11    | MapView.Gesture.Rotate
12    | MapView.Gesture.Tilt

anchors.fill: parent causes the map to fill the containing viewport, which is Window in this case. The zoomLevel has a higher value, the closer the camera is to the ground.

1Text {
2   anchors.right: parent.right
3   anchors.top: parent.top
4   text: fpsCounter.fps
5}

The frames-per-second (fps) counter is displayed in the top right corner of the map.

1<RCC>
2   <qresource prefix="/">
3      <file>main.qml</file>
4      <file>strasbourg.nmea</file>
5   </qresource>
6</RCC>

The qml.qrc file lists the strasbourg.nmea GPS position log file.

QML Examples

Maps SDK for Qt Examples can be downloaded or cloned with Git