1   /* Copyright 2022-2026 Luc Maisonobe
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.adm.acm;
19  
20  import java.util.Optional;
21  
22  import org.hipparchus.geometry.euclidean.threed.Vector3D;
23  import org.hipparchus.linear.MatrixUtils;
24  import org.hipparchus.linear.RealMatrix;
25  import org.orekit.annotation.Nullable;
26  import org.orekit.files.ccsds.definitions.FrameFacade;
27  import org.orekit.files.ccsds.section.CommentsContainer;
28  
29  /** Spacecraft physical properties.
30   * <p>
31   * Beware that the Orekit getters and setters all rely on SI units. The parsers
32   * and writers take care of converting these SI units into CCSDS mandatory units.
33   * The {@link org.orekit.utils.units.Unit Unit} class provides useful
34   * {@link org.orekit.utils.units.Unit#fromSI(double) fromSi} and
35   * {@link org.orekit.utils.units.Unit#toSI(double) toSI} methods in case the callers
36   * already use CCSDS units instead of the API SI units. The general-purpose
37   * {@link org.orekit.utils.units.Unit Unit} class (without an 's') and the
38   * CCSDS-specific {@link org.orekit.files.ccsds.definitions.Units Units} class
39   * (with an 's') also provide some predefined units. These predefined units and the
40   * {@link org.orekit.utils.units.Unit#fromSI(double) fromSi} and
41   * {@link org.orekit.utils.units.Unit#toSI(double) toSI} conversion methods are indeed
42   * what the parsers and writers use for the conversions.
43   * </p>
44   * @author Luc Maisonobe
45   * @since 12.0
46   */
47  public class AttitudePhysicalProperties extends CommentsContainer {
48  
49      /** Drag coefficient. */
50      @Nullable
51      private Double dragCoefficient;
52  
53      /** Total mass at T₀. */
54      @Nullable
55      private Double wetMass;
56  
57      /** Mass without propellant. */
58      @Nullable
59      private Double dryMass;
60  
61      /** Reference frame for center of pressure. */
62      @Nullable
63      private FrameFacade centerOfPressureReferenceFrame;
64  
65      /** Location of center of pressure. */
66      @Nullable
67      private Vector3D centerOfPressure;
68  
69      /** Reference frame for inertia. */
70      @Nullable
71      private FrameFacade inertiaReferenceFrame;
72  
73      /** Inertia matrix. */
74      @Nullable
75      private RealMatrix inertiaMatrix;
76  
77      /**
78       * Simple constructor.
79       */
80      public AttitudePhysicalProperties() {
81      }
82  
83      /** {@inheritDoc} */
84      @Override
85      public void validate(final double version) {
86          super.validate(version);
87          if (centerOfPressureReferenceFrame != null) {
88              checkNotNull(centerOfPressure, AttitudePhysicalPropertiesKey.CP.name());
89          }
90      }
91  
92      /** Get the drag coefficient.
93       * @return the drag coefficient
94       */
95      public Optional<Double> getDragCoefficient() {
96          return Optional.ofNullable(dragCoefficient);
97      }
98  
99      /** Set the the drag coefficient.
100      * @param dragCoefficient the drag coefficient
101      */
102     public void setDragCoefficient(final double dragCoefficient) {
103         refuseFurtherComments();
104         this.dragCoefficient = dragCoefficient;
105     }
106 
107     /** Get the total mass at T₀.
108      * @return total mass at T₀
109      */
110     public Optional<Double> getWetMass() {
111         return Optional.ofNullable(wetMass);
112     }
113 
114     /** Set the total mass at T₀.
115      * @param wetMass total mass at T₀
116      */
117     public void setWetMass(final double wetMass) {
118         refuseFurtherComments();
119         this.wetMass = wetMass;
120     }
121 
122     /** Get the mass without propellant.
123      * @return mass without propellant
124      */
125     public Optional<Double> getDryMass() {
126         return Optional.ofNullable(dryMass);
127     }
128 
129     /** Set the mass without propellant.
130      * @param dryMass mass without propellant
131      */
132     public void setDryMass(final double dryMass) {
133         refuseFurtherComments();
134         this.dryMass = dryMass;
135     }
136 
137     /** Get reference frame for center of pressure.
138      * @return reference frame for center of pressure
139      */
140     public Optional<FrameFacade> getCenterOfPressureReferenceFrame() {
141         return Optional.ofNullable(centerOfPressureReferenceFrame);
142     }
143 
144     /** Set reference frame for center of pressure.
145      * @param centerOfPressureReferenceFrame reference frame for center of pressure
146      */
147     public void setCenterOfPressureReferenceFrame(final FrameFacade centerOfPressureReferenceFrame) {
148         this.centerOfPressureReferenceFrame = centerOfPressureReferenceFrame;
149     }
150 
151     /** Get the location of center of pressure.
152      * @return location of center of pressure
153      */
154     public Optional<Vector3D> getCenterOfPressure() {
155         return Optional.ofNullable(centerOfPressure);
156     }
157 
158     /** Set the location of center of pressure.
159      * @param centerOfPressure location of center of pressure
160      */
161     public void setCenterOfPressure(final Vector3D centerOfPressure) {
162         this.centerOfPressure = centerOfPressure;
163     }
164 
165     /** Get reference frame for inertia.
166      * @return reference frame for inertia
167      */
168     public Optional<FrameFacade> getInertiaReferenceFrame() {
169         return Optional.ofNullable(inertiaReferenceFrame);
170     }
171 
172     /** Set reference frame for inertia.
173      * @param inertiaReferenceFrame reference frame for inertia
174      */
175     public void setInertiaReferenceFrame(final FrameFacade inertiaReferenceFrame) {
176         this.inertiaReferenceFrame = inertiaReferenceFrame;
177     }
178 
179     /** Get the inertia matrix.
180      * @return the inertia matrix
181      */
182     public Optional<RealMatrix> getInertiaMatrix() {
183         return Optional.ofNullable(inertiaMatrix);
184     }
185 
186     /** Set an entry in the inertia matrix.
187      * <p>
188      * Both I(j, k) and I(k, j) are set.
189      * </p>
190      * @param j row index (must be between 0 and 3 (inclusive)
191      * @param k column index (must be between 0 and 3 (inclusive)
192      * @param entry value of the matrix entry
193      */
194     public void setInertiaMatrixEntry(final int j, final int k, final double entry) {
195         refuseFurtherComments();
196         if (inertiaMatrix == null) {
197             inertiaMatrix = MatrixUtils.createRealMatrix(3, 3);
198         }
199         inertiaMatrix.setEntry(j, k, entry);
200         inertiaMatrix.setEntry(k, j, entry);
201     }
202 
203 }