UpdatableFrame.java

  1. /* Copyright 2002-2013 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.orekit.errors.FrameAncestorException;
  20. import org.orekit.errors.OrekitException;
  21. import org.orekit.errors.OrekitMessages;
  22. import org.orekit.time.AbsoluteDate;


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

  53.     /** Serializable UID. */
  54.     private static final long serialVersionUID = -2075893064211339303L;

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

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

  88.     /** Update the transform from parent frame implicitly according to two other
  89.      * frames.

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

  136.         Frame fA = f1;
  137.         Frame fB = f2;
  138.         Transform fAtoB = f1Tof2;

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

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

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

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

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

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

  162.     }

  163.     /** Local provider for transforms. */
  164.     private static class UpdatableProvider implements TransformProvider {

  165.         /** Serializable UID. */
  166.         private static final long serialVersionUID = 4436954500689776331L;

  167.         /** Current transform. */
  168.         private AtomicReference<Transform> transform;

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

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

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

  185.     }

  186. }