38 std::make_shared<ECEFProvider<Scalar>>(rotation_angle);
46 std::make_shared<ECEFProvider<Scalar>>(model, t_seconds);
54 auto provider = std::make_shared<NEDProvider<Scalar>>(lon, lat);
56 frames_[
FRAME_NED.id] = provider->frame();
60 auto provider = std::make_shared<ENUProvider<Scalar>>(lon, lat);
62 frames_[
FRAME_ENU.id] = provider->frame();
67 std::make_shared<GeocentricProvider<Scalar>>(lon, lat_gc);
74 auto provider = std::make_shared<RailProvider<Scalar>>(origin, azimuth,
83 std::make_shared<CDAProvider<Scalar>>(origin, bearing, m);
85 frames_[
FRAME_CDA.id] = provider->frame();
90 std::make_shared<BodyProvider<Scalar>>(yaw, pitch, roll);
101 providers_[
FRAME_BODY.id] = std::make_shared<BodyProvider<Scalar>>(q);
113 std::make_shared<WindProvider<Scalar>>(alpha, beta);
119 std::make_shared<StabilityProvider<Scalar>>(alpha);
125 if (!registry_.has_frame(
id)) {
135 "ECEF; use set_provider()");
139 std::make_shared<CoordinateFrameProvider<Scalar>>(
frame);
140 frames_[
id.id] =
frame;
145 if (!registry_.has_frame(
id)) {
155 providers_[
id.id] = std::move(provider);
156 frames_[
id.id].reset();
164 FrameID id = registry_.register_frame(name, parent);
166 providers_[
id.id] = std::move(provider);
167 frames_[
id.id].reset();
177 assert_registered(from);
178 assert_registered(to);
184 if (registry_.parent_of(from) == to) {
185 return provider_for_child(from)->to_parent(v);
189 if (registry_.parent_of(to) == from) {
190 return provider_for_child(to)->from_parent(v);
193 return chain(from, to).transform_vector(v);
199 assert_registered(from);
200 assert_registered(to);
206 if (registry_.parent_of(from) == to) {
207 return provider_for_child(from)->position_to_parent(pos);
211 if (registry_.parent_of(to) == from) {
212 return provider_for_child(to)->position_from_parent(pos);
215 return chain(from, to).transform_position(pos);
219 assert_registered(from);
220 assert_registered(to);
223 identity_path.
frames = {from};
224 identity_path.
lca = from;
230 const FramePath path = registry_.find_path(from, to);
234 return build_chain(path);
242 assert_registered(
id);
243 if (
id.
id >= frames_.size() || !frames_[
id.id].has_value()) {
245 "Requested frame is not available as CoordinateFrame");
247 return *frames_[
id.id];
254 std::vector<std::shared_ptr<TransformProvider<Scalar>>> providers_;
255 std::vector<std::optional<CoordinateFrame<Scalar>>> frames_;
257 void initialize_storage() {
258 providers_.resize(registry_.
size());
259 frames_.resize(registry_.
size());
267 std::make_shared<ECEFProvider<Scalar>>(Scalar(0));
275 void ensure_capacity(FrameID
id) {
276 const size_t needed =
static_cast<size_t>(
id.id + 1);
277 if (providers_.size() < needed) {
278 providers_.resize(needed);
280 if (frames_.size() < needed) {
281 frames_.resize(needed);
285 void assert_registered(FrameID
id)
const {
286 if (!registry_.has_frame(
id)) {
287 throw CoordinateError(
"Frame is not registered in this context");
291 [[nodiscard]]
bool has_cached_frame(FrameID
id)
const {
292 return id.id < frames_.
size() && frames_[
id.id].has_value();
295 [[nodiscard]] std::shared_ptr<TransformProvider<Scalar>>
296 provider_for_child(FrameID child)
const {
297 if (child.id >= providers_.size() || !providers_[child.id]) {
298 throw CoordinateError(
"Missing provider for frame edge");
300 return providers_[child.id];
303 [[nodiscard]] TransformChain<Scalar>
304 build_chain(
const FramePath &path)
const {
305 std::vector<std::shared_ptr<TransformProvider<Scalar>>> ascending;
306 std::vector<std::shared_ptr<TransformProvider<Scalar>>> descending;
307 ascending.reserve(
static_cast<size_t>(path.ascending_count));
308 descending.reserve(
static_cast<size_t>(path.descending_count));
312 for (
int i = 0; i < path.ascending_count; ++i) {
313 const FrameID child = path.frames[
static_cast<size_t>(i)];
314 const FrameID parent = path.frames[
static_cast<size_t>(i + 1)];
315 if (registry_.parent_of(child) != parent) {
316 throw CoordinateError(
317 "Invalid path topology while building chain");
319 ascending.push_back(provider_for_child(child));
324 const int start = path.ascending_count + 1;
325 for (
int i = start; i < static_cast<int>(path.frames.size()); ++i) {
326 const FrameID parent = path.frames[
static_cast<size_t>(i - 1)];
327 const FrameID child = path.frames[
static_cast<size_t>(i)];
328 if (registry_.parent_of(child) != parent) {
329 throw CoordinateError(
330 "Invalid path topology while building chain");
332 descending.push_back(provider_for_child(child));
335 return TransformChain<Scalar>(path, ascending, descending);
Exception hierarchy for Vulcan aerospace library.
Coordinate system errors (invalid LLA, singularities).
Definition VulcanError.hpp:53
Vec3< Scalar > transform_position(const Vec3< Scalar > &pos, FrameID from, FrameID to) const
Definition FrameContext.hpp:196
const FrameRegistry & registry() const
Definition FrameContext.hpp:250
void set_geocentric(Scalar lon, Scalar lat_gc)
Definition FrameContext.hpp:65
void set_provider(FrameID id, std::shared_ptr< TransformProvider< Scalar > > provider)
Definition FrameContext.hpp:143
void set_frame(FrameID id, const CoordinateFrame< Scalar > &frame)
Set a frame using CoordinateFrame math (requires parent=ECEF).
Definition FrameContext.hpp:124
void set_ned(Scalar lon, Scalar lat)
Definition FrameContext.hpp:53
void set_body_euler(Scalar yaw, Scalar pitch, Scalar roll)
Definition FrameContext.hpp:88
void set_stability(Scalar alpha)
Definition FrameContext.hpp:117
FrameContext()
Definition FrameContext.hpp:23
TransformChain< Scalar > chain(FrameID from, FrameID to) const
Definition FrameContext.hpp:218
void set_body_quaternion(const janus::Quaternion< Scalar > &q)
Definition FrameContext.hpp:100
FrameID add_frame(const std::string &name, FrameID parent, std::shared_ptr< TransformProvider< Scalar > > provider)
Definition FrameContext.hpp:159
const CoordinateFrame< Scalar > & frame(FrameID id) const
Definition FrameContext.hpp:241
void set_ecef(Scalar rotation_angle)
Definition FrameContext.hpp:36
void set_cda(const LLA< Scalar > &origin, Scalar bearing, const EarthModel &m=EarthModel::WGS84())
Definition FrameContext.hpp:80
void set_wind(Scalar alpha, Scalar beta)
Definition FrameContext.hpp:111
void set_ecef(const EarthRotationModel &model, double t_seconds)
Definition FrameContext.hpp:44
FrameContext(FrameRegistry registry)
Definition FrameContext.hpp:27
void set_enu(Scalar lon, Scalar lat)
Definition FrameContext.hpp:59
Vec3< Scalar > transform(const Vec3< Scalar > &v, FrameID from, FrameID to) const
Definition FrameContext.hpp:175
void set_rail(const LLA< Scalar > &origin, Scalar azimuth, Scalar elevation, const EarthModel &m=EarthModel::WGS84())
Definition FrameContext.hpp:72
Setup-time frame tree registry with LCA path finding.
Definition FrameRegistry.hpp:32
size_t size() const
Definition FrameRegistry.hpp:153
bool has_frame(FrameID id) const
Definition FrameRegistry.hpp:125
Definition Aerodynamics.hpp:11
constexpr FrameID FRAME_GEOCENTRIC
Definition FrameID.hpp:56
CoordinateFrame< Scalar > body_from_euler(const CoordinateFrame< Scalar > &ned, Scalar yaw, Scalar pitch, Scalar roll)
Definition FrameVehicle.hpp:99
constexpr FrameID FRAME_ECI
Definition FrameID.hpp:49
CoordinateFrame< Scalar > body_from_quaternion(const CoordinateFrame< Scalar > &ned, const janus::Quaternion< Scalar > &q_body_to_ned)
Definition FrameVehicle.hpp:29
constexpr FrameID FRAME_CDA
Definition FrameID.hpp:58
constexpr FrameID FRAME_RAIL
Definition FrameID.hpp:57
constexpr FrameID FRAME_WIND
Definition FrameID.hpp:54
constexpr FrameID FRAME_BODY
Definition FrameID.hpp:53
constexpr FrameID FRAME_ECEF
Definition FrameID.hpp:50
constexpr FrameID FRAME_STABILITY
Definition FrameID.hpp:55
constexpr FrameID FRAME_ENU
Definition FrameID.hpp:52
constexpr FrameID FRAME_NED
Definition FrameID.hpp:51
Definition FramePrimitives.hpp:44
static CoordinateFrame eci(Scalar gmst)
Definition FramePrimitives.hpp:243
static CoordinateFrame ecef()
Definition FramePrimitives.hpp:231
Definition EarthModel.hpp:27
static constexpr EarthModel WGS84()
WGS84 reference ellipsoid (most common for GPS/navigation).
Definition EarthModel.hpp:45
Definition EarthModel.hpp:75
virtual double ecef_to_eci_angle(double t_seconds) const
Definition EarthModel.hpp:85
Universal frame identifier.
Definition FrameID.hpp:25
uint32_t id
Definition FrameID.hpp:26
Ordered path between frames from source to target.
Definition FrameRegistry.hpp:15
std::vector< FrameID > frames
Definition FrameRegistry.hpp:16
int descending_count
Definition FrameRegistry.hpp:19
bool is_valid() const
Definition FrameRegistry.hpp:21
int ascending_count
Definition FrameRegistry.hpp:18
FrameID lca
Definition FrameRegistry.hpp:17
Definition Geodetic.hpp:27