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  
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.complex.Quaternion;
24  import org.hipparchus.linear.MatrixUtils;
25  import org.hipparchus.linear.RealMatrix;
26  import org.orekit.files.ccsds.definitions.FrameFacade;
27  import org.orekit.files.ccsds.definitions.OrbitRelativeFrame;
28  import org.orekit.files.ccsds.section.CommentsContainer;
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 PhysicalProperties extends CommentsContainer {
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      /** Optimally Enclosing Box parent reference frame. */
66      private FrameFacade oebParentFrame;
67  
68      /** Optimally Enclosing Box parent reference frame epoch. */
69      private AbsoluteDate oebParentFrameEpoch;
70  
71      /** Quaternion defining Optimally Enclosing Box. */
72      private final double[] oebQ;
73  
74      /** Dimensions of Optimally Enclosing Box along X-OEB (i.e max). */
75      private double oebMax;
76  
77      /** Dimensions of Optimally Enclosing Box along Y-OEB (i.e intermediate). */
78      private double oebIntermediate;
79  
80      /** Dimensions of Optimally Enclosing Box along Z-OEB (i.e min). */
81      private double oebMin;
82  
83      /** Cross-sectional area of Optimally Enclosing Box along X-OEB. */
84      private double oebAreaAlongMax;
85  
86      /** Cross-sectional area of Optimally Enclosing Box along Y-OEB. */
87      private double oebAreaAlongIntermediate;
88  
89      /** Cross-sectional area of Optimally Enclosing Box along Z-OEB. */
90      private double oebAreaAlongMin;
91  
92      /** Minimum cross-sectional area for collision probability estimation purposes. */
93      private double minAreaForCollisionProbability;
94  
95      /** Maximum cross-sectional area for collision probability estimation purposes. */
96      private double maxAreaForCollisionProbability;
97  
98      /** Typical (50th percentile) cross-sectional area for collision probability estimation purposes. */
99      private double typAreaForCollisionProbability;
100 
101     /** Typical (50th percentile) radar cross-section. */
102     private double rcs;
103 
104     /** Minimum radar cross-section. */
105     private double minRcs;
106 
107     /** Maximum radar cross-section. */
108     private double maxRcs;
109 
110     /** Attitude-independent SRP area, not already into attitude-dependent area along OEB. */
111     private double srpConstantArea;
112 
113     /** Nominal SRP coefficient. */
114     private double srpCoefficient;
115 
116     /** SRP coefficient 1σ uncertainty. */
117     private double srpUncertainty;
118 
119     /** Typical (50th percentile) visual magnitude. */
120     private double vmAbsolute;
121 
122     /** Minimum apparent visual magnitude. */
123     private double vmApparentMin;
124 
125     /** Typical (50th percentile) apparent visual magnitude. */
126     private double vmApparent;
127 
128     /** Maximum apparent visual magnitude. */
129     private double vmApparentMax;
130 
131     /** Typical (50th percentile) coefficient of reflectivity. */
132     private double reflectivity;
133 
134     /** Attitude control mode. */
135     private String attitudeControlMode;
136 
137     /** Type of actuator for attitude control. */
138     private String attitudeActuatorType;
139 
140     /** Accuracy of attitude knowledge. */
141     private double attitudeKnowledgeAccuracy;
142 
143     /** Accuracy of attitude control. */
144     private double attitudeControlAccuracy;
145 
146     /** Overall accuracy of spacecraft to maintain attitude. */
147     private double attitudePointingAccuracy;
148 
149     /** Average average frequency of orbit or attitude maneuvers (in SI units, hence per second). */
150     private double maneuversFrequency;
151 
152     /** Maximum composite thrust the spacecraft can accomplish. */
153     private double maxThrust;
154 
155     /** Total ΔV capability at beginning of life. */
156     private double bolDv;
157 
158     /** Total ΔV remaining for spacecraft. */
159     private double remainingDv;
160 
161     /** Inertia matrix. */
162     private RealMatrix inertiaMatrix;
163 
164     /** Simple constructor.
165      * @param epochT0 T0 epoch from file metadata
166      */
167     PhysicalProperties(final AbsoluteDate epochT0) {
168         // we don't call the setXxx() methods in order to avoid
169         // calling refuseFurtherComments as a side effect
170         dockedWith                     = new ArrayList<>();
171         dragConstantArea                  = Double.NaN;
172         dragCoefficient         = Double.NaN;
173         dragUncertainty                = 0.0;
174         initialWetMass                    = Double.NaN;
175         wetMass                           = Double.NaN;
176         dryMass                        = Double.NaN;
177         oebParentFrame                 = new FrameFacade(null, null, OrbitRelativeFrame.RIC, null,
178                                                          OrbitRelativeFrame.RIC.name());
179         oebParentFrameEpoch            = epochT0;
180         oebQ                           = new double[4];
181         oebMax                         = Double.NaN;
182         oebIntermediate                = Double.NaN;
183         oebMin                         = Double.NaN;
184         oebAreaAlongMax                = Double.NaN;
185         oebAreaAlongIntermediate       = Double.NaN;
186         oebAreaAlongMin                = Double.NaN;
187         minAreaForCollisionProbability = Double.NaN;
188         maxAreaForCollisionProbability = Double.NaN;
189         typAreaForCollisionProbability = Double.NaN;
190         rcs                            = Double.NaN;
191         minRcs                         = Double.NaN;
192         maxRcs                         = Double.NaN;
193         srpConstantArea                = Double.NaN;
194         srpCoefficient          = Double.NaN;
195         srpUncertainty                 = Double.NaN;
196         vmAbsolute                     = Double.NaN;
197         vmApparentMin                  = Double.NaN;
198         vmApparent                     = Double.NaN;
199         vmApparentMax                  = Double.NaN;
200         reflectivity                   = Double.NaN;
201         attitudeKnowledgeAccuracy      = Double.NaN;
202         attitudeControlAccuracy        = Double.NaN;
203         attitudePointingAccuracy       = Double.NaN;
204         maneuversFrequency             = Double.NaN;
205         maxThrust                      = Double.NaN;
206         bolDv                          = Double.NaN;
207         remainingDv                    = Double.NaN;
208         inertiaMatrix                  = MatrixUtils.createRealMatrix(3, 3);
209     }
210 
211     /** Get manufacturer name.
212      * @return manufacturer name
213      */
214     public String getManufacturer() {
215         return manufacturer;
216     }
217 
218     /** Set manufacturer name.
219      * @param manufacturer manufacturer name
220      */
221     public void setManufacturer(final String manufacturer) {
222         refuseFurtherComments();
223         this.manufacturer = manufacturer;
224     }
225 
226     /** Get the bus model name.
227      * @return bus model name
228      */
229     public String getBusModel() {
230         return busModel;
231     }
232 
233     /** Set the bus model name.
234      * @param busModel bus model name
235      */
236     public void setBusModel(final String busModel) {
237         refuseFurtherComments();
238         this.busModel = busModel;
239     }
240 
241     /** Get the other space objects this object is docked to.
242      * @return the oother space objects this object is docked to
243      */
244     public List<String> getDockedWith() {
245         return dockedWith;
246     }
247 
248     /** Set the other space objects this object is docked to.
249      * @param dockedWith the other space objects this object is docked to
250      */
251     public void setDockedWith(final List<String> dockedWith) {
252         refuseFurtherComments();
253         this.dockedWith = dockedWith;
254     }
255 
256     /** Get the attitude-independent drag cross-sectional area, not already into attitude-dependent area along OEB.
257      * @return attitude-independent drag cross-sectional area, not already into attitude-dependent area along OEB
258      */
259     public double getDragConstantArea() {
260         return dragConstantArea;
261     }
262 
263     /** Set the attitude-independent drag cross-sectional area, not already into attitude-dependent area along OEB.
264      * @param dragConstantArea attitude-independent drag cross-sectional area, not already into attitude-dependent area along OEB
265      */
266     public void setDragConstantArea(final double dragConstantArea) {
267         refuseFurtherComments();
268         this.dragConstantArea = dragConstantArea;
269     }
270 
271     /** Get the nominal drag coefficient.
272      * @return the nominal drag coefficient
273      */
274     public double getDragCoefficient() {
275         return dragCoefficient;
276     }
277 
278     /** Set the the nominal drag coefficient.
279      * @param dragCoefficient the nominal drag coefficient
280      */
281     public void setDragCoefficient(final double dragCoefficient) {
282         refuseFurtherComments();
283         this.dragCoefficient = dragCoefficient;
284     }
285 
286     /** Get the drag coefficient 1σ uncertainty.
287      * @return drag coefficient 1σ uncertainty (in %)
288      */
289     public double getDragUncertainty() {
290         return dragUncertainty;
291     }
292 
293     /** Set the drag coefficient 1σ uncertainty.
294      * @param dragUncertainty drag coefficient 1σ uncertainty (in %)
295      */
296     public void setDragUncertainty(final double dragUncertainty) {
297         refuseFurtherComments();
298         this.dragUncertainty = dragUncertainty;
299     }
300 
301     /** Get the total mass at beginning of life.
302      * @return total mass at beginning of life
303      */
304     public double getInitialWetMass() {
305         return initialWetMass;
306     }
307 
308     /** Set the total mass at beginning of life.
309      * @param initialWetMass total mass at beginning of life
310      */
311     public void setInitialWetMass(final double initialWetMass) {
312         refuseFurtherComments();
313         this.initialWetMass = initialWetMass;
314     }
315 
316     /** Get the total mass at T₀.
317      * @return total mass at T₀
318      */
319     public double getWetMass() {
320         return wetMass;
321     }
322 
323     /** Set the total mass at T₀.
324      * @param wetMass total mass at T₀
325      */
326     public void setWetMass(final double wetMass) {
327         refuseFurtherComments();
328         this.wetMass = wetMass;
329     }
330 
331     /** Get the mass without propellant.
332      * @return mass without propellant
333      */
334     public double getDryMass() {
335         return dryMass;
336     }
337 
338     /** Set the mass without propellant.
339      * @param dryMass mass without propellant
340      */
341     public void setDryMass(final double dryMass) {
342         refuseFurtherComments();
343         this.dryMass = dryMass;
344     }
345 
346     /** Get the Optimally Enclosing Box parent reference frame.
347      * @return Optimally Enclosing Box parent reference frame
348      */
349     public FrameFacade getOebParentFrame() {
350         return oebParentFrame;
351     }
352 
353     /** Set the Optimally Enclosing Box parent reference frame.
354      * @param oebParentFrame Optimally Enclosing Box parent reference frame
355      */
356     public void setOebParentFrame(final FrameFacade oebParentFrame) {
357         refuseFurtherComments();
358         this.oebParentFrame = oebParentFrame;
359     }
360 
361     /** Get the Optimally Enclosing Box parent reference frame epoch.
362      * @return Optimally Enclosing Box parent reference frame epoch
363      */
364     public AbsoluteDate getOebParentFrameEpoch() {
365         return oebParentFrameEpoch;
366     }
367 
368     /** Set the Optimally Enclosing Box parent reference frame epoch.
369      * @param oebParentFrameEpoch Optimally Enclosing Box parent reference frame epoch
370      */
371     public void setOebParentFrameEpoch(final AbsoluteDate oebParentFrameEpoch) {
372         refuseFurtherComments();
373         this.oebParentFrameEpoch = oebParentFrameEpoch;
374     }
375 
376     /** Get the quaternion defining Optimally Enclosing Box.
377      * @return quaternion defining Optimally Enclosing Box
378      */
379     public Quaternion getOebQ() {
380         return new Quaternion(oebQ[0], oebQ[1], oebQ[2], oebQ[3]);
381     }
382 
383     /** set the component of quaternion defining Optimally Enclosing Box.
384      * @param i index of the component
385      * @param qI component of quaternion defining Optimally Enclosing Box
386      */
387     public void setOebQ(final int i, final double qI) {
388         refuseFurtherComments();
389         oebQ[i] = qI;
390     }
391 
392     /** Get the dimensions of Optimally Enclosing Box along X-OEB (i.e max).
393      * @return dimensions of Optimally Enclosing Box along X-OEB (i.e max)
394      */
395     public double getOebMax() {
396         return oebMax;
397     }
398 
399     /** Set the dimensions of Optimally Enclosing Box along X-OEB (i.e max).
400      * @param oebMax dimensions of Optimally Enclosing Box along X-OEB (i.e max)
401      */
402     public void setOebMax(final double oebMax) {
403         refuseFurtherComments();
404         this.oebMax = oebMax;
405     }
406 
407     /** Get the dimensions of Optimally Enclosing Box along Y-OEB (i.e intermediate).
408      * @return dimensions of Optimally Enclosing Box along Y-OEB (i.e intermediate).
409      */
410     public double getOebIntermediate() {
411         return oebIntermediate;
412     }
413 
414     /** Set the dimensions of Optimally Enclosing Box along Y-OEB (i.e intermediate).
415      * @param oebIntermediate dimensions of Optimally Enclosing Box along Y-OEB (i.e intermediate).
416      */
417     public void setOebIntermediate(final double oebIntermediate) {
418         refuseFurtherComments();
419         this.oebIntermediate = oebIntermediate;
420     }
421 
422     /** Get the dimensions of Optimally Enclosing Box along Z-OEB (i.e min).
423      * @return dimensions of Optimally Enclosing Box along Z-OEB (i.e min)
424      */
425     public double getOebMin() {
426         return oebMin;
427     }
428 
429     /** Set the dimensions of Optimally Enclosing Box along Z-OEB (i.e min).
430      * @param oebMin dimensions of Optimally Enclosing Box along Z-OEB (i.e min)
431      */
432     public void setOebMin(final double oebMin) {
433         refuseFurtherComments();
434         this.oebMin = oebMin;
435     }
436 
437     /** Get the cross-sectional area of Optimally Enclosing Box along X-OEB.
438      * @return cross-sectional area of Optimally Enclosing Box along X-OEB
439      */
440     public double getOebAreaAlongMax() {
441         return oebAreaAlongMax;
442     }
443 
444     /** Set the cross-sectional area of Optimally Enclosing Box along X-OEB.
445      * @param oebAreaAlongMax cross-sectional area of Optimally Enclosing Box along X-OEB
446      */
447     public void setOebAreaAlongMax(final double oebAreaAlongMax) {
448         refuseFurtherComments();
449         this.oebAreaAlongMax = oebAreaAlongMax;
450     }
451 
452     /** Get the cross-sectional area of Optimally Enclosing Box along Y-OEB.
453      * @return cross-sectional area of Optimally Enclosing Box along Y-OEB
454      */
455     public double getOebAreaAlongIntermediate() {
456         return oebAreaAlongIntermediate;
457     }
458 
459     /** Set the cross-sectional area of Optimally Enclosing Box along Y-OEB.
460      * @param oebAreaAlongIntermediate cross-sectional area of Optimally Enclosing Box along X-OEB
461      */
462     public void setOebAreaAlongIntermediate(final double oebAreaAlongIntermediate) {
463         refuseFurtherComments();
464         this.oebAreaAlongIntermediate = oebAreaAlongIntermediate;
465     }
466 
467     /** Get the cross-sectional area of Optimally Enclosing Box along Z-OEB.
468      * @return cross-sectional area of Optimally Enclosing Box along X-OEB
469      */
470     public double getOebAreaAlongMin() {
471         return oebAreaAlongMin;
472     }
473 
474     /** Set the cross-sectional area of Optimally Enclosing Box along Z-OEB.
475      * @param oebAreaAlongMin cross-sectional area of Optimally Enclosing Box along X-OEB
476      */
477     public void setOebAreaAlongMin(final double oebAreaAlongMin) {
478         refuseFurtherComments();
479         this.oebAreaAlongMin = oebAreaAlongMin;
480     }
481 
482     /** Get the minimum cross-sectional area for collision probability estimation purposes.
483      * @return minimum cross-sectional area for collision probability estimation purposes
484      */
485     public double getMinAreaForCollisionProbability() {
486         return minAreaForCollisionProbability;
487     }
488 
489     /** Set the minimum cross-sectional area for collision probability estimation purposes.
490      * @param minAreaForCollisionProbability minimum cross-sectional area for collision probability estimation purposes
491      */
492     public void setMinAreaForCollisionProbability(final double minAreaForCollisionProbability) {
493         refuseFurtherComments();
494         this.minAreaForCollisionProbability = minAreaForCollisionProbability;
495     }
496 
497     /** Get the maximum cross-sectional area for collision probability estimation purposes.
498      * @return maximum cross-sectional area for collision probability estimation purposes
499      */
500     public double getMaxAreaForCollisionProbability() {
501         return maxAreaForCollisionProbability;
502     }
503 
504     /** Set the maximum cross-sectional area for collision probability estimation purposes.
505      * @param maxAreaForCollisionProbability maximum cross-sectional area for collision probability estimation purposes
506      */
507     public void setMaxAreaForCollisionProbability(final double maxAreaForCollisionProbability) {
508         refuseFurtherComments();
509         this.maxAreaForCollisionProbability = maxAreaForCollisionProbability;
510     }
511 
512     /** Get the typical (50th percentile) cross-sectional area for collision probability estimation purposes.
513      * @return typical (50th percentile) cross-sectional area for collision probability estimation purposes
514      */
515     public double getTypAreaForCollisionProbability() {
516         return typAreaForCollisionProbability;
517     }
518 
519     /** Get the typical (50th percentile) cross-sectional area for collision probability estimation purposes.
520      * @param typAreaForCollisionProbability typical (50th percentile) cross-sectional area for collision probability estimation purposes
521      */
522     public void setTypAreaForCollisionProbability(final double typAreaForCollisionProbability) {
523         refuseFurtherComments();
524         this.typAreaForCollisionProbability = typAreaForCollisionProbability;
525     }
526 
527     /** Get the typical (50th percentile) radar cross-section.
528      * @return typical (50th percentile) radar cross-section
529      */
530     public double getRcs() {
531         return rcs;
532     }
533 
534     /** Set the typical (50th percentile) radar cross-section.
535      * @param rcs typical (50th percentile) radar cross-section
536      */
537     public void setRcs(final double rcs) {
538         refuseFurtherComments();
539         this.rcs = rcs;
540     }
541 
542     /** Get the minimum radar cross-section.
543      * @return minimum radar cross-section
544      */
545     public double getMinRcs() {
546         return minRcs;
547     }
548 
549     /** Set the minimum radar cross-section.
550      * @param minRcs minimum radar cross-section
551      */
552     public void setMinRcs(final double minRcs) {
553         refuseFurtherComments();
554         this.minRcs = minRcs;
555     }
556 
557     /** Get the maximum radar cross-section.
558      * @return maximum radar cross-section
559      */
560     public double getMaxRcs() {
561         return maxRcs;
562     }
563 
564     /** Set the maximum radar cross-section.
565      * @param maxRcs maximum radar cross-section
566      */
567     public void setMaxRcs(final double maxRcs) {
568         refuseFurtherComments();
569         this.maxRcs = maxRcs;
570     }
571 
572     /** Get the attitude-independent SRP area, not already into attitude-dependent area along OEB.
573      * @return attitude-independent SRP area, not already into attitude-dependent area along OEB
574      */
575     public double getSrpConstantArea() {
576         return srpConstantArea;
577     }
578 
579     /** Set the attitude-independent SRP area, not already into attitude-dependent area along OEB.
580      * @param srpConstantArea attitude-independent SRP area, not already into attitude-dependent area along OEB
581      */
582     public void setSrpConstantArea(final double srpConstantArea) {
583         refuseFurtherComments();
584         this.srpConstantArea = srpConstantArea;
585     }
586 
587     /** Get the nominal SRP coefficient.
588      * @return nominal SRP coefficient
589      */
590     public double getSrpCoefficient() {
591         return srpCoefficient;
592     }
593 
594     /** Set the nominal SRP coefficient.
595      * @param srpCoefficient nominal SRP coefficient
596      */
597     public void setSrpCoefficient(final double srpCoefficient) {
598         refuseFurtherComments();
599         this.srpCoefficient = srpCoefficient;
600     }
601 
602     /** Get the SRP coefficient 1σ uncertainty.
603      * @return SRP coefficient 1σ uncertainty
604      */
605     public double getSrpUncertainty() {
606         return srpUncertainty;
607     }
608 
609     /** Set the SRP coefficient 1σ uncertainty.
610      * @param srpUncertainty SRP coefficient 1σ uncertainty.
611      */
612     public void setSrpUncertainty(final double srpUncertainty) {
613         refuseFurtherComments();
614         this.srpUncertainty = srpUncertainty;
615     }
616 
617     /** Get the typical (50th percentile) visual magnitude.
618      * @return typical (50th percentile) visual magnitude
619      */
620     public double getVmAbsolute() {
621         return vmAbsolute;
622     }
623 
624     /** Set the typical (50th percentile) visual magnitude.
625      * @param vmAbsolute typical (50th percentile) visual magnitude
626      */
627     public void setVmAbsolute(final double vmAbsolute) {
628         refuseFurtherComments();
629         this.vmAbsolute = vmAbsolute;
630     }
631 
632     /** Get the minimum apparent visual magnitude.
633      * @return minimum apparent visual magnitude
634      */
635     public double getVmApparentMin() {
636         return vmApparentMin;
637     }
638 
639     /** Set the minimum apparent visual magnitude.
640      * @param vmApparentMin minimum apparent visual magnitude
641      */
642     public void setVmApparentMin(final double vmApparentMin) {
643         refuseFurtherComments();
644         this.vmApparentMin = vmApparentMin;
645     }
646 
647     /** Get the typical (50th percentile) apparent visual magnitude.
648      * @return typical (50th percentile) apparent visual magnitude
649      */
650     public double getVmApparent() {
651         return vmApparent;
652     }
653 
654     /** Set the typical (50th percentile) apparent visual magnitude.
655      * @param vmApparent typical (50th percentile) apparent visual magnitude
656      */
657     public void setVmApparent(final double vmApparent) {
658         refuseFurtherComments();
659         this.vmApparent = vmApparent;
660     }
661 
662     /** Get the maximum apparent visual magnitude.
663      * @return maximum apparent visual magnitude
664      */
665     public double getVmApparentMax() {
666         return vmApparentMax;
667     }
668 
669     /** Set the maximum apparent visual magnitude.
670      * @param vmApparentMax maximum apparent visual magnitude
671      */
672     public void setVmApparentMax(final double vmApparentMax) {
673         refuseFurtherComments();
674         this.vmApparentMax = vmApparentMax;
675     }
676 
677     /** Get the typical (50th percentile) coefficient of reflectivity.
678      * @return typical (50th percentile) coefficient of reflectivity
679      */
680     public double getReflectivity() {
681         return reflectivity;
682     }
683 
684     /** Set the typical (50th percentile) coefficient of reflectivity.
685      * @param reflectivity typical (50th percentile) coefficient of reflectivity
686      */
687     public void setReflectivity(final double reflectivity) {
688         refuseFurtherComments();
689         this.reflectivity = reflectivity;
690     }
691 
692     /** Get the attitude control mode.
693      * @return attitude control mode
694      */
695     public String getAttitudeControlMode() {
696         return attitudeControlMode;
697     }
698 
699     /** Set the attitude control mode.
700      * @param attitudeControlMode attitude control mode
701      */
702     public void setAttitudeControlMode(final String attitudeControlMode) {
703         refuseFurtherComments();
704         this.attitudeControlMode = attitudeControlMode;
705     }
706 
707     /** Get the type of actuator for attitude control.
708      * @return type of actuator for attitude control
709      */
710     public String getAttitudeActuatorType() {
711         return attitudeActuatorType;
712     }
713 
714     /** Set the type of actuator for attitude control.
715      * @param attitudeActuatorType type of actuator for attitude control
716      */
717     public void setAttitudeActuatorType(final String attitudeActuatorType) {
718         refuseFurtherComments();
719         this.attitudeActuatorType = attitudeActuatorType;
720     }
721 
722     /** Get the accuracy of attitude knowledge.
723      * @return accuracy of attitude knowledge
724      */
725     public double getAttitudeKnowledgeAccuracy() {
726         return attitudeKnowledgeAccuracy;
727     }
728 
729     /** Set the accuracy of attitude knowledge.
730      * @param attitudeKnowledgeAccuracy accuracy of attitude knowledge
731      */
732     public void setAttitudeKnowledgeAccuracy(final double attitudeKnowledgeAccuracy) {
733         refuseFurtherComments();
734         this.attitudeKnowledgeAccuracy = attitudeKnowledgeAccuracy;
735     }
736 
737     /** Get the accuracy of attitude control.
738      * @return accuracy of attitude control
739      */
740     public double getAttitudeControlAccuracy() {
741         return attitudeControlAccuracy;
742     }
743 
744     /** Set the accuracy of attitude control.
745      * @param attitudeControlAccuracy accuracy of attitude control
746      */
747     public void setAttitudeControlAccuracy(final double attitudeControlAccuracy) {
748         refuseFurtherComments();
749         this.attitudeControlAccuracy = attitudeControlAccuracy;
750     }
751 
752     /** Get the overall accuracy of spacecraft to maintain attitude.
753      * @return overall accuracy of spacecraft to maintain attitude
754      */
755     public double getAttitudePointingAccuracy() {
756         return attitudePointingAccuracy;
757     }
758 
759     /** Set the overall accuracy of spacecraft to maintain attitude.
760      * @param attitudePointingAccuracy overall accuracy of spacecraft to maintain attitude
761      */
762     public void setAttitudePointingAccuracy(final double attitudePointingAccuracy) {
763         refuseFurtherComments();
764         this.attitudePointingAccuracy = attitudePointingAccuracy;
765     }
766 
767     /** Get the average number of orbit or attitude maneuvers per year.
768      * @return average number of orbit or attitude maneuvers per year.
769      */
770     public double getManeuversPerYear() {
771         return maneuversFrequency * Constants.JULIAN_YEAR;
772     }
773 
774     /** Get the average frequency of orbit or attitude maneuvers (in SI units, hence per second).
775      * @return average frequency of orbit or attitude maneuvers (in SI units, hence per second).
776      */
777     public double getManeuversFrequency() {
778         return maneuversFrequency;
779     }
780 
781     /** Set the average frequency of orbit or attitude maneuvers (in SI units, hence per second).
782      * @param maneuversFrequency average frequency of orbit or attitude (in SI units, hence per second).
783      */
784     public void setManeuversFrequency(final double maneuversFrequency) {
785         refuseFurtherComments();
786         this.maneuversFrequency = maneuversFrequency;
787     }
788 
789     /** Get the maximum composite thrust the spacecraft can accomplish.
790      * @return maximum composite thrust the spacecraft can accomplish
791      */
792     public double getMaxThrust() {
793         return maxThrust;
794     }
795 
796     /** Set the maximum composite thrust the spacecraft can accomplish.
797      * @param maxThrust maximum composite thrust the spacecraft can accomplish
798      */
799     public void setMaxThrust(final double maxThrust) {
800         refuseFurtherComments();
801         this.maxThrust = maxThrust;
802     }
803 
804     /** Get the total ΔV capability at beginning of life.
805      * @return total ΔV capability at beginning of life
806      */
807     public double getBolDv() {
808         return bolDv;
809     }
810 
811     /** Set the total ΔV capability at beginning of life.
812      * @param bolDv total ΔV capability at beginning of life
813      */
814     public void setBolDv(final double bolDv) {
815         refuseFurtherComments();
816         this.bolDv = bolDv;
817     }
818 
819     /** Get the total ΔV remaining for spacecraft.
820      * @return total ΔV remaining for spacecraft
821      */
822     public double getRemainingDv() {
823         return remainingDv;
824     }
825 
826     /** Set the total ΔV remaining for spacecraft.
827      * @param remainingDv total ΔV remaining for spacecraft
828      */
829     public void setRemainingDv(final double remainingDv) {
830         refuseFurtherComments();
831         this.remainingDv = remainingDv;
832     }
833 
834     /** Get the inertia matrix.
835      * @return the inertia matrix
836      */
837     public RealMatrix getInertiaMatrix() {
838         return inertiaMatrix;
839     }
840 
841     /** Set an entry in the inertia matrix.
842      * <p>
843      * Both I(j, k) and I(k, j) are set.
844      * </p>
845      * @param j row index (must be between 0 and 3 (inclusive)
846      * @param k column index (must be between 0 and 3 (inclusive)
847      * @param entry value of the matrix entry
848      */
849     public void setInertiaMatrixEntry(final int j, final int k, final double entry) {
850         refuseFurtherComments();
851         inertiaMatrix.setEntry(j, k, entry);
852         inertiaMatrix.setEntry(k, j, entry);
853     }
854 
855 }