Vulcan
Aerospace Engineering Utilities Built on Janus
Loading...
Searching...
No Matches
Epoch.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <iomanip>
4#include <janus/janus.hpp>
5#include <sstream>
6#include <string>
11
12namespace vulcan::time {
13
40template <typename Scalar> class Epoch {
41 public:
42 // =========================================================================
43 // Constructors
44 // =========================================================================
45
49 Epoch() : m_tai_sec(Scalar(0.0)), m_delta_at(37) {}
50
58 explicit Epoch(const Scalar &tai_seconds, int delta_at = 37)
59 : m_tai_sec(tai_seconds), m_delta_at(delta_at) {}
60
61 // =========================================================================
62 // Factory Methods (Static Construction)
63 // =========================================================================
64
68 static Epoch from_tai_seconds(const Scalar &tai_sec, int delta_at = 37) {
69 return Epoch(tai_sec, delta_at);
70 }
71
75 static Epoch from_jd_tai(const Scalar &jd_tai, int delta_at = 37) {
76 Scalar tai_sec = jd_to_j2000_seconds(jd_tai);
77 return Epoch(tai_sec, delta_at);
78 }
79
83 static Epoch from_jd_tt(const Scalar &jd_tt, int delta_at = 37) {
84 Scalar jd_tai = tt_to_tai(jd_tt);
86 }
87
91 static Epoch from_jd_gps(const Scalar &jd_gps, int delta_at = 37) {
92 Scalar jd_tai = gps_to_tai(jd_gps);
94 }
95
103 static Epoch from_utc(int year, int month, int day, int hour = 0,
104 int min = 0, double sec = 0.0)
105 requires std::is_floating_point_v<Scalar>
106 {
107 double utc_jd = calendar_to_jd(year, month, day, hour, min, sec);
108 int delta_at = leap_seconds_at_utc(utc_jd);
109 double tai_jd = utc_to_tai(utc_jd, delta_at);
110 double tai_sec = jd_to_j2000_seconds(tai_jd);
111 return Epoch(tai_sec, delta_at);
112 }
113
117 static Epoch from_gps_week(int week, const Scalar &seconds_of_week,
118 int delta_at = 37) {
119 Scalar gps_sec_since_epoch =
120 static_cast<double>(week) * constants::time::SECONDS_PER_WEEK +
121 seconds_of_week;
122 // GPS epoch is 1980-01-06 00:00:00 UTC
123 // In TAI seconds since J2000.0:
124 // GPS epoch JD = 2444244.5
125 // J2000.0 JD = 2451545.0
126 // Delta = -7300.5 days = -630763200 seconds
127 constexpr double GPS_EPOCH_TAI_SEC =
131 Scalar tai_sec = GPS_EPOCH_TAI_SEC + gps_sec_since_epoch;
132 return Epoch(tai_sec, delta_at);
133 }
134
135 // =========================================================================
136 // Time Scale Accessors (Julian Dates)
137 // =========================================================================
138
142 [[nodiscard]] Scalar jd_tai() const {
143 return j2000_seconds_to_jd(m_tai_sec);
144 }
145
149 [[nodiscard]] Scalar jd_tt() const { return tai_to_tt(jd_tai()); }
150
154 [[nodiscard]] Scalar jd_gps() const { return tai_to_gps(jd_tai()); }
155
159 [[nodiscard]] Scalar jd_utc() const {
160 return tai_to_utc(jd_tai(), m_delta_at);
161 }
162
166 [[nodiscard]] Scalar jd_tdb() const { return tt_to_tdb(jd_tt()); }
167
171 [[nodiscard]] Scalar mjd_tt() const { return jd_to_mjd(jd_tt()); }
172
173 // =========================================================================
174 // Time Scale Accessors (Seconds)
175 // =========================================================================
176
180 [[nodiscard]] const Scalar &tai_seconds() const { return m_tai_sec; }
181
185 [[nodiscard]] Scalar tt_seconds() const {
186 return m_tai_sec + constants::time::TT_TAI_OFFSET;
187 }
188
194 [[nodiscard]] Scalar centuries_tt() const {
196 }
197
198 // =========================================================================
199 // GPS Time Accessors
200 // =========================================================================
201
205 [[nodiscard]] int gps_week() const
206 requires std::is_floating_point_v<Scalar>
207 {
208 Scalar gps_jd = jd_gps();
209 double days_since_gps_epoch = gps_jd - constants::time::JD_GPS_EPOCH;
210 return static_cast<int>(std::floor(days_since_gps_epoch / 7.0));
211 }
212
216 [[nodiscard]] Scalar gps_seconds_of_week() const {
217 Scalar gps_jd = jd_gps();
218 Scalar days_since_gps_epoch = gps_jd - constants::time::JD_GPS_EPOCH;
219 // fmod for symbolic
220 if constexpr (std::is_floating_point_v<Scalar>) {
221 double weeks =
222 std::floor(static_cast<double>(days_since_gps_epoch) / 7.0);
223 double days_into_week = days_since_gps_epoch - weeks * 7.0;
224 return days_into_week * constants::time::SECONDS_PER_DAY;
225 } else {
226 // Symbolic: use janus::fmod
227 Scalar days_into_week =
228 janus::fmod(days_since_gps_epoch, Scalar(7.0));
229 return days_into_week * constants::time::SECONDS_PER_DAY;
230 }
231 }
232
233 // =========================================================================
234 // Leap Second Access
235 // =========================================================================
236
240 [[nodiscard]] int delta_at() const { return m_delta_at; }
241
245 void set_delta_at(int delta_at) { m_delta_at = delta_at; }
246
247 // =========================================================================
248 // Arithmetic Operators
249 // =========================================================================
250
254 Epoch operator+(const Scalar &seconds) const {
255 return Epoch(m_tai_sec + seconds, m_delta_at);
256 }
257
261 Epoch operator-(const Scalar &seconds) const {
262 return Epoch(m_tai_sec - seconds, m_delta_at);
263 }
264
268 Scalar operator-(const Epoch &other) const {
269 return m_tai_sec - other.m_tai_sec;
270 }
271
275 Epoch &operator+=(const Scalar &seconds) {
276 m_tai_sec = m_tai_sec + seconds;
277 return *this;
278 }
279
283 Epoch &operator-=(const Scalar &seconds) {
284 m_tai_sec = m_tai_sec - seconds;
285 return *this;
286 }
287
288 // =========================================================================
289 // String Conversion (Numeric Only)
290 // =========================================================================
291
295 [[nodiscard]] std::string to_iso_string() const
296 requires std::is_floating_point_v<Scalar>
297 {
298 double utc_jd = jd_utc();
299 auto [year, month, day, hour, min, sec] = jd_to_calendar(utc_jd);
300
301 std::ostringstream oss;
302 oss << std::setfill('0') << std::setw(4) << year << '-' << std::setw(2)
303 << month << '-' << std::setw(2) << day << 'T' << std::setw(2)
304 << hour << ':' << std::setw(2) << min << ':' << std::setw(2)
305 << static_cast<int>(sec);
306
307 // Add fractional seconds if significant
308 double frac = sec - std::floor(sec);
309 if (frac > 1e-6) {
310 oss << '.' << std::setw(3) << static_cast<int>(frac * 1000);
311 }
312
313 oss << 'Z';
314 return oss.str();
315 }
316
320 [[nodiscard]] std::tuple<int, int, int, int, int, double>
322 requires std::is_floating_point_v<Scalar>
323 {
324 double utc_jd = jd_utc();
325 return jd_to_calendar(utc_jd);
326 }
327
328 private:
329 Scalar m_tai_sec;
330 int m_delta_at;
331};
332
333// =============================================================================
334// Type Aliases
335// =============================================================================
336
339
342
343} // namespace vulcan::time
Definition Epoch.hpp:40
static Epoch from_gps_week(int week, const Scalar &seconds_of_week, int delta_at=37)
Create Epoch from GPS week and seconds.
Definition Epoch.hpp:117
Epoch()
Default constructor (J2000.0 epoch).
Definition Epoch.hpp:49
Epoch operator-(const Scalar &seconds) const
Subtract duration in seconds.
Definition Epoch.hpp:261
static Epoch from_jd_tai(const Scalar &jd_tai, int delta_at=37)
Create Epoch from TAI Julian Date.
Definition Epoch.hpp:75
double jd_tai() const
Definition Epoch.hpp:142
std::string to_iso_string() const
Convert to ISO 8601 string in UTC.
Definition Epoch.hpp:295
const double & tai_seconds() const
Definition Epoch.hpp:180
Scalar operator-(const Epoch &other) const
Time difference in seconds.
Definition Epoch.hpp:268
Scalar tt_seconds() const
Get TT seconds since J2000.0.
Definition Epoch.hpp:185
Epoch & operator-=(const Scalar &seconds)
Subtract duration in seconds (in-place).
Definition Epoch.hpp:283
Scalar mjd_tt() const
Get Modified Julian Date in TT scale.
Definition Epoch.hpp:171
double jd_tt() const
Definition Epoch.hpp:149
Scalar jd_tdb() const
Get Julian Date in TDB scale.
Definition Epoch.hpp:166
Scalar jd_utc() const
Get Julian Date in UTC scale (using stored delta_at).
Definition Epoch.hpp:159
double jd_gps() const
Definition Epoch.hpp:154
Epoch & operator+=(const Scalar &seconds)
Add duration in seconds (in-place).
Definition Epoch.hpp:275
Scalar gps_seconds_of_week() const
Get seconds within the GPS week.
Definition Epoch.hpp:216
void set_delta_at(int delta_at)
Set the TAI - UTC offset.
Definition Epoch.hpp:245
std::tuple< int, int, int, int, int, double > to_utc_calendar() const
Convert to calendar components in UTC.
Definition Epoch.hpp:321
int gps_week() const
Get GPS week number.
Definition Epoch.hpp:205
Scalar centuries_tt() const
Get Julian centuries since J2000.0 in TT scale.
Definition Epoch.hpp:194
Epoch operator+(const Scalar &seconds) const
Add duration in seconds.
Definition Epoch.hpp:254
static Epoch from_jd_gps(const Scalar &jd_gps, int delta_at=37)
Create Epoch from GPS Julian Date.
Definition Epoch.hpp:91
int delta_at() const
Definition Epoch.hpp:240
static Epoch from_jd_tt(const Scalar &jd_tt, int delta_at=37)
Create Epoch from TT Julian Date.
Definition Epoch.hpp:83
static Epoch from_utc(int year, int month, int day, int hour=0, int min=0, double sec=0.0)
Create Epoch from UTC calendar (numeric only).
Definition Epoch.hpp:103
static Epoch from_tai_seconds(const Scalar &tai_sec, int delta_at=37)
Create Epoch from TAI seconds since J2000.0.
Definition Epoch.hpp:68
Epoch(const Scalar &tai_seconds, int delta_at=37)
Construct from TAI seconds since J2000.0.
Definition Epoch.hpp:58
constexpr double JD_GPS_EPOCH
Julian Date of GPS epoch (1980-01-06 00:00:00 UTC).
Definition TimeConstants.hpp:19
constexpr double SECONDS_PER_WEEK
Seconds per week (for GPS).
Definition TimeConstants.hpp:57
constexpr double SECONDS_PER_DAY
Seconds per day.
Definition TimeConstants.hpp:45
constexpr double SECONDS_PER_CENTURY
Seconds per Julian century.
Definition TimeConstants.hpp:48
constexpr double JD_J2000
Julian Date of J2000.0 epoch (2000-01-01 12:00:00 TT).
Definition TimeConstants.hpp:10
constexpr double TT_TAI_OFFSET
TT - TAI offset [s] (exact, by definition).
Definition TimeConstants.hpp:32
constexpr double TAI_GPS_OFFSET
TAI - GPS offset [s].
Definition TimeConstants.hpp:38
Definition Epoch.hpp:12
constexpr Scalar gps_to_tai(const Scalar &gps_jd)
Convert GPS Julian Date to TAI Julian Date.
Definition TimeScales.hpp:69
int leap_seconds_at_utc(double utc_jd)
Get TAI - UTC offset for a given UTC Julian Date.
Definition LeapSeconds.hpp:93
constexpr Scalar utc_to_tai(const Scalar &utc_jd, int delta_at)
Convert UTC Julian Date to TAI Julian Date (templated).
Definition TimeScales.hpp:89
Epoch< double > NumericEpoch
Numeric epoch (double-precision).
Definition Epoch.hpp:338
std::tuple< int, int, int, int, int, double > jd_to_calendar(double jd)
Convert Julian Date to calendar date/time (numeric only).
Definition JulianDate.hpp:46
constexpr Scalar tt_to_tai(const Scalar &tt_jd)
Convert TT Julian Date to TAI Julian Date.
Definition TimeScales.hpp:45
constexpr Scalar j2000_seconds_to_jd(const Scalar &sec)
Convert seconds since J2000.0 to Julian Date.
Definition JulianDate.hpp:132
constexpr Scalar tai_to_utc(const Scalar &tai_jd, int delta_at)
Convert TAI Julian Date to UTC Julian Date (templated).
Definition TimeScales.hpp:103
Scalar tt_to_tdb(const Scalar &tt_jd)
Convert TT Julian Date to TDB Julian Date.
Definition TimeScales.hpp:188
constexpr Scalar jd_to_j2000_seconds(const Scalar &jd)
Convert Julian Date to seconds since J2000.0.
Definition JulianDate.hpp:124
constexpr Scalar jd_to_mjd(const Scalar &jd)
Convert Julian Date to Modified Julian Date.
Definition JulianDate.hpp:103
constexpr Scalar tai_to_tt(const Scalar &tai_jd)
Convert TAI Julian Date to TT Julian Date.
Definition TimeScales.hpp:36
Epoch< janus::SymbolicScalar > SymbolicEpoch
Symbolic epoch (CasADi MX).
Definition Epoch.hpp:341
double calendar_to_jd(int year, int month, int day, int hour=0, int min=0, double sec=0.0)
Convert calendar date/time to Julian Date.
Definition JulianDate.hpp:24
constexpr Scalar tai_to_gps(const Scalar &tai_jd)
Convert TAI Julian Date to GPS Julian Date.
Definition TimeScales.hpp:60