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