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 }