InterSatDirectViewDetector.java

  1. /* Copyright 2002-2020 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.bodies.OneAxisEllipsoid;
  21. import org.orekit.frames.Frame;
  22. import org.orekit.propagation.PropagatorsParallelizer;
  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 inter-satellites direct view (i.e. no masking by central body limb).
  29.  * <p>
  30.  * As this detector needs two satellites, it embeds one {@link
  31.  * PVCoordinatesProvider coordinates provider} for the slave satellite
  32.  * and is registered as an event detector in the propagator of the master
  33.  * satellite. The slave satellite provider will therefore be driven by this
  34.  * detector (and hence by the propagator in which this detector is registered).
  35.  * </p>
  36.  * <p>
  37.  * In order to avoid infinite recursion, care must be taken to have the slave
  38.  * satellite provider being <em>completely independent</em> from anything else.
  39.  * In particular, if the provider is a propagator, it should <em>not</em> be run
  40.  * together in a {@link PropagatorsParallelizer propagators parallelizer} with
  41.  * the propagator this detector is registered in. It is fine however to configure
  42.  * two separate propagators PsA and PsB with similar settings for the slave satellite
  43.  * and one propagator Pm for the master satellite and then use Psa in this detector
  44.  * registered within Pm while Pm and Psb are run in the context of a {@link
  45.  * PropagatorsParallelizer propagators parallelizer}.
  46.  * </p>
  47.  * <p>
  48.  * For efficiency reason during the event search loop, it is recommended to have
  49.  * the slave provider be an analytical propagator or an ephemeris. A numerical propagator
  50.  * as a slave propagator works but is expected to be computationally costly.
  51.  * </p>
  52.  * <p>
  53.  * The {@code g} function of this detector is positive when satellites can see
  54.  * each other directly and negative when the central body limb is in between and
  55.  * blocks the direct view.
  56.  * </p>
  57.  * <p>
  58.  * This detector only checks masking by central body limb, it does not take into
  59.  * account satellites antenna patterns. If these patterns must be considered, then
  60.  * this detector can be {@link BooleanDetector#andCombine(EventDetector...) and combined}
  61.  * with  the {@link BooleanDetector#notCombine(EventDetector) logical not} of
  62.  * {@link FieldOfViewDetector field of view detectors}.
  63.  * </p>
  64.  * @author Luc Maisonobe
  65.  * @since 9.3
  66.  */
  67. public class InterSatDirectViewDetector extends AbstractDetector<InterSatDirectViewDetector> {

  68.     /** Central body. */
  69.     private final OneAxisEllipsoid body;

  70.     /** Equatorial radius squared. */
  71.     private final double ae2;

  72.     /** 1 minus flatness squared. */
  73.     private final double g2;

  74.     /** Coordinates provider for the slave satellite. */
  75.     private final PVCoordinatesProvider slave;

  76.     /** simple constructor.
  77.      *
  78.      * @param body central body
  79.      * @param slave provider for the slave satellite
  80.      */
  81.     public InterSatDirectViewDetector(final OneAxisEllipsoid body, final PVCoordinatesProvider slave) {
  82.         this(body, slave, DEFAULT_MAXCHECK, DEFAULT_THRESHOLD, DEFAULT_MAX_ITER,
  83.              new ContinueOnEvent<>());
  84.     }

  85.     /** Private constructor.
  86.      * @param body central body
  87.      * @param slave provider for the slave satellite
  88.      * @param maxCheck  maximum checking interval (s)
  89.      * @param threshold convergence threshold (s)
  90.      * @param maxIter   maximum number of iterations in the event time search
  91.      * @param handler   event handler to call at event occurrences
  92.      */
  93.     private InterSatDirectViewDetector(final OneAxisEllipsoid body,
  94.                                        final PVCoordinatesProvider slave,
  95.                                        final double maxCheck,
  96.                                        final double threshold,
  97.                                        final int maxIter,
  98.                                        final EventHandler<? super InterSatDirectViewDetector> handler) {
  99.         super(maxCheck, threshold, maxIter, handler);
  100.         this.body  = body;
  101.         this.ae2   = body.getEquatorialRadius() * body.getEquatorialRadius();
  102.         this.g2    = (1.0 - body.getFlattening()) * (1.0 - body.getFlattening());
  103.         this.slave = slave;
  104.     }

  105.     /** Get the central body.
  106.      * @return central body
  107.      */
  108.     public OneAxisEllipsoid getCentralBody() {
  109.         return body;
  110.     }

  111.     /** Get the provider for the slave satellite.
  112.      * @return provider for the slave satellite
  113.      */
  114.     public PVCoordinatesProvider getSlave() {
  115.         return slave;
  116.     }

  117.     /** {@inheritDoc} */
  118.     @Override
  119.     protected InterSatDirectViewDetector create(final double newMaxCheck,
  120.                                                 final double newThreshold,
  121.                                                 final int newMaxIter,
  122.                                                 final EventHandler<? super InterSatDirectViewDetector> newHandler) {
  123.         return new InterSatDirectViewDetector(body, slave, newMaxCheck, newThreshold, newMaxIter, newHandler);
  124.     }

  125.     /** {@inheritDoc}
  126.      * <p>
  127.      * The {@code g} function of this detector is positive when satellites can see
  128.      * each other directly and negative when the central body limb is in between and
  129.      * blocks the direct view.
  130.      * </p>
  131.      */
  132.     @Override
  133.     public double g(final SpacecraftState state) {

  134.         // get the line between master and slave in body frame
  135.         final AbsoluteDate date    = state.getDate();
  136.         final Frame        frame   = body.getBodyFrame();
  137.         final Vector3D     pMaster = state.getPVCoordinates(frame).getPosition();
  138.         final Vector3D     pSlave  = slave.getPVCoordinates(date, frame).getPosition();

  139.         // points along the master/slave lines are defined as
  140.         // xk = x + k * dx, yk = y + k * dy, zk = z + k * dz
  141.         // so k is 0 at master and 1 at slave
  142.         final double x  = pMaster.getX();
  143.         final double y  = pMaster.getY();
  144.         final double z  = pMaster.getZ();
  145.         final double dx = pSlave.getX() - x;
  146.         final double dy = pSlave.getY() - y;
  147.         final double dz = pSlave.getZ() - z;

  148.         // intersection between line and central body surface
  149.         // is a root of a 2nd degree polynomial :
  150.         // a k^2 - 2 b k + c = 0
  151.         final double a =   g2 * (dx * dx + dy * dy) + dz * dz;
  152.         final double b = -(g2 * (x * dx + y * dy) + z * dz);
  153.         final double c =   g2 * (x * x + y * y - ae2) + z * z;
  154.         final double s = b * b - a * c;
  155.         if (s < 0) {
  156.             // the quadratic has no solution, the line between master and slave
  157.             // doesn't crosses central body limb, direct view is possible
  158.             // return a positive value, preserving continuity across zero crossing
  159.             return -s;
  160.         }

  161.         // the quadratic has two solutions (degenerated to one if s = 0)
  162.         // direct view is blocked when one of these solutions is between 0 and 1
  163.         final double k1 = (b < 0) ? (b - FastMath.sqrt(s)) / a : c / (b + FastMath.sqrt(s));
  164.         final double k2 = c / (a * k1);
  165.         if (FastMath.max(k1, k2) < 0.0 || FastMath.min(k1, k2) > 1.0) {
  166.             // the intersections are either behind master or farther away than slave
  167.             // along the line, direct view is possible
  168.             // return a positive value, preserving continuity across zero crossing
  169.             return s;
  170.         } else {
  171.             // part of the central body is between master and slave
  172.             // this includes unrealistic cases where master, slave or both are inside the central body ;-)
  173.             // in all these cases, direct view is blocked
  174.             // return a negative value, preserving continuity across zero crossing
  175.             return -s;
  176.         }

  177.     }

  178. }