Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions app/position/providers/androidpositionprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,19 @@ void jniOnPositionUpdated( JNIEnv *env, jclass clazz, jint instanceId, jobject l

if ( location.callMethod<jboolean>( "hasAltitude" ) )
{
const jdouble value = location.callMethod<jdouble>( "getAltitude" );
if ( !qFuzzyIsNull( value ) )
const jdouble ellipsoidHeight = location.callMethod<jdouble>( "getAltitude" );
if ( !qFuzzyIsNull( ellipsoidHeight ) )
{
// transform the altitude from EPSG:4979 (WGS84 (EPSG:4326) + ellipsoidal height) to specified geoid model
const QgsPoint geoidPosition = InputUtils::transformPoint(
PositionKit::positionCrs3DEllipsoidHeight(),
PositionKit::positionCrs3D(),
QgsProject::instance()->transformContext(),
{longitude, latitude, value} );
{longitude, latitude, ellipsoidHeight} );
pos.elevation = geoidPosition.z();

const double geoidSeparation = ellipsoidHeight - geoidPosition.z();
pos.elevation_diff = geoidSeparation;
}
}

Expand Down
24 changes: 18 additions & 6 deletions app/position/providers/bluetoothpositionprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,11 +204,23 @@ void BluetoothPositionProvider::positionUpdateReceived()
// we know the connection is working because we just received data from the device
setState( tr( "Connected" ), State::Connected );

QByteArray rawNmea = mSocket->readAll();
QString nmea( rawNmea );

QgsGpsInformation data = mNmeaParser.parseNmeaString( nmea );

emit positionChanged( GeoPosition::fromQgsGpsInformation( data ) );
const QByteArray rawNmea = mSocket->readAll();
const QString nmea( rawNmea );

const QgsGpsInformation data = mNmeaParser.parseNmeaString( nmea );
GeoPosition positionData = GeoPosition::fromQgsGpsInformation( data );

// The geoid models used in GNSS devices can be often times unreliable, thus we apply the transformations ourselves
// GNSS supplied orthometric elevation -> ellipsoid elevation -> orthometric elevation based on our model
const double ellipsoidElevation = positionData.elevation + positionData.elevation_diff;
const QgsPoint geoidPosition = InputUtils::transformPoint(
PositionKit::positionCrs3DEllipsoidHeight(),
PositionKit::positionCrs3D(),
QgsProject::instance()->transformContext(),
{positionData.longitude, positionData.latitude, ellipsoidElevation} );
positionData.elevation = geoidPosition.z();
positionData.elevation_diff = ellipsoidElevation - geoidPosition.z();

emit positionChanged( positionData );
}
}
14 changes: 14 additions & 0 deletions app/position/providers/internalpositionprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,20 @@ void InternalPositionProvider::parsePositionUpdate( const QGeoPositionInfo &posi
positionDataHasChanged = true;
}

// QGeoCoordinate::altitude() docs claim that it is above the sea level (i.e. geoid) altitude,
// but that's not really true in our case:
// - on Android - it is MSL altitude only if "useMslAltitude" parameter is passed to the Android
// Qt positioning plugin, which we don't do - see https://doc.qt.io/qt-6/position-plugin-android.html
// - on iOS - it would return MSL altitude, but we have a custom patch in vcpkg to return
// ellipsoid altitude (so we do not rely on geoid model of unknown quality/resolution)
const double ellipsoidAltitude = position.coordinate().altitude();
const double geoidSeparation = ellipsoidAltitude - geoidPosition.z();
if ( !qgsDoubleNear( geoidSeparation, mLastPosition.elevation_diff ) )
{
mLastPosition.elevation_diff = geoidSeparation;
positionDataHasChanged = true;
}

bool hasSpeedInfo = position.hasAttribute( QGeoPositionInfo::GroundSpeed );
if ( hasSpeedInfo && !qgsDoubleNear( position.attribute( QGeoPositionInfo::GroundSpeed ), mLastPosition.speed ) )
{
Expand Down
49 changes: 36 additions & 13 deletions app/position/providers/simulatedpositionprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,30 @@
***************************************************************************/

#include "simulatedpositionprovider.h"

#include <memory>
#include <QtNumeric>

#include "inpututils.h"
#include "qgspoint.h"

SimulatedPositionProvider::SimulatedPositionProvider( double longitude, double latitude, double flightRadius, double timerTimeout, QObject *parent )
SimulatedPositionProvider::SimulatedPositionProvider( const double longitude, const double latitude, const double flightRadius, const double updateTimeout, QObject *parent )
: AbstractPositionProvider( QStringLiteral( "simulated" ), QStringLiteral( "internal" ), QStringLiteral( "Simulated provider" ), parent )
, mTimer( new QTimer() )
, mLongitude( longitude )
, mLatitude( latitude )
, mFlightRadius( flightRadius )
, mTimerTimeout( timerTimeout )
, mTimerTimeout( updateTimeout )
{
std::random_device seed;
mGenerator = std::unique_ptr<std::mt19937>( new std::mt19937( seed() ) );
mGenerator = std::make_unique<std::mt19937>( seed() );

connect( mTimer.get(), &QTimer::timeout, this, &SimulatedPositionProvider::generateNextPosition );

SimulatedPositionProvider::startUpdates();
}

void SimulatedPositionProvider::setUpdateInterval( double msecs )
void SimulatedPositionProvider::setUpdateInterval( const double msecs )
{
stopUpdates();
mTimerTimeout = msecs;
Expand All @@ -37,7 +42,7 @@ SimulatedPositionProvider::~SimulatedPositionProvider() = default;

void SimulatedPositionProvider::startUpdates()
{
mTimer->start( mTimerTimeout );
mTimer->start( static_cast<int>( mTimerTimeout ) );
generateNextPosition();
}

Expand All @@ -51,7 +56,7 @@ void SimulatedPositionProvider::closeProvider()
mTimer->stop();
}

void SimulatedPositionProvider::setPosition( QgsPoint position )
void SimulatedPositionProvider::setPosition( const QgsPoint position )
{
if ( position.isEmpty() )
return;
Expand Down Expand Up @@ -84,16 +89,27 @@ void SimulatedPositionProvider::generateRadiusPosition()
position.latitude = latitude;
position.longitude = longitude;

double altitude = ( *mGenerator )() % 40 + 20; // rand altitude <20,55>m and lost (0)
if ( altitude <= 55 )
double ellipsoidAltitude = ( *mGenerator )() % 40 + 80; // rand altitude <80,115>m and lost (NaN)
if ( ellipsoidAltitude <= 115 )
{
const QgsPoint geoidPosition = InputUtils::transformPoint(
PositionKit::positionCrs3DEllipsoidHeight(),
PositionKit::positionCrs3D(),
QgsCoordinateTransformContext(),
{longitude, latitude, ellipsoidAltitude} );
position.elevation = geoidPosition.z();
position.elevation_diff = ellipsoidAltitude - position.elevation;
}
else
{
position.elevation = altitude;
position.elevation = qQNaN();
position.elevation_diff = qQNaN();
}

QDateTime timestamp = QDateTime::currentDateTime();
const QDateTime timestamp = QDateTime::currentDateTime();
position.utcDateTime = timestamp;

position.direction = 360 - int( mAngle ) % 360;
position.direction = 360 - static_cast<int>( mAngle ) % 360;

int accuracy = ( *mGenerator )() % 40; // rand accuracy <0,35>m and lost (-1)
if ( accuracy > 35 )
Expand All @@ -115,9 +131,16 @@ void SimulatedPositionProvider::generateConstantPosition()
GeoPosition position;
position.latitude = mLatitude;
position.longitude = mLongitude;
position.elevation = 20;
// we take 100 as elevation returned by WGS84 ellipsoid and recalculate it to geoid
const QgsPoint geoidPosition = InputUtils::transformPoint(
PositionKit::positionCrs3DEllipsoidHeight(),
PositionKit::positionCrs3D(),
QgsCoordinateTransformContext(),
{mLongitude, mLatitude, 100} );
position.elevation = geoidPosition.z();
position.elevation_diff = 100 - position.elevation;
position.utcDateTime = QDateTime::currentDateTime();
position.direction = 360 - int( mAngle ) % 360;
position.direction = 360 - static_cast<int>( mAngle ) % 360;
position.hacc = ( *mGenerator )() % 20;
position.satellitesUsed = ( *mGenerator )() % 30;
position.satellitesVisible = ( *mGenerator )() % 30;
Expand Down
12 changes: 6 additions & 6 deletions app/position/providers/simulatedpositionprovider.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,16 @@ class SimulatedPositionProvider : public AbstractPositionProvider
double updateTimeout = 1000,
QObject *parent = nullptr
);
virtual ~SimulatedPositionProvider() override;
~SimulatedPositionProvider() override;

virtual void setUpdateInterval( double msecs ) override;
void setUpdateInterval( double msecs ) override;

public slots:
virtual void startUpdates() override;
virtual void stopUpdates() override;
virtual void closeProvider() override;
void startUpdates() override;
void stopUpdates() override;
void closeProvider() override;

virtual void setPosition( QgsPoint position ) override;
void setPosition( QgsPoint position ) override;

void generateNextPosition();

Expand Down
4 changes: 2 additions & 2 deletions app/qml/gps/MMGpsDataDrawer.qml
Original file line number Diff line number Diff line change
Expand Up @@ -323,10 +323,10 @@ MMComponents.MMDrawer {

title: qsTr( "Geoid separation" )
value: {
if ( !__positionKit.hasPosition || Number.isNaN( __positionKit.geoidSeparation ) ) {
if ( !PositionKit.hasPosition || Number.isNaN( PositionKit.geoidSeparation ) ) {
return qsTr( "N/A" )
}
__inputUtils.formatNumber( __positionKit.geoidSeparation, 2 ) + " m"
__inputUtils.formatNumber( PositionKit.geoidSeparation, 2 ) + " m"
}

alignmentRight: Positioner.index % 2 === 1
Expand Down
5 changes: 2 additions & 3 deletions app/test/testposition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -396,8 +396,7 @@ void TestPosition::testPositionTracking()
QSignalSpy trackingSpy( &manager, &PositionTrackingManager::trackedGeometryChanged );

trackingSpy.wait( 4000 ); // new position should be emited in 2k ms

QVERIFY( manager.trackedGeometry().asWkt( 3 ).startsWith( QStringLiteral( "LineString ZM (-92.36 38.93 20" ) ) );
QVERIFY( manager.trackedGeometry().asWkt( 3 ).startsWith( QStringLiteral( "LineString ZM (-92.36 38.93 133.331" ) ) );

// store the geometry
QgsVectorLayer *trackingLayer = QgsProject::instance()->mapLayer<QgsVectorLayer *>( "tracking_layer_aad89df7_21db_466e_b5c1_a80160f74c01" );
Expand All @@ -411,7 +410,7 @@ void TestPosition::testPositionTracking()

int addedFid = addedSpy.at( 1 ).at( 0 ).toInt();
QgsFeature f = trackingLayer->getFeature( addedFid );
QVERIFY( f.geometry().asWkt( 3 ).startsWith( QStringLiteral( "LineString ZM (-92.36 38.93 20" ) ) );
QVERIFY( f.geometry().asWkt( 3 ).startsWith( QStringLiteral( "LineString ZM (-92.36 38.93 133.331" ) ) );

QString datetimeFormat = QStringLiteral( "dd.MM.yyyy hh:mm:ss" );
QString dateTrackingStartedFromManager = manager.startTime().toString( datetimeFormat );
Expand Down
Loading