1   /* Copyright 2002-2021 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.attitudes;
18  
19  import java.util.Collection;
20  import java.util.Map.Entry;
21  import java.util.NavigableMap;
22  import java.util.TreeMap;
23  
24  import org.hipparchus.CalculusFieldElement;
25  import org.orekit.errors.OrekitException;
26  import org.orekit.errors.OrekitMessages;
27  import org.orekit.frames.Frame;
28  import org.orekit.time.AbsoluteDate;
29  import org.orekit.time.FieldAbsoluteDate;
30  import org.orekit.utils.FieldPVCoordinatesProvider;
31  import org.orekit.utils.PVCoordinatesProvider;
32  
33  /**
34   * A {@link BoundedAttitudeProvider} that covers a larger time span from several constituent
35   * attitude providers that cover shorter time spans.
36   *
37   * @author Bryan Cazabonne
38   * @since 10.3
39   */
40  public class AggregateBoundedAttitudeProvider implements BoundedAttitudeProvider {
41  
42      /** Constituent attitude provider. */
43      private final NavigableMap<AbsoluteDate, BoundedAttitudeProvider> providers;
44  
45      /**
46       * Constructor.
47       * @param providers attitude providers that provide the backing data for this instance.
48       *                  There must be at least one attitude provider in the collection.
49       *                  If there are gaps between the {@link BoundedAttitudeProvider#getMaxDate()}
50       *                  of one attitude provider and the {@link BoundedAttitudeProvider#getMinDate()}
51       *                  of the next attitude provider an exception may be thrown by any method of
52       *                  this class at any time. If there are overlaps between the the {@link
53       *                  BoundedAttitudeProvider#getMaxDate()} of one attitude provider and the {@link
54       *                  BoundedAttitudeProvider#getMinDate()} of the next attitude provider then the
55       *                  attitude provider with the latest {@link BoundedAttitudeProvider#getMinDate()}
56       *                  is used.
57       */
58      public AggregateBoundedAttitudeProvider(final Collection<? extends BoundedAttitudeProvider> providers) {
59  
60          // Check if the collection is empty
61          if (providers.isEmpty()) {
62              throw new OrekitException(OrekitMessages.NOT_ENOUGH_ATTITUDE_PROVIDERS);
63          }
64  
65          // Initialize map
66          this.providers = new TreeMap<>();
67  
68          // Loop on providers
69          for (final BoundedAttitudeProvider provider : providers) {
70              // Fill collection
71              this.providers.put(provider.getMinDate(), provider);
72          }
73  
74      }
75  
76      /** {@inheritDoc} */
77      @Override
78      public Attitude getAttitude(final PVCoordinatesProvider pvProv, final AbsoluteDate date,
79                                  final Frame frame) {
80  
81          // Get the attitude provider for the given date
82          final BoundedAttitudeProvider provider = getAttitudeProvider(date);
83  
84          // Build attitude
85          return provider.getAttitude(pvProv, date, frame);
86  
87      }
88  
89      /** {@inheritDoc} */
90      @Override
91      public <T extends CalculusFieldElement<T>> FieldAttitude<T> getAttitude(final FieldPVCoordinatesProvider<T> pvProv,
92                                                                          final FieldAbsoluteDate<T> date, final Frame frame) {
93  
94          // Get the attitude provider for the given date
95          final BoundedAttitudeProvider provider = getAttitudeProvider(date.toAbsoluteDate());
96  
97          // Build attitude
98          return provider.getAttitude(pvProv, date, frame);
99  
100     }
101 
102     /** {@inheritDoc} */
103     @Override
104     public AbsoluteDate getMinDate() {
105         return providers.firstEntry().getValue().getMinDate();
106     }
107 
108     /** {@inheritDoc} */
109     @Override
110     public AbsoluteDate getMaxDate() {
111         return providers.lastEntry().getValue().getMaxDate();
112     }
113 
114     /**
115      * Get the attitude provider to use for the given date.
116      * @param date of query
117      * @return attitude provider to use on date.
118      */
119     private BoundedAttitudeProvider getAttitudeProvider(final AbsoluteDate date) {
120         final Entry<AbsoluteDate, BoundedAttitudeProvider> attitudeEntry = providers.floorEntry(date);
121         if (attitudeEntry != null) {
122             return attitudeEntry.getValue();
123         } else {
124             // Let the first attitude provider throw the exception
125             return providers.firstEntry().getValue();
126         }
127     }
128 
129 }