Program Listing for File attitude_dynamics.cc¶
↰ Return to documentation for file (dynamics/attitude_dynamics.cc)
#include "lupnt/dynamics/attitude_dynamics.h"
#include "lupnt/conversions/attitude_conversions.h"
#include "lupnt/conversions/frame_converter.h"
#include "lupnt/core/asset_factory.h"
#include "lupnt/data/kernels.h"
#include "lupnt/states/state.h"
namespace lupnt {
// AttitudeDynamics *************************************************************
AttitudeDynamics::AttitudeDynamics(Config& config) : Dynamics(config) {}
State AttitudeDynamics::Propagate(const State& x0, Real t0, Real tf, const State& rv) {
(void)rv;
return Propagate(x0, t0, tf, nullptr);
}
// FixedAttitudeDynamics *********************************************************
FixedAttitudeDynamics::FixedAttitudeDynamics(Config& config) : AttitudeDynamics(config) {}
State FixedAttitudeDynamics::Propagate(const State& x0, Real t0, Real tf, const State* u) {
(void)t0;
(void)u;
(void)tf;
return x0;
}
REGISTER_FACTORY_CLASS(AttitudeDynamics, FixedAttitudeDynamics)
// FixedPointingDynamics ********************************************************
FixedPointingDynamics::FixedPointingDynamics(Config& config) {
primary_axis_ = enum_cast<Axis>(config["primary_axis"].as<std::string>()).value();
primary_body_id_ = enum_cast<BodyId>(config["primary_body_id"].as<std::string>()).value();
secondary_axis_ = enum_cast<Axis>(config["secondary_axis"].as<std::string>()).value();
secondary_body_id_ = enum_cast<BodyId>(config["secondary_body_id"].as<std::string>()).value();
}
State FixedPointingDynamics::Propagate(const State& qw, Real t0, Real tf, const State* u) {
LUPNT_CHECK(false, "Position and velocity required for fixed pointing dynamics",
"FixedPointingDynamics");
(void)t0;
(void)u;
(void)tf;
return qw;
}
State FixedPointingDynamics::Propagate(const State& qw, Real t0, Real tf, const State& rv) {
(void)t0;
Frame frame = qw.GetFrame();
LUPNT_CHECK(frame == rv.GetFrame(),
fmt::format("Frame mismatch: {} {}", enum_name(frame), enum_name(rv.GetFrame())),
"FixedPointingDynamics");
LUPNT_CHECK(rv.GetType() == Cart6::TYPE,
fmt::format("rv must be a Cart6 state: {}", rv.GetType()), "FixedPointingDynamics");
Vec3 r = rv.head(3);
auto func = [&](Real t) {
Vec3 dir1 = -r + GetBodyPos(GetLupntEpoch() + t, primary_body_id_, frame);
Vec3 dir2 = -r + GetBodyPos(GetLupntEpoch() + t, secondary_body_id_, frame);
int i0 = static_cast<int>(primary_axis_);
int i1 = static_cast<int>(secondary_axis_);
int i2 = 3 - i0 - i1;
Vec3 e0, e1, e2;
e0 = dir1.normalized();
e1 = dir2.normalized();
e2 = (i1 == (i0 + 1) % 3) ? e0.cross(e1) : e1.cross(e0);
e1 = (i2 == (i0 + 1) % 3) ? e0.cross(e2) : e2.cross(e0);
Mat3 R_b2w = Mat3::Zero();
R_b2w.col(i0) = e0.normalized();
R_b2w.col(i1) = e1.normalized();
R_b2w.col(i2) = e2.normalized();
return (Vec9)R_b2w.reshaped();
};
Real t = tf.val();
Mat3 R_b2w = func(tf).reshaped(3, 3);
Mat3 R_b2w_dot = derivative(func, wrt(t), at(t)).reshaped(3, 3);
Vec3 w_w = RotToAngularVelocity(R_b2w, R_b2w_dot);
Vec4 q_b2w = RotToQuat(R_b2w);
return Attitude(q_b2w, w_w, qw.GetFrame());
}
REGISTER_FACTORY_CLASS(AttitudeDynamics, FixedPointingDynamics)
// Define the GetRegistry function for this specialization (must come before explicit
// instantiation)
template <> std::unordered_map<std::string, AssetFactory<AttitudeDynamics, Config&>::Creator>&
AssetFactory<AttitudeDynamics, Config&>::GetRegistry() {
return Registry();
}
// Explicit template instantiation to ensure single registry across library boundaries
template class AssetFactory<AttitudeDynamics, Config&>;
} // namespace lupnt