Skip to content
Permalink
Browse files

[feature][gps] Add option to calculate bearing based on travel direction

For devices which report faulty bearing measurements, this option can
be used to instead calculate the GPS bearing based on the previous
two recorded locations
  • Loading branch information
nyalldawson committed Jun 19, 2020
1 parent 66ce30c commit 847295758cadfd684c8a7a576788ed9289e53d34
@@ -254,6 +254,7 @@ QgsGpsInformationWidget::QgsGpsInformationWidget( QgsMapCanvas *mapCanvas, QWidg
// Restore state

mGroupShowMarker->setChecked( mySettings.value( QStringLiteral( "gps/showMarker" ), "true" ).toBool() );
mTravelBearingCheckBox->setChecked( mySettings.value( QStringLiteral( "gps/calculateBearingFromTravel" ), "false" ).toBool() );
mSliderMarkerSize->setValue( mySettings.value( QStringLiteral( "gps/markerSize" ), "12" ).toInt() );
mSpinTrackWidth->setValue( mySettings.value( QStringLiteral( "gps/trackWidth" ), "2" ).toInt() );
mBtnTrackColor->setColor( mySettings.value( QStringLiteral( "gps/trackColor" ), QColor( Qt::red ) ).value<QColor>() );
@@ -452,6 +453,7 @@ QgsGpsInformationWidget::~QgsGpsInformationWidget()
mySettings.setValue( QStringLiteral( "gps/trackColor" ), mBtnTrackColor->color() );
mySettings.setValue( QStringLiteral( "gps/markerSize" ), mSliderMarkerSize->value() );
mySettings.setValue( QStringLiteral( "gps/showMarker" ), mGroupShowMarker->isChecked() );
mySettings.setValue( QStringLiteral( "gps/calculateBearingFromTravel" ), mTravelBearingCheckBox->isChecked() );
mySettings.setValue( QStringLiteral( "gps/autoAddVertices" ), mCbxAutoAddVertices->isChecked() );
mySettings.setValue( QStringLiteral( "gps/autoCommit" ), mCbxAutoCommit->isChecked() );
mySettings.setValue( QStringLiteral( "gps/acquisitionInterval" ), mCboAcquisitionInterval->currentText() );
@@ -959,6 +961,7 @@ void QgsGpsInformationWidget::displayGPSInformation( const QgsGpsInformation &in
// Avoid refreshing / panning if we haven't moved
if ( mLastGpsPosition != myNewCenter )
{
mSecondLastGpsPosition = mLastGpsPosition;
mLastGpsPosition = myNewCenter;
mLastNmeaPosition = newNmeaPosition;
mLastNmeaTime = newNmeaTime;
@@ -999,26 +1002,36 @@ void QgsGpsInformationWidget::displayGPSInformation( const QgsGpsInformation &in
updateGpsDistanceStatusMessage();
}

if ( !std::isnan( info.direction ) )
if ( !std::isnan( info.direction ) || ( mTravelBearingCheckBox->isChecked() && !mSecondLastGpsPosition.isEmpty() ) )
{
double trueNorth = 0;
QgsSettings settings;
if ( settings.value( QStringLiteral( "gps/correctForTrueNorth" ), false, QgsSettings::App ).toBool() )
double bearing = 0;
double trueNorth = 0;
if ( !mTravelBearingCheckBox->isChecked() )
{
try
{
trueNorth = QgsBearingUtils::bearingTrueNorth( mMapCanvas->mapSettings().destinationCrs(), QgsProject::instance()->transformContext(), mMapCanvas->mapSettings().visibleExtent().center() );
}
catch ( QgsException & )
bearing = info.direction;
if ( settings.value( QStringLiteral( "gps/correctForTrueNorth" ), false, QgsSettings::App ).toBool() )
{
try
{
trueNorth = QgsBearingUtils::bearingTrueNorth( mMapCanvas->mapSettings().destinationCrs(), QgsProject::instance()->transformContext(), mMapCanvas->mapSettings().visibleExtent().center() );
}
catch ( QgsException & )
{

}
}
}
else
{
bearing = 180 * mDistanceCalculator.bearing( mSecondLastGpsPosition, mLastGpsPosition ) / M_PI;
}

const double adjustment = settings.value( QStringLiteral( "gps/bearingAdjustment" ), 0.0, QgsSettings::App ).toDouble();

if ( mRotateMapCheckBox->isChecked() && ( !mLastRotateTimer.isValid() || mLastRotateTimer.hasExpired( mSpinMapRotateInterval->value() * 1000 ) ) )
{
mMapCanvas->setRotation( trueNorth - info.direction - adjustment );
mMapCanvas->setRotation( trueNorth - bearing - adjustment );
mLastRotateTimer.restart();
}

@@ -1031,7 +1044,7 @@ void QgsGpsInformationWidget::displayGPSInformation( const QgsGpsInformation &in
}

mMapBearingItem->setGpsPosition( myNewCenter );
mMapBearingItem->setGpsBearing( info.direction - trueNorth + adjustment );
mMapBearingItem->setGpsBearing( bearing - trueNorth + adjustment );
}
else if ( mMapBearingItem )
{
@@ -136,6 +136,7 @@ class APP_EXPORT QgsGpsInformationWidget: public QgsPanelWidget, public QgsMapCa
// not used QPointF gpsToPixelPosition( const QgsPoint& point );
QgsRubberBand *mRubberBand = nullptr;
QgsPointXY mLastGpsPosition;
QgsPointXY mSecondLastGpsPosition;
QVector<QgsPoint> mCaptureList;
double mLastElevation = 0.0;
FixStatus mLastFixStatus;
@@ -157,8 +157,8 @@ gray = no data
<rect>
<x>0</x>
<y>0</y>
<width>121</width>
<height>488</height>
<width>114</width>
<height>504</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_2">
@@ -577,9 +577,9 @@ gray = no data
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>306</width>
<height>1000</height>
<y>-425</y>
<width>315</width>
<height>1183</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_7">
@@ -631,7 +631,7 @@ gray = no data
<item row="0" column="0">
<widget class="QLineEdit" name="mTxtLogFile">
<property name="enabled">
<bool>true</bool>
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
@@ -650,7 +650,7 @@ gray = no data
<item row="0" column="1">
<widget class="QPushButton" name="mBtnLogFile">
<property name="enabled">
<bool>true</bool>
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
@@ -727,20 +727,10 @@ gray = no data
<property name="spacing">
<number>2</number>
</property>
<item row="0" column="0">
<widget class="QRadioButton" name="mRadAutodetect">
<property name="text">
<string>Autodetect</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QRadioButton" name="mRadUserPath">
<item row="1" column="0">
<widget class="QRadioButton" name="mRadInternal">
<property name="text">
<string>Serial device</string>
<string>Internal</string>
</property>
</widget>
</item>
@@ -778,6 +768,16 @@ gray = no data
</item>
</layout>
</item>
<item row="0" column="0">
<widget class="QRadioButton" name="mRadAutodetect">
<property name="text">
<string>Autodetect</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="5" column="0">
<layout class="QGridLayout" name="gridLayout_12">
<property name="leftMargin">
@@ -870,10 +870,10 @@ gray = no data
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QRadioButton" name="mRadInternal">
<item row="2" column="0">
<widget class="QRadioButton" name="mRadUserPath">
<property name="text">
<string>Internal</string>
<string>Serial device</string>
</property>
</widget>
</item>
@@ -939,7 +939,7 @@ gray = no data
</widget>
</item>
<item row="2" column="1">
<widget class="QgsColorButton" name="mBtnTrackColor">
<widget class="QgsColorButton" name="mBtnTrackColor" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
@@ -949,7 +949,7 @@ gray = no data
<property name="styleSheet">
<string/>
</property>
<property name="text">
<property name="text" stdset="0">
<string/>
</property>
</widget>
@@ -986,30 +986,30 @@ gray = no data
<item row="0" column="1">
<widget class="QgsFieldComboBox" name="mCboTimestampField"/>
</item>
<item row="1" column="0">
<item row="2" column="0">
<widget class="QLabel" name="mLblTimestampFormat">
<property name="text">
<string>Format</string>
</property>
</widget>
</item>
<item row="1" column="1">
<item row="2" column="1">
<widget class="QComboBox" name="mCboTimestampFormat"/>
</item>
<item row="2" column="0">
<item row="3" column="0">
<widget class="QLabel" name="mLblTimeZone">
<property name="text">
<string>Timezone</string>
</property>
</widget>
</item>
<item row="2" column="1">
<item row="3" column="1">
<widget class="QComboBox" name="mCboTimeZones"/>
</item>
<item row="3" column="1">
<item row="4" column="1">
<widget class="QSpinBox" name="mLeapSeconds"/>
</item>
<item row="3" column="0">
<item row="4" column="0">
<widget class="QCheckBox" name="mCbxLeapSeconds">
<property name="toolTip">
<string>Apply leap seconds correction by adding the seconds to GPS timestamp</string>
@@ -1022,6 +1022,16 @@ gray = no data
</layout>
</widget>
</item>
<item row="3" column="0">
<widget class="QCheckBox" name="mTravelBearingCheckBox">
<property name="toolTip">
<string>If checked, the bearing reported by the GPS device will be ignored and the bearing will instead be calculated by the angle between the previous two GPS locations</string>
</property>
<property name="text">
<string>Calculate bearing from travel direction</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
@@ -1119,7 +1129,7 @@ gray = no data
</widget>
</item>
<item>
<widget class="QgsSpinBox" name="mSpinMapRotateInterval">
<widget class="QgsSpinBox" name="mSpinMapRotateInterval" native="true">
<property name="enabled">
<bool>false</bool>
</property>
@@ -1129,22 +1139,22 @@ gray = no data
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="specialValueText">
<property name="specialValueText" stdset="0">
<string>On GPS signal</string>
</property>
<property name="suffix">
<property name="suffix" stdset="0">
<string> s</string>
</property>
<property name="minimum">
<property name="minimum" stdset="0">
<number>0</number>
</property>
<property name="maximum">
<property name="maximum" stdset="0">
<number>1000</number>
</property>
<property name="singleStep">
<property name="singleStep" stdset="0">
<number>1</number>
</property>
<property name="value">
<property name="value" stdset="0">
<number>0</number>
</property>
</widget>
@@ -1483,6 +1493,17 @@ gray = no data
<class>QgsPanelWidget</class>
<extends>QWidget</extends>
<header>qgspanelwidget.h</header>
<container>1</container>
</customwidget>
<customwidget>
<class>QgsColorButton</class>
<extends>QWidget</extends>
<header>qgscolorbutton.h</header>
</customwidget>
<customwidget>
<class>QgsSpinBox</class>
<extends>QWidget</extends>
<header>qgsspinbox.h</header>
</customwidget>
</customwidgets>
<tabstops>

0 comments on commit 8472957

Please sign in to comment.
You can’t perform that action at this time.