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.models.earth.ionosphere;
18  
19  import org.hipparchus.CalculusFieldElement;
20  import org.hipparchus.geometry.euclidean.threed.FieldVector3D;
21  import org.hipparchus.geometry.euclidean.threed.Vector3D;
22  import org.orekit.bodies.OneAxisEllipsoid;
23  
24  /**
25   * Abstract ionospheric model parent class.
26   * <p>
27   * Defines an abstract IonosphericModel parent class to hold
28   * the earth model, which is used in calculating path delay.
29   * </p>
30   *
31   * @author Brianna Aubin
32   * @since 14.0
33   */
34  public abstract class AbstractIonosphericModel implements IonosphericModel {
35  
36      /** Stores earth data. */
37      private final OneAxisEllipsoid earth;
38  
39      /** Simple constructor.
40       * @param earth elliptic earth body
41       * @since 14.0
42       */
43      protected AbstractIonosphericModel(final OneAxisEllipsoid earth) {
44          this.earth = earth;
45      }
46  
47      /** Get the earth body shape for earth-frame calculations.
48       * @return earth body shape
49       * @since 14.0
50       */
51      public final OneAxisEllipsoid getEarth() {
52          return earth;
53      }
54  
55      /**
56       * Checks to see if it is valid to calculate the ionospheric path delay
57       * for a position endpoint value w.r.t. the minimum altitude point
58       * between two given objects (whether they are space or ground based).
59       * @param position     position of object value being considered (one of the two endpoints)
60       * @param p1           position of first endpoint in the link
61       * @param p2           position of second endpoint in the link
62       * @param baseAltitude altitude of the groundpoint that represents the minimum
63       *                     altitude value on the path between p1 and p2
64       * @return True if the path delay needs to be calculated
65       */
66      protected final Boolean checkIfPathIsValid(final Vector3D position, final Vector3D p1, final Vector3D p2, final Double baseAltitude) {
67          final Double elevation = position.getDelta();
68          return endpointCheck(elevation, position) ^ midpointCheck(elevation, p1, p2, baseAltitude);
69      }
70  
71      /**
72       * Checks to see if it is valid to calculate the ionospheric path delay
73       * for a position endpoint value w.r.t. the minimum altitude point
74       * between two given objects (whether they are space or ground based).
75       * @param <T>          type of the elements
76       * @param position     position of object value being considered (one of the two endpoints)
77       * @param p1           position of first endpoint in the link
78       * @param p2           position of second endpoint in the link
79       * @param baseAltitude altitude of the groundpoint that represents the minimum
80       *                     altitude value on the path between p1 and p2
81       * @return True if the path delay needs to be calculated
82       */
83      protected final <T extends CalculusFieldElement<T>> Boolean checkIfPathIsValid(final FieldVector3D<T> position, final FieldVector3D<T> p1, final FieldVector3D<T> p2, final Double baseAltitude) {
84          return checkIfPathIsValid(position.toVector3D(), p1.toVector3D(), p2.toVector3D(), baseAltitude);
85      }
86  
87      /**
88       * These conditions are true for either a ground-space link, or a space-space link where
89       * the minimum altitude point of the link is co-located with one of the spacecraft.
90       * @param elevation    elevation of object value being considered w.r.t. the
91       *                     minimum altitude point between the two link end points
92       * @param position     position of object value being considered (one of the two endpoints)
93       * @return boolean indiciating whther the path delay needs to be calculated
94       */
95      private Boolean endpointCheck(final Double elevation, final Vector3D position) {
96  
97          // Check that elevation of position value in topocentric frame is > 0 deg
98          // This is true for a ground-space link, or a space-space link where one satellite has a lower
99          // altitude than the other
100         final Boolean elevationCheck = elevation > 1e-7;
101 
102         // Check that distance to topocentric frame is > 1 m
103         final Boolean distanceCheck = position.getNorm() > 1.0;
104 
105         return elevationCheck && distanceCheck;
106     }
107 
108     /**
109      * This is true for a space-space link where the minimum altitude point is not
110      * co-located with either spacecraft.
111      * @param elevation    elevation of object value being considered w.r.t. the
112      *                     minimum altitude point between the two link end points
113      * @param p1           position of first endpoint in the link
114      * @param p2           position of second endpoint in the link
115      * @param baseAltitude altitude of the groundpoint that represents the minimum
116      *                     altitude value on the path between p1 and p2
117      * @return boolean indiciating whther the path delay needs to be calculated
118      */
119     private Boolean midpointCheck(final Double elevation, final Vector3D p1, final Vector3D p2, final Double baseAltitude) {
120 
121         // Check that elevation of position value in topocentric frame is == 0 deg
122         final Boolean elevationCheck = Math.abs(elevation) < 1e-5;
123 
124         // Check that both endpoints have zero-altitude w.r.t. the topocentric frame
125         final Boolean distanceCheck = Math.abs(p1.getZ()) < 1e-5 && Math.abs(p2.getZ()) < 1e-5;
126 
127         // Checks that the minimum altitude point is NOT inside the earth
128         final Boolean altitudeCheck = baseAltitude > -1e-6;
129 
130         return elevationCheck && distanceCheck && altitudeCheck;
131     }
132 
133 }