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