0.5.0
Loading...
Searching...
No Matches
Gravity.hpp
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 Gravity.hpp
10/// @brief Different Gravity Models
11/// @author T. Topp (topp@ins.uni-stuttgart.de)
12/// @author M. Maier (marcel.maier@ins.uni-stuttgart.de)
13/// @date 2020-09-15
14
15#pragma once
16
17#include <cstdint>
18#include <Eigen/Dense>
19#include <Eigen/Core>
20
25
26namespace NAV
27{
28/// Available Gravitation Models
29enum class GravitationModel : uint8_t
30{
31 None, ///< Gravity Model turned off
32 Const, ///< Constant gravitation
33 WGS84, ///< World Geodetic System 1984
34 WGS84_Skydel, ///< World Geodetic System 1984 implemented by the Skydel Simulator // FIXME: Remove after Skydel uses the same as Instinct
35 Somigliana, ///< Somigliana gravity model
36 EGM96, ///< Earth Gravitational Model 1996
37 COUNT, ///< Amount of items in the enum
38};
39
40/// @brief Converts the enum to a string
41/// @param[in] gravitationModel Enum value to convert into text
42/// @return String representation of the enum
43const char* to_string(GravitationModel gravitationModel);
44
45/// @brief Shows a ComboBox to select the gravitation model
46/// @param[in] label Label to show beside the combo box. This has to be a unique id for ImGui.
47/// @param[in] gravitationModel Reference to the gravitation model to select
48bool ComboGravitationModel(const char* label, GravitationModel& gravitationModel);
49
50/// @brief Returns a constant gravitation of 9.81 [m/s^2] in down direction
51/// @return Gravitation vector in local-navigation frame coordinates in [m/s^2]
52template<typename T>
53[[nodiscard]] Eigen::Vector3<T> n_calcGravitation_Const()
54{
55 return { T(0.0), T(0.0), T(9.81) };
56}
57
58/// @brief Calculates the gravitation (acceleration due to mass attraction of the Earth) at the WGS84 reference ellipsoid
59/// using the Somigliana model and makes corrections for altitude
60/// @param[in] latitude Latitude in [rad]
61/// @param[in] altitude Altitude in [m]
62/// @return Gravitation vector in local-navigation frame coordinates in [m/s^2]
63///
64/// @note See S. Gleason (2009) - GNSS Applications and Methods (Chapter 6.2.3.2 - eq. 6.16)
65template<typename T>
66[[nodiscard]] Eigen::Vector3<T> n_calcGravitation_SomiglianaAltitude(const T& latitude, const T& altitude)
67{
68 // eq 6.16 has a fault in the denominator, it should be a sin^2(latitude)
69 auto g_0 = 9.7803253359 * (1.0 + 1.931853e-3 * std::pow(std::sin(latitude), 2))
70 / std::sqrt(1.0 - InsConst::WGS84::e_squared * std::pow(std::sin(latitude), 2));
71
72 // Altitude compensation (Matlab example from Chapter 6_GNSS_INS_1 - glocal.m)
73 auto k = 1.0
74 - (2.0 * altitude / InsConst::WGS84::a)
75 * (1.0 + InsConst::WGS84::f
76 + (std::pow(InsConst::omega_ie * InsConst::WGS84::a, 2))
78 + 3.0 * std::pow(altitude / InsConst::WGS84::a, 2.0);
79
80 return { T(0.0), T(0.0), k * g_0 };
81}
82
83/// @brief Calculates the gravitation (acceleration due to mass attraction of the Earth) at the WGS84 reference ellipsoid
84/// using gravity as derived from the gravity potential. However, the north component of the centrifugal acceleration is neglected in order to match the implementation of Skydel's 'ImuPlugin'
85/// @param[in] latitude Latitude in [rad]
86/// @param[in] altitude Altitude in [m]
87/// @return Gravitation vector in local-navigation frame coordinates in [m/s^2]
88///
89/// @note See Skydel API plug-in 'skydel_plugin/source/library/inertial_math/Sources/source/gravity.cpp'
90template<typename T>
91[[nodiscard]] Eigen::Vector3<T> n_calcGravitation_WGS84_Skydel(const T& latitude, const T& altitude)
92{
93 // geocentric latitude determination from geographic latitude
94 auto latitudeGeocentric = std::atan((std::pow(InsConst::WGS84::b, 2.0) / std::pow(InsConst::WGS84::a, 2.0)) * std::tan(latitude));
95 // effective radius determination, i.e. earth radius on WGS84 spheroid plus local altitude --> possible error!! altitude in lla should be added rather than subtracted!
96 auto radiusSpheroid = InsConst::WGS84::a * (1.0 - InsConst::WGS84::f * std::pow(std::sin(latitudeGeocentric), 2.0)) - altitude;
97
98 // Derivation of gravity, i.e. gravitational potential derived after effective radius
99 auto gravitationMagnitude = InsConst::WGS84::MU * std::pow(radiusSpheroid, -2.0)
100 - 3.0 * InsConst::WGS84::MU * InsConst::WGS84::J2 * std::pow(InsConst::WGS84::a, 2.0) * 0.5 * std::pow(radiusSpheroid, -4.0) * (3.0 * std::pow(std::sin(latitudeGeocentric), 2.0) - 1.0)
101 - std::pow(InsConst::omega_ie_Skydel, 2.0) * radiusSpheroid * std::pow(std::cos(latitudeGeocentric), 2.0);
102
103 return { T(0.0), T(0.0), gravitationMagnitude };
104}
105
106/// @brief Calculates the gravitation (acceleration due to mass attraction of the Earth) at the WGS84 reference ellipsoid
107/// using gravity as derived from the gravity potential.
108/// @param[in] latitude Latitude in [rad]
109/// @param[in] altitude Altitude in [m]
110/// @return Gravitation vector in local-navigation frame coordinates in [m/s^2]
111///
112/// @note See 'INS-Projects/INSTINCT/SpecificLiterature/GravityPotentialWGS84' in NC folder (eq. (3) derived after 'r')
113template<typename T>
114[[nodiscard]] Eigen::Vector3<T> n_calcGravitation_WGS84(const T& latitude, const T& altitude)
115{
116 // Geocentric latitude determination from geographic latitude
117 auto latitudeGeocentric = std::atan((std::pow(InsConst::WGS84::b, 2.0) / std::pow(InsConst::WGS84::a, 2.0)) * std::tan(latitude));
118 // Radius of spheroid determination
119 auto radiusSpheroid = InsConst::WGS84::a * (1.0 - InsConst::WGS84::f * std::pow(std::sin(latitudeGeocentric), 2.0)) + altitude;
120
121 // Magnitude of the gravity, i.e. without orientation
122 auto gravitationMagnitude = InsConst::WGS84::MU * std::pow(radiusSpheroid, -2.0)
123 - 3.0 * InsConst::WGS84::MU * InsConst::WGS84::J2 * std::pow(InsConst::WGS84::a, 2.0) * 0.5 * std::pow(radiusSpheroid, -4.0) * (3.0 * std::pow(std::sin(latitudeGeocentric), 2.0) - 1.0)
124 - std::pow(InsConst::omega_ie, 2.0) * radiusSpheroid * std::pow(std::cos(latitudeGeocentric), 2.0);
125
126 return { T(0.0), T(0.0), gravitationMagnitude };
127}
128
129/// @brief Calculates the gravitation (acceleration due to mass attraction of the Earth) at the WGS84 reference ellipsoid
130/// using the EGM96 spherical harmonic model (up to order 10)
131/// @param[in] lla_position [ϕ, λ, h] Latitude, Longitude, Altitude in [rad, rad, m]
132/// @param[in] ndegree Degree of the EGM96 (1 <= ndegree <= 10)
133/// @return Gravitation vector in local-navigation frame coordinates in [m/s^2]
134///
135/// @note See Groves (2013) Chapter 2.4.3 and 'GUT User Guide' (2018) Chapter 7.4
136template<typename Derived>
137[[nodiscard]] Eigen::Vector3<typename Derived::Scalar> n_calcGravitation_EGM96(const Eigen::MatrixBase<Derived>& lla_position, size_t ndegree = 10)
138{
141
142 auto e_position = trafo::lla2ecef_WGS84(lla_position);
143
144 // Geocentric latitude determination from Groves (2013) - eq. (2.114)
145 auto latitudeGeocentric = std::atan(e_position(2) / std::sqrt(e_position(0) * e_position(0) + e_position(1) * e_position(1)));
146
147 // Spherical coordinates
148 auto radius = std::sqrt(e_position(0) * e_position(0) + e_position(1) * e_position(1) + e_position(2) * e_position(2));
149 auto elevation = M_PI_2 - latitudeGeocentric; // [rad]
150 const auto& azimuth = lla_position(1); // [rad]
151
152 // Gravitation vector in local-navigation frame coordinates in [m/s^2]
153 Eigen::Vector3<typename Derived::Scalar> n_gravitation = Eigen::Vector3<typename Derived::Scalar>::Zero();
154
155 typename Derived::Scalar Pnm(0.0);
156 typename Derived::Scalar Pnmd(0.0);
157
158 auto coeffsRows = egm96Coeffs.size();
159
160 // Associated Legendre Polynomial Coefficients 'P' and their derivatives 'Pd'
161 auto [P, Pd] = associatedLegendre(elevation, ndegree);
162
163 for (size_t i = 0; i < coeffsRows; i++) // NOLINT(clang-analyzer-core.UndefinedBinaryOperatorResult) // FIXME: Wrong error message about Eigen (error: The left operand of '*' is a garbage value)
164 {
165 // Retrieving EGM96 coefficients
166 auto n = static_cast<int>(egm96Coeffs.at(i).at(0)); // Degree of the Associated Legendre Polynomial
167 auto m = static_cast<int>(egm96Coeffs.at(i).at(1)); // Order of the Associated Legendre Polynomial
168 auto C = egm96Coeffs.at(i).at(2);
169 auto S = egm96Coeffs.at(i).at(3);
170
171 if (static_cast<size_t>(n) == ndegree + 1)
172 {
173 // Ending of the for-loop once the iterated 'n' becomes larger than the user-defined 'ndegree'
174 i = coeffsRows;
175 }
176 else
177 {
178 // Retrieving the parameters of the associated Legendre Polynomials
179 Pnm = P(n, m);
180 Pnmd = Pd(n, m);
181
182 auto nd = static_cast<double>(n);
183 auto md = static_cast<double>(m);
184
185 // Gravity vector from differentiation of the gravity potential in spherical coordinates (see 'GUT User Guide' eq. 7.4.2)
186 n_gravitation(0) += std::pow((InsConst::WGS84::a / radius), nd) * (C * std::cos(md * azimuth) + S * std::sin(md * azimuth)) * Pnmd;
187 n_gravitation(1) += std::pow((InsConst::WGS84::a / radius), nd) * md * (C * std::sin(md * azimuth) - S * std::cos(md * azimuth)) * Pnm;
188 n_gravitation(2) += (nd + 1.0) * std::pow((InsConst::WGS84::a / radius), nd) * (C * std::cos(md * azimuth) + S * std::sin(md * azimuth)) * Pnm;
189 }
190 }
191
192 return { -InsConst::WGS84::MU / (radius * radius) * n_gravitation(0),
193 (1.0 / std::sin(elevation)) * (-InsConst::WGS84::MU / (radius * radius)) * n_gravitation(1),
194 InsConst::WGS84::MU / (radius * radius) * (1.0 + n_gravitation(2)) };
195}
196
197/// @brief Calculates the gravitation (acceleration due to mass attraction of the Earth)
198/// @param[in] lla_position [ϕ, λ, h] Latitude, Longitude, Altitude in [rad, rad, m]
199/// @param[in] gravitationModel Gravitation model to use
200/// @return Gravitation vector in local-navigation frame coordinates in [m/s^2]
201template<typename Derived>
202[[nodiscard]] Eigen::Vector3<typename Derived::Scalar> n_calcGravitation(const Eigen::MatrixBase<Derived>& lla_position,
203 GravitationModel gravitationModel = GravitationModel::EGM96)
204{
205 const typename Derived::Scalar& latitude = lla_position(0);
206 const typename Derived::Scalar& altitude = lla_position(2);
207
208 switch (gravitationModel)
209 {
211 return Eigen::Vector3<typename Derived::Scalar>::Zero();
215 return n_calcGravitation_WGS84(latitude, altitude);
217 return n_calcGravitation_WGS84_Skydel(latitude, altitude);
219 return n_calcGravitation_SomiglianaAltitude(latitude, altitude);
221 return n_calcGravitation_EGM96(lla_position);
223 return Eigen::Vector3<typename Derived::Scalar>::Zero();
224 }
225
226 return Eigen::Vector3<typename Derived::Scalar>::Zero();
227}
228
229} // namespace NAV
Associated Legendre Polynomials for EGM96.
Holds all Constants.
Transformation collection.
static constexpr double f
Flattening f = (a-b)/a.
Definition Constants.hpp:52
static constexpr double J2
Dynamic form factor, derived [-].
Definition Constants.hpp:60
static constexpr double b
Semi-minor axis = polar radius.
Definition Constants.hpp:54
static constexpr double MU
Gravitational constant (mass of Earth’s atmosphere included) [m³/s²].
Definition Constants.hpp:58
static constexpr double a
Semi-major axis = equatorial radius.
Definition Constants.hpp:50
static constexpr double e_squared
Square of the first eccentricity of the ellipsoid.
Definition Constants.hpp:56
static constexpr double omega_ie
Nominal mean angular velocity of the Earth in [rad/s].
static constexpr double omega_ie_Skydel
Nominal mean angular velocity of the Earth in [rad/s]. Value implemented by the Skydel GNSS simulator...
std::array< std::array< double, 6 >, 65338 > egm96Coeffs
EGM96 coefficients.
std::pair< Eigen::MatrixX< T >, Eigen::MatrixX< T > > associatedLegendre(const T &theta, size_t ndegree=10)
Calculates the associated Legendre Polynomial coefficients necessary for the EGM96.
Eigen::Vector3< typename Derived::Scalar > lla2ecef_WGS84(const Eigen::MatrixBase< Derived > &lla_position)
Converts latitude, longitude and altitude into Earth-centered-Earth-fixed coordinates using WGS84.
Eigen::Vector3< typename Derived::Scalar > n_calcGravitation(const Eigen::MatrixBase< Derived > &lla_position, GravitationModel gravitationModel=GravitationModel::EGM96)
Calculates the gravitation (acceleration due to mass attraction of the Earth)
Definition Gravity.hpp:202
Eigen::Vector3< T > n_calcGravitation_WGS84(const T &latitude, const T &altitude)
Calculates the gravitation (acceleration due to mass attraction of the Earth) at the WGS84 reference ...
Definition Gravity.hpp:114
Eigen::Vector3< T > n_calcGravitation_WGS84_Skydel(const T &latitude, const T &altitude)
Calculates the gravitation (acceleration due to mass attraction of the Earth) at the WGS84 reference ...
Definition Gravity.hpp:91
@ COUNT
Amount of items in the enum.
@ None
Ionosphere model turned off.
const char * to_string(gui::widgets::PositionWithFrame::ReferenceFrame refFrame)
Converts the enum to a string.
GravitationModel
Available Gravitation Models.
Definition Gravity.hpp:30
@ WGS84_Skydel
World Geodetic System 1984 implemented by the Skydel Simulator // FIXME: Remove after Skydel uses the...
Definition Gravity.hpp:34
@ COUNT
Amount of items in the enum.
Definition Gravity.hpp:37
@ WGS84
World Geodetic System 1984.
Definition Gravity.hpp:33
@ None
Gravity Model turned off.
Definition Gravity.hpp:31
@ Const
Constant gravitation.
Definition Gravity.hpp:32
@ EGM96
Earth Gravitational Model 1996.
Definition Gravity.hpp:36
@ Somigliana
Somigliana gravity model.
Definition Gravity.hpp:35
bool ComboGravitationModel(const char *label, GravitationModel &gravitationModel)
Shows a ComboBox to select the gravitation model.
Definition Gravity.cpp:40
Eigen::Vector3< T > n_calcGravitation_Const()
Returns a constant gravitation of 9.81 [m/s^2] in down direction.
Definition Gravity.hpp:53
Eigen::Vector3< typename Derived::Scalar > n_calcGravitation_EGM96(const Eigen::MatrixBase< Derived > &lla_position, size_t ndegree=10)
Calculates the gravitation (acceleration due to mass attraction of the Earth) at the WGS84 reference ...
Definition Gravity.hpp:137
Eigen::Vector3< T > n_calcGravitation_SomiglianaAltitude(const T &latitude, const T &altitude)
Calculates the gravitation (acceleration due to mass attraction of the Earth) at the WGS84 reference ...
Definition Gravity.hpp:66