1 /* Copyright 2020-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.propagation.events;
18
19 import org.hipparchus.geometry.euclidean.threed.Vector3D;
20 import org.hipparchus.ode.events.Action;
21 import org.orekit.bodies.CelestialBodies;
22 import org.orekit.propagation.SpacecraftState;
23 import org.orekit.propagation.events.handlers.EventHandler;
24 import org.orekit.propagation.events.handlers.StopOnDecreasing;
25 import org.orekit.utils.PVCoordinatesProvider;
26
27 /** Detects when two moving objects come close to each other, as seen from spacecraft.
28 * <p>The main use case for this detector is when the primary object is in fact a ground
29 * station, modeled as a {@link org.orekit.frames.TopocentricFrame} and when the secondary
30 * is the {@link CelestialBodies#getSun() Sun}, for computing
31 * optical reflections.</p>
32 * <p>The default handler behavior is to {@link Action#STOP stop}
33 * propagation when objects enter the proximity zone. This can be changed by calling
34 * {@link #withHandler(EventHandler)} after construction.</p>
35 * @see org.orekit.propagation.Propagator#addEventDetector(EventDetector)
36 * @author Luc Maisonobe
37 * @author Thomas Paulet
38 * @since 11.0
39 */
40 public class AngularSeparationFromSatelliteDetector extends AbstractDetector<AngularSeparationFromSatelliteDetector> {
41
42 /** Primary object, at the center of the proximity zone. */
43 private final PVCoordinatesProvider primaryObject;
44
45 /** Secondary object, that may come close to the primary, as seen from the spacecraft . */
46 private final PVCoordinatesProvider secondaryObject;
47
48 /** Proximity angle (rad). */
49 private final double proximityAngle;
50
51 /** Build a new angular detachment detector.
52 * @param primaryObject primaryObject, at the center of the proximity zone
53 * @param secondaryObject secondaryObject, that may come close to
54 * the primaryObject as seen from the spacecraft
55 * @param proximityAngle proximity angle as seen from spacecraft, at which events are triggered (rad)
56 */
57 public AngularSeparationFromSatelliteDetector(final PVCoordinatesProvider primaryObject,
58 final PVCoordinatesProvider secondaryObject,
59 final double proximityAngle) {
60 this(EventDetectionSettings.getDefaultEventDetectionSettings(), new StopOnDecreasing(),
61 primaryObject, secondaryObject, proximityAngle);
62 }
63
64 /** Protected constructor with full parameters.
65 * <p>
66 * This constructor is not public as users are expected to use the builder
67 * API with the various {@code withXxx()} methods to set up the instance
68 * in a readable manner without using a huge amount of parameters.
69 * </p>
70 * @param detectionSettings detection Settings
71 * @param handler event handler to call at event occurrences
72 * @param primaryObject primaryObject at the center of the proximity zone
73 * @param secondaryObject secondaryObject, that may come close to
74 * the primaryObject as seen from the spacecraft
75 * @param proximityAngle proximity angle as seen from secondaryObject, at which events are triggered (rad)
76 * @since 13.0
77 */
78 protected AngularSeparationFromSatelliteDetector(final EventDetectionSettings detectionSettings,
79 final EventHandler handler,
80 final PVCoordinatesProvider primaryObject,
81 final PVCoordinatesProvider secondaryObject,
82 final double proximityAngle) {
83 super(detectionSettings, handler);
84 this.primaryObject = primaryObject;
85 this.secondaryObject = secondaryObject;
86 this.proximityAngle = proximityAngle;
87 }
88
89 /** {@inheritDoc} */
90 @Override
91 protected AngularSeparationFromSatelliteDetector create(final EventDetectionSettings detectionSettings,
92 final EventHandler newHandler) {
93 return new AngularSeparationFromSatelliteDetector(detectionSettings, newHandler,
94 primaryObject, secondaryObject, proximityAngle);
95 }
96
97 /** Get the primaryObject, at the center of the proximity zone.
98 * @return primaryObject
99 */
100 public PVCoordinatesProvider getPrimaryObject() {
101 return primaryObject;
102 }
103
104 /** Get the secondaryObject.
105 * @return secondaryObject
106 */
107 public PVCoordinatesProvider getSecondaryObject() {
108 return secondaryObject;
109 }
110
111 /** Get the proximity angle (rad).
112 * @return the proximity angle
113 */
114 public double getProximityAngle() {
115 return proximityAngle;
116 }
117
118 /** Compute the value of the switching function.
119 * <p>
120 * This function measures the angular separation between primary and secondary objects
121 * as seen from the spacecraft minus the proximity angle. It therefore triggers
122 * decreasing events when the secondary object enters the proximity zone and increasing
123 * events when it leaves the proximity zone.
124 * </p>
125 * <p>
126 * No shadowing effect is taken into account, so this method is computed and
127 * may trigger events even when the secondary object is behind the primary.
128 * If such effects must be taken into account the
129 * detector must be associated with a {@link EventEnablingPredicateFilter predicate
130 * filter} where the {@link EnablingPredicate predicate function} is based on eclipse conditions.
131 * </p>
132 * @param s the current state information: date, kinematics, attitude
133 * @return value of the switching function
134 */
135 public double g(final SpacecraftState s) {
136 final Vector3D sPosition = s.getPosition();
137 final Vector3D primaryPos = primaryObject .getPosition(s.getDate(), s.getFrame());
138 final Vector3D secondaryPos = secondaryObject.getPosition(s.getDate(), s.getFrame());
139 final double separation = Vector3D.angle(primaryPos.subtract(sPosition),
140 secondaryPos.subtract(sPosition));
141 return separation - proximityAngle;
142 }
143
144 }