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.cdm;
18
19 import java.util.List;
20
21 import org.orekit.annotation.DefaultDataContext;
22 import org.orekit.bodies.CelestialBody;
23 import org.orekit.bodies.CelestialBodyFactory;
24 import org.orekit.data.DataContext;
25 import org.orekit.errors.OrekitException;
26 import org.orekit.errors.OrekitMessages;
27 import org.orekit.files.ccsds.definitions.YesNoUnknown;
28 import org.orekit.files.ccsds.definitions.BodyFacade;
29 import org.orekit.files.ccsds.definitions.FrameFacade;
30 import org.orekit.files.ccsds.definitions.CelestialBodyFrame;
31 import org.orekit.files.ccsds.definitions.ModifiedFrame;
32 import org.orekit.files.ccsds.definitions.TimeSystem;
33 import org.orekit.files.ccsds.ndm.odm.ocm.ObjectType;
34 import org.orekit.files.ccsds.section.Metadata;
35 import org.orekit.frames.Frame;
36
37 /**
38 * This class gathers the meta-data present in the Conjunction Data Message (CDM).
39 * @author Melina Vanel
40 * @since 11.2
41 */
42 public class CdmMetadata extends Metadata {
43
44 /** CDM relative metadata. */
45 private CdmRelativeMetadata relativeMetadata;
46
47 /** Refering to object 1 or 2. */
48 private String object;
49
50 /** Unique satellite identification designator for the object. */
51 private String objectDesignator;
52
53 /** Specification of satellite catalog source. */
54 private String catalogName;
55
56 /** Object name. */
57 private String objectName;
58
59 /** International designator for the object as assigned by the UN Committee
60 * on Space Research (COSPAR) and the US National Space Science Data Center (NSSDC). */
61 private String internationalDesignator;
62
63 /** Type of object. */
64 private ObjectType objectType;
65
66 /** Operator contact position for the space object. */
67 private String operatorContact;
68
69 /** Operator organization for the space object. */
70 private String operatorOrganization;
71
72 /** Operator phone for the space object. */
73 private String operatorPhone;
74
75 /** Operator email for the space object. */
76 private String operatorEmail;
77
78 /** Unique identifier of Orbit Data Message(s) that are linked (relevant) to this Conjunction Data Message. */
79 private String odmMsgLink;
80
81 /** Unique identifier of Attitude Data Message(s) that are linked (relevant) to this Conjunction Data Message. */
82 private String admMsgLink;
83
84 /** Unique name of the external ephemeris file used for the object or NONE. */
85 private String ephemName;
86
87 /** Flag indicating whether new tracking observations are anticipated prior to the issue of the next CDM associated with the event
88 * specified by CONJUNCTION_ID. */
89 private YesNoUnknown obsBeforeNextMessage;
90
91 /** Operator email for the space object. */
92 private CovarianceMethod covarianceMethod;
93
94 /** Maneuver capacity. */
95 private Maneuvrable maneuverable;
96
97 /** Central body around which Object1 and 2 are orbiting. */
98 private BodyFacade orbitCenter;
99
100 /** Reference frame in which state vector data are given. */
101 private FrameFacade refFrame;
102
103 /** Gravity model name. */
104 private String gravityModel;
105
106 /** Degree of the gravity model. */
107 private int gravityDegree;
108
109 /** Order of the gravity model. */
110 private int gravityOrder;
111
112 /** Name of atmospheric model. */
113 private String atmosphericModel;
114
115 /** N-body perturbation bodies. */
116 private List<BodyFacade> nBodyPerturbations;
117
118 /** Is solar radiation pressure taken into account or not ? STANDARD CCSDS saying YES/NO choice and optional */
119 private YesNoUnknown isSolarRadPressure;
120
121 /** Is solid Earth and ocean tides taken into account or not. STANDARD CCSDS saying YES/NO choice and optional */
122 private YesNoUnknown isEarthTides;
123
124 /** Is in-track thrust modelling used or not. STANDARD CCSDS saying YES/NO choice and optional */
125 private YesNoUnknown isIntrackThrustModeled;
126
127 /** The source from which the covariance data used in the report for both Object 1 and Object 2 originates. */
128 private String covarianceSource;
129
130 /** Flag indicating the type of alternate covariance information provided. */
131 private AltCovarianceType altCovType;
132
133 /** Reference frame in which the alternate covariance data are given. */
134 private FrameFacade altCovRefFrame;
135
136 /** Simple constructor.
137 */
138 @DefaultDataContext
139 public CdmMetadata() {
140 super(null);
141 orbitCenter = new BodyFacade(CelestialBodyFactory.EARTH.toUpperCase(), CelestialBodyFactory.getEarth());
142 }
143
144 /** Simple constructor.
145 *
146 * @param dataContext data context
147 */
148 public CdmMetadata(final DataContext dataContext) {
149 super(null);
150 final CelestialBody earth = dataContext.getCelestialBodies().getEarth();
151 orbitCenter = new BodyFacade(earth.getName().toUpperCase(), earth);
152 }
153
154 /** {@inheritDoc} */
155 @Override
156 public void validate(final double version) {
157 // We only check values that are mandatory in a cdm file
158 checkNotNull(object, CdmMetadataKey.OBJECT.name());
159 checkNotNull(objectDesignator, CdmMetadataKey.OBJECT_DESIGNATOR.name());
160 checkNotNull(catalogName, CdmMetadataKey.CATALOG_NAME.name());
161 checkNotNull(objectName, CdmMetadataKey.OBJECT_NAME.name());
162 checkNotNull(internationalDesignator, CdmMetadataKey.INTERNATIONAL_DESIGNATOR.name());
163 checkNotNull(ephemName, CdmMetadataKey.EPHEMERIS_NAME.name());
164 checkNotNull(covarianceMethod, CdmMetadataKey.COVARIANCE_METHOD.name());
165 checkNotNull(maneuverable, CdmMetadataKey.MANEUVERABLE.name());
166 checkNotNull(refFrame, CdmMetadataKey.REF_FRAME.name());
167 }
168
169 /**
170 * Get the relative metadata following header, they are the common metadata for the CDM.
171 * @return relativeMetadata relative metadata
172 */
173 public CdmRelativeMetadata getRelativeMetadata() {
174 return relativeMetadata;
175 }
176
177 /**
178 * Set the relative metadata following header, they are the common metadata for the CDM.
179 * @param relativeMetadata relative metadata
180 */
181 public void setRelativeMetadata(final CdmRelativeMetadata relativeMetadata) {
182 this.relativeMetadata = relativeMetadata;
183 }
184
185 /**
186 * Get the object name for which metadata are given.
187 * @return the object name
188 */
189 public String getObject() {
190 return object;
191 }
192
193 /**
194 * Set the object name for which metadata are given.
195 * @param object = object 1 or 2 to be set
196 */
197 public void setObject(final String object) {
198 this.setTimeSystem(TimeSystem.UTC);
199 refuseFurtherComments();
200 this.object = object;
201 }
202
203 /**
204 * Get the object satellite catalog designator for which metadata are given.
205 * @return the satellite catalog designator for the object
206 */
207 public String getObjectDesignator() {
208 return objectDesignator;
209 }
210
211 /**
212 * Set the satellite designator for the object for which metadata are given.
213 * @param objectDesignator for the spacecraft to be set
214 */
215 public void setObjectDesignator(final String objectDesignator) {
216 refuseFurtherComments();
217 this.objectDesignator = objectDesignator;
218 }
219
220 /**
221 * Get the satellite catalog used for the object.
222 * @return the catalog name
223 */
224 public String getCatalogName() {
225 return catalogName;
226 }
227
228 /**
229 * Set the satellite catalog name used for object.
230 * @param catalogName for the spacecraft to be set
231 */
232 public void setCatalogName(final String catalogName) {
233 refuseFurtherComments();
234 this.catalogName = catalogName;
235 }
236
237 /**
238 * Get the spacecraft name for the object.
239 * @return the spacecraft name
240 */
241 public String getObjectName() {
242 return objectName;
243 }
244
245 /**
246 * Set the spacecraft name used for object.
247 * @param objectName for the spacecraft to be set
248 */
249 public void setObjectName(final String objectName) {
250 refuseFurtherComments();
251 this.objectName = objectName;
252 }
253
254 /**
255 * Get the international designator for the object.
256 * @return the international designator
257 */
258 public String getInternationalDes() {
259 return internationalDesignator;
260 }
261
262 /**
263 * Set the international designator used for object.
264 * @param internationalDes for the object to be set
265 */
266 public void setInternationalDes(final String internationalDes) {
267 refuseFurtherComments();
268 this.internationalDesignator = internationalDes;
269 }
270
271 /**
272 * Get the type of object.
273 * @return the object type
274 */
275 public ObjectType getObjectType() {
276 return objectType;
277 }
278
279 /**
280 * Set the type of object.
281 * @param objectType type of object
282 */
283 public void setObjectType(final ObjectType objectType) {
284 refuseFurtherComments();
285 this.objectType = objectType;
286 }
287
288 /**
289 * Get the contact position of the owner / operator of the object.
290 * @return the contact position
291 */
292 public String getOperatorContactPosition() {
293 return operatorContact;
294 }
295
296 /**
297 * Set the contact position for the object owner / operator.
298 * @param opContact for the object to be set
299 */
300 public void setOperatorContactPosition(final String opContact) {
301 refuseFurtherComments();
302 this.operatorContact = opContact;
303 }
304
305 /**
306 * Get the contact organisation of the object.
307 * @return the contact organisation
308 */
309 public String getOperatorOrganization() {
310 return operatorOrganization;
311 }
312
313 /**
314 * Set the contact organisation of the object.
315 * @param operatorOrganization contact organisation for the object to be set
316 */
317 public void setOperatorOrganization(final String operatorOrganization) {
318 refuseFurtherComments();
319 this.operatorOrganization = operatorOrganization;
320 }
321
322 /**
323 * Get the contact phone of the operator of the object.
324 * @return the operator phone
325 */
326 public String getOperatorPhone() {
327 return operatorPhone;
328 }
329
330 /**
331 * Set the operator phone of the object.
332 * @param operatorPhone contact phone for the object to be set
333 */
334 public void setOperatorPhone(final String operatorPhone) {
335 refuseFurtherComments();
336 this.operatorPhone = operatorPhone;
337 }
338
339 /**
340 * Get the email of the operator of the object.
341 * @return the operator email
342 */
343 public String getOperatorEmail() {
344 return operatorEmail;
345 }
346
347 /**
348 * Set the object operator email.
349 * @param operatorEmail operator email for the object to be set
350 */
351 public void setOperatorEmail(final String operatorEmail) {
352 refuseFurtherComments();
353 this.operatorEmail = operatorEmail;
354 }
355
356 /**
357 * Get the unique name of the external ephemeris used for OD.
358 * @return the name of ephemeris used
359 */
360 public String getEphemName() {
361 return ephemName;
362 }
363
364 /**
365 * Set the name of external ephemeris used for OD.
366 * @param ephemName me of external ephemeris used
367 */
368 public void setEphemName(final String ephemName) {
369 refuseFurtherComments();
370 this.ephemName = ephemName;
371 }
372
373 /**
374 * Get the method name used to calculate covariance during OD.
375 * @return the name of covariance calculation method
376 */
377 public CovarianceMethod getCovarianceMethod() {
378 return covarianceMethod;
379 }
380
381 /**
382 * Set the method name used to calculate covariance during OD.
383 * @param covarianceMethod method name for covariance calculation
384 */
385 public void setCovarianceMethod(final CovarianceMethod covarianceMethod) {
386 refuseFurtherComments();
387 this.covarianceMethod = covarianceMethod;
388 }
389
390 /**
391 * Get the ability of object to maneuver or not.
392 * @return the ability to maneuver
393 */
394 public Maneuvrable getManeuverable() {
395 return maneuverable;
396 }
397
398 /**
399 * Set the object maneuver ability.
400 * @param maneuverable ability to maneuver
401 */
402 public void setManeuverable(final Maneuvrable maneuverable) {
403 refuseFurtherComments();
404 this.maneuverable = maneuverable;
405 }
406
407 /**
408 * Get the central body for object 1 and 2.
409 * @return the name of the central body
410 */
411 public BodyFacade getOrbitCenter() {
412 return orbitCenter;
413 }
414
415 /**
416 * Set the central body name for object 1 and 2.
417 * @param orbitCenter name of the central body
418 */
419 public void setOrbitCenter(final BodyFacade orbitCenter) {
420 refuseFurtherComments();
421 this.orbitCenter = orbitCenter;
422 }
423
424 /**
425 * Get the reference frame in which data are given: used for state vector and
426 * Keplerian elements data (and for the covariance reference frame if none is given).
427 *
428 * @return the reference frame
429 */
430 public Frame getFrame() {
431 if (orbitCenter == null || orbitCenter.getBody() == null) {
432 throw new OrekitException(OrekitMessages.NO_DATA_LOADED_FOR_CELESTIAL_BODY, "No Orbit center name");
433 }
434 if (refFrame == null) {
435 throw new OrekitException(OrekitMessages.CCSDS_INVALID_FRAME, "No reference frame");
436 }
437 else {
438 if (refFrame.asFrame() == null) {
439 throw new OrekitException(OrekitMessages.CCSDS_INVALID_FRAME, refFrame.getName());
440 }
441 }
442 // Just return frame if we don't need to shift the center based on CENTER_NAME
443 // MCI and ICRF are the only non-Earth centered frames specified in Annex A.
444 final boolean isMci = refFrame.asCelestialBodyFrame() == CelestialBodyFrame.MCI;
445 final boolean isIcrf = refFrame.asCelestialBodyFrame() == CelestialBodyFrame.ICRF;
446 final boolean isSolarSystemBarycenter =
447 CelestialBodyFactory.SOLAR_SYSTEM_BARYCENTER.equals(orbitCenter.getBody().getName());
448 if (!(isMci || isIcrf) && CelestialBodyFactory.EARTH.equals(orbitCenter.getBody().getName()) ||
449 isMci && CelestialBodyFactory.MARS.equals(orbitCenter.getBody().getName()) ||
450 isIcrf && isSolarSystemBarycenter) {
451 return refFrame.asFrame();
452 }
453 // else, translate frame to specified center.
454 return new ModifiedFrame(refFrame.asFrame(), refFrame.asCelestialBodyFrame(),
455 orbitCenter.getBody(), orbitCenter.getName());
456 }
457
458 /**
459 * Get the value of {@code REF_FRAME} as an Orekit {@link Frame}. The {@code
460 * ORBIT_CENTER} key word has not been applied yet, so the returned frame may not
461 * correspond to the reference frame of the data in the file.
462 * @return the reference frame
463 */
464 public FrameFacade getRefFrame() {
465 return refFrame;
466 }
467
468 /**
469 * Set the name of the reference frame in which the state vector data are given.
470 * @param refFrame reference frame
471 */
472 public void setRefFrame(final FrameFacade refFrame) {
473 refuseFurtherComments();
474 this.refFrame = refFrame;
475 }
476
477 /** Get gravity model name.
478 * @return gravity model name
479 */
480 public String getGravityModel() {
481 return gravityModel;
482 }
483
484 /** Get degree of the gravity model.
485 * @return degree of the gravity model
486 */
487 public int getGravityDegree() {
488 return gravityDegree;
489 }
490
491 /** Get order of the gravity model.
492 * @return order of the gravity model
493 */
494 public int getGravityOrder() {
495 return gravityOrder;
496 }
497
498 /** Set gravity model.
499 * @param name name of the model
500 * @param degree degree of the model
501 * @param order order of the model
502 */
503 public void setGravityModel(final String name, final int degree, final int order) {
504 refuseFurtherComments();
505 this.gravityModel = name;
506 this.gravityDegree = degree;
507 this.gravityOrder = order;
508 }
509
510 /** Get name of atmospheric model.
511 * @return name of atmospheric model
512 */
513 public String getAtmosphericModel() {
514 return atmosphericModel;
515 }
516
517 /** Set name of atmospheric model.
518 * @param atmosphericModel name of atmospheric model
519 */
520 public void setAtmosphericModel(final String atmosphericModel) {
521 refuseFurtherComments();
522 this.atmosphericModel = atmosphericModel;
523 }
524
525 /** Get n-body perturbation bodies.
526 * @return n-body perturbation bodies
527 */
528 public List<BodyFacade> getNBodyPerturbations() {
529 return nBodyPerturbations;
530 }
531
532 /** Set n-body perturbation bodies.
533 * @param nBody n-body perturbation bodies
534 */
535 public void setNBodyPerturbations(final List<BodyFacade> nBody) {
536 refuseFurtherComments();
537 this.nBodyPerturbations = nBody;
538 }
539
540 /**
541 * Get Enum YesNoUnknown that indicates if Solar Radiation Pressure is taken into account or not.
542 * @return isSolarRadPressure YesNoUnknown
543 */
544 public YesNoUnknown getSolarRadiationPressure() {
545 return isSolarRadPressure;
546 }
547
548 /**
549 * Set Enum that indicates if Solar Radiation Pressure is taken into account or not.
550 * @param isSolRadPressure YesNoUnknown
551 */
552 public void setSolarRadiationPressure(final YesNoUnknown isSolRadPressure) {
553 refuseFurtherComments();
554 this.isSolarRadPressure = isSolRadPressure;
555 }
556
557 /**
558 * Get Enum YesNoUnknown that indicates if Earth and ocean tides are taken into account or not.
559 * @return isEarthTides YesNoUnknown
560 */
561 public YesNoUnknown getEarthTides() {
562 return isEarthTides;
563 }
564
565 /**
566 * Set Enum YesNoUnknown that indicates if Earth and ocean tides are taken into account or not.
567 * @param EarthTides YesNoUnknown
568 */
569 public void setEarthTides(final YesNoUnknown EarthTides) {
570 refuseFurtherComments();
571 this.isEarthTides = EarthTides;
572 }
573
574 /**
575 * Get Enum YesNoUnknown that indicates if intrack thrust modeling was into account or not.
576 * @return isEarthTides YesNoUnknown
577 */
578 public YesNoUnknown getIntrackThrust() {
579 return isIntrackThrustModeled;
580 }
581
582 /**
583 * Set boolean that indicates if intrack thrust modeling was into account or not.
584 * @param IntrackThrustModeled YesNoUnknown
585 */
586 public void setIntrackThrust(final YesNoUnknown IntrackThrustModeled) {
587 refuseFurtherComments();
588 this.isIntrackThrustModeled = IntrackThrustModeled;
589 }
590
591 /** Get the source of the covariance data.
592 * @return the covarianceSource
593 */
594 public String getCovarianceSource() {
595 return covarianceSource;
596 }
597
598 /** Set the source of the covariance data.
599 * @param covarianceSource the covarianceSource to set
600 */
601 public void setCovarianceSource(final String covarianceSource) {
602 refuseFurtherComments();
603 this.covarianceSource = covarianceSource;
604 }
605
606 /** Get the flag indicating the type of alternate covariance information provided.
607 * @return the altCovType
608 */
609 public AltCovarianceType getAltCovType() {
610 return altCovType;
611 }
612
613 /** Set the flag indicating the type of alternate covariance information provided.
614 * @param altCovType the altCovType to set
615 */
616 public void setAltCovType(final AltCovarianceType altCovType) {
617 refuseFurtherComments();
618 this.altCovType = altCovType;
619 }
620
621 /**
622 * Get the value of {@code ALT_COV_REF_FRAME} as an Orekit {@link Frame}.
623 * @return the reference frame
624 */
625 public FrameFacade getAltCovRefFrame() {
626 return altCovRefFrame;
627 }
628
629 /**
630 * Set the name of the reference frame in which the alternate covariance data are given.
631 * @param altCovRefFrame alternate covariance reference frame
632 */
633 public void setAltCovRefFrame(final FrameFacade altCovRefFrame) {
634 refuseFurtherComments();
635
636 if (getAltCovType() == null) {
637 throw new OrekitException(OrekitMessages.CCSDS_MISSING_KEYWORD, CdmMetadataKey.ALT_COV_TYPE);
638 }
639
640 if (altCovRefFrame.asFrame() == null) {
641 throw new OrekitException(OrekitMessages.CCSDS_INVALID_FRAME, altCovRefFrame.getName());
642 }
643
644 // Only set the frame if within the allowed options: GCRF, EME2000, ITRF
645 if ( altCovRefFrame.asCelestialBodyFrame() == CelestialBodyFrame.GCRF ||
646 altCovRefFrame.asCelestialBodyFrame() == CelestialBodyFrame.EME2000 ||
647 altCovRefFrame.asCelestialBodyFrame().name().contains("ITRF") ) {
648 this.altCovRefFrame = altCovRefFrame;
649 } else {
650 throw new OrekitException(OrekitMessages.CCSDS_INVALID_FRAME, altCovRefFrame.getName());
651 }
652 }
653
654 /** Get the unique identifier of Orbit Data Message(s) that are linked (relevant) to this Conjunction Data Message.
655 * @return the odmMsgLink
656 */
657 public String getOdmMsgLink() {
658 return odmMsgLink;
659 }
660
661 /** Set the unique identifier of Orbit Data Message(s) that are linked (relevant) to this Conjunction Data Message.
662 * @param odmMsgLink the odmMsgLink to set
663 */
664 public void setOdmMsgLink(final String odmMsgLink) {
665 refuseFurtherComments();
666 this.odmMsgLink = odmMsgLink;
667 }
668
669 /** Get the unique identifier of Attitude Data Message(s) that are linked (relevant) to this Conjunction Data Message.
670 * @return the admMsgLink
671 */
672 public String getAdmMsgLink() {
673 return admMsgLink;
674 }
675
676 /** Set the unique identifier of Attitude Data Message(s) that are linked (relevant) to this Conjunction Data Message.
677 * @param admMsgLink the admMsgLink to set
678 */
679 public void setAdmMsgLink(final String admMsgLink) {
680 refuseFurtherComments();
681 this.admMsgLink = admMsgLink;
682 }
683
684 /** Get the flag indicating whether new tracking observations are anticipated prior to the issue of the next CDM associated with the event
685 * specified by CONJUNCTION_ID.
686 * @return the obsBeforeNextMessage
687 */
688 public YesNoUnknown getObsBeforeNextMessage() {
689 return obsBeforeNextMessage;
690 }
691
692 /** Set the flag indicating whether new tracking observations are anticipated prior to the issue of the next CDM associated with the event
693 * specified by CONJUNCTION_ID.
694 * @param obsBeforeNextMessage the obsBeforeNextMessage to set
695 */
696 public void setObsBeforeNextMessage(final YesNoUnknown obsBeforeNextMessage) {
697 refuseFurtherComments();
698 this.obsBeforeNextMessage = obsBeforeNextMessage;
699 }
700 }