UpdatableFrame.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.frames;

  18. import java.util.concurrent.atomic.AtomicReference;

  19. import org.hipparchus.RealFieldElement;
  20. import org.orekit.errors.FrameAncestorException;
  21. import org.orekit.errors.OrekitException;
  22. import org.orekit.errors.OrekitMessages;
  23. import org.orekit.time.AbsoluteDate;
  24. import org.orekit.time.FieldAbsoluteDate;


  25. /** Frame whose transform from its parent can be updated.
  26.  * <p>This class allows to control the relative position of two parts
  27.  * of the global frames tree using any two frames in each part as
  28.  * control handles. Consider the following simplified frames tree as an
  29.  * example:</p>
  30.  * <pre>
  31.  *              GCRF
  32.  *                |
  33.  *  --------------------------------
  34.  *  |             |                |
  35.  * Sun        satellite          Earth
  36.  *                |                |
  37.  *        on-board antenna   ground station
  38.  *                                 |
  39.  *                          tracking antenna
  40.  * </pre>
  41.  * <p>Tracking measurements really correspond to the link between the ground
  42.  * and on-board antennas. This is tightly linked to the transform between
  43.  * these two frames, however neither frame is the direct parent frame of the
  44.  * other one: the path involves four intermediate frames. When we process a
  45.  * measurement, what we really want to update is the transform that defines
  46.  * the satellite frame with respect to its parent GCRF frame.</p>
  47.  * <p>In order to implement the above case, the satellite frame is defined
  48.  * as an instance of this class and its {@link #updateTransform(Frame, Frame,
  49.  * Transform, AbsoluteDate) updateTransform} would be called each time we want
  50.  * to adjust the frame, i.e. each time we get a new measurement between the
  51.  * two antennas.</p>
  52.  * @author Luc Maisonobe
  53.  */
  54. public class UpdatableFrame extends Frame {

  55.     /** Serializable UID. */
  56.     private static final long serialVersionUID = -2075893064211339303L;

  57.     /** Build a non-inertial frame from its transform with respect to its parent.
  58.      * <p>calling this constructor is equivalent to call
  59.      * {@link #UpdatableFrame(Frame, Transform, String, boolean)
  60.      * UpdatableFrame(parent, transform, name, false)}.</p>
  61.      * @param parent parent frame (must be non-null)
  62.      * @param transform transform from parent frame to instance
  63.      * @param name name of the frame
  64.      * @exception IllegalArgumentException if the parent frame is null
  65.      */
  66.     public UpdatableFrame(final Frame parent, final Transform transform, final String name)
  67.         throws IllegalArgumentException {
  68.         this(parent, transform, name, false);
  69.     }

  70.     /** Build a frame from its transform with respect to its parent.
  71.      * <p>The convention for the transform is that it is from parent
  72.      * frame to instance. This means that the two following frames
  73.      * are similar:</p>
  74.      * <pre>
  75.      * Frame frame1 = new Frame(FramesFactory.getGCRF(), new Transform(t1, t2));
  76.      * Frame frame2 = new Frame(new Frame(FramesFactory.getGCRF(), t1), t2);
  77.      * </pre>
  78.      * @param parent parent frame (must be non-null)
  79.      * @param transform transform from parent frame to instance
  80.      * @param name name of the frame
  81.      * @param pseudoInertial true if frame is considered pseudo-inertial
  82.      * (i.e. suitable for propagating orbit)
  83.      * @exception IllegalArgumentException if the parent frame is null
  84.      */
  85.     public UpdatableFrame(final Frame parent, final Transform transform, final String name,
  86.                           final boolean pseudoInertial)
  87.         throws IllegalArgumentException {
  88.         super(parent, new UpdatableProvider(transform), name, pseudoInertial);
  89.     }

  90.     /** Update the transform from parent frame implicitly according to two other
  91.      * frames.

  92.      * <p>This method allows to control the relative position of two parts
  93.      * of the global frames tree using any two frames in each part as
  94.      * control handles. Consider the following simplified frames tree as an
  95.      * example:</p>
  96.      * <pre>
  97.      *              GCRF
  98.      *                |
  99.      *  --------------------------------
  100.      *  |             |                |
  101.      * Sun        satellite          Earth
  102.      *                |                |
  103.      *        on-board antenna   ground station
  104.      *                                 |
  105.      *                          tracking antenna
  106.      * </pre>
  107.      * <p>Tracking measurements really correspond to the link between the ground
  108.      * and on-board antennas. This is tightly linked to the transform between
  109.      * these two frames, however neither frame is the direct parent frame of the
  110.      * other one: the path involves four intermediate frames. When we process a
  111.      * measurement, what we really want to update is the transform that defines
  112.      * the satellite frame with respect to its parent GCRF frame. This
  113.      * is the purpose of this method. This update is done by the following call,
  114.      * where <code>measurementTransform</code> represents the measurement as a
  115.      * simple translation transform between the two antenna frames:</p>
  116.      * <pre><code>
  117.      * satellite.updateTransform(onBoardAntenna, trackingAntenna,
  118.      *                           measurementTransform, date);
  119.      * </code></pre>
  120.      * <p>One way to represent the behavior of the method is to consider the
  121.      * sub-tree rooted at the instance on one hand (satellite and on-board antenna
  122.      * in the example above) and the tree containing all the other frames on the
  123.      * other hand (GCRF, Sun, Earth, ground station, tracking antenna).
  124.      * Both tree are considered as two solid sets linked together by a flexible
  125.      * spring, which is the transform we want to update. The method stretches the
  126.      * spring to make sure the transform between the two specified frames (one in
  127.      * each tree part) matches the specified transform.</p>
  128.      * @param f1 first control frame (may be the instance itself)
  129.      * @param f2 second control frame (may be the instance itself)
  130.      * @param f1Tof2 desired transform from first to second control frame
  131.      * @param date date of the transform
  132.      * @exception OrekitException if the path between the two control frames does
  133.      * not cross the link between instance and its parent frame or if some
  134.      * intermediate transform fails
  135.      */
  136.     public void updateTransform(final Frame f1, final Frame f2, final Transform f1Tof2,
  137.                                 final AbsoluteDate date) throws OrekitException {

  138.         Frame fA = f1;
  139.         Frame fB = f2;
  140.         Transform fAtoB = f1Tof2;

  141.         // make sure f1 is not a child of the instance
  142.         if (fA.isChildOf(this) || (fA == this)) {

  143.             if (fB.isChildOf(this) || (fB == this)) {
  144.                 throw new FrameAncestorException(OrekitMessages.FRAME_ANCESTOR_OF_BOTH_FRAMES,
  145.                                                  getName(), fA.getName(), fB.getName());
  146.             }

  147.             // swap f1 and f2 to make sure the child is f2
  148.             final Frame tmp = fA;
  149.             fA = fB;
  150.             fB = tmp;
  151.             fAtoB = fAtoB.getInverse();

  152.         } else  if (!(fB.isChildOf(this) || (fB == this))) {
  153.             throw new FrameAncestorException(OrekitMessages.FRAME_ANCESTOR_OF_NEITHER_FRAME,
  154.                                              getName(), fA.getName(), fB.getName());
  155.         }

  156.         // rebuild the transform by traveling from parent to self
  157.         // WITHOUT using the existing provider from parent to self that will be updated
  158.         final Transform parentTofA   = getParent().getTransformTo(fA, date);
  159.         final Transform fBtoSelf     = fB.getTransformTo(this, date);
  160.         final Transform fAtoSelf     = new Transform(date, fAtoB, fBtoSelf);
  161.         final Transform parentToSelf = new Transform(date, parentTofA, fAtoSelf);

  162.         // update the existing provider from parent to self
  163.         ((UpdatableProvider) getTransformProvider()).setTransform(parentToSelf);

  164.     }

  165.     /** Local provider for transforms. */
  166.     private static class UpdatableProvider implements TransformProvider {

  167.         /** Serializable UID. */
  168.         private static final long serialVersionUID = 4436954500689776331L;

  169.         /** Current transform. */
  170.         private AtomicReference<Transform> transform;

  171.         /** Simple constructor.
  172.          * @param transform initial value of the transform
  173.          */
  174.         UpdatableProvider(final Transform transform) {
  175.             this.transform = new AtomicReference<Transform>(transform);
  176.         }

  177.         /** Update the transform from the parent frame to the instance.
  178.          * @param transform new transform from parent frame to instance
  179.          */
  180.         public void setTransform(final Transform transform) {
  181.             this.transform.set(transform);
  182.         }

  183.         /** {@inheritDoc} */
  184.         public Transform getTransform(final AbsoluteDate date) {
  185.             return transform.get();
  186.         }

  187.         /** {@inheritDoc} */
  188.         @Override
  189.         public <T extends RealFieldElement<T>> FieldTransform<T> getTransform(final FieldAbsoluteDate<T> date) {
  190.             return new FieldTransform<>(date.getField(), transform.get());
  191.         }
  192.     }

  193. }