QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
GPSProtocolMath.cc
Go to the documentation of this file.
1#include "GPSProtocolMath.h"
2
3#include <chrono>
4#include <cmath>
5#include <iomanip>
6#include <limits>
7#include <locale>
8#include <sstream>
9
10#include <GeographicLib/Geocentric.hpp>
11
12namespace GPSProtocolMath {
13
15{
16 Ecef result;
17 GeographicLib::Geocentric::WGS84().Forward(position.latitudeDegrees, position.longitudeDegrees,
18 position.altitudeMeters, result.x, result.y, result.z);
19 return result;
20}
21
23{
25 double height = 0;
26 GeographicLib::Geocentric::WGS84().Reverse(position.x, position.y, position.z, result.latitudeDegrees,
27 result.longitudeDegrees, height);
28 result.altitudeMeters = height;
29 return result;
30}
31
32bool nearEarthSurface(const Ecef& position)
33{
34 const double radius = std::hypot(position.x, position.y, position.z);
35 return radius >= 6000000 && radius <= 7000000;
36}
37
38uint64_t utcMicroseconds(int year, int month, int day, int hour, int minute, int second, int32_t nsec)
39{
40 using namespace std::chrono;
41 const int64_t monthIndex = static_cast<int64_t>(year) * 12 + (month - 1);
42 const int64_t normalizedYear = monthIndex / 12 - (monthIndex % 12 < 0 ? 1 : 0);
43 if (normalizedYear < int(std::chrono::year::min()) || normalizedYear > int(std::chrono::year::max())) {
44 return 0;
45 }
46 const auto normalizedMonth = static_cast<unsigned>((monthIndex % 12 + 12) % 12 + 1);
47 const sys_seconds instant =
48 sys_days(std::chrono::year(static_cast<int>(normalizedYear)) / std::chrono::month(normalizedMonth) / 1) +
49 days(day - 1) + hours(hour) + minutes(minute) + seconds(second);
50 const auto date = floor<days>(instant);
51 if (date < sys_days(std::chrono::year::min() / January / 1) ||
52 date > sys_days(std::chrono::year::max() / December / 31)) {
53 return 0;
54 }
55 const int64_t epoch = instant.time_since_epoch().count();
56 if (epoch <= UTC_PLAUSIBILITY_FLOOR_SECS ||
57 static_cast<uint64_t>(epoch) > static_cast<uint64_t>((std::numeric_limits<time_t>::max)())) {
58 return 0;
59 }
60 return static_cast<uint64_t>(epoch) * 1000000ULL + nsec / 1000;
61}
62
63} // namespace GPSProtocolMath
64
65QByteArray gpsFixedDecimal(double value, int decimals)
66{
67 std::ostringstream text;
68 text.imbue(std::locale::classic());
69 text << std::fixed << std::setprecision(decimals) << value;
70 return QByteArray::fromStdString(text.str());
71}
QByteArray gpsFixedDecimal(double value, int decimals)
int32_t height
Definition UBXPlan.cc:44
Unit conversions and geodesy shared by receiver families and their callers.
Ecef toEcef(const GPSEllipsoidPosition &position)
constexpr time_t UTC_PLAUSIBILITY_FLOOR_SECS
Receiver dates before this instant (2009-02-13) are implausible and reported as unknown.
bool nearEarthSurface(const Ecef &position)
GPSEllipsoidPosition fromEcef(const Ecef &position)
uint64_t utcMicroseconds(int year, int month, int day, int hour, int minute, int second, int32_t nsec)
WGS84 geodetic position with ellipsoid height, not mean-sea-level altitude.