Program Listing for File gravity.hpp

Return to documentation for file (src/navtk/navutils/gravity.hpp)

#pragma once

#include <navtk/factory.hpp>
#include <navtk/inspect.hpp>
#include <navtk/navutils/navigation.hpp>
#include <navtk/tensors.hpp>

namespace navtk {
namespace navutils {

enum class GravModels {
    TITTERTON,
    SCHWARTZ,
    SAVAGE
};

Vector3 calculate_gravity_titterton(double alt, double lat, double R0);

template <typename S1, typename S2, IfBothTensorsOfDim<S1, S2, 0>* = nullptr>
Vector3 calculate_gravity_schwartz(const S1& alt, const S2& lat) {
    // Apply gravity model from K.P. Schwartz ENGO 623 Course Notes (University of Calgary)
    // This is the GRS80 gravity model from
    // http://geoweb.mit.edu/~tah/12.221_2005/grs80_corr.pdf
    // combined with the height variation correction given in
    // https://archive.org/details/HeiskanenMoritz1967PhysicalGeodesy/page/n87
    // eq 2-123
    const double a1 = 9.7803267715;
    const double a2 = 0.0052790414;
    const double a3 = 0.0000232718;
    const double a4 = -3.0876910891E-6;
    const double a5 = 4.3977311E-9;
    const double a6 = 7.211E-13;
    auto sin_lat    = sin(lat);
    auto sin2_lat   = sin_lat * sin_lat;
    auto sin4_lat   = sin2_lat * sin2_lat;

    double g = 0.0;
    if (alt >= 0)
        g = a1 * (1 + a2 * sin2_lat + a3 * sin4_lat) + (a4 + a5 * sin2_lat) * alt + a6 * alt * alt;
    else {
        // Original does not account for negative altitudes- implement
        // linear scaling of gravity at altitude 0 as recommended in Savage
        // 5.4-2 and done elsewhere (T+W)
        auto g0  = a1 * (1 + a2 * sin2_lat + a3 * sin4_lat);
        auto R_N = meridian_radius(lat);
        auto R_E = transverse_radius(lat);
        auto R_0 = sqrt(R_N * R_E);
        g        = g0 * (1 + alt / R_0);
    }
    return {0.0, 0.0, g};
}

template <typename B1 = Vector, typename B2 = Vector, IfTensorsMaxDim<1, B1, B2>* = nullptr>
Matrix calculate_gravity_schwartz(const B1& alt, const B2& lat) {
    auto alt_vec = to_vec(alt);
    auto lat_vec = to_vec(lat);
    // Apply gravity model from K.P. Schwartz ENGO 623 Course Notes (University of Calgary)
    // This is the GRS80 gravity model from
    // http://geoweb.mit.edu/~tah/12.221_2005/grs80_corr.pdf
    // combined with the height variation correction given in
    // https://archive.org/details/HeiskanenMoritz1967PhysicalGeodesy/page/n87
    // eq 2-123
    const size_t N = std::max(alt_vec.shape()[0], lat_vec.shape()[0]);

    Matrix gravity = empty(N, 3);

    const double a1 = 9.7803267715;
    const double a2 = 0.0052790414;
    const double a3 = 0.0000232718;
    const double a4 = -3.0876910891E-6;
    const double a5 = 4.3977311E-9;
    const double a6 = 7.211E-13;
    Scalar sin_lat, sin2_lat, sin4_lat, g0, r_0, altitude;

    // is it better to run these in a batch, or call with the single versions
    // of `meridian_radius` and `transverse_radius`, since they won't always
    // be needed?
    auto R_Ns = meridian_radius(lat_vec);
    auto R_Es = transverse_radius(lat_vec);

    for (size_t i = 0; i < N; i++) {
        gravity(i, 0) = 0;
        gravity(i, 1) = 0;

        altitude = alt_vec(i);

        sin_lat  = sin(lat_vec(i));
        sin2_lat = sin_lat * sin_lat;
        sin4_lat = sin2_lat * sin2_lat;

        if (altitude >= 0)
            gravity(i, 2) = a1 * (1 + a2 * sin2_lat + a3 * sin4_lat) +
                            (a4 + a5 * sin2_lat) * altitude + a6 * altitude * altitude;
        else {
            // Original does not account for negative altitudes- implement
            // linear scaling of gravity at altitude 0 as recommended in Savage
            // 5.4-2 and done elsewhere (T+W)
            g0            = a1 * (1 + a2 * sin2_lat + a3 * sin4_lat);
            r_0           = sqrt(R_Ns(i) * R_Es(i));
            gravity(i, 2) = g0 * (1 + altitude / r_0);
        }
    }

    return gravity;
}

Vector3 calculate_gravity_savage_n(const Matrix& C_n_to_e, double h);

Vector3 calculate_gravity_savage_ned(const Matrix& C_n_to_e, double h);
}  // namespace navutils
}  // namespace navtk