0.2.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
14
15#pragma once
16
17#include <Eigen/Dense>
18#include <Eigen/Core>
19
21#include "util/Logger.hpp"
24#include "internal/egm96Coeffs.hpp"
25
26namespace NAV
27{
29enum class GravitationModel : int
30{
31 None,
32 WGS84,
35 EGM96,
36 COUNT,
37};
38
42const char* to_string(GravitationModel gravitationModel);
43
47bool ComboGravitationModel(const char* label, GravitationModel& gravitationModel);
48
56template<typename Scalar, typename = std::enable_if_t<std::is_floating_point_v<Scalar>>>
57[[nodiscard]] Eigen::Vector3<Scalar> n_calcGravitation_SomiglianaAltitude(const Scalar& latitude, const Scalar& altitude)
58{
59 // eq 6.16 has a fault in the denominator, it should be a sin^2(latitude)
60 auto g_0 = 9.7803253359 * (1.0 + 1.931853e-3 * std::pow(std::sin(latitude), 2))
61 / std::sqrt(1.0 - InsConst<Scalar>::WGS84::e_squared * std::pow(std::sin(latitude), 2));
62
63 // Altitude compensation (Matlab example from Chapter 6_GNSS_INS_1 - glocal.m)
64 auto k = 1
65 - (2 * altitude / InsConst<Scalar>::WGS84::a)
69 + 3 * std::pow(altitude / InsConst<Scalar>::WGS84::a, 2);
70
71 return { 0.0, 0.0, k * g_0 };
72}
73
81template<typename Scalar, typename = std::enable_if_t<std::is_floating_point_v<Scalar>>>
82[[nodiscard]] Eigen::Vector3<Scalar> n_calcGravitation_WGS84_Skydel(const Scalar& latitude, const Scalar& altitude)
83{
84 // geocentric latitude determination from geographic latitude
85 auto latitudeGeocentric = std::atan((std::pow(InsConst<Scalar>::WGS84::b, 2.0) / std::pow(InsConst<Scalar>::WGS84::a, 2.0)) * std::tan(latitude));
86 // effective radius determination, i.e. earth radius on WGS84 spheroid plus local altitude --> possible error!! altitude in lla should be added rather than subtracted!
87 auto radiusSpheroid = InsConst<Scalar>::WGS84::a * (1.0 - InsConst<Scalar>::WGS84::f * std::pow(std::sin(latitudeGeocentric), 2.0)) - altitude;
88
89 // Derivation of gravity, i.e. gravitational potential derived after effective radius
90 auto gravitationMagnitude = InsConst<Scalar>::WGS84::MU * std::pow(radiusSpheroid, -2.0)
91 - 3 * InsConst<Scalar>::WGS84::MU * InsConst<Scalar>::WGS84::J2 * std::pow(InsConst<Scalar>::WGS84::a, 2.0) * 0.5 * std::pow(radiusSpheroid, -4.0) * (3 * std::pow(std::sin(latitudeGeocentric), 2.0) - 1)
92 - std::pow(InsConst<Scalar>::omega_ie_Skydel, 2.0) * radiusSpheroid * std::pow(std::cos(latitudeGeocentric), 2.0);
93
94 return { 0, 0, gravitationMagnitude };
95}
96
104template<typename Scalar, typename = std::enable_if_t<std::is_floating_point_v<Scalar>>>
105[[nodiscard]] Eigen::Vector3<Scalar> n_calcGravitation_WGS84(const Scalar& latitude, const Scalar& altitude)
106{
107 // Geocentric latitude determination from geographic latitude
108 auto latitudeGeocentric = std::atan((std::pow(InsConst<Scalar>::WGS84::b, 2.0) / std::pow(InsConst<Scalar>::WGS84::a, 2.0)) * std::tan(latitude));
109 // Radius of spheroid determination
110 auto radiusSpheroid = InsConst<Scalar>::WGS84::a * (1.0 - InsConst<Scalar>::WGS84::f * std::pow(std::sin(latitudeGeocentric), 2.0)) + altitude;
111
112 // Magnitude of the gravity, i.e. without orientation
113 auto gravitationMagnitude = InsConst<Scalar>::WGS84::MU * std::pow(radiusSpheroid, -2.0)
114 - 3 * InsConst<Scalar>::WGS84::MU * InsConst<Scalar>::WGS84::J2 * std::pow(InsConst<Scalar>::WGS84::a, 2.0) * 0.5 * std::pow(radiusSpheroid, -4.0) * (3 * std::pow(std::sin(latitudeGeocentric), 2.0) - 1)
115 - std::pow(InsConst<Scalar>::omega_ie, 2.0) * radiusSpheroid * std::pow(std::cos(latitudeGeocentric), 2.0);
116
117 return { 0, 0, gravitationMagnitude };
118}
119
127template<typename Derived>
128[[nodiscard]] Eigen::Vector3<typename Derived::Scalar> n_calcGravitation_EGM96(const Eigen::MatrixBase<Derived>& lla_position, size_t ndegree = 10)
129{
132
133 auto e_position = trafo::lla2ecef_WGS84(lla_position);
134
135 // Geocentric latitude determination from Groves (2013) - eq. (2.114)
136 auto latitudeGeocentric = std::atan(e_position(2) / std::sqrt(e_position(0) * e_position(0) + e_position(1) * e_position(1)));
137
138 // Spherical coordinates
139 auto radius = std::sqrt(e_position(0) * e_position(0) + e_position(1) * e_position(1) + e_position(2) * e_position(2));
140 auto elevation = M_PI_2 - latitudeGeocentric; // [rad]
141 auto azimuth = lla_position(1); // [rad]
142
143 // Gravitation vector in local-navigation frame coordinates in [m/s^2]
144 Eigen::Vector3<typename Derived::Scalar> n_gravitation = Eigen::Vector3<typename Derived::Scalar>::Zero();
145
146 typename Derived::Scalar Pnm = 0;
147 typename Derived::Scalar Pnmd = 0;
148
149 auto coeffsRows = egm96Coeffs.size();
150
151 // Associated Legendre Polynomial Coefficients 'P' and their derivatives 'Pd'
152 auto [P, Pd] = associatedLegendre(static_cast<double>(elevation), ndegree);
153
154 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)
155 {
156 // Retrieving EGM96 coefficients
157 auto n = static_cast<int>(egm96Coeffs.at(i).at(0)); // Degree of the Associated Legendre Polynomial
158 auto m = static_cast<int>(egm96Coeffs.at(i).at(1)); // Order of the Associated Legendre Polynomial
159 auto C = egm96Coeffs.at(i).at(2);
160 auto S = egm96Coeffs.at(i).at(3);
161
162 if (static_cast<size_t>(n) == ndegree + 1)
163 {
164 // Ending of the for-loop once the iterated 'n' becomes larger than the user-defined 'ndegree'
165 i = coeffsRows;
166 }
167 else
168 {
169 // Retrieving the parameters of the associated Legendre Polynomials
170 Pnm = P(n, m);
171 Pnmd = Pd(n, m);
172
173 auto nd = static_cast<double>(n);
174 auto md = static_cast<double>(m);
175
176 // Gravity vector from differentiation of the gravity potential in spherical coordinates (see 'GUT User Guide' eq. 7.4.2)
177 n_gravitation(0) += std::pow((InsConst<typename Derived::Scalar>::WGS84::a / radius), nd) * (C * std::cos(md * azimuth) + S * std::sin(md * azimuth)) * Pnmd;
178 n_gravitation(1) += std::pow((InsConst<typename Derived::Scalar>::WGS84::a / radius), nd) * md * (C * std::sin(md * azimuth) - S * std::cos(md * azimuth)) * Pnm;
179 n_gravitation(2) += (nd + 1.0) * std::pow((InsConst<typename Derived::Scalar>::WGS84::a / radius), nd) * (C * std::cos(md * azimuth) + S * std::sin(md * azimuth)) * Pnm;
180 }
181 }
182
183 return { -InsConst<typename Derived::Scalar>::WGS84::MU / (radius * radius) * n_gravitation(0),
184 (1.0 / std::sin(elevation)) * (-InsConst<typename Derived::Scalar>::WGS84::MU / (radius * radius)) * n_gravitation(1),
185 InsConst<typename Derived::Scalar>::WGS84::MU / (radius * radius) * (1.0 + n_gravitation(2)) };
186}
187
192template<typename Derived>
193[[nodiscard]] Eigen::Vector3<typename Derived::Scalar> n_calcGravitation(const Eigen::MatrixBase<Derived>& lla_position,
194 GravitationModel gravitationModel = GravitationModel::EGM96)
195{
196 const typename Derived::Scalar& latitude = lla_position(0);
197 const typename Derived::Scalar& altitude = lla_position(2);
198
199 if (gravitationModel == GravitationModel::WGS84)
200 {
201 return n_calcGravitation_WGS84(latitude, altitude);
202 }
203 if (gravitationModel == GravitationModel::WGS84_Skydel) // TODO: This function becomes obsolete, once the ImuStream is deactivated due to the 'InstinctDataStream'
204 {
205 return n_calcGravitation_WGS84_Skydel(latitude, altitude);
206 }
207 if (gravitationModel == GravitationModel::Somigliana)
208 {
209 return n_calcGravitation_SomiglianaAltitude(latitude, altitude);
210 }
211 if (gravitationModel == GravitationModel::EGM96)
212 {
213 return n_calcGravitation_EGM96(lla_position);
214 }
215 return Eigen::Vector3<typename Derived::Scalar>::Zero();
216}
217
218} // namespace NAV
Associated Legendre Polynomials for EGM96.
Holds all Constants.
Transformation collection.
@ None
None.
Definition GlobalActions.hpp:19
Eigen::Vector3< Scalar > n_calcGravitation_WGS84_Skydel(const Scalar &latitude, const Scalar &altitude)
Calculates the gravitation (acceleration due to mass attraction of the Earth) at the WGS84 reference ...
Definition Gravity.hpp:82
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:193
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...
@ WGS84
World Geodetic System 1984.
@ EGM96
Earth Gravitational Model 1996.
@ Somigliana
Somigliana gravity model.
bool ComboGravitationModel(const char *label, GravitationModel &gravitationModel)
Shows a ComboBox to select the gravitation model.
Eigen::Vector3< Scalar > n_calcGravitation_WGS84(const Scalar &latitude, const Scalar &altitude)
Calculates the gravitation (acceleration due to mass attraction of the Earth) at the WGS84 reference ...
Definition Gravity.hpp:105
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:128
Eigen::Vector3< Scalar > n_calcGravitation_SomiglianaAltitude(const Scalar &latitude, const Scalar &altitude)
Calculates the gravitation (acceleration due to mass attraction of the Earth) at the WGS84 reference ...
Definition Gravity.hpp:57
@ COUNT
Amount of items in the enum.
Utility class for logging to console and file.
const char * to_string(gui::widgets::PositionWithFrame::ReferenceFrame refFrame)
Converts the enum to a string.
Constants.
Definition Constants.hpp:26
static const std::array< std::array< double, 6 >, 65338 > egm96Coeffs
EGM96 coefficients.
Definition egm96Coeffs.hpp:22
std::pair< Eigen::MatrixXd, Eigen::MatrixXd > associatedLegendre(double theta, size_t ndegree=10)
Calculates the associated Legendre Polynomial coefficients necessary for the EGM96.