File DynamicFrame.hpp¶
File List > astrea > astro > astro > frames > types > DynamicFrame.hpp
Go to the documentation of this file
#pragma once
#include <string>
#include <astro/frames/CartesianVector.hpp>
#include <astro/frames/Frame.hpp>
#include <astro/frames/FrameReference.hpp>
#include <astro/frames/frames.hpp>
#include <astro/time/Date.hpp>
#include <astro/types/typedefs.hpp>
namespace astrea {
namespace astro {
template <class Frame_T, FrameAxis axis>
requires(axis != FrameAxis::ICRF && axis != FrameAxis::J2000 && axis != FrameAxis::BODY_FIXED)
struct DynamicFrame : public Frame<CelestialBodyId::CUSTOM, axis> {
protected:
DynamicFrame(const FrameReference* parent) :
_parent(parent),
_isInstantaneous(false)
{
if (parent == nullptr) {
throw std::invalid_argument(
"Parent of a dynamic frame cannot be null. Use Frame_T::instantaneous(r, v) "
"for instantaneous dynamic state/frames."
);
}
}
DynamicFrame(const RadiusVector<frames::earth::icrf>& position, const VelocityVector<frames::earth::icrf>& velocity) :
_position(position),
_velocity(velocity),
_isInstantaneous(true)
{
}
public:
static constexpr CelestialBodyId get_origin() { return Frame<CelestialBodyId::CUSTOM, axis>::get_origin(); }
static constexpr FrameAxis get_axis() { return Frame<CelestialBodyId::CUSTOM, axis>::get_axis(); }
static Frame_T instantaneous(const RadiusVector<frames::earth::icrf>& position, const VelocityVector<frames::earth::icrf>& velocity)
{
return Frame_T(position, velocity);
}
template <typename Value_T>
CartesianVector<Value_T, Frame_T>
rotate_into_this_frame(const CartesianVector<Value_T, frames::earth::icrf>& vec, const Date& date) const
{
return get_dcm_impl(date) * vec;
}
template <typename Value_T>
CartesianVector<Value_T, frames::earth::icrf>
rotate_out_of_this_frame(const CartesianVector<Value_T, Frame_T>& vec, const Date& date) const
{
return get_dcm_impl(date).transpose() * vec;
}
RadiusVector<Frame_T> convert_to_this_frame(const RadiusVector<frames::earth::icrf>& vec, const Date& date) const
{
return get_dcm_impl(date) * (vec - get_inertial_position(date));
}
RadiusVector<frames::earth::icrf> convert_from_this_frame(const RadiusVector<Frame_T>& vec, const Date& date) const
{
return get_dcm_impl(date).transpose() * vec + get_inertial_position(date);
}
private:
DCM<frames::earth::icrf, Frame_T> get_dcm_impl(const Date& date) const
{
return static_cast<const Frame_T*>(this)->get_dcm(date);
}
RadiusVector<frames::earth::icrf> get_center_offset(const Date& date) const { return get_inertial_position(date); }
protected:
const FrameReference* _parent;
RadiusVector<frames::earth::icrf> _position;
VelocityVector<frames::earth::icrf> _velocity;
bool _isInstantaneous;
RadiusVector<frames::earth::icrf> get_inertial_position(const Date& date) const
{
return _isInstantaneous ? _position : _parent->get_inertial_position(date); // TODO: maybe store date for instantaneous and throw here if it doesn't match
}
VelocityVector<frames::earth::icrf> get_inertial_velocity(const Date& date) const
{
return _isInstantaneous ? _velocity : _parent->get_inertial_velocity(date);
}
};
} // namespace astro
} // namespace astrea