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;
19
20 import java.util.Arrays;
21
22 import org.hipparchus.geometry.euclidean.threed.Vector3D;
23 import org.orekit.errors.OrekitException;
24 import org.orekit.errors.OrekitMessages;
25 import org.orekit.files.ccsds.section.CommentsContainer;
26 import org.orekit.time.AbsoluteDate;
27 import org.orekit.utils.TimeStampedPVCoordinates;
28
29 /** Container for state vector data.
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 11.0
46 */
47 public class StateVector extends CommentsContainer {
48
49 /** Epoch of state vector and optional Keplerian elements. */
50 private AbsoluteDate epoch;
51
52 /** Position vector (m). */
53 private final double[] position;
54
55 /** Velocity vector (m/s). */
56 private final double[] velocity;
57
58 /** Acceleration vector (m/s²). */
59 private final double[] acceleration;
60
61 /** Create an empty data set.
62 */
63 public StateVector() {
64 position = new double[3];
65 velocity = new double[3];
66 acceleration = new double[3];
67 Arrays.fill(position, Double.NaN);
68 Arrays.fill(velocity, Double.NaN);
69 Arrays.fill(acceleration, Double.NaN);
70 }
71
72 /** {@inheritDoc} */
73 @Override
74 public void validate(final double version) {
75 super.validate(version);
76 checkNotNull(epoch, StateVectorKey.EPOCH.name());
77 if (Double.isNaN(position[0] + position[1] + position[2])) {
78 throw new OrekitException(OrekitMessages.UNINITIALIZED_VALUE_FOR_KEY, "{X|Y|Z}");
79 }
80 if (Double.isNaN(velocity[0] + velocity[1] + velocity[2])) {
81 throw new OrekitException(OrekitMessages.UNINITIALIZED_VALUE_FOR_KEY, "{X|Y|Z}_DOT");
82 }
83 }
84
85 /** Get epoch of state vector, Keplerian elements and covariance matrix data.
86 * @return epoch the epoch
87 */
88 public AbsoluteDate getEpoch() {
89 return epoch;
90 }
91
92 /** Set epoch of state vector, Keplerian elements and covariance matrix data.
93 * @param epoch the epoch to be set
94 */
95 public void setEpoch(final AbsoluteDate epoch) {
96 refuseFurtherComments();
97 this.epoch = epoch;
98 }
99
100 /**
101 * Set position component.
102 * @param index component index (counting from 0)
103 * @param value position component
104 */
105 public void setP(final int index, final double value) {
106 refuseFurtherComments();
107 position[index] = value;
108 }
109
110 /**
111 * Set velocity component.
112 * @param index component index (counting from 0)
113 * @param value velocity component
114 */
115 public void setV(final int index, final double value) {
116 refuseFurtherComments();
117 velocity[index] = value;
118 }
119
120 /**
121 * Set acceleration component.
122 * @param index component index (counting from 0)
123 * @param value acceleration component
124 */
125 public void setA(final int index, final double value) {
126 refuseFurtherComments();
127 acceleration[index] = value;
128 }
129
130 /** Check if state contains acceleration data.
131 * @return true is state contains acceleration data
132 */
133 public boolean hasAcceleration() {
134 return !Double.isNaN(acceleration[0] + acceleration[1] + acceleration[2]);
135 }
136
137 /** Convert to {@link TimeStampedPVCoordinates}.
138 * @return a new {@link TimeStampedPVCoordinates}
139 */
140 public TimeStampedPVCoordinates toTimeStampedPVCoordinates() {
141 return new TimeStampedPVCoordinates(epoch,
142 new Vector3D(position),
143 new Vector3D(velocity),
144 hasAcceleration() ? new Vector3D(acceleration) : Vector3D.ZERO);
145 }
146
147 }
148