Vulcan
Aerospace Engineering Utilities Built on Janus
Loading...
Searching...
No Matches
FrameKinematics.hpp
Go to the documentation of this file.
1// Vulcan Coordinate Transforms
2// Velocity transforms and non-inertial accelerations for ECEF/ECI
3#pragma once
4
8
9#include <janus/math/Linalg.hpp>
10
11namespace vulcan {
12
13// =============================================================================
14// Velocity Transforms
15// =============================================================================
16
30template <typename Scalar>
31Vec3<Scalar> velocity_ecef_to_eci(const Vec3<Scalar> &v_ecef,
32 const Vec3<Scalar> &r_ecef,
33 const CoordinateFrame<Scalar> &eci,
34 const EarthModel &m = EarthModel::WGS84()) {
35 // Earth's angular velocity vector in ECEF: [0, 0, omega]
36 Vec3<Scalar> omega_ecef;
37 omega_ecef << Scalar(0), Scalar(0), Scalar(m.omega);
38
39 // omega x r gives velocity contribution from rotation
40 Vec3<Scalar> omega_cross_r = janus::cross(omega_ecef, r_ecef);
41
42 // v_ecef_inertial = v_ecef + omega x r (velocity of ECEF point in inertial
43 // frame)
44 Vec3<Scalar> v_ecef_inertial = v_ecef + omega_cross_r;
45
46 // Transform to ECI
47 return eci.from_ecef(v_ecef_inertial);
48}
49
61template <typename Scalar>
62Vec3<Scalar> velocity_eci_to_ecef(const Vec3<Scalar> &v_eci,
63 const Vec3<Scalar> &r_ecef,
64 const CoordinateFrame<Scalar> &eci,
65 const EarthModel &m = EarthModel::WGS84()) {
66 // Transform v_eci to ECEF
67 Vec3<Scalar> v_ecef_inertial = eci.to_ecef(v_eci);
68
69 // Earth's angular velocity in ECEF
70 Vec3<Scalar> omega_ecef;
71 omega_ecef << Scalar(0), Scalar(0), Scalar(m.omega);
72
73 // Subtract omega x r
74 Vec3<Scalar> omega_cross_r = janus::cross(omega_ecef, r_ecef);
75
76 return v_ecef_inertial - omega_cross_r;
77}
78
79// =============================================================================
80// Non-Inertial Accelerations
81// =============================================================================
82
105template <typename Scalar>
106Vec3<Scalar> coriolis_centrifugal(const Vec3<Scalar> &r_ecef,
107 const Vec3<Scalar> &v_ecef,
108 const EarthModel &m = EarthModel::WGS84()) {
109 // Earth's angular velocity vector in ECEF: [0, 0, omega]
110 Vec3<Scalar> omega;
111 omega << Scalar(0), Scalar(0), Scalar(m.omega);
112
113 // Coriolis: -2(omega x v)
114 Vec3<Scalar> coriolis = Scalar(-2) * janus::cross(omega, v_ecef);
115
116 // Centrifugal: -omega x (omega x r)
117 Vec3<Scalar> omega_cross_r = janus::cross(omega, r_ecef);
118 Vec3<Scalar> centrifugal = -janus::cross(omega, omega_cross_r);
119
120 return coriolis + centrifugal;
121}
122
129template <typename Scalar>
130Vec3<Scalar> coriolis_acceleration(const Vec3<Scalar> &v_ecef,
131 const EarthModel &m = EarthModel::WGS84()) {
132 Vec3<Scalar> omega;
133 omega << Scalar(0), Scalar(0), Scalar(m.omega);
134
135 return Scalar(-2) * janus::cross(omega, v_ecef);
136}
137
144template <typename Scalar>
145Vec3<Scalar>
146centrifugal_acceleration(const Vec3<Scalar> &r_ecef,
147 const EarthModel &m = EarthModel::WGS84()) {
148 Vec3<Scalar> omega;
149 omega << Scalar(0), Scalar(0), Scalar(m.omega);
150
151 Vec3<Scalar> omega_cross_r = janus::cross(omega, r_ecef);
152 return -janus::cross(omega, omega_cross_r);
153}
154
155// =============================================================================
156// Relative Position/Velocity
157// =============================================================================
158
165template <typename Scalar>
166Vec3<Scalar> relative_position(const Vec3<Scalar> &r_target,
167 const Vec3<Scalar> &r_observer) {
168 return r_target - r_observer;
169}
170
177template <typename Scalar>
178Scalar range(const Vec3<Scalar> &r1, const Vec3<Scalar> &r2) {
179 return janus::norm(r1 - r2);
180}
181
190template <typename Scalar>
191Scalar range_rate(const Vec3<Scalar> &r_target, const Vec3<Scalar> &v_target,
192 const Vec3<Scalar> &r_observer,
193 const Vec3<Scalar> &v_observer) {
194 Vec3<Scalar> r_rel = r_target - r_observer;
195 Vec3<Scalar> v_rel = v_target - v_observer;
196
197 Scalar r_mag = janus::norm(r_rel);
198 Scalar eps = Scalar(1e-10);
199 Scalar is_zero = r_mag < eps;
200
201 // Range rate = relative velocity dot unit line-of-sight
202 Scalar rdot = janus::dot(r_rel, v_rel) / r_mag;
203
204 // Handle zero range case
205 return janus::where(is_zero, Scalar(0), rdot);
206}
207
208// =============================================================================
209// State Propagation Helpers
210// =============================================================================
211
229template <typename Scalar>
230Vec3<Scalar> omega_ned_wrt_ecef(const Vec3<Scalar> &v_ned, Scalar lat,
231 Scalar alt,
232 const EarthModel &m = EarthModel::WGS84()) {
233 Scalar sin_lat = janus::sin(lat);
234 Scalar cos_lat = janus::cos(lat);
235
236 // Radius of curvature in meridian
237 Scalar denom = janus::sqrt(Scalar(1) - Scalar(m.e2) * sin_lat * sin_lat);
238 Scalar R_n =
239 Scalar(m.a) * (Scalar(1) - Scalar(m.e2)) / (denom * denom * denom);
240 R_n = R_n + alt;
241
242 // Radius of curvature in prime vertical
243 Scalar R_e = Scalar(m.a) / denom + alt;
244
245 // Angular velocity of NED wrt ECEF in NED coordinates
246 Vec3<Scalar> omega;
247 omega << -v_ned(0) / R_n, v_ned(1) / R_e, v_ned(1) * janus::tan(lat) / R_e;
248
249 return omega;
250}
251
264template <typename Scalar>
265Vec3<Scalar> omega_ned_wrt_eci(const Vec3<Scalar> &v_ned, Scalar lat,
266 Scalar alt,
267 const EarthModel &m = EarthModel::WGS84()) {
268 // Angular velocity of NED wrt ECEF
269 Vec3<Scalar> omega_ned_ecef = omega_ned_wrt_ecef(v_ned, lat, alt, m);
270
271 // Earth's angular velocity in NED: [omega*cos(lat), 0, -omega*sin(lat)]
272 Scalar sin_lat = janus::sin(lat);
273 Scalar cos_lat = janus::cos(lat);
274
275 Vec3<Scalar> omega_earth_ned;
276 omega_earth_ned << Scalar(m.omega) * cos_lat, Scalar(0),
277 -Scalar(m.omega) * sin_lat;
278
279 return omega_ned_ecef + omega_earth_ned;
280}
281
282} // namespace vulcan
Definition Aerodynamics.hpp:11
Scalar range(const Vec3< Scalar > &r1, const Vec3< Scalar > &r2)
Definition FrameKinematics.hpp:178
Vec3< Scalar > coriolis_centrifugal(const Vec3< Scalar > &r_ecef, const Vec3< Scalar > &v_ecef, const EarthModel &m=EarthModel::WGS84())
Definition FrameKinematics.hpp:106
Vec3< Scalar > centrifugal_acceleration(const Vec3< Scalar > &r_ecef, const EarthModel &m=EarthModel::WGS84())
Definition FrameKinematics.hpp:146
Vec3< Scalar > velocity_eci_to_ecef(const Vec3< Scalar > &v_eci, const Vec3< Scalar > &r_ecef, const CoordinateFrame< Scalar > &eci, const EarthModel &m=EarthModel::WGS84())
Definition FrameKinematics.hpp:62
Vec3< Scalar > coriolis_acceleration(const Vec3< Scalar > &v_ecef, const EarthModel &m=EarthModel::WGS84())
Definition FrameKinematics.hpp:130
Vec3< Scalar > velocity_ecef_to_eci(const Vec3< Scalar > &v_ecef, const Vec3< Scalar > &r_ecef, const CoordinateFrame< Scalar > &eci, const EarthModel &m=EarthModel::WGS84())
Definition FrameKinematics.hpp:31
Scalar range_rate(const Vec3< Scalar > &r_target, const Vec3< Scalar > &v_target, const Vec3< Scalar > &r_observer, const Vec3< Scalar > &v_observer)
Definition FrameKinematics.hpp:191
Vec3< Scalar > relative_position(const Vec3< Scalar > &r_target, const Vec3< Scalar > &r_observer)
Definition FrameKinematics.hpp:166
Vec3< Scalar > omega_ned_wrt_eci(const Vec3< Scalar > &v_ned, Scalar lat, Scalar alt, const EarthModel &m=EarthModel::WGS84())
Definition FrameKinematics.hpp:265
Vec3< Scalar > omega_ned_wrt_ecef(const Vec3< Scalar > &v_ned, Scalar lat, Scalar alt, const EarthModel &m=EarthModel::WGS84())
Definition FrameKinematics.hpp:230
Definition FramePrimitives.hpp:44
Vec3< Scalar > to_ecef(const Vec3< Scalar > &v) const
Definition FramePrimitives.hpp:90
Vec3< Scalar > from_ecef(const Vec3< Scalar > &v) const
Definition FramePrimitives.hpp:75
Definition EarthModel.hpp:27
static constexpr EarthModel WGS84()
WGS84 reference ellipsoid (most common for GPS/navigation).
Definition EarthModel.hpp:45