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 package org.orekit.frames.encounter;
18
19 import org.hipparchus.CalculusFieldElement;
20 import org.hipparchus.Field;
21 import org.hipparchus.geometry.euclidean.threed.FieldRotation;
22 import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
23 import org.hipparchus.geometry.euclidean.threed.Rotation;
24 import org.hipparchus.geometry.euclidean.threed.Vector3D;
25 import org.hipparchus.geometry.euclidean.twod.FieldVector2D;
26 import org.hipparchus.geometry.euclidean.twod.Vector2D;
27 import org.hipparchus.linear.Array2DRowFieldMatrix;
28 import org.hipparchus.linear.Array2DRowRealMatrix;
29 import org.hipparchus.linear.FieldMatrix;
30 import org.hipparchus.linear.MatrixUtils;
31 import org.hipparchus.linear.RealMatrix;
32 import org.hipparchus.util.MathArrays;
33 import org.orekit.frames.LOF;
34 import org.orekit.time.AbsoluteDate;
35 import org.orekit.time.FieldAbsoluteDate;
36 import org.orekit.utils.FieldPVCoordinates;
37 import org.orekit.utils.PVCoordinates;
38
39 import java.util.Arrays;
40 import java.util.List;
41 import java.util.stream.Collectors;
42
43 /**
44 * Interface for encounter local orbital frame.
45 * <p>
46 * Encounter local orbital frame are defined using two objects, one of them is placed at the origin and the other is
47 * expressed relatively to the origin.
48 *
49 * @author Vincent Cucchietti
50 * @since 12.0
51 */
52 public interface EncounterLOF extends LOF {
53
54 /**
55 * {@inheritDoc} It is unnecessary to use this method when dealing with {@link EncounterLOF}, use
56 * {@link #rotationFromInertial(Field, FieldPVCoordinates)} instead.
57 */
58 @Override
59 default <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromInertial(Field<T> field,
60 FieldAbsoluteDate<T> date,
61 FieldPVCoordinates<T> pv) {
62 return rotationFromInertial(field, pv);
63 }
64
65 /**
66 * {@inheritDoc} It is unnecessary to use this method when dealing with {@link EncounterLOF}, use
67 * {@link #rotationFromInertial(PVCoordinates)} instead.
68 */
69 @Override
70 default Rotation rotationFromInertial(AbsoluteDate date, PVCoordinates pv) {
71 return rotationFromInertial(pv);
72 }
73
74 /**
75 * Get the rotation from inertial to this encounter local orbital frame.
76 * <p>
77 * <b>BEWARE: The given origin's position and velocity coordinates must be given in the frame in which this instance
78 * has been expressed in.</b>
79 *
80 * @param field field to which the elements belong
81 * @param origin position-velocity of the origin in the same inertial frame as the one this instance has been expressed
82 * in.
83 * @param <T> type of the field elements
84 *
85 * @return rotation from inertial to this encounter local orbital frame
86 */
87 default <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromInertial(final Field<T> field,
88 final FieldPVCoordinates<T> origin) {
89 return rotationFromInertial(field, origin, getFieldOther(field));
90 }
91
92 /**
93 * Get the rotation from inertial to this encounter local orbital frame.
94 * <p>
95 * <b>BEWARE: The given origin's position and velocity coordinates must be given in the frame in which this instance
96 * has been expressed in.</b>
97 *
98 * @param origin position-velocity of the origin in some inertial frame
99 *
100 * @return rotation from inertial to this encounter local orbital frame
101 */
102 default Rotation rotationFromInertial(final PVCoordinates origin) {
103 return rotationFromInertial(origin, getOther());
104 }
105
106 /**
107 * Get the rotation from inertial to this encounter local orbital frame.
108 * <p>
109 * <b>BEWARE: The given origin's position and velocity coordinates must be given in the frame in which this instance
110 * has been expressed in.</b>
111 *
112 * @param field field to which the elements belong
113 * @param origin position-velocity of the origin in the same inertial frame as other
114 * @param other position-velocity of the other in the same inertial frame as origin
115 * @param <T> type of the field elements
116 *
117 * @return rotation from inertial to this encounter local orbital frame
118 */
119 <T extends CalculusFieldElement<T>> FieldRotation<T> rotationFromInertial(Field<T> field,
120 FieldPVCoordinates<T> origin,
121 FieldPVCoordinates<T> other);
122
123 /**
124 * Get the rotation from inertial to this encounter local orbital frame.
125 * <p>
126 * <b>BEWARE: The given origin's position and velocity coordinates must be given in the frame in which this instance
127 * has been expressed in.</b>
128 *
129 * @param origin position-velocity of the origin in the same inertial frame as other
130 * @param other position-velocity of the other instance in the same inertial frame as origin
131 *
132 * @return rotation from inertial to this encounter local orbital frame
133 */
134 Rotation rotationFromInertial(PVCoordinates origin, PVCoordinates other);
135
136 /**
137 * Project given {@link RealMatrix matrix} expressed in this encounter local orbital frame onto the collision plane.
138 *
139 * @param matrix matrix to project, a 3 by 3 matrix is expected
140 *
141 * @return projected matrix onto the collision plane defined by this encounter local orbital frame
142 */
143 default RealMatrix projectOntoCollisionPlane(RealMatrix matrix) {
144 final RealMatrix projectionMatrix = computeProjectionMatrix();
145 return projectionMatrix.multiply(matrix.multiplyTransposed(projectionMatrix));
146 }
147
148 /**
149 * Get the 2x3 projection matrix that projects values expressed in this encounter local orbital frame to the collision
150 * plane.
151 *
152 * @return 2x3 projection matrix
153 */
154 default RealMatrix computeProjectionMatrix() {
155 // Remove axis normal to collision plane from the identity matrix
156 final RealMatrix identity = MatrixUtils.createRealIdentityMatrix(3);
157 final List<double[]> projectionMatrixDataList = Arrays.stream(identity.getData())
158 .filter(values -> !Arrays.equals(values,
159 getAxisNormalToCollisionPlane().toArray()))
160 .collect(Collectors.toList());
161
162 // Map list<double[]> to double[][]
163 final double[][] projectionMatrixData = new double[2][3];
164 for (int i = 0; i < 2; i++) {
165 projectionMatrixData[i] = projectionMatrixDataList.get(i);
166 }
167
168 return new Array2DRowRealMatrix(projectionMatrixData);
169 }
170
171 /**
172 * Project given {@link RealMatrix matrix} expressed in this encounter local orbital frame onto the collision plane
173 * defined by this same encounter local orbital frame.
174 *
175 * @param matrix matrix to project, a 3 by 3 matrix is expected
176 * @param <T> type of the field elements
177 *
178 * @return projected matrix onto the collision plane defined by this encounter local orbital frame
179 */
180 default <T extends CalculusFieldElement<T>> FieldMatrix<T> projectOntoCollisionPlane(FieldMatrix<T> matrix) {
181 final FieldMatrix<T> projectionMatrix = computeProjectionMatrix(matrix.getField());
182 return projectionMatrix.multiply(matrix.multiplyTransposed(projectionMatrix));
183 }
184
185 /**
186 * Get the 2x3 projection matrix that projects values expressed in this encounter local orbital frame to the collision
187 * plane defined by this same encounter local orbital frame.
188 *
189 * @param field field to which the elements belong
190 * @param <T> type of the field elements
191 *
192 * @return 2x3 projection matrix
193 */
194 default <T extends CalculusFieldElement<T>> FieldMatrix<T> computeProjectionMatrix(Field<T> field) {
195 // Remove axis normal to collision plane from the identity matrix
196 final FieldMatrix<T> identity = MatrixUtils.createFieldIdentityMatrix(field, 3);
197 final List<T[]> projectionMatrixDataList = Arrays.stream(identity.getData())
198 .filter(values -> !Arrays.equals(values,
199 getAxisNormalToCollisionPlane(
200 field).toArray()))
201 .collect(Collectors.toList());
202
203 // Map list<C[]> to C[][]
204 final T[][] projectionMatrixData = MathArrays.buildArray(field, 2, 3);
205 for (int i = 0; i < 2; i++) {
206 projectionMatrixData[i] = projectionMatrixDataList.get(i);
207 }
208
209 return new Array2DRowFieldMatrix<>(projectionMatrixData);
210 }
211
212 /**
213 * Get the axis normal to the collision plane (i, j or k) in this encounter local orbital frame.
214 *
215 * @param field field of the elements
216 * @param <T> type of the field elements
217 *
218 * @return axis normal to the collision plane (i, j or k) in this encounter local orbital frame
219 */
220 <T extends CalculusFieldElement<T>> FieldVector3D<T> getAxisNormalToCollisionPlane(Field<T> field);
221
222 /**
223 * Project given {@link Vector3D vector} expressed in this encounter local orbital frame onto the collision plane.
224 *
225 * @param vector vector to project
226 *
227 * @return projected vector onto the collision plane defined by this encounter local orbital frame
228 */
229 default Vector2D projectOntoCollisionPlane(Vector3D vector) {
230 final RealMatrix projectionMatrix = computeProjectionMatrix();
231 final RealMatrix vectorInMatrix = new Array2DRowRealMatrix(vector.toArray());
232
233 return new Vector2D(projectionMatrix.multiply(vectorInMatrix).getColumn(0));
234 }
235
236 /**
237 * Project given {@link Vector3D vector} expressed in this encounter local orbital frame onto the collision plane.
238 *
239 * @param vector vector to project
240 * @param <T> type of the field elements
241 *
242 * @return projected vector onto the collision plane defined by this encounter local orbital frame
243 */
244 default <T extends CalculusFieldElement<T>> FieldVector2D<T> projectOntoCollisionPlane(
245 final FieldVector3D<T> vector) {
246 final FieldMatrix<T> projectionMatrix = computeProjectionMatrix(vector.getX().getField());
247 final FieldMatrix<T> vectorInMatrix = new Array2DRowFieldMatrix<>(vector.toArray());
248
249 return new FieldVector2D<>(projectionMatrix.multiply(vectorInMatrix).getColumn(0));
250 }
251
252 /** Get other's position and velocity coordinates.
253 * @param field field of the element
254 * @param <T> type of the element
255 *
256 * @return other's position and velocity coordinates
257 */
258 <T extends CalculusFieldElement<T>> FieldPVCoordinates<T> getFieldOther(Field<T> field);
259
260 /**
261 * Get the axis normal to the collision plane (i, j or k) in this encounter local orbital frame.
262 *
263 * @return axis normal to the collision plane (i, j or k) in this encounter local orbital frame
264 */
265 Vector3D getAxisNormalToCollisionPlane();
266
267 /** Get other's position and velocity coordinates.
268 * @return other's position and velocity coordinates
269 */
270 PVCoordinates getOther();
271
272 /** Get flag that indicates if current local orbital frame shall be treated as pseudo-inertial.
273 * @return flag that indicates if current local orbital frame shall be treated as pseudo-inertial
274 */
275 @Override
276 default boolean isQuasiInertial() {
277 return true;
278 }
279
280 }