Esempio n. 1
0
/* $Procedure ZZSPKGO0 ( S/P Kernel, geometric state ) */
/* Subroutine */ int zzspkgo0_(integer *targ, doublereal *et, char *ref, 
	integer *obs, doublereal *state, doublereal *lt, ftnlen ref_len)
{
    /* System generated locals */
    integer i__1, i__2, i__3;

    /* Builtin functions */
    integer s_cmp(char *, char *, ftnlen, ftnlen), s_rnge(char *, integer, 
	    char *, integer);

    /* Local variables */
    extern /* Subroutine */ int zzfrmch0_(integer *, integer *, doublereal *, 
	    doublereal *);
    integer cobs, legs;
    doublereal sobs[6];
    extern /* Subroutine */ int mxvg_(doublereal *, doublereal *, integer *, 
	    integer *, doublereal *);
    integer i__;
    extern /* Subroutine */ int vaddg_(doublereal *, doublereal *, integer *, 
	    doublereal *), etcal_(doublereal *, char *, ftnlen);
    integer refid;
    extern /* Subroutine */ int chkin_(char *, ftnlen);
    char oname[40];
    doublereal descr[5];
    integer ctarg[20];
    char ident[40], tname[40];
    extern /* Subroutine */ int errch_(char *, char *, ftnlen, ftnlen), 
	    moved_(doublereal *, integer *, doublereal *);
    logical found;
    extern /* Subroutine */ int repmi_(char *, char *, integer *, char *, 
	    ftnlen, ftnlen, ftnlen);
    doublereal starg[120]	/* was [6][20] */;
    logical nofrm;
    extern /* Subroutine */ int vsubg_(doublereal *, doublereal *, integer *, 
	    doublereal *);
    doublereal stemp[6];
    integer ctpos;
    doublereal vtemp[6];
    extern doublereal vnorm_(doublereal *);
    extern /* Subroutine */ int bodc2n_(integer *, char *, logical *, ftnlen);
    extern logical failed_(void);
    extern /* Subroutine */ int cleard_(integer *, doublereal *);
    integer handle, cframe;
    extern doublereal clight_(void);
    integer tframe[20];
    extern /* Subroutine */ int namfrm_(char *, integer *, ftnlen);
    extern integer isrchi_(integer *, integer *, integer *);
    extern /* Subroutine */ int sigerr_(char *, ftnlen), chkout_(char *, 
	    ftnlen), prefix_(char *, integer *, char *, ftnlen, ftnlen), 
	    irfnum_(char *, integer *, ftnlen), setmsg_(char *, ftnlen), 
	    suffix_(char *, integer *, char *, ftnlen, ftnlen);
    integer tmpfrm;
    extern /* Subroutine */ int irfrot_(integer *, integer *, doublereal *), 
	    spksfs_(integer *, doublereal *, integer *, doublereal *, char *, 
	    logical *, ftnlen);
    extern integer frstnp_(char *, ftnlen);
    extern logical return_(void);
    extern /* Subroutine */ int spkpvn_(integer *, doublereal *, doublereal *,
	     integer *, doublereal *, integer *);
    doublereal stxfrm[36]	/* was [6][6] */;
    extern /* Subroutine */ int intstr_(integer *, char *, ftnlen);
    integer nct;
    doublereal rot[9]	/* was [3][3] */;
    extern /* Subroutine */ int mxv_(doublereal *, doublereal *, doublereal *)
	    ;
    char tstring[80];

/* $ Abstract */

/*     SPICE Private routine intended solely for the support of SPICE */
/*     routines.  Users should not call this routine directly due */
/*     to the volatile nature of this routine. */

/*     Compute the geometric state (position and velocity) of a target */
/*     body relative to an observing 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 */

/*     SPK */

/* $ Keywords */

/*     EPHEMERIS */

/* $ Declarations */
/* $ Abstract */

/*     This file contains the number of inertial reference */
/*     frames that are currently known by the SPICE toolkit */
/*     software. */

/* $ 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 */

/*     FRAMES */

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

/*     VARIABLE  I/O  DESCRIPTION */
/*     --------  ---  -------------------------------------------------- */
/*     NINERT     P   Number of known inertial reference frames. */

/* $ Parameters */

/*     NINERT     is the number of recognized inertial reference */
/*                frames.  This value is needed by both CHGIRF */
/*                ZZFDAT, and FRAMEX. */

/* $ Author_and_Institution */

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

/* $ Literature_References */

/*     None. */

/* $ Version */

/* -    SPICELIB Version 1.0.0, 10-OCT-1996 (WLT) */

/* -& */
/* $ Brief_I/O */

/*     Variable  I/O  Description */
/*     --------  ---  -------------------------------------------------- */
/*     TARG       I   Target body. */
/*     ET         I   Target epoch. */
/*     REF        I   Target reference frame. */
/*     OBS        I   Observing body. */
/*     STATE      O   State of target. */
/*     LT         O   Light time. */

/* $ Detailed_Input */

/*     TARG        is the standard NAIF ID code for a target body. */

/*     ET          is the epoch (ephemeris time) at which the state */
/*                 of the target body is to be computed. */

/*     REF         is the name of the reference frame to */
/*                 which the vectors returned by the routine should */
/*                 be rotated. This may be any frame supported by */
/*                 the SPICELIB subroutine ZZFRMCH0. */

/*     OBS         is the standard NAIF ID code for an observing body. */

/* $ Detailed_Output */

/*     STATE       contains the position and velocity of the target */
/*                 body, relative to the observing body, corrected */
/*                 for the specified aberrations, at epoch ET.  STATE */
/*                 has six elements:  the first three contain the */
/*                 target's position; the last three contain the target's */
/*                 velocity.  These vectors are rotated into the */
/*                 specified reference frame. Units are always */
/*                 km and km/sec. */

/*     LT          is the one-way light time in seconds from the */
/*                 observing body to the geometric position of the */
/*                 target body at the specified epoch. */

/* $ Parameters */

/*     None. */

/* $ Exceptions */

/*     1) If insufficient ephemeris data has been loaded to compute */
/*        the necessary states, the error SPICE(SPKINSUFFDATA) is */
/*        signaled. */

/* $ Files */

/*     See: $Restrictions. */

/* $ Particulars */

/*     ZZSPKGO0 computes the geometric state, T(t), of the target */
/*     body and the geometric state, O(t), of the observing body */
/*     relative to the first common center of motion.  Subtracting */
/*     O(t) from T(t) gives the geometric state of the target */
/*     body relative to the observer. */


/*        CENTER ----- O(t) */
/*            |      / */
/*            |     / */
/*            |    / */
/*            |   /  T(t) - O(t) */
/*            |  / */
/*           T(t) */


/*     The one-way light time, tau, is given by */


/*               | T(t) - O(t) | */
/*        tau = ----------------- */
/*                      c */


/*     For example, if the observing body is -94, the Mars Observer */
/*     spacecraft, and the target body is 401, Phobos, then the */
/*     first common center is probably 4, the Mars Barycenter. */
/*     O(t) is the state of -94 relative to 4 and T(t) is the */
/*     state of 401 relative to 4. */

/*     The center could also be the Solar System Barycenter, body 0. */
/*     For example, if the observer is 399, Earth, and the target */
/*     is 299, Venus, then O(t) would be the state of 399 relative */
/*     to 0 and T(t) would be the state of 299 relative to 0. */

/*     Ephemeris data from more than one segment may be required */
/*     to determine the states of the target body and observer */
/*     relative to a common center.  ZZSPKGO0 reads as many segments */
/*     as necessary, from as many files as necessary, using files */
/*     that have been loaded by previous calls to SPKLEF (load */
/*     ephemeris file). */

/*     ZZSPKGO0 is similar to SPKEZ but returns geometric states */
/*     only, with no option to make planetary (light-time) nor */
/*     stellar aberration corrections.  The geometric states */
/*     returned by SPKEZ and ZZSPKGO0 are the same. */

/* $ Examples */

/*     The following code example computes the geometric */
/*     state of the moon with respect to the earth and */
/*     then prints the distance of the moon from the */
/*     the earth at a number of epochs. */

/*     Assume the SPK file SAMPLE.BSP contains ephemeris data */
/*     for the moon relative to earth over the time interval */
/*     from BEGIN to END. */

/*            INTEGER               EARTH */
/*            PARAMETER           ( EARTH = 399 ) */

/*            INTEGER               MOON */
/*            PARAMETER           ( MOON  = 301 ) */

/*            INTEGER               N */
/*            PARAMETER           ( N     = 100 ) */

/*            INTEGER               HANDLE */
/*            CHARACTER*(20)        UTC */
/*            DOUBLE PRECISION      BEGIN */
/*            DOUBLE PRECISION      DELTA */
/*            DOUBLE PRECISION      END */
/*            DOUBLE PRECISION      ET */
/*            DOUBLE PRECISION      STATE ( 6 ) */

/*     C */
/*     C      Load the binary SPK ephemeris file. */
/*     C */
/*            CALL SPKLEF ( 'SAMPLE.BSP', HANDLE ) */

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

/*     C */
/*     C      Divide the interval of coverage [BEGIN,END] into */
/*     C      N steps.  At each step, compute the state, and */
/*     C      print out the epoch in UTC time and position norm. */
/*     C */
/*            DELTA = ( END - BEGIN ) / N */

/*            DO I = 0, N */

/*               ET = BEGIN + I*DELTA */

/*               CALL ZZSPKGO0 ( MOON, ET, 'J2000', EARTH, STATE, LT ) */

/*               CALL ET2UTC ( ET, 'C', 0, UTC ) */

/*               WRITE (*,*) UTC, VNORM ( STATE ) */

/*            END DO */

/* $ Restrictions */

/*     1) SPICE Private routine. */

/*     2) The ephemeris files to be used by ZZSPKGO0 must be loaded */
/*        by SPKLEF before ZZSPKGO0 is called. */

/* $ Literature_References */

/*     None. */

/* $ Author_and_Institution */

/*     J.E. McLean (JPL) */
/*     W.L. Taber  (JPL) */

/* $ Version */

/* -    SPICELIB Version 1.1.0, 06-SEP-2005 (NJB) */

/*        Updated to remove non-standard use of duplicate arguments */
/*        in VADDG calls. */

/* -    SPICELIB Version 1.0.0, 05-JAN-2005 (NJB) */

/*        Based on SPICELIB Version 2.3.0, 05-JAN-2005 (NJB) */

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

/*     geometric state of one body relative to another */

/* -& */
/* $ Revisions */

/* -    SPICELIB Version 1.1.0, 06-SEP-2005 (NJB) */

/*        Updated to remove non-standard use of duplicate arguments */
/*        in VADDG calls. */

/* -& */

/*     This is the idea: */

/*     Every body moves with respect to some center. The center */
/*     is itself a body, which in turn moves about some other */
/*     center.  If we begin at the target body (T), follow */
/*     the chain, */

/*                                   T */
/*                                     \ */
/*           SSB                        \ */
/*               \                     C[1] */
/*                \                     / */
/*                 \                   / */
/*                  \                 / */
/*                   \               / */
/*                  C[3]-----------C[2] */

/*     and avoid circular definitions (A moves about B, and B moves */
/*     about A), eventually we get the state relative to the solar */
/*     system barycenter (which, for our purposes, doesn't move). */
/*     Thus, */

/*        T    = T     + C[1]     + C[2]     + ... + C[n] */
/*         SSB    C[1]       C[2]       [C3]             SSB */

/*     where */

/*        X */
/*         Y */

/*     is the state of body X relative to body Y. */

/*     However, we don't want to follow each chain back to the SSB */
/*     if it isn't necessary.  Instead we will just follow the chain */
/*     of the target body and follow the chain of the observing body */
/*     until we find a common node in the tree. */

/*     In the example below, C is the first common node.  We compute */
/*     the state of TARG relative to C and the state of OBS relative */
/*     to C, then subtract the two states. */

/*                                   TARG */
/*                                     \ */
/*           SSB                        \ */
/*               \                       A */
/*                \                     /            OBS */
/*                 \                   /              | */
/*                  \                 /               | */
/*                   \               /                | */
/*                    B-------------C-----------------D */




/*     SPICELIB functions */


/*     Local parameters */


/*     CHLEN is the maximum length of a chain.  That is, */
/*     it is the maximum number of bodies in the chain from */
/*     the target or observer to the SSB. */


/*     Local variables */


/*     In-line Function Definitions */


/*     Standard SPICE error handling. */

    if (return_()) {
	return 0;
    } else {
	chkin_("ZZSPKGO0", (ftnlen)8);
    }

/*     We take care of the obvious case first.  It TARG and OBS are the */
/*     same we can just fill in zero. */

    if (*targ == *obs) {
	*lt = 0.;
	cleard_(&c__6, state);
	chkout_("ZZSPKGO0", (ftnlen)8);
	return 0;
    }

/*     CTARG contains the integer codes of the bodies in the */
/*     target body chain, beginning with TARG itself and then */
/*     the successive centers of motion. */

/*     STARG(1,I) is the state of the target body relative */
/*     to CTARG(I).  The id-code of the frame of this state is */
/*     stored in TFRAME(I). */

/*     COBS and SOBS will contain the centers and states of the */
/*     observing body.  (They are single elements instead of arrays */
/*     because we only need the current center and state of the */
/*     observer relative to it.) */

/*     First, we construct CTARG and STARG.  CTARG(1) is */
/*     just the target itself, and STARG(1,1) is just a zero */
/*     vector, that is, the state of the target relative */
/*     to itself. */

/*     Then we follow the chain, filling up CTARG and STARG */
/*     as we go.  We use SPKSFS to search through loaded */
/*     files to find the first segment applicable to CTARG(1) */
/*     and time ET.  Then we use SPKPVN to compute the state */
/*     of the body CTARG(1) at ET in the segment that was found */
/*     and get its center and frame of motion (CTARG(2) and TFRAME(2). */

/*     We repeat the process for CTARG(2) and so on, until */
/*     there is no data found for some CTARG(I) or until we */
/*     reach the SSB. */

/*     Next, we find centers and states in a similar manner */
/*     for the observer.  It's a similar construction as */
/*     described above, but I is always 1.  COBS and SOBS */
/*     are overwritten with each new center and state, */
/*     beginning at OBS.  However, we stop when we encounter */
/*     a common center of motion, that is when COBS is equal */
/*     to CTARG(I) for some I. */

/*     Finally, we compute the desired state of the target */
/*     relative to the observer by subtracting the state of */
/*     the observing body relative to the common node from */
/*     the state of the target body relative to the common */
/*     node. */

/*     CTPOS is the position in CTARG of the common node. */


/*     Since Inertial frames are the most extensively used frames */
/*     we use the more restrictive routine IRFNUM to attempt to */
/*     look up the id-code for REF.  If IRFNUM comes up empty handed */
/*     we then call the more general routine NAMFRM. */

    irfnum_(ref, &refid, ref_len);
    if (refid == 0) {
	namfrm_(ref, &refid, ref_len);
    }
    if (refid == 0) {
	if (frstnp_(ref, ref_len) > 0) {
	    setmsg_("The string supplied to specify the reference frame, ('#"
		    "') contains non-printing characters.  The two most commo"
		    "n causes for this kind of error are: 1. an error in the "
		    "call to ZZSPKGO0; 2. an uninitialized variable. ", (
		    ftnlen)215);
	    errch_("#", ref, (ftnlen)1, ref_len);
	} else if (s_cmp(ref, " ", ref_len, (ftnlen)1) == 0) {
	    setmsg_("The string supplied to specify the reference frame is b"
		    "lank.  The most common cause for this kind of error is a"
		    "n uninitialized variable. ", (ftnlen)137);
	} else {
	    setmsg_("The string supplied to specify the reference frame was "
		    "'#'.  This frame is not recognized. Possible causes for "
		    "this error are: 1. failure to load the frame definition "
		    "into the kernel pool; 2. An out-of-date edition of the t"
		    "oolkit. ", (ftnlen)231);
	    errch_("#", ref, (ftnlen)1, ref_len);
	}
	sigerr_("SPICE(UNKNOWNFRAME)", (ftnlen)19);
	if (failed_()) {
	    chkout_("ZZSPKGO0", (ftnlen)8);
	    return 0;
	}
    }

/*     Fill in CTARG and STARG until no more data is found */
/*     or until we reach the SSB.  If the chain gets too */
/*     long to fit in CTARG, that is if I equals CHLEN, */
/*     then overwrite the last elements of CTARG and STARG. */

/*     Note the check for FAILED in the loop.  If SPKSFS */
/*     or SPKPVN happens to fail during execution, and the */
/*     current error handling action is to NOT abort, then */
/*     FOUND may be stuck at TRUE, CTARG(I) will never */
/*     become zero, and the loop will execute indefinitely. */


/*     Construct CTARG and STARG.  Begin by assigning the */
/*     first elements:  TARG and the state of TARG relative */
/*     to itself. */

    i__ = 1;
    ctarg[(i__1 = i__ - 1) < 20 && 0 <= i__1 ? i__1 : s_rnge("ctarg", i__1, 
	    "zzspkgo0_", (ftnlen)532)] = *targ;
    found = TRUE_;
    cleard_(&c__6, &starg[(i__1 = i__ * 6 - 6) < 120 && 0 <= i__1 ? i__1 : 
	    s_rnge("starg", i__1, "zzspkgo0_", (ftnlen)535)]);
    while(found && i__ < 20 && ctarg[(i__1 = i__ - 1) < 20 && 0 <= i__1 ? 
	    i__1 : s_rnge("ctarg", i__1, "zzspkgo0_", (ftnlen)537)] != *obs &&
	     ctarg[(i__2 = i__ - 1) < 20 && 0 <= i__2 ? i__2 : s_rnge("ctarg",
	     i__2, "zzspkgo0_", (ftnlen)537)] != 0) {

/*        Find a file and segment that has state */
/*        data for CTARG(I). */

	spksfs_(&ctarg[(i__1 = i__ - 1) < 20 && 0 <= i__1 ? i__1 : s_rnge(
		"ctarg", i__1, "zzspkgo0_", (ftnlen)546)], et, &handle, descr,
		 ident, &found, (ftnlen)40);
	if (found) {

/*           Get the state of CTARG(I) relative to some */
/*           center of motion.  This new center goes in */
/*           CTARG(I+1) and the state is called STEMP. */

	    ++i__;
	    spkpvn_(&handle, descr, et, &tframe[(i__1 = i__ - 1) < 20 && 0 <= 
		    i__1 ? i__1 : s_rnge("tframe", i__1, "zzspkgo0_", (ftnlen)
		    556)], &starg[(i__2 = i__ * 6 - 6) < 120 && 0 <= i__2 ? 
		    i__2 : s_rnge("starg", i__2, "zzspkgo0_", (ftnlen)556)], &
		    ctarg[(i__3 = i__ - 1) < 20 && 0 <= i__3 ? i__3 : s_rnge(
		    "ctarg", i__3, "zzspkgo0_", (ftnlen)556)]);

/*           Here's what we have.  STARG is the state of CTARG(I-1) */
/*           relative to CTARG(I) in reference frame TFRAME(I) */

/*           If one of the routines above failed during */
/*           execution, we just give up and check out. */

	    if (failed_()) {
		chkout_("ZZSPKGO0", (ftnlen)8);
		return 0;
	    }
	}
    }
    tframe[0] = tframe[1];

/*     If the loop above ended because we ran out of */
/*     room in the arrays CTARG and STARG, then we */
/*     continue finding states but we overwrite the */
/*     last elements of CTARG and STARG. */

/*     If, as a result, the first common node is */
/*     overwritten, we'll just have to settle for */
/*     the last common node.  This will cause a small */
/*     loss of precision, but it's better than other */
/*     alternatives. */

    if (i__ == 20) {
	while(found && ctarg[19] != 0 && ctarg[19] != *obs) {

/*           Find a file and segment that has state */
/*           data for CTARG(CHLEN). */

	    spksfs_(&ctarg[19], et, &handle, descr, ident, &found, (ftnlen)40)
		    ;
	    if (found) {

/*              Get the state of CTARG(CHLEN) relative to */
/*              some center of motion.  The new center */
/*              overwrites the old.  The state is called */
/*              STEMP. */

		spkpvn_(&handle, descr, et, &tmpfrm, stemp, &ctarg[19]);

/*              Add STEMP to the state of TARG relative to */
/*              the old center to get the state of TARG */
/*              relative to the new center.  Overwrite */
/*              the last element of STARG. */

		if (tframe[19] == tmpfrm) {
		    moved_(&starg[114], &c__6, vtemp);
		} else if (tmpfrm > 0 && tmpfrm <= 21 && tframe[19] > 0 && 
			tframe[19] <= 21) {
		    irfrot_(&tframe[19], &tmpfrm, rot);
		    mxv_(rot, &starg[114], vtemp);
		    mxv_(rot, &starg[117], &vtemp[3]);
		} else {
		    zzfrmch0_(&tframe[19], &tmpfrm, et, stxfrm);
		    if (failed_()) {
			chkout_("ZZSPKGO0", (ftnlen)8);
			return 0;
		    }
		    mxvg_(stxfrm, &starg[114], &c__6, &c__6, vtemp);
		}
		vaddg_(vtemp, stemp, &c__6, &starg[114]);
		tframe[19] = tmpfrm;

/*              If one of the routines above failed during */
/*              execution, we just give up and check out. */

		if (failed_()) {
		    chkout_("ZZSPKGO0", (ftnlen)8);
		    return 0;
		}
	    }
	}
    }
    nct = i__;

/*     NCT is the number of elements in CTARG, */
/*     the chain length.  We have in hand the following information */

/*        STARG(1...6,K)  state of body */
/*        CTARG(K-1)      relative to body CTARG(K) in the frame */
/*        TFRAME(K) */


/*     For K = 2,..., NCT. */

/*     CTARG(1) = TARG */
/*     STARG(1...6,1) = ( 0, 0, 0, 0, 0, 0 ) */
/*     TFRAME(1)      = TFRAME(2) */


/*     Now follow the observer's chain.  Assign */
/*     the first values for COBS and SOBS. */

    cobs = *obs;
    cleard_(&c__6, sobs);

/*     Perhaps we have a common node already. */
/*     If so it will be the last node on the */
/*     list CTARG. */

/*     We let CTPOS will be the position of the common */
/*     node in CTARG if one is found.  It will */
/*     be zero if COBS is not found in CTARG. */

    if (ctarg[(i__1 = nct - 1) < 20 && 0 <= i__1 ? i__1 : s_rnge("ctarg", 
	    i__1, "zzspkgo0_", (ftnlen)692)] == cobs) {
	ctpos = nct;
	cframe = tframe[(i__1 = ctpos - 1) < 20 && 0 <= i__1 ? i__1 : s_rnge(
		"tframe", i__1, "zzspkgo0_", (ftnlen)694)];
    } else {
	ctpos = 0;
    }

/*     Repeat the same loop as above, but each time */
/*     we encounter a new center of motion, check to */
/*     see if it is a common node.  (When CTPOS is */
/*     not zero, CTARG(CTPOS) is the first common node.) */

/*     Note that we don't need a centers array nor a */
/*     states array, just a single center and state */
/*     is sufficient --- we just keep overwriting them. */
/*     When the common node is found, we have everything */
/*     we need in that one center (COBS) and state */
/*     (SOBS-state of the target relative to COBS). */

    found = TRUE_;
    nofrm = TRUE_;
    legs = 0;
    while(found && cobs != 0 && ctpos == 0) {

/*        Find a file and segment that has state */
/*        data for COBS. */

	spksfs_(&cobs, et, &handle, descr, ident, &found, (ftnlen)40);
	if (found) {

/*           Get the state of COBS; call it STEMP. */
/*           The center of motion of COBS becomes the */
/*           new COBS. */

	    if (legs == 0) {
		spkpvn_(&handle, descr, et, &tmpfrm, sobs, &cobs);
	    } else {
		spkpvn_(&handle, descr, et, &tmpfrm, stemp, &cobs);
	    }
	    if (nofrm) {
		nofrm = FALSE_;
		cframe = tmpfrm;
	    }

/*           Add STEMP to the state of OBS relative to */
/*           the old COBS to get the state of OBS */
/*           relative to the new COBS. */

	    if (cframe == tmpfrm) {

/*              On the first leg of the state of the observer, we */
/*              don't have to add anything, the state of the observer */
/*              is already in SOBS.  We only have to add when the */
/*              number of legs in the observer state is one or greater. */

		if (legs > 0) {
		    vaddg_(sobs, stemp, &c__6, vtemp);
		    moved_(vtemp, &c__6, sobs);
		}
	    } else if (tmpfrm > 0 && tmpfrm <= 21 && cframe > 0 && cframe <= 
		    21) {
		irfrot_(&cframe, &tmpfrm, rot);
		mxv_(rot, sobs, vtemp);
		mxv_(rot, &sobs[3], &vtemp[3]);
		vaddg_(vtemp, stemp, &c__6, sobs);
		cframe = tmpfrm;
	    } else {
		zzfrmch0_(&cframe, &tmpfrm, et, stxfrm);
		if (failed_()) {
		    chkout_("ZZSPKGO0", (ftnlen)8);
		    return 0;
		}
		mxvg_(stxfrm, sobs, &c__6, &c__6, vtemp);
		vaddg_(vtemp, stemp, &c__6, sobs);
		cframe = tmpfrm;
	    }

/*           Check failed.  We don't want to loop */
/*           indefinitely. */

	    if (failed_()) {
		chkout_("ZZSPKGO0", (ftnlen)8);
		return 0;
	    }

/*           We now have one more leg of the path for OBS.  Set */
/*           LEGS to reflect this.  Then see if the new center */
/*           is a common node. If not, repeat the loop. */

	    ++legs;
	    ctpos = isrchi_(&cobs, &nct, ctarg);
	}
    }

/*     If CTPOS is zero at this point, it means we */
/*     have not found a common node though we have */
/*     searched through all the available data. */

    if (ctpos == 0) {
	bodc2n_(targ, tname, &found, (ftnlen)40);
	if (found) {
	    prefix_("# (", &c__0, tname, (ftnlen)3, (ftnlen)40);
	    suffix_(")", &c__0, tname, (ftnlen)1, (ftnlen)40);
	    repmi_(tname, "#", targ, tname, (ftnlen)40, (ftnlen)1, (ftnlen)40)
		    ;
	} else {
	    intstr_(targ, tname, (ftnlen)40);
	}
	bodc2n_(obs, oname, &found, (ftnlen)40);
	if (found) {
	    prefix_("# (", &c__0, oname, (ftnlen)3, (ftnlen)40);
	    suffix_(")", &c__0, oname, (ftnlen)1, (ftnlen)40);
	    repmi_(oname, "#", obs, oname, (ftnlen)40, (ftnlen)1, (ftnlen)40);
	} else {
	    intstr_(obs, oname, (ftnlen)40);
	}
	setmsg_("Insufficient ephemeris data has been loaded to compute the "
		"state of TARG relative to OBS at the ephemeris epoch #. ", (
		ftnlen)115);
	etcal_(et, tstring, (ftnlen)80);
	errch_("TARG", tname, (ftnlen)4, (ftnlen)40);
	errch_("OBS", oname, (ftnlen)3, (ftnlen)40);
	errch_("#", tstring, (ftnlen)1, (ftnlen)80);
	sigerr_("SPICE(SPKINSUFFDATA)", (ftnlen)20);
	chkout_("ZZSPKGO0", (ftnlen)8);
	return 0;
    }

/*     If CTPOS is not zero, then we have reached a */
/*     common node, specifically, */

/*        CTARG(CTPOS) = COBS = CENTER */

/*     (in diagram below).  The STATE of the target */
/*     (TARG) relative to the observer (OBS) is just */

/*        STARG(1,CTPOS) - SOBS. */



/*                     SOBS */
/*         CENTER ---------------->OBS */
/*            |                  . */
/*            |                . */
/*         S  |              .   E */
/*         T  |            .   T */
/*         A  |          .   A */
/*         R  |        .   T */
/*         G  |      .   S */
/*            |    . */
/*            |  . */
/*            V L */
/*           TARG */


/*     And the light-time between them is just */

/*               | STATE | */
/*          LT = --------- */
/*                   c */


/*     Compute the state of the target relative to CTARG(CTPOS) */

    if (ctpos == 1) {
	tframe[0] = cframe;
    }
    i__1 = ctpos - 1;
    for (i__ = 2; i__ <= i__1; ++i__) {
	if (tframe[(i__2 = i__ - 1) < 20 && 0 <= i__2 ? i__2 : s_rnge("tframe"
		, i__2, "zzspkgo0_", (ftnlen)890)] == tframe[(i__3 = i__) < 
		20 && 0 <= i__3 ? i__3 : s_rnge("tframe", i__3, "zzspkgo0_", (
		ftnlen)890)]) {
	    vaddg_(&starg[(i__2 = i__ * 6 - 6) < 120 && 0 <= i__2 ? i__2 : 
		    s_rnge("starg", i__2, "zzspkgo0_", (ftnlen)892)], &starg[(
		    i__3 = (i__ + 1) * 6 - 6) < 120 && 0 <= i__3 ? i__3 : 
		    s_rnge("starg", i__3, "zzspkgo0_", (ftnlen)892)], &c__6, 
		    vtemp);
	    moved_(vtemp, &c__6, &starg[(i__2 = (i__ + 1) * 6 - 6) < 120 && 0 
		    <= i__2 ? i__2 : s_rnge("starg", i__2, "zzspkgo0_", (
		    ftnlen)893)]);
	} else if (tframe[(i__3 = i__) < 20 && 0 <= i__3 ? i__3 : s_rnge(
		"tframe", i__3, "zzspkgo0_", (ftnlen)895)] > 0 && tframe[(
		i__3 = i__) < 20 && 0 <= i__3 ? i__3 : s_rnge("tframe", i__3, 
		"zzspkgo0_", (ftnlen)895)] <= 21 && tframe[(i__2 = i__ - 1) < 
		20 && 0 <= i__2 ? i__2 : s_rnge("tframe", i__2, "zzspkgo0_", (
		ftnlen)895)] > 0 && tframe[(i__2 = i__ - 1) < 20 && 0 <= i__2 
		? i__2 : s_rnge("tframe", i__2, "zzspkgo0_", (ftnlen)895)] <= 
		21) {
	    irfrot_(&tframe[(i__2 = i__ - 1) < 20 && 0 <= i__2 ? i__2 : 
		    s_rnge("tframe", i__2, "zzspkgo0_", (ftnlen)897)], &
		    tframe[(i__3 = i__) < 20 && 0 <= i__3 ? i__3 : s_rnge(
		    "tframe", i__3, "zzspkgo0_", (ftnlen)897)], rot);
	    mxv_(rot, &starg[(i__2 = i__ * 6 - 6) < 120 && 0 <= i__2 ? i__2 : 
		    s_rnge("starg", i__2, "zzspkgo0_", (ftnlen)898)], stemp);
	    mxv_(rot, &starg[(i__2 = i__ * 6 - 3) < 120 && 0 <= i__2 ? i__2 : 
		    s_rnge("starg", i__2, "zzspkgo0_", (ftnlen)899)], &stemp[
		    3]);
	    vaddg_(stemp, &starg[(i__2 = (i__ + 1) * 6 - 6) < 120 && 0 <= 
		    i__2 ? i__2 : s_rnge("starg", i__2, "zzspkgo0_", (ftnlen)
		    900)], &c__6, vtemp);
	    moved_(vtemp, &c__6, &starg[(i__2 = (i__ + 1) * 6 - 6) < 120 && 0 
		    <= i__2 ? i__2 : s_rnge("starg", i__2, "zzspkgo0_", (
		    ftnlen)901)]);
	} else {
	    zzfrmch0_(&tframe[(i__2 = i__ - 1) < 20 && 0 <= i__2 ? i__2 : 
		    s_rnge("tframe", i__2, "zzspkgo0_", (ftnlen)905)], &
		    tframe[(i__3 = i__) < 20 && 0 <= i__3 ? i__3 : s_rnge(
		    "tframe", i__3, "zzspkgo0_", (ftnlen)905)], et, stxfrm);
	    if (failed_()) {
		chkout_("ZZSPKGO0", (ftnlen)8);
		return 0;
	    }
	    mxvg_(stxfrm, &starg[(i__2 = i__ * 6 - 6) < 120 && 0 <= i__2 ? 
		    i__2 : s_rnge("starg", i__2, "zzspkgo0_", (ftnlen)912)], &
		    c__6, &c__6, stemp);
	    vaddg_(stemp, &starg[(i__2 = (i__ + 1) * 6 - 6) < 120 && 0 <= 
		    i__2 ? i__2 : s_rnge("starg", i__2, "zzspkgo0_", (ftnlen)
		    913)], &c__6, vtemp);
	    moved_(vtemp, &c__6, &starg[(i__2 = (i__ + 1) * 6 - 6) < 120 && 0 
		    <= i__2 ? i__2 : s_rnge("starg", i__2, "zzspkgo0_", (
		    ftnlen)914)]);
	}
    }

/*     To avoid unnecessary frame transformations we'll do */
/*     a bit of extra decision making here.  It's a lot */
/*     faster to make logical checks than it is to compute */
/*     frame transformations. */

    if (tframe[(i__1 = ctpos - 1) < 20 && 0 <= i__1 ? i__1 : s_rnge("tframe", 
	    i__1, "zzspkgo0_", (ftnlen)927)] == cframe) {
	vsubg_(&starg[(i__1 = ctpos * 6 - 6) < 120 && 0 <= i__1 ? i__1 : 
		s_rnge("starg", i__1, "zzspkgo0_", (ftnlen)929)], sobs, &c__6,
		 state);
    } else if (tframe[(i__1 = ctpos - 1) < 20 && 0 <= i__1 ? i__1 : s_rnge(
	    "tframe", i__1, "zzspkgo0_", (ftnlen)931)] == refid) {

/*        If the last frame associated with the target is already */
/*        in the requested output frame, we convert the state of */
/*        the observer to that frame and then subtract the state */
/*        of the observer from the state of the target. */

	if (refid > 0 && refid <= 21 && cframe > 0 && cframe <= 21) {
	    irfrot_(&cframe, &refid, rot);
	    mxv_(rot, sobs, stemp);
	    mxv_(rot, &sobs[3], &stemp[3]);
	} else {
	    zzfrmch0_(&cframe, &refid, et, stxfrm);
	    if (failed_()) {
		chkout_("ZZSPKGO0", (ftnlen)8);
		return 0;
	    }
	    mxvg_(stxfrm, sobs, &c__6, &c__6, stemp);
	}

/*        We've now transformed SOBS into the requested reference frame. */
/*        Set CFRAME to reflect this. */

	cframe = refid;
	vsubg_(&starg[(i__1 = ctpos * 6 - 6) < 120 && 0 <= i__1 ? i__1 : 
		s_rnge("starg", i__1, "zzspkgo0_", (ftnlen)963)], stemp, &
		c__6, state);
    } else if (cframe > 0 && cframe <= 21 && tframe[(i__1 = ctpos - 1) < 20 &&
	     0 <= i__1 ? i__1 : s_rnge("tframe", i__1, "zzspkgo0_", (ftnlen)
	    966)] > 0 && tframe[(i__1 = ctpos - 1) < 20 && 0 <= i__1 ? i__1 : 
	    s_rnge("tframe", i__1, "zzspkgo0_", (ftnlen)966)] <= 21) {

/*        If both frames are inertial we use IRFROT instead of */
/*        ZZFRMCH0 to get things into a common frame. */

	irfrot_(&tframe[(i__1 = ctpos - 1) < 20 && 0 <= i__1 ? i__1 : s_rnge(
		"tframe", i__1, "zzspkgo0_", (ftnlen)972)], &cframe, rot);
	mxv_(rot, &starg[(i__1 = ctpos * 6 - 6) < 120 && 0 <= i__1 ? i__1 : 
		s_rnge("starg", i__1, "zzspkgo0_", (ftnlen)973)], stemp);
	mxv_(rot, &starg[(i__1 = ctpos * 6 - 3) < 120 && 0 <= i__1 ? i__1 : 
		s_rnge("starg", i__1, "zzspkgo0_", (ftnlen)974)], &stemp[3]);
	vsubg_(stemp, sobs, &c__6, state);
    } else {

/*        Use the more general routine ZZFRMCH0 to make the */
/*        transformation. */

	zzfrmch0_(&tframe[(i__1 = ctpos - 1) < 20 && 0 <= i__1 ? i__1 : 
		s_rnge("tframe", i__1, "zzspkgo0_", (ftnlen)982)], &cframe, 
		et, stxfrm);
	if (failed_()) {
	    chkout_("ZZSPKGO0", (ftnlen)8);
	    return 0;
	}
	mxvg_(stxfrm, &starg[(i__1 = ctpos * 6 - 6) < 120 && 0 <= i__1 ? i__1 
		: s_rnge("starg", i__1, "zzspkgo0_", (ftnlen)989)], &c__6, &
		c__6, stemp);
	vsubg_(stemp, sobs, &c__6, state);
    }

/*     Finally, rotate as needed into the requested frame. */

    if (cframe == refid) {

/*        We don't have to do anything in this case. */

    } else if (refid > 0 && refid <= 21 && cframe > 0 && cframe <= 21) {

/*        Since both frames are inertial, we use the more direct */
/*        routine IRFROT to get the transformation to REFID. */

	irfrot_(&cframe, &refid, rot);
	mxv_(rot, state, stemp);
	mxv_(rot, &state[3], &stemp[3]);
	moved_(stemp, &c__6, state);
    } else {
	zzfrmch0_(&cframe, &refid, et, stxfrm);
	if (failed_()) {
	    chkout_("ZZSPKGO0", (ftnlen)8);
	    return 0;
	}
	mxvg_(stxfrm, state, &c__6, &c__6, stemp);
	moved_(stemp, &c__6, state);
    }
    *lt = vnorm_(state) / clight_();
    chkout_("ZZSPKGO0", (ftnlen)8);
    return 0;
} /* zzspkgo0_ */
Esempio n. 2
0
/* $Procedure SPKE10 ( Evaluate SPK record, type 10 ) */
/* Subroutine */ int spke10_(doublereal *et, doublereal *record, doublereal *
	state)
{
    /* Initialized data */

    static logical first = TRUE_;

    /* System generated locals */
    doublereal d__1;

    /* Builtin functions */
    double cos(doublereal), sin(doublereal);

    /* Local variables */
    extern /* Subroutine */ int vadd_(doublereal *, doublereal *, doublereal *
	    );
    static doublereal dwdt, mypi;
    extern /* Subroutine */ int vequ_(doublereal *, doublereal *), mxvg_(
	    doublereal *, doublereal *, integer *, integer *, doublereal *);
    static doublereal my2pi, w;
    extern /* Subroutine */ int chkin_(char *, ftnlen);
    static doublereal denom, precm[36]	/* was [6][6] */;
    extern /* Subroutine */ int moved_(doublereal *, integer *, doublereal *),
	     vlcom_(doublereal *, doublereal *, doublereal *, doublereal *, 
	    doublereal *);
    static doublereal vcomp[3], numer, n0;
    extern doublereal twopi_(void);
    static doublereal s1[6], s2[6], t1, t2;
    extern /* Subroutine */ int ev2lin_(doublereal *, doublereal *, 
	    doublereal *, doublereal *);
    extern doublereal pi_(void);
    static doublereal dargdt;
    extern /* Subroutine */ int dpspce_(doublereal *, doublereal *, 
	    doublereal *, doublereal *);
    static doublereal mnrate;
    extern /* Subroutine */ int vlcomg_(integer *, doublereal *, doublereal *,
	     doublereal *, doublereal *, doublereal *), chkout_(char *, 
	    ftnlen);
    static doublereal invprc[36]	/* was [6][6] */;
    static logical loworb;
    static doublereal tmpsta[6];
    extern /* Subroutine */ int zzteme_(doublereal *, doublereal *);
    extern logical return_(void);
    extern /* Subroutine */ int invstm_(doublereal *, doublereal *);
    static doublereal arg;

/* $ Abstract */

/*     Evaluate a single SPK data record from a segment of type 10 */
/*     (NORAD two-line element sets.). */

/* $ 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 */

/*     SPK */

/* $ Keywords */

/*     EPHEMERIS */

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

/*     Variable  I/O  Description */
/*     --------  ---  -------------------------------------------------- */
/*     ET         I   Target epoch. */
/*     RECORD     I   Data record. */
/*     STATE      O   State (position and velocity). */

/* $ Detailed_Input */

/*     ET          is a target epoch, specified as ephemeris seconds past */
/*                 J2000, at which a state vector is to be computed. */

/*     RECORD      is a data record which, when evaluated at epoch ET, */
/*                 will give the state (position and velocity) of some */
/*                 body, relative to some center, in some inertial */
/*                 reference frame. */

/*                 The structure of RECORD is: */

/*                     RECORD(1) */
/*                        .            Geophysical Constants such as */
/*                        .            GM, J2, J3, J4, etc. */
/*                        . */
/*                     RECORD(NGEOCN) */

/*                     RECORD(NGEOCN + 1) */
/*                        . */
/*                        .            elements and epoch for the body */
/*                        .            at epoch 1. */
/*                        . */
/*                     RECORD(NGEOCN + NELEMN ) */

/*                     RECORD(NGEOCN + NELEMN + 1) */
/*                        . */
/*                        .            elements and epoch for the body */
/*                        .            at epoch 2. */
/*                        . */
/*                     RECORD(NGEOCN + 2*NELEMN ) */

/*                 Epoch 1 and epoch 2 are the times in the segment that */
/*                 bracket ET.  If ET is less than the first time in the */
/*                 segment then both epochs 1 and 2 are equal to the */
/*                 first time.  And if ET is greater than the last time */
/*                 then, epochs 1 and 2 are set equal to this last time. */

/* $ Detailed_Output */

/*     STATE       is the state produced by evaluating RECORD at ET. */
/*                 Units are km and km/sec. */

/* $ Parameters */

/*     None. */

/* $ Exceptions */

/*     1) If there is a problem evaluating the two-line elements, */
/*     the error will be diagnosed by EV2LIN. */

/* $ Files */

/*     None. */

/* $ Particulars */

/*     This routine interpolates a state from the two reference sets */
/*     of two-line element sets contained in RECORD. */

/*     It is assumed that this routine is used in conjunction with */
/*     the routine SPKR10 as shown here: */

/*        CALL SPKR10 ( HANDLE, DESCR, ET, RECORD         ) */
/*        CALL SPKE10 (                ET, RECORD, STATE  ) */

/*     Where it is known in advance that the HANDLE, DESCR pair points */
/*     to a type 10 data segment. */

/* $ Examples */

/*     The SPKEnn routines are almost always used in conjunction with */
/*     the corresponding SPKRnn routines, which read the records from */
/*     SPK files. */

/*     The data returned by the SPKRnn routine is in its rawest form, */
/*     taken directly from the segment.  As such, it will be meaningless */
/*     to a user unless he/she understands the structure of the data type */
/*     completely.  Given that understanding, however, the SPKRnn */
/*     routines might be used to examine raw segment data before */
/*     evaluating it with the SPKEnn routines. */


/*     C */
/*     C     Get a segment applicable to a specified body and epoch. */
/*     C */
/*           CALL SPKSFS ( BODY, ET, HANDLE, DESCR, IDENT, FOUND ) */

/*     C */
/*     C     Look at parts of the descriptor. */
/*     C */
/*           CALL DAFUS ( DESCR, 2, 6, DCD, ICD ) */
/*           CENTER = ICD( 2 ) */
/*           REF    = ICD( 3 ) */
/*           TYPE   = ICD( 4 ) */

/*           IF ( TYPE .EQ. 10 ) THEN */

/*              CALL SPKR10 ( HANDLE, DESCR, ET, RECORD ) */
/*                  . */
/*                  .  Look at the RECORD data. */
/*                  . */
/*              CALL SPKE10 ( ET, RECORD, STATE ) */
/*                  . */
/*                  .  Check out the evaluated state. */
/*                  . */
/*           END IF */

/* $ Restrictions */

/*     None. */

/* $ Literature_References */

/*     None. */

/* $ Author_and_Institution */

/*     N.J. Bachman    (JPL) */
/*     W.L. Taber      (JPL) */

/* $ Version */

/* -    SPICELIB Version 2.0.0, 01-JAN-2011 (EDW) */

/*        Correction of state transformation calculation. Algorithm */
/*        now computes state transformation as from TEME to J2000. */
/*        The previous version of this routine calculated TETE to */
/*        J2000. */

/* -    SPICELIB Version 1.1.0, 01-SEP-2005 (NJB) */

/*        Updated to remove non-standard use of duplicate arguments */
/*        in MTXV and VADD calls. */

/* -    SPICELIB Version 1.0.0 18-JUL-1997 (WLT) */

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

/*     evaluate type_10 spk segment */

/* -& */

/*     SPICELIB functions */


/*     Local Parameters */



/*     The following parameters give the location of the various */
/*     geophysical parameters needed for the two line element */
/*     sets.  We need these only so that we can count how many there */
/*     are (NGEOCN). */

/*     KJ2  --- location of J2 */
/*     KJ3  --- location of J3 */
/*     KJ4  --- location if J4 */
/*     KKE  --- location of KE = sqrt(GM) in earth-radii**1.5/MIN */
/*     KQO  --- upper bound of atmospheric model in KM */
/*     KSO  --- lower bound of atmospheric model in KM */
/*     KER  --- earth equatorial radius in KM. */
/*     KAE  --- distance units/earth radius */


/*     An enumeration of the various components of the */
/*     a two-line element set.  These are needed so that we */
/*     can locate the epochs in the two sets and so that */
/*     we can count the number of elements in a two-line */
/*     element set. */

/*     KNDT20 */
/*     KNDD60 */
/*     KBSTAR */
/*     KINCL */
/*     KNODE0 */
/*     KECC */
/*     KOMEGA */
/*     KMO */
/*     KNO */
/*     KEPOCH */


/*     The nutation in obliquity and longitude as well as their rates */
/*     follow the elements.  So we've got four angles/angle rates */
/*     following the elements */


/*     The locations of the epochs and the starts of the element */
/*     sets are given below. */


/*     Local variables */


/*     Standard SPICE error handling. */

    if (return_()) {
	return 0;
    } else {
	chkin_("SPKE10", (ftnlen)6);
    }
    if (first) {
	first = FALSE_;
	mypi = pi_();
	my2pi = twopi_();
    }

/*     Fetch the mean motion from the first set of two-line elements */
/*     stored in the record. */

    n0 = record[16];
    mnrate = my2pi / 225.;
    loworb = n0 >= mnrate;

/*     Fetch the two epochs stored in the record. */

    t1 = record[17];
    t2 = record[31];

/*     Evaluate the two states. Call them s_1(t) and s_2(t). */
/*     Let the position and velocity components be: p_1, v_1, p_2, v_2. */

/*     The final position is a weighted average. */

/*     Let */

/*        W(t) =  0.5 + 0.5*COS( PI*(t-t1)/(t2-t1) ) */

/*     then */

/*        p  = W(t)*p_1(t) + (1 - W(t))*p_2(t) */
/*        v  = W(t)*v_1(t) + (1 - W(t))*v_2(t) + W'(t)*(p_1(t) - p_2(t)) */

/*     If t1 = t2, the state is just s(t1). */


/*     Note: there are a number of weighting schemes we could have */
/*     used.  This one has the nice property that */

/*     The graph of W is symmetric about the point */


/*        ( (t1+t2)/2,  W( (t1+t2)/2 ) ) */

/*     The range of W is from 1 to 0. The derivative of W is */
/*     symmetric and zero at both t1 and t2. */

    if (t1 != t2) {
	if (loworb) {
	    ev2lin_(et, record, &record[8], s1);
	    ev2lin_(et, record, &record[22], s2);
	} else {
	    dpspce_(et, record, &record[8], s1);
	    dpspce_(et, record, &record[22], s2);
	}

/*        Compute the weighting function that we'll need later */
/*        when we combine states 1 and 2. */

	numer = *et - t1;
	denom = t2 - t1;
	arg = numer * mypi / denom;
	dargdt = mypi / denom;
	w = cos(arg) * .5 + .5;
	dwdt = sin(arg) * -.5 * dargdt;

/*        Now compute the weighted average of the two states. */

	d__1 = 1. - w;
	vlcomg_(&c__6, &w, s1, &d__1, s2, state);
	d__1 = -dwdt;
	vlcom_(&dwdt, s1, &d__1, s2, vcomp);
	vadd_(&state[3], vcomp, &tmpsta[3]);
	vequ_(&tmpsta[3], &state[3]);
    } else {
	if (loworb) {
	    ev2lin_(et, record, &record[8], state);
	} else {
	    dpspce_(et, record, &record[8], state);
	}
    }

/*     Finally, convert the TEME state to J2000.  First get */
/*     the rotation from J2000 to TEME... */

    zzteme_(et, precm);

/*     ...now convert STATE to J2000. Invert the state transformation */
/*     operator (important to correctly do this). */

    invstm_(precm, invprc);

/*     Map STATE to the corresponding expression in J2000. */

    mxvg_(invprc, state, &c__6, &c__6, tmpsta);
    moved_(tmpsta, &c__6, state);
    chkout_("SPKE10", (ftnlen)6);
    return 0;
} /* spke10_ */
Esempio n. 3
0
/* $Procedure      ZZGFSSOB ( GF, state of sub-observer point ) */
/* Subroutine */ int zzgfssob_(char *method, integer *trgid, doublereal *et, 
	char *fixref, char *abcorr, integer *obsid, doublereal *radii, 
	doublereal *state, ftnlen method_len, ftnlen fixref_len, ftnlen 
	abcorr_len)
{
    /* Initialized data */

    static logical first = TRUE_;
    static integer prvobs = 0;
    static integer prvtrg = 0;
    static char svobs[36] = "                                    ";
    static char svtarg[36] = "                                    ";

    /* System generated locals */
    integer i__1;

    /* Builtin functions */
    integer s_rnge(char *, integer, char *, integer);

    /* Local variables */
    doublereal dalt[2];
    logical near__, geom;
    extern /* Subroutine */ int vhat_(doublereal *, doublereal *), vscl_(
	    doublereal *, doublereal *, doublereal *);
    extern doublereal vdot_(doublereal *, doublereal *);
    logical xmit;
    extern /* Subroutine */ int mxvg_(doublereal *, doublereal *, integer *, 
	    integer *, doublereal *);
    doublereal upos[3];
    extern /* Subroutine */ int zzstelab_(logical *, doublereal *, doublereal 
	    *, doublereal *, doublereal *, doublereal *), zzcorsxf_(logical *,
	     doublereal *, doublereal *, doublereal *);
    integer i__;
    extern /* Subroutine */ int zzprscor_(char *, logical *, ftnlen);
    doublereal t;
    extern /* Subroutine */ int vaddg_(doublereal *, doublereal *, integer *, 
	    doublereal *);
    doublereal scale;
    extern /* Subroutine */ int chkin_(char *, ftnlen), errch_(char *, char *,
	     ftnlen, ftnlen);
    doublereal savel[3];
    logical found;
    extern /* Subroutine */ int moved_(doublereal *, integer *, doublereal *),
	     vsubg_(doublereal *, doublereal *, integer *, doublereal *);
    doublereal stemp[6];
    extern logical eqstr_(char *, char *, ftnlen, ftnlen);
    doublereal xform[36]	/* was [6][6] */;
    logical uselt;
    extern /* Subroutine */ int bodc2s_(integer *, char *, ftnlen);
    doublereal ssbtg0[6];
    extern logical failed_(void);
    doublereal sa[3];
    extern /* Subroutine */ int cleard_(integer *, doublereal *);
    doublereal lt;
    integer frcode;
    extern doublereal clight_(void);
    extern logical return_(void);
    doublereal corxfi[36]	/* was [6][6] */, corxfm[36]	/* was [6][6] 
	    */, fxosta[6], fxpsta[6], fxpvel[3], fxtsta[6], obspnt[6], obssta[
	    12]	/* was [6][2] */, obstrg[6], acc[3], pntsta[6], raysta[6], 
	    sastat[6], spoint[3], srfvec[3], ssbobs[6], ssbtrg[6], trgepc;
    integer center, clssid, frclss;
    logical attblk[6], usestl;
    extern /* Subroutine */ int setmsg_(char *, ftnlen);
    logical fnd;
    extern /* Subroutine */ int sigerr_(char *, ftnlen), chkout_(char *, 
	    ftnlen), namfrm_(char *, integer *, ftnlen), frinfo_(integer *, 
	    integer *, integer *, integer *, logical *), errint_(char *, 
	    integer *, ftnlen), spkgeo_(integer *, doublereal *, char *, 
	    integer *, doublereal *, doublereal *, ftnlen), vminug_(
	    doublereal *, integer *, doublereal *), dnearp_(doublereal *, 
	    doublereal *, doublereal *, doublereal *, doublereal *, 
	    doublereal *, logical *), surfpv_(doublereal *, doublereal *, 
	    doublereal *, doublereal *, doublereal *, doublereal *, logical *)
	    , subpnt_(char *, char *, doublereal *, char *, char *, char *, 
	    doublereal *, doublereal *, doublereal *, ftnlen, ftnlen, ftnlen, 
	    ftnlen, ftnlen), spkssb_(integer *, doublereal *, char *, 
	    doublereal *, ftnlen);
    doublereal dlt;
    extern /* Subroutine */ int sxform_(char *, char *, doublereal *, 
	    doublereal *, ftnlen, ftnlen), qderiv_(integer *, doublereal *, 
	    doublereal *, doublereal *, doublereal *), invstm_(doublereal *, 
	    doublereal *);

/* $ Abstract */

/*     SPICE private routine intended solely for the support of SPICE */
/*     routines. Users should not call this routine directly due to the */
/*     volatile nature of this routine. */

/*     Return the state of a sub-observer point used to define */
/*     coordinates referenced in a GF search. */

/* $ 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 */

/*     GF */
/*     SPK */
/*     TIME */
/*     NAIF_IDS */
/*     FRAMES */

/* $ Keywords */

/*     GEOMETRY */
/*     PRIVATE */
/*     SEARCH */

/* $ Declarations */
/* $ Abstract */

/*     This file contains public, global parameter declarations */
/*     for the SPICELIB Geometry Finder (GF) subsystem. */

/* $ 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 */

/*     GF */

/* $ Keywords */

/*     GEOMETRY */
/*     ROOT */

/* $ Restrictions */

/*     None. */

/* $ Author_and_Institution */

/*     N.J. Bachman      (JPL) */
/*     L.E. Elson        (JPL) */
/*     E.D. Wright       (JPL) */

/* $ Literature_References */

/*     None. */

/* $ Version */

/* -    SPICELIB Version 1.3.0, 01-OCT-2011 (NJB) */

/*       Added NWILUM parameter. */

/* -    SPICELIB Version 1.2.0, 14-SEP-2010 (EDW) */

/*       Added NWPA parameter. */

/* -    SPICELIB Version 1.1.0, 08-SEP-2009 (EDW) */

/*       Added NWRR parameter. */
/*       Added NWUDS parameter. */

/* -    SPICELIB Version 1.0.0, 21-FEB-2009 (NJB) (LSE) (EDW) */

/* -& */

/*     Root finding parameters: */

/*     CNVTOL is the default convergence tolerance used by the */
/*     high-level GF search API routines. This tolerance is */
/*     used to terminate searches for binary state transitions: */
/*     when the time at which a transition occurs is bracketed */
/*     by two times that differ by no more than CNVTOL, the */
/*     transition time is considered to have been found. */

/*     Units are TDB seconds. */


/*     NWMAX is the maximum number of windows allowed for user-defined */
/*     workspace array. */

/*        DOUBLE PRECISION      WORK   ( LBCELL : MW, NWMAX ) */

/*     Currently no more than twelve windows are required; the three */
/*     extra windows are spares. */

/*     Callers of GFEVNT can include this file and use the parameter */
/*     NWMAX to declare the second dimension of the workspace array */
/*     if necessary. */


/*     Callers of GFIDST should declare their workspace window */
/*     count using NWDIST. */


/*     Callers of GFSEP should declare their workspace window */
/*     count using NWSEP. */


/*     Callers of GFRR should declare their workspace window */
/*     count using NWRR. */


/*     Callers of GFUDS should declare their workspace window */
/*     count using NWUDS. */


/*     Callers of GFPA should declare their workspace window */
/*     count using NWPA. */


/*     Callers of GFILUM should declare their workspace window */
/*     count using NWILUM. */


/*     ADDWIN is a parameter used to expand each interval of the search */
/*     (confinement) window by a small amount at both ends in order to */
/*     accommodate searches using equality constraints. The loaded */
/*     kernel files must accommodate these expanded time intervals. */


/*     FRMNLN is a string length for frame names. */


/*     NVRMAX is the maximum number of vertices if FOV type is "POLYGON" */


/*     FOVTLN -- maximum length for FOV string. */


/*     Specify the character strings that are allowed in the */
/*     specification of field of view shapes. */


/*     Character strings that are allowed in the */
/*     specification of occultation types: */


/*     Occultation target shape specifications: */


/*     Specify the number of supported occultation types and occultation */
/*     type string length: */


/*     Instrument field-of-view (FOV) parameters */

/*     Maximum number of FOV boundary vectors: */


/*     FOV shape parameters: */

/*        circle */
/*        ellipse */
/*        polygon */
/*        rectangle */


/*     End of file gf.inc. */

/* $ Abstract */

/*     SPICE private include file intended solely for the support of */
/*     SPICE routines. Users should not include this routine in their */
/*     source code due to the volatile nature of this file. */

/*     This file contains private, global parameter declarations */
/*     for the SPICELIB Geometry Finder (GF) subsystem. */

/* $ 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 */

/*     GF */

/* $ Keywords */

/*     GEOMETRY */
/*     ROOT */

/* $ Restrictions */

/*     None. */

/* $ Author_and_Institution */

/*     N.J. Bachman      (JPL) */
/*     E.D. Wright       (JPL) */

/* $ Literature_References */

/*     None. */

/* $ Version */

/* -    SPICELIB Version 1.0.0, 17-FEB-2009 (NJB) (EDW) */

/* -& */

/*     The set of supported coordinate systems */

/*        System          Coordinates */
/*        ----------      ----------- */
/*        Rectangular     X, Y, Z */
/*        Latitudinal     Radius, Longitude, Latitude */
/*        Spherical       Radius, Colatitude, Longitude */
/*        RA/Dec          Range, Right Ascension, Declination */
/*        Cylindrical     Radius, Longitude, Z */
/*        Geodetic        Longitude, Latitude, Altitude */
/*        Planetographic  Longitude, Latitude, Altitude */

/*     Below we declare parameters for naming coordinate systems. */
/*     User inputs naming coordinate systems must match these */
/*     when compared using EQSTR. That is, user inputs must */
/*     match after being left justified, converted to upper case, */
/*     and having all embedded blanks removed. */


/*     Below we declare names for coordinates. Again, user */
/*     inputs naming coordinates must match these when */
/*     compared using EQSTR. */


/*     Note that the RA parameter value below matches */

/*        'RIGHT ASCENSION' */

/*     when extra blanks are compressed out of the above value. */


/*     Parameters specifying types of vector definitions */
/*     used for GF coordinate searches: */

/*     All string parameter values are left justified, upper */
/*     case, with extra blanks compressed out. */

/*     POSDEF indicates the vector is defined by the */
/*     position of a target relative to an observer. */


/*     SOBDEF indicates the vector points from the center */
/*     of a target body to the sub-observer point on */
/*     that body, for a given observer and target. */


/*     SOBDEF indicates the vector points from the center */
/*     of a target body to the surface intercept point on */
/*     that body, for a given observer, ray, and target. */


/*     Number of workspace windows used by ZZGFREL: */


/*     Number of additional workspace windows used by ZZGFLONG: */


/*     Index of "existence window" used by ZZGFCSLV: */


/*     Progress report parameters: */

/*     MXBEGM, */
/*     MXENDM    are, respectively, the maximum lengths of the progress */
/*               report message prefix and suffix. */

/*     Note: the sum of these lengths, plus the length of the */
/*     "percent complete" substring, should not be long enough */
/*     to cause wrap-around on any platform's terminal window. */


/*     Total progress report message length upper bound: */


/*     End of file zzgf.inc. */

/* $ Abstract */

/*     Include file zzabcorr.inc */

/*     SPICE private file intended solely for the support of SPICE */
/*     routines.  Users should not include this file directly due */
/*     to the volatile nature of this file */

/*     The parameters below define the structure of an aberration */
/*     correction attribute block. */

/* $ 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. */

/* $ Parameters */

/*     An aberration correction attribute block is an array of logical */
/*     flags indicating the attributes of the aberration correction */
/*     specified by an aberration correction string.  The attributes */
/*     are: */

/*        - Is the correction "geometric"? */

/*        - Is light time correction indicated? */

/*        - Is stellar aberration correction indicated? */

/*        - Is the light time correction of the "converged */
/*          Newtonian" variety? */

/*        - Is the correction for the transmission case? */

/*        - Is the correction relativistic? */

/*    The parameters defining the structure of the block are as */
/*    follows: */

/*       NABCOR    Number of aberration correction choices. */

/*       ABATSZ    Number of elements in the aberration correction */
/*                 block. */

/*       GEOIDX    Index in block of geometric correction flag. */

/*       LTIDX     Index of light time flag. */

/*       STLIDX    Index of stellar aberration flag. */

/*       CNVIDX    Index of converged Newtonian flag. */

/*       XMTIDX    Index of transmission flag. */

/*       RELIDX    Index of relativistic flag. */

/*    The following parameter is not required to define the block */
/*    structure, but it is convenient to include it here: */

/*       CORLEN    The maximum string length required by any aberration */
/*                 correction string */

/* $ Author_and_Institution */

/*     N.J. Bachman    (JPL) */

/* $ Literature_References */

/*     None. */

/* $ Version */

/* -    SPICELIB Version 1.0.0, 18-DEC-2004 (NJB) */

/* -& */
/*     Number of aberration correction choices: */


/*     Aberration correction attribute block size */
/*     (number of aberration correction attributes): */


/*     Indices of attributes within an aberration correction */
/*     attribute block: */


/*     Maximum length of an aberration correction string: */


/*     End of include file zzabcorr.inc */

/* $ Brief_I/O */

/*     VARIABLE  I/O  DESCRIPTION */
/*     --------  ---  -------------------------------------------------- */
/*     METHOD     I   Computation method. */
/*     TRGID      I   Target ID code. */
/*     ET         I   Computation epoch. */
/*     FIXREF     I   Reference frame name. */
/*     ABCORR     I   Aberration correction. */
/*     OBSID      I   Observer ID code. */
/*     RADII      I   Target radii. */
/*     STATE      O   State used to define coordinates. */

/* $ Detailed_Input */

/*     METHOD      is a short string providing parameters defining */
/*                 the computation method to be used. Any value */
/*                 supported by SUBPNT may be used. */


/*     TRGID      is the NAIF ID code of the target object. */

/*                *This routine assumes that the target is modeled */
/*                as a tri-axial ellipsoid.* */


/*     ET         is the time, expressed as ephemeris seconds past J2000 */
/*                TDB, at which the specified state is to be computed. */


/*     FIXREF     is the name of the reference frame relative to which */
/*                the state of interest is specified. */

/*                FIXREF must be centered on the target body. */

/*                Case, leading and trailing blanks are not significant */
/*                in the string FIXREF. */


/*     ABCORR     indicates the aberration corrections to be applied to */
/*                the state of the target body to account for one-way */
/*                light time and stellar aberration. The orientation */
/*                of the target body will also be corrected for one-way */
/*                light time when light time corrections are requested. */

/*                Supported aberration correction options for */
/*                observation (case where radiation is received by */
/*                observer at ET) are: */

/*                   NONE           No correction. */
/*                   LT             Light time only. */
/*                   LT+S           Light time and stellar aberration. */
/*                   CN             Converged Newtonian (CN) light time. */
/*                   CN+S           CN light time and stellar aberration. */

/*                Supported aberration correction options for */
/*                transmission (case where radiation is emitted from */
/*                observer at ET) are: */

/*                   XLT            Light time only. */
/*                   XLT+S          Light time and stellar aberration. */
/*                   XCN            Converged Newtonian (CN) light time. */
/*                   XCN+S          CN light time and stellar aberration. */

/*                For detailed information, see the geometry finder */
/*                required reading, gf.req.  Also see the header of */
/*                SPKEZR, which contains a detailed discussion of */
/*                aberration corrections. */

/*                Case, leading and trailing blanks are not significant */
/*                in the string ABCORR. */


/*     OBSID      is the NAIF ID code of the observer. */


/*     RADII      is an array containing three radii defining */
/*                a reference ellipsoid for the target body. */

/* $ Detailed_Output */

/*     STATE     is the state of the sub-observer point at ET. */
/*               The first three components of STATE contain the */
/*               sub-observer point itself; the last three */
/*               components contain the derivative with respect to */
/*               time of the position. The state is expressed */
/*               relative to the body-fixed frame designated by */
/*               FIXREF. */

/*               Units are km and km/s. */

/* $ Parameters */

/*     None. */

/* $ Exceptions */

/*     1)  If the aberration correction ABCORR is not recognized, */
/*         the error will be diagnosed by routines in the call tree */
/*         of this routine. */

/*     2)  If the frame FIXREF is not recognized by the frames */
/*         subsystem, the error will be diagnosed by routines in the */
/*         call tree of this routine. */

/*     3)  FIXREF must be centered on the target body; if it isn't, */
/*         the error will be diagnosed by routines in the call tree */
/*         of this routine. */

/*     4)  Any error that occurs while look up the state of the target */
/*         or observer will be diagnosed by routines in the call tree of */
/*         this routine. */

/*     5)  Any error that occurs while look up the orientation of */
/*         the target will be diagnosed by routines in the call tree of */
/*         this routine. */

/*     6)  If the input method is not recognized, the error */
/*         SPICE(NOTSUPPORTED) will be signaled. */

/* $ Files */

/*     Appropriate kernels must be loaded 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: if the target body shape is modeled as an */
/*          ellipsoid, 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. */

/*        - 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 */

/*     This routine isolates the computation of the sub-observer state */
/*     (that is, the sub-observer point and its derivative with respect */
/*     to time). */

/*     This routine is used by the GF coordinate utility routines in */
/*     order to solve for time windows on which specified mathematical */
/*     conditions involving coordinates are satisfied. The role of */
/*     this routine is to provide Cartesian state vectors enabling */
/*     the GF coordinate utilities to determine the signs of the */
/*     derivatives with respect to time of coordinates of interest. */

/* $ Examples */

/*     See ZZGFCOST. */

/* $ Restrictions */

/*     1)  This routine is restricted to use with ellipsoidal target */
/*         shape models. */

/*     2)  The computations performed by this routine are intended */
/*         to be compatible with those performed by the SPICE */
/*         routine SUBPNT. If that routine changes, this routine */
/*         may need to be updated. */

/*     3)  This routine presumes that error checking of inputs */
/*         has, where possible, already been performed by the */
/*         GF coordinate utility initialization routine. */

/*     4)  The interface and functionality of this set of routines may */
/*         change without notice. These routines should be called only */
/*         by SPICELIB routines. */

/* $ Literature_References */

/*     None. */

/* $ Author_and_Institution */

/*     N.J. Bachman   (JPL) */

/* $ Version */

/* -    SPICELIB Version 2.0.0 12-MAY-2009 (NJB) */

/*        Upgraded to support targets and observers having */
/*        no names associated with their ID codes. */

/* -    SPICELIB Version 1.0.0 05-MAR-2009 (NJB) */

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

/*     sub-observer state */

/* -& */

/*     SPICELIB functions */


/*     Local parameters */


/*     Local variables */


/*     Saved variables */


/*     Initial values */


/*     Standard SPICE error handling. */

    if (return_()) {
	return 0;
    }
    chkin_("ZZGFSSOB", (ftnlen)8);
    if (first || *trgid != prvtrg) {
	bodc2s_(trgid, svtarg, (ftnlen)36);
	prvtrg = *trgid;
    }
    if (first || *obsid != prvobs) {
	bodc2s_(obsid, svobs, (ftnlen)36);
	prvobs = *obsid;
    }
    first = FALSE_;

/*     Parse the aberration correction specifier. */

    zzprscor_(abcorr, attblk, abcorr_len);
    geom = attblk[0];
    uselt = attblk[1];
    usestl = attblk[2];
    xmit = attblk[4];

/*     Decide whether the sub-observer point is computed using */
/*     the "near point" or "surface intercept" method. Only */
/*     ellipsoids may be used a shape models for this computation. */

    if (eqstr_(method, "Near point: ellipsoid", method_len, (ftnlen)21)) {
	near__ = TRUE_;
    } else if (eqstr_(method, "Intercept: ellipsoid", method_len, (ftnlen)20))
	     {
	near__ = FALSE_;
    } else {
	setmsg_("Sub-observer point computation method # is not supported by"
		" this routine.", (ftnlen)73);
	errch_("#", method, (ftnlen)1, method_len);
	sigerr_("SPICE(NOTSUPPORTED)", (ftnlen)19);
	chkout_("ZZGFSSOB", (ftnlen)8);
	return 0;
    }
    if (geom) {

/*        This is the geometric case. */

/*        We need to check the body-fixed reference frame here. */

	namfrm_(fixref, &frcode, fixref_len);
	frinfo_(&frcode, &center, &frclss, &clssid, &fnd);
	if (failed_()) {
	    chkout_("ZZGFSSOB", (ftnlen)8);
	    return 0;
	}
	if (! fnd) {
	    setmsg_("Input reference frame # was not recognized.", (ftnlen)43)
		    ;
	    errch_("#", fixref, (ftnlen)1, fixref_len);
	    sigerr_("SPICE(NOFRAME)", (ftnlen)14);
	    chkout_("ZZGFSSOB", (ftnlen)8);
	    return 0;
	}
	if (center != *trgid) {
	    setmsg_("Input reference frame # is centered on body # instead o"
		    "f body #.", (ftnlen)64);
	    errch_("#", fixref, (ftnlen)1, fixref_len);
	    errint_("#", &center, (ftnlen)1);
	    errint_("#", trgid, (ftnlen)1);
	    sigerr_("SPICE(INVALIDFRAME)", (ftnlen)19);
	    chkout_("ZZGFSSOB", (ftnlen)8);
	    return 0;
	}

/*        Get the state of the target with respect to the observer, */
/*        expressed relative to the target body-fixed frame. We don't */
/*        need to propagate states to the solar system barycenter in */
/*        this case. */

	spkgeo_(trgid, et, fixref, obsid, fxtsta, &lt, fixref_len);
	if (failed_()) {
	    chkout_("ZZGFSSOB", (ftnlen)8);
	    return 0;
	}

/*        Compute the state of the observer with respect to the target */
/*        in the body-fixed frame. */

	vminug_(fxtsta, &c__6, fxosta);

/*        Now we can obtain the surface velocity of the sub-observer */
/*        point. */

	if (near__) {

/*           The sub-observer point method is "near point." */

	    dnearp_(fxosta, radii, &radii[1], &radii[2], fxpsta, dalt, &found)
		    ;
	    if (! found) {
		setmsg_("The sub-observer state could could not be computed "
			"because the velocity was not well defined. DNEARP re"
			"turned \"not found.\"", (ftnlen)122);
		sigerr_("SPICE(DEGENERATECASE)", (ftnlen)21);
		chkout_("ZZGFSSOB", (ftnlen)8);
		return 0;
	    }
	} else {

/*           The sub-observer point method is "surface */
/*           intercept point." The ray direction is simply */
/*           the negative of the observer's position relative */
/*           to the target center. */

	    vminug_(fxosta, &c__6, raysta);
	    surfpv_(fxosta, raysta, radii, &radii[1], &radii[2], fxpsta, &
		    found);

/*           Although in general it's not an error for SURFPV to */
/*           be unable to compute an intercept state, it *is* */
/*           an error in this case, since the ray points toward */
/*           the center of the target. */

	    if (! found) {
		setmsg_("The sub-observer state could could not be computed "
			"because the velocity was not well defined. SURFPV re"
			"turned \"not found.\"", (ftnlen)122);
		sigerr_("SPICE(DEGENERATECASE)", (ftnlen)21);
		chkout_("ZZGFSSOB", (ftnlen)8);
		return 0;
	    }
	}
    } else if (uselt) {

/*        Light time and possibly stellar aberration corrections are */
/*        applied. */

/*        Most our work consists of getting ready to call either of the */
/*        SPICELIB routines DNEARP or SURFPV. In order to make this */
/*        call, we'll need the velocity of the observer relative to the */
/*        target body's center in the target body-fixed frame. We must */
/*        evaluate the rotation state of the target at the correct */
/*        epoch, and account for the rate of change of light time, if */
/*        light time corrections are used. The algorithm we use depends */
/*        on the algorithm used in SUBPNT, since we're computing the */
/*        derivative with respect to time of the solution found by that */
/*        routine. */

/*        In this algorithm, we must take into account the fact that */
/*        SUBPNT performs light time and stellar aberration corrections */
/*        for the sub-observer point, not for the center of the target */
/*        body. */

/*        If light time and stellar aberration corrections are used, */

/*           - Find the aberration corrected sub-observer point and the */
/*             light time-corrected epoch TRGEPC associated with the */
/*             sub-observer point. */

/*           - Use TRGEPC to find the position of the target relative to */
/*             the solar system barycenter. */

/*           - Use TRGEPC to find the orientation of the target relative */
/*             to the J2000 reference frame. */

/*           - Find the light-time corrected position of the */
/*             sub-observer point; use this to compute the stellar */
/*             aberration offset that applies to the sub-observer point, */
/*             as well as the velocity of this offset. */

/*           - Find the corrected state of the target center as seen */
/*             from the observer, where the corrections are those */
/*             applicable to the sub-observer point. */

/*           - Negate the corrected target center state to obtain the */
/*             state of the observer relative to the target. */

/*           - Express the state of the observer relative to the target */
/*             in the target body fixed frame at TRGEPC. */


/*        Below, we'll use the convention that vectors expressed */
/*        relative to the body-fixed frame have names of the form */

/*           FX* */

/*        Note that SUBPNT will signal an error if FIXREF is not */
/*        actually centered on the target body. */

	subpnt_(method, svtarg, et, fixref, abcorr, svobs, spoint, &trgepc, 
		srfvec, method_len, (ftnlen)36, fixref_len, abcorr_len, (
		ftnlen)36);

/*        Get J2000-relative states of observer and target with respect */
/*        to the solar system barycenter at their respective epochs of */
/*        participation. */

	spkssb_(obsid, et, "J2000", ssbobs, (ftnlen)5);
	spkssb_(trgid, &trgepc, "J2000", ssbtg0, (ftnlen)5);

/*        Get the uncorrected J2000 to body-fixed to state */
/*        transformation at TRGEPC. */

	sxform_("J2000", fixref, &trgepc, xform, (ftnlen)5, fixref_len);
	if (failed_()) {
	    chkout_("ZZGFSSOB", (ftnlen)8);
	    return 0;
	}

/*        Initialize the state of the sub-observer point in the */
/*        body-fixed frame. At this point we don't know the */
/*        point's velocity; set it to zero. */

	moved_(spoint, &c__3, fxpsta);
	cleard_(&c__3, &fxpsta[3]);
	if (usestl) {

/*           We're going to need the acceleration of the observer */
/*           relative to the SSB. Compute this now. */

	    for (i__ = 1; i__ <= 2; ++i__) {

/*              The epoch is ET -/+ TDELTA. */

		t = *et + ((i__ << 1) - 3) * 1.;
		spkssb_(obsid, &t, "J2000", &obssta[(i__1 = i__ * 6 - 6) < 12 
			&& 0 <= i__1 ? i__1 : s_rnge("obssta", i__1, "zzgfss"
			"ob_", (ftnlen)652)], (ftnlen)5);
	    }
	    if (failed_()) {
		chkout_("ZZGFSSOB", (ftnlen)8);
		return 0;
	    }

/*           Compute the observer's acceleration using a quadratic */
/*           approximation. */

	    qderiv_(&c__3, &obssta[3], &obssta[9], &c_b40, acc);
	}

/*        The rest of the algorithm is iterative. On the first */
/*        iteration, we don't have a good estimate of the velocity */
/*        of the sub-observer point relative to the body-fixed */
/*        frame. Since we're using this velocity as an input */
/*        to the aberration velocity computations, we */
/*        expect that treating this velocity as zero on the first */
/*        pass yields a reasonable estimate. On the second pass, */
/*        we'll use the velocity derived on the first pass. */

	cleard_(&c__3, fxpvel);

/*        We'll also estimate the rate of change of light time */
/*        as zero on the first pass. */

	dlt = 0.;
	for (i__ = 1; i__ <= 2; ++i__) {

/*           Correct the target's velocity for the rate of */
/*           change of light time. */

	    if (xmit) {
		scale = dlt + 1.;
	    } else {
		scale = 1. - dlt;
	    }

/*           Scale the velocity portion of the target state to */
/*           correct the velocity for the rate of change of light */
/*           time. */

	    moved_(ssbtg0, &c__3, ssbtrg);
	    vscl_(&scale, &ssbtg0[3], &ssbtrg[3]);

/*           Get the state of the target with respect to the observer. */

	    vsubg_(ssbtrg, ssbobs, &c__6, obstrg);

/*           Correct the J2000 to body-fixed state transformation matrix */
/*           for the rate of change of light time. */

	    zzcorsxf_(&xmit, &dlt, xform, corxfm);

/*           Invert CORXFM to obtain the corrected */
/*           body-fixed to J2000 state transformation. */

	    invstm_(corxfm, corxfi);

/*           Convert the sub-observer point state to the J2000 frame. */

	    mxvg_(corxfi, fxpsta, &c__6, &c__6, pntsta);

/*           Find the J2000-relative state of the sub-observer */
/*           point with respect to the target. */

	    vaddg_(obstrg, pntsta, &c__6, obspnt);
	    if (usestl) {

/*              Now compute the stellar aberration correction */
/*              applicable to OBSPNT. We need the velocity of */
/*              this correction as well. */

		zzstelab_(&xmit, acc, &ssbobs[3], obspnt, sa, savel);
		moved_(sa, &c__3, sastat);
		moved_(savel, &c__3, &sastat[3]);

/*              Adding the stellar aberration state to the target center */
/*              state gives us the state of the target center with */
/*              respect to the observer, corrected for the aberrations */
/*              applicable to the sub-observer point. */
		vaddg_(obstrg, sastat, &c__6, stemp);
	    } else {
		moved_(obstrg, &c__6, stemp);
	    }

/*           Convert STEMP to the body-fixed reference frame. */

	    mxvg_(corxfm, stemp, &c__6, &c__6, fxtsta);

/*           At long last, compute the state of the observer */
/*           with respect to the target in the body-fixed frame. */

	    vminug_(fxtsta, &c__6, fxosta);

/*           Now we can obtain the surface velocity of the */
/*           sub-observer point. */

	    if (near__) {

/*              The sub-observer point method is "near point." */

		dnearp_(fxosta, radii, &radii[1], &radii[2], fxpsta, dalt, &
			found);
		if (! found) {
		    setmsg_("The sub-observer state could could not be compu"
			    "ted because the velocity was not well defined.  "
			    "DNEARP returned \"not found.\"", (ftnlen)123);
		    sigerr_("SPICE(DEGENERATECASE)", (ftnlen)21);
		    chkout_("ZZGFSSOB", (ftnlen)8);
		    return 0;
		}
	    } else {

/*              The sub-observer point method is "surface intercept */
/*              point." The ray direction is simply the negative of the */
/*              observer's position relative to the target center. */

		vminug_(fxosta, &c__6, raysta);
		surfpv_(fxosta, raysta, radii, &radii[1], &radii[2], fxpsta, &
			found);

/*              Although in general it's not an error for SURFPV to be */
/*              unable to compute an intercept state, it *is* an error */
/*              in this case, since the ray points toward the center of */
/*              the target. */

		if (! found) {
		    setmsg_("The sub-observer state could could not be compu"
			    "ted because the velocity was not well defined. S"
			    "URFPV returned \"not found.\"", (ftnlen)122);
		    sigerr_("SPICE(DEGENERATECASE)", (ftnlen)21);
		    chkout_("ZZGFSSOB", (ftnlen)8);
		    return 0;
		}
	    }

/*           At this point we can update the surface point */
/*           velocity and light time derivative estimates. */

/*           In order to compute the light time rate, we'll */
/*           need the J2000-relative velocity of the sub-observer */
/*           point with respect to the observer. First convert */
/*           the sub-observer state to the J2000 frame, then */
/*           add the result to the state of the target center */
/*           with respect to the observer. */

	    mxvg_(corxfi, fxpsta, &c__6, &c__6, pntsta);
	    vaddg_(obstrg, pntsta, &c__6, obspnt);

/*           Now that we have an improved estimate of the */
/*           sub-observer state, we can estimate the rate of */
/*           change of light time as */

/*              range rate */
/*              ---------- */
/*                  c */


/*           If we're correcting for stellar aberration, *ideally* we */
/*           should remove that correction now, since the light time */
/*           rate is based on light time between the observer and the */
/*           light-time corrected sub-observer point. But the error made */
/*           by including stellar aberration is too small to make it */
/*           worthwhile to make this adjustment. */

	    vhat_(obspnt, upos);
	    dlt = vdot_(&obspnt[3], upos) / clight_();

/*           With FXPVEL and DLT updated, we'll repeat our */
/*           computations. */

	}
    } else {

/*        We should never get here. */

	setmsg_("Aberration correction # was not recognized.", (ftnlen)43);
	errch_("#", abcorr, (ftnlen)1, abcorr_len);
	sigerr_("SPICE(NOTSUPPORTED)", (ftnlen)19);
	chkout_("ZZGFSSOB", (ftnlen)8);
	return 0;
    }

/*     Copy the computed state to the output argument STATE. */

    moved_(fxpsta, &c__6, state);
    chkout_("ZZGFSSOB", (ftnlen)8);
    return 0;
} /* zzgfssob_ */
Esempio n. 4
0
/* $Procedure SPKPV ( S/P Kernel, position and velocity ) */
/* Subroutine */ int spkpv_(integer *handle, doublereal *descr, doublereal *
	et, char *ref, doublereal *state, integer *center, ftnlen ref_len)
{
    extern /* Subroutine */ int mxvg_(doublereal *, doublereal *, integer *, 
	    integer *, doublereal *), chkin_(char *, ftnlen), dafus_(
	    doublereal *, integer *, integer *, doublereal *, integer *), 
	    errch_(char *, char *, ftnlen, ftnlen);
    doublereal xform[36]	/* was [6][6] */, dc[2];
    integer ic[6];
    extern /* Subroutine */ int frmchg_(integer *, integer *, doublereal *, 
	    doublereal *), namfrm_(char *, integer *, ftnlen);
    integer irfreq;
    extern /* Subroutine */ int sigerr_(char *, ftnlen), chkout_(char *, 
	    ftnlen), setmsg_(char *, ftnlen);
    doublereal tstate[6];
    extern logical return_(void);
    extern /* Subroutine */ int spkpvn_(integer *, doublereal *, doublereal *,
	     integer *, doublereal *, integer *);
    integer irf;

/* $ Abstract */

/*     Return the state (position and velocity) of a target body */
/*     relative to some center of motion in a specified frame. */

/* $ 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 */

/*     SPK */

/* $ Keywords */

/*     EPHEMERIS */

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

/*     Variable  I/O  Description */
/*     --------  ---  -------------------------------------------------- */
/*     HANDLE     I   File handle. */
/*     DESCR      I   Segment descriptor. */
/*     ET         I   Target epoch. */
/*     REF        I   Target reference frame. */
/*     STATE      O   Position, velocity. */
/*     CENTER     O   Center of state. */

/* $ Detailed_Input */

/*     HANDLE, */
/*     DESCR       are the file handle assigned to a SPK file, and the */
/*                 descriptor for a segment within the file. Together */
/*                 they determine the ephemeris data from which the */
/*                 state of the body is to be computed. */

/*     ET          is the epoch (ephemeris time) at which the state */
/*                 is to be computed. */

/*     REF         is the name of the reference frame to */
/*                 which the vectors returned by the routine should */
/*                 be rotated. This may be any frame supported by */
/*                 the SPICELIB subroutine FRMCHG. */

/* $ Detailed_Output */

/*     STATE       contains the position and velocity, at epoch ET, */
/*                 for whatever body is covered by the specified segment. */
/*                 STATE has six elements:  the first three contain the */
/*                 body's position; the last three contain the body's */
/*                 velocity.  These vectors are rotated into the */
/*                 specified reference frame, the origin of */
/*                 which is located at the center of motion for the */
/*                 body (see CENTER, below).  Units are always km and */
/*                 km/sec. */

/*     CENTER      is the integer ID code of the center of motion for */
/*                 the state. */

/* $ Parameters */

/*     NONE. */

/* $ Files */

/*     See argument HANDLE. */

/* $ Exceptions */

/*     1) If the requested reference frame is not supported by the */
/*        current version of CHGIRF, the error 'SPICE(SPKREFNOTSUPP)' */
/*        is signalled. */

/* $ Particulars */

/*     Once SPKPV was the most basic of the SPK readers, the reader upon */
/*     which SPKSSB, SPKAPP, and SPKEZ were built. However, its function */
/*     has now largely been replaced by SPKPVN. SPKPV should not normally */
/*     be called except by old software written before the release of */
/*     SPKPVN. This routine should be considered obsolete. */


/* $ Examples */

/*     In the following code fragment, an entire SPK file is searched */
/*     for segments containing a particular epoch. For each one found, */
/*     the body, center, segment identifier, and range at the epoch */
/*     are printed out. */

/*        CALL DAFOPR ( 'TEST.SPK', HANDLE ) */
/*        CALL DAFBFS (             HANDLE ) */

/*        CALL DAFFNA ( FOUND  ) */

/*        DO WHILE ( FOUND ) */
/*           CALL DAFGS ( DESCR ) */
/*           CALL DAFUS ( DESCR, 2, 6, DC, IC ) */

/*           IF ( DC(1) .LE. ET  .AND.  ET .LE. DC(2) ) THEN */
/*              CALL SPKPV ( HANDLE, DESCR, ET, 'J2000', STATE, CENTER ) */
/*              CALL DAFGN ( IDENT ) */

/*              WRITE (*,*) */
/*              WRITE (*,*) 'Body   = ', IC(1) */
/*              WRITE (*,*) 'Center = ', CENTER, */
/*              WRITE (*,*) 'ID     = ', IDENT */
/*              WRITE (*,*) 'Range  = ', VNORM ( STATE ) */
/*           END IF */

/*           CALL DAFFNA ( FOUND ) */
/*        END DO */

/* $ Restrictions */

/*     None. */

/* $ Literature_References */

/*     NAIF Document 168.0, "S- and P- Kernel (SPK) Specification and */
/*     User's Guide" */

/* $ Author_and_Institution */

/*     K.R. Gehringer  (JPL) */
/*     W.L. Taber      (JPL) */
/*     J.M. Lynch      (JPL) */
/*     R.E. Thurman    (JPL) */
/*     I.M. Underwood  (JPL) */

/* $ Version */

/* -    SPICELIB Version 6.0.0, 19-SEP-1995 (WLT) */

/*        The routine was updated to handle non-inertial frames. */

/* -    SPICELIB Version 5.0.0, 13-MAR-1995 (KRG) */

/*        The routine was updated to handle type 14. */

/*        A new exception, 3, was also added. */

/* -    SPICELIB Version 4.0.0, 04-NOV-1994 (WLT) */

/*        The routine was updated to handle type 15. */

/* -    SPICELIB Version 3.0.0, 04-AUG-1993 (NJB) */

/*        The routine was updated to handle types 08 and 09. */

/* -    SPICELIB Version 2.0.0, 01-APR-1992 (JML) */

/*        The routine was updated to handle type 05. */

/* -    SPICELIB Version 1.0.2, 18-JUL-1991 (NJB) */

/*        The description of the output STATE was expanded slightly. */

/* -    SPICELIB Version 1.0.1, 22-MAR-1990 (HAN) */

/*        Literature references added to the header. */

/* -    SPICELIB Version 1.0.0, 31-JAN-1990 (IMU) (RET) */

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

/*     position and velocity from ephemeris */
/*     spk file position and velocity */

/* -& */
/* $ Revisions */

/* -    SPICELIB Version 6.0.0, 6-OCT-1994 (WLT) */

/*        The routine was updated to handle non-inertial frames. */

/* -    SPICELIB Version 5.0.0, 13-MAR-1995 (KRG) */

/*        The routine was updated to handle type 14. */

/*        A new exception, 3, was also added. */

/* -    SPICELIB Version 4.0.0, 04-NOV-1994 (WLT) */

/*        The routine was updated to handle type 15. */

/* -    SPICELIB Version 3.0.0, 04-AUG-1993 (NJB) */

/*        The routine was updated to handle types 08 and 09. */

/* -    SPICELIB Version 2.0.0, 01-APR-1992 (JML) */

/*        The routine was updated to handle type 05. */

/* -& */

/*     SPICELIB functions */


/*     Some local space is needed in which to return records, and */
/*     into which to unpack the segment descriptor. */


/*     Standard SPICE error handling. */

    if (return_()) {
	return 0;
    } else {
	chkin_("SPKPV", (ftnlen)5);
    }
    dafus_(descr, &c__2, &c__6, dc, ic);
    *center = ic[1];
    irf = ic[2];

/*     Rotate the raw state from its native frame to the only if the */
/*     native frame differs from the one requested by the user. */

    namfrm_(ref, &irfreq, ref_len);
    if (irfreq == 0) {
	setmsg_("No support for frame #.", (ftnlen)23);
	errch_("#", ref, (ftnlen)1, ref_len);
	sigerr_("SPICE(SPKREFNOTSUPP)", (ftnlen)20);
    } else if (irfreq != irf) {
	spkpvn_(handle, descr, et, &irf, tstate, center);
	frmchg_(&irf, &irfreq, et, xform);
	mxvg_(xform, tstate, &c__6, &c__6, state);
    } else {
	spkpvn_(handle, descr, et, &irf, state, center);
    }
    chkout_("SPKPV", (ftnlen)5);
    return 0;
} /* spkpv_ */