File Equinoctial.cpp¶
File List > astrea > astro > astro > state > orbital_elements > instances > Equinoctial.cpp
Go to the documentation of this file
/*
* The GNU Lesser General Public License (LGPL)
*
* Copyright (c) 2025 Jay Iuliano
*
* This file is part of Astrea.
* Astrea is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
* Astrea 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 Lesser General Public License for more details. You should
* have received a copy of the GNU General Public License along with Astrea. If not, see <https://www.gnu.org/licenses/>.
*/
#include <astro/state/orbital_elements/instances/Equinoctial.hpp>
#include <iomanip>
#include <iostream>
#include <mp-units/math.h>
#include <mp-units/systems/angular/math.h>
#include <mp-units/systems/si.h>
#include <mp-units/systems/si/math.h>
#include <math/interpolation.hpp>
#include <astro/state/orbital_elements/OrbitalElements.hpp>
#include <astro/state/orbital_elements/instances/Keplerian.hpp>
#include <astro/systems/AstrodynamicsSystem.hpp>
#include <astro/types/typedefs.hpp>
#include <astro/utilities/conversions.hpp>
using namespace mp_units;
using namespace mp_units::angular;
using angular::unit_symbols::deg;
using angular::unit_symbols::rad;
using si::unit_symbols::km;
using si::unit_symbols::s;
namespace astrea {
namespace astro {
Equinoctial Equinoctial::LEO(const GravParam& mu) { return Equinoctial(Keplerian::LEO(), mu); }
Equinoctial Equinoctial::LMEO(const GravParam& mu) { return Equinoctial(Keplerian::LMEO(), mu); }
Equinoctial Equinoctial::GPS(const GravParam& mu) { return Equinoctial(Keplerian::GPS(), mu); }
Equinoctial Equinoctial::HMEO(const GravParam& mu) { return Equinoctial(Keplerian::HMEO(), mu); }
Equinoctial Equinoctial::GEO(const GravParam& mu) { return Equinoctial(Keplerian::GEO(), mu); }
Equinoctial::Equinoctial(const Keplerian& elements, const GravParam& mu)
{
// Get r and v
const auto& a = elements.get_semimajor();
const auto& ecc = elements.get_eccentricity();
const auto& inc = elements.get_inclination();
const auto& raan = elements.get_right_ascension();
const auto& argPer = elements.get_argument_of_perigee();
const auto& theta = elements.get_true_anomaly();
// Semilatus rectum
_semilatus = a * (1 - ecc * ecc);
// Non-dimensionalized parameters
_f = ecc * cos(argPer + raan);
_g = ecc * sin(argPer + raan);
_h = tan(inc / 2.0) * cos(raan);
_k = tan(inc / 2.0) * sin(raan);
// True longitude
_trueLongitude = wrap_angle(raan + argPer + theta);
}
Equinoctial::Equinoctial(const Cartesian& elements, const GravParam& mu) :
Equinoctial(Keplerian(elements, mu), mu)
{
}
Equinoctial::Equinoctial(const OrbitalElements& elements, const GravParam& mu)
{
*this = elements.in_element_set<Equinoctial>(mu);
}
// Copy constructor
Equinoctial::Equinoctial(const Equinoctial& other) :
_semilatus(other._semilatus),
_f(other._f),
_g(other._g),
_h(other._h),
_k(other._k),
_trueLongitude(other._trueLongitude)
{
}
// Move constructor
Equinoctial::Equinoctial(Equinoctial&& other) noexcept :
_semilatus(std::move(other._semilatus)),
_f(std::move(other._f)),
_g(std::move(other._g)),
_h(std::move(other._h)),
_k(std::move(other._k)),
_trueLongitude(std::move(other._trueLongitude))
{
}
// Move assignment operator
Equinoctial& Equinoctial::operator=(Equinoctial&& other) noexcept
{
if (this != &other) {
_semilatus = std::move(other._semilatus);
_f = std::move(other._f);
_g = std::move(other._g);
_h = std::move(other._h);
_k = std::move(other._k);
_trueLongitude = std::move(other._trueLongitude);
}
return *this;
}
// Copy assignment operator
Equinoctial& Equinoctial::operator=(const Equinoctial& other) { return *this = Equinoctial(other); }
// Comparitors operators
bool Equinoctial::operator==(const Equinoctial& other) const
{
return (
_semilatus == other._semilatus && _f == other._f && _g == other._g && _h == other._h && _k == other._k &&
_trueLongitude == other._trueLongitude
);
}
bool Equinoctial::operator!=(const Equinoctial& other) const { return !(*this == other); }
// Mathmatical operators
Equinoctial Equinoctial::operator+(const Equinoctial& other) const
{
return Equinoctial(
_semilatus + other._semilatus,
_f + other._f,
_g + other._g,
_h + other._h,
_k + other._k,
_trueLongitude + other._trueLongitude
);
}
Equinoctial& Equinoctial::operator+=(const Equinoctial& other)
{
_semilatus += other._semilatus;
_f += other._f;
_g += other._g;
_h += other._h;
_k += other._k;
_trueLongitude += other._trueLongitude;
return *this;
}
Equinoctial Equinoctial::operator-(const Equinoctial& other) const
{
return Equinoctial(
_semilatus - other._semilatus,
_f - other._f,
_g - other._g,
_h - other._h,
_k - other._k,
_trueLongitude - other._trueLongitude
);
}
Equinoctial& Equinoctial::operator-=(const Equinoctial& other)
{
_semilatus -= other._semilatus;
_f -= other._f;
_g -= other._g;
_h -= other._h;
_k -= other._k;
_trueLongitude -= other._trueLongitude;
return *this;
}
Equinoctial Equinoctial::operator*(const Unitless& multiplier) const
{
return Equinoctial(_semilatus * multiplier, _f * multiplier, _g * multiplier, _h * multiplier, _k * multiplier, _trueLongitude * multiplier);
}
Equinoctial& Equinoctial::operator*=(const Unitless& multiplier)
{
_semilatus *= multiplier;
_f *= multiplier;
_g *= multiplier;
_h *= multiplier;
_k *= multiplier;
_trueLongitude *= multiplier;
return *this;
}
EquinoctialPartial Equinoctial::operator/(const Time& time) const
{
return EquinoctialPartial(_semilatus / time, _f / time, _g / time, _h / time, _k / time, _trueLongitude / time);
}
Equinoctial Equinoctial::operator/(const Unitless& divisor) const
{
return Equinoctial(_semilatus / divisor, _f / divisor, _g / divisor, _h / divisor, _k / divisor, _trueLongitude / divisor);
}
Equinoctial& Equinoctial::operator/=(const Unitless& divisor)
{
_semilatus /= divisor;
_f /= divisor;
_g /= divisor;
_h /= divisor;
_k /= divisor;
_trueLongitude /= divisor;
return *this;
}
Equinoctial
Equinoctial::interpolate(const Time& thisTime, const Time& otherTime, const Equinoctial& other, const GravParam& mu, const Time& targetTime) const
{
const std::array<Time, 2> times = { thisTime, otherTime };
const Distance interpSemimajor =
math::fast_interpolate<Time, Distance>(times, { _semilatus, other.get_semilatus() }, targetTime);
const Unitless interpEcc = math::fast_interpolate<Time, Unitless>(times, { _f, other.get_f() }, targetTime);
const Unitless interpInc = math::fast_interpolate<Time, Unitless>(times, { _g, other.get_g() }, targetTime);
const Unitless interpRaan = math::fast_interpolate<Time, Unitless>(times, { _h, other.get_h() }, targetTime);
const Unitless interpArgPer = math::fast_interpolate<Time, Unitless>(times, { _k, other.get_k() }, targetTime);
const Angle interpTheta = math::fast_interpolate<Time, Angle>(times, { _trueLongitude, other.get_true_longitude() }, targetTime);
return Equinoctial(interpSemimajor, interpEcc, interpInc, interpRaan, interpArgPer, interpTheta);
}
std::vector<Unitless> Equinoctial::force_to_vector() const
{
return { _semilatus / _semilatus.unit, _f, _g, _h, _k, _trueLongitude / _trueLongitude.unit };
}
Equinoctial Equinoctial::from_vector(const std::vector<Unitless>& vec)
{
if (vec.size() != 6) {
throw std::runtime_error("Input vector must have exactly 6 elements to convert to Equinoctial.");
}
return Equinoctial(vec[0] * detail::distance_unit, vec[1], vec[2], vec[3], vec[4], vec[5] * detail::angle_unit);
}
Equinoctial EquinoctialPartial::operator*(const Time& time) const
{
return Equinoctial(_semilatusPartial * time, _fPartial * time, _gPartial * time, _hPartial * time, _kPartial * time, _trueLongitudePartial * time);
}
std::vector<Unitless> EquinoctialPartial::force_to_vector() const
{
return { _semilatusPartial / _semilatusPartial.unit,
_fPartial / _fPartial.unit,
_gPartial / _gPartial.unit,
_hPartial / _hPartial.unit,
_kPartial / _kPartial.unit,
_trueLongitudePartial / _trueLongitudePartial.unit };
}
std::ostream& operator<<(std::ostream& os, Equinoctial const& elements)
{
os << "[";
os << elements.get_semilatus() << ", ";
os << elements.get_f() << ", ";
os << elements.get_g() << ", ";
os << elements.get_h() << ", ";
os << elements.get_k() << ", ";
os << elements.get_true_longitude();
os << "] (Equinoctial)";
return os;
}
std::ostream& operator<<(std::ostream& os, EquinoctialPartial const& elements)
{
os << "[";
os << elements._semilatusPartial << ", ";
os << elements._fPartial << ", ";
os << elements._gPartial << ", ";
os << elements._hPartial << ", ";
os << elements._kPartial << ", ";
os << elements._trueLongitudePartial;
os << "] (EquinoctialPartial)";
return os;
}
} // namespace astro
} // namespace astrea