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.files.ccsds.ndm.odm.ocm;
18  
19  import org.orekit.files.ccsds.definitions.OdMethodFacade;
20  import org.orekit.files.ccsds.definitions.Units;
21  import org.orekit.files.ccsds.utils.ContextBinding;
22  import org.orekit.files.ccsds.utils.lexical.ParseToken;
23  import org.orekit.files.ccsds.utils.lexical.TokenType;
24  import org.orekit.utils.units.Unit;
25  
26  
27  /** Keys for {@link OrbitDetermination orbit determination data} entries.
28   * @author Luc Maisonobe
29   * @since 11.0
30   */
31  public enum OrbitDeterminationKey {
32  
33      /** Comment entry. */
34      COMMENT((token, context, container) ->
35              token.getType() == TokenType.ENTRY ? container.addComment(token.getContentAsNormalizedString()) : true),
36  
37      /** Identification number. */
38      OD_ID((token, context, container) -> token.processAsFreeTextString(container::setId)),
39  
40      /** Identification of previous orbit determination. */
41      OD_PREV_ID((token, context, container) -> token.processAsFreeTextString(container::setPrevId)),
42  
43      /** Orbit determination method. */
44      OD_METHOD((token, context, container) -> {
45          if (token.getType() == TokenType.ENTRY) {
46              container.setMethod(OdMethodFacade.parse(token.getRawContent()));
47          }
48          return true;
49      }),
50  
51      /** Time tag for orbit determination solved-for state. */
52      OD_EPOCH((token, context, container) -> token.processAsDate(container::setEpoch, context)),
53  
54      /** Time elapsed between first accepted observation on epoch. */
55      DAYS_SINCE_FIRST_OBS((token, context, container) -> token.processAsDouble(Unit.DAY, context.getParsedUnitsBehavior(),
56                                                                                container::setTimeSinceFirstObservation)),
57  
58      /** Time elapsed between last accepted observation on epoch. */
59      DAYS_SINCE_LAST_OBS((token, context, container) -> token.processAsDouble(Unit.DAY, context.getParsedUnitsBehavior(),
60                                                                               container::setTimeSinceLastObservation)),
61  
62      /** Time span of observation recommended for the OD of the object. */
63      RECOMMENDED_OD_SPAN((token, context, container) -> token.processAsDouble(Unit.DAY, context.getParsedUnitsBehavior(),
64                                                                               container::setRecommendedOdSpan)),
65  
66      /** Actual time span used for the OD of the object. */
67      ACTUAL_OD_SPAN((token, context, container) -> token.processAsDouble(Unit.DAY, context.getParsedUnitsBehavior(),
68                                                                          container::setActualOdSpan)),
69  
70      /** Number of observations available within the actual OD span. */
71      OBS_AVAILABLE((token, context, container) -> token.processAsInteger(container::setObsAvailable)),
72  
73      /** Number of observations accepted within the actual OD span. */
74      OBS_USED((token, context, container) -> token.processAsInteger(container::setObsUsed)),
75  
76      /** Number of sensors tracks available for the OD within the actual OD span. */
77      TRACKS_AVAILABLE((token, context, container) -> token.processAsInteger(container::setTracksAvailable)),
78  
79      /** Number of sensors tracks accepted for the OD within the actual OD span. */
80      TRACKS_USED((token, context, container) -> token.processAsInteger(container::setTracksUsed)),
81  
82      /** Maximum time between observations in the OD of the object. */
83      MAXIMUM_OBS_GAP((token, context, container) -> token.processAsDouble(Unit.DAY, context.getParsedUnitsBehavior(),
84                                                                           container::setMaximumObsGap)),
85  
86      /** Positional error ellipsoid 1σ major eigenvalue at the epoch of OD. */
87      OD_EPOCH_EIGMAJ((token, context, container) -> token.processAsDouble(Unit.METRE, context.getParsedUnitsBehavior(),
88                                                                           container::setEpochEigenMaj)),
89  
90      /** Positional error ellipsoid 1σ intermediate eigenvalue at the epoch of OD. */
91      OD_EPOCH_EIGINT((token, context, container) -> token.processAsDouble(Unit.METRE, context.getParsedUnitsBehavior(),
92                                                                           container::setEpochEigenInt)),
93  
94      /** Positional error ellipsoid 1σ minor eigenvalue at the epoch of OD. */
95      OD_EPOCH_EIGMIN((token, context, container) -> token.processAsDouble(Unit.METRE, context.getParsedUnitsBehavior(),
96                                                                           container::setEpochEigenMin)),
97  
98      /** Maximum predicted major eigenvalue of 1σ positional error ellipsoid over entire time span of the OCM. */
99      OD_MAX_PRED_EIGMAJ((token, context, container) -> token.processAsDouble(Unit.METRE, context.getParsedUnitsBehavior(),
100                                                                             container::setMaxPredictedEigenMaj)),
101 
102     /** Minimum predicted minor eigenvalue of 1σ positional error ellipsoid over entire time span of the OCM. */
103     OD_MIN_PRED_EIGMIN((token, context, container) -> token.processAsDouble(Unit.METRE, context.getParsedUnitsBehavior(),
104                                                                             container::setMinPredictedEigenMin)),
105 
106     /** Confidence metric. */
107     OD_CONFIDENCE((token, context, container) -> token.processAsDouble(Unit.PERCENT, context.getParsedUnitsBehavior(),
108                                                                        container::setConfidence)),
109 
110     /** Generalize Dilution Of Precision. */
111     GDOP((token, context, container) -> token.processAsDouble(Unit.ONE, context.getParsedUnitsBehavior(), container::setGdop)),
112 
113     /** Number of solved-for states. */
114     SOLVE_N((token, context, container) -> token.processAsInteger(container::setSolveN)),
115 
116     /** Description of state elements solved-for. */
117     SOLVE_STATES((token, context, container) -> token.processAsFreeTextList(container::setSolveStates)),
118 
119     /** Number of consider parameters. */
120     CONSIDER_N((token, context, container) -> token.processAsInteger(container::setConsiderN)),
121 
122     /** Description of consider parameters. */
123     CONSIDER_PARAMS((token, context, container) -> token.processAsFreeTextList(container::setConsiderParameters)),
124 
125     /** Specific Energy Dissipation Rate.
126      * @since 12.0
127      */
128     SEDR((token, context, container) -> token.processAsDouble(Units.W_PER_KG, context.getParsedUnitsBehavior(),
129                                                               container::setSedr)),
130 
131     /** Number of sensors used. */
132     SENSORS_N((token, context, container) -> token.processAsInteger(container::setSensorsN)),
133 
134     /** Description of sensors used. */
135     SENSORS((token, context, container) -> token.processAsFreeTextList(container::setSensors)),
136 
137     /** Weighted RMS residual ratio. */
138     WEIGHTED_RMS((token, context, container) -> token.processAsDouble(Unit.ONE, context.getParsedUnitsBehavior(),
139                                                                       container::setWeightedRms)),
140 
141     /** Observation data types used. */
142     DATA_TYPES((token, context, container) -> token.processAsFreeTextList(container::setDataTypes));
143 
144     /** Processing method. */
145     private final transient TokenProcessor processor;
146 
147     /** Simple constructor.
148      * @param processor processing method
149      */
150     OrbitDeterminationKey(final TokenProcessor processor) {
151         this.processor = processor;
152     }
153 
154     /** Process an token.
155      * @param token token to process
156      * @param context context binding
157      * @param container container to fill
158      * @return true of token was accepted
159      */
160     public boolean process(final ParseToken token, final ContextBinding context, final OrbitDetermination container) {
161         return processor.process(token, context, container);
162     }
163 
164     /** Interface for processing one token. */
165     interface TokenProcessor {
166         /** Process one token.
167          * @param token token to process
168          * @param context context binding
169          * @param container container to fill
170          * @return true of token was accepted
171          */
172         boolean process(ParseToken token, ContextBinding context, OrbitDetermination container);
173     }
174 
175 }