Added functions to convert between various astronomical time systems: UTC, TAI, TT, and TDB

ver1_5_1
Chris Laurel 2006-09-01 07:20:50 +00:00
parent 2dc7bf90e0
commit fcaae7d93e
2 changed files with 246 additions and 22 deletions

View File

@ -30,6 +30,49 @@ const double astro::LunarMass = 7.354e22;
// epoch B1950: 22:09 UT on 21 Dec 1949
#define B1950 2433282.423
// Difference in seconds between Terrestrial Time and International
// Atomic Time
static const double dTA = 32.184;
struct LeapSecondRecord
{
int seconds;
double t;
};
// Table of leap second insertions. The leap second always
// appears as the last second of the day immediately prior
// to the date in the table.
static const LeapSecondRecord LeapSeconds[] =
{
{ 10, 2441317.5 }, // 1 Jan 1972
{ 11, 2441499.5 }, // 1 Jul 1972
{ 12, 2441683.5 }, // 1 Jan 1973
{ 13, 2442048.5 }, // 1 Jan 1974
{ 14, 2442413.5 }, // 1 Jan 1975
{ 15, 2442778.5 }, // 1 Jan 1976
{ 16, 2443144.5 }, // 1 Jan 1977
{ 17, 2443509.5 }, // 1 Jan 1978
{ 18, 2443874.5 }, // 1 Jan 1979
{ 19, 2444239.5 }, // 1 Jan 1980
{ 20, 2444786.5 }, // 1 Jul 1981
{ 21, 2445151.5 }, // 1 Jul 1982
{ 22, 2445516.5 }, // 1 Jul 1983
{ 23, 2446247.5 }, // 1 Jul 1985
{ 24, 2447161.5 }, // 1 Jan 1988
{ 25, 2447892.5 }, // 1 Jan 1990
{ 26, 2448257.5 }, // 1 Jan 1991
{ 27, 2448804.5 }, // 1 Jul 1992
{ 28, 2449169.5 }, // 1 Jul 1993
{ 29, 2449534.5 }, // 1 Jul 1994
{ 30, 2450083.5 }, // 1 Jan 1996
{ 31, 2450630.5 }, // 1 Jul 1997
{ 32, 2451179.5 }, // 1 Jan 1999
{ 33, 2453736.5 }, // 1 Jan 2006
};
static Mat3f equatorialToCelestial = Mat3f::xrotation(degToRad(23.4392911f));
static Mat3d equatorialToCelestiald = Mat3d::xrotation(degToRad(23.4392911));
@ -56,16 +99,6 @@ float astro::appMagToLum(float mag, float lyrs)
return absMagToLum(appToAbsMag(mag, lyrs));
}
float astro::absToAppMag(float absMag, float lyrs)
{
return (float) (absMag - 5 + 5 * log10(lyrs / LY_PER_PARSEC));
}
float astro::appToAbsMag(float appMag, float lyrs)
{
return (float) (appMag + 5 - 5 * log10(lyrs / LY_PER_PARSEC));
}
float astro::lightYearsToParsecs(float ly)
{
return ly / (float) LY_PER_PARSEC;
@ -116,11 +149,6 @@ double astro::lightYearsToAU(double ly)
return ly * AU_PER_LY;
}
float astro::AUtoLightYears(float au)
{
return au / (float) AU_PER_LY;
}
float astro::AUtoKilometers(float au)
{
return au * (float) KM_PER_AU;
@ -322,6 +350,7 @@ double astro::meanEclipticObliquity(double jd)
return 23.439292 - de;
}
astro::Date::Date()
{
year = 0;
@ -363,8 +392,8 @@ astro::Date::Date(double jd)
double dday = c - e - (int) (30.6001 * f) + ((jd + 0.5) - (int) (jd + 0.5));
/* This following used to be 14.0, but gcc was computing it incorrectly, so
it was changed to 14 */
// This following used to be 14.0, but gcc was computing it incorrectly, so
// it was changed to 14
month = f - 1 - 12 * (int) (f / 14);
year = d - 4715 - (int) ((7.0 + month) / 10.0);
day = (int) dday;
@ -403,6 +432,7 @@ astro::Date::operator double() const
}
// TODO: need option to parse UTC times (with leap seconds)
bool astro::parseDate(const string& s, astro::Date& date)
{
int year = 0;
@ -423,7 +453,7 @@ bool astro::parseDate(const string& s, astro::Date& date)
if (hour > 23 || minute > 59 || second > 59)
return false;
// Cheesy days/month calculation . . .
// Days / month calculation . . .
int maxDay = 31 - ((0xa50 >> month) & 0x1);
if (month == 2)
{
@ -433,7 +463,7 @@ bool astro::parseDate(const string& s, astro::Date& date)
else
maxDay = 28;
}
if (day > (unsigned int)maxDay || day < 1)
if (day > (unsigned int) maxDay || day < 1)
return false;
date.year = year;
@ -460,3 +490,157 @@ ostream& operator<<(ostream& s, const astro::Date d)
return s;
}
/********* Time scale conversion functions ***********/
// Convert from Atomic Time to UTC
astro::Date
astro::TAItoUTC(double tai)
{
unsigned int nRecords = sizeof(LeapSeconds) / sizeof(LeapSeconds[0]);
double dAT = LeapSeconds[0].seconds;
double dD = 0.0;
int extraSecs = 0;
for (unsigned int i = nRecords - 1; i > 0; i--)
{
if (tai - LeapSeconds[i].seconds / 86400.0 >= LeapSeconds[i].t)
{
dAT = LeapSeconds[i].seconds;
break;
}
else if (tai - LeapSeconds[i - 1].seconds / 86400.0 >= LeapSeconds[i].t)
{
dAT = LeapSeconds[i].seconds;
extraSecs = LeapSeconds[i].seconds - LeapSeconds[i - 1].seconds;
break;
}
}
Date utcDate(tai - dAT / 86400.0);
utcDate.seconds += extraSecs;
return utcDate;
}
// Convert from UTC to Atomic Time
double
astro::UTCtoTAI(const astro::Date& utc)
{
unsigned int nRecords = sizeof(LeapSeconds) / sizeof(LeapSeconds[0]);
double dAT = LeapSeconds[0].seconds;
double utcjd = (double) Date(utc.year, utc.month, utc.day);
for (unsigned int i = nRecords - 1; i > 0; i--)
{
if (utcjd >= LeapSeconds[i].t)
{
dAT = LeapSeconds[i].seconds;
break;
}
}
double tai = utcjd + (utc.hour * 1440.0 + utc.minute * 60.0 + utc.seconds + dAT) / 86400.0;
return tai;
}
// Convert from Terrestrial Time to Atomic Time
double
astro::TTtoTAI(double tt)
{
return tt - dTA / 86400.0;
}
// Convert from Atomic Time to Terrestrial TIme
double
astro::TAItoTT(double tai)
{
return tai + dTA / 86400.0;
}
// Correction for converting from Terrestrial Time to Barycentric Dynamical
// Time. Constants and algorithm from "Time Routines in CSPICE",
// http://sohowww.nascom.nasa.gov/solarsoft/stereo/gen/exe/icy/doc/time.req
static const double K = 1.657e-3;
static const double EB = 1.671e-2;
static const double M0 = 6.239996;
static const double M1 = 1.99096871e-7;
double TDBcorrection(double tdb)
{
// t is seconds from J2000.0
double t = (tdb - astro::J2000) * 86400.0;
// Approximate calculation of Earth's mean anomaly
double M = M0 + M1 * t;
// Compute the eccentric anomaly
double E = M + EB * sin(M);
return K * sin(E);
}
// Convert from Terrestrial Time to Barycentric Dynamical Time
double
astro::TTtoTDB(double tt)
{
return tt + TDBcorrection(tt);
}
// Convert from Barycentric Dynamical Time to Terrestrial Time
double
astro::TDBtoTT(double tdb)
{
return tdb - TDBcorrection(tdb);
}
// Convert from TAI to Julian Date UTC. The Julian Date UTC functions should
// generally be avoided because there's no provision for dealing with leap
// seconds.
double
astro::JDUTCtoTAI(double utc)
{
unsigned int nRecords = sizeof(LeapSeconds) / sizeof(LeapSeconds[0]);
double dAT = LeapSeconds[0].seconds;
for (unsigned int i = nRecords - 1; i > 0; i--)
{
if (utc > LeapSeconds[i].t)
{
dAT = LeapSeconds[i].seconds;
break;
}
}
return utc + dAT / 86400.0;
}
// Convert from Julian Date UTC to TAI
double
astro::TAItoJDUTC(double tai)
{
unsigned int nRecords = sizeof(LeapSeconds) / sizeof(LeapSeconds[0]);
double dAT = LeapSeconds[0].seconds;
for (unsigned int i = nRecords - 1; i > 0; i--)
{
if (tai - LeapSeconds[i - 1].seconds / 86400.0 > LeapSeconds[i].t)
{
dAT = LeapSeconds[i].seconds;
break;
}
}
return tai - dAT / 86400.0;
}

View File

@ -12,6 +12,7 @@
#include <iostream>
#include <string>
#include <cmath>
#include <celmath/vecmath.h>
#include <celengine/univcoord.h>
@ -62,12 +63,45 @@ namespace astro
Equator_J2000,
};
// Time scale conversions
// UTC - Coordinated Universal Time
// TAI - International Atomic Time
// TT - Terrestrial Time
// TCB - Barycentric Coordinate Time
// TDB - Barycentric Dynamical Time
// Convert to and from UTC dates
double UTCtoTAI(const astro::Date& utc);
astro::Date TAItoUTC(double tai);
// Convert among uniform time scales
double TTtoTAI(double tt);
double TAItoTT(double tai);
double TTtoTDB(double tt);
double TDBtoTT(double tdb);
// Conversions to and from Julian Date UTC--other time systems
// should be prefered.
double JDUTCtoTAI(double utc);
double TAItoJDUTC(double tai);
// Magnitude conversions
float lumToAbsMag(float lum);
float lumToAppMag(float lum, float lyrs);
float absMagToLum(float mag);
float appMagToLum(float mag, float lyrs);
float absToAppMag(float absMag, float lyrs);
float appToAbsMag(float appMag, float lyrs);
template<class T> T absToAppMag(T absMag, T lyrs)
{
return (T) (absMag - 5 + 5 * log10(lyrs / LY_PER_PARSEC));
}
template<class T> T appToAbsMag(T appMag, T lyrs)
{
return (T) (appMag + 5 - 5 * log10(lyrs / LY_PER_PARSEC));
}
// Distance conversions
float lightYearsToParsecs(float);
double lightYearsToParsecs(double);
float parsecsToLightYears(float);
@ -78,7 +112,13 @@ namespace astro
double kilometersToLightYears(double);
float lightYearsToAU(float);
double lightYearsToAU(double);
float AUtoLightYears(float);
// TODO: templatize the rest of the conversion functions
template<class T> T AUtoLightYears(T ly)
{
return ly * (T) AU_PER_LY;
}
float AUtoKilometers(float);
double AUtoKilometers(double);
float kilometersToAU(float);