1   /* Copyright 2002-2026 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;
18  
19  import org.hipparchus.complex.Quaternion;
20  import org.orekit.files.ccsds.definitions.CcsdsFrameMapper;
21  import org.orekit.files.ccsds.definitions.FrameFacade;
22  import org.orekit.files.ccsds.ndm.cdm.AdditionalParameters;
23  import org.orekit.files.ccsds.ndm.odm.ocm.OrbitPhysicalProperties;
24  import org.orekit.files.ccsds.section.CommentsContainer;
25  import org.orekit.frames.Frame;
26  import org.orekit.time.AbsoluteDate;
27  
28  /** Container for common physical properties for both {@link OrbitPhysicalProperties} and {@link AdditionalParameters}.
29   * <p>
30   * Beware that the Orekit getters and setters all rely on SI units. The parsers
31   * and writers take care of converting these SI units into CCSDS mandatory units.
32   * The {@link org.orekit.utils.units.Unit Unit} class provides useful
33   * {@link org.orekit.utils.units.Unit#fromSI(double) fromSi} and
34   * {@link org.orekit.utils.units.Unit#toSI(double) toSI} methods in case the callers
35   * already use CCSDS units instead of the API SI units. The general-purpose
36   * {@link org.orekit.utils.units.Unit Unit} class (without an 's') and the
37   * CCSDS-specific {@link org.orekit.files.ccsds.definitions.Units Units} class
38   * (with an 's') also provide some predefined units. These predefined units and the
39   * {@link org.orekit.utils.units.Unit#fromSI(double) fromSi} and
40   * {@link org.orekit.utils.units.Unit#toSI(double) toSI} conversion methods are indeed
41   * what the parsers and writers use for the conversions.
42   * </p>
43   * @author Maxime Journot
44   * @since 11.3
45   */
46  public class CommonPhysicalProperties extends CommentsContainer {
47  
48      /** For creating a {@link Frame}. */
49      private final CcsdsFrameMapper frameMapper;
50  
51      /** Optimally Enclosing Box parent reference frame. */
52      private FrameFacade oebParentFrame;
53  
54      /** Optimally Enclosing Box parent reference frame epoch. */
55      private AbsoluteDate oebParentFrameEpoch;
56  
57      /** Quaternion defining Optimally Enclosing Box. */
58      private final double[] oebQ;
59  
60      /** Maximum physical dimension of Optimally Enclosing Box. */
61      private double oebMax;
62  
63      /** Intermediate physical dimension of Optimally Enclosing Box. */
64      private double oebIntermediate;
65  
66      /** Minimum physical dimension of Optimally Enclosing Box. */
67      private double oebMin;
68  
69      /** Cross-sectional area of Optimally Enclosing Box when viewed along the maximum OEB direction. */
70      private double oebAreaAlongMax;
71  
72      /** Cross-sectional area of Optimally Enclosing Box when viewed along the intermediate OEB direction. */
73      private double oebAreaAlongIntermediate;
74  
75      /** Cross-sectional area of Optimally Enclosing Box when viewed along the minimum OEB direction. */
76      private double oebAreaAlongMin;
77  
78          /** Typical (50th percentile) radar cross-section. */
79      private double rcs;
80  
81      /** Minimum radar cross-section. */
82      private double minRcs;
83  
84      /** Maximum radar cross-section. */
85      private double maxRcs;
86  
87      /** Typical (50th percentile) visual magnitude. */
88      private double vmAbsolute;
89  
90      /** Minimum apparent visual magnitude. */
91      private double vmApparentMin;
92  
93      /** Typical (50th percentile) apparent visual magnitude. */
94      private double vmApparent;
95  
96      /** Maximum apparent visual magnitude. */
97      private double vmApparentMax;
98  
99      /** Typical (50th percentile) coefficient of reflectivity. */
100     private double reflectance;
101 
102     /**
103      * Simple constructor.
104      *
105      * @param frameMapper for creating a {@link Frame}.
106      * @since 13.1.5
107      */
108     public CommonPhysicalProperties(final CcsdsFrameMapper frameMapper) {
109         // 502.0-B-3 (page 6-23) says the default is RSW_ROTATING, but also says,
110         // "This keyword shall be provided if OEB_Q1,2,3,4 are specified".
111         // Which means it must be specified in the file any time it would be used,
112         // which leaves the default without any effect.
113         this.frameMapper         = frameMapper;
114         oebParentFrame           = new FrameFacade(null, null, null, null, null);
115         // 502.0-B-3 (page 6-23) says the default is EPOCH_TZERO from the OCM metadata.
116         oebParentFrameEpoch      = null;
117         // 502.0-B-3 (page 6-23) says these four values are optional.
118         oebQ                     = new double[] {Double.NaN, Double.NaN, Double.NaN, Double.NaN};
119         oebMax                   = Double.NaN;
120         oebIntermediate          = Double.NaN;
121         oebMin                   = Double.NaN;
122         oebAreaAlongMax          = Double.NaN;
123         oebAreaAlongIntermediate = Double.NaN;
124         oebAreaAlongMin          = Double.NaN;
125         rcs                      = Double.NaN;
126         minRcs                   = Double.NaN;
127         maxRcs                   = Double.NaN;
128         vmAbsolute               = Double.NaN;
129         vmApparentMin            = Double.NaN;
130         vmApparent               = Double.NaN;
131         vmApparentMax            = Double.NaN;
132         reflectance              = Double.NaN;
133     }
134 
135     /** Get the Optimally Enclosing Box parent reference frame.
136      * @return Optimally Enclosing Box parent reference frame
137      */
138     public FrameFacade getOebParentFrame() {
139         return oebParentFrame;
140     }
141 
142     /** Set the Optimally Enclosing Box parent reference frame.
143      * @param oebParentFrame Optimally Enclosing Box parent reference frame
144      */
145     public void setOebParentFrame(final FrameFacade oebParentFrame) {
146         refuseFurtherComments();
147         this.oebParentFrame = oebParentFrame;
148     }
149 
150     /** Get the Optimally Enclosing Box parent reference frame epoch.
151      * @return Optimally Enclosing Box parent reference frame epoch
152      */
153     public AbsoluteDate getOebParentFrameEpoch() {
154         return oebParentFrameEpoch;
155     }
156 
157     /** Set the Optimally Enclosing Box parent reference frame epoch.
158      * @param oebParentFrameEpoch Optimally Enclosing Box parent reference frame epoch
159      */
160     public void setOebParentFrameEpoch(final AbsoluteDate oebParentFrameEpoch) {
161         refuseFurtherComments();
162         this.oebParentFrameEpoch = oebParentFrameEpoch;
163     }
164 
165     /**
166      * Get the mapping between a CCSDS frame and a {@link Frame}.
167      *
168      * @return the frame mapper.
169      * @since 13.1.5
170      */
171     public CcsdsFrameMapper getFrameMapper() {
172         return frameMapper;
173     }
174 
175     /**
176      * Get the frame OEB parent frame. Note that only the orientation of the
177      * returned frame is significant, the position of the returned frame is
178      * irrelevant and should be ignored.
179      *
180      * @return Orekit frame for this covariance history.
181      * @see #getOebParentFrame()
182      * @see #getOebParentFrameEpoch()
183      * @see #getFrameMapper()
184      * @since 13.1.5
185      */
186     public Frame getOebParent() {
187         return getFrameMapper()
188                 .buildCcsdsFrame(getOebParentFrame(), getOebParentFrameEpoch());
189     }
190 
191     /** Get the quaternion defining Optimally Enclosing Box.
192      * @return quaternion defining Optimally Enclosing Box
193      */
194     public Quaternion getOebQ() {
195         return new Quaternion(oebQ[0], oebQ[1], oebQ[2], oebQ[3]);
196     }
197 
198     /** set the component of quaternion defining Optimally Enclosing Box.
199      * @param i index of the component
200      * @param qI component of quaternion defining Optimally Enclosing Box
201      */
202     public void setOebQ(final int i, final double qI) {
203         refuseFurtherComments();
204         oebQ[i] = qI;
205     }
206 
207     /** Get the maximum physical dimension of the OEB.
208      * @return maximum physical dimension of the OEB.
209      */
210     public double getOebMax() {
211         return oebMax;
212     }
213 
214     /** Set the maximum physical dimension of the OEB.
215      * @param oebMax maximum physical dimension of the OEB.
216      */
217     public void setOebMax(final double oebMax) {
218         refuseFurtherComments();
219         this.oebMax = oebMax;
220     }
221 
222     /** Get the intermediate physical dimension of the OEB.
223      * @return intermediate physical dimension of the OEB.
224      */
225     public double getOebIntermediate() {
226         return oebIntermediate;
227     }
228 
229     /** Set the intermediate physical dimension of the OEB.
230      * @param oebIntermediate intermediate physical dimension of the OEB.
231      */
232     public void setOebIntermediate(final double oebIntermediate) {
233         refuseFurtherComments();
234         this.oebIntermediate = oebIntermediate;
235     }
236 
237     /** Get the minimum physical dimension of the OEB.
238      * @return dimensions the minimum physical dimension of the OEB.
239      */
240     public double getOebMin() {
241         return oebMin;
242     }
243 
244     /** Set the minimum physical dimension of the OEB.
245      * @param oebMin the minimum physical dimension of the OEB.
246      */
247     public void setOebMin(final double oebMin) {
248         refuseFurtherComments();
249         this.oebMin = oebMin;
250     }
251 
252     /** Get the cross-sectional area of Optimally Enclosing Box when viewed along the maximum OEB direction.
253      * @return cross-sectional area of Optimally Enclosing Box when viewed along the maximum OEB direction.
254      */
255     public double getOebAreaAlongMax() {
256         return oebAreaAlongMax;
257     }
258 
259     /** Set the cross-sectional area of Optimally Enclosing Box when viewed along the maximum OEB direction.
260      * @param oebAreaAlongMax cross-sectional area of Optimally Enclosing Box when viewed along the maximum OEB direction.
261      */
262     public void setOebAreaAlongMax(final double oebAreaAlongMax) {
263         refuseFurtherComments();
264         this.oebAreaAlongMax = oebAreaAlongMax;
265     }
266 
267     /** Get the cross-sectional area of Optimally Enclosing Box when viewed along the intermediate OEB direction.
268      * @return cross-sectional area of Optimally Enclosing Box when viewed along the intermediate OEB direction.
269      */
270     public double getOebAreaAlongIntermediate() {
271         return oebAreaAlongIntermediate;
272     }
273 
274     /** Set the cross-sectional area of Optimally Enclosing Box when viewed along the intermediate OEB direction.
275      * @param oebAreaAlongIntermediate cross-sectional area of Optimally Enclosing Box when viewed along the intermediate OEB direction.
276      */
277     public void setOebAreaAlongIntermediate(final double oebAreaAlongIntermediate) {
278         refuseFurtherComments();
279         this.oebAreaAlongIntermediate = oebAreaAlongIntermediate;
280     }
281 
282     /** Get the cross-sectional area of Optimally Enclosing Box when viewed along the minimum OEB direction.
283      * @return cross-sectional area of Optimally Enclosing Box when viewed along the minimum OEB direction.
284      */
285     public double getOebAreaAlongMin() {
286         return oebAreaAlongMin;
287     }
288 
289     /** Set the cross-sectional area of Optimally Enclosing Box when viewed along the minimum OEB direction.
290      * @param oebAreaAlongMin cross-sectional area of Optimally Enclosing Box when viewed along the minimum OEB direction.
291      */
292     public void setOebAreaAlongMin(final double oebAreaAlongMin) {
293         refuseFurtherComments();
294         this.oebAreaAlongMin = oebAreaAlongMin;
295     }
296 
297 
298     /** Get the typical (50th percentile) radar cross-section.
299      * @return typical (50th percentile) radar cross-section
300      */
301     public double getRcs() {
302         return rcs;
303     }
304 
305     /** Set the typical (50th percentile) radar cross-section.
306      * @param rcs typical (50th percentile) radar cross-section
307      */
308     public void setRcs(final double rcs) {
309         refuseFurtherComments();
310         this.rcs = rcs;
311     }
312 
313     /** Get the minimum radar cross-section.
314      * @return minimum radar cross-section
315      */
316     public double getMinRcs() {
317         return minRcs;
318     }
319 
320     /** Set the minimum radar cross-section.
321      * @param minRcs minimum radar cross-section
322      */
323     public void setMinRcs(final double minRcs) {
324         refuseFurtherComments();
325         this.minRcs = minRcs;
326     }
327 
328     /** Get the maximum radar cross-section.
329      * @return maximum radar cross-section
330      */
331     public double getMaxRcs() {
332         return maxRcs;
333     }
334 
335     /** Set the maximum radar cross-section.
336      * @param maxRcs maximum radar cross-section
337      */
338     public void setMaxRcs(final double maxRcs) {
339         refuseFurtherComments();
340         this.maxRcs = maxRcs;
341     }
342 
343     /** Get the typical (50th percentile) visual magnitude.
344      * @return typical (50th percentile) visual magnitude
345      */
346     public double getVmAbsolute() {
347         return vmAbsolute;
348     }
349 
350     /** Set the typical (50th percentile) visual magnitude.
351      * @param vmAbsolute typical (50th percentile) visual magnitude
352      */
353     public void setVmAbsolute(final double vmAbsolute) {
354         refuseFurtherComments();
355         this.vmAbsolute = vmAbsolute;
356     }
357 
358     /** Get the minimum apparent visual magnitude.
359      * @return minimum apparent visual magnitude
360      */
361     public double getVmApparentMin() {
362         return vmApparentMin;
363     }
364 
365     /** Set the minimum apparent visual magnitude.
366      * @param vmApparentMin minimum apparent visual magnitude
367      */
368     public void setVmApparentMin(final double vmApparentMin) {
369         refuseFurtherComments();
370         this.vmApparentMin = vmApparentMin;
371     }
372 
373     /** Get the typical (50th percentile) apparent visual magnitude.
374      * @return typical (50th percentile) apparent visual magnitude
375      */
376     public double getVmApparent() {
377         return vmApparent;
378     }
379 
380     /** Set the typical (50th percentile) apparent visual magnitude.
381      * @param vmApparent typical (50th percentile) apparent visual magnitude
382      */
383     public void setVmApparent(final double vmApparent) {
384         refuseFurtherComments();
385         this.vmApparent = vmApparent;
386     }
387 
388     /** Get the maximum apparent visual magnitude.
389      * @return maximum apparent visual magnitude
390      */
391     public double getVmApparentMax() {
392         return vmApparentMax;
393     }
394 
395     /** Set the maximum apparent visual magnitude.
396      * @param vmApparentMax maximum apparent visual magnitude
397      */
398     public void setVmApparentMax(final double vmApparentMax) {
399         refuseFurtherComments();
400         this.vmApparentMax = vmApparentMax;
401     }
402 
403     /** Get the typical (50th percentile) coefficient of reflectance.
404      * @return typical (50th percentile) coefficient of reflectance
405      */
406     public double getReflectance() {
407         return reflectance;
408     }
409 
410     /** Set the typical (50th percentile) coefficient of reflectance.
411      * @param reflectance typical (50th percentile) coefficient of reflectance
412      */
413     public void setReflectance(final double reflectance) {
414         refuseFurtherComments();
415         this.reflectance = reflectance;
416     }
417 }