IodGibbs.java

  1. /* Copyright 2002-2018 CS Systèmes d'Information
  2.  * Licensed to CS Systèmes d'Information (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.estimation.iod;

  18. import org.hipparchus.geometry.euclidean.threed.Vector3D;
  19. import org.hipparchus.util.FastMath;
  20. import org.orekit.estimation.measurements.PV;
  21. import org.orekit.frames.Frame;
  22. import org.orekit.orbits.KeplerianOrbit;
  23. import org.orekit.time.AbsoluteDate;
  24. import org.orekit.utils.PVCoordinates;

  25. /**
  26.  * Gibbs initial orbit determination.
  27.  * An orbit is determined from three position vectors.
  28.  *
  29.  * Reference:
  30.  *  Vallado, D., Fundamentals of Astrodynamics and Applications
  31.  *
  32.  * @author Joris Olympio
  33.  * @since 8.0
  34.  *
  35.  */
  36. public class IodGibbs {

  37.     /** Threshold for checking coplanr vectors. */
  38.     private static final double COPLANAR_THRESHOLD = FastMath.toRadians(5.);

  39.     /** gravitationnal constant. */
  40.     private final double mu;

  41.     /** Creator.
  42.      *
  43.      * @param mu gravitational constant
  44.      */
  45.     public IodGibbs(final double mu) {
  46.         this.mu = mu;
  47.     }

  48.     /** Give an initial orbit estimation, assuming Keplerian motion.
  49.      * All observations should be from the same location.
  50.      *
  51.      * @param frame measure frame
  52.      * @param pv1 PV measure 1 taken in frame
  53.      * @param pv2 PV measure 2 taken in frame
  54.      * @param pv3 PV measure 3 taken in frame
  55.      * @return an initial orbit estimation
  56.      */
  57.     public KeplerianOrbit estimate(final Frame frame, final PV pv1, final PV pv2, final PV pv3) {

  58.         return estimate(frame,
  59.                         pv1.getPosition(), pv1.getDate(),
  60.                         pv2.getPosition(), pv2.getDate(),
  61.                         pv3.getPosition(), pv3.getDate());
  62.     }

  63.     /** Give an initial orbit estimation, assuming Keplerian motion.
  64.      * All observations should be from the same location.
  65.      *
  66.      * @param frame measure frame
  67.      * @param r1 position 1 measured in frame
  68.      * @param date1 date of measure 1
  69.      * @param r2 position 2 measured in frame
  70.      * @param date2 date of measure 2
  71.      * @param r3 position 3 measured in frame
  72.      * @param date3 date of measure 3
  73.      * @return an initial orbit estimation
  74.      */
  75.     public KeplerianOrbit estimate(final Frame frame,
  76.                                    final Vector3D r1, final AbsoluteDate date1,
  77.                                    final Vector3D r2, final AbsoluteDate date2,
  78.                                    final Vector3D r3, final AbsoluteDate date3) {
  79.         // Checks measures are not at the same date
  80.         if (date1.equals(date2) || date1.equals(date3) || date2.equals(date3)) {
  81.             //throw new OrekitException("The measures are not different!");
  82.         }

  83.         // Checks measures are in the same plane
  84.         final double num = r1.normalize().dotProduct(r2.normalize().crossProduct(r3.normalize()));
  85.         final double alpha = FastMath.PI / 2.0 - FastMath.acos(num);
  86.         if (FastMath.abs(alpha) > COPLANAR_THRESHOLD) {
  87.             // throw something
  88.             //throw new OrekitException("Non coplanar points!");
  89.         }

  90.         final Vector3D D = r1.crossProduct(r2).add(r2.crossProduct(r3).add(r3.crossProduct(r1)));

  91.         final Vector3D N = (r2.crossProduct(r3)).scalarMultiply(r1.getNorm())
  92.                 .add((r3.crossProduct(r1)).scalarMultiply(r2.getNorm()))
  93.                 .add((r1.crossProduct(r2)).scalarMultiply(r3.getNorm()));

  94.         final Vector3D B = D.crossProduct(r2);

  95.         final Vector3D S = r1.scalarMultiply(r2.getNorm() - r3.getNorm())
  96.                 .add(r2.scalarMultiply(r3.getNorm() - r1.getNorm())
  97.                      .add(r3.scalarMultiply(r1.getNorm() - r2.getNorm())));

  98.         // middle velocity
  99.         final double vm = FastMath.sqrt(mu / (N.getNorm() * D.getNorm()));
  100.         final Vector3D vlEci = B.scalarMultiply(vm / r2.getNorm()).add(S.scalarMultiply(vm));

  101.         // compile a new middle point with position, velocity
  102.         final PVCoordinates pv = new PVCoordinates(r2, vlEci);
  103.         final AbsoluteDate date = date2;

  104.         // compute the equivalent Keplerian orbit
  105.         return new KeplerianOrbit(pv, frame, date, mu);
  106.     }
  107. }