1   /* Copyright 2002-2022 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.ArrayList;
20  import java.util.List;
21  
22  import org.hipparchus.geometry.euclidean.threed.Vector3D;
23  import org.orekit.errors.OrekitException;
24  import org.orekit.errors.OrekitMessages;
25  import org.orekit.files.ccsds.definitions.PocMethodFacade;
26  import org.orekit.files.ccsds.definitions.TimeSystem;
27  import org.orekit.time.AbsoluteDate;
28  
29  /** This class gathers the relative meta-data present in the Conjunction Data Message (CDM).
30   * @author Melina Vanel
31   * @since 11.2
32   */
33  public class CdmRelativeMetadata {
34  
35      /** Time System: used for metadata, orbit state and covariance data. */
36      private TimeSystem timeSystem;
37  
38      /** Comment. */
39      private List<String> comment;
40  
41      /** Date and time in UTC of the closest approach. */
42      private AbsoluteDate tca;
43  
44      /** Norm of relative position vector at TCA. */
45      private double missDistance;
46  
47      /** Norm of relative velocity vector at TCA. */
48      private double relativeSpeed;
49  
50      /** The length of the relative position vector, normalized to one-sigma dispersions of the combined error covariance
51       * in the direction of the relative position vector. */
52      private double mahalanobisDistance;
53  
54      /** The R component of Object2’s position relative to Object1’s position in the Radial/Transverse/Normal coordinate frame. */
55      private double relativePositionR;
56  
57      /** The T component of Object2’s position relative to Object1’s position in the Radial/Transverse/Normal coordinate frame. */
58      private double relativePositionT;
59  
60      /** The N component of Object2’s position relative to Object1’s position in the Radial/Transverse/Normal coordinate frame. */
61      private double relativePositionN;
62  
63      /** The R component of Object2’s velocity relative to Object1’s veloity in the Radial/Transverse/Normal coordinate frame. */
64      private double relativeVelocityR;
65  
66      /** The T component of Object2’s velocity relative to Object1’s veloity in the Radial/Transverse/Normal coordinate frame. */
67      private double relativeVelocityT;
68  
69      /** The N component of Object2’s velocity relative to Object1’s veloity in the Radial/Transverse/Normal coordinate frame. */
70      private double relativeVelocityN;
71  
72      /** The start time in UTC of the screening period for the conjunction assessment. */
73      private AbsoluteDate startScreenPeriod;
74  
75      /** The stop time in UTC of the screening period for the conjunction assessment. */
76      private AbsoluteDate stopScreenPeriod;
77  
78      /** Shape of the screening volume. */
79      private ScreenVolumeShape screenVolumeShape;
80  
81      /** Shape of the screening volume. */
82      private double screenVolumeRadius;
83  
84      /** Name of the Object1 centered reference frame in which the screening volume data are given. */
85      private ScreenVolumeFrame screenVolumeFrame;
86  
87      /** The R or T (depending on if RTN or TVN is selected) component size of the screening volume in the SCREEN_VOLUME_FRAME. */
88      private double screenVolumeX;
89  
90      /** The T or V (depending on if RTN or TVN is selected) component size of the screening volume in the SCREEN_VOLUME_FRAME. */
91      private double screenVolumeY;
92  
93      /** The N component size of the screening volume in the SCREEN_VOLUME_FRAME. */
94      private double screenVolumeZ;
95  
96      /** The time in UTC when Object2 enters the screening volume. */
97      private AbsoluteDate screenEntryTime;
98  
99      /** The time in UTC when Object2 exits the screening volume. */
100     private AbsoluteDate screenExitTime;
101 
102     /** The probability (denoted ‘p’ where 0.0<=p<=1.0), that Object1 and Object2 will collide. */
103     private double collisionProbability;
104 
105     /** The method that was used to calculate the collision probability. */
106     private PocMethodFacade collisionProbabilityMethod;
107 
108     /** the Originator’s ID that uniquely identifies the conjunction to which the message refers. */
109     private String conjunctionId;
110 
111     /** The approach angle computed between Objects 1 and 2 in the RTN coordinate frame relative to object 1. */
112     private double approachAngle;
113 
114     /** The type of screening to be used. */
115     private ScreenType screenType;
116 
117     /** The maximum collision probability that Object1 and Object2 will collide. */
118     private double maxCollisionProbability;
119 
120     /** The method that was used to calculate the maximum collision probability. */
121     private PocMethodFacade maxCollisionProbabilityMethod;
122 
123    /**  The space environment fragmentation impact (SEFI) adjusted estimate of collision probability that Object1 and Object2 will collide. */
124     private double sefiCollisionProbability;
125 
126     /** The method that was used to calculate the space environment fragmentation impact collision probability. */
127     private PocMethodFacade sefiCollisionProbabilityMethod;
128 
129     /** The Space environment fragmentation model used. */
130     private String sefiFragmentationModel;
131 
132     /** The collision probability screening threshold used to identify this conjunction. */
133     private double screenPcThreshold;
134 
135     /** An array of 1 to n elements indicating the percentile(s) for which estimates of the collision probability are provided in the
136      * COLLISION_PROBABILITY variable. */
137     private int[] collisionPercentile;
138 
139     /** ID of previous CDM issued for event identified by CONJUNCTION_ID. */
140     private String previousMessageId;
141 
142     /** UTC epoch of the previous CDM issued for the event identified by CONJUNCTION_ID. */
143     private AbsoluteDate previousMessageEpoch;
144 
145     /** Scheduled UTC epoch of the next CDM associated with the event identified by CONJUNCTION_ID. */
146     private AbsoluteDate nextMessageEpoch;
147 
148     /** Simple constructor.
149      */
150     public CdmRelativeMetadata() {
151         this.comment = new ArrayList<>();
152 
153         this.relativeSpeed        = Double.NaN;
154         this.relativePositionR    = Double.NaN;
155         this.relativePositionT    = Double.NaN;
156         this.relativePositionN    = Double.NaN;
157 
158         this.relativeVelocityR    = Double.NaN;
159         this.relativeVelocityT    = Double.NaN;
160         this.relativeVelocityN    = Double.NaN;
161 
162         this.approachAngle        = Double.NaN;
163         this.screenVolumeRadius   = Double.NaN;
164         this.screenPcThreshold    = Double.NaN;
165         this.mahalanobisDistance  = Double.NaN;
166 
167 
168         this.screenVolumeX        = Double.NaN;
169         this.screenVolumeY        = Double.NaN;
170         this.screenVolumeZ        = Double.NaN;
171         this.collisionProbability = Double.NaN;
172         this.maxCollisionProbability  = Double.NaN;
173         this.sefiCollisionProbability = Double.NaN;
174 
175     }
176 
177     /** Check is all mandatory entries have been initialized.
178     */
179     public void validate() {
180         checkNotNull(tca,            CdmRelativeMetadataKey.TCA);
181         checkNotNull(missDistance,   CdmRelativeMetadataKey.MISS_DISTANCE);
182         checkScreenVolumeConditions();
183     }
184 
185     /**
186      * Get the Originator’s ID that uniquely identifies the conjunction to which the message refers.
187      * @return the conjunction id
188      */
189     public String getConjunctionId() {
190         return conjunctionId;
191     }
192 
193     /**
194      * Set the Originator’s ID that uniquely identifies the conjunction to which the message refers.
195      * @param conjunctionId the conjunction id to be set
196      */
197     public void setConjunctionId(final String conjunctionId) {
198         this.conjunctionId = conjunctionId;
199     }
200 
201     /**
202      * Get the date and time in UTC of the closest approach.
203      * @return time of closest approach
204      */
205     public AbsoluteDate getTca() {
206         return tca;
207     }
208 
209     /**
210      * Set the date and time in UTC of the closest approach.
211      * @param tca time of closest approach to be set
212      */
213     public void setTca(final AbsoluteDate tca) {
214         this.tca = tca;
215     }
216 
217     /**
218      * Get the norm of relative position vector at TCA.
219      * @return the miss distance (in m)
220      */
221     public double getMissDistance() {
222         return missDistance;
223     }
224 
225     /**
226      * Set the norm of relative position vector at TCA.
227      * @param missDistance the miss distance to be set (in m)
228      */
229     public void setMissDistance(final double missDistance) {
230         this.missDistance = missDistance;
231     }
232 
233     /**
234      * Get the norm of relative velocity vector at TCA.
235      * @return the relative speed at TCA (in m/s)
236      */
237     public double getRelativeSpeed() {
238         return relativeSpeed;
239     }
240 
241     /**
242      * Set the norm of relative velocity vector at TCA.
243      * @param relativeSpeed the relative speed (in m/s) at TCA to be set
244      */
245     public void setRelativeSpeed(final double relativeSpeed) {
246         this.relativeSpeed = relativeSpeed;
247     }
248 
249     /**
250      * Get the Object2’s velocity vector relative to Object1's at TCA in RTN frame, getX for R component,
251      * getY for T component, getZ for N component.
252      * @return the relative speed vector at TCA (in m/s)
253      */
254     public Vector3D getRelativeVelocity() {
255         return new Vector3D(relativeVelocityR, relativeVelocityT, relativeVelocityN);
256     }
257 
258     /**
259      * Get the Object2’s position vector relative to Object1's at TCA in RTN frame, getX for R component,
260      * getY for T component, getZ for N component.
261      * @return the relative position vector at TCA (in m)
262      */
263     public Vector3D getRelativePosition() {
264         return new Vector3D(relativePositionR, relativePositionT, relativePositionN);
265     }
266 
267     /**
268      * Set the R component of Object2’s position relative to Object1’s in RTN frame.
269      * @param relativePositionR the R component (in m) of Object2’s position relative to Object1’s
270      */
271     public void setRelativePositionR(final double relativePositionR) {
272         this.relativePositionR = relativePositionR;
273     }
274 
275     /**
276      * Set the T component of Object2’s position relative to Object1’s in RTN frame.
277      * @param relativePositionT the T component (in m) of Object2’s position relative to Object1’s
278      */
279     public void setRelativePositionT(final double relativePositionT) {
280         this.relativePositionT = relativePositionT;
281     }
282 
283     /**
284      * Set the N component of Object2’s position relative to Object1’s in RTN frame.
285      * @param relativePositionN the N component (in m) of Object2’s position relative to Object1’s
286      */
287     public void setRelativePositionN(final double relativePositionN) {
288         this.relativePositionN = relativePositionN;
289     }
290 
291     /**
292      * Set the R component of Object2’s velocity relative to Object1’s in RTN frame.
293      * @param relativeVelocityR the R component (in m/s) of Object2’s velocity relative to Object1’s
294      */
295     public void setRelativeVelocityR(final double relativeVelocityR) {
296         this.relativeVelocityR = relativeVelocityR;
297     }
298 
299     /**
300      * Set the T component of Object2’s velocity relative to Object1’s in RTN frame.
301      * @param relativeVelocityT the T component (in m/s) of Object2’s velocity relative to Object1’s
302      */
303     public void setRelativeVelocityT(final double relativeVelocityT) {
304         this.relativeVelocityT = relativeVelocityT;
305     }
306 
307     /**
308      * Set the N component of Object2’s velocity relative to Object1’s in RTN frame.
309      * @param relativeVelocityN the N component (in m/s) of Object2’s velocity relative to Object1’s
310      */
311     public void setRelativeVelocityN(final double relativeVelocityN) {
312         this.relativeVelocityN = relativeVelocityN;
313     }
314 
315     /**
316      * Get the start time in UTC of the screening period for the conjunction assessment.
317      * @return start time in UTC of the screening period
318      */
319     public AbsoluteDate getStartScreenPeriod() {
320         return startScreenPeriod;
321     }
322 
323     /**
324      * Set the start time in UTC of the screening period for the conjunction assessment.
325      * @param startScreenPeriod start time in UTC of the screening period to be set
326      */
327     public void setStartScreenPeriod(final AbsoluteDate startScreenPeriod) {
328         this.startScreenPeriod = startScreenPeriod;
329     }
330 
331     /**
332      * Get the stop time in UTC of the screening period for the conjunction assessment.
333      * @return stop time in UTC of the screening period
334      */
335     public AbsoluteDate getStopScreenPeriod() {
336         return stopScreenPeriod;
337     }
338 
339     /**
340      * Set the stop time in UTC of the screening period for the conjunction assessment.
341      * @param stopScreenPeriod stop time in UTC of the screening period to be set
342      */
343     public void setStopScreenPeriod(final AbsoluteDate stopScreenPeriod) {
344         this.stopScreenPeriod = stopScreenPeriod;
345     }
346 
347     /**
348      * Get the name of the Object1 centered reference frame in which the screening volume data are given.
349      * @return name of screen volume frame
350      */
351     public ScreenVolumeFrame getScreenVolumeFrame() {
352         return screenVolumeFrame;
353     }
354 
355     /**
356      * Set the name of the Object1 centered reference frame in which the screening volume data are given.
357      * @param screenVolumeFrame name of screen volume frame
358      */
359     public void setScreenVolumeFrame(final ScreenVolumeFrame screenVolumeFrame) {
360         this.screenVolumeFrame = screenVolumeFrame;
361     }
362 
363     /**
364      * Get the shape of the screening volume.
365      * @return shape of the screening volume
366      */
367     public ScreenVolumeShape getScreenVolumeShape() {
368         return screenVolumeShape;
369     }
370 
371     /**
372      * Set the shape of the screening volume.
373      * @param screenVolumeShape shape of the screening volume
374      */
375     public void setScreenVolumeShape(final ScreenVolumeShape screenVolumeShape) {
376         this.screenVolumeShape = screenVolumeShape;
377     }
378 
379     /**
380      * Get the R or T (depending on if RTN or TVN is selected) component size of the screening volume in the corresponding frame.
381      * @return first component size of the screening volume (in m)
382      */
383     public double getScreenVolumeX() {
384         return screenVolumeX;
385     }
386 
387     /**
388      * Set the R or T (depending on if RTN or TVN is selected) component size of the screening volume in the corresponding frame.
389      * @param screenVolumeX first component size of the screening volume (in m)
390      */
391     public void setScreenVolumeX(final double screenVolumeX) {
392         this.screenVolumeX = screenVolumeX;
393     }
394 
395     /**
396      * Get the T or V (depending on if RTN or TVN is selected) component size of the screening volume in the corresponding frame.
397      * @return second component size of the screening volume (in m)
398      */
399     public double getScreenVolumeY() {
400         return screenVolumeY;
401     }
402 
403     /**
404      * Set the T or V (depending on if RTN or TVN is selected) component size of the screening volume in the corresponding frame.
405      * @param screenVolumeY second component size of the screening volume (in m)
406      */
407     public void setScreenVolumeY(final double screenVolumeY) {
408         this.screenVolumeY = screenVolumeY;
409     }
410 
411     /**
412      * Get the N component size of the screening volume in the corresponding frame.
413      * @return third component size of the screening volume (in m)
414      */
415     public double getScreenVolumeZ() {
416         return screenVolumeZ;
417     }
418 
419     /**
420      * Set the N component size of the screening volume in the corresponding frame.
421      * @param screenVolumeZ third component size of the screening volume (in m)
422      */
423     public void setScreenVolumeZ(final double screenVolumeZ) {
424         this.screenVolumeZ = screenVolumeZ;
425     }
426 
427     /**
428      * Get the time in UTC when Object2 enters the screening volume.
429      * @return time in UTC when Object2 enters the screening volume
430      */
431     public AbsoluteDate getScreenEntryTime() {
432         return screenEntryTime;
433     }
434 
435     /**
436      * Set the time in UTC when Object2 enters the screening volume.
437      * @param screenEntryTime time in UTC when Object2 enters the screening volume
438      */
439     public void setScreenEntryTime(final AbsoluteDate screenEntryTime) {
440         this.screenEntryTime = screenEntryTime;
441     }
442 
443     /**
444      * Get the time in UTC when Object2 exits the screening volume.
445      * @return time in UTC when Object2 exits the screening volume
446      */
447     public AbsoluteDate getScreenExitTime() {
448         return screenExitTime;
449     }
450 
451     /**
452      * Set the time in UTC when Object2 exits the screening volume.
453      * @param screenExitTime time in UTC when Object2 exits the screening volume
454      */
455     public void setScreenExitTime(final AbsoluteDate screenExitTime) {
456         this.screenExitTime = screenExitTime;
457     }
458 
459     /**
460      * Get the probability (between 0.0 and 1.0) that Object1 and Object2 will collide.
461      * @return probability of collision
462      */
463     public double getCollisionProbability() {
464         return collisionProbability;
465     }
466 
467     /**
468      * Set the probability (between 0.0 and 1.0) that Object1 and Object2 will collide.
469      * @param collisionProbability first component size of the screening volume
470      */
471     public void setCollisionProbability(final double collisionProbability) {
472         this.collisionProbability = collisionProbability;
473     }
474 
475     /**
476      * Get the method that was used to calculate the collision probability.
477      * @return method to calculate probability of collision
478      */
479     public PocMethodFacade getCollisionProbaMethod() {
480         return collisionProbabilityMethod;
481     }
482 
483     /**
484      * Set the method that was used to calculate the collision probability.
485      * @param collisionProbaMethod method used to calculate probability of collision
486      */
487     public void setCollisionProbaMethod(final PocMethodFacade collisionProbaMethod) {
488         this.collisionProbabilityMethod = collisionProbaMethod;
489     }
490 
491     /** Complain if a field is null.
492      * @param field field to check
493      * @param key key associated with the field
494      */
495     public void checkNotNull(final Object field, final Enum<?> key) {
496         if (field == null) {
497             throw new OrekitException(OrekitMessages.UNINITIALIZED_VALUE_FOR_KEY, key.name());
498         }
499     }
500 
501     /** Set the Time System that: for CDM, is used for relative metadata, metadata,
502      * OD parameters, state vector. In CDM all date are given in UTC.
503      * @param timeSystem the time system to be set
504      */
505     public void setTimeSystem(final TimeSystem timeSystem) {
506         this.timeSystem = timeSystem;
507     }
508 
509     /** Get the Time System that: for CDM, is used for relative metadata, metadata,
510      * OD parameters, state vector. In CDM all date are given in UTC.
511      * @return the time system
512      */
513     public TimeSystem getTimeSystem() {
514         return timeSystem;
515     }
516 
517     /** Set comment for relative metadata.
518      * @param comments to be set
519      */
520     public void addComment(final String comments) {
521         this.comment.add(comments);
522     }
523 
524     /** Get comment for relative metadata.
525      * @return the time system
526      */
527     public List<String> getComment() {
528         return comment;
529     }
530 
531     /** Get the approach angle computed between Objects 1 and 2 in the RTN coordinate frame relative to object 1.
532      * @return the approachAngle
533      */
534     public double getApproachAngle() {
535         return approachAngle;
536     }
537 
538     /** Set the approach angle computed between Objects 1 and 2 in the RTN coordinate frame relative to object 1.
539      * @param approachAngle the approachAngle to set
540      */
541     public void setApproachAngle(final double approachAngle) {
542         this.approachAngle = approachAngle;
543     }
544 
545     /** Get the type of screening to be used.
546      * @return the screenType
547      */
548     public ScreenType getScreenType() {
549         return screenType;
550     }
551 
552     /** Set the type of screening to be used.
553      * @param screenType the screenType to set
554      */
555     public void setScreenType(final ScreenType screenType) {
556         this.screenType = screenType;
557     }
558 
559     /**
560      * @return the maxCollisionProbability
561      */
562     public double getMaxCollisionProbability() {
563         return maxCollisionProbability;
564     }
565 
566     /**
567      * @param maxCollisionProbability the maxCollisionProbability to set
568      */
569     public void setMaxCollisionProbability(final double maxCollisionProbability) {
570         this.maxCollisionProbability = maxCollisionProbability;
571     }
572 
573     /**
574      * @return the maxCollisionProbabilityMethod
575      */
576     public PocMethodFacade getMaxCollisionProbabilityMethod() {
577         return maxCollisionProbabilityMethod;
578     }
579 
580     /**
581      * @param pocMethodFacade the maxCollisionProbabilityMethod to set
582      */
583     public void setMaxCollisionProbabilityMethod(final PocMethodFacade pocMethodFacade) {
584         this.maxCollisionProbabilityMethod = pocMethodFacade;
585     }
586 
587     /**
588      * @return the sefiCollisionProbability
589      */
590     public double getSefiCollisionProbability() {
591         return sefiCollisionProbability;
592     }
593 
594     /**
595      * @param sefiCollisionProbability the sefiCollisionProbability to set
596      */
597     public void setSefiCollisionProbability(final double sefiCollisionProbability) {
598         this.sefiCollisionProbability = sefiCollisionProbability;
599     }
600 
601     /**
602      * @return the sefiCollisionProbabilityMethod
603      */
604     public PocMethodFacade getSefiCollisionProbabilityMethod() {
605         return sefiCollisionProbabilityMethod;
606     }
607 
608     /**
609      * @param pocMethodFacade the sefiCollisionProbabilityMethod to set
610      */
611     public void setSefiCollisionProbabilityMethod(final PocMethodFacade pocMethodFacade) {
612         this.sefiCollisionProbabilityMethod = pocMethodFacade;
613     }
614 
615     /**
616      * @return the sefiFragmentationModel
617      */
618     public String getSefiFragmentationModel() {
619         return sefiFragmentationModel;
620     }
621 
622     /**
623      * @param sefiFragmentationModel the sefiFragmentationModel to set
624      */
625     public void setSefiFragmentationModel(final String sefiFragmentationModel) {
626         this.sefiFragmentationModel = sefiFragmentationModel;
627     }
628 
629     /** Get the Mahalanobis Distance. The length of the relative position vector, normalized to one-sigma dispersions of the combined error covariance
630      * in the direction of the relative position vector.
631      * @return the mahalanobisDistance
632      */
633     public double getMahalanobisDistance() {
634         return mahalanobisDistance;
635     }
636 
637     /** Set the Mahalanobis Distance. The length of the relative position vector, normalized to one-sigma dispersions of the combined error covariance
638      * in the direction of the relative position vector.
639      * @param mahalanobisDistance the mahalanobisDistance to set
640      */
641     public void setMahalanobisDistance(final double mahalanobisDistance) {
642         this.mahalanobisDistance = mahalanobisDistance;
643     }
644 
645     /**
646      * @return the screenVolumeRadius
647      */
648     public double getScreenVolumeRadius() {
649         return screenVolumeRadius;
650     }
651 
652     /**
653      * @param screenVolumeRadius the screenVolumeRadius to set
654      */
655     public void setScreenVolumeRadius(final double screenVolumeRadius) {
656         this.screenVolumeRadius = screenVolumeRadius;
657     }
658 
659     /** Get the collision probability screening threshold used to identify this conjunction.
660     * @return the screenPcThreshold
661     */
662     public double getScreenPcThreshold() {
663         return screenPcThreshold;
664     }
665 
666     /** Set the collision probability screening threshold used to identify this conjunction.
667     * @param screenPcThreshold the screenPcThreshold to set
668     */
669     public void setScreenPcThreshold(final double screenPcThreshold) {
670         this.screenPcThreshold = screenPcThreshold;
671     }
672 
673     public void checkScreenVolumeConditions() {
674 
675         if (this.getScreenType() == ScreenType.SHAPE) {
676 
677             if (this.getScreenEntryTime() == null) {
678                 throw new OrekitException(OrekitMessages.CCSDS_MISSING_KEYWORD, CdmRelativeMetadataKey.SCREEN_ENTRY_TIME);
679             }
680 
681             if (this.getScreenExitTime() == null) {
682                 throw new OrekitException(OrekitMessages.CCSDS_MISSING_KEYWORD, CdmRelativeMetadataKey.SCREEN_EXIT_TIME);
683             }
684 
685             if (this.getScreenVolumeShape() == null) {
686                 throw new OrekitException(OrekitMessages.CCSDS_MISSING_KEYWORD, CdmRelativeMetadataKey.SCREEN_VOLUME_SHAPE);
687             }
688 
689             if (this.getScreenVolumeShape() == ScreenVolumeShape.SPHERE) {
690 
691                 if (Double.isNaN(this.getScreenVolumeRadius())) {
692                     throw new OrekitException(OrekitMessages.CCSDS_MISSING_KEYWORD, CdmRelativeMetadataKey.SCREEN_VOLUME_RADIUS);
693                 }
694 
695             } else if (this.getScreenVolumeShape() == ScreenVolumeShape.ELLIPSOID || this.getScreenVolumeShape() == ScreenVolumeShape.BOX) {
696 
697                 if (this.getScreenVolumeFrame() == null) {
698                     throw new OrekitException(OrekitMessages.CCSDS_MISSING_KEYWORD, CdmRelativeMetadataKey.SCREEN_VOLUME_FRAME);
699                 }
700                 if (Double.isNaN(this.getScreenVolumeX())) {
701                     throw new OrekitException(OrekitMessages.CCSDS_MISSING_KEYWORD, CdmRelativeMetadataKey.SCREEN_VOLUME_X);
702                 }
703                 if (Double.isNaN(this.getScreenVolumeY())) {
704                     throw new OrekitException(OrekitMessages.CCSDS_MISSING_KEYWORD, CdmRelativeMetadataKey.SCREEN_VOLUME_Y);
705                 }
706                 if (Double.isNaN(this.getScreenVolumeZ())) {
707                     throw new OrekitException(OrekitMessages.CCSDS_MISSING_KEYWORD, CdmRelativeMetadataKey.SCREEN_VOLUME_Z);
708                 }
709             }
710 
711         } else if (this.getScreenType() == ScreenType.PC || this.getScreenType() == ScreenType.PC_MAX) {
712 
713             if (Double.isNaN(this.getScreenPcThreshold())) {
714                 throw new OrekitException(OrekitMessages.CCSDS_MISSING_KEYWORD, CdmRelativeMetadataKey.SCREEN_PC_THRESHOLD);
715             }
716         }
717 
718     }
719 
720     /** Get the array of 1 to n elements indicating the percentile(s) for which estimates of the collision probability are provided in the
721      * COLLISION_PROBABILITY variable.
722      * @return the collisionPercentile
723      */
724     public int[] getCollisionPercentile() {
725         return collisionPercentile == null ? null : collisionPercentile.clone();
726     }
727 
728     /** Set the array of 1 to n elements indicating the percentile(s) for which estimates of the collision probability are provided in the
729      * COLLISION_PROBABILITY variable.
730      * @param collisionPercentile the collisionPercentile to set
731      */
732     public void setCollisionPercentile(final int[] collisionPercentile) {
733         this.collisionPercentile = collisionPercentile == null ? null : collisionPercentile.clone();;
734     }
735 
736     /** Get the ID of previous CDM issued for event identified by CONJUNCTION_ID.
737      * @return the previousMessageId
738      */
739     public String getPreviousMessageId() {
740         return previousMessageId;
741     }
742 
743     /** Set the ID of previous CDM issued for event identified by CONJUNCTION_ID.
744      * @param previousMessageId the previousMessageId to set
745      */
746     public void setPreviousMessageId(final String previousMessageId) {
747         this.previousMessageId = previousMessageId;
748     }
749 
750     /** Get the UTC epoch of the previous CDM issued for the event identified by CONJUNCTION_ID.
751      * @return the previousMessageEpoch
752      */
753     public AbsoluteDate getPreviousMessageEpoch() {
754         return previousMessageEpoch;
755     }
756 
757     /** Set the UTC epoch of the previous CDM issued for the event identified by CONJUNCTION_ID.
758      * @param previousMessageEpoch the previousMessageEpoch to set
759      */
760     public void setPreviousMessageEpoch(final AbsoluteDate previousMessageEpoch) {
761         this.previousMessageEpoch = previousMessageEpoch;
762     }
763 
764     /** Get Scheduled UTC epoch of the next CDM associated with the event identified by CONJUNCTION_ID.
765      * @return the nextMessageEpoch
766      */
767     public AbsoluteDate getNextMessageEpoch() {
768         return nextMessageEpoch;
769     }
770 
771     /** Set Scheduled UTC epoch of the next CDM associated with the event identified by CONJUNCTION_ID.
772      * @param nextMessageEpoch the nextMessageEpoch to set
773      */
774     public void setNextMessageEpoch(final AbsoluteDate nextMessageEpoch) {
775         this.nextMessageEpoch = nextMessageEpoch;
776     }
777 }