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