Skip to content

Commit

Permalink
Fix/160 gpx export elevation data inconsistency (#162)
Browse files Browse the repository at this point in the history
* FIX: GPX: Export the <ele> as "above mean sea level"

- Properly initialise and export the trackpoint time (as ISO 8601
format, including timezone "Z")

Other:
- Use "auto" type

* Explicityl set time zone to UTC

- In order such that the time zone gets exported in toString() (as "Z")
  • Loading branch information
till213 authored Jul 9, 2024
1 parent 0048fc6 commit f81a678
Show file tree
Hide file tree
Showing 60 changed files with 360 additions and 240 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,14 @@
* Few users were probably aware of what this "Recording Frequency" settings was supposed to do and left it at "auto"
* Removing the timer-based recording also simplified the code
- The Statistics dialog now shows separate recording rates, for both positition (always around 1 Hz) and attitude samples (e.g. 30 Hz, that is the *simulation frame* rate)
- GPX export: the geoid height (&lt;geoidheight&gt;) can now also optionally be exported
* This may be useful to calculate the ellipsoidial height *h* ([WGS84 reference ellipsoid](https://en.wikipedia.org/wiki/World_Geodetic_System#WGS_84)) as follows: h = H + N = &lt;ele&gt; + &lt;geoidheight&gt;
* Also refer to [Find Ellipsoidal Height from Orthometric Height](https://www.mathworks.com/help/map/ellipsoid-geoid-and-orthometric-height.html)

## Bug Fixes
- GPX export
* The elevation (&lt;ele&gt;) values are now properly exported as "above mean sea level" (and not "above WGS84 reference ellipsoid" anymore)
* The trackpoint timestamps are properly calculated and exported when exporting the entire flight (and not just the user aircraft); the proper timezone suffix (Z) is appended, too (ISO 8601 format)

## 0.17.5
This bug fix release provides an important correction for a regression that would prevent recording (and possibly replay as well), due to wrongly creating an IPv4 network connection instead of a local ("pipe") connection.
Expand Down
54 changes: 29 additions & 25 deletions src/Kernel/include/Kernel/Convert.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,26 +57,27 @@ class KERNEL_API Convert final
~Convert();

/*!
* Converts the \c height height above WGS84 reference ellipsoid to height above the earth
* Converts the \p height above WGS84 reference ellipsoid to height above the earth
* gravity model (EGM) geoid according to the installed EGM data file. The conversion is
* essentially evaluating the so-called undulation at position \c latitude, \c longitude
* and adjusting the given \c height accordingly.
* essentially evaluating the so-called undulation at position \p latitude, \p longitude
* and adjusting the given \p height accordingly.
*
* If no EGM data file is available (not installed, not readable) then simply
* \c meters is returned.
* \p meters is returned.
*
* Also refer to https://gisgeography.com/geoid-mean-sea-level/
* Also refer to https://gisgeography.com/geoid-mean-sea-level/ and
* https://www.mathworks.com/help/map/ellipsoid-geoid-and-orthometric-height.html
*
* \param height
* the altitude to convert [meters]
* \param latitude
* the latitude of the position
* \param longitude
* the longitude of the position
* \return the converted altitude in meters above the EGM geoid; or \c height if no EGM data
* \return the converted altitude in meters above the EGM geoid; or \p height if no EGM data
* file could be read
*/
inline double wgs84ToEgmGeoid(double height, double latitude, double longitude) noexcept
inline double ellipsoidToGeoidHeight(double height, double latitude, double longitude) noexcept
{
// In meters
double heightAboveGeoid {0.0};
Expand All @@ -98,26 +99,29 @@ class KERNEL_API Convert final
}

/*!
* Converts the \c height height above the EGM geoid to height above the WGS84 reference
* Converts the \p height above the EGM geoid to height above the WGS84 reference
* ellipsoid according to the installed EGM data file. The conversion is
* essentially evaluating the so-called undulation at position \c latitude, \c longitude
* and adjusting the given \c height accordingly.
* essentially evaluating the so-called undulation at position \p latitude, \p longitude
* and adjusting the given \p height accordingly.
*
* When setting the \p height to 0 the so-called geoid height is returned.
*
* If no EGM data file is available (not installed, not readable) then simply
* \c meters is returned.
* \p height is returned.
*
* Also refer to https://gisgeography.com/wgs84-world-geodetic-system/
* Also refer to https://gisgeography.com/wgs84-world-geodetic-system/ and
* https://www.mathworks.com/help/map/ellipsoid-geoid-and-orthometric-height.html
*
* \param height
* the altitude to convert [meters]
* \param latitude
* the latitude of the position
* \param longitude
* the longitude of the position
* \return the converted altitude in meters above the WGS84 reference ellipsoid; or \c height
* \return the converted altitude in meters above the WGS84 reference ellipsoid; or \p height
* if no EGM data file could be read
*/
inline double egmToWgs84Ellipsoid(double height, double latitude, double longitude) noexcept
inline double geoidToEllipsoidHeight(double height, double latitude, double longitude) noexcept
{
// In meters
double heightAboveEllipsoid {height};
Expand All @@ -141,7 +145,7 @@ class KERNEL_API Convert final
};

/*!
* Converts the \c radians to degrees.
* Converts the \p radians to degrees.
*
* \param radians
* the radians to convert
Expand All @@ -152,9 +156,9 @@ class KERNEL_API Convert final
};

/*!
* Converts the \c feet to meters.
* Converts the \p feet to meters.
*
* \return the \c feet converted to meters
* \return the \p feet converted to meters
* \sa https://www.convertunits.com/from/feet/to/meter
*/
static constexpr double feetToMeters(double feet) noexcept
Expand All @@ -163,9 +167,9 @@ class KERNEL_API Convert final
}

/*!
* Converts the \c meters to feet.
* Converts the \p meters to feet.
*
* \return the \c meters converted to feet
* \return the \p meters converted to feet
* \sa https://www.convertunits.com/from/meter/to/feet
*/
static constexpr double metersToFeet(double meters) noexcept
Expand All @@ -174,7 +178,7 @@ class KERNEL_API Convert final
}

/*!
* Converts the \c feetPerSecond to knots.
* Converts the \p feetPerSecond to knots.
*
* \param feetPerSecond
* the feet per second to convert
Expand All @@ -187,7 +191,7 @@ class KERNEL_API Convert final
}

/*!
* Converts \c knots to feet per second.
* Converts \p knots to feet per second.
*
* \param knots
* the knots to convert
Expand All @@ -200,7 +204,7 @@ class KERNEL_API Convert final
}

/*!
* Converts the \c knots to meters per second.
* Converts the \p knots to meters per second.
*
* \param knots
* the knots to convert
Expand All @@ -213,7 +217,7 @@ class KERNEL_API Convert final
}

/*!
* Converts the \c metersPerSecond to knots.
* Converts the \p metersPerSecond to knots.
*
* \param metersPerSecond
* the meters per second to convert
Expand All @@ -226,7 +230,7 @@ class KERNEL_API Convert final
}

/*!
* Converts the \c feetPerSecond to km/h.
* Converts the \p feetPerSecond to km/h.
*
* \param feetPerSecond
* the feet per second to convert
Expand All @@ -239,7 +243,7 @@ class KERNEL_API Convert final
}

/*!
* Converts the \c metersPerSecond to feet/s.
* Converts the \p metersPerSecond to feet/s.
*
* \param metersPerSecond
* the meters per second to convert
Expand Down
2 changes: 1 addition & 1 deletion src/Kernel/include/Kernel/SkyMath.h
Original file line number Diff line number Diff line change
Expand Up @@ -581,7 +581,7 @@ namespace SkyMath
// Same date
fromDateTimeUtc.setDate(toDateTimeUtc.date());
fromDateTimeUtc.setTime(fromDateTime.toUTC().time());
fromDateTimeUtc.setTimeZone(QTimeZone::utc());
fromDateTimeUtc.setTimeZone(QTimeZone::UTC);
break;
case TimeOffsetSync::None:
fromDateTimeUtc = toDateTimeUtc;
Expand Down
2 changes: 1 addition & 1 deletion src/Model/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ target_sources(${LIBRARY_NAME}
include/Model/AbstractComponent.h
include/Model/Flight.h src/Flight.cpp
include/Model/FlightData.h
include/Model/FlightSummary.h
include/Model/FlightSummary.h src/FlightSummary.cpp
include/Model/FlightDate.h src/FlightDate.cpp
include/Model/FlightCondition.h src/FlightCondition.cpp
include/Model/Aircraft.h src/Aircraft.cpp
Expand Down
2 changes: 2 additions & 0 deletions src/Model/include/Model/FlightCondition.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ struct MODEL_API FlightCondition final
bool onAnyRunway {false};
bool onParkingSpot {false};

FlightCondition() noexcept;

void clear() noexcept;
};

Expand Down
2 changes: 2 additions & 0 deletions src/Model/include/Model/FlightSummary.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ struct MODEL_API FlightSummary final
QString startLocation;
QString endLocation;
QString title;

FlightSummary() noexcept;
};

#endif // FLIGHTSUMMARY_H
2 changes: 1 addition & 1 deletion src/Model/include/Model/PositionData.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ struct MODEL_API PositionData final : public TimeVariableData
// Position
double latitude {0.0};
double longitude {0.0};
// GPS altitude
// Above mean sea level (MSL) altitude ("true altitude")
double altitude {0.0};
// Indicated pressure altitude (analytical purposes only)
double indicatedAltitude {0.0};
Expand Down
4 changes: 2 additions & 2 deletions src/Model/src/Flight.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,7 @@ void Flight::setFlightCondition(FlightCondition flightCondition) noexcept
FlightSummary Flight::getFlightSummary() const noexcept
{
const auto &aircraft = getUserAircraft();
const AircraftInfo &aircraftInfo = aircraft.getAircraftInfo();
const auto &aircraftInfo = aircraft.getAircraftInfo();

FlightSummary summary;
summary.flightId = d->flightData.id;
Expand All @@ -288,7 +288,7 @@ FlightSummary Flight::getFlightSummary() const noexcept
summary.endSimulationLocalTime = d->flightData.flightCondition.endLocalDateTime;
summary.endSimulationZuluTime = d->flightData.flightCondition.endZuluDateTime;

const FlightPlan &flightPlan = aircraft.getFlightPlan();
const auto &flightPlan = aircraft.getFlightPlan();
if (flightPlan.count() > 0) {
summary.startLocation = flightPlan[0].identifier;
}
Expand Down
9 changes: 9 additions & 0 deletions src/Model/src/FlightCondition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,19 @@
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include <QDateTime>
#include <QTimeZone>

#include "FlightCondition.h"

// PUBLIC

FlightCondition::FlightCondition() noexcept
{
startZuluDateTime.setTimeZone(QTimeZone::UTC);
endZuluDateTime.setTimeZone(QTimeZone::UTC);
}

void FlightCondition::clear() noexcept
{
*this = FlightCondition();
Expand Down
2 changes: 1 addition & 1 deletion src/Model/src/FlightPlan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ void FlightPlan::add(Waypoint waypoint) noexcept

void FlightPlan::update(int index, const Waypoint &waypoint) noexcept
{
Waypoint currentWaypoint = d->waypoints.at(index);
auto currentWaypoint = d->waypoints.at(index);
bool changed = false;
if (index >= 0 && index < static_cast<int>(d->waypoints.size())) {
if (currentWaypoint.timestamp != waypoint.timestamp) {
Expand Down
36 changes: 36 additions & 0 deletions src/Model/src/FlightSummary.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/**
* Sky Dolly - The Black Sheep for Your Flight Recordings
*
* Copyright (c) Oliver Knoll
* All rights reserved.
*
* MIT License
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of this
* software and associated documentation files (the "Software"), to deal in the Software
* without restriction, including without limitation the rights to use, copy, modify, merge,
* publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
* to whom the Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all copies or
* substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
* PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
* FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include <QDateTime>
#include <QTimeZone>

#include "FlightSummary.h"

// PUBLIC

FlightSummary::FlightSummary() noexcept
{
startSimulationZuluTime.setTimeZone(QTimeZone::UTC);
endSimulationZuluTime.setTimeZone(QTimeZone::UTC);
}
7 changes: 6 additions & 1 deletion src/Model/src/Waypoint.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#include <QDateTime>
#include <QTimeZone>

#include "Waypoint.h"

// PUBLIC
Expand All @@ -31,7 +34,9 @@ Waypoint::Waypoint(float latitude, float longitude, float altitude) noexcept
latitude(latitude),
longitude(longitude),
altitude(altitude)
{}
{
zuluTime.setTimeZone(QTimeZone::UTC);
}

bool Waypoint::isValid() const noexcept
{
Expand Down
16 changes: 8 additions & 8 deletions src/Persistence/src/Dao/SQLite/SQLiteAircraftDao.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ std::vector<Aircraft> SQLiteAircraftDao::getByFlightId(std::int64_t flightId, bo

bool SQLiteAircraftDao::adjustAircraftSequenceNumbersByFlightId(std::int64_t flightId, std::size_t sequenceNumber) const noexcept
{
const QSqlDatabase db {QSqlDatabase::database(d->connectionName)};
const auto db {QSqlDatabase::database(d->connectionName)};
QSqlQuery query {db};
query.prepare(
"update aircraft "
Expand Down Expand Up @@ -231,7 +231,7 @@ bool SQLiteAircraftDao::deleteAllByFlightId(std::int64_t flightId) const noexcep
ok = d->waypointDao->deleteByFlightId(flightId);
}
if (ok) {
const QSqlDatabase db {QSqlDatabase::database(d->connectionName)};
const auto db {QSqlDatabase::database(d->connectionName)};
QSqlQuery query {db};
query.prepare(
"delete "
Expand Down Expand Up @@ -277,7 +277,7 @@ bool SQLiteAircraftDao::deleteById(std::int64_t id) const noexcept
ok = d->waypointDao->deleteByAircraftId(id);
}
if (ok) {
const QSqlDatabase db {QSqlDatabase::database(d->connectionName)};
const auto db {QSqlDatabase::database(d->connectionName)};
QSqlQuery query {db};
query.prepare(
"delete "
Expand All @@ -299,7 +299,7 @@ bool SQLiteAircraftDao::deleteById(std::int64_t id) const noexcept
std::vector<AircraftInfo> SQLiteAircraftDao::getAircraftInfosByFlightId(std::int64_t flightId, bool *ok) const noexcept
{
std::vector<AircraftInfo> aircraftInfos;
const QSqlDatabase db {QSqlDatabase::database(d->connectionName)};
const auto db {QSqlDatabase::database(d->connectionName)};
QSqlQuery query {db};
query.setForwardOnly(true);
query.prepare(
Expand Down Expand Up @@ -357,7 +357,7 @@ std::vector<AircraftInfo> SQLiteAircraftDao::getAircraftInfosByFlightId(std::int

bool SQLiteAircraftDao::updateTimeOffset(std::int64_t id, std::int64_t timeOffset) const noexcept
{
const QSqlDatabase db {QSqlDatabase::database(d->connectionName)};
const auto db {QSqlDatabase::database(d->connectionName)};
QSqlQuery query {db};
query.prepare(
"update aircraft "
Expand All @@ -378,7 +378,7 @@ bool SQLiteAircraftDao::updateTimeOffset(std::int64_t id, std::int64_t timeOffse

bool SQLiteAircraftDao::updateTailNumber(std::int64_t id, const QString &tailNumber) const noexcept
{
const QSqlDatabase db {QSqlDatabase::database(d->connectionName)};
const auto db {QSqlDatabase::database(d->connectionName)};
QSqlQuery query {db};
query.prepare(
"update aircraft "
Expand All @@ -402,7 +402,7 @@ bool SQLiteAircraftDao::updateTailNumber(std::int64_t id, const QString &tailNum
inline std::int64_t SQLiteAircraftDao::insertAircraft(std::int64_t flightId, std::size_t sequenceNumber, const Aircraft &aircraft) const noexcept
{
std::int64_t aircraftId {Const::InvalidId};
const QSqlDatabase db {QSqlDatabase::database(d->connectionName)};
const auto db {QSqlDatabase::database(d->connectionName)};
QSqlQuery query {db};
query.prepare(
"insert into aircraft ("
Expand Down Expand Up @@ -431,7 +431,7 @@ inline std::int64_t SQLiteAircraftDao::insertAircraft(std::int64_t flightId, std
const AircraftType &aircraftType = aircraft.getAircraftInfo().aircraftType;
bool ok = d->aircraftTypeDao->upsert(aircraftType);
if (ok) {
const AircraftInfo &info = aircraft.getAircraftInfo();
const auto &info = aircraft.getAircraftInfo();
query.bindValue(":flight_id", QVariant::fromValue(flightId));
query.bindValue(":seq_nr", QVariant::fromValue(sequenceNumber));
query.bindValue(":type", aircraftType.type);
Expand Down
Loading

0 comments on commit f81a678

Please sign in to comment.