File OrbitalElements.hpp¶
File List > astrea > astro > astro > state > orbital_elements > OrbitalElements.hpp
Go to the documentation of this file
#pragma once
#include <iosfwd>
#include <variant>
#include <units/units.hpp>
// Astro
#include <astro/astro.fwd.hpp>
#include <astro/state/orbital_elements/instances/Cartesian.hpp>
#include <astro/state/orbital_elements/instances/Equinoctial.hpp>
#include <astro/state/orbital_elements/instances/Keplerian.hpp>
#include <astro/types/type_traits.hpp>
#include <astro/types/typedefs.hpp>
#include <astro/types/variant_util.hpp>
namespace astrea {
namespace astro {
template <typename T, typename U>
concept IsConstructableTo = requires(T elements, const GravParam& mu) {
{ U(elements, mu) };
};
template <typename T>
concept HasDirectCartesianConversion = requires(const T elements, const GravParam& mu) {
{ elements.to_cartesian(mu) } -> std::same_as<Cartesian>;
};
template <typename T>
concept HasDirectKeplerianConversion = requires(const T elements, const GravParam& mu) {
{ elements.to_keplerian(mu) } -> std::same_as<Keplerian>;
};
template <typename T>
concept HasDirectEquinoctialConversion = requires(const T elements, const GravParam& mu) {
{ elements.to_equinoctial(mu) } -> std::same_as<Equinoctial>;
};
template <typename T>
concept HasIterpolate =
requires(const T elements, const Time& thisTime, const Time& otherTime, const T& other, const GravParam& mu, const Time& targetTime) {
{ elements.interpolate(thisTime, otherTime, other, mu, targetTime) } -> std::same_as<T>;
};
template <typename T>
concept HasToVector = requires(const T elements) {
{ elements.force_to_vector() } -> std::same_as<std::vector<Unitless>>;
};
template <typename T>
concept HasMathOperators = requires(const T elements, const T other, const Unitless scalar) {
{ elements + other } -> std::same_as<T>;
{ elements - other } -> std::same_as<T>;
{ elements* scalar } -> std::same_as<T>;
{ elements / scalar } -> std::same_as<T>;
};
template <typename T>
concept HasInPlaceMathOperators = requires(T elements, const T other, const Unitless scalar) {
{ elements += other };
{ elements -= other };
{ elements *= scalar };
{ elements /= scalar };
};
template <typename T>
concept IsOrbitalElements = requires(T) {
std::is_same<T, remove_cv_ref<T>>::value;
std::is_default_constructible<T>::value;
std::is_copy_constructible<T>::value;
std::is_move_constructible<T>::value;
std::is_destructible<T>::value;
requires !std::is_same<T, OrbitalElements>::value;
requires std::is_same<T, Cartesian>::value || IsConstructableTo<T, Cartesian> || HasDirectCartesianConversion<T>;
requires HasToVector<T>;
requires HasMathOperators<T>;
requires HasInPlaceMathOperators<T>;
};
class OrbitalElementPartials; // Forward declaration
class OrbitalElements {
using ElementVariant = std::variant<Cartesian, Keplerian, Equinoctial>;
friend std::ostream& operator<<(std::ostream& os, const OrbitalElements& state);
friend class StateTransitionMatrix;
friend class State;
public:
OrbitalElements() :
_elements(Cartesian())
{
}
OrbitalElements(Cartesian elements) :
_elements(elements)
{
}
OrbitalElements(Keplerian elements) :
_elements(elements)
{
}
OrbitalElements(Equinoctial elements) :
_elements(elements)
{
}
OrbitalElements& convert_to_set(const std::size_t idx, const GravParam& mu);
OrbitalElements convert_to_set(const std::size_t idx, const GravParam& mu) const;
template <IsOrbitalElements T>
OrbitalElements& convert_to_set(const GravParam& mu)
{
_elements = in_element_set<T>(mu);
return *this;
}
template <IsOrbitalElements T>
OrbitalElements convert_to_set(const GravParam& mu) const
{
return in_element_set<T>(mu);
}
template <IsOrbitalElements T>
T in_element_set(const GravParam& mu) const
{
return std::visit([&](const auto& x) -> T { return T(x, mu); }, _elements);
}
bool operator==(const OrbitalElements& other) const;
OrbitalElements operator+(const OrbitalElements& other) const;
OrbitalElements& operator+=(const OrbitalElements& other);
OrbitalElements operator-(const OrbitalElements& other) const;
OrbitalElements& operator-=(const OrbitalElements& other);
OrbitalElements operator*(const Unitless& multiplier) const;
OrbitalElements& operator*=(const Unitless& multiplier);
OrbitalElementPartials operator/(const Time& divisor) const;
std::vector<Unitless> force_to_vector() const;
OrbitalElements operator/(const Unitless& divisor) const;
OrbitalElements& operator/=(const Unitless& divisor);
OrbitalElements
interpolate(const Time& thisTime, const Time& otherTime, const OrbitalElements& other, const GravParam& mu, const Time& targetTime) const;
const ElementVariant& extract() const;
ElementVariant& extract();
constexpr std::size_t index() const { return _elements.index(); }
template <typename T>
static constexpr std::size_t get_set_id()
{
return get_variant_index<ElementVariant, T, 0>();
}
private:
ElementVariant _elements;
OrbitalElements convert_to_set_impl(const std::size_t idx, const GravParam& mu) const;
static OrbitalElements from_vector(const std::vector<Unitless>& vec, const std::size_t idx);
};
class OrbitalElementPartials {
using PartialVariant = std::variant<CartesianPartial, KeplerianPartial, EquinoctialPartial>;
friend std::ostream& operator<<(std::ostream& os, const OrbitalElementPartials& state);
public:
OrbitalElementPartials() :
_elements(CartesianPartial())
{
}
OrbitalElementPartials(CartesianPartial elements) :
_elements(elements)
{
}
OrbitalElementPartials(KeplerianPartial elements) :
_elements(elements)
{
}
OrbitalElementPartials(EquinoctialPartial elements) :
_elements(elements)
{
}
OrbitalElements operator*(const Time& time) const;
const PartialVariant& extract() const;
PartialVariant& extract();
constexpr std::size_t index() const { return _elements.index(); }
std::vector<Unitless> force_to_vector() const;
private:
PartialVariant _elements;
void same_underlying_type(const OrbitalElementPartials& other) const;
};
void throw_mismatched_types();
bool nearly_equal(const OrbitalElements& first, const OrbitalElements& second, bool ignoreFastVariable = false, Unitless relTol = 1.0e-5 * astrea::detail::unitless);
bool nearly_equal(
const OrbitalElementPartials& first,
const OrbitalElementPartials& second,
bool ignoreFastVariable = false,
Unitless relTol = 1.0e-5 * astrea::detail::unitless
);
} // namespace astro
} // namespace astrea