0.3.0
Loading...
Searching...
No Matches
NiellMappingFunction.cpp
Go to the documentation of this file.
1// This file is part of INSTINCT, the INS Toolkit for Integrated
2// Navigation Concepts and Training by the Institute of Navigation of
3// the University of Stuttgart, Germany.
4//
5// This Source Code Form is subject to the terms of the Mozilla Public
6// License, v. 2.0. If a copy of the MPL was not distributed with this
7// file, You can obtain one at https://mozilla.org/MPL/2.0/.
8
9/// @file NiellMappingFunction.cpp
10/// @brief Niell Mapping Function (NMF)
11/// @author T. Topp (topp@ins.uni-stuttgart.de)
12/// @date 2024-10-17
13/// @note See https://gssc.esa.int/navipedia/index.php/Mapping_of_Niell
14/// @note See \cite Niell1996 Niell1996
15
20#include "util/Logger.hpp"
21
23{
24
25constexpr std::array<double, 5> latitude{ deg2rad(15.0), deg2rad(30.0), deg2rad(45.0), deg2rad(60.0), deg2rad(75.0) };
26constexpr double a_ht = 2.53e-5;
27constexpr double b_ht = 5.49e-3;
28constexpr double c_ht = 1.14e-3;
29
30namespace
31{
32
33std::array<double, 3> interpolateAverage(double lat)
34{
35 std::array<double, 5> a{ 1.2769934e-3, 1.2683230e-3, 1.2465397e-3, 1.2196049e-3, 1.2045996e-3 };
36 std::array<double, 5> b{ 2.9153695e-3, 2.9152299e-3, 2.9288445e-3, 2.9022565e-3, 2.9024912e-3 };
37 std::array<double, 5> c{ 62.610505e-3, 62.837393e-3, 63.721774e-3, 63.824265e-3, 64.258455e-3 };
38
39 auto ls = math::lerpSearch(latitude, lat);
40 ls.t = std::clamp(ls.t, 0.0, 1.0);
41
42 return { std::lerp(a.at(ls.l), a.at(ls.u), ls.t),
43 std::lerp(b.at(ls.l), b.at(ls.u), ls.t),
44 std::lerp(c.at(ls.l), c.at(ls.u), ls.t) };
45}
46
47std::array<double, 3> interpolateAmplitude(double lat)
48{
49 std::array<double, 5> a{ 0.0000000e-0, 1.2709626e-5, 2.6523662e-5, 3.4000452e-5, 4.1202191e-5 };
50 std::array<double, 5> b{ 0.0000000e-0, 2.1414979e-5, 3.0160779e-5, 7.2562722e-5, 11.723375e-5 };
51 std::array<double, 5> c{ 0.0000000e-0, 9.0128400e-5, 4.3497037e-5, 84.795348e-5, 170.37206e-5 };
52
53 auto ls = math::lerpSearch(latitude, lat);
54 ls.t = std::clamp(ls.t, 0.0, 1.0);
55
56 return { std::lerp(a.at(ls.l), a.at(ls.u), ls.t),
57 std::lerp(b.at(ls.l), b.at(ls.u), ls.t),
58 std::lerp(c.at(ls.l), c.at(ls.u), ls.t) };
59}
60
61std::array<double, 3> interpolateWet(double lat)
62{
63 std::array<double, 5> a{ 5.8021897e-4, 5.6794847e-4, 5.8118019e-4, 5.9727542e-4, 6.1641693e-4 };
64 std::array<double, 5> b{ 1.4275268e-3, 1.5138625e-3, 1.4572752e-3, 1.5007428e-3, 1.7599082e-3 };
65 std::array<double, 5> c{ 4.3472961e-2, 4.6729510e-2, 4.3908931e-2, 4.4626982e-2, 5.4736038e-2 };
66
67 auto ls = math::lerpSearch(latitude, lat);
68 ls.t = std::clamp(ls.t, 0.0, 1.0);
69
70 return { std::lerp(a.at(ls.l), a.at(ls.u), ls.t),
71 std::lerp(b.at(ls.l), b.at(ls.u), ls.t),
72 std::lerp(c.at(ls.l), c.at(ls.u), ls.t) };
73}
74
75// mapping normalised to unity at zenith [Marini, 1972]
76double mappingNormalizedAtZenith(double elevation, double a, double b, double c)
77{
78 auto sinE = std::sin(elevation);
79 return (1.0 + a / (1.0 + b / (1.0 + c)))
80 / (sinE + a / (sinE + b / (sinE + c)));
81}
82
83} // namespace
84
85} // namespace NAV::internal::NMF
86
87double NAV::calcTropoMapFunc_NMFH(const InsTime& epoch, const Eigen::Vector3d& lla_pos, double elevation)
88{
89 using namespace internal::NMF; // NOLINT(google-build-using-namespace)
90
91 auto yDoySod = epoch.toYDoySod();
92 double doy = yDoySod.doy + static_cast<double>(yDoySod.sod) / InsTimeUtil::SECONDS_PER_DAY;
93
94 // reference day is 28 January
95 double year = (doy - 28.0) / 365.25 + (lla_pos(0) < 0.0 ? 0.5 : 0.0); // Add half a year for southern latitudes
96 double cosY = std::cos(2 * M_PI * year);
97
98 double lat = std::abs(lla_pos(0));
99
100 auto avg = interpolateAverage(lat);
101 auto amp = interpolateAmplitude(lat);
102 double a_d = avg[0] - amp[0] * cosY;
103 double b_d = avg[1] - amp[1] * cosY;
104 double c_d = avg[2] - amp[2] * cosY;
105
106 double dm = (1.0 / std::sin(elevation) - mappingNormalizedAtZenith(elevation, a_ht, b_ht, c_ht)) * lla_pos(2) / 1e3;
107 // ellipsoidal height instead of height above sea level
108 return mappingNormalizedAtZenith(elevation, a_d, b_d, c_d) + dm;
109}
110
111double NAV::calcTropoMapFunc_NMFW(const Eigen::Vector3d& lla_pos, double elevation)
112{
113 using namespace internal::NMF; // NOLINT(google-build-using-namespace)
114
115 auto [a_w, b_w, c_w] = interpolateWet(std::abs(lla_pos(0)));
116 return mappingNormalizedAtZenith(elevation, a_w, b_w, c_w);
117}
The class is responsible for all time-related tasks.
Utility class for logging to console and file.
Simple Math functions.
Niell Mapping Function.
The class is responsible for all time-related tasks.
Definition InsTime.hpp:710
constexpr InsTime_YDoySod toYDoySod(TimeSystem timesys=UTC) const
Converts this time object into a different format.
Definition InsTime.hpp:903
constexpr int32_t SECONDS_PER_DAY
Seconds / Day.
Definition InsTime.hpp:60
constexpr std::array< double, 5 > latitude
LerpSearchResult lerpSearch(const auto &data, const auto &value)
Searches the value in the data container.
Definition Math.hpp:367
double calcTropoMapFunc_NMFH(const InsTime &epoch, const Eigen::Vector3d &lla_pos, double elevation)
Calculates the Niell Mapping Function (NMF) for the hydrostatic delay.
constexpr auto deg2rad(const T &deg)
Convert Degree to Radians.
Definition Units.hpp:21
double calcTropoMapFunc_NMFW(const Eigen::Vector3d &lla_pos, double elevation)
Calculates the Niell Mapping Function (NMF) for the wet delay.
int32_t doy
Contains day of year in GPS standard time [GPST].
Definition InsTime.hpp:615