mirror of
				https://github.com/gnss-sdr/gnss-sdr
				synced 2025-11-04 09:13:05 +00:00 
			
		
		
		
	Adding a new geographical coordinate transformations and helpers library for system testing
This commit is contained in:
		@@ -18,6 +18,7 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
set(SYSTEM_TESTING_LIB_SOURCES
 | 
					set(SYSTEM_TESTING_LIB_SOURCES
 | 
				
			||||||
 | 
					    geofunctions.cc
 | 
				
			||||||
    spirent_motion_csv_dump_reader.cc
 | 
					    spirent_motion_csv_dump_reader.cc
 | 
				
			||||||
    rtklib_solver_dump_reader.cc
 | 
					    rtklib_solver_dump_reader.cc
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										473
									
								
								src/tests/system-tests/libs/geofunctions.cc
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										473
									
								
								src/tests/system-tests/libs/geofunctions.cc
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,473 @@
 | 
				
			|||||||
 | 
					/*!
 | 
				
			||||||
 | 
					 * \file geofunctions.h
 | 
				
			||||||
 | 
					 * \brief A set of coordinate transformations functions and helpers,
 | 
				
			||||||
 | 
					 * some of them migrated from MATLAB, for geographic information systems.
 | 
				
			||||||
 | 
					 * \author Javier Arribas, 2018. jarribas(at)cttc.es
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * -------------------------------------------------------------------------
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (C) 2010-2018  (see AUTHORS file for a list of contributors)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * GNSS-SDR is a software defined Global Navigation
 | 
				
			||||||
 | 
					 *          Satellite Systems receiver
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This file is part of GNSS-SDR.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * GNSS-SDR is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * GNSS-SDR is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with GNSS-SDR. If not, see <https://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * -------------------------------------------------------------------------
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#include "geofunctions.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define STRP_G_SI 9.80665
 | 
				
			||||||
 | 
					#define STRP_PI 3.1415926535898  //!< Pi as defined in IS-GPS-200E
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					arma::mat Skew_symmetric(arma::vec a)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    arma::mat A = arma::zeros(3, 3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    A << 0.0 << -a(2) << a(1) << arma::endr
 | 
				
			||||||
 | 
					      << a(2) << 0.0 << -a(0) << arma::endr
 | 
				
			||||||
 | 
					      << -a(1) << a(0) << 0 << arma::endr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //    {{0, -a(2),  a(1)},
 | 
				
			||||||
 | 
					    //         {a(2),     0, -a(0)},
 | 
				
			||||||
 | 
					    //         {-a(1),  a(0),     0}};
 | 
				
			||||||
 | 
					    return A;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					double WGS84_g0(double Lat_rad)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    double k = 0.001931853;        //normal gravity constant
 | 
				
			||||||
 | 
					    double e2 = 0.00669438002290;  //the square of the first numerical eccentricity
 | 
				
			||||||
 | 
					    double nge = 9.7803253359;     //normal gravity value on the equator (m/sec^2)
 | 
				
			||||||
 | 
					    double b = sin(Lat_rad);       //Lat in degrees
 | 
				
			||||||
 | 
					    b = b * b;
 | 
				
			||||||
 | 
					    double g0 = nge * (1 + k * b) / (sqrt(1 - e2 * b));
 | 
				
			||||||
 | 
					    return g0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					double WGS84_geocentric_radius(double Lat_geodetic_rad)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    //WGS84 earth model Geocentric radius (Eq. 2.88)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    double WGS84_A = 6378137.0;       //Semi-major axis of the Earth, a [m]
 | 
				
			||||||
 | 
					    double WGS84_IF = 298.257223563;  //Inverse flattening of the Earth
 | 
				
			||||||
 | 
					    double WGS84_F = (1 / WGS84_IF);  //The flattening of the Earth
 | 
				
			||||||
 | 
					    //double WGS84_B=(WGS84_A*(1-WGS84_F)); // Semi-minor axis of the Earth [m]
 | 
				
			||||||
 | 
					    double WGS84_E = (sqrt(2 * WGS84_F - WGS84_F * WGS84_F));  //Eccentricity of the Earth
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //transverse radius of curvature
 | 
				
			||||||
 | 
					    double R_E = WGS84_A / sqrt(1 -
 | 
				
			||||||
 | 
					                                WGS84_E * WGS84_E *
 | 
				
			||||||
 | 
					                                    sin(Lat_geodetic_rad) *
 | 
				
			||||||
 | 
					                                    sin(Lat_geodetic_rad));  // (Eq. 2.66)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //gocentric radius at the Earth surface
 | 
				
			||||||
 | 
					    double r_eS = R_E * sqrt(cos(Lat_geodetic_rad) * cos(Lat_geodetic_rad) +
 | 
				
			||||||
 | 
					                             (1 - WGS84_E * WGS84_E) * (1 - WGS84_E * WGS84_E) * sin(Lat_geodetic_rad) * sin(Lat_geodetic_rad));  // (Eq. 2.88)
 | 
				
			||||||
 | 
					    return r_eS;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int topocent(double *Az, double *El, double *D, const arma::vec &x, const arma::vec &dx)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    double lambda;
 | 
				
			||||||
 | 
					    double phi;
 | 
				
			||||||
 | 
					    double h;
 | 
				
			||||||
 | 
					    double dtr = STRP_PI / 180.0;
 | 
				
			||||||
 | 
					    double a = 6378137.0;         // semi-major axis of the reference ellipsoid WGS-84
 | 
				
			||||||
 | 
					    double finv = 298.257223563;  // inverse of flattening of the reference ellipsoid WGS-84
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Transform x into geodetic coordinates
 | 
				
			||||||
 | 
					    togeod(&phi, &lambda, &h, a, finv, x(0), x(1), x(2));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    double cl = cos(lambda * dtr);
 | 
				
			||||||
 | 
					    double sl = sin(lambda * dtr);
 | 
				
			||||||
 | 
					    double cb = cos(phi * dtr);
 | 
				
			||||||
 | 
					    double sb = sin(phi * dtr);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    arma::mat F = arma::zeros(3, 3);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    F(0, 0) = -sl;
 | 
				
			||||||
 | 
					    F(0, 1) = -sb * cl;
 | 
				
			||||||
 | 
					    F(0, 2) = cb * cl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    F(1, 0) = cl;
 | 
				
			||||||
 | 
					    F(1, 1) = -sb * sl;
 | 
				
			||||||
 | 
					    F(1, 2) = cb * sl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    F(2, 0) = 0;
 | 
				
			||||||
 | 
					    F(2, 1) = cb;
 | 
				
			||||||
 | 
					    F(2, 2) = sb;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    arma::vec local_vector;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    local_vector = arma::htrans(F) * dx;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    double E = local_vector(0);
 | 
				
			||||||
 | 
					    double N = local_vector(1);
 | 
				
			||||||
 | 
					    double U = local_vector(2);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    double hor_dis;
 | 
				
			||||||
 | 
					    hor_dis = sqrt(E * E + N * N);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (hor_dis < 1.0E-20)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            *Az = 0;
 | 
				
			||||||
 | 
					            *El = 90;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            *Az = atan2(E, N) / dtr;
 | 
				
			||||||
 | 
					            *El = atan2(U, hor_dis) / dtr;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (*Az < 0)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            *Az = *Az + 360.0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    *D = sqrt(dx(0) * dx(0) + dx(1) * dx(1) + dx(2) * dx(2));
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int togeod(double *dphi, double *dlambda, double *h, double a, double finv, double X, double Y, double Z)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    *h = 0;
 | 
				
			||||||
 | 
					    double tolsq = 1.e-10;  // tolerance to accept convergence
 | 
				
			||||||
 | 
					    int maxit = 10;         // max number of iterations
 | 
				
			||||||
 | 
					    double rtd = 180.0 / STRP_PI;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // compute square of eccentricity
 | 
				
			||||||
 | 
					    double esq;
 | 
				
			||||||
 | 
					    if (finv < 1.0E-20)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            esq = 0.0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            esq = (2.0 - 1.0 / finv) / finv;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // first guess
 | 
				
			||||||
 | 
					    double P = sqrt(X * X + Y * Y);  // P is distance from spin axis
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //direct calculation of longitude
 | 
				
			||||||
 | 
					    if (P > 1.0E-20)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            *dlambda = atan2(Y, X) * rtd;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            *dlambda = 0.0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // correct longitude bound
 | 
				
			||||||
 | 
					    if (*dlambda < 0)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            *dlambda = *dlambda + 360.0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    double r = sqrt(P * P + Z * Z);  // r is distance from origin (0,0,0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    double sinphi;
 | 
				
			||||||
 | 
					    if (r > 1.0E-20)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            sinphi = Z / r;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            sinphi = 0.0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    *dphi = asin(sinphi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // initial value of height  =  distance from origin minus
 | 
				
			||||||
 | 
					    // approximate distance from origin to surface of ellipsoid
 | 
				
			||||||
 | 
					    if (r < 1.0E-20)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            *h = 0;
 | 
				
			||||||
 | 
					            return 1;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    *h = r - a * (1 - sinphi * sinphi / finv);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // iterate
 | 
				
			||||||
 | 
					    double cosphi;
 | 
				
			||||||
 | 
					    double N_phi;
 | 
				
			||||||
 | 
					    double dP;
 | 
				
			||||||
 | 
					    double dZ;
 | 
				
			||||||
 | 
					    double oneesq = 1.0 - esq;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for (int i = 0; i < maxit; i++)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            sinphi = sin(*dphi);
 | 
				
			||||||
 | 
					            cosphi = cos(*dphi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            // compute radius of curvature in prime vertical direction
 | 
				
			||||||
 | 
					            N_phi = a / sqrt(1 - esq * sinphi * sinphi);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            //    compute residuals in P and Z
 | 
				
			||||||
 | 
					            dP = P - (N_phi + (*h)) * cosphi;
 | 
				
			||||||
 | 
					            dZ = Z - (N_phi * oneesq + (*h)) * sinphi;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            //    update height and latitude
 | 
				
			||||||
 | 
					            *h = *h + (sinphi * dZ + cosphi * dP);
 | 
				
			||||||
 | 
					            *dphi = *dphi + (cosphi * dZ - sinphi * dP) / (N_phi + (*h));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            //     test for convergence
 | 
				
			||||||
 | 
					            if ((dP * dP + dZ * dZ) < tolsq)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            if (i == (maxit - 1))
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    // LOG(WARNING) << "The computation of geodetic coordinates did not converge";
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    *dphi = (*dphi) * rtd;
 | 
				
			||||||
 | 
					    return 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					arma::mat Gravity_ECEF(arma::vec r_eb_e)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    //Parameters
 | 
				
			||||||
 | 
					    double R_0 = 6378137;           //WGS84 Equatorial radius in meters
 | 
				
			||||||
 | 
					    double mu = 3.986004418E14;     //WGS84 Earth gravitational constant (m^3 s^-2)
 | 
				
			||||||
 | 
					    double J_2 = 1.082627E-3;       //WGS84 Earth's second gravitational constant
 | 
				
			||||||
 | 
					    double omega_ie = 7.292115E-5;  // Earth rotation rate (rad/s)
 | 
				
			||||||
 | 
					    // Calculate distance from center of the Earth
 | 
				
			||||||
 | 
					    double mag_r = sqrt(arma::as_scalar(r_eb_e.t() * r_eb_e));
 | 
				
			||||||
 | 
					    // If the input position is 0,0,0, produce a dummy output
 | 
				
			||||||
 | 
					    arma::vec g = arma::zeros(3, 1);
 | 
				
			||||||
 | 
					    if (mag_r != 0)
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            //Calculate gravitational acceleration using (2.142)
 | 
				
			||||||
 | 
					            double z_scale = 5 * pow((r_eb_e(2) / mag_r), 2);
 | 
				
			||||||
 | 
					            arma::vec tmp_vec = {(1 - z_scale) * r_eb_e(0),
 | 
				
			||||||
 | 
					                (1 - z_scale) * r_eb_e(1),
 | 
				
			||||||
 | 
					                (3 - z_scale) * r_eb_e(2)};
 | 
				
			||||||
 | 
					            arma::vec gamma_ = (-mu / pow(mag_r, 3)) * (r_eb_e + 1.5 * J_2 * pow(R_0 / mag_r, 2) * tmp_vec);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            //Add centripetal acceleration using (2.133)
 | 
				
			||||||
 | 
					            g(0) = gamma_(0) + pow(omega_ie, 2) * r_eb_e(0);
 | 
				
			||||||
 | 
					            g(1) = gamma_(1) + pow(omega_ie, 2) * r_eb_e(1);
 | 
				
			||||||
 | 
					            g(2) = gamma_(2);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    return g;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					arma::vec LLH_to_deg(arma::vec LLH)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    double rtd = 180.0 / STRP_PI;
 | 
				
			||||||
 | 
					    LLH(0) = LLH(0) * rtd;
 | 
				
			||||||
 | 
					    LLH(1) = LLH(1) * rtd;
 | 
				
			||||||
 | 
					    return LLH;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					double degtorad(double angleInDegrees)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    double angleInRadians = (STRP_PI / 180.0) * angleInDegrees;
 | 
				
			||||||
 | 
					    return angleInRadians;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					double radtodeg(double angleInRadians)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    double angleInDegrees = (180.0 / STRP_PI) * angleInRadians;
 | 
				
			||||||
 | 
					    return angleInDegrees;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					double mstoknotsh(double MetersPerSeconds)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    double knots = mstokph(MetersPerSeconds) * 0.539957;
 | 
				
			||||||
 | 
					    return knots;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					double mstokph(double MetersPerSeconds)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    double kph = 3600.0 * MetersPerSeconds / 1e3;
 | 
				
			||||||
 | 
					    return kph;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					arma::vec CTM_to_Euler(arma::mat C)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    //Calculate Euler angles using (2.23)
 | 
				
			||||||
 | 
					    arma::vec eul = arma::zeros(3, 1);
 | 
				
			||||||
 | 
					    eul(0) = atan2(C(1, 2), C(2, 2));  // roll
 | 
				
			||||||
 | 
					    if (C(0, 2) < -1.0) C(0, 2) = -1.0;
 | 
				
			||||||
 | 
					    if (C(0, 2) > 1.0) C(0, 2) = 1.0;
 | 
				
			||||||
 | 
					    eul(1) = -asin(C(0, 2));           // pitch
 | 
				
			||||||
 | 
					    eul(2) = atan2(C(0, 1), C(0, 0));  // yaw
 | 
				
			||||||
 | 
					    return eul;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					arma::mat Euler_to_CTM(arma::vec eul)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    //Eq.2.15
 | 
				
			||||||
 | 
					    //Euler angles to Attitude matrix is equivalent to rotate the body
 | 
				
			||||||
 | 
					    //in the three axes:
 | 
				
			||||||
 | 
					    //     arma::mat Ax= {{1,0,0}, {0,cos(Att_phi),sin(Att_phi)} ,{0,-sin(Att_phi),cos(Att_phi)}};
 | 
				
			||||||
 | 
					    //     arma::mat Ay= {{cos(Att_theta), 0, -sin(Att_theta)}, {0,1,0} , {sin(Att_theta), 0, cos(Att_theta)}};
 | 
				
			||||||
 | 
					    //     arma::mat Az= {{cos(Att_psi), sin(Att_psi), 0}, {-sin(Att_psi), cos(Att_psi), 0},{0,0,1}};
 | 
				
			||||||
 | 
					    //     arma::mat C_b_n=Ax*Ay*Az; // Attitude expressed in the LOCAL FRAME (NED)
 | 
				
			||||||
 | 
					    //    C_b_n=C_b_n.t();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //Precalculate sines and cosines of the Euler angles
 | 
				
			||||||
 | 
					    double sin_phi = sin(eul(0));
 | 
				
			||||||
 | 
					    double cos_phi = cos(eul(0));
 | 
				
			||||||
 | 
					    double sin_theta = sin(eul(1));
 | 
				
			||||||
 | 
					    double cos_theta = cos(eul(1));
 | 
				
			||||||
 | 
					    double sin_psi = sin(eul(2));
 | 
				
			||||||
 | 
					    double cos_psi = cos(eul(2));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    arma::mat C = arma::zeros(3, 3);
 | 
				
			||||||
 | 
					    //Calculate coordinate transformation matrix using (2.22)
 | 
				
			||||||
 | 
					    C(0, 0) = cos_theta * cos_psi;
 | 
				
			||||||
 | 
					    C(0, 1) = cos_theta * sin_psi;
 | 
				
			||||||
 | 
					    C(0, 2) = -sin_theta;
 | 
				
			||||||
 | 
					    C(1, 0) = -cos_phi * sin_psi + sin_phi * sin_theta * cos_psi;
 | 
				
			||||||
 | 
					    C(1, 1) = cos_phi * cos_psi + sin_phi * sin_theta * sin_psi;
 | 
				
			||||||
 | 
					    C(1, 2) = sin_phi * cos_theta;
 | 
				
			||||||
 | 
					    C(2, 0) = sin_phi * sin_psi + cos_phi * sin_theta * cos_psi;
 | 
				
			||||||
 | 
					    C(2, 1) = -sin_phi * cos_psi + cos_phi * sin_theta * sin_psi;
 | 
				
			||||||
 | 
					    C(2, 2) = cos_phi * cos_theta;
 | 
				
			||||||
 | 
					    return C;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					arma::vec cart2geo(arma::vec XYZ, int elipsoid_selection)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    const double a[5] = {6378388.0, 6378160.0, 6378135.0, 6378137.0, 6378137.0};
 | 
				
			||||||
 | 
					    const double f[5] = {1.0 / 297.0, 1.0 / 298.247, 1.0 / 298.26, 1.0 / 298.257222101, 1.0 / 298.257223563};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    double lambda = atan2(XYZ[1], XYZ[0]);
 | 
				
			||||||
 | 
					    double ex2 = (2.0 - f[elipsoid_selection]) * f[elipsoid_selection] / ((1.0 - f[elipsoid_selection]) * (1.0 - f[elipsoid_selection]));
 | 
				
			||||||
 | 
					    double c = a[elipsoid_selection] * sqrt(1.0 + ex2);
 | 
				
			||||||
 | 
					    double phi = atan(XYZ[2] / ((sqrt(XYZ[0] * XYZ[0] + XYZ[1] * XYZ[1]) * (1.0 - (2.0 - f[elipsoid_selection])) * f[elipsoid_selection])));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    double h = 0.1;
 | 
				
			||||||
 | 
					    double oldh = 0.0;
 | 
				
			||||||
 | 
					    double N;
 | 
				
			||||||
 | 
					    int iterations = 0;
 | 
				
			||||||
 | 
					    do
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            oldh = h;
 | 
				
			||||||
 | 
					            N = c / sqrt(1 + ex2 * (cos(phi) * cos(phi)));
 | 
				
			||||||
 | 
					            phi = atan(XYZ[2] / ((sqrt(XYZ[0] * XYZ[0] + XYZ[1] * XYZ[1]) * (1.0 - (2.0 - f[elipsoid_selection]) * f[elipsoid_selection] * N / (N + h)))));
 | 
				
			||||||
 | 
					            h = sqrt(XYZ[0] * XYZ[0] + XYZ[1] * XYZ[1]) / cos(phi) - N;
 | 
				
			||||||
 | 
					            iterations = iterations + 1;
 | 
				
			||||||
 | 
					            if (iterations > 100)
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
 | 
					                    //std::cout << "Failed to approximate h with desired precision. h-oldh= " << h - oldh;
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    while (std::abs(h - oldh) > 1.0e-12);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    arma::vec LLH = {{phi, lambda, h}};  //radians
 | 
				
			||||||
 | 
					    return LLH;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ECEF_to_Geo(arma::vec r_eb_e, arma::vec v_eb_e, arma::mat C_b_e, arma::vec &LLH, arma::vec &v_eb_n, arma::mat &C_b_n)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    //Compute the Latitude of the ECEF position
 | 
				
			||||||
 | 
					    LLH = cart2geo(r_eb_e, 4);  //ECEF -> WGS84 geographical
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Calculate ECEF to Geographical coordinate transformation matrix using (2.150)
 | 
				
			||||||
 | 
					    double cos_lat = cos(LLH(0));
 | 
				
			||||||
 | 
					    double sin_lat = sin(LLH(0));
 | 
				
			||||||
 | 
					    double cos_long = cos(LLH(1));
 | 
				
			||||||
 | 
					    double sin_long = sin(LLH(1));
 | 
				
			||||||
 | 
					    //C++11 and arma >= 5.2
 | 
				
			||||||
 | 
					    //    arma::mat C_e_n = {{-sin_lat * cos_long, -sin_lat * sin_long,  cos_lat},
 | 
				
			||||||
 | 
					    //                      {-sin_long, cos_long, 0},
 | 
				
			||||||
 | 
					    //                      {-cos_lat * cos_long, -cos_lat * sin_long, -sin_lat}}; //ECEF to Geo
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //C++98 arma <5.2
 | 
				
			||||||
 | 
					    arma::mat C_e_n = arma::zeros(3, 3);
 | 
				
			||||||
 | 
					    C_e_n << -sin_lat * cos_long << -sin_lat * sin_long << cos_lat << arma::endr
 | 
				
			||||||
 | 
					          << -sin_long << cos_long << 0 << arma::endr
 | 
				
			||||||
 | 
					          << -cos_lat * cos_long << -cos_lat * sin_long << -sin_lat << arma::endr;  //ECEF to Geo
 | 
				
			||||||
 | 
					    // Transform velocity using (2.73)
 | 
				
			||||||
 | 
					    v_eb_n = C_e_n * v_eb_e;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    C_b_n = C_e_n * C_b_e;  // Attitude conversion from ECEF to NED
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Geo_to_ECEF(arma::vec LLH, arma::vec v_eb_n, arma::mat C_b_n, arma::vec &r_eb_e, arma::vec &v_eb_e, arma::mat &C_b_e)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    // Parameters
 | 
				
			||||||
 | 
					    double R_0 = 6378137;        //WGS84 Equatorial radius in meters
 | 
				
			||||||
 | 
					    double e = 0.0818191908425;  //WGS84 eccentricity
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Calculate transverse radius of curvature using (2.105)
 | 
				
			||||||
 | 
					    double R_E = R_0 / sqrt(1 - (e * sin(LLH(0))) * (e * sin(LLH(0))));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Convert position using (2.112)
 | 
				
			||||||
 | 
					    double cos_lat = cos(LLH(0));
 | 
				
			||||||
 | 
					    double sin_lat = sin(LLH(0));
 | 
				
			||||||
 | 
					    double cos_long = cos(LLH(1));
 | 
				
			||||||
 | 
					    double sin_long = sin(LLH(1));
 | 
				
			||||||
 | 
					    r_eb_e = {(R_E + LLH(2)) * cos_lat * cos_long,
 | 
				
			||||||
 | 
					        (R_E + LLH(2)) * cos_lat * sin_long,
 | 
				
			||||||
 | 
					        ((1 - e * e) * R_E + LLH(2)) * sin_lat};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    //Calculate ECEF to Geo coordinate transformation matrix using (2.150)
 | 
				
			||||||
 | 
					    //C++11 and arma>=5.2
 | 
				
			||||||
 | 
					    //    arma::mat C_e_n = {{-sin_lat * cos_long, -sin_lat * sin_long,  cos_lat},
 | 
				
			||||||
 | 
					    //                       {-sin_long,            cos_long,        0},
 | 
				
			||||||
 | 
					    //                       {-cos_lat * cos_long, -cos_lat * sin_long, -sin_lat}};
 | 
				
			||||||
 | 
					    //C++98 arma <5.2
 | 
				
			||||||
 | 
					    //Calculate ECEF to Geo coordinate transformation matrix using (2.150)
 | 
				
			||||||
 | 
					    arma::mat C_e_n = arma::zeros(3, 3);
 | 
				
			||||||
 | 
					    C_e_n << -sin_lat * cos_long << -sin_lat * sin_long << cos_lat << arma::endr
 | 
				
			||||||
 | 
					          << -sin_long << cos_long << 0 << arma::endr
 | 
				
			||||||
 | 
					          << -cos_lat * cos_long << -cos_lat * sin_long << -sin_lat << arma::endr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Transform velocity using (2.73)
 | 
				
			||||||
 | 
					    v_eb_e = C_e_n.t() * v_eb_n;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Transform attitude using (2.15)
 | 
				
			||||||
 | 
					    C_b_e = C_e_n.t() * C_b_n;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void pv_Geo_to_ECEF(double L_b, double lambda_b, double h_b, arma::vec v_eb_n, arma::vec &r_eb_e, arma::vec &v_eb_e)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					    //% Parameters
 | 
				
			||||||
 | 
					    double R_0 = 6378137;        //WGS84 Equatorial radius in meters
 | 
				
			||||||
 | 
					    double e = 0.0818191908425;  //WGS84 eccentricity
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Calculate transverse radius of curvature using (2.105)
 | 
				
			||||||
 | 
					    double R_E = R_0 / sqrt(1 - pow(e * sin(L_b), 2));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Convert position using (2.112)
 | 
				
			||||||
 | 
					    double cos_lat = cos(L_b);
 | 
				
			||||||
 | 
					    double sin_lat = sin(L_b);
 | 
				
			||||||
 | 
					    double cos_long = cos(lambda_b);
 | 
				
			||||||
 | 
					    double sin_long = sin(lambda_b);
 | 
				
			||||||
 | 
					    r_eb_e = {(R_E + h_b) * cos_lat * cos_long,
 | 
				
			||||||
 | 
					        (R_E + h_b) * cos_lat * sin_long,
 | 
				
			||||||
 | 
					        ((1 - pow(e, 2)) * R_E + h_b) * sin_lat};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Calculate ECEF to Geo coordinate transformation matrix using (2.150)
 | 
				
			||||||
 | 
					    arma::mat C_e_n = arma::zeros(3, 3);
 | 
				
			||||||
 | 
					    C_e_n << -sin_lat * cos_long << -sin_lat * sin_long << cos_lat << arma::endr
 | 
				
			||||||
 | 
					          << -sin_long << cos_long << 0 << arma::endr
 | 
				
			||||||
 | 
					          << -cos_lat * cos_long << -cos_lat * sin_long << -sin_lat << arma::endr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Transform velocity using (2.73)
 | 
				
			||||||
 | 
					    v_eb_e = C_e_n.t() * v_eb_n;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										156
									
								
								src/tests/system-tests/libs/geofunctions.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										156
									
								
								src/tests/system-tests/libs/geofunctions.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,156 @@
 | 
				
			|||||||
 | 
					/*!
 | 
				
			||||||
 | 
					 * \file geofunctions.h
 | 
				
			||||||
 | 
					 * \brief A set of coordinate transformations functions and helpers,
 | 
				
			||||||
 | 
					 * some of them migrated from MATLAB, for geographic information systems.
 | 
				
			||||||
 | 
					 * \author Javier Arribas, 2018. jarribas(at)cttc.es
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * -------------------------------------------------------------------------
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Copyright (C) 2010-2018  (see AUTHORS file for a list of contributors)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * GNSS-SDR is a software defined Global Navigation
 | 
				
			||||||
 | 
					 *          Satellite Systems receiver
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * This file is part of GNSS-SDR.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * GNSS-SDR is free software: you can redistribute it and/or modify
 | 
				
			||||||
 | 
					 * it under the terms of the GNU General Public License as published by
 | 
				
			||||||
 | 
					 * the Free Software Foundation, either version 3 of the License, or
 | 
				
			||||||
 | 
					 * (at your option) any later version.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * GNSS-SDR is distributed in the hope that it will be useful,
 | 
				
			||||||
 | 
					 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
				
			||||||
 | 
					 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
				
			||||||
 | 
					 * GNU General Public License for more details.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * You should have received a copy of the GNU General Public License
 | 
				
			||||||
 | 
					 * along with GNSS-SDR. If not, see <https://www.gnu.org/licenses/>.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * -------------------------------------------------------------------------
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#ifndef GEOFUNCTIONS_H
 | 
				
			||||||
 | 
					#define GEOFUNCTIONS_H
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include <armadillo>
 | 
				
			||||||
 | 
					//    %Skew_symmetric - Calculates skew-symmetric matrix
 | 
				
			||||||
 | 
					arma::mat Skew_symmetric(arma::vec a);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					double WGS84_g0(double Lat_rad);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					double WGS84_geocentric_radius(double Lat_geodetic_rad);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*  Transformation of vector dx into topocentric coordinate
 | 
				
			||||||
 | 
					      system with origin at x
 | 
				
			||||||
 | 
					         Inputs:
 | 
				
			||||||
 | 
					            x           - vector origin coordinates (in ECEF system [X; Y; Z;])
 | 
				
			||||||
 | 
					            dx          - vector ([dX; dY; dZ;]).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					         Outputs:
 | 
				
			||||||
 | 
					            D           - vector length. Units like the input
 | 
				
			||||||
 | 
					            Az          - azimuth from north positive clockwise, degrees
 | 
				
			||||||
 | 
					            El          - elevation angle, degrees
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            Based on a Matlab function by Kai Borre
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int topocent(double *Az, double *El, double *D, const arma::vec &x, const arma::vec &dx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Subroutine to calculate geodetic coordinates latitude, longitude,
 | 
				
			||||||
 | 
					        height given Cartesian coordinates X,Y,Z, and reference ellipsoid
 | 
				
			||||||
 | 
					        values semi-major axis (a) and the inverse of flattening (finv).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					         The output units of angular quantities will be in decimal degrees
 | 
				
			||||||
 | 
					          (15.5 degrees not 15 deg 30 min). The output units of h will be the
 | 
				
			||||||
 | 
					          same as the units of X,Y,Z,a.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					           Inputs:
 | 
				
			||||||
 | 
					               a           - semi-major axis of the reference ellipsoid
 | 
				
			||||||
 | 
					               finv        - inverse of flattening of the reference ellipsoid
 | 
				
			||||||
 | 
					               X,Y,Z       - Cartesian coordinates
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					           Outputs:
 | 
				
			||||||
 | 
					               dphi        - latitude
 | 
				
			||||||
 | 
					               dlambda     - longitude
 | 
				
			||||||
 | 
					               h           - height above reference ellipsoid
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					               Based in a Matlab function by Kai Borre
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					int togeod(double *dphi, double *dlambda, double *h, double a, double finv, double X, double Y, double Z);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//Gravitation_ECI - Calculates  acceleration due to gravity resolved about
 | 
				
			||||||
 | 
					//ECEF-frame
 | 
				
			||||||
 | 
					arma::mat Gravity_ECEF(arma::vec r_eb_e);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/* Conversion of Cartesian coordinates (X,Y,Z) to geographical
 | 
				
			||||||
 | 
					 coordinates (latitude, longitude, h) on a selected reference ellipsoid.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					   Choices of Reference Ellipsoid for Geographical Coordinates
 | 
				
			||||||
 | 
					             0. International Ellipsoid 1924
 | 
				
			||||||
 | 
					             1. International Ellipsoid 1967
 | 
				
			||||||
 | 
					             2. World Geodetic System 1972
 | 
				
			||||||
 | 
					             3. Geodetic Reference System 1980
 | 
				
			||||||
 | 
					             4. World Geodetic System 1984
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					arma::vec cart2geo(arma::vec XYZ, int elipsoid_selection);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					arma::vec LLH_to_deg(arma::vec LLH);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					double degtorad(double angleInDegrees);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					double radtodeg(double angleInRadians);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					double mstoknotsh(double MetersPerSeconds);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					double mstokph(double Kph);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					arma::vec CTM_to_Euler(arma::mat C);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					arma::mat Euler_to_CTM(arma::vec eul);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void ECEF_to_Geo(arma::vec r_eb_e, arma::vec v_eb_e, arma::mat C_b_e, arma::vec &LLH, arma::vec &v_eb_n, arma::mat &C_b_n);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//    %
 | 
				
			||||||
 | 
					//    % Inputs:
 | 
				
			||||||
 | 
					//    %   L_b           latitude (rad)
 | 
				
			||||||
 | 
					//    %   lambda_b      longitude (rad)
 | 
				
			||||||
 | 
					//    %   h_b           height (m)
 | 
				
			||||||
 | 
					//    %   v_eb_n        velocity of body frame w.r.t. ECEF frame, resolved along
 | 
				
			||||||
 | 
					//    %                 north, east, and down (m/s)
 | 
				
			||||||
 | 
					//    %   C_b_n         body-to-NED coordinate transformation matrix
 | 
				
			||||||
 | 
					//    %
 | 
				
			||||||
 | 
					//    % Outputs:
 | 
				
			||||||
 | 
					//    %   r_eb_e        Cartesian position of body frame w.r.t. ECEF frame, resolved
 | 
				
			||||||
 | 
					//    %                 along ECEF-frame axes (m)
 | 
				
			||||||
 | 
					//    %   v_eb_e        velocity of body frame w.r.t. ECEF frame, resolved along
 | 
				
			||||||
 | 
					//    %                 ECEF-frame axes (m/s)
 | 
				
			||||||
 | 
					//    %   C_b_e         body-to-ECEF-frame coordinate transformation matrix
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					//    % Copyright 2012, Paul Groves
 | 
				
			||||||
 | 
					//    % License: BSD; see license.txt for details
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void Geo_to_ECEF(arma::vec LLH, arma::vec v_eb_n, arma::mat C_b_n, arma::vec &r_eb_e, arma::vec &v_eb_e, arma::mat &C_b_e);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//pv_Geo_to_ECEF - Converts curvilinear to Cartesian position and velocity
 | 
				
			||||||
 | 
					//resolving axes from NED to ECEF
 | 
				
			||||||
 | 
					//This function created 11/4/2012 by Paul Groves
 | 
				
			||||||
 | 
					//%
 | 
				
			||||||
 | 
					//% Inputs:
 | 
				
			||||||
 | 
					//%   L_b           latitude (rad)
 | 
				
			||||||
 | 
					//%   lambda_b      longitude (rad)
 | 
				
			||||||
 | 
					//%   h_b           height (m)
 | 
				
			||||||
 | 
					//%   v_eb_n        velocity of body frame w.r.t. ECEF frame, resolved along
 | 
				
			||||||
 | 
					//%                 north, east, and down (m/s)
 | 
				
			||||||
 | 
					//%
 | 
				
			||||||
 | 
					//% Outputs:
 | 
				
			||||||
 | 
					//%   r_eb_e        Cartesian position of body frame w.r.t. ECEF frame, resolved
 | 
				
			||||||
 | 
					//%                 along ECEF-frame axes (m)
 | 
				
			||||||
 | 
					//%   v_eb_e        velocity of body frame w.r.t. ECEF frame, resolved along
 | 
				
			||||||
 | 
					//%                 ECEF-frame axes (m/s)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void pv_Geo_to_ECEF(double L_b, double lambda_b, double h_b, arma::vec v_eb_n, arma::vec &r_eb_e, arma::vec &v_eb_e);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
		Reference in New Issue
	
	Block a user