AbstractGNSSAttitudeProvider.java

  1. /* Copyright 2002-2023 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.gnss.attitude;

  18. import java.util.HashMap;
  19. import java.util.Map;
  20. import java.util.SortedSet;
  21. import java.util.TreeSet;

  22. import org.hipparchus.Field;
  23. import org.hipparchus.CalculusFieldElement;
  24. import org.orekit.attitudes.Attitude;
  25. import org.orekit.attitudes.FieldAttitude;
  26. import org.orekit.frames.Frame;
  27. import org.orekit.time.AbsoluteDate;
  28. import org.orekit.time.ChronologicalComparator;
  29. import org.orekit.time.FieldAbsoluteDate;
  30. import org.orekit.time.TimeStamped;
  31. import org.orekit.utils.ExtendedPVCoordinatesProvider;
  32. import org.orekit.utils.FieldPVCoordinatesProvider;
  33. import org.orekit.utils.PVCoordinatesProvider;
  34. import org.orekit.utils.TimeStampedAngularCoordinates;
  35. import org.orekit.utils.TimeStampedFieldAngularCoordinates;

  36. /**
  37.  * Base class for attitude providers for navigation satellites.
  38.  *
  39.  * @author Luc Maisonobe
  40.  * @since 9.2
  41.  */
  42. abstract class AbstractGNSSAttitudeProvider implements GNSSAttitudeProvider {

  43.     /** Start of validity for this provider. */
  44.     private final AbsoluteDate validityStart;

  45.     /** End of validity for this provider. */
  46.     private final AbsoluteDate validityEnd;

  47.     /** Provider for Sun position. */
  48.     private final ExtendedPVCoordinatesProvider sun;

  49.     /** Inertial frame where velocity are computed. */
  50.     private final Frame inertialFrame;

  51.     /** Turns already encountered. */
  52.     private final SortedSet<TimeStamped> turns;

  53.     /** Turns already encountered. */
  54.     private final transient Map<Field<? extends CalculusFieldElement<?>>, SortedSet<TimeStamped>> fieldTurns;

  55.     /** Simple constructor.
  56.      * @param validityStart start of validity for this provider
  57.      * @param validityEnd end of validity for this provider
  58.      * @param sun provider for Sun position
  59.      * @param inertialFrame inertial frame where velocity are computed
  60.      */
  61.     protected AbstractGNSSAttitudeProvider(final AbsoluteDate validityStart,
  62.                                            final AbsoluteDate validityEnd,
  63.                                            final ExtendedPVCoordinatesProvider sun,
  64.                                            final Frame inertialFrame) {
  65.         this.validityStart = validityStart;
  66.         this.validityEnd   = validityEnd;
  67.         this.sun           = sun;
  68.         this.inertialFrame = inertialFrame;
  69.         this.turns         = new TreeSet<>(new ChronologicalComparator());
  70.         this.fieldTurns    = new HashMap<>();
  71.     }

  72.     /** {@inheritDoc} */
  73.     @Override
  74.     public AbsoluteDate validityStart() {
  75.         return validityStart;
  76.     }

  77.     /** {@inheritDoc} */
  78.     @Override
  79.     public AbsoluteDate validityEnd() {
  80.         return validityEnd;
  81.     }

  82.     /** {@inheritDoc} */
  83.     @Override
  84.     public Attitude getAttitude(final PVCoordinatesProvider pvProv,
  85.                                 final AbsoluteDate date,
  86.                                 final Frame frame) {

  87.         // compute yaw correction
  88.         final TurnSpan                      turnSpan  = getTurnSpan(date);
  89.         final GNSSAttitudeContext           context   = new GNSSAttitudeContext(date, sun, pvProv, inertialFrame, turnSpan);
  90.         final TimeStampedAngularCoordinates corrected = correctedYaw(context);
  91.         if (turnSpan == null && context.getTurnSpan() != null) {
  92.             // we have encountered a new turn, store it
  93.             turns.add(context.getTurnSpan());
  94.         }

  95.         return new Attitude(inertialFrame, corrected).withReferenceFrame(frame);

  96.     }

  97.     /** {@inheritDoc} */
  98.     @Override
  99.     public <T extends CalculusFieldElement<T>> FieldAttitude<T> getAttitude(final FieldPVCoordinatesProvider<T> pvProv,
  100.                                                                             final FieldAbsoluteDate<T> date,
  101.                                                                             final Frame frame) {

  102.         // compute yaw correction
  103.         final FieldTurnSpan<T>                      turnSpan  = getTurnSpan(date);
  104.         final GNSSFieldAttitudeContext<T>           context   = new GNSSFieldAttitudeContext<>(date, sun, pvProv, inertialFrame, turnSpan);
  105.         final TimeStampedFieldAngularCoordinates<T> corrected = correctedYaw(context);
  106.         if (turnSpan == null && context.getTurnSpan() != null) {
  107.             // we have encountered a new turn, store it
  108.             fieldTurns.get(date.getField()).add(context.getTurnSpan());
  109.         }

  110.         return new FieldAttitude<>(inertialFrame, corrected).withReferenceFrame(frame);

  111.     }

  112.     /** Get the turn span covering a date.
  113.      * @param date date to check
  114.      * @return turn span covering the date, or null if no span covers this date
  115.      */
  116.     private TurnSpan getTurnSpan(final AbsoluteDate date) {

  117.         // as the reference date of the turn span is the end + margin date,
  118.         // the span to consider can only be the first span that is after date
  119.         final SortedSet<TimeStamped> after = turns.tailSet(date);
  120.         if (!after.isEmpty()) {
  121.             final TurnSpan ts = (TurnSpan) after.first();
  122.             if (ts.inTurnTimeRange(date)) {
  123.                 return ts;
  124.             }
  125.         }

  126.         // no turn covers the date
  127.         return null;

  128.     }

  129.     /** Get the turn span covering a date.
  130.      * @param date date to check
  131.      * @param <T> type of the field elements
  132.      * @return turn span covering the date, or null if no span covers this date
  133.      */
  134.     private <T extends CalculusFieldElement<T>> FieldTurnSpan<T> getTurnSpan(final FieldAbsoluteDate<T> date) {

  135.         SortedSet<TimeStamped> sortedSet = fieldTurns.get(date.getField());
  136.         if (sortedSet == null) {
  137.             // this is the first time we manage such a field, prepare a sorted set for it
  138.             sortedSet = new TreeSet<>(new ChronologicalComparator());
  139.             fieldTurns.put(date.getField(), sortedSet);
  140.         }

  141.         // as the reference date of the turn span is the end + margin date,
  142.         // the span to consider can only be the first span that is after date
  143.         final AbsoluteDate dateDouble = date.toAbsoluteDate();
  144.         final SortedSet<TimeStamped> after = sortedSet.tailSet(dateDouble);
  145.         if (!after.isEmpty()) {
  146.             @SuppressWarnings("unchecked")
  147.             final FieldTurnSpan<T> ts = (FieldTurnSpan<T>) after.first();
  148.             if (ts.inTurnTimeRange(dateDouble)) {
  149.                 return ts;
  150.             }
  151.         }

  152.         // no turn covers the date
  153.         return null;

  154.     }

  155.     /** Get provider for Sun position.
  156.      * @return provider for Sun position
  157.      * @since 12.0
  158.      */
  159.     protected ExtendedPVCoordinatesProvider getSun() {
  160.         return sun;
  161.     }

  162.     /** Get inertial frame where velocity are computed.
  163.      * @return inertial frame where velocity are computed
  164.      */
  165.     protected Frame getInertialFrame() {
  166.         return inertialFrame;
  167.     }

  168.     /** Select the
  169.     /** Compute GNSS attitude with midnight/noon yaw turn correction.
  170.      * @param context context data for attitude computation
  171.      * @return corrected yaw, using inertial frame as the reference
  172.      */
  173.     protected abstract TimeStampedAngularCoordinates correctedYaw(GNSSAttitudeContext context);

  174.     /** Compute GNSS attitude with midnight/noon yaw turn correction.
  175.      * @param context context data for attitude computation
  176.      * @param <T> type of the field elements
  177.      * @return corrected yaw, using inertial frame as the reference
  178.      */
  179.     protected abstract <T extends CalculusFieldElement<T>> TimeStampedFieldAngularCoordinates<T>
  180.         correctedYaw(GNSSFieldAttitudeContext<T> context);

  181. }