GLONASSDate.java

  1. /* Copyright 2002-2025 CS GROUP
  2.  * Licensed to CS GROUP (CS) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * CS licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *   http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.orekit.time;

  18. import org.hipparchus.util.FastMath;
  19. import org.orekit.annotation.DefaultDataContext;
  20. import org.orekit.data.DataContext;
  21. import org.orekit.propagation.analytical.gnss.data.GNSSConstants;
  22. import org.orekit.utils.Constants;

  23. /**
  24.  * Container for date in GLONASS form.
  25.  * @author Bryan Cazabonne
  26.  * @see AbsoluteDate
  27.  * @see "GLONASS Interface Control Document v1.0, 2016"
  28.  * @since 10.0
  29.  */
  30. public class GLONASSDate implements TimeStamped {

  31.     /** Constant for date computation. */
  32.     private static final int C1 = 44195;

  33.     /** Constant for date computation. */
  34.     private static final int C2 = 45290;

  35.     /** The number of the current day in a four year interval N<sub>a</sub>. */
  36.     private final int na;

  37.     /** The number of the current four year interval N<sub>4</sub>. */
  38.     private final int n4;

  39.     /** Number of seconds since N<sub>a</sub>. */
  40.     private final double secInNa;

  41.     /** Current Julian date JD0. */
  42.     private double jd0;

  43.     /** Greenwich Mean Sidereal Time (rad). */
  44.     private double gmst;

  45.     /** Corresponding date. */
  46.     private final AbsoluteDate date;

  47.     /** Build an instance corresponding to a GLONASS date.
  48.      *
  49.      * <p>This method uses the {@link DataContext#getDefault() default data context}.
  50.      *
  51.      * @param na the number of the current day in a four year interval
  52.      * @param n4 the number of the current four year interval
  53.      * @param secInNa the number of seconds since na start
  54.      * @see #GLONASSDate(int, int, double, TimeScale)
  55.      */
  56.     @DefaultDataContext
  57.     public GLONASSDate(final int na, final int n4, final double secInNa) {
  58.         this(na, n4, secInNa, DataContext.getDefault().getTimeScales().getGLONASS());
  59.     }

  60.     /**
  61.      * Build an instance corresponding to a GLONASS date.
  62.      *
  63.      * @param na      the number of the current day in a four year interval
  64.      * @param n4      the number of the current four year interval
  65.      * @param secInNa the number of seconds since na start
  66.      * @param glonass time scale.
  67.      * @since 10.1
  68.      */
  69.     public GLONASSDate(final int na,
  70.                        final int n4,
  71.                        final double secInNa,
  72.                        final TimeScale glonass) {
  73.         this.na      = na;
  74.         this.n4      = n4;
  75.         this.secInNa = secInNa;
  76.         // Compute JD0
  77.         final int ratio = FastMath.round((float) (na - 3) / (25 + C1 + C2));
  78.         this.jd0  = 1461 * (n4 - 1) + na + 2450082.5 - ratio;
  79.         // GMST
  80.         this.gmst = computeGMST();
  81.         this.date = computeDate(glonass);
  82.     }

  83.     /** Build an instance from an absolute date.
  84.      *
  85.      * <p>This method uses the {@link DataContext#getDefault() default data context}.
  86.      *
  87.      * @param date absolute date to consider
  88.      * @see #GLONASSDate(AbsoluteDate, TimeScale)
  89.      */
  90.     @DefaultDataContext
  91.     public GLONASSDate(final AbsoluteDate date) {
  92.         this(date, DataContext.getDefault().getTimeScales().getGLONASS());
  93.     }

  94.     /**
  95.      * Build an instance from an absolute date.
  96.      *
  97.      * @param date    absolute date to consider
  98.      * @param glonass time scale.
  99.      * @since 10.1
  100.      */
  101.     public GLONASSDate(final AbsoluteDate date, final TimeScale glonass) {
  102.         final DateTimeComponents dateTime = date.getComponents(glonass);
  103.         // N4
  104.         final int year = dateTime.getDate().getYear();
  105.         this.n4 = ((int) (year - 1996) / 4) + 1;
  106.         // Na
  107.         final int start = 1996 + 4 * (n4 - 1);
  108.         final double duration = date.durationFrom(new AbsoluteDate(start, 1, 1, glonass));
  109.         this.na = (int) (duration / 86400) + 1;
  110.         this.secInNa = dateTime.getTime().getSecondsInLocalDay();
  111.         // Compute JD0
  112.         final int ratio = FastMath.round((float) (na - 3) / (25 + C1 + C2));
  113.         this.jd0 = 1461 * (n4 - 1) + na + 2450082.5 - ratio;
  114.         // GMST
  115.         this.gmst = computeGMST();
  116.         this.date = date;
  117.     }

  118.     @Override
  119.     public AbsoluteDate getDate() {
  120.         return date;
  121.     }

  122.     /** Get the number of seconds since N<sub>a</sub> start.
  123.      * @return number of seconds since N<sub>a</sub> start
  124.      */
  125.     public double getSecInDay() {
  126.         return secInNa;
  127.     }

  128.     /** Get the number of the current day in a four year interval.
  129.      * @return the number of the current day in a four year interval
  130.      */
  131.     public int getDayNumber() {
  132.         return na;
  133.     }

  134.     /** Get the number of the current four year interval.
  135.      * @return the number of the current four year interval
  136.      */
  137.     public int getIntervalNumber() {
  138.         return n4;
  139.     }

  140.     /** Get the current Julian date JD0.
  141.      * @return the current date JD0
  142.      */
  143.     public double getJD0() {
  144.         return jd0;
  145.     }

  146.     /** Get the Greenwich Mean Sidereal Time.
  147.      * @return the Greenwich Mean Sidereal Time (rad)
  148.      */
  149.     public double getGMST() {
  150.         return gmst;
  151.     }

  152.     /** Compute the Greenwich Mean Sidereal Time using the current Julian date JD0.
  153.      * @return the Greenwich Mean Sidereal Time (rad)
  154.      */
  155.     private double computeGMST() {
  156.         final double ref = 2451545.0;
  157.         // Earth's rotation angle in radians
  158.         final double era = 2. * GNSSConstants.GLONASS_PI *
  159.                         (0.7790572732640 + 1.00273781191135448 * (jd0 - ref));
  160.         // Time from Epoch 2000 (1st January, 00:00 UTC) till current Epoch in Julian centuries
  161.         final double time = (jd0 - ref) / Constants.JULIAN_CENTURY;
  162.         // Time to the power n
  163.         final double time2 = time * time;
  164.         final double time3 = time2 * time;
  165.         final double time4 = time2 * time2;
  166.         final double time5 = time2 * time3;
  167.         // GMST computation
  168.         final double gTime = era + 7.03270726e-8 + time * 2.23603658710194e-2 +
  169.                         time2 * 6.7465784654e-6 - time3 * 2.1332e-12 - time4 * 1.452308e-10 - time5 * 1.784e-13;
  170.         return gTime;
  171.     }

  172.     /** Compute the GLONASS date.
  173.      * @return the date
  174.      * @param glonass time scale.
  175.      */
  176.     private AbsoluteDate computeDate(final TimeScale glonass) {
  177.         // Compute the number of Julian day for the current date
  178.         final double jdn = jd0 + 0.5;
  179.         // Coefficients
  180.         final int a = (int) (jdn + 32044);
  181.         final int b = (4 * a + 3) / 146097;
  182.         final int c = a - (146097 * b) / 4;
  183.         final int d = (4 * c + 3) / 1461;
  184.         final int e = c - (1461 * d) / 4;
  185.         final int m = (5 * e + 2) / 153;
  186.         // Year, month and day
  187.         final int day   = e - (153 * m + 2) / 5 + 1;
  188.         final int month = m + 3 - 12 * (m / 10);
  189.         final int year  = 100 * b + d - 4800 + m / 10;
  190.         return new AbsoluteDate(new DateComponents(year, month, day),
  191.                                 new TimeComponents(secInNa),
  192.                                 glonass);
  193.     }

  194. }