GroundAtNightDetector.java

  1. /* Copyright 2002-2024 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. import org.hipparchus.geometry.euclidean.threed.Vector3D;
  19. import org.hipparchus.util.FastMath;
  20. import org.orekit.frames.Frame;
  21. import org.orekit.frames.TopocentricFrame;
  22. import org.orekit.models.AtmosphericRefractionModel;
  23. import org.orekit.propagation.SpacecraftState;
  24. import org.orekit.propagation.events.handlers.ContinueOnEvent;
  25. import org.orekit.propagation.events.handlers.EventHandler;
  26. import org.orekit.time.AbsoluteDate;
  27. import org.orekit.utils.PVCoordinatesProvider;


  28. /** Detector for ground location being at night.
  29.  * <p>
  30.  * This detector is mainly useful for scheduling optical measurements
  31.  * (either passive telescope observation of satellites against the stars background
  32.  *  or active satellite laser ranging).
  33.  * </p>
  34.  * <p>
  35.  * The {@code g} function of this detector is positive when ground is at night
  36.  * (i.e. Sun is below dawn/dusk elevation angle).
  37.  * </p>
  38.  * @author Luc Maisonobe
  39.  * @since 9.3
  40.  */
  41. public class GroundAtNightDetector extends AbstractDetector<GroundAtNightDetector> {

  42.     /** Sun elevation at civil dawn/dusk (6° below horizon). */
  43.     public static final double CIVIL_DAWN_DUSK_ELEVATION = FastMath.toRadians(-6.0);

  44.     /** Sun elevation at nautical dawn/dusk (12° below horizon). */
  45.     public static final double NAUTICAL_DAWN_DUSK_ELEVATION = FastMath.toRadians(-12.0);

  46.     /** Sun elevation at astronomical dawn/dusk (18° below horizon). */
  47.     public static final double ASTRONOMICAL_DAWN_DUSK_ELEVATION = FastMath.toRadians(-18.0);

  48.     /** Ground location to check. */
  49.     private final TopocentricFrame groundLocation;

  50.     /** Provider for Sun position. */
  51.     private final PVCoordinatesProvider sun;

  52.     /** Sun elevation below which we consider night is dark enough. */
  53.     private final double dawnDuskElevation;

  54.     /** Atmospheric Model used for calculations, if defined. */
  55.     private final AtmosphericRefractionModel refractionModel;

  56.     /** Simple constructor.
  57.      * <p>
  58.      * Beware that {@link org.orekit.models.earth.EarthStandardAtmosphereRefraction Earth
  59.      * standard refraction model} does apply only for elevations above -2°. It is therefore
  60.      * not suitable for used with {@link #CIVIL_DAWN_DUSK_ELEVATION} (-6°), {@link
  61.      * #NAUTICAL_DAWN_DUSK_ELEVATION} (-12°) or {@link #ASTRONOMICAL_DAWN_DUSK_ELEVATION} (-18°).
  62.      * The {@link org.orekit.models.earth.EarthITU453AtmosphereRefraction ITU 453 refraction model}
  63.      * which can compute refraction at large negative elevations should be preferred.
  64.      * </p>
  65.      * @param groundLocation ground location to check
  66.      * @param sun provider for Sun position
  67.      * @param dawnDuskElevation Sun elevation below which we consider night is dark enough (rad)
  68.      * (typically {@link #ASTRONOMICAL_DAWN_DUSK_ELEVATION})
  69.      * @param refractionModel reference to refraction model (null if refraction should be ignored)
  70.      */
  71.     public GroundAtNightDetector(final TopocentricFrame groundLocation, final PVCoordinatesProvider sun,
  72.                                  final double dawnDuskElevation,
  73.                                  final AtmosphericRefractionModel refractionModel) {
  74.         this(groundLocation, sun, dawnDuskElevation, refractionModel,
  75.              AdaptableInterval.of(DEFAULT_MAXCHECK), DEFAULT_THRESHOLD, DEFAULT_MAX_ITER,
  76.              new ContinueOnEvent());
  77.     }

  78.     /** Private constructor.
  79.      * @param groundLocation ground location from which measurement is performed
  80.      * @param sun provider for Sun position
  81.      * @param dawnDuskElevation Sun elevation below which we consider night is dark enough (rad)
  82.      * (typically {@link #ASTRONOMICAL_DAWN_DUSK_ELEVATION})
  83.      * @param refractionModel reference to refraction model (null if refraction should be ignored),
  84.      * @param maxCheck  maximum checking interval
  85.      * @param threshold convergence threshold (s)
  86.      * @param maxIter   maximum number of iterations in the event time search
  87.      * @param handler   event handler to call at event occurrences
  88.      */
  89.     protected GroundAtNightDetector(final TopocentricFrame groundLocation, final PVCoordinatesProvider sun,
  90.                                     final double dawnDuskElevation,
  91.                                     final AtmosphericRefractionModel refractionModel,
  92.                                     final AdaptableInterval maxCheck,
  93.                                     final double threshold,
  94.                                     final int maxIter,
  95.                                     final EventHandler handler) {
  96.         super(maxCheck, threshold, maxIter, handler);
  97.         this.groundLocation    = groundLocation;
  98.         this.sun               = sun;
  99.         this.dawnDuskElevation = dawnDuskElevation;
  100.         this.refractionModel   = refractionModel;
  101.     }

  102.     /** {@inheritDoc} */
  103.     @Override
  104.     protected GroundAtNightDetector create(final AdaptableInterval newMaxCheck,
  105.                                            final double newThreshold,
  106.                                            final int newMaxIter,
  107.                                            final EventHandler newHandler) {
  108.         return new GroundAtNightDetector(groundLocation, sun, dawnDuskElevation, refractionModel,
  109.                                          newMaxCheck, newThreshold, newMaxIter, newHandler);
  110.     }

  111.     /** {@inheritDoc}
  112.      * <p>
  113.      * The {@code g} function of this detector is positive when ground is at night
  114.      * (i.e. Sun is below dawn/dusk elevation angle).
  115.      * </p>
  116.      * <p>
  117.      * This function only depends on date, not on the actual position of the spacecraft.
  118.      * </p>
  119.      */
  120.     @Override
  121.     public double g(final SpacecraftState state) {

  122.         final AbsoluteDate  date     = state.getDate();
  123.         final Frame         frame    = state.getFrame();
  124.         final Vector3D      position = sun.getPosition(date, frame);
  125.         final double trueElevation   = groundLocation.getElevation(position, frame, date);

  126.         final double calculatedElevation;
  127.         if (refractionModel != null) {
  128.             calculatedElevation = trueElevation + refractionModel.getRefraction(trueElevation);
  129.         } else {
  130.             calculatedElevation = trueElevation;
  131.         }

  132.         return dawnDuskElevation - calculatedElevation;

  133.     }

  134. }