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  
18  package org.orekit.files.ccsds.ndm.odm.ocm;
19  
20  import java.util.ArrayList;
21  import java.util.List;
22  
23  import org.hipparchus.linear.DefaultRealMatrixChangingVisitor;
24  import org.hipparchus.linear.MatrixUtils;
25  import org.hipparchus.linear.RealMatrix;
26  import org.orekit.files.ccsds.definitions.CcsdsFrameMapper;
27  import org.orekit.files.ccsds.ndm.CommonPhysicalProperties;
28  import org.orekit.frames.Frame;
29  import org.orekit.time.AbsoluteDate;
30  import org.orekit.utils.Constants;
31  
32  /** Spacecraft physical properties.
33   * @author Luc Maisonobe
34   * @since 11.0
35   */
36  public class OrbitPhysicalProperties extends CommonPhysicalProperties {
37  
38      /** Satellite manufacturer name. */
39      private String manufacturer;
40  
41      /** Bus model name. */
42      private String busModel;
43  
44      /** Other space objects this object is docked to. */
45      private List<String> dockedWith;
46  
47      /** Attitude-independent drag cross-sectional area, not already into attitude-dependent area along OEB. */
48      private double dragConstantArea;
49  
50      /** Nominal drag coefficient. */
51      private double dragCoefficient;
52  
53      /** Drag coefficient 1σ uncertainty. */
54      private double dragUncertainty;
55  
56      /** Total mass at beginning of life. */
57      private double initialWetMass;
58  
59      /** Total mass at T₀. */
60      private double wetMass;
61  
62      /** Mass without propellant. */
63      private double dryMass;
64  
65      /** Minimum cross-sectional area for collision probability estimation purposes. */
66      private double minAreaForCollisionProbability;
67  
68      /** Maximum cross-sectional area for collision probability estimation purposes. */
69      private double maxAreaForCollisionProbability;
70  
71      /** Typical (50th percentile) cross-sectional area for collision probability estimation purposes. */
72      private double typAreaForCollisionProbability;
73  
74      /** Attitude-independent SRP area, not already into attitude-dependent area along OEB. */
75      private double srpConstantArea;
76  
77      /** Nominal SRP coefficient. */
78      private double srpCoefficient;
79  
80      /** SRP coefficient 1σ uncertainty. */
81      private double srpUncertainty;
82  
83      /** Attitude control mode. */
84      private String attitudeControlMode;
85  
86      /** Type of actuator for attitude control. */
87      private String attitudeActuatorType;
88  
89      /** Accuracy of attitude knowledge. */
90      private double attitudeKnowledgeAccuracy;
91  
92      /** Accuracy of attitude control. */
93      private double attitudeControlAccuracy;
94  
95      /** Overall accuracy of spacecraft to maintain attitude. */
96      private double attitudePointingAccuracy;
97  
98      /** Average average frequency of orbit or attitude maneuvers (in SI units, hence per second). */
99      private double maneuversFrequency;
100 
101     /** Maximum composite thrust the spacecraft can accomplish. */
102     private double maxThrust;
103 
104     /** Total ΔV capability at beginning of life. */
105     private double bolDv;
106 
107     /** Total ΔV remaining for spacecraft. */
108     private double remainingDv;
109 
110     /** Inertia matrix. */
111     private final RealMatrix inertiaMatrix;
112 
113     /**
114      * Simple constructor.
115      *
116      * @param epochT0     T0 epoch from file metadata
117      * @param frameMapper for creating a {@link Frame}.
118      * @since 13.1.5
119      */
120     public OrbitPhysicalProperties(final AbsoluteDate epochT0,
121                                    final CcsdsFrameMapper frameMapper) {
122 
123         // Call to CommonPhysicalProperties constructor
124         super(frameMapper);
125 
126         // we don't call the setXxx() methods in order to avoid
127         // calling refuseFurtherComments as a side effect
128         dockedWith                     = new ArrayList<>();
129         // 502.0-B-3 (page 6-22) says these drag values are optional.
130         dragConstantArea               = Double.NaN;
131         dragCoefficient                = Double.NaN;
132         dragUncertainty                = Double.NaN;
133         // 502.0-B-3 (page 6-25) says these SRP values are optional.
134         srpCoefficient                 = Double.NaN;
135         srpConstantArea                = Double.NaN;
136         srpUncertainty                 = Double.NaN;
137         initialWetMass                 = Double.NaN;
138         wetMass                        = Double.NaN;
139         dryMass                        = Double.NaN;
140         minAreaForCollisionProbability = Double.NaN;
141         maxAreaForCollisionProbability = Double.NaN;
142         typAreaForCollisionProbability = Double.NaN;
143         attitudeKnowledgeAccuracy      = Double.NaN;
144         attitudeControlAccuracy        = Double.NaN;
145         attitudePointingAccuracy       = Double.NaN;
146         maneuversFrequency             = Double.NaN;
147         maxThrust                      = Double.NaN;
148         bolDv                          = Double.NaN;
149         remainingDv                    = Double.NaN;
150         // 502.0-B-3 (page 6-27) says these inertia values are optional.
151         inertiaMatrix                  = MatrixUtils.createRealMatrix(3, 3);
152         // set all values to NaN
153         inertiaMatrix.walkInOptimizedOrder(new DefaultRealMatrixChangingVisitor() {
154             @Override
155             public double visit(final int i, final int j, final double v) {
156                 return Double.NaN;
157             }
158         });
159     }
160 
161     /** Get manufacturer name.
162      * @return manufacturer name
163      */
164     public String getManufacturer() {
165         return manufacturer;
166     }
167 
168     /** Set manufacturer name.
169      * @param manufacturer manufacturer name
170      */
171     public void setManufacturer(final String manufacturer) {
172         refuseFurtherComments();
173         this.manufacturer = manufacturer;
174     }
175 
176     /** Get the bus model name.
177      * @return bus model name
178      */
179     public String getBusModel() {
180         return busModel;
181     }
182 
183     /** Set the bus model name.
184      * @param busModel bus model name
185      */
186     public void setBusModel(final String busModel) {
187         refuseFurtherComments();
188         this.busModel = busModel;
189     }
190 
191     /** Get the other space objects this object is docked to.
192      * @return the oother space objects this object is docked to
193      */
194     public List<String> getDockedWith() {
195         return dockedWith;
196     }
197 
198     /** Set the other space objects this object is docked to.
199      * @param dockedWith the other space objects this object is docked to
200      */
201     public void setDockedWith(final List<String> dockedWith) {
202         refuseFurtherComments();
203         this.dockedWith = dockedWith;
204     }
205 
206     /** Get the attitude-independent drag cross-sectional area, not already into attitude-dependent area along OEB.
207      * @return attitude-independent drag cross-sectional area, not already into attitude-dependent area along OEB
208      */
209     public double getDragConstantArea() {
210         return dragConstantArea;
211     }
212 
213     /** Set the attitude-independent drag cross-sectional area, not already into attitude-dependent area along OEB.
214      * @param dragConstantArea attitude-independent drag cross-sectional area, not already into attitude-dependent area along OEB
215      */
216     public void setDragConstantArea(final double dragConstantArea) {
217         refuseFurtherComments();
218         this.dragConstantArea = dragConstantArea;
219     }
220 
221     /** Get the nominal drag coefficient.
222      * @return the nominal drag coefficient
223      */
224     public double getDragCoefficient() {
225         return dragCoefficient;
226     }
227 
228     /** Set the the nominal drag coefficient.
229      * @param dragCoefficient the nominal drag coefficient
230      */
231     public void setDragCoefficient(final double dragCoefficient) {
232         refuseFurtherComments();
233         this.dragCoefficient = dragCoefficient;
234     }
235 
236     /** Get the drag coefficient 1σ uncertainty.
237      * @return drag coefficient 1σ uncertainty (in %)
238      */
239     public double getDragUncertainty() {
240         return dragUncertainty;
241     }
242 
243     /** Set the drag coefficient 1σ uncertainty.
244      * @param dragUncertainty drag coefficient 1σ uncertainty (in %)
245      */
246     public void setDragUncertainty(final double dragUncertainty) {
247         refuseFurtherComments();
248         this.dragUncertainty = dragUncertainty;
249     }
250 
251     /** Get the total mass at beginning of life.
252      * @return total mass at beginning of life
253      */
254     public double getInitialWetMass() {
255         return initialWetMass;
256     }
257 
258     /** Set the total mass at beginning of life.
259      * @param initialWetMass total mass at beginning of life
260      */
261     public void setInitialWetMass(final double initialWetMass) {
262         refuseFurtherComments();
263         this.initialWetMass = initialWetMass;
264     }
265 
266     /** Get the total mass at T₀.
267      * @return total mass at T₀
268      */
269     public double getWetMass() {
270         return wetMass;
271     }
272 
273     /** Set the total mass at T₀.
274      * @param wetMass total mass at T₀
275      */
276     public void setWetMass(final double wetMass) {
277         refuseFurtherComments();
278         this.wetMass = wetMass;
279     }
280 
281     /** Get the mass without propellant.
282      * @return mass without propellant
283      */
284     public double getDryMass() {
285         return dryMass;
286     }
287 
288     /** Set the mass without propellant.
289      * @param dryMass mass without propellant
290      */
291     public void setDryMass(final double dryMass) {
292         refuseFurtherComments();
293         this.dryMass = dryMass;
294     }
295 
296     /** Get the minimum cross-sectional area for collision probability estimation purposes.
297      * @return minimum cross-sectional area for collision probability estimation purposes
298      */
299     public double getMinAreaForCollisionProbability() {
300         return minAreaForCollisionProbability;
301     }
302 
303     /** Set the minimum cross-sectional area for collision probability estimation purposes.
304      * @param minAreaForCollisionProbability minimum cross-sectional area for collision probability estimation purposes
305      */
306     public void setMinAreaForCollisionProbability(final double minAreaForCollisionProbability) {
307         refuseFurtherComments();
308         this.minAreaForCollisionProbability = minAreaForCollisionProbability;
309     }
310 
311     /** Get the maximum cross-sectional area for collision probability estimation purposes.
312      * @return maximum cross-sectional area for collision probability estimation purposes
313      */
314     public double getMaxAreaForCollisionProbability() {
315         return maxAreaForCollisionProbability;
316     }
317 
318     /** Set the maximum cross-sectional area for collision probability estimation purposes.
319      * @param maxAreaForCollisionProbability maximum cross-sectional area for collision probability estimation purposes
320      */
321     public void setMaxAreaForCollisionProbability(final double maxAreaForCollisionProbability) {
322         refuseFurtherComments();
323         this.maxAreaForCollisionProbability = maxAreaForCollisionProbability;
324     }
325 
326     /** Get the typical (50th percentile) cross-sectional area for collision probability estimation purposes.
327      * @return typical (50th percentile) cross-sectional area for collision probability estimation purposes
328      */
329     public double getTypAreaForCollisionProbability() {
330         return typAreaForCollisionProbability;
331     }
332 
333     /** Get the typical (50th percentile) cross-sectional area for collision probability estimation purposes.
334      * @param typAreaForCollisionProbability typical (50th percentile) cross-sectional area for collision probability estimation purposes
335      */
336     public void setTypAreaForCollisionProbability(final double typAreaForCollisionProbability) {
337         refuseFurtherComments();
338         this.typAreaForCollisionProbability = typAreaForCollisionProbability;
339     }
340 
341     /** Get the attitude-independent SRP area, not already into attitude-dependent area along OEB.
342      * @return attitude-independent SRP area, not already into attitude-dependent area along OEB
343      */
344     public double getSrpConstantArea() {
345         return srpConstantArea;
346     }
347 
348     /** Set the attitude-independent SRP area, not already into attitude-dependent area along OEB.
349      * @param srpConstantArea attitude-independent SRP area, not already into attitude-dependent area along OEB
350      */
351     public void setSrpConstantArea(final double srpConstantArea) {
352         refuseFurtherComments();
353         this.srpConstantArea = srpConstantArea;
354     }
355 
356     /** Get the nominal SRP coefficient.
357      * @return nominal SRP coefficient
358      */
359     public double getSrpCoefficient() {
360         return srpCoefficient;
361     }
362 
363     /** Set the nominal SRP coefficient.
364      * @param srpCoefficient nominal SRP coefficient
365      */
366     public void setSrpCoefficient(final double srpCoefficient) {
367         refuseFurtherComments();
368         this.srpCoefficient = srpCoefficient;
369     }
370 
371     /** Get the SRP coefficient 1σ uncertainty.
372      * @return SRP coefficient 1σ uncertainty
373      */
374     public double getSrpUncertainty() {
375         return srpUncertainty;
376     }
377 
378     /** Set the SRP coefficient 1σ uncertainty.
379      * @param srpUncertainty SRP coefficient 1σ uncertainty.
380      */
381     public void setSrpUncertainty(final double srpUncertainty) {
382         refuseFurtherComments();
383         this.srpUncertainty = srpUncertainty;
384     }
385 
386     /** Get the attitude control mode.
387      * @return attitude control mode
388      */
389     public String getAttitudeControlMode() {
390         return attitudeControlMode;
391     }
392 
393     /** Set the attitude control mode.
394      * @param attitudeControlMode attitude control mode
395      */
396     public void setAttitudeControlMode(final String attitudeControlMode) {
397         refuseFurtherComments();
398         this.attitudeControlMode = attitudeControlMode;
399     }
400 
401     /** Get the type of actuator for attitude control.
402      * @return type of actuator for attitude control
403      */
404     public String getAttitudeActuatorType() {
405         return attitudeActuatorType;
406     }
407 
408     /** Set the type of actuator for attitude control.
409      * @param attitudeActuatorType type of actuator for attitude control
410      */
411     public void setAttitudeActuatorType(final String attitudeActuatorType) {
412         refuseFurtherComments();
413         this.attitudeActuatorType = attitudeActuatorType;
414     }
415 
416     /** Get the accuracy of attitude knowledge.
417      * @return accuracy of attitude knowledge
418      */
419     public double getAttitudeKnowledgeAccuracy() {
420         return attitudeKnowledgeAccuracy;
421     }
422 
423     /** Set the accuracy of attitude knowledge.
424      * @param attitudeKnowledgeAccuracy accuracy of attitude knowledge
425      */
426     public void setAttitudeKnowledgeAccuracy(final double attitudeKnowledgeAccuracy) {
427         refuseFurtherComments();
428         this.attitudeKnowledgeAccuracy = attitudeKnowledgeAccuracy;
429     }
430 
431     /** Get the accuracy of attitude control.
432      * @return accuracy of attitude control
433      */
434     public double getAttitudeControlAccuracy() {
435         return attitudeControlAccuracy;
436     }
437 
438     /** Set the accuracy of attitude control.
439      * @param attitudeControlAccuracy accuracy of attitude control
440      */
441     public void setAttitudeControlAccuracy(final double attitudeControlAccuracy) {
442         refuseFurtherComments();
443         this.attitudeControlAccuracy = attitudeControlAccuracy;
444     }
445 
446     /** Get the overall accuracy of spacecraft to maintain attitude.
447      * @return overall accuracy of spacecraft to maintain attitude
448      */
449     public double getAttitudePointingAccuracy() {
450         return attitudePointingAccuracy;
451     }
452 
453     /** Set the overall accuracy of spacecraft to maintain attitude.
454      * @param attitudePointingAccuracy overall accuracy of spacecraft to maintain attitude
455      */
456     public void setAttitudePointingAccuracy(final double attitudePointingAccuracy) {
457         refuseFurtherComments();
458         this.attitudePointingAccuracy = attitudePointingAccuracy;
459     }
460 
461     /** Get the average number of orbit or attitude maneuvers per year.
462      * @return average number of orbit or attitude maneuvers per year.
463      */
464     public double getManeuversPerYear() {
465         return maneuversFrequency * Constants.JULIAN_YEAR;
466     }
467 
468     /** Get the average frequency of orbit or attitude maneuvers (in SI units, hence per second).
469      * @return average frequency of orbit or attitude maneuvers (in SI units, hence per second).
470      */
471     public double getManeuversFrequency() {
472         return maneuversFrequency;
473     }
474 
475     /** Set the average frequency of orbit or attitude maneuvers (in SI units, hence per second).
476      * @param maneuversFrequency average frequency of orbit or attitude (in SI units, hence per second).
477      */
478     public void setManeuversFrequency(final double maneuversFrequency) {
479         refuseFurtherComments();
480         this.maneuversFrequency = maneuversFrequency;
481     }
482 
483     /** Get the maximum composite thrust the spacecraft can accomplish.
484      * @return maximum composite thrust the spacecraft can accomplish
485      */
486     public double getMaxThrust() {
487         return maxThrust;
488     }
489 
490     /** Set the maximum composite thrust the spacecraft can accomplish.
491      * @param maxThrust maximum composite thrust the spacecraft can accomplish
492      */
493     public void setMaxThrust(final double maxThrust) {
494         refuseFurtherComments();
495         this.maxThrust = maxThrust;
496     }
497 
498     /** Get the total ΔV capability at beginning of life.
499      * @return total ΔV capability at beginning of life
500      */
501     public double getBolDv() {
502         return bolDv;
503     }
504 
505     /** Set the total ΔV capability at beginning of life.
506      * @param bolDv total ΔV capability at beginning of life
507      */
508     public void setBolDv(final double bolDv) {
509         refuseFurtherComments();
510         this.bolDv = bolDv;
511     }
512 
513     /** Get the total ΔV remaining for spacecraft.
514      * @return total ΔV remaining for spacecraft
515      */
516     public double getRemainingDv() {
517         return remainingDv;
518     }
519 
520     /** Set the total ΔV remaining for spacecraft.
521      * @param remainingDv total ΔV remaining for spacecraft
522      */
523     public void setRemainingDv(final double remainingDv) {
524         refuseFurtherComments();
525         this.remainingDv = remainingDv;
526     }
527 
528     /** Get the inertia matrix.
529      * @return the inertia matrix
530      */
531     public RealMatrix getInertiaMatrix() {
532         return inertiaMatrix;
533     }
534 
535     /** Set an entry in the inertia matrix.
536      * <p>
537      * Both I(j, k) and I(k, j) are set.
538      * </p>
539      * @param j row index (must be between 0 and 3 (inclusive)
540      * @param k column index (must be between 0 and 3 (inclusive)
541      * @param entry value of the matrix entry
542      */
543     public void setInertiaMatrixEntry(final int j, final int k, final double entry) {
544         refuseFurtherComments();
545         inertiaMatrix.setEntry(j, k, entry);
546         inertiaMatrix.setEntry(k, j, entry);
547     }
548 
549 }