Program Listing for File frame_converter.cc¶
↰ Return to documentation for file (conversions/frame_converter.cc)
#include "lupnt/conversions/frame_converter.h"
#include "lupnt/conversions/frame_conversions.h"
#include "lupnt/conversions/frame_converter.h"
#include "lupnt/conversions/frame_converter_spice.h"
#include "lupnt/conversions/state_converter.h"
#include "lupnt/core/constants.h"
#include "lupnt/states/state.h"
#define FRAME_CONVERSION(from, to, func) \
{{Frame::from, Frame::to}, [](Real t, const Vec6& rv) -> Vec6 { return func(t, rv); }}
namespace lupnt {
const std::map<Frame, BodyId> frame_centers = {
// Earth
{Frame::ITRF, BodyId::EARTH},
{Frame::ECEF, BodyId::EARTH},
{Frame::GCRF, BodyId::EARTH},
{Frame::EME, BodyId::EARTH},
{Frame::ECI, BodyId::EARTH},
{Frame::ICRF, BodyId::SOLAR_SYSTEM_BARYCENTER},
// Moon
{Frame::MOON_ME, BodyId::MOON},
{Frame::MOON_CI, BodyId::MOON},
{Frame::MOON_PA, BodyId::MOON},
{Frame::MOON_OP, BodyId::MOON},
// Solar System
{Frame::MARS_FIXED, BodyId::MARS},
{Frame::VENUS_FIXED, BodyId::VENUS},
};
BodyId GetFrameCenter(Frame frame) {
auto it = frame_centers.find(frame);
LUPNT_CHECK(it != frame_centers.end(),
fmt::format("Frame {} not found in frame_centers", enum_name(frame)),
"FrameConverter");
return it->second;
}
std::ostream& operator<<(std::ostream& os, Frame frame) {
switch (frame) {
case Frame::ITRF: os << "ITRF"; break;
case Frame::GCRF: os << "GCRF"; break;
case Frame::EME: os << "EME"; break;
case Frame::ICRF: os << "ICRF"; break;
case Frame::SER: os << "SER"; break;
case Frame::GSE: os << "GSE"; break;
case Frame::MOD: os << "MOD"; break;
case Frame::TOD: os << "TOD"; break;
case Frame::EMR: os << "EMR"; break;
case Frame::MOON_CI: os << "MOON_CI"; break;
case Frame::MOON_PA: os << "MOON_PA"; break;
case Frame::MOON_ME: os << "MOON_ME"; break;
case Frame::MOON_OP: os << "MOON_OP"; break;
case Frame::MARS_FIXED: os << "MARS_FIXED"; break;
case Frame::VENUS_FIXED: os << "VENUS_FIXED"; break;
default: throw std::runtime_error("Frame not implemented");
}
return os;
}
template <int N>
Vec<N> ConvertFrameBase(Real t_tdb, const Vec<N>& rv_in, Frame frame_in, Frame frame_out) {
if (frame_in == frame_out) return rv_in;
switch (frame_in) {
// Earth ***************
case Frame::ICRF:
return ConvertFrame(t_tdb, IcrfToGcrf(t_tdb, rv_in), Frame::GCRF, frame_out);
case Frame::ITRF: // Frame::ECEF:
return ConvertFrame(t_tdb, ItrfToGcrf(t_tdb, rv_in), Frame::GCRF, frame_out);
case Frame::GCRF:
switch (frame_out) {
case Frame::ICRF: return GcrfToIcrf(t_tdb, rv_in);
case Frame::ITRF: return GcrfToItrf(t_tdb, rv_in);
case Frame::SER:
case Frame::GSE: throw std::runtime_error("Not implemented");
case Frame::EMR: return GcrfToEmr(t_tdb, rv_in);
case Frame::EME: return GcrfToEme(rv_in);
case Frame::MOD:
case Frame::TOD: throw std::runtime_error("Not implemented");
case Frame::MOON_PA:
case Frame::MOON_ME:
case Frame::MOON_OP:
case Frame::MOON_CI:
return ConvertFrame(t_tdb, GcrfToMoonCi(t_tdb, rv_in), Frame::MOON_CI, frame_out);
default: throw std::runtime_error("Not implemented");
}
case Frame::EME: // Frame::ECI:
return ConvertFrame(t_tdb, EmeToGcrf(rv_in), Frame::GCRF, frame_out);
case Frame::EMR: return ConvertFrame(t_tdb, EmrToGcrf(t_tdb, rv_in), Frame::GCRF, frame_out);
case Frame::SER:
case Frame::GSE:
case Frame::MOD:
case Frame::TOD: throw std::runtime_error("Not implemented");
// Moon ***************
case Frame::MOON_CI:
switch (frame_out) {
case Frame::MOON_OP: return MoonCiToOp(t_tdb, rv_in);
case Frame::MOON_PA: return MoonCiToPa(t_tdb, rv_in);
case Frame::MOON_ME: return MoonPaToMe(MoonCiToPa(t_tdb, rv_in));
default: return ConvertFrame(t_tdb, MoonCiToGcrf(t_tdb, rv_in), Frame::GCRF, frame_out);
}
case Frame::MOON_ME: return ConvertFrame(t_tdb, MoonMeToPa(rv_in), Frame::MOON_PA, frame_out);
case Frame::MOON_PA: {
if (frame_out == Frame::MOON_ME) return MoonPaToMe(rv_in);
return ConvertFrame(t_tdb, MoonPaToCi(t_tdb, rv_in), Frame::MOON_CI, frame_out);
}
case Frame::MOON_OP:
return ConvertFrame(t_tdb, MoonOpToCi(t_tdb, rv_in), Frame::MOON_CI, frame_out);
// Solar System ***************
case Frame::MERCURY_FIXED:
case Frame::VENUS_FIXED:
case Frame::MARS_FIXED:
case Frame::JUPITER_FIXED:
case Frame::SATURN_FIXED:
case Frame::URANUS_FIXED:
case Frame::NEPTUNE_FIXED:
case Frame::MERCURY_CI:
case Frame::VENUS_CI:
case Frame::MARS_CI:
case Frame::JUPITER_CI:
case Frame::SATURN_CI:
case Frame::URANUS_CI:
case Frame::NEPTUNE_CI:
case Frame::UNDEFINED: throw std::runtime_error("Not implemented");
}
throw std::runtime_error("Conversion not implemented");
return Vec<N>::Zero();
}
template Vec6 ConvertFrameBase(Real t_tdb, const Vec6& rv_in, Frame frame_in, Frame frame_out);
template Vec3 ConvertFrameBase(Real t_tdb, const Vec3& r_in, Frame frame_in, Frame frame_out);
Vec3 ConvertFrame(Real t_tdb, const Vec3& r_in, Frame frame_in, Frame frame_out,
bool rotate_only) {
if (frame_in == frame_out) return r_in;
if (!rotate_only) return ConvertFrameBase(t_tdb, r_in, frame_in, frame_out);
auto [R, r] = GetFrameRotationTranslation(t_tdb, frame_in, frame_out);
return R * r_in + r;
}
Vec6 ConvertFrame(Real t_tdb, const Vec6& rv_in, Frame frame_in, Frame frame_out,
bool rotate_only) {
if (frame_in == frame_out) return rv_in;
if (!rotate_only) return ConvertFrameBase(t_tdb, rv_in, frame_in, frame_out);
auto [R, r] = GetFrameRotationTranslation(t_tdb, frame_in, frame_out);
Vec6 rv_out;
rv_out.head(3) = R * rv_in.head(3) + r;
rv_out.tail(3) = R * rv_in.tail(3);
return rv_out;
}
MatX6 ConvertFrame(Real t_tdb, const MatX6& rv_in, Frame frame_in, Frame frame_out,
bool rotate_only) {
MatX6 rv_out(rv_in.rows(), 6);
if (rotate_only) {
auto [R, r] = GetFrameRotationTranslation(t_tdb, frame_in, frame_out);
for (int i = 0; i < rv_in.rows(); i++) {
rv_out.row(i).head(3) = R * rv_in.row(i).head(3).transpose() + r;
rv_out.row(i).tail(3) = R * rv_in.row(i).tail(3).transpose();
}
} else {
for (int i = 0; i < rv_in.rows(); i++)
rv_out.row(i)
= ConvertFrameBase(t_tdb, rv_in.row(i).transpose().eval(), frame_in, frame_out);
}
return rv_out;
}
MatX3 ConvertFrame(Real t_tdb, const MatX3& r_in, Frame frame_in, Frame frame_out,
bool rotate_only) {
MatX3 r_out(r_in.rows(), 3);
if (rotate_only) {
auto [R, r] = GetFrameRotationTranslation(t_tdb, frame_in, frame_out);
for (int i = 0; i < r_in.rows(); i++) r_out.row(i) = R * r_in.row(i).transpose() + r;
} else {
for (int i = 0; i < r_in.rows(); i++)
r_out.row(i) = ConvertFrameBase(t_tdb, r_in.row(i).transpose().eval(), frame_in, frame_out);
}
return r_out;
}
MatX6 ConvertFrame(const VecX& t_tdb, const Vec6& rv_in, Frame frame_in, Frame frame_out,
bool rotate_only) {
MatX6 rv_out(t_tdb.size(), 6);
for (int i = 0; i < t_tdb.size(); i++)
rv_out.row(i) = ConvertFrame(t_tdb(i), rv_in, frame_in, frame_out, rotate_only);
return rv_out;
}
MatX3 ConvertFrame(const VecX& t_tdb, const Vec3& r_in, Frame frame_in, Frame frame_out,
bool rotate_only) {
MatX3 r_out(t_tdb.size(), 3);
for (int i = 0; i < t_tdb.size(); i++)
r_out.row(i) = ConvertFrame(t_tdb(i), r_in, frame_in, frame_out, rotate_only);
return r_out;
}
MatX6 ConvertFrame(const VecX& t_tdb, const MatX6& rv_in, Frame frame_in, Frame frame_out,
bool rotate_only) {
LUPNT_CHECK(t_tdb.size() == rv_in.rows(), "Epoch and rv_in must have same size",
"FrameConverter");
MatX6 rv_out(t_tdb.size(), 6);
for (int i = 0; i < t_tdb.size(); i++)
rv_out.row(i) = ConvertFrame(t_tdb(i), rv_in.row(i).transpose().eval(), frame_in, frame_out,
rotate_only);
return rv_out;
}
MatX3 ConvertFrame(const VecX& t_tdb, const MatX3& r_in, Frame frame_in, Frame frame_out,
bool rotate_only) {
if (t_tdb.size() != r_in.rows()) throw std::runtime_error("Epoch and r_in must have same size");
MatX3 r_out(t_tdb.size(), 3);
for (int i = 0; i < t_tdb.size(); i++) {
Vec3 r_in_ = r_in.row(i).transpose();
r_out.row(i) = ConvertFrame(t_tdb(i), r_in_, frame_in, frame_out, rotate_only);
}
return r_out;
}
State ConvertFrame(Real t_tdb, const State& x_in, Frame frame_out, bool rotate_only) {
if (x_in.GetFrame() == frame_out) return x_in;
Cart6 rv_in = ConvertState(x_in, Cart6::TYPE);
Cart6 rv_out = ConvertFrame(t_tdb, Vec6(rv_in), x_in.GetFrame(), frame_out, rotate_only);
rv_out.SetFrame(frame_out);
return ConvertState(rv_out, x_in.GetType());
}
std::pair<Mat3, Vec3> GetFrameRotationTranslation(Real t_tdb, Frame from_frame, Frame to_frame) {
MatX3 I3 = Mat3::Identity();
Mat3 M = ConvertFrame(t_tdb, I3, from_frame, to_frame);
MatX3 r0 = MatX3::Zero(1, 3);
Vec3 r = ConvertFrame(t_tdb, r0, from_frame, to_frame).transpose();
Mat3 R = (M.rowwise() - r.transpose()).transpose();
return std::make_pair(R, r);
}
std::pair<Mat6, Vec6> GetFrameRotationTranslationRv(Real t_tdb, Frame from_frame,
Frame to_frame) {
// Transform the zero state -> this is the affine offset t6.
MatX6 zero_row = MatX6::Zero(1, 6);
Vec6 t6 = ConvertFrame(t_tdb, zero_row, from_frame, to_frame, false).row(0).transpose(); // 6x1
// Transform the six basis states (each row is one basis vector).
MatX6 I6 = Mat6::Identity();
MatX6 Y = ConvertFrame(t_tdb, I6, from_frame, to_frame, false); // 6x6
// Build R6: columns are (Y_row_i^T - t6), for i=0..5.
Mat6 R6;
for (int j = 0; j < 6; ++j) {
R6.col(j) = Y.row(j).transpose() - t6; // 6x1
}
return {R6, t6};
}
} // namespace lupnt