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  
18  package org.orekit.files.ccsds.ndm.odm.ocm;
19  
20  import java.util.Collections;
21  import java.util.List;
22  
23  import org.hipparchus.geometry.euclidean.threed.Vector3D;
24  import org.orekit.errors.OrekitException;
25  import org.orekit.errors.OrekitMessages;
26  import org.orekit.files.ccsds.definitions.BodyFacade;
27  import org.orekit.files.ccsds.definitions.DutyCycleType;
28  import org.orekit.files.ccsds.definitions.FrameFacade;
29  import org.orekit.files.ccsds.definitions.OrbitRelativeFrame;
30  import org.orekit.files.ccsds.definitions.SpacecraftBodyFrame;
31  import org.orekit.files.ccsds.section.CommentsContainer;
32  import org.orekit.time.AbsoluteDate;
33  import org.orekit.utils.units.Unit;
34  
35  /** Metadata for maneuver history.
36   * <p>
37   * Beware that the Orekit getters and setters all rely on SI units. The parsers
38   * and writers take care of converting these SI units into CCSDS mandatory units.
39   * The {@link org.orekit.utils.units.Unit Unit} class provides useful
40   * {@link org.orekit.utils.units.Unit#fromSI(double) fromSi} and
41   * {@link org.orekit.utils.units.Unit#toSI(double) toSI} methods in case the callers
42   * already use CCSDS units instead of the API SI units. The general-purpose
43   * {@link org.orekit.utils.units.Unit Unit} class (without an 's') and the
44   * CCSDS-specific {@link org.orekit.files.ccsds.definitions.Units Units} class
45   * (with an 's') also provide some predefined units. These predefined units and the
46   * {@link org.orekit.utils.units.Unit#fromSI(double) fromSi} and
47   * {@link org.orekit.utils.units.Unit#toSI(double) toSI} conversion methods are indeed
48   * what the parsers and writers use for the conversions.
49   * </p>
50   * @author Luc Maisonobe
51   * @since 11.0
52   */
53  public class OrbitManeuverHistoryMetadata extends CommentsContainer {
54  
55      /** Default duty cycle type.
56       * @since 12.0
57       */
58      public static final DutyCycleType DEFAULT_DC_TYPE = DutyCycleType.CONTINUOUS;
59  
60      /** Maneuver identification number. */
61      private String manID;
62  
63      /** Identification number of previous maneuver. */
64      private String manPrevID;
65  
66      /** Identification number of next maneuver. */
67      private String manNextID;
68  
69      /** Basis of this maneuver history data. */
70      private ManBasis manBasis;
71  
72      /** Identification number of the orbit determination or simulation upon which this maneuver is based. */
73      private String manBasisID;
74  
75      /** Identifier of the device used for this maneuver. */
76      private String manDeviceID;
77  
78      /** Completion time of previous maneuver. */
79      private AbsoluteDate manPrevEpoch;
80  
81      /** Start time of next maneuver. */
82      private AbsoluteDate manNextEpoch;
83  
84      /** Reference frame of the maneuver. */
85      private FrameFacade manReferenceFrame;
86  
87      /** Epoch of the maneuver reference frame. */
88      private AbsoluteDate manFrameEpoch;
89  
90      /** Purposes of the maneuver. */
91      private List<String> manPurpose;
92  
93      /** Prediction source on which this maneuver is based. */
94      private String manPredSource;
95  
96      /** Origin of maneuver gravitational assist body. */
97      private BodyFacade gravitationalAssist;
98  
99      /** Type of duty cycle. */
100     private DutyCycleType dcType;
101 
102     /** Start time of duty cycle-based maneuver window. */
103     private AbsoluteDate dcWindowOpen;
104 
105     /** End time of duty cycle-based maneuver window. */
106     private AbsoluteDate dcWindowClose;
107 
108     /** Minimum number of "ON" duty cycles. */
109     private int dcMinCycles;
110 
111     /** Maximum number of "ON" duty cycles. */
112     private int dcMaxCycles;
113 
114     /** Start time of initial duty cycle-based maneuver execution. */
115     private AbsoluteDate dcExecStart;
116 
117     /** End time of final duty cycle-based maneuver execution. */
118     private AbsoluteDate dcExecStop;
119 
120     /** Duty cycle thrust reference time. */
121     private AbsoluteDate dcRefTime;
122 
123     /** Duty cycle pulse "ON" duration. */
124     private double dcTimePulseDuration;
125 
126     /** Duty cycle elapsed time between start of a pulse and start of next pulse. */
127     private double dcTimePulsePeriod;
128 
129     /** Reference direction for triggering duty cycle. */
130     private Vector3D dcRefDir;
131 
132     /** Spacecraft body frame in which {@link #dcBodyTrigger} is specified. */
133     private SpacecraftBodyFrame dcBodyFrame;
134 
135     /** Direction in {@link #dcBodyFrame body frame} for triggering duty cycle. */
136     private Vector3D dcBodyTrigger;
137 
138     /** Phase angle of pulse start. */
139     private double dcPhaseStartAngle;
140 
141     /** Phase angle of pulse stop. */
142     private double dcPhaseStopAngle;
143 
144     /** Maneuver elements of information. */
145     private List<ManeuverFieldType> manComposition;
146 
147     /** Units of covariance element set. */
148     private List<Unit> manUnits;
149 
150     /** Simple constructor.
151      * @param epochT0 T0 epoch from file metadata
152      */
153     public OrbitManeuverHistoryMetadata(final AbsoluteDate epochT0) {
154         // we don't call the setXxx() methods in order to avoid
155         // calling refuseFurtherComments as a side effect
156         // In 502.0-B-3 (p. 6-39) MAN_BASIS is optional and has no default
157         manBasis            = null;
158         manReferenceFrame   = new FrameFacade(null, null,
159                                               OrbitRelativeFrame.TNW_INERTIAL, null,
160                                               OrbitRelativeFrame.TNW_INERTIAL.name());
161         manFrameEpoch       = epochT0;
162         manPurpose          = Collections.emptyList();
163         dcType              = DEFAULT_DC_TYPE;
164         dcMinCycles         = -1;
165         dcMaxCycles         = -1;
166         dcTimePulseDuration = Double.NaN;
167         dcTimePulsePeriod   = Double.NaN;
168     }
169 
170     /** {@inheritDoc} */
171     @Override
172     public void validate(final double version) {
173         super.validate(version);
174         checkNotNull(manID,          OrbitManeuverHistoryMetadataKey.MAN_ID.name());
175         checkNotNull(manDeviceID,    OrbitManeuverHistoryMetadataKey.MAN_DEVICE_ID.name());
176 
177         if (dcType != DutyCycleType.CONTINUOUS) {
178             checkNotNull(dcWindowOpen,       OrbitManeuverHistoryMetadataKey.DC_WIN_OPEN.name());
179             checkNotNull(dcWindowClose,      OrbitManeuverHistoryMetadataKey.DC_WIN_CLOSE.name());
180             checkNotNull(dcExecStart,        OrbitManeuverHistoryMetadataKey.DC_EXEC_START.name());
181             checkNotNull(dcExecStop,         OrbitManeuverHistoryMetadataKey.DC_EXEC_STOP.name());
182             checkNotNull(dcRefTime,          OrbitManeuverHistoryMetadataKey.DC_REF_TIME.name());
183             checkNotNaN(dcTimePulseDuration, OrbitManeuverHistoryMetadataKey.DC_TIME_PULSE_DURATION.name());
184             checkNotNaN(dcTimePulsePeriod,   OrbitManeuverHistoryMetadataKey.DC_TIME_PULSE_PERIOD.name());
185         }
186         if (dcType == DutyCycleType.TIME_AND_ANGLE) {
187             checkNotNull(dcRefDir,           OrbitManeuverHistoryMetadataKey.DC_REF_DIR.name());
188             checkNotNull(dcBodyFrame,        OrbitManeuverHistoryMetadataKey.DC_BODY_FRAME.name());
189             checkNotNull(dcBodyTrigger,      OrbitManeuverHistoryMetadataKey.DC_BODY_TRIGGER.name());
190             checkNotNull(dcPhaseStartAngle,  OrbitManeuverHistoryMetadataKey.DC_PA_START_ANGLE.name());
191             checkNotNull(dcPhaseStopAngle,   OrbitManeuverHistoryMetadataKey.DC_PA_STOP_ANGLE.name());
192         }
193 
194         checkNotNull(manComposition, OrbitManeuverHistoryMetadataKey.MAN_COMPOSITION.name());
195         if (!manComposition.get(0).isTime()) {
196             throw new OrekitException(OrekitMessages.CCSDS_MANEUVER_MISSING_TIME, manID);
197         }
198         final int firstNonTime = (manComposition.size() > 1 && manComposition.get(1).isTime()) ? 2 : 1;
199 
200         if (manUnits != null) {
201             if (manUnits.size() != manComposition.size() - firstNonTime) {
202                 throw new OrekitException(OrekitMessages.CCSDS_MANEUVER_UNITS_WRONG_NB_COMPONENTS,
203                                           manID);
204             }
205             for (int i = 0; i < manUnits.size(); ++i) {
206                 manComposition.get(firstNonTime + i).checkUnit(manUnits.get(i));
207             }
208         }
209     }
210 
211     /** Get maneuver identification number.
212      * @return maneuver identification number
213      */
214     public String getManID() {
215         return manID;
216     }
217 
218     /** Set maneuver identification number.
219      * @param manID maneuver identification number
220      */
221     public void setManID(final String manID) {
222         refuseFurtherComments();
223         this.manID = manID;
224     }
225 
226     /** Get identification number of previous maneuver.
227      * @return identification number of previous maneuver
228      */
229     public String getManPrevID() {
230         return manPrevID;
231     }
232 
233     /** Set identification number of previous maneuver.
234      * @param manPrevID identification number of previous maneuver
235      */
236     public void setManPrevID(final String manPrevID) {
237         refuseFurtherComments();
238         this.manPrevID = manPrevID;
239     }
240 
241     /** Get identification number of next maneuver.
242      * @return identification number of next maneuver
243      */
244     public String getManNextID() {
245         return manNextID;
246     }
247 
248     /** Set identification number of next maneuver.
249      * @param manNextID identification number of next maneuver
250      */
251     public void setManNextID(final String manNextID) {
252         refuseFurtherComments();
253         this.manNextID = manNextID;
254     }
255 
256     /** Get basis of this maneuver history data.
257      * @return basis of this maneuver history data
258      */
259     public ManBasis getManBasis() {
260         return manBasis;
261     }
262 
263     /** Set basis of this maneuver history data.
264      * @param manBasis basis of this maneuver history data
265      */
266     public void setManBasis(final ManBasis manBasis) {
267         refuseFurtherComments();
268         this.manBasis = manBasis;
269     }
270 
271     /** Get identification number of the orbit determination or simulation upon which this maneuver is based.
272      * @return identification number of the orbit determination or simulation upon which this maneuver is based
273      */
274     public String getManBasisID() {
275         return manBasisID;
276     }
277 
278     /** Set identification number of the orbit determination or simulation upon which this maneuver is based.
279      * @param manBasisID identification number of the orbit determination or simulation upon which this maneuver is based
280      */
281     public void setManBasisID(final String manBasisID) {
282         refuseFurtherComments();
283         this.manBasisID = manBasisID;
284     }
285 
286     /** Get identifier of the device used for this maneuver.
287      * @return identifier of the device used for this maneuver
288      */
289     public String getManDeviceID() {
290         return manDeviceID;
291     }
292 
293     /** Set identifier of the device used for this maneuver.
294      * @param manDeviceID identifier of the device used for this maneuver
295      */
296     public void setManDeviceID(final String manDeviceID) {
297         refuseFurtherComments();
298         this.manDeviceID = manDeviceID;
299     }
300 
301     /** Get completion time of previous maneuver.
302      * @return completion time of previous maneuver
303      */
304     public AbsoluteDate getManPrevEpoch() {
305         return manPrevEpoch;
306     }
307 
308     /** Set completion time of previous maneuver.
309      * @param manPrevEpoch completion time of previous maneuver
310      */
311     public void setManPrevEpoch(final AbsoluteDate manPrevEpoch) {
312         refuseFurtherComments();
313         this.manPrevEpoch = manPrevEpoch;
314     }
315 
316     /** Get start time of next maneuver.
317      * @return start time of next maneuver
318      */
319     public AbsoluteDate getManNextEpoch() {
320         return manNextEpoch;
321     }
322 
323     /** Set start time of next maneuver.
324      * @param manNextEpoch start time of next maneuver
325      */
326     public void setManNextEpoch(final AbsoluteDate manNextEpoch) {
327         refuseFurtherComments();
328         this.manNextEpoch = manNextEpoch;
329     }
330 
331     /** Get the purposes of the maneuver.
332      * @return purposes of the maneuver
333      */
334     public List<String> getManPurpose() {
335         return manPurpose;
336     }
337 
338     /** Set the purposes of the maneuver.
339      * @param manPurpose purposes of the maneuver
340      */
341     public void setManPurpose(final List<String> manPurpose) {
342         this.manPurpose = manPurpose;
343     }
344 
345     /** Get prediction source on which this maneuver is based.
346      * @return prediction source on which this maneuver is based
347      */
348     public String getManPredSource() {
349         return manPredSource;
350     }
351 
352     /** Set prediction source on which this maneuver is based.
353      * @param manPredSource prediction source on which this maneuver is based
354      */
355     public void setManPredSource(final String manPredSource) {
356         refuseFurtherComments();
357         this.manPredSource = manPredSource;
358     }
359 
360     /** Get reference frame of the maneuver.
361      * @return reference frame of the maneuver
362      */
363     public FrameFacade getManReferenceFrame() {
364         return manReferenceFrame;
365     }
366 
367     /** Set reference frame of the maneuver.
368      * @param manReferenceFrame the reference frame to be set
369      */
370     public void setManReferenceFrame(final FrameFacade manReferenceFrame) {
371         refuseFurtherComments();
372         this.manReferenceFrame = manReferenceFrame;
373     }
374 
375     /** Get epoch of the {@link #getManReferenceFrame() maneuver reference frame}.
376      * @return epoch of the {@link #getManReferenceFrame() maneuver reference frame}
377      */
378     public AbsoluteDate getManFrameEpoch() {
379         return manFrameEpoch;
380     }
381 
382     /** Set epoch of the {@link #getManReferenceFrame() maneuver reference frame}.
383      * @param manFrameEpoch epoch of the {@link #getManReferenceFrame() maneuver reference frame}
384      */
385     public void setManFrameEpoch(final AbsoluteDate manFrameEpoch) {
386         refuseFurtherComments();
387         this.manFrameEpoch = manFrameEpoch;
388     }
389 
390     /** Get the origin of gravitational assist.
391      * @return the origin of gravitational assist.
392      */
393     public BodyFacade getGravitationalAssist() {
394         return gravitationalAssist;
395     }
396 
397     /** Set the origin of gravitational assist.
398      * @param gravitationalAssist origin of gravitational assist to be set
399      */
400     public void setGravitationalAssist(final BodyFacade gravitationalAssist) {
401         refuseFurtherComments();
402         this.gravitationalAssist = gravitationalAssist;
403     }
404 
405     /** Get type of duty cycle.
406      * @return type of duty cycle
407      */
408     public DutyCycleType getDcType() {
409         return dcType;
410     }
411 
412     /** Set type of duty cycle.
413      * @param dcType type of duty cycle
414      */
415     public void setDcType(final DutyCycleType dcType) {
416         this.dcType = dcType;
417     }
418 
419     /** Get the start time of duty cycle-based maneuver window.
420      * @return start time of duty cycle-based maneuver window
421      */
422     public AbsoluteDate getDcWindowOpen() {
423         return dcWindowOpen;
424     }
425 
426     /** Set the start time of duty cycle-based maneuver window.
427      * @param dcWindowOpen start time of duty cycle-based maneuver window
428      */
429     public void setDcWindowOpen(final AbsoluteDate dcWindowOpen) {
430         this.dcWindowOpen = dcWindowOpen;
431     }
432 
433     /** Get the end time of duty cycle-based maneuver window.
434      * @return end time of duty cycle-based maneuver window
435      */
436     public AbsoluteDate getDcWindowClose() {
437         return dcWindowClose;
438     }
439 
440     /** Set the end time of duty cycle-based maneuver window.
441      * @param dcWindowClose end time of duty cycle-based maneuver window
442      */
443     public void setDcWindowClose(final AbsoluteDate dcWindowClose) {
444         this.dcWindowClose = dcWindowClose;
445     }
446 
447     /** Get the minimum number of "ON" duty cycles.
448      * @return minimum number of "ON" duty cycles (-1 if not set)
449      */
450     public int getDcMinCycles() {
451         return dcMinCycles;
452     }
453 
454     /** Set the minimum number of "ON" duty cycles.
455      * @param dcMinCycles minimum number of "ON" duty cycles
456      */
457     public void setDcMinCycles(final int dcMinCycles) {
458         this.dcMinCycles = dcMinCycles;
459     }
460 
461     /** Get the maximum number of "ON" duty cycles.
462      * @return maximum number of "ON" duty cycles (-1 if not set)
463      */
464     public int getDcMaxCycles() {
465         return dcMaxCycles;
466     }
467 
468     /** Set the maximum number of "ON" duty cycles.
469      * @param dcMaxCycles maximum number of "ON" duty cycles
470      */
471     public void setDcMaxCycles(final int dcMaxCycles) {
472         this.dcMaxCycles = dcMaxCycles;
473     }
474 
475     /** Get the start time of initial duty cycle-based maneuver execution.
476      * @return start time of initial duty cycle-based maneuver execution
477      */
478     public AbsoluteDate getDcExecStart() {
479         return dcExecStart;
480     }
481 
482     /** Set the start time of initial duty cycle-based maneuver execution.
483      * @param dcExecStart start time of initial duty cycle-based maneuver execution
484      */
485     public void setDcExecStart(final AbsoluteDate dcExecStart) {
486         this.dcExecStart = dcExecStart;
487     }
488 
489     /** Get the end time of final duty cycle-based maneuver execution.
490      * @return end time of final duty cycle-based maneuver execution
491      */
492     public AbsoluteDate getDcExecStop() {
493         return dcExecStop;
494     }
495 
496     /** Set the end time of final duty cycle-based maneuver execution.
497      * @param dcExecStop end time of final duty cycle-based maneuver execution
498      */
499     public void setDcExecStop(final AbsoluteDate dcExecStop) {
500         this.dcExecStop = dcExecStop;
501     }
502 
503     /** Get duty cycle thrust reference time.
504      * @return duty cycle thrust reference time
505      */
506     public AbsoluteDate getDcRefTime() {
507         return dcRefTime;
508     }
509 
510     /** Set duty cycle thrust reference time.
511      * @param dcRefTime duty cycle thrust reference time
512      */
513     public void setDcRefTime(final AbsoluteDate dcRefTime) {
514         this.dcRefTime = dcRefTime;
515     }
516 
517     /** Get duty cycle pulse "ON" duration.
518      * @return duty cycle pulse "ON" duration
519      */
520     public double getDcTimePulseDuration() {
521         return dcTimePulseDuration;
522     }
523 
524     /** Set duty cycle pulse "ON" duration.
525      * @param dcTimePulseDuration duty cycle pulse "ON" duration
526      */
527     public void setDcTimePulseDuration(final double dcTimePulseDuration) {
528         this.dcTimePulseDuration = dcTimePulseDuration;
529     }
530 
531     /** Get duty cycle elapsed time between start of a pulse and start of next pulse.
532      * @return duty cycle elapsed time between start of a pulse and start of next pulse
533      */
534     public double getDcTimePulsePeriod() {
535         return dcTimePulsePeriod;
536     }
537 
538     /** Set duty cycle elapsed time between start of a pulse and start of next pulse.
539      * @param dcTimePulsePeriod duty cycle elapsed time between start of a pulse and start of next pulse
540      */
541     public void setDcTimePulsePeriod(final double dcTimePulsePeriod) {
542         this.dcTimePulsePeriod = dcTimePulsePeriod;
543     }
544 
545     /** Get reference direction for triggering duty cycle.
546      * @return reference direction for triggering duty cycle
547      */
548     public Vector3D getDcRefDir() {
549         return dcRefDir;
550     }
551 
552     /** Set reference direction for triggering duty cycle.
553      * @param dcRefDir reference direction for triggering duty cycle
554      */
555     public void setDcRefDir(final Vector3D dcRefDir) {
556         this.dcRefDir = dcRefDir;
557     }
558 
559     /** Get spacecraft body frame in which {@link #getDcBodyTrigger()} is specified.
560      * @return spacecraft body frame in which {@link #getDcBodyTrigger()} is specified
561      */
562     public SpacecraftBodyFrame getDcBodyFrame() {
563         return dcBodyFrame;
564     }
565 
566     /** Set spacecraft body frame in which {@link #getDcBodyTrigger()} is specified.
567      * @param dcBodyFrame spacecraft body frame in which {@link #getDcBodyTrigger()} is specified
568      */
569     public void setDcBodyFrame(final SpacecraftBodyFrame dcBodyFrame) {
570         this.dcBodyFrame = dcBodyFrame;
571     }
572 
573     /** Get direction in {@link #getDcBodyFrame() body frame} for triggering duty cycle.
574      * @return direction in {@link #getDcBodyFrame() body frame} for triggering duty cycle
575      */
576     public Vector3D getDcBodyTrigger() {
577         return  dcBodyTrigger;
578     }
579 
580     /** Set direction in {@link #getDcBodyFrame() body frame} for triggering duty cycle.
581      * @param dcBodyTrigger direction in {@link #getDcBodyFrame() body frame} for triggering duty cycle
582      */
583     public void setDcBodyTrigger(final Vector3D dcBodyTrigger) {
584         this.dcBodyTrigger = dcBodyTrigger;
585     }
586 
587     /** Get phase angle of pulse start.
588      * @return phase angle of pulse start
589      */
590     public double getDcPhaseStartAngle() {
591         return dcPhaseStartAngle;
592     }
593 
594     /** Set phase angle of pulse start.
595      * @param dcPhaseStartAngle phase angle of pulse start
596      */
597     public void setDcPhaseStartAngle(final double dcPhaseStartAngle) {
598         this.dcPhaseStartAngle = dcPhaseStartAngle;
599     }
600 
601     /** Get phase angle of pulse stop.
602      * @return phase angle of pulse stop
603      */
604     public double getDcPhaseStopAngle() {
605         return dcPhaseStopAngle;
606     }
607 
608     /** Set phase angle of pulse stop.
609      * @param dcPhaseStopAngle phase angle of pulse stop
610      */
611     public void setDcPhaseStopAngle(final double dcPhaseStopAngle) {
612         this.dcPhaseStopAngle = dcPhaseStopAngle;
613     }
614 
615     /** Get maneuver elements of information.
616      * @return maneuver element of information
617      */
618     public List<ManeuverFieldType> getManComposition() {
619         return manComposition;
620     }
621 
622     /** Set maneuver element of information.
623      * @param manComposition maneuver element of information
624      */
625     public void setManComposition(final List<ManeuverFieldType> manComposition) {
626         refuseFurtherComments();
627         this.manComposition = manComposition;
628     }
629 
630     /** Get maneuver elements of information units.
631      * @return maneuver element of information units
632      */
633     public List<Unit> getManUnits() {
634         return manUnits;
635     }
636 
637     /** Set maneuver element of information units.
638      * @param manUnits maneuver element of information units
639      */
640     public void setManUnits(final List<Unit> manUnits) {
641         refuseFurtherComments();
642         this.manUnits = manUnits;
643     }
644 
645 }