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;
19
20 import java.util.Arrays;
21
22 import org.hipparchus.geometry.euclidean.threed.Vector3D;
23 import org.orekit.annotation.Nullable;
24 import org.orekit.errors.OrekitException;
25 import org.orekit.errors.OrekitMessages;
26 import org.orekit.files.ccsds.section.CommentsContainer;
27 import org.orekit.time.AbsoluteDate;
28 import org.orekit.utils.TimeStampedPVCoordinates;
29
30 /** Container for state vector data.
31 * <p>
32 * Beware that the Orekit getters and setters all rely on SI units. The parsers
33 * and writers take care of converting these SI units into CCSDS mandatory units.
34 * The {@link org.orekit.utils.units.Unit Unit} class provides useful
35 * {@link org.orekit.utils.units.Unit#fromSI(double) fromSi} and
36 * {@link org.orekit.utils.units.Unit#toSI(double) toSI} methods in case the callers
37 * already use CCSDS units instead of the API SI units. The general-purpose
38 * {@link org.orekit.utils.units.Unit Unit} class (without an 's') and the
39 * CCSDS-specific {@link org.orekit.files.ccsds.definitions.Units Units} class
40 * (with an 's') also provide some predefined units. These predefined units and the
41 * {@link org.orekit.utils.units.Unit#fromSI(double) fromSi} and
42 * {@link org.orekit.utils.units.Unit#toSI(double) toSI} conversion methods are indeed
43 * what the parsers and writers use for the conversions.
44 * </p>
45 * @author Luc Maisonobe
46 * @since 11.0
47 */
48 public class StateVector extends CommentsContainer {
49
50 /** Epoch of state vector and optional Keplerian elements. */
51 private AbsoluteDate epoch;
52
53 /** Position vector (m). */
54 private final double[] position;
55
56 /** Velocity vector (m/s). */
57 private final double[] velocity;
58
59 /** Acceleration vector (m/s²). */
60 @Nullable
61 private double[] acceleration;
62
63 /** Create an empty data set.
64 */
65 public StateVector() {
66 position = new double[3];
67 velocity = new double[3];
68 Arrays.fill(position, Double.NaN);
69 Arrays.fill(velocity, 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 if (acceleration == null) {
128 acceleration = new double[3];
129 Arrays.fill(acceleration, Double.NaN);
130 }
131 acceleration[index] = value;
132 }
133
134 /** Check if state contains acceleration data.
135 * @return true is state contains acceleration data
136 */
137 public boolean hasAcceleration() {
138 return acceleration != null;
139 }
140
141 /** Convert to {@link TimeStampedPVCoordinates}.
142 * @return a new {@link TimeStampedPVCoordinates}
143 */
144 public TimeStampedPVCoordinates toTimeStampedPVCoordinates() {
145 return new TimeStampedPVCoordinates(epoch,
146 new Vector3D(position),
147 new Vector3D(velocity),
148 hasAcceleration() ? new Vector3D(acceleration) : Vector3D.ZERO);
149 }
150
151 }
152