Beispiel #1
0
/* $Procedure      LTIME ( Light Time ) */
/* Subroutine */ int ltime_(doublereal *etobs, integer *obs, char *dir, 
	integer *targ, doublereal *ettarg, doublereal *elapsd, ftnlen dir_len)
{
    /* Builtin functions */
    integer s_cmp(char *, char *, ftnlen, ftnlen);

    /* Local variables */
    doublereal sobs[6], myet, c__;
    integer r__;
    extern /* Subroutine */ int chkin_(char *, ftnlen), errch_(char *, char *,
	     ftnlen, ftnlen);
    doublereal starg[6];
    extern doublereal vdist_(doublereal *, doublereal *);
    extern integer rtrim_(char *, ftnlen);
    extern logical failed_(void);
    doublereal lt;
    extern doublereal clight_(void);
    integer bcentr;
    extern /* Subroutine */ int spkgeo_(integer *, doublereal *, char *, 
	    integer *, doublereal *, doublereal *, ftnlen), sigerr_(char *, 
	    ftnlen), chkout_(char *, ftnlen), setmsg_(char *, ftnlen);
    extern logical return_(void);

/* $ Abstract */

/*     This routine computes the transmit (or receive) time */
/*     of a signal at a specified target, given the receive */
/*     (or transmit) time at a specified observer. The elapsed */
/*     time between transmit and receive is also returned. */

/* $ Disclaimer */

/*     THIS SOFTWARE AND ANY RELATED MATERIALS WERE CREATED BY THE */
/*     CALIFORNIA INSTITUTE OF TECHNOLOGY (CALTECH) UNDER A U.S. */
/*     GOVERNMENT CONTRACT WITH THE NATIONAL AERONAUTICS AND SPACE */
/*     ADMINISTRATION (NASA). THE SOFTWARE IS TECHNOLOGY AND SOFTWARE */
/*     PUBLICLY AVAILABLE UNDER U.S. EXPORT LAWS AND IS PROVIDED "AS-IS" */
/*     TO THE RECIPIENT WITHOUT WARRANTY OF ANY KIND, INCLUDING ANY */
/*     WARRANTIES OF PERFORMANCE OR MERCHANTABILITY OR FITNESS FOR A */
/*     PARTICULAR USE OR PURPOSE (AS SET FORTH IN UNITED STATES UCC */
/*     SECTIONS 2312-2313) OR FOR ANY PURPOSE WHATSOEVER, FOR THE */
/*     SOFTWARE AND RELATED MATERIALS, HOWEVER USED. */

/*     IN NO EVENT SHALL CALTECH, ITS JET PROPULSION LABORATORY, OR NASA */
/*     BE LIABLE FOR ANY DAMAGES AND/OR COSTS, INCLUDING, BUT NOT */
/*     LIMITED TO, INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, */
/*     INCLUDING ECONOMIC DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS, */
/*     REGARDLESS OF WHETHER CALTECH, JPL, OR NASA BE ADVISED, HAVE */
/*     REASON TO KNOW, OR, IN FACT, SHALL KNOW OF THE POSSIBILITY. */

/*     RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF */
/*     THE SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY */
/*     CALTECH AND NASA FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE */
/*     ACTIONS OF RECIPIENT IN THE USE OF THE SOFTWARE. */

/* $ Required_Reading */

/*      None. */

/* $ Keywords */

/*       SPK */

/* $ Declarations */
/* $ Brief_I/O */

/*      VARIABLE  I/O  DESCRIPTION */
/*      --------  ---  -------------------------------------------------- */
/*      ETOBS      I   Epoch of a signal at some observer */
/*      OBS        I   NAIF-id of some observer */
/*      DIR        I   Direction the signal travels ( '->' or '<-' ) */
/*      TARG       I   NAIF-id of the target object */
/*      ETTARG     O   Epoch of the signal at the target */
/*      ELAPSD     O   Time between transmit and receipt of the signal */

/* $ Detailed_Input */

/*     ETOBS       is an epoch expressed in ephemeris second (TDB) */
/*                 past the epoch of the J2000 reference system. */
/*                 This is the time at which an electromagnetic */
/*                 signal is "at" the observer. */

/*     OBS         is the NAIF-id of some observer. */

/*     DIR         is the direction the signal travels.  The */
/*                 acceptable values are '->' and '<-'.  When */
/*                 you read the calling sequence from left to */
/*                 right, the "arrow" given by DIR indicates */
/*                 which way the electromagnetic signal is travelling. */

/*                 If the argument list reads as below, */

/*                  ..., OBS, '->', TARG, ... */

/*                 the signal is travelling from the observer to the */
/*                 target. */

/*                 If the argument reads as */

/*                  ..., OBS, '<-', TARG */

/*                 the signal is travelling from the target to */
/*                 the observer. */

/*     TARG        is the NAIF-id of the target. */

/* $ Detailed_Output */

/*     ETTARG      is the epoch expressed in ephemeris seconds (TDB) */
/*                 past the epoch of the J2000 reference system */
/*                 at which the electromagnetic signal is "at" the */
/*                 target body. */

/*                 Note ETTARG is computed using only Newtonian */
/*                 assumptions about the propagation of light. */

/*     ELAPSD      is the number of ephemeris seconds (TDB) between */
/*                 transmission and receipt of the signal. */

/*                 ELAPSD = DABS( ETOBS - ETTARG ) */

/* $ Parameters */

/*      None. */

/* $ Files */

/*      None. */

/* $ Exceptions */

/*     1) If DIR is not one of '->' or '<-' the error */
/*       'SPICE(BADDIRECTION)' will be signalled. In this case */
/*        ETTARG and ELAPSD will not be altered from their */
/*        input values. */

/*     2) If insufficient ephemeris information is available to */
/*        compute the outputs ETTARG and ELAPSD, or if observer */
/*        or target is not recognized, the problems is diagnosed */
/*        by a routine in the call tree of this routine. */

/*        In this case, the value of ETTARG will be set to ETOBS */
/*        and ELAPSD will be set to zero. */

/* $ Particulars */


/*     Suppose a radio signal travels between two solar system */
/*     objects. Given an ephemeris for the two objects, which way */
/*     the signal is travelling, and the time when the signal is */
/*     "at" at one of the objects (the observer OBS), this routine */
/*     determines when the signal is "at" the other object (the */
/*     target TARG).   It also returns the elapsed time between */
/*     transmission and receipt of the signal. */


/* $ Examples */

/*     Example 1. */
/*     ---------- */
/*     Suppose a signal is transmitted at time ET from the Goldstone */
/*     tracking site (id-code 399001) to a spacecraft whose id-code */
/*     is -77. */


/*           signal travelling to spacecraft */
/*       *  -._.-._.-._.-._.-._.-._.-._.-._.->  * */

/*       Goldstone (OBS=399001)            Spacecraft (TARG = -77) */
/*       at epoch ETOBS(given)             at epoch ETTARG(unknown) */

/*     Assuming that all of the required SPICE kernels have been */
/*     loaded, the code fragment below shows how to compute the */
/*     time (ARRIVE) at which the signal arrives at the spacecraft */
/*     and how long (HOWLNG) it took the signal to reach the spacecraft. */
/*     (Note that we display the arrival time as the number of seconds */
/*     past J2000.) */

/*        OBS   = 399001 */
/*        TARG  = -77 */
/*        ETOBS = ET */

/*        CALL LTIME ( ETOBS, OBS, '->', TARG, ARRIVE, HOWLNG ) */
/*        CALL ETCAL */

/*        WRITE (*,*) 'The signal arrived at time: ', ARRIVE */
/*        WRITE (*,*) 'It took ', HOWLNG, ' seconds to get there.' */


/*     Example 2. */
/*     ---------- */
/*     Suppose a signal is received at the Goldstone tracking sight */
/*     at epoch ET from the spacecraft of the previous example. */

/*               signal sent from spacecraft */
/*         *  <-._.-._.-._.-._.-._.-._.-._.-._.- * */

/*       Goldstone (OBS=399001)               Spacecraft (TARG = -77) */
/*       at epoch ETOBS(given)                at epoch ETTARG(unknown) */

/*     Again assuming that all the required kernels have been loaded */
/*     the code fragment below computes the epoch at which the */
/*     signal was transmitted from the spacecraft. */

/*        OBS   = 399001 */
/*        TARG  = -77 */
/*        ETOBS = ET */

/*        CALL LTIME ( ETOBS, OBS, '<-', TARG, SENT, HOWLNG ) */
/*        CALL ETCAL */

/*        WRITE (*,*) 'The signal was transmitted at: ', SENT */
/*        WRITE (*,*) 'It took ', HOWLNG, ' seconds to get here.' */

/*     EXAMPLE 3 */
/*     --------- */
/*     Suppose there is a transponder on board the spacecraft of */
/*     the previous examples that transmits a signal back to the */
/*     sender exactly 1 microsecond after a signal arrives at */
/*     the spacecraft.  If we send a signal from Goldstone */
/*     to the spacecraft and wait to receive it at Canberra. */
/*     What will be the epoch at which the return signal arrives */
/*     in Canberra? ( The id-code for Canberra is 399002 ). */

/*     Again, assuming we've loaded all the necessary kernels, */
/*     the fragment below will give us the answer. */

/*        GSTONE = 399001 */
/*        SC     = -77 */
/*        CANBER = 399002 */
/*        ETGOLD = ET */

/*        CALL LTIME ( ETGOLD, GSTONE, '->', SC, SCGET, LT1 ) */

/*     Account for the microsecond delay between receipt and transmit */

/*        SCSEND = SCGET + 0.000001 */

/*        CALL LTIME ( SCSEND, SC, '->', CANBER, ETCANB, LT2 ) */

/*        RNDTRP = ETCANB - ETGOLD */

/*        WRITE (*,*) 'The  signal arrives in Canberra at: ', ETCANB */
/*        WRITE (*,*) 'Round trip time for the signal was: ', RNDTRP */

/* $ Restrictions */

/*     None. */

/* $ Author_and_Institution */

/*      W.L. Taber      (JPL) */

/* $ Literature_References */

/*      None. */

/* $ Version */

/* -    SPICELIB Version 1.1.2, 22-SEP-2004 (EDW) */

/*        Placed Copyright after Abstract. */

/* -    SPICELIB Version 1.1.1, 18-NOV-1996 (WLT) */

/*        Errors in the examples section were corrected. */

/* -    SPICELIB Version 1.1.0, 10-JUL-1996 (WLT) */

/*        Added Copyright Notice to the header. */

/* -    SPICELIB Version 1.0.0, 10-NOV-1995 (WLT) */


/* -& */
/* $ Index_Entries */

/*     Compute uplink and downlink light time */

/* -& */

/*     SPICELIB Functions */


/*     Local Variables */

    if (return_()) {
	return 0;
    }
    chkin_("LTIME", (ftnlen)5);

/*     First perform the obvious error check. */

    if (s_cmp(dir, "->", (ftnlen)2, (ftnlen)2) != 0 && s_cmp(dir, "<-", (
	    ftnlen)2, (ftnlen)2) != 0) {
	setmsg_("The direction specifier for the signal was '#'  it must be "
		"either '->' or '<-'. ", (ftnlen)80);
	r__ = rtrim_(dir, (ftnlen)2);
	errch_("#", dir, (ftnlen)1, r__);
	sigerr_("SPICE(BADDIRECTION)", (ftnlen)19);
	chkout_("LTIME", (ftnlen)5);
	return 0;
    }

/*     We need two constants, the speed of light and the id-code */
/*     for the solar system barycenter. */

    c__ = clight_();
    bcentr = 0;
    myet = *etobs;

/*     First get the barycenter relative states of the observer */
/*     and target. */

    spkgeo_(obs, &myet, "J2000", &bcentr, sobs, &lt, (ftnlen)5);
    spkgeo_(targ, &myet, "J2000", &bcentr, starg, &lt, (ftnlen)5);
    *elapsd = vdist_(sobs, starg) / c__;

/*     The rest is straight forward.  We either add the elapsed */
/*     time to get the next state or subtract the elapsed time. */
/*     This depends on whether we are receiving or transmitting */
/*     at the observer. */

/*     Note that 3 iterations as performed here gives us */
/*     Newtonian accuracy to the nanosecond level for all */
/*     known objects in the solar system.  The ephemeris */
/*     is certain to be much worse than this. */

    if (s_cmp(dir, "->", (ftnlen)2, (ftnlen)2) == 0) {
	*ettarg = myet + *elapsd;
	spkgeo_(targ, ettarg, "J2000", &bcentr, starg, &lt, (ftnlen)5);
	*elapsd = vdist_(sobs, starg) / c__;
	*ettarg = myet + *elapsd;
	spkgeo_(targ, ettarg, "J2000", &bcentr, starg, &lt, (ftnlen)5);
	*elapsd = vdist_(sobs, starg) / c__;
	*ettarg = myet + *elapsd;
	spkgeo_(targ, ettarg, "J2000", &bcentr, starg, &lt, (ftnlen)5);
	*elapsd = vdist_(sobs, starg) / c__;
	*ettarg = myet + *elapsd;
    } else {
	*ettarg = myet - *elapsd;
	spkgeo_(targ, ettarg, "J2000", &bcentr, starg, &lt, (ftnlen)5);
	*elapsd = vdist_(sobs, starg) / c__;
	*ettarg = myet - *elapsd;
	spkgeo_(targ, ettarg, "J2000", &bcentr, starg, &lt, (ftnlen)5);
	*elapsd = vdist_(sobs, starg) / c__;
	*ettarg = myet - *elapsd;
	spkgeo_(targ, ettarg, "J2000", &bcentr, starg, &lt, (ftnlen)5);
	*elapsd = vdist_(sobs, starg) / c__;
	*ettarg = myet - *elapsd;
    }
    if (failed_()) {
	*ettarg = myet;
	*elapsd = 0.;
    }
    chkout_("LTIME", (ftnlen)5);
    return 0;
} /* ltime_ */
Beispiel #2
0
/* $Procedure  VREL ( Vector relative difference, 3 dimensions ) */
doublereal vrel_(doublereal *v1, doublereal *v2)
{
    /* System generated locals */
    doublereal ret_val, d__1, d__2;

    /* Local variables */
    extern doublereal vdist_(doublereal *, doublereal *), vnorm_(doublereal *)
	    ;
    doublereal denorm, nunorm;

/* $ Abstract */

/*   Return the relative difference between two 3-dimensional vectors. */

/* $ Disclaimer */

/*     THIS SOFTWARE AND ANY RELATED MATERIALS WERE CREATED BY THE */
/*     CALIFORNIA INSTITUTE OF TECHNOLOGY (CALTECH) UNDER A U.S. */
/*     GOVERNMENT CONTRACT WITH THE NATIONAL AERONAUTICS AND SPACE */
/*     ADMINISTRATION (NASA). THE SOFTWARE IS TECHNOLOGY AND SOFTWARE */
/*     PUBLICLY AVAILABLE UNDER U.S. EXPORT LAWS AND IS PROVIDED "AS-IS" */
/*     TO THE RECIPIENT WITHOUT WARRANTY OF ANY KIND, INCLUDING ANY */
/*     WARRANTIES OF PERFORMANCE OR MERCHANTABILITY OR FITNESS FOR A */
/*     PARTICULAR USE OR PURPOSE (AS SET FORTH IN UNITED STATES UCC */
/*     SECTIONS 2312-2313) OR FOR ANY PURPOSE WHATSOEVER, FOR THE */
/*     SOFTWARE AND RELATED MATERIALS, HOWEVER USED. */

/*     IN NO EVENT SHALL CALTECH, ITS JET PROPULSION LABORATORY, OR NASA */
/*     BE LIABLE FOR ANY DAMAGES AND/OR COSTS, INCLUDING, BUT NOT */
/*     LIMITED TO, INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, */
/*     INCLUDING ECONOMIC DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS, */
/*     REGARDLESS OF WHETHER CALTECH, JPL, OR NASA BE ADVISED, HAVE */
/*     REASON TO KNOW, OR, IN FACT, SHALL KNOW OF THE POSSIBILITY. */

/*     RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF */
/*     THE SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY */
/*     CALTECH AND NASA FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE */
/*     ACTIONS OF RECIPIENT IN THE USE OF THE SOFTWARE. */

/* $ Required_Reading */

/*   None. */

/* $ Keywords */

/*     MATH */
/*     VECTOR */

/* $ Declarations */
/* $ Brief_I/O */

/*     Variable  I/O  Description */
/*     --------  ---  -------------------------------------------------- */
/*      V1,V2     I   Input vectors. */

/* $ Detailed_Input */

/*      V1, V2        are two 3-dimensional vectors for which the */
/*                    relative difference is to be computed. */

/* $ Detailed_Output */

/*      VREL          is the relative difference between V1 and V2. */
/*                    It is defined as: */
/*                                             || V1 - V2 || */
/*                              VREL   =   ---------------------- */
/*                                         MAX ( ||V1||, ||V2|| ) */

/*                    where || X || indicates the Euclidean norm of */
/*                    the vector X. */

/*                    VREL assumes values in the range [0,2]. If both */
/*                    V1 and V2 are zero vectors then VREL is defined */
/*                    to be zero. */


/* $ Parameters */

/*     None. */

/* $ Exceptions */

/*     Error free. */

/*     If both V1 and V2 are zero vectors then VREL is defined */
/*     to be zero. */

/* $ Files */

/*     None. */

/* $ Particulars */

/*     This function computes the relative difference between two */
/*     3-dimensional vectors as defined above. */

/*     The function VRELG may be used to find the relative difference */
/*     for two vectors of general dimension. */

/* $ Examples */

/*     This example code fragment computes the relative difference */
/*     between the geometric and light time corrected state of Io */
/*     with respect to Voyager 2 at a given UTC time. */

/*     C */
/*     C     The NAIF integer code for Io is 501 and the code for */
/*     C     Voyager 2 is -32. */
/*     C */

/*           INTEGER               IO */
/*           PARAMETER           ( IO  = 501 ) */

/*           INTEGER               VG2 */
/*           PARAMETER           ( VG2 = -32 ) */

/*     C */
/*     C     Spicelib function */
/*     C */
/*           DOUBLE PRECISION      VREL */
/*     C */
/*     C     Local variables */
/*     C */
/*           DOUBLE PRECISION      STATE ( 6 ) */
/*           DOUBLE PRECISION      POS1  ( 3 ) */
/*           DOUBLE PRECISION      POS2  ( 3 ) */
/*           DOUBLE PRECISION      DIFF */
/*           DOUBLE PRECISION      LT */
/*           DOUBLE PRECISION      ET */

/*           INTEGER               HANDLE */

/*           CHARACTER*(20)        UTC */

/*           DATA                  UTC / '1979 JUN 25 12:00:00' / */

/*     C */
/*     C     Load the sample SPK ephemeris file. */
/*     C */
/*           CALL SPKLEF ( 'VG2_JUP.BSP', HANDLE ) */
/*     C */
/*     C     Convert the UTC time string to ephemeris time. */
/*     C */
/*           CALL UTC2ET ( UTC, ET ) */
/*     C */
/*     C     First calculate the geometric state and then the light */
/*     C     time corrected state. */
/*     C */
/*           CALL SPKEZ ( IO, ET, 'J2000', 'NONE', VG2, STATE, LT ) */

/*           CALL VEQU  ( STATE, POS1 ) */

/*           CALL SPKEZ ( IO, ET, 'J2000', 'LT', VG2, STATE, LT ) */

/*           CALL VEQU  ( STATE, POS2 ) */
/*     C */
/*     C     Call VREL to find the relative difference between the */
/*     C     two states. */
/*     C */
/*           DIFF = VREL ( POS1, POS2 ) */

/*           . */
/*           . */
/*           . */

/* $ Restrictions */

/*     None. */

/* $ Literature_References */

/*     None. */

/* $ Author_and_Institution */

/*     J.M. Lynch     (JPL) */

/* $ Version */

/* -    SPICELIB Version 1.0.0, 15-JUN-1992 (JML) */

/* -& */
/* $ Index_Entries */

/*     relative difference of 3-dimensional vectors */

/* -& */

/*     SPICELIB functions */


/*     Local variables */


/*     If the numerator is zero then set VREL equal to zero. Otherwise, */
/*     perform the rest of the calculation. */

/*     This handles the case where both vectors are zero vectors since */
/*     the distance between them will be zero. */

    nunorm = vdist_(v1, v2);
    if (nunorm == 0.) {
	ret_val = 0.;
    } else {
/* Computing MAX */
	d__1 = vnorm_(v1), d__2 = vnorm_(v2);
	denorm = max(d__1,d__2);
	ret_val = nunorm / denorm;
    }
    return ret_val;
} /* vrel_ */
Beispiel #3
0
/* $Procedure      SUBPT ( Sub-observer point ) */
/* Subroutine */ int subpt_(char *method, char *target, doublereal *et, char *
	abcorr, char *obsrvr, doublereal *spoint, doublereal *alt, ftnlen 
	method_len, ftnlen target_len, ftnlen abcorr_len, ftnlen obsrvr_len)
{
    /* Initialized data */

    static doublereal origin[3] = { 0.,0.,0. };

    doublereal radii[3];
    extern /* Subroutine */ int chkin_(char *, ftnlen), errch_(char *, char *,
	     ftnlen, ftnlen);
    logical found;
    extern doublereal vdist_(doublereal *, doublereal *);
    extern /* Subroutine */ int spkez_(integer *, doublereal *, char *, char *
	    , integer *, doublereal *, doublereal *, ftnlen, ftnlen);
    extern logical eqstr_(char *, char *, ftnlen, ftnlen);
    extern /* Subroutine */ int bods2c_(char *, integer *, logical *, ftnlen);
    integer obscde;
    doublereal lt;
    extern /* Subroutine */ int bodvcd_(integer *, char *, integer *, integer 
	    *, doublereal *, ftnlen);
    integer frcode;
    extern /* Subroutine */ int cidfrm_(integer *, integer *, char *, logical 
	    *, ftnlen);
    integer nradii;
    char frname[80];
    integer trgcde;
    extern /* Subroutine */ int nearpt_(doublereal *, doublereal *, 
	    doublereal *, doublereal *, doublereal *, doublereal *), sigerr_(
	    char *, ftnlen), chkout_(char *, ftnlen), setmsg_(char *, ftnlen);
    doublereal tstate[6];
    extern logical return_(void);
    extern /* Subroutine */ int vminus_(doublereal *, doublereal *), surfpt_(
	    doublereal *, doublereal *, doublereal *, doublereal *, 
	    doublereal *, doublereal *, logical *);
    doublereal pos[3];

/* $ Abstract */

/*     Deprecated: This routine has been superseded by the SPICELIB */
/*     routine SUBPNT. This routine is supported for purposes of */
/*     backward compatibility only. */

/*     Compute the rectangular coordinates of the sub-observer point on */
/*     a target body at a particular epoch, optionally corrected for */
/*     planetary (light time) and stellar aberration.  Return these */
/*     coordinates expressed in the body-fixed frame associated with the */
/*     target body.  Also, return the observer's altitude above the */
/*     target body. */

/* $ Disclaimer */

/*     THIS SOFTWARE AND ANY RELATED MATERIALS WERE CREATED BY THE */
/*     CALIFORNIA INSTITUTE OF TECHNOLOGY (CALTECH) UNDER A U.S. */
/*     GOVERNMENT CONTRACT WITH THE NATIONAL AERONAUTICS AND SPACE */
/*     ADMINISTRATION (NASA). THE SOFTWARE IS TECHNOLOGY AND SOFTWARE */
/*     PUBLICLY AVAILABLE UNDER U.S. EXPORT LAWS AND IS PROVIDED "AS-IS" */
/*     TO THE RECIPIENT WITHOUT WARRANTY OF ANY KIND, INCLUDING ANY */
/*     WARRANTIES OF PERFORMANCE OR MERCHANTABILITY OR FITNESS FOR A */
/*     PARTICULAR USE OR PURPOSE (AS SET FORTH IN UNITED STATES UCC */
/*     SECTIONS 2312-2313) OR FOR ANY PURPOSE WHATSOEVER, FOR THE */
/*     SOFTWARE AND RELATED MATERIALS, HOWEVER USED. */

/*     IN NO EVENT SHALL CALTECH, ITS JET PROPULSION LABORATORY, OR NASA */
/*     BE LIABLE FOR ANY DAMAGES AND/OR COSTS, INCLUDING, BUT NOT */
/*     LIMITED TO, INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, */
/*     INCLUDING ECONOMIC DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS, */
/*     REGARDLESS OF WHETHER CALTECH, JPL, OR NASA BE ADVISED, HAVE */
/*     REASON TO KNOW, OR, IN FACT, SHALL KNOW OF THE POSSIBILITY. */

/*     RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF */
/*     THE SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY */
/*     CALTECH AND NASA FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE */
/*     ACTIONS OF RECIPIENT IN THE USE OF THE SOFTWARE. */

/* $ Required_Reading */

/*     FRAMES */
/*     PCK */
/*     SPK */
/*     TIME */

/* $ Keywords */

/*     GEOMETRY */

/* $ Declarations */
/* $ Brief_I/O */

/*     Variable  I/O  Description */
/*     --------  ---  -------------------------------------------------- */
/*     METHOD     I   Computation method. */
/*     TARGET     I   Name of target body. */
/*     ET         I   Epoch in ephemeris seconds past J2000 TDB. */
/*     ABCORR     I   Aberration correction. */
/*     OBSRVR     I   Name of observing body. */
/*     SPOINT     O   Sub-observer point on the target body. */
/*     ALT        O   Altitude of the observer above the target body. */

/* $ Detailed_Input */

/*     METHOD      is a short string specifying the computation method */
/*                 to be used.  The choices are: */

/*                    'Near point'       The sub-observer point is */
/*                                       defined as the nearest point on */
/*                                       the target relative to the */
/*                                       observer. */

/*                    'Intercept'        The sub-observer point is */
/*                                       defined as the target surface */
/*                                       intercept of the line */
/*                                       containing the observer and the */
/*                                       target's center. */

/*                 In both cases, the intercept computation treats the */
/*                 surface of the target body as a triaxial ellipsoid. */
/*                 The ellipsoid's radii must be available in the kernel */
/*                 pool. */

/*                 Neither case nor white space are significant in */
/*                 METHOD.  For example, the string ' NEARPOINT' is */
/*                 valid. */


/*     TARGET      is the name of a target body.  Optionally, you may */
/*                 supply the integer ID code for the object as */
/*                 an integer string.  For example both 'MOON' and */
/*                 '301' are legitimate strings that indicate the */
/*                 moon is the target body. This routine assumes */
/*                 that this body is modeled by a tri-axial ellipsoid, */
/*                 and that a PCK file containing its radii has been */
/*                 loaded into the kernel pool via FURNSH. */

/*     ET          is the epoch in ephemeris seconds past J2000 at which */
/*                 the sub-observer point on the target body is to be */
/*                 computed. */


/*     ABCORR      indicates the aberration corrections to be applied */
/*                 when computing the observer-target state.  ABCORR */
/*                 may be any of the following. */

/*                    'NONE'     Apply no correction. Return the */
/*                               geometric sub-observer point on the */
/*                               target body. */

/*                    'LT'       Correct for planetary (light time) */
/*                               aberration.  Both the state and rotation */
/*                               of the target body are corrected for */
/*                               light time. */

/*                    'LT+S'     Correct for planetary (light time) and */
/*                               stellar aberrations. Both the state and */
/*                               rotation of the target body are */
/*                               corrected for light time. */

/*                    'CN'       Converged Newtonian light time */
/*                               corrections.  This is the same as LT */
/*                               corrections but with further iterations */
/*                               to a converged Newtonian light time */
/*                               solution.  Given that relativistic */
/*                               effects may be as large as the higher */
/*                               accuracy achieved by this computation, */
/*                               this is correction is seldom worth the */
/*                               additional computations required unless */
/*                               the user incorporates additional */
/*                               relativistic corrections.  Both the */
/*                               state and rotation of the target body */
/*                               are corrected for light time. */

/*                    'CN+S'     Converged Newtonian light time */
/*                               corrections and stellar aberration. */
/*                               Both the state and rotation of the */
/*                               target body are corrected for light */
/*                               time. */

/*     OBSRVR      is the name of the observing body.  This is typically */
/*                 a spacecraft, the earth, or a surface point on the */
/*                 earth. Optionally, you  may supply the ID code of */
/*                 the object as an integer string. For example, both */
/*                 'EARTH' and '399' are legitimate strings to supply */
/*                 to indicate the observer is Earth. */

/* $ Detailed_Output */

/*     SPOINT      is the sub-observer point on the target body at ET */
/*                 expressed relative to the body-fixed frame of the */
/*                 target body. */

/*                 The sub-observer point is defined either as the point */
/*                 on the target body that is closest to the observer, */
/*                 or the target surface intercept of the line from the */
/*                 observer to the target's center; the input argument */
/*                 METHOD selects the definition to be used. */

/*                 The body-fixed frame, which is time-dependent, is */
/*                 evaluated at ET if ABCORR is 'NONE'; otherwise the */
/*                 frame is evaluated at ET-LT, where LT is the one-way */
/*                 light time from target to observer. */

/*                 The state of the target body is corrected for */
/*                 aberration as specified by ABCORR; the corrected */
/*                 state is used in the geometric computation.  As */
/*                 indicated above, the rotation of the target is */
/*                 retarded by one-way light time if ABCORR specifies */
/*                 that light time correction is to be done. */


/*     ALT         is the "altitude" of the observer above the target */
/*                 body.  When METHOD specifies a "near point" */
/*                 computation, ALT is truly altitude in the standard */
/*                 geometric sense:  the length of a segment dropped from */
/*                 the observer to the target's surface, such that the */
/*                 segment is perpendicular to the surface at the */
/*                 contact point SPOINT. */

/*                 When METHOD specifies an "intercept" computation, ALT */
/*                 is still the length of the segment from the observer */
/*                 to the surface point SPOINT, but this segment in */
/*                 general is not perpendicular to the surface. */

/* $ Parameters */

/*     None. */

/* $ Exceptions */

/*     If any of the listed errors occur, the output arguments are */
/*     left unchanged. */


/*     1) If the input argument METHOD is not recognized, the error */
/*        SPICE(DUBIOUSMETHOD) is signaled. */

/*     2) If either of the input body names TARGET or OBSRVR cannot be */
/*        mapped to NAIF integer codes, the error SPICE(IDCODENOTFOUND) */
/*        is signaled. */

/*     3) If OBSRVR and TARGET map to the same NAIF integer ID codes, the */
/*        error SPICE(BODIESNOTDISTINCT) is signaled. */

/*     4) If frame definition data enabling the evaluation of the state */
/*        of the target relative to the observer in target body-fixed */
/*        coordinates have not been loaded prior to calling SUBPT, the */
/*        error will be diagnosed and signaled by a routine in the call */
/*        tree of this routine. */

/*     5) If the specified aberration correction is not recognized, the */
/*        error will be diagnosed and signaled by a routine in the call */
/*        tree of this routine. */

/*     6) If insufficient ephemeris data have been loaded prior to */
/*        calling SUBPT, the error will be diagnosed and signaled by a */
/*        routine in the call tree of this routine. */

/*     7) If the triaxial radii of the target body have not been loaded */
/*        into the kernel pool prior to calling SUBPT, the error will be */
/*        diagnosed and signaled by a routine in the call tree of this */
/*        routine. */

/*     8) The target must be an extended body:  if any of the radii of */
/*        the target body are non-positive, the error will be diagnosed */
/*        and signaled by routines in the call tree of this routine. */

/*     9) If PCK data supplying a rotation model for the target body */
/*        have not been loaded prior to calling SUBPT, the error will be */
/*        diagnosed and signaled by a routine in the call tree of this */
/*        routine. */

/* $ Files */

/*     Appropriate SPK, PCK, and frame kernels must be loaded */
/*     prior by the calling program before this routine is called. */

/*     The following data are required: */

/*        - SPK data:  ephemeris data for target and observer must be */
/*          loaded.  If aberration corrections are used, the states of */
/*          target and observer relative to the solar system barycenter */
/*          must be calculable from the available ephemeris data. */
/*          Typically ephemeris data are made available by loading one */
/*          or more SPK files via FURNSH. */

/*        - PCK data:  triaxial radii for the target body must be loaded */
/*          into the kernel pool.  Typically this is done by loading a */
/*          text PCK file via FURNSH. */

/*        - Further PCK data:  rotation data for the target body must */
/*          be loaded.  These may be provided in a text or binary PCK */
/*          file.  Either type of file may be loaded via FURNSH. */

/*        - Frame data:  if a frame definition is required to convert */
/*          the observer and target states to the body-fixed frame of */
/*          the target, that definition must be available in the kernel */
/*          pool.  Typically the definition is supplied by loading a */
/*          frame kernel via FURNSH. */

/*     In all cases, kernel data are normally loaded once per program */
/*     run, NOT every time this routine is called. */

/* $ Particulars */

/*     SUBPT computes the sub-observer point on a target body. */
/*     (The sub-observer point is commonly called the sub-spacecraft */
/*     point when the observer is a spacecraft.)  SUBPT also */
/*     determines the altitude of the observer above the target body. */

/*     There are two different popular ways to define the sub-observer */
/*     point:  "nearest point on target to observer" or "target surface */
/*     intercept of line containing observer and target."  These */
/*     coincide when the target is spherical and generally are distinct */
/*     otherwise. */

/*     When comparing sub-point computations with results from sources */
/*     other than SPICE, it's essential to make sure the same geometric */
/*     definitions are used. */

/* $ Examples */

/*     The numerical results shown for this example may differ across */
/*     platforms.  The results depend on the SPICE kernels used as */
/*     input, the compiler and supporting libraries, and the machine */
/*     specific arithmetic implementation. */

/*     In the following example program, the file */

/*        spk_m_031103-040201_030502.bsp */

/*     is a binary SPK file containing data for Mars Global Surveyor, */
/*     Mars, and the Sun for a time interval bracketing the date */

/*         2004 JAN 1 12:00:00 UTC. */

/*     pck00007.tpc is a planetary constants kernel file containing */
/*     radii and rotation model constants.  naif0007.tls is a */
/*     leapseconds kernel. */

/*     Find the sub-observer point of the Mars Global Surveyor (MGS) */
/*     spacecraft on Mars for a specified time.  Perform the computation */
/*     twice, using both the "intercept" and "near point" options. */


/*           IMPLICIT NONE */

/*           CHARACTER*25          METHOD ( 2 ) */

/*           INTEGER               I */

/*           DOUBLE PRECISION      ALT */
/*           DOUBLE PRECISION      DPR */
/*           DOUBLE PRECISION      ET */
/*           DOUBLE PRECISION      LAT */
/*           DOUBLE PRECISION      LON */
/*           DOUBLE PRECISION      RADIUS */
/*           DOUBLE PRECISION      SPOINT ( 3 ) */

/*           DATA                  METHOD / 'Intercept', 'Near point' / */

/*     C */
/*     C     Load kernel files. */
/*     C */
/*           CALL FURNSH ( 'naif0007.tls'                   ) */
/*           CALL FURNSH ( 'pck00007.tpc'                   ) */
/*           CALL FURNSH ( 'spk_m_031103-040201_030502.bsp' ) */

/*     C */
/*     C     Convert the UTC request time to ET (seconds past */
/*     C     J2000, TDB). */
/*     C */
/*           CALL STR2ET ( '2004 JAN 1 12:00:00', ET ) */

/*     C */
/*     C     Compute sub-spacecraft point using light time and stellar */
/*     C     aberration corrections.  Use the "target surface intercept" */
/*     C     definition of sub-spacecraft point on the first loop */
/*     C     iteration, and use the "near point" definition on the */
/*     C     second. */
/*     C */
/*           DO I = 1, 2 */

/*              CALL SUBPT ( METHOD(I), */
/*          .               'MARS',     ET,     'LT+S', */
/*          .               'MGS',      SPOINT,  ALT    ) */

/*     C */
/*     C        Convert rectangular coordinates to planetocentric */
/*     C        latitude and longitude.  Convert radians to degrees. */
/*     C */
/*              CALL RECLAT ( SPOINT, RADIUS, LON, LAT  ) */

/*              LON = LON * DPR () */
/*              LAT = LAT * DPR () */

/*     C */
/*     C        Write the results. */
/*     C */
/*              WRITE (*,*) ' ' */
/*              WRITE (*,*) 'Computation method: ', METHOD(I) */
/*              WRITE (*,*) ' ' */
/*              WRITE (*,*) '  Radius                   (km)  = ', RADIUS */
/*              WRITE (*,*) '  Planetocentric Latitude  (deg) = ', LAT */
/*              WRITE (*,*) '  Planetocentric Longitude (deg) = ', LON */
/*              WRITE (*,*) '  Altitude                 (km)  = ', ALT */
/*              WRITE (*,*) ' ' */

/*           END DO */

/*           END */


/*     When this program is executed, the output will be: */


/*        Computation method: Intercept */

/*          Radius                   (km)  =   3387.97077 */
/*          Planetocentric Latitude  (deg) =  -39.7022724 */
/*          Planetocentric Longitude (deg) =  -159.226663 */
/*          Altitude                 (km)  =   373.173506 */


/*        Computation method: Near point */

/*          Radius                   (km)  =   3387.9845 */
/*          Planetocentric Latitude  (deg) =  -39.6659329 */
/*          Planetocentric Longitude (deg) =  -159.226663 */
/*          Altitude                 (km)  =   373.166636 */


/* $ Restrictions */

/*     None. */

/* $ Literature_References */

/*     None. */

/* $ Author_and_Institution */

/*     C.H. Acton     (JPL) */
/*     N.J. Bachman   (JPL) */
/*     J.E. McLean    (JPL) */

/* $ Version */

/* -    SPICELIB Version 1.2.3, 18-MAY-2010 (BVS) */

/*        Index line now states that this routine is deprecated. */

/* -    SPICELIB Version 1.2.2, 17-MAR-2009 (EDW) */

/*        Typo correction in Required_Reading, changed */
/*        FRAME to FRAMES. */

/* -    SPICELIB Version 1.2.1, 07-FEB-2008 (NJB) */

/*        Abstract now states that this routine is deprecated. */

/* -    SPICELIB Version 1.2.0, 24-OCT-2005 (NJB) */

/*        Replaced call to BODVAR with call to BODVCD. */

/* -    SPICELIB Version 1.1.0, 21-JUL-2004 (EDW) */

/*        Changed BODN2C call to BODS2C giving the routine */
/*        the capability to accept string representations of */
/*        interger IDs for TARGET and OBSRVR. */

/* -    SPICELIB Version 1.0.1, 27-JUL-2003 (NJB) (CHA) */

/*        Various header corrections were made.  The example program */
/*        was upgraded to use real kernels, and the program's output is */
/*        shown. */

/* -    SPICELIB Version 1.0.0, 03-SEP-1999 (NJB) (JEM) */

/* -& */
/* $ Index_Entries */

/*     DEPRECATED sub-observer point */

/* -& */

/*     SPICELIB functions */


/*     Local parameters */


/*     Local variables */


/*     Saved variables */


/*     Initial values */


/*     Standard SPICE error handling. */

    if (return_()) {
	return 0;
    } else {
	chkin_("SUBPT", (ftnlen)5);
    }

/*     Obtain integer codes for the target and observer. */

/*     Target... */

    bods2c_(target, &trgcde, &found, target_len);
    if (! found) {
	setmsg_("The target, '#', is not a recognized name for an ephemeris "
		"object. The cause of this problem may be that you need an up"
		"dated version of the SPICE Toolkit. ", (ftnlen)155);
	errch_("#", target, (ftnlen)1, target_len);
	sigerr_("SPICE(IDCODENOTFOUND)", (ftnlen)21);
	chkout_("SUBPT", (ftnlen)5);
	return 0;
    }

/*     ...observer. */

    bods2c_(obsrvr, &obscde, &found, obsrvr_len);
    if (! found) {
	setmsg_("The observer, '#', is not a recognized name for an ephemeri"
		"s object. The cause of this problem may be that you need an "
		"updated version of the SPICE Toolkit. ", (ftnlen)157);
	errch_("#", obsrvr, (ftnlen)1, obsrvr_len);
	sigerr_("SPICE(IDCODENOTFOUND)", (ftnlen)21);
	chkout_("SUBPT", (ftnlen)5);
	return 0;
    }

/*     Check the input body codes.  If they are equal, signal */
/*     an error. */

    if (obscde == trgcde) {
	setmsg_("In computing the sub-observer point, the observing body and"
		" target body are the same. Both are #.", (ftnlen)97);
	errch_("#", obsrvr, (ftnlen)1, obsrvr_len);
	sigerr_("SPICE(BODIESNOTDISTINCT)", (ftnlen)24);
	chkout_("SUBPT", (ftnlen)5);
	return 0;
    }

/*     Get the radii of the target body from the kernel pool. */

    bodvcd_(&trgcde, "RADII", &c__3, &nradii, radii, (ftnlen)5);

/*     Find the name of the body-fixed frame associated with the */
/*     target body.  We'll want the state of the target relative to */
/*     the observer in this body-fixed frame. */

    cidfrm_(&trgcde, &frcode, frname, &found, (ftnlen)80);
    if (! found) {
	setmsg_("No body-fixed frame is associated with target body #; a fra"
		"me kernel must be loaded to make this association.  Consult "
		"the FRAMES Required Reading for details.", (ftnlen)159);
	errch_("#", target, (ftnlen)1, target_len);
	sigerr_("SPICE(NOFRAME)", (ftnlen)14);
	chkout_("SUBPT", (ftnlen)5);
	return 0;
    }

/*     Determine the position of the observer in target */
/*     body-fixed coordinates. */

/*         -  Call SPKEZR to compute the position of the target */
/*            body as seen from the observing body and the light time */
/*            (LT) between them.  SPKEZR returns a state which is */
/*            the position and velocity, but we'll only use the position */
/*            which is the first three elements.  We request that the */
/*            coordinates of POS be returned relative to the body fixed */
/*            reference frame associated with the target body, using */
/*            aberration corrections specified by the input argument */
/*            ABCORR. */

/*         -  Call VMINUS to negate the direction of the vector (POS) */
/*            so it will be the position of the observer as seen from */
/*            the target body in target body fixed coordinates. */

/*            Note that this result is not the same as the result of */
/*            calling SPKEZR with the target and observer switched.  We */
/*            computed the vector FROM the observer TO the target in */
/*            order to get the proper light time and stellar aberration */
/*            corrections (if requested).  Now we need the inverse of */
/*            that corrected vector in order to compute the sub-point. */

    spkez_(&trgcde, et, frname, abcorr, &obscde, tstate, &lt, (ftnlen)80, 
	    abcorr_len);

/*     Negate the target's state to obtain the position of the observer */
/*     relative to the target. */

    vminus_(tstate, pos);

/*     Find the sub-point and "altitude" (distance from observer to */
/*     sub-point) using the specified geometric definition. */

    if (eqstr_(method, "Near point", method_len, (ftnlen)10)) {

/*        Locate the nearest point to the observer on the target. */

	nearpt_(pos, radii, &radii[1], &radii[2], spoint, alt);
    } else if (eqstr_(method, "Intercept", method_len, (ftnlen)9)) {
	surfpt_(origin, pos, radii, &radii[1], &radii[2], spoint, &found);

/*        Since the line in question passes through the center of the */
/*        target, there will always be a surface intercept.  So we should */
/*        never have FOUND = .FALSE. */

	if (! found) {
	    setmsg_("Call to SURFPT returned FOUND=FALSE even though vertex "
		    "of ray is at target center. This indicates a bug. Please"
		    " contact NAIF.", (ftnlen)125);
	    sigerr_("SPICE(BUG)", (ftnlen)10);
	    chkout_("SUBPT", (ftnlen)5);
	    return 0;
	}

/*        SURFPT doesn't compute altitude, so do it here. */

	*alt = vdist_(pos, spoint);
    } else {
	setmsg_("The computation method # was not recognized. Allowed values"
		" are \"Near point\" and \"Intercept.\"", (ftnlen)93);
	errch_("#", method, (ftnlen)1, method_len);
	sigerr_("SPICE(DUBIOUSMETHOD)", (ftnlen)20);
	chkout_("SUBPT", (ftnlen)5);
	return 0;
    }
    chkout_("SUBPT", (ftnlen)5);
    return 0;
} /* subpt_ */