org.orekit.time
包是一个独立的包,提供处理时代和时间尺度以及比较瞬间的类。
主要的类是AbsoluteDate
,它表示一个唯一的时间瞬间,以便能够将其与空间动力学和天文学领域中使用的许多不同的时间尺度相对应。
这极大地简化了开发,因为它隐藏了一些模型的内部细节。例如,在使用基于JPL的星历时,时间必须是地球时(以前称为星历时)。然而,这是一个实现细节,从高级应用程序调用Orekit的人不必处理它。AbsoluteDate
类允许用户传递一个日期,而不管它是在哪个时间尺度上定义的,转换将根据需要透明地进行。
日期通常通过指定特定的时间尺度来定义。例如,J2000.0纪元是根据其日历组件定义的,其Terrestrial Time中的时间为2000-01-01T12:00:00。了解各种可用的时间尺度定义非常重要,以避免错误。TimeScalesFactory
类提供了几个预定义的时间尺度:
国际原子时
这是地球表面可以使用的最准确和规律的时间尺度。
地球时
根据国际天文学联合会(IAU)1991年推荐的第四条建议地球表面的坐标时间定义,它是Ephemeris Time TE的继任者。按照惯例,TT = TAI + 32.184秒。
协调世界时
UTC主要与TAI相关,但不时引入一些步进调整,以考虑地球自转的不规则性,并防止法定时间与白天和黑夜的相对漂移。国际地球自转服务(IERS)负责这个时间计算。这些调整需要引入闰秒,这意味着有些日子不是86400秒长。
世界时1
UT1是与地球实际自转直接相关的时间尺度。它是一个不规则的尺度,反映了地球的不规则自转速率。UT1和UTCScale之间的偏移量可以在IERS发布的地球定向参数中找到。
地心坐标时间
地球质心处的坐标时间。这个时间尺度与TTScale(因此与TAI)线性相关。
重心动力学时间
用于计算太阳系中的星历。这个时间与TT相差一些由于地球运动引起的小的相对论修正。
重心坐标时间
用于太阳系计算的坐标时间。这个时间尺度与TDBScale线性相关。
全球定位系统参考尺度
这个尺度在GPS纪元开始时等于UTC,当时UTC比TAI晚19秒,自那时以来一直与TAI平行(即UTC现在由于闰秒与GPS有偏差)。TGPS = TAI - 19秒。
伽利略系统参考尺度
这个尺度在伽利略纪元(1999-08-22T00:00:00Z)等于UTC + 13秒。伽利略系统时间和GPS时间非常接近。在没有任何错误的情况下,它们应该是相同的。这两个尺度之间的偏移量是GGTO,它取决于用于实现时间尺度的时钟。它的数量级约为几十纳秒。这个类不实现这个偏移量。
格洛纳斯系统参考尺度
这个尺度在任何时间都等于UTC + 3小时。格洛纳斯系统时间与UTC尺度一样包括闰秒(它们发生在同一时刻,格洛纳斯时钟时间是UTC之前3小时)。
准天顶参考尺度
准天顶系统时间和GPS时间非常接近。在没有任何错误的情况下,它们应该是相同的。这两个尺度之间的偏移量是GGTO,它取决于用于实现时间尺度的时钟。这个类不实现这个偏移量。
格林威治平恒星时尺度
格林威治平恒星时是格林威治子午线和当天平均春分点的时角,以0h UT1为基准。
Orekit支持1961年至1972年间使用的UTC-TAI偏移的线性模型,以及自1972年以来仅具有整秒偏移(和闰秒)的恒定模型。下图显示了截至2010年的偏移历史。
有三种主要的方式来定义一个日期:
第一种选项更直观,但对于某些需求来说不足够。后两种选项由于时间刻度的复杂性而容易混淆。理解两者之间的区别是避免大误差的关键。
一个表观秒偏移是一个与时间刻度同步的时钟上两个读数之间的差异。例如,如果第一个读数是23:59:59,第二个读数是00:00:00,那么表观秒偏移就是1秒。经过的持续时间是一个秒数的计数,可以通过在第一个时刻开始并在第二个时刻停止的秒表来测量。大多数情况下,这两个时间是相同的。然而,如果时间刻度是UTC,并且在引入闰秒时进行读数,那么两个事件之间的经过时间是2秒而不是1秒!
方法offsetFrom
接受日期和时间刻度作为参数,计算表观偏移量。方法durationFrom
只接受日期作为参数,计算经过的持续时间。在上面的例子中,第一个方法将返回1秒,而第二个方法将返回2秒:
TimeScale utc = TimeScalesFactory.getUTC();
AbsoluteDate start = new AbsoluteDate(2005, 12, 31, 23, 59, 59, utc);
AbsoluteDate stop = new AbsoluteDate(2006, 1, 1, 0, 0, 0, utc);
System.out.println(stop.offsetFrom(start, utc)); // 输出 1.0
System.out.println(stop.durationFrom(start)); // 输出 2.0
这个属性可以反过来用来定义日期。我们可以将第二个时刻定义为当时钟的读数距离第一个日期的读数还有一秒时发生的时刻。我们也可以将其定义为自第一个时刻开始经过两秒的时刻,而不引用任何外部时钟。两种方法都是可行的,这取决于可用的数据及其含义。以下代码展示了这两种方法:
TimeScale utc = TimeScalesFactory.getUTC();
AbsoluteDate referenceDate = new AbsoluteDate(2005, 12, 31, 23, 59, 59, utc);
AbsoluteDate date1 = new AbsoluteDate(referenceDate, 1.0, utc);
AbsoluteDate date2 = new AbsoluteDate(referenceDate, 2.0);
变量date1
和date2
表示相同的时刻。第一个是相对于时间刻度定义的,第二个是独立于任何时间刻度定义的。
Orekit定义了10个参考时刻。前7个在太空领域中常用,第7个在计算机科学领域中常用,最后两个方便在最小/最大研究循环中进行初始化:
一旦构建完成,AbsoluteDate
可以与其他日期进行比较,并转换为其他时间尺度并表示。它用于定义状态、轨道、坐标系等。
包含日期的类实现了TimeStamped
接口。单例ChronologicalComparator
可以按照时间顺序对实现该接口的对象进行排序。这对于星历非常有用。可以使用通用的TimeStamped
实例来定义这样的集合,如下面的示例所示。这个技巧是我们希望在headSet
、tailSet
或subSet
等方法中允许使用AbsoluteDate
实例。
public class MyClass implements TimeStamped {
...
}
public class Ephemeris {
// 我们将星历声明为包含通用的 TimeStamped 实例
private final TreeSet<TimeStamped> ephemeris;
public Ephemeris(MyClass[] array) {
ephemeris = new TreeSet<TimeStamped>(new ChronologicalComparator());
for (int i = 0; i < n; ++i) {
ephemeris.add(new MyClass(...));
}
}
public MyClass getBefore(AbsoluteDate date) {
// 由于 AbsoluteDate 实现了 TimeStamped,我们可以这样做
return (MyClass) ephemeris.headSet(date).last();
}
public MyClass getAfter(AbsoluteDate date) {
// 由于 AbsoluteDate 实现了 TimeStamped,我们可以这样做
return (MyClass) ephemeris.tailSet(date).first();
}
}
许多航天动力学对象与日期相关(当然包括日期本身,还有姿态、轨道、位置-速度坐标或航天器状态等)。在某些情况下,可以通过非常小的时间偏移量轻微地移动这些对象,例如在计算有限差分时。在这些情况下,被迫设置完整的传播模型将会很麻烦。时间包提供了一个简单的参数化接口:TimeShiftable
,它定义了一个shiftedBy
方法,应该由允许这种小偏移的类实现。该方法返回一个在时间上偏移的新实例,而不改变原始对象。
这个特性不应该用于需要复杂传播模型的大偏移。