/* $Procedure ZZSPKAP1 ( S/P Kernel, apparent state ) */ /* Subroutine */ int zzspkap1_(integer *targ, doublereal *et, char *ref, doublereal *sobs, char *abcorr, doublereal *starg, doublereal *lt, ftnlen ref_len, ftnlen abcorr_len) { /* Initialized data */ static logical first = TRUE_; static char flags[5*9] = "NONE " "LT " "LT+S " "CN " "CN+S " "XLT " "XLT+S" "XCN " "XCN+S"; static char prvcor[5] = " "; /* System generated locals */ integer i__1; doublereal d__1; /* Builtin functions */ integer s_cmp(char *, char *, ftnlen, ftnlen); /* Subroutine */ int s_copy(char *, char *, ftnlen, ftnlen); /* Local variables */ char corr[5]; extern /* Subroutine */ int zzspksb1_(integer *, doublereal *, char *, doublereal *, ftnlen); static logical xmit; extern /* Subroutine */ int vequ_(doublereal *, doublereal *); integer i__, refid; extern /* Subroutine */ int chkin_(char *, ftnlen), errch_(char *, char *, ftnlen, ftnlen), moved_(doublereal *, integer *, doublereal *); static logical usecn; doublereal sapos[3]; extern /* Subroutine */ int vsubg_(doublereal *, doublereal *, integer *, doublereal *); static logical uselt; extern doublereal vnorm_(doublereal *), clight_(void); extern integer isrchc_(char *, integer *, char *, ftnlen, ftnlen); extern /* Subroutine */ int stelab_(doublereal *, doublereal *, doublereal *), sigerr_(char *, ftnlen), chkout_(char *, ftnlen), stlabx_(doublereal *, doublereal *, doublereal *); integer ltsign; extern /* Subroutine */ int ljucrs_(integer *, char *, char *, ftnlen, ftnlen), setmsg_(char *, ftnlen); doublereal tstate[6]; integer maxitr; extern /* Subroutine */ int irfnum_(char *, integer *, ftnlen); extern logical return_(void); static logical usestl; extern logical odd_(integer *); /* $ Abstract */ /* Deprecated: This routine has been superseded by SPKAPS. This */ /* routine is supported for purposes of backward compatibility only. */ /* Return the state (position and velocity) of a target body */ /* relative to an observer, optionally corrected for light time and */ /* stellar aberration. */ /* $ 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 */ /* -------- --- -------------------------------------------------- */ /* TARG I Target body. */ /* ET I Observer epoch. */ /* REF I Inertial reference frame of observer's state. */ /* SOBS I State of observer wrt. solar system barycenter. */ /* ABCORR I Aberration correction flag. */ /* STARG O State of target. */ /* LT O One way light time between observer and target. */ /* $ Detailed_Input */ /* TARG is the NAIF ID code for a target body. The target */ /* and observer define a state vector whose position */ /* component points from the observer to the target. */ /* ET is the ephemeris time, expressed as seconds past J2000 */ /* TDB, at which the state of the target body relative to */ /* the observer is to be computed. ET refers to time at */ /* the observer's location. */ /* REF is the inertial reference frame with respect to which */ /* the observer's state SOBS is expressed. REF must be */ /* recognized by the SPICE Toolkit. The acceptable */ /* frames are listed in the Frames Required Reading, as */ /* well as in the SPICELIB routine CHGIRF. */ /* Case and blanks are not significant in the string REF. */ /* SOBS is the geometric (uncorrected) state of the observer */ /* relative to the solar system barycenter at epoch ET. */ /* SOBS is a 6-vector: the first three components of */ /* SOBS represent a Cartesian position vector; the last */ /* three components represent the corresponding velocity */ /* vector. SOBS is expressed relative to the inertial */ /* reference frame designated by REF. */ /* Units are always km and km/sec. */ /* 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. See the discussion */ /* in the Particulars section for recommendations on */ /* how to choose aberration corrections. */ /* ABCORR may be any of the following: */ /* 'NONE' Apply no correction. Return the */ /* geometric state of the target body */ /* relative to the observer. */ /* The following values of ABCORR apply to the */ /* "reception" case in which photons depart from the */ /* target's location at the light-time corrected epoch */ /* ET-LT and *arrive* at the observer's location at ET: */ /* 'LT' Correct for one-way light time (also */ /* called "planetary aberration") using a */ /* Newtonian formulation. This correction */ /* yields the state of the target at the */ /* moment it emitted photons arriving at */ /* the observer at ET. */ /* The light time correction involves */ /* iterative solution of the light time */ /* equation (see Particulars for details). */ /* The solution invoked by the 'LT' option */ /* uses one iteration. */ /* 'LT+S' Correct for one-way light time and */ /* stellar aberration using a Newtonian */ /* formulation. This option modifies the */ /* state obtained with the 'LT' option to */ /* account for the observer's velocity */ /* relative to the solar system */ /* barycenter. The result is the apparent */ /* state of the target---the position and */ /* velocity of the target as seen by the */ /* observer. */ /* 'CN' Converged Newtonian light time */ /* correction. In solving the light time */ /* equation, the 'CN' correction iterates */ /* until the solution converges (three */ /* iterations on all supported platforms). */ /* Whether the 'CN+S' solution is */ /* substantially more accurate than the */ /* 'LT' solution depends on the geometry */ /* of the participating objects and on the */ /* accuracy of the input data. In all */ /* cases this routine will execute more */ /* slowly when a converged solution is */ /* computed. See the Particulars section */ /* of SPKEZR for a discussion of precision */ /* of light time corrections. */ /* 'CN+S' Converged Newtonian light time */ /* correction and stellar aberration */ /* correction. */ /* The following values of ABCORR apply to the */ /* "transmission" case in which photons *depart* from */ /* the observer's location at ET and arrive at the */ /* target's location at the light-time corrected epoch */ /* ET+LT: */ /* 'XLT' "Transmission" case: correct for */ /* one-way light time using a Newtonian */ /* formulation. This correction yields the */ /* state of the target at the moment it */ /* receives photons emitted from the */ /* observer's location at ET. */ /* 'XLT+S' "Transmission" case: correct for */ /* one-way light time and stellar */ /* aberration using a Newtonian */ /* formulation This option modifies the */ /* state obtained with the 'XLT' option to */ /* account for the observer's velocity */ /* relative to the solar system */ /* barycenter. The position component of */ /* the computed target state indicates the */ /* direction that photons emitted from the */ /* observer's location must be "aimed" to */ /* hit the target. */ /* 'XCN' "Transmission" case: converged */ /* Newtonian light time correction. */ /* 'XCN+S' "Transmission" case: converged */ /* Newtonian light time correction and */ /* stellar aberration correction. */ /* Neither special nor general relativistic effects are */ /* accounted for in the aberration corrections applied */ /* by this routine. */ /* Case and blanks are not significant in the string */ /* ABCORR. */ /* $ Detailed_Output */ /* STARG is a Cartesian state vector representing the position */ /* and velocity of the target body relative to the */ /* specified observer. STARG is corrected for the */ /* specified aberrations, and is expressed with respect */ /* to the specified inertial reference frame. The first */ /* three components of STARG represent the x-, y- and */ /* z-components of the target's position; last three */ /* components form the corresponding velocity vector. */ /* The position component of STARG points from the */ /* observer's location at ET to the aberration-corrected */ /* location of the target. Note that the sense of the */ /* position vector is independent of the direction of */ /* radiation travel implied by the aberration */ /* correction. */ /* The velocity component of STARG is obtained by */ /* evaluating the target's geometric state at the light */ /* time corrected epoch, so for aberration-corrected */ /* states, the velocity is not precisely equal to the */ /* time derivative of the position. */ /* Units are always km and km/sec. */ /* LT is the one-way light time between the observer and */ /* target in seconds. If the target state is corrected */ /* for aberrations, then LT is the one-way light time */ /* between the observer and the light time corrected */ /* target location. */ /* $ Parameters */ /* None. */ /* $ Exceptions */ /* 1) If the value of ABCORR is not recognized, the error */ /* 'SPICE(SPKINVALIDOPTION)' is signaled. */ /* 2) If the reference frame requested is not a recognized */ /* inertial reference frame, the error 'SPICE(BADFRAME)' */ /* is signaled. */ /* 3) If the state of the target relative to the solar system */ /* barycenter cannot be computed, the error will be diagnosed */ /* by routines in the call tree of this routine. */ /* $ Files */ /* This routine computes states using SPK files that have been */ /* loaded into the SPICE system, normally via the kernel loading */ /* interface routine FURNSH. Application programs typically load */ /* kernels once before this routine is called, for example during */ /* program initialization; kernels need not be loaded repeatedly. */ /* See the routine FURNSH and the SPK and KERNEL Required Reading */ /* for further information on loading (and unloading) kernels. */ /* If any of the ephemeris data used to compute STARG are expressed */ /* relative to a non-inertial frame in the SPK files providing those */ /* data, additional kernels may be needed to enable the reference */ /* frame transformations required to compute the state. Normally */ /* these additional kernels are PCK files or frame kernels. Any */ /* such kernels must already be loaded at the time this routine is */ /* called. */ /* $ Particulars */ /* In space science or engineering applications one frequently */ /* wishes to know where to point a remote sensing instrument, such */ /* as an optical camera or radio antenna, in order to observe or */ /* otherwise receive radiation from a target. This pointing problem */ /* is complicated by the finite speed of light: one needs to point */ /* to where the target appears to be as opposed to where it actually */ /* is at the epoch of observation. We use the adjectives */ /* "geometric," "uncorrected," or "true" to refer to an actual */ /* position or state of a target at a specified epoch. When a */ /* geometric position or state vector is modified to reflect how it */ /* appears to an observer, we describe that vector by any of the */ /* terms "apparent," "corrected," "aberration corrected," or "light */ /* time and stellar aberration corrected." */ /* The SPICE Toolkit can correct for two phenomena affecting the */ /* apparent location of an object: one-way light time (also called */ /* "planetary aberration") and stellar aberration. Correcting for */ /* one-way light time is done by computing, given an observer and */ /* observation epoch, where a target was when the observed photons */ /* departed the target's location. The vector from the observer to */ /* this computed target location is called a "light time corrected" */ /* vector. The light time correction depends on the motion of the */ /* target, but it is independent of the velocity of the observer */ /* relative to the solar system barycenter. Relativistic effects */ /* such as light bending and gravitational delay are not accounted */ /* for in the light time correction performed by this routine. */ /* The velocity of the observer also affects the apparent location */ /* of a target: photons arriving at the observer are subject to a */ /* "raindrop effect" whereby their velocity relative to the observer */ /* is, using a Newtonian approximation, the photons' velocity */ /* relative to the solar system barycenter minus the velocity of the */ /* observer relative to the solar system barycenter. This effect is */ /* called "stellar aberration." Stellar aberration is independent */ /* of the velocity of the target. The stellar aberration formula */ /* used by this routine is non-relativistic. */ /* Stellar aberration corrections are applied after light time */ /* corrections: the light time corrected target position vector is */ /* used as an input to the stellar aberration correction. */ /* When light time and stellar aberration corrections are both */ /* applied to a geometric position vector, the resulting position */ /* vector indicates where the target "appears to be" from the */ /* observer's location. */ /* As opposed to computing the apparent position of a target, one */ /* may wish to compute the pointing direction required for */ /* transmission of photons to the target. This requires correction */ /* of the geometric target position for the effects of light time and */ /* stellar aberration, but in this case the corrections are computed */ /* for radiation traveling from the observer to the target. */ /* The "transmission" light time correction yields the target's */ /* location as it will be when photons emitted from the observer's */ /* location at ET arrive at the target. The transmission stellar */ /* aberration correction is the inverse of the traditional stellar */ /* aberration correction: it indicates the direction in which */ /* radiation should be emitted so that, using a Newtonian */ /* approximation, the sum of the velocity of the radiation relative */ /* to the observer and of the observer's velocity, relative to the */ /* solar system barycenter, yields a velocity vector that points in */ /* the direction of the light time corrected position of the target. */ /* The traditional aberration corrections applicable to observation */ /* and those applicable to transmission are related in a simple way: */ /* one may picture the geometry of the "transmission" case by */ /* imagining the "observation" case running in reverse time order, */ /* and vice versa. */ /* One may reasonably object to using the term "observer" in the */ /* transmission case, in which radiation is emitted from the */ /* observer's location. The terminology was retained for */ /* consistency with earlier documentation. */ /* Below, we indicate the aberration corrections to use for some */ /* common applications: */ /* 1) Find the apparent direction of a target for a remote-sensing */ /* observation. */ /* Use 'LT+S' or 'CN+S: apply both light time and stellar */ /* aberration corrections. */ /* Note that using light time corrections alone ('LT' or 'CN') */ /* is generally not a good way to obtain an approximation to */ /* an apparent target vector: since light time and stellar */ /* aberration corrections often partially cancel each other, */ /* it may be more accurate to use no correction at all than to */ /* use light time alone. */ /* 2) Find the corrected pointing direction to radiate a signal */ /* to a target. This computation is often applicable for */ /* implementing communications sessions. */ /* Use 'XLT+S' or 'XCN+S: apply both light time and stellar */ /* aberration corrections for transmission. */ /* 3) Compute the apparent position of a target body relative */ /* to a star or other distant object. */ /* Use 'LT', 'CN', 'LT+S', or 'CN+S' as needed to match the */ /* correction applied to the position of the distant */ /* object. For example, if a star position is obtained from */ /* a catalog, the position vector may not be corrected for */ /* stellar aberration. In this case, to find the angular */ /* separation of the star and the limb of a planet, the */ /* vector from the observer to the planet should be */ /* corrected for light time but not stellar aberration. */ /* 4) Obtain an uncorrected state vector derived directly from */ /* data in an SPK file. */ /* Use 'NONE'. */ /* C */ /* 5) Use a geometric state vector as a low-accuracy estimate */ /* of the apparent state for an application where execution */ /* speed is critical: */ /* Use 'NONE'. */ /* 6) While this routine cannot perform the relativistic */ /* aberration corrections required to compute states */ /* with the highest possible accuracy, it can supply the */ /* geometric states required as inputs to these computations: */ /* Use 'NONE', then apply high-accuracy aberration */ /* corrections (not available in the SPICE Toolkit). */ /* Below, we discuss in more detail how the aberration corrections */ /* applied by this routine are computed. */ /* Geometric case */ /* ============== */ /* SPKAPP begins by computing the geometric position T(ET) of the */ /* target body relative to the solar system barycenter (SSB). */ /* Subtracting the geometric position of the observer O(ET) gives */ /* the geometric position of the target body relative to the */ /* observer. The one-way light time, LT, is given by */ /* | T(ET) - O(ET) | */ /* LT = ------------------- */ /* c */ /* The geometric relationship between the observer, target, and */ /* solar system barycenter is as shown: */ /* SSB ---> O(ET) */ /* | / */ /* | / */ /* | / */ /* | / T(ET) - O(ET) */ /* V V */ /* T(ET) */ /* The returned state consists of the position vector */ /* T(ET) - O(ET) */ /* and a velocity obtained by taking the difference of the */ /* corresponding velocities. In the geometric case, the */ /* returned velocity is actually the time derivative of the */ /* position. */ /* Reception case */ /* ============== */ /* When any of the options 'LT', 'CN', 'LT+S', 'CN+S' is */ /* selected, SPKAPP computes the position of the target body at */ /* epoch ET-LT, where LT is the one-way light time. Let T(t) and */ /* O(t) represent the positions of the target and observer */ /* relative to the solar system barycenter at time t; then LT is */ /* the solution of the light-time equation */ /* | T(ET-LT) - O(ET) | */ /* LT = ------------------------ (1) */ /* c */ /* The ratio */ /* | T(ET) - O(ET) | */ /* --------------------- (2) */ /* c */ /* is used as a first approximation to LT; inserting (2) into the */ /* RHS of the light-time equation (1) yields the "one-iteration" */ /* estimate of the one-way light time. Repeating the process */ /* until the estimates of LT converge yields the "converged */ /* Newtonian" light time estimate. */ /* Subtracting the geometric position of the observer O(ET) gives */ /* the position of the target body relative to the observer: */ /* T(ET-LT) - O(ET). */ /* SSB ---> O(ET) */ /* | \ | */ /* | \ | */ /* | \ | T(ET-LT) - O(ET) */ /* | \ | */ /* V V V */ /* T(ET) T(ET-LT) */ /* The position component of the light-time corrected state */ /* is the vector */ /* T(ET-LT) - O(ET) */ /* The velocity component of the light-time corrected state */ /* is the difference */ /* T_vel(ET-LT) - O_vel(ET) */ /* where T_vel and O_vel are, respectively, the velocities of */ /* the target and observer relative to the solar system */ /* barycenter at the epochs ET-LT and ET. */ /* If correction for stellar aberration is requested, the target */ /* position is rotated toward the solar system barycenter- */ /* relative velocity vector of the observer. The rotation is */ /* computed as follows: */ /* Let r be the light time corrected vector from the observer */ /* to the object, and v be the velocity of the observer with */ /* respect to the solar system barycenter. Let w be the angle */ /* between them. The aberration angle phi is given by */ /* sin(phi) = v sin(w) / c */ /* Let h be the vector given by the cross product */ /* h = r X v */ /* Rotate r by phi radians about h to obtain the apparent */ /* position of the object. */ /* The velocity component of the output state STARG is */ /* not corrected for stellar aberration. */ /* Transmission case */ /* ================== */ /* When any of the options 'XLT', 'XCN', 'XLT+S', 'XCN+S' are */ /* selected, SPKAPP computes the position of the target body T at */ /* epoch ET+LT, where LT is the one-way light time. LT is the */ /* solution of the light-time equation */ /* | T(ET+LT) - O(ET) | */ /* LT = ------------------------ (3) */ /* c */ /* Subtracting the geometric position of the observer, O(ET), */ /* gives the position of the target body relative to the */ /* observer: T(ET-LT) - O(ET). */ /* SSB --> O(ET) */ /* / | * */ /* / | * T(ET+LT) - O(ET) */ /* / |* */ /* / *| */ /* V V V */ /* T(ET+LT) T(ET) */ /* The position component of the light-time corrected state */ /* is the vector */ /* T(ET+LT) - O(ET) */ /* The velocity component of the light-time corrected state */ /* is the difference */ /* T_vel(ET+LT) - O_vel(ET) */ /* where T_vel and O_vel are, respectively, the velocities of */ /* the target and observer relative to the solar system */ /* barycenter at the epochs ET+LT and ET. */ /* If correction for stellar aberration is requested, the target */ /* position is rotated away from the solar system barycenter- */ /* relative velocity vector of the observer. The rotation is */ /* computed as in the reception case, but the sign of the */ /* rotation angle is negated. */ /* The velocity component of the output state STARG is */ /* not corrected for stellar aberration. */ /* Neither special nor general relativistic effects are accounted */ /* for in the aberration corrections performed by this routine. */ /* $ Examples */ /* In the following code fragment, SPKSSB and SPKAPP are used */ /* to display the position of Io (body 501) as seen from the */ /* Voyager 2 spacecraft (Body -32) at a series of epochs. */ /* Normally, one would call the high-level reader SPKEZR to obtain */ /* state vectors. The example below illustrates the interface */ /* of this routine but is not intended as a recommendation on */ /* how to use the SPICE SPK subsystem. */ /* The use of integer ID codes is necessitated by the low-level */ /* interface of this routine. */ /* IO = 501 */ /* VGR2 = -32 */ /* DO WHILE ( EPOCH .LE. END ) */ /* CALL SPKSSB ( VGR2, EPOCH, 'J2000', STVGR2 ) */ /* CALL SPKAPP ( IO, EPOCH, 'J2000', STVGR2, */ /* . 'LT+S', STIO, LT ) */ /* CALL RECRAD ( STIO, RANGE, RA, DEC ) */ /* WRITE (*,*) RA * DPR(), DEC * DPR() */ /* EPOCH = EPOCH + DELTA */ /* END DO */ /* $ Restrictions */ /* 1) The kernel files to be used by SPKAPP must be loaded */ /* (normally by the SPICELIB kernel loader FURNSH) before */ /* this routine is called. */ /* 2) Unlike most other SPK state computation routines, this */ /* routine requires that the input state be relative to an */ /* inertial reference frame. Non-inertial frames are not */ /* supported by this routine. */ /* 3) In a future version of this routine, the implementation */ /* of the aberration corrections may be enhanced to improve */ /* accuracy. */ /* $ Literature_References */ /* SPK Required Reading. */ /* $ Author_and_Institution */ /* N.J. Bachman (JPL) */ /* H.A. Neilan (JPL) */ /* W.L. Taber (JPL) */ /* B.V. Semenov (JPL) */ /* I.M. Underwood (JPL) */ /* $ Version */ /* - SPICELIB Version 3.1.0, 04-JUL-2014 (NJB) (BVS) */ /* Discussion of light time corrections was updated. Assertions */ /* that converged light time corrections are unlikely to be */ /* useful were removed. */ /* Last update was 21-SEP-2013 (BVS) */ /* Updated to call LJUCRS instead of CMPRSS/UCASE. */ /* - SPICELIB Version 3.0.3, 18-MAY-2010 (BVS) */ /* Index lines now state that this routine is deprecated. */ /* - SPICELIB Version 3.0.2, 08-JAN-2008 (NJB) */ /* The Abstract section of the header was updated to */ /* indicate that this routine has been deprecated. */ /* - SPICELIB Version 3.0.1, 20-OCT-2003 (EDW) */ /* Added mention that LT returns in seconds. */ /* Corrected spelling errors. */ /* - SPICELIB Version 3.0.0, 18-DEC-2001 (NJB) */ /* Updated to handle aberration corrections for transmission */ /* of radiation. Formerly, only the reception case was */ /* supported. The header was revised and expanded to explain */ /* the functionality of this routine in more detail. */ /* - SPICELIB Version 2.1.0, 09-JUL-1996 (WLT) */ /* Corrected the description of LT in the Detailed Output */ /* section of the header. */ /* - SPICELIB Version 2.0.0, 22-MAY-1995 (WLT) */ /* The routine was modified to support the options 'CN' and */ /* 'CN+S' aberration corrections. Moreover, diagnostics were */ /* added to check for reference frames that are not recognized */ /* inertial frames. */ /* - SPICELIB Version 1.1.2, 10-MAR-1992 (WLT) */ /* Comment section for permuted index source lines was added */ /* following the header. */ /* - SPICELIB Version 1.1.1, 06-MAR-1991 (JML) */ /* In the example program, the calling sequence of SPKAPP */ /* was corrected. */ /* - SPICELIB Version 1.1.0, 25-MAY-1990 (HAN) */ /* The local variable CORR was added to eliminate a */ /* run-time error that occurred when SPKAPP was determining */ /* what corrections to apply to the state. */ /* - SPICELIB Version 1.0.1, 22-MAR-1990 (HAN) */ /* Literature references added to the header. */ /* - SPICELIB Version 1.0.0, 31-JAN-1990 (IMU) */ /* -& */ /* $ Index_Entries */ /* DEPRECATED low-level aberration correction */ /* DEPRECATED apparent state from spk file */ /* DEPRECATED get apparent state */ /* -& */ /* $ Revisions */ /* - SPICELIB Version 2.0.0, 22-MAY-1995 (WLT) */ /* The routine was modified to support the options 'CN' and */ /* 'CN+S' aberration corrections. Moreover, diagnostics were */ /* added to check for reference frames that are not recognized */ /* inertial frames. */ /* - SPICELIB Version 1.1.1, 06-MAR-1991 (JML) */ /* In the example program, the calling sequence of SPKAPP */ /* was corrected. */ /* - SPICELIB Version 1.1.0, 25-MAY-1990 (HAN) */ /* The local variable CORR was added to eliminate a run-time */ /* error that occurred when SPKAPP was determining what */ /* corrections to apply to the state. If the literal string */ /* 'LT' was assigned to ABCORR, SPKAPP attempted to look at */ /* ABCORR(3:4). Because ABCORR is a passed length argument, its */ /* length is not guaranteed, and those positions may not exist. */ /* Searching beyond the bounds of a string resulted in a */ /* run-time error at NAIF because NAIF compiles SPICELIB using the */ /* CHECK=BOUNDS option for the DEC VAX/VMX DCL FORTRAN command. */ /* Also, without the local variable CORR, SPKAPP would have to */ /* modify the value of a passed argument, ABCORR. That's a no no. */ /* -& */ /* SPICELIB functions */ /* Local parameters */ /* Indices of flags in the FLAGS array: */ /* Local variables */ /* Saved variables */ /* Initial values */ /* Standard SPICE error handling. */ if (return_()) { return 0; } else { chkin_("ZZSPKAP1", (ftnlen)8); } if (first || s_cmp(abcorr, prvcor, abcorr_len, (ftnlen)5) != 0) { /* The aberration correction flag differs from the value it */ /* had on the previous call, if any. Analyze the new flag. */ /* Remove leading and embedded white space from the aberration */ /* correction flag and convert to upper case. */ ljucrs_(&c__0, abcorr, corr, abcorr_len, (ftnlen)5); /* Locate the flag in our list of flags. */ i__ = isrchc_(corr, &c__9, flags, (ftnlen)5, (ftnlen)5); if (i__ == 0) { setmsg_("Requested aberration correction # is not supported.", ( ftnlen)51); errch_("#", abcorr, (ftnlen)1, abcorr_len); sigerr_("SPICE(SPKINVALIDOPTION)", (ftnlen)23); chkout_("ZZSPKAP1", (ftnlen)8); return 0; } /* The aberration correction flag is recognized; save it. */ s_copy(prvcor, abcorr, (ftnlen)5, abcorr_len); /* Set logical flags indicating the attributes of the requested */ /* correction. */ xmit = i__ > 5; uselt = i__ == 2 || i__ == 3 || i__ == 6 || i__ == 7; usestl = i__ > 1 && odd_(&i__); usecn = i__ == 4 || i__ == 5 || i__ == 8 || i__ == 9; first = FALSE_; } /* See if the reference frame is a recognized inertial frame. */ irfnum_(ref, &refid, ref_len); if (refid == 0) { setmsg_("The requested frame '#' is not a recognized inertial frame. " , (ftnlen)60); errch_("#", ref, (ftnlen)1, ref_len); sigerr_("SPICE(BADFRAME)", (ftnlen)15); chkout_("ZZSPKAP1", (ftnlen)8); return 0; } /* Determine the sign of the light time offset. */ if (xmit) { ltsign = 1; } else { ltsign = -1; } /* Find the geometric state of the target body with respect to the */ /* solar system barycenter. Subtract the state of the observer */ /* to get the relative state. Use this to compute the one-way */ /* light time. */ zzspksb1_(targ, et, ref, starg, ref_len); vsubg_(starg, sobs, &c__6, tstate); moved_(tstate, &c__6, starg); *lt = vnorm_(starg) / clight_(); /* To correct for light time, find the state of the target body */ /* at the current epoch minus the one-way light time. Note that */ /* the observer remains where he is. */ if (uselt) { maxitr = 1; } else if (usecn) { maxitr = 3; } else { maxitr = 0; } i__1 = maxitr; for (i__ = 1; i__ <= i__1; ++i__) { d__1 = *et + ltsign * *lt; zzspksb1_(targ, &d__1, ref, starg, ref_len); vsubg_(starg, sobs, &c__6, tstate); moved_(tstate, &c__6, starg); *lt = vnorm_(starg) / clight_(); } /* At this point, STARG contains the light time corrected */ /* state of the target relative to the observer. */ /* If stellar aberration correction is requested, perform it now. */ /* Stellar aberration corrections are not applied to the target's */ /* velocity. */ if (usestl) { if (xmit) { /* This is the transmission case. */ /* Compute the position vector obtained by applying */ /* "reception" stellar aberration to STARG. */ stlabx_(starg, &sobs[3], sapos); vequ_(sapos, starg); } else { /* This is the reception case. */ /* Compute the position vector obtained by applying */ /* "reception" stellar aberration to STARG. */ stelab_(starg, &sobs[3], sapos); vequ_(sapos, starg); } } chkout_("ZZSPKAP1", (ftnlen)8); return 0; } /* zzspkap1_ */
/* $Procedure GFUDS ( GF, user defined scalar ) */ /* Subroutine */ int gfuds_(U_fp udfunc, U_fp udqdec, char *relate, doublereal *refval, doublereal *adjust, doublereal *step, doublereal * cnfine, integer *mw, integer *nw, doublereal *work, doublereal * result, ftnlen relate_len) { /* System generated locals */ integer work_dim1, work_offset, i__1; /* Local variables */ extern /* Subroutine */ int zzgfudlt_(); extern /* Subroutine */ int zzgfrelx_(U_fp, U_fp, U_fp, U_fp, U_fp, S_fp, char *, doublereal *, doublereal *, doublereal *, doublereal *, integer *, integer *, doublereal *, logical *, U_fp, U_fp, U_fp, char *, char *, logical *, L_fp, doublereal *, ftnlen, ftnlen, ftnlen), chkin_(char *, ftnlen), errdp_(char *, doublereal *, ftnlen); extern integer sized_(doublereal *); extern logical gfbail_(); extern /* Subroutine */ int scardd_(integer *, doublereal *); extern /* Subroutine */ int gfrefn_(), gfrepf_(), gfrepi_(), gfrepu_(), gfstep_(); char rptpre[1*2], rptsuf[1*2]; extern /* Subroutine */ int setmsg_(char *, ftnlen), sigerr_(char *, ftnlen), chkout_(char *, ftnlen), errint_(char *, integer *, ftnlen), gfsstp_(doublereal *); extern logical odd_(integer *); doublereal tol; extern /* Subroutine */ int zzgfref_(doublereal *); /* $ Abstract */ /* Perform a GF search on a user defined scalar quantity. */ /* $ 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 */ /* WINDOWS */ /* $ Keywords */ /* EVENT */ /* EPHEMERIS */ /* SEARCH */ /* WINDOW */ /* $ 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.0.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. */ /* 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. */ /* $ Brief_I/O */ /* Variable I/O Description */ /* -------- --- -------------------------------------------------- */ /* LBCELL P SPICE Cell lower bound. */ /* CNVTOL P Convergence tolerance. */ /* UDFUNC I Name of the routine that computes the scalar value */ /* of interest at some time. */ /* UDQDEC I Name of the routine that computes whether the */ /* current state is decreasing. */ /* RELATE I Operator that either looks for an extreme value */ /* (max, min, local, absolute) or compares the */ /* geometric quantity value and a number. */ /* REFVAL I Value used as reference for geometric quantity */ /* condition. */ /* ADJUST I Allowed variation for absolute extremal */ /* geometric conditions. */ /* STEP I Step size used for locating extrema and roots. */ /* CNFINE I SPICE window to which the search is confined. */ /* MW I Size of workspace windows. */ /* NW I Number of workspace windows. */ /* WORK I Array containing workspace windows. */ /* RESULT I-O SPICE window containing results. */ /* $ Detailed_Input */ /* UDFUNC the routine that returns the value of the scalar */ /* quantity of interest at time ET. The calling sequence */ /* for UDFUNC is: */ /* CALL UDFUNC ( ET, VALUE ) */ /* where: */ /* ET a double precision value representing */ /* ephemeris time, expressed as seconds past */ /* J2000 TDB, at which to determine the scalar */ /* value. */ /* VALUE is the value of the scalar quantity */ /* at ET. */ /* UDQDEC the name of the routine that determines if the scalar */ /* quantity calculated by UDFUNC is decreasing. */ /* The calling sequence: */ /* CALL UDQDEC ( UDFUNC, ET, ISDECR ) */ /* where: */ /* ET a double precision value representing */ /* ephemeris time, expressed as seconds past */ /* J2000 TDB, at which to determine the time */ /* derivative of UDFUNC. */ /* ISDECR a logical return indicating whether */ /* or not the scalar value returned by UDFUNC */ /* is decreasing. ISDECR returns true if the */ /* time derivative of UDFUNC at ET is */ /* negative. */ /* RELATE the scalar string comparison operator indicating */ /* the numeric constraint of interest. Values are: */ /* '>' value of scalar quantity greater than some */ /* reference (REFVAL). */ /* '=' value of scalar quantity equal to some */ /* reference (REFVAL). */ /* '<' value of scalar quantity less than some */ /* reference (REFVAL). */ /* 'ABSMAX' The scalar quantity is at an absolute */ /* maximum. */ /* 'ABSMIN' The scalar quantity is at an absolute */ /* minimum. */ /* 'LOCMAX' The scalar quantity is at a local */ /* maximum. */ /* 'LOCMIN' The scalar quantity is at a local */ /* minimum. */ /* The caller may indicate that the region of interest */ /* is the set of time intervals where the quantity is */ /* within a specified distance of an absolute extremum. */ /* The argument ADJUST (described below) is used to */ /* specified this distance. */ /* Local extrema are considered to exist only in the */ /* interiors of the intervals comprising the confinement */ /* window: a local extremum cannot exist at a boundary */ /* point of the confinement window. */ /* RELATE is insensitive to case, leading and */ /* trailing blanks. */ /* REFVAL is the reference value used to define an equality or */ /* inequality to satisfied by the scalar quantity. */ /* The units of REFVAL are those of the scalar quantity. */ /* ADJUST the amount by which the quantity is allowed to vary */ /* from an absolute extremum. */ /* If the search is for an absolute minimum is performed, */ /* the resulting window contains time intervals when the */ /* geometric quantity value has values between */ /* ABSMIN and ABSMIN + ADJUST. */ /* If the search is for an absolute maximum, the */ /* corresponding range is between ABSMAX - ADJUST and */ /* ABSMAX. */ /* ADJUST is not used for searches for local extrema, */ /* equality or inequality conditions and must have value */ /* zero for such searches. */ /* STEP the double precision time step size to use in */ /* the search. */ /* STEP must be short enough to for a search using this */ /* step size to locate the time intervals where the */ /* scalar quantity function is monotone increasing or */ /* decreasing. However, STEP must not be *too* short, */ /* or the search will take an unreasonable amount of time. */ /* The choice of STEP affects the completeness but not */ /* the precision of solutions found by this routine; the */ /* precision is controlled by the convergence tolerance. */ /* See the discussion of the parameter CNVTOL for */ /* details. */ /* STEP has units of TDB seconds. */ /* CNFINE is a SPICE window that confines the time period over */ /* which the specified search is conducted. CNFINE may */ /* consist of a single interval or a collection of */ /* intervals. */ /* In some cases the confinement window can be used to */ /* greatly reduce the time period that must be searched */ /* for the desired solution. See the Particulars section */ /* below for further discussion. */ /* See the Examples section below for a code example */ /* that shows how to create a confinement window. */ /* CNFINE must be initialized by the caller via the */ /* SPICELIB routine SSIZED. */ /* MW is a parameter specifying the length of the SPICE */ /* windows in the workspace array WORK (see description */ /* below) used by this routine. */ /* MW should be set to a number at least twice as large */ /* as the maximum number of intervals required by any */ /* workspace window. In many cases, it's not necessary to */ /* compute an accurate estimate of how many intervals are */ /* needed; rather, the user can pick a size considerably */ /* larger than what's really required. */ /* However, since excessively large arrays can prevent */ /* applications from compiling, linking, or running */ /* properly, sometimes MW must be set according to */ /* the actual workspace requirement. A rule of thumb */ /* for the number of intervals NINTVLS needed is */ /* NINTVLS = 2*N + ( M / STEP ) */ /* where */ /* N is the number of intervals in the confinement */ /* window */ /* M is the measure of the confinement window, in */ /* units of seconds */ /* STEP is the search step size in seconds */ /* MW should then be set to */ /* 2 * NINTVLS */ /* NW is a parameter specifying the number of SPICE windows */ /* in the workspace array WORK (see description below) */ /* used by this routine. (The reason this dimension is */ /* an input argument is that this allows run-time */ /* error checking to be performed.) */ /* NW must be at least as large as the parameter NWUDS. */ /* WORK is an array used to store workspace windows. This */ /* array should be declared by the caller as shown: */ /* DOUBLE PRECISION WORK ( LBCELL : MW, NW ) */ /* WORK need not be initialized by the caller. */ /* RESULT a double precision SPICE window which will contain the */ /* search results. RESULT must be declared and initialized */ /* with sufficient size to capture the full set of time */ /* intervals within the search region on which the */ /* specified constraint is satisfied. */ /* RESULT must be initialized by the caller via the */ /* SPICELIB routine SSIZED. */ /* If RESULT is non-empty on input, its contents */ /* will be discarded before GFUDS conducts its search. */ /* $ Detailed_Output */ /* WORK the input workspace array, modified by this */ /* routine. */ /* RESULT is a SPICE window containing the time intervals within */ /* the confinement window, during which the specified */ /* condition on the scalar quantity is met. */ /* If the search is for local extrema, or for absolute */ /* extrema with ADJUST set to zero, then normally each */ /* interval of RESULT will be a singleton: the left and */ /* right endpoints of each interval will be identical. */ /* If no times within the confinement window satisfy the */ /* search, RESULT will be returned with a cardinality */ /* of zero. */ /* $ Parameters */ /* LBCELL the integer value defining the lower bound for */ /* SPICE Cell arrays (a SPICE window is a kind of cell). */ /* CNVTOL is the convergence tolerance used for finding */ /* endpoints of the intervals comprising the result */ /* window. CNVTOL is also used for finding intermediate */ /* results; in particular, CNVTOL is used for finding the */ /* windows on which the range rate is increasing */ /* or decreasing. CNVTOL is used to determine when binary */ /* searches for roots should terminate: when a root is */ /* bracketed within an interval of length CNVTOL; the */ /* root is considered to have been found. */ /* The accuracy, as opposed to precision, of roots found */ /* by this routine depends on the accuracy of the input */ /* data. In most cases, the accuracy of solutions will be */ /* inferior to their precision. */ /* See INCLUDE file gf.inc for declarations and descriptions of */ /* parameters used throughout the GF system. */ /* $ Exceptions */ /* 1) In order for this routine to produce correct results, */ /* the step size must be appropriate for the problem at hand. */ /* Step sizes that are too large may cause this routine to miss */ /* roots; step sizes that are too small may cause this routine */ /* to run unacceptably slowly and in some cases, find spurious */ /* roots. */ /* This routine does not diagnose invalid step sizes, except */ /* that if the step size is non-positive, the error */ /* SPICE(INVALIDSTEP) is signaled. */ /* 2) Due to numerical errors, in particular, */ /* - truncation error in time values */ /* - finite tolerance value */ /* - errors in computed geometric quantities */ /* it is *normal* for the condition of interest to not always be */ /* satisfied near the endpoints of the intervals comprising the */ /* RESULT window. One technique to handle such a situation, */ /* slightly contract RESULT using the window routine WNCOND. */ /* 3) If the workspace window size MW is less than 2 or not an even */ /* value, the error SPICE(INVALIDDIMENSION) will signal. If the */ /* size of the workspace is too small, an error is signaled by a */ /* routine in the call tree of this routine. */ /* 4) If the size of the SPICE window RESULT is less than 2 or */ /* not an even value, the error SPICE(INVALIDDIMENSION) will */ /* signal. If RESULT has insufficient capacity to contain the */ /* number of intervals on which the specified distance condition */ /* is met, the error will be diagnosed by a routine in the call */ /* tree of this routine. */ /* 5) If the window count NW is less than NWUDS, the error */ /* SPICE(INVALIDDIMENSION) will be signaled. */ /* 6) If an error (typically cell overflow) occurs during */ /* window arithmetic, the error will be diagnosed by a routine */ /* in the call tree of this routine. */ /* 7) If the relational operator RELATE is not recognized, an */ /* error is signaled by a routine in the call tree of this */ /* routine. */ /* 8) If ADJUST is negative, the error SPICE(VALUEOUTOFRANGE) will */ /* signal from a routine in the call tree of this routine. */ /* A non-zero value for ADJUST when RELATE has any value other */ /* than "ABSMIN" or "ABSMAX" causes the error SPICE(INVALIDVALUE) */ /* to signal from a routine in the call tree of this routine. */ /* 9) If required ephemerides or other kernel data are not */ /* available, an error is signaled by a routine in the call tree */ /* of this routine. */ /* $ Files */ /* Appropriate kernels must be loaded by the calling program before */ /* this routine is called. */ /* If the scalar function requires access to ephemeris data: */ /* - SPK data: ephemeris data for any body over the */ /* time period defined by the confinement window 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. */ /* - If non-inertial reference frames are used, then PCK */ /* files, frame kernels, C-kernels, and SCLK kernels may be */ /* needed. */ /* In all cases, kernel data are normally loaded once per program */ /* run, NOT every time this routine is called. */ /* $ Particulars */ /* This routine determines a set of one or more time intervals */ /* within the confinement window when the scalar function */ /* satisfies a caller-specified constraint. The resulting set of */ /* intervals is returned as a SPICE window. */ /* UDQDEC Default Template */ /* ======================= */ /* The user must supply a routine to determine whether sign of the */ /* time derivative of UDFUNC is positive or negative at ET. For */ /* cases where UDFUNC is numerically well behaved, the user */ /* may find it convenient to use a routine based on the below */ /* template. UDDC determines the truth of the expression */ /* d (UDFUNC) */ /* -- < 0 */ /* dt */ /* using the library routine UDDF to numerically calculate the */ /* derivative of UDFUNC using a three-point estimation. */ /* Please see the Examples section for an example of GFDECR use. */ /* SUBROUTINE GFDECR ( UDFUNC, ET, ISDECR ) */ /* IMPLICIT NONE */ /* EXTERNAL UDFUNC */ /* EXTERNAL UDDF */ /* DOUBLE PRECISION ET */ /* LOGICAL ISDECR */ /* DOUBLE PRECISION DT */ /* DT = h, double precision interval size */ /* CALL UDDC ( UDFUNC, ET, DT, ISDECR ) */ /* END */ /* The Search Process */ /* ================== */ /* Regardless of the type of constraint selected by the caller, this */ /* routine starts the search for solutions by determining the time */ /* periods, within the confinement window, over which the specified */ /* scalar function is monotone increasing and monotone */ /* decreasing. Each of these time periods is represented by a SPICE */ /* window. Having found these windows, all of the quantity */ /* function's local extrema within the confinement window are known. */ /* Absolute extrema then can be found very easily. */ /* Within any interval of these "monotone" windows, there will be at */ /* most one solution of any equality constraint. Since the boundary */ /* of the solution set for any inequality constraint is the set */ /* of points where an equality constraint is met, the solutions of */ /* both equality and inequality constraints can be found easily */ /* once the monotone windows have been found. */ /* Step Size */ /* ========= */ /* The monotone windows (described above) are found using a two-step */ /* search process. Each interval of the confinement window is */ /* searched as follows: first, the input step size is used to */ /* determine the time separation at which the sign of the rate of */ /* change of quantity function will be sampled. Starting at */ /* the left endpoint of an interval, samples will be taken at each */ /* step. If a change of sign is found, a root has been bracketed; at */ /* that point, the time at which the time derivative of the quantity */ /* function is zero can be found by a refinement process, for */ /* example, using a binary search. */ /* Note that the optimal choice of step size depends on the lengths */ /* of the intervals over which the quantity function is monotone: */ /* the step size should be shorter than the shortest of these */ /* intervals (within the confinement window). */ /* The optimal step size is *not* necessarily related to the lengths */ /* of the intervals comprising the result window. For example, if */ /* the shortest monotone interval has length 10 days, and if the */ /* shortest result window interval has length 5 minutes, a step size */ /* of 9.9 days is still adequate to find all of the intervals in the */ /* result window. In situations like this, the technique of using */ /* monotone windows yields a dramatic efficiency improvement over a */ /* state-based search that simply tests at each step whether the */ /* specified constraint is satisfied. The latter type of search can */ /* miss solution intervals if the step size is shorter than the */ /* shortest solution interval. */ /* Having some knowledge of the relative geometry of the targets and */ /* observer can be a valuable aid in picking a reasonable step size. */ /* In general, the user can compensate for lack of such knowledge by */ /* picking a very short step size; the cost is increased computation */ /* time. */ /* Note that the step size is not related to the precision with which */ /* the endpoints of the intervals of the result window are computed. */ /* That precision level is controlled by the convergence tolerance. */ /* Convergence Tolerance */ /* ===================== */ /* Once a root has been bracketed, a refinement process is used to */ /* narrow down the time interval within which the root must lie. */ /* This refinement process terminates when the location of the root */ /* has been determined to within an error margin called the */ /* "convergence tolerance." */ /* The GF subsystem defines a parameter, CNVTOL (from gf.inc), as a */ /* default tolerance. This represents a "tight" tolerance value */ /* so that the tolerance doesn't become the limiting factor in the */ /* accuracy of solutions found by this routine. In general the */ /* accuracy of input data will be the limiting factor. */ /* Making the tolerance tighter than CNVTOL is unlikely to */ /* be useful, since the results are unlikely to be more accurate. */ /* Making the tolerance looser will speed up searches somewhat, */ /* since a few convergence steps will be omitted. However, in most */ /* cases, the step size is likely to have a much greater affect */ /* on processing time than would the convergence tolerance. */ /* The Confinement Window */ /* ====================== */ /* The simplest use of the confinement window is to specify a time */ /* interval within which a solution is sought. However, the */ /* confinement window can, in some cases, be used to make searches */ /* more efficient. Sometimes it's possible to do an efficient search */ /* to reduce the size of the time period over which a relatively */ /* slow search of interest must be performed. */ /* $ Examples */ /* The numerical results shown for these examples may differ across */ /* platforms. The results depend on the SPICE kernels used as */ /* input, the compiler and supporting libraries, and the machine */ /* specific arithmetic implementation. */ /* Conduct a search on the range-rate of the vector from the Sun */ /* to the Moon. Define a function to calculate the value. */ /* Use the meta-kernel shown below to load the required SPICE */ /* kernels. */ /* KPL/MK */ /* File name: standard.tm */ /* This meta-kernel is intended to support operation of SPICE */ /* example programs. The kernels shown here should not be */ /* assumed to contain adequate or correct versions of data */ /* required by SPICE-based user applications. */ /* In order for an application to use this meta-kernel, the */ /* kernels referenced here must be present in the user's */ /* current working directory. */ /* \begindata */ /* KERNELS_TO_LOAD = ( 'de414.bsp', */ /* 'pck00008.tpc', */ /* 'naif0009.tls' ) */ /* \begintext */ /* Code: */ /* PROGRAM GFUDS_T */ /* IMPLICIT NONE */ /* C */ /* C Include GF parameter declarations: */ /* C */ /* INCLUDE 'gf.inc' */ /* EXTERNAL GFQ */ /* EXTERNAL GFDECR */ /* C */ /* C SPICELIB functions */ /* C */ /* DOUBLE PRECISION SPD */ /* DOUBLE PRECISION DVNORM */ /* INTEGER WNCARD */ /* C */ /* C Local parameters */ /* C */ /* INTEGER LBCELL */ /* PARAMETER ( LBCELL = -5 ) */ /* C */ /* C Use the parameter MAXWIN for both the result window size */ /* C and the workspace size. */ /* C */ /* INTEGER MAXWIN */ /* PARAMETER ( MAXWIN = 20000 ) */ /* C */ /* C Length of strings: */ /* C */ /* INTEGER TIMLEN */ /* PARAMETER ( TIMLEN = 26 ) */ /* INTEGER NLOOPS */ /* PARAMETER ( NLOOPS = 7 ) */ /* C */ /* C Local variables */ /* C */ /* CHARACTER*(TIMLEN) TIMSTR */ /* CHARACTER*(TIMLEN) RELATE (NLOOPS) */ /* DOUBLE PRECISION ADJUST */ /* DOUBLE PRECISION CNFINE ( LBCELL : 2 ) */ /* DOUBLE PRECISION DRDT */ /* DOUBLE PRECISION ET0 */ /* DOUBLE PRECISION ET1 */ /* DOUBLE PRECISION FINISH */ /* DOUBLE PRECISION LT */ /* DOUBLE PRECISION POS ( 6 ) */ /* DOUBLE PRECISION REFVAL */ /* DOUBLE PRECISION RESULT ( LBCELL : MAXWIN ) */ /* DOUBLE PRECISION START */ /* DOUBLE PRECISION STEP */ /* DOUBLE PRECISION WORK ( LBCELL : MAXWIN, NWUDS ) */ /* INTEGER I */ /* INTEGER J */ /* DATA RELATE / '=', */ /* . '<', */ /* . '>', */ /* . 'LOCMIN', */ /* . 'ABSMIN', */ /* . 'LOCMAX', */ /* . 'ABSMAX' / */ /* C */ /* C Load kernels. */ /* C */ /* CALL FURNSH ( 'standard.tm' ) */ /* C */ /* C Initialize windows. */ /* C */ /* CALL SSIZED ( MAXWIN, RESULT ) */ /* CALL SSIZED ( 2, CNFINE ) */ /* CALL SCARDD ( 0, CNFINE ) */ /* C */ /* C Store the time bounds of our search interval in */ /* C the confinement window. */ /* C */ /* CALL STR2ET ( '2007 JAN 1', ET0 ) */ /* CALL STR2ET ( '2007 APR 1', ET1 ) */ /* CALL WNINSD ( ET0, ET1, CNFINE ) */ /* C */ /* C Search using a step size of 1 day (in units of seconds). */ /* C The reference value is .3365 km/s - a range rate value known */ /* C to exist during the confinement window. We're not using the */ /* C adjustment feature, so we set ADJUST to zero. */ /* C */ /* STEP = SPD() */ /* REFVAL = .3365D0 */ /* ADJUST = 0.D0 */ /* DO J=1, NLOOPS */ /* WRITE(*,*) 'Relation condition: ', RELATE(J) */ /* C */ /* C Perform the search. The SPICE window RESULT contains */ /* C the set of times when the condition is met. */ /* C */ /* CALL GFUDS ( GFQ, GFDECR, */ /* . RELATE(J), REFVAL, ADJUST, STEP, CNFINE, */ /* . MAXWIN, NWUDS, WORK, RESULT ) */ /* C */ /* C Display the results. */ /* C */ /* IF ( WNCARD(RESULT) .EQ. 0 ) THEN */ /* WRITE (*, '(A)') 'Result window is empty.' */ /* ELSE */ /* DO I = 1, WNCARD(RESULT) */ /* C */ /* C Fetch the endpoints of the Ith interval */ /* C of the result window. */ /* C */ /* CALL WNFETD ( RESULT, I, START, FINISH ) */ /* CALL SPKEZR ( 'MOON', START, 'J2000', 'NONE', */ /* . 'SUN', POS, LT ) */ /* DRDT = DVNORM(POS) */ /* CALL TIMOUT ( START, 'YYYY-MON-DD HR:MN:SC.###', */ /* . TIMSTR ) */ /* WRITE (*, '(A,F16.9)' ) 'Start time, drdt = '// */ /* . TIMSTR, DRDT */ /* CALL SPKEZR ( 'MOON', FINISH, 'J2000', 'NONE', */ /* . 'SUN', POS, LT ) */ /* DRDT = DVNORM(POS) */ /* CALL TIMOUT ( FINISH, 'YYYY-MON-DD HR:MN:SC.###', */ /* . TIMSTR ) */ /* WRITE (*, '(A,F16.9)' ) 'Stop time, drdt = '// */ /* . TIMSTR, DRDT */ /* END DO */ /* END IF */ /* WRITE(*,*) ' ' */ /* END DO */ /* END */ /* C-Procedure GFQ */ /* SUBROUTINE GFQ ( ET, VALUE ) */ /* IMPLICIT NONE */ /* C- Abstract */ /* C */ /* C User defined geometric quantity function. In this case, */ /* C the range from the sun to the Moon at TDB time ET. */ /* C */ /* DOUBLE PRECISION ET */ /* DOUBLE PRECISION VALUE */ /* C */ /* C Local variables. */ /* C */ /* INTEGER TARG */ /* INTEGER OBS */ /* CHARACTER*(12) REF */ /* CHARACTER*(12) ABCORR */ /* DOUBLE PRECISION STATE ( 6 ) */ /* DOUBLE PRECISION LT */ /* DOUBLE PRECISION DVNORM */ /* C */ /* C Initialization. Retrieve the vector from the Sun to */ /* C the Moon in the J2000 frame, without aberration */ /* C correction. */ /* C */ /* TARG = 301 */ /* REF = 'J2000' */ /* ABCORR = 'NONE' */ /* OBS = 10 */ /* CALL SPKEZ ( TARG, ET, REF, ABCORR, OBS, STATE, LT ) */ /* C */ /* C Calculate the scalar range rate corresponding the */ /* C STATE vector. */ /* C */ /* VALUE = DVNORM( STATE ) */ /* END */ /* C-Procedure GFDECR */ /* SUBROUTINE GFDECR ( UDFUNC, ET, ISDECR ) */ /* IMPLICIT NONE */ /* C- Abstract */ /* C */ /* C User defined function to detect if the function derivative */ /* C is negative (the function is decreasing) at TDB time ET. */ /* C */ /* EXTERNAL UDFUNC */ /* EXTERNAL UDDF */ /* DOUBLE PRECISION ET */ /* LOGICAL ISDECR */ /* DOUBLE PRECISION DT */ /* DT = 1.D0 */ /* C */ /* C Determine if GFQ is decreasing at ET. */ /* C */ /* C UDDC - the default GF function to determine if */ /* C the derivative of the user defined */ /* C function is negative at ET. */ /* C */ /* C UDFUNC - the user defined scalar quantity function. */ /* C */ /* CALL UDDC ( UDFUNC, ET, DT, ISDECR ) */ /* END */ /* The program outputs: */ /* Relation condition: = */ /* Start time, drdt = 2007-JAN-02 00:35:19.574 0.336500000 */ /* Stop time, drdt = 2007-JAN-02 00:35:19.574 0.336500000 */ /* Start time, drdt = 2007-JAN-19 22:04:54.899 0.336500000 */ /* Stop time, drdt = 2007-JAN-19 22:04:54.899 0.336500000 */ /* Start time, drdt = 2007-FEB-01 23:30:13.428 0.336500000 */ /* Stop time, drdt = 2007-FEB-01 23:30:13.428 0.336500000 */ /* Start time, drdt = 2007-FEB-17 11:10:46.540 0.336500000 */ /* Stop time, drdt = 2007-FEB-17 11:10:46.540 0.336500000 */ /* Start time, drdt = 2007-MAR-04 15:50:19.929 0.336500000 */ /* Stop time, drdt = 2007-MAR-04 15:50:19.929 0.336500000 */ /* Start time, drdt = 2007-MAR-18 09:59:05.959 0.336500000 */ /* Stop time, drdt = 2007-MAR-18 09:59:05.959 0.336500000 */ /* Relation condition: < */ /* Start time, drdt = 2007-JAN-02 00:35:19.574 0.336500000 */ /* Stop time, drdt = 2007-JAN-19 22:04:54.899 0.336500000 */ /* Start time, drdt = 2007-FEB-01 23:30:13.428 0.336500000 */ /* Stop time, drdt = 2007-FEB-17 11:10:46.540 0.336500000 */ /* Start time, drdt = 2007-MAR-04 15:50:19.929 0.336500000 */ /* Stop time, drdt = 2007-MAR-18 09:59:05.959 0.336500000 */ /* Relation condition: > */ /* Start time, drdt = 2007-JAN-01 00:00:00.000 0.515522367 */ /* Stop time, drdt = 2007-JAN-02 00:35:19.574 0.336500000 */ /* Start time, drdt = 2007-JAN-19 22:04:54.899 0.336500000 */ /* Stop time, drdt = 2007-FEB-01 23:30:13.428 0.336500000 */ /* Start time, drdt = 2007-FEB-17 11:10:46.540 0.336500000 */ /* Stop time, drdt = 2007-MAR-04 15:50:19.929 0.336500000 */ /* Start time, drdt = 2007-MAR-18 09:59:05.959 0.336500000 */ /* Stop time, drdt = 2007-APR-01 00:00:00.000 0.793546222 */ /* Relation condition: LOCMIN */ /* Start time, drdt = 2007-JAN-11 07:03:58.988 -0.803382743 */ /* Stop time, drdt = 2007-JAN-11 07:03:58.988 -0.803382743 */ /* Start time, drdt = 2007-FEB-10 06:26:15.439 -0.575837623 */ /* Stop time, drdt = 2007-FEB-10 06:26:15.439 -0.575837623 */ /* Start time, drdt = 2007-MAR-12 03:28:36.404 -0.441800446 */ /* Stop time, drdt = 2007-MAR-12 03:28:36.404 -0.441800446 */ /* Relation condition: ABSMIN */ /* Start time, drdt = 2007-JAN-11 07:03:58.988 -0.803382743 */ /* Stop time, drdt = 2007-JAN-11 07:03:58.988 -0.803382743 */ /* Relation condition: LOCMAX */ /* Start time, drdt = 2007-JAN-26 02:27:33.766 1.154648992 */ /* Stop time, drdt = 2007-JAN-26 02:27:33.766 1.154648992 */ /* Start time, drdt = 2007-FEB-24 09:35:07.816 1.347132236 */ /* Stop time, drdt = 2007-FEB-24 09:35:07.816 1.347132236 */ /* Start time, drdt = 2007-MAR-25 17:26:56.150 1.428141707 */ /* Stop time, drdt = 2007-MAR-25 17:26:56.150 1.428141707 */ /* Relation condition: ABSMAX */ /* Start time, drdt = 2007-MAR-25 17:26:56.150 1.428141707 */ /* Stop time, drdt = 2007-MAR-25 17:26:56.150 1.428141707 */ /* $ Restrictions */ /* 1) Any kernel files required by this routine must be loaded */ /* (normally via the SPICELIB routine FURNSH) before this routine */ /* is called. */ /* $ Literature_References */ /* None. */ /* $ Author_and_Institution */ /* N.J. Bachman (JPL) */ /* E.D. Wright (JPL) */ /* $ Version */ /* - SPICELIB Version 1.0.0 16-FEB-2010 (EDW) */ /* -& */ /* $ Index_Entries */ /* GF user defined scalar function search */ /* -& */ /* SPICELIB functions. */ /* Local variables. */ /* Dummy variables. */ /* Parameter adjustments */ work_dim1 = *mw + 6; work_offset = work_dim1 - 5; /* Function Body */ chkin_("GFUDS", (ftnlen)5); /* Check the step size. */ if (*step <= 0.) { setmsg_("Step size was #; step size must be positive.", (ftnlen)44); errdp_("#", step, (ftnlen)1); sigerr_("SPICE(INVALIDSTEP)", (ftnlen)18); chkout_("GFUDS", (ftnlen)5); return 0; } /* Confirm minimum number of windows. */ if (*nw < 5) { setmsg_("Workspace window count was #; count must be at least #.", ( ftnlen)55); errint_("#", nw, (ftnlen)1); errint_("#", &c__5, (ftnlen)1); sigerr_("SPICE(INVALIDDIMENSION)", (ftnlen)23); chkout_("GFUDS", (ftnlen)5); return 0; } /* Confirm minimum window sizes. */ if (*mw < 2 || odd_(mw)) { setmsg_("Workspace window size was #; size must be at least 2 and an" " even value.", (ftnlen)71); errint_("#", mw, (ftnlen)1); sigerr_("SPICE(INVALIDDIMENSION)", (ftnlen)23); chkout_("GFUDS", (ftnlen)5); return 0; } /* Check the result window size. */ i__1 = sized_(result); if (sized_(result) < 2 || odd_(&i__1)) { setmsg_("Result window size was #; size must be at least 2 and an ev" "en value.", (ftnlen)68); i__1 = sized_(result); errint_("#", &i__1, (ftnlen)1); sigerr_("SPICE(INVALIDDIMENSION)", (ftnlen)23); chkout_("GFUDS", (ftnlen)5); return 0; } /* Set the step size. */ gfsstp_(step); /* Set the reference value. */ zzgfref_(refval); /* Use the default GF convergence tolerance. */ tol = 1e-6; /* Initialize the RESULT window to empty. */ scardd_(&c__0, result); /* Call ZZGFRELX to do the event detection work. */ zzgfrelx_((U_fp)gfstep_, (U_fp)gfrefn_, (U_fp)udqdec, (U_fp)zzgfudlt_, ( U_fp)udfunc, (S_fp)zzgfref_, relate, refval, &tol, adjust, cnfine, mw, nw, work, &c_false, (U_fp)gfrepi_, (U_fp)gfrepu_, (U_fp) gfrepf_, rptpre, rptsuf, &c_false, (L_fp)gfbail_, result, relate_len, (ftnlen)1, (ftnlen)1); chkout_("GFUDS", (ftnlen)5); return 0; } /* gfuds_ */
/* $Procedure CKR05 ( Read CK record from segment, type 05 ) */ /* Subroutine */ int ckr05_(integer *handle, doublereal *descr, doublereal * sclkdp, doublereal *tol, logical *needav, doublereal *record, logical *found) { /* Initialized data */ static integer lbeg = -1; static integer lend = -1; static integer lhand = 0; static doublereal prevn = -1.; static doublereal prevnn = -1.; static doublereal prevs = -1.; /* System generated locals */ integer i__1, i__2; doublereal d__1, d__2; /* Builtin functions */ integer i_dnnt(doublereal *), s_rnge(char *, integer, char *, integer); /* Local variables */ integer high; doublereal rate; integer last, type__, i__, j, n; doublereal t; integer begin; extern /* Subroutine */ int chkin_(char *, ftnlen), dafus_(doublereal *, integer *, integer *, doublereal *, integer *); integer nidir; extern doublereal dpmax_(void); extern /* Subroutine */ int moved_(doublereal *, integer *, doublereal *); integer npdir, nsrch; extern /* Subroutine */ int errdp_(char *, doublereal *, ftnlen); integer lsize, first, nints, rsize; doublereal start; extern /* Subroutine */ int dafgda_(integer *, integer *, integer *, doublereal *); doublereal dc[2]; integer ic[6]; extern logical failed_(void); integer bufbas, dirbas; doublereal hepoch; extern doublereal brcktd_(doublereal *, doublereal *, doublereal *); doublereal lepoch; integer npread, nsread, remain, pbegix, sbegix, timbas; doublereal pbuffr[101]; extern integer lstled_(doublereal *, integer *, doublereal *); doublereal sbuffr[103]; integer pendix, sendix, packsz; extern /* Subroutine */ int sigerr_(char *, ftnlen), chkout_(char *, ftnlen); integer maxwnd; doublereal contrl[5]; extern /* Subroutine */ int setmsg_(char *, ftnlen), errint_(char *, integer *, ftnlen); extern integer lstltd_(doublereal *, integer *, doublereal *); doublereal nstart; extern logical return_(void); integer pgroup, sgroup, wndsiz, wstart, subtyp; doublereal nnstrt; extern logical odd_(integer *); integer end, low; /* $ Abstract */ /* Read a single CK data record from a segment of type 05 */ /* (MEX/Rosetta Attitude file interpolation). */ /* $ 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 */ /* CK */ /* $ Keywords */ /* POINTING */ /* $ Declarations */ /* $ Abstract */ /* Declare parameters specific to CK type 05. */ /* $ 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 */ /* CK */ /* $ Keywords */ /* CK */ /* $ Restrictions */ /* None. */ /* $ Author_and_Institution */ /* N.J. Bachman (JPL) */ /* $ Literature_References */ /* None. */ /* $ Version */ /* - SPICELIB Version 1.0.0, 20-AUG-2002 (NJB) */ /* -& */ /* CK type 5 subtype codes: */ /* Subtype 0: Hermite interpolation, 8-element packets. Quaternion */ /* and quaternion derivatives only, no angular velocity */ /* vector provided. Quaternion elements are listed */ /* first, followed by derivatives. Angular velocity is */ /* derived from the quaternions and quaternion */ /* derivatives. */ /* Subtype 1: Lagrange interpolation, 4-element packets. Quaternion */ /* only. Angular velocity is derived by differentiating */ /* the interpolating polynomials. */ /* Subtype 2: Hermite interpolation, 14-element packets. */ /* Quaternion and angular angular velocity vector, as */ /* well as derivatives of each, are provided. The */ /* quaternion comes first, then quaternion derivatives, */ /* then angular velocity and its derivatives. */ /* Subtype 3: Lagrange interpolation, 7-element packets. Quaternion */ /* and angular velocity vector provided. The quaternion */ /* comes first. */ /* Packet sizes associated with the various subtypes: */ /* End of file ck05.inc. */ /* $ Abstract */ /* Declarations of the CK data type specific and general CK low */ /* level routine parameters. */ /* $ 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 */ /* CK.REQ */ /* $ Keywords */ /* CK */ /* $ Restrictions */ /* 1) If new CK types are added, the size of the record passed */ /* between CKRxx and CKExx must be registered as separate */ /* parameter. If this size will be greater than current value */ /* of the CKMRSZ parameter (which specifies the maximum record */ /* size for the record buffer used inside CKPFS) then it should */ /* be assigned to CKMRSZ as a new value. */ /* $ Author_and_Institution */ /* N.J. Bachman (JPL) */ /* B.V. Semenov (JPL) */ /* $ Literature_References */ /* CK Required Reading. */ /* $ Version */ /* - SPICELIB Version 2.0.0, 19-AUG-2002 (NJB) */ /* Updated to support CK type 5. */ /* - SPICELIB Version 1.0.0, 05-APR-1999 (BVS) */ /* -& */ /* Number of quaternion components and number of quaternion and */ /* angular rate components together. */ /* CK Type 1 parameters: */ /* CK1DTP CK data type 1 ID; */ /* CK1RSZ maximum size of a record passed between CKR01 */ /* and CKE01. */ /* CK Type 2 parameters: */ /* CK2DTP CK data type 2 ID; */ /* CK2RSZ maximum size of a record passed between CKR02 */ /* and CKE02. */ /* CK Type 3 parameters: */ /* CK3DTP CK data type 3 ID; */ /* CK3RSZ maximum size of a record passed between CKR03 */ /* and CKE03. */ /* CK Type 4 parameters: */ /* CK4DTP CK data type 4 ID; */ /* CK4PCD parameter defining integer to DP packing schema that */ /* is applied when seven number integer array containing */ /* polynomial degrees for quaternion and angular rate */ /* components packed into a single DP number stored in */ /* actual CK records in a file; the value of must not be */ /* changed or compatibility with existing type 4 CK files */ /* will be lost. */ /* CK4MXD maximum Chebychev polynomial degree allowed in type 4 */ /* records; the value of this parameter must never exceed */ /* value of the CK4PCD; */ /* CK4SFT number of additional DPs, which are not polynomial */ /* coefficients, located at the beginning of a type 4 */ /* CK record that passed between routines CKR04 and CKE04; */ /* CK4RSZ maximum size of type 4 CK record passed between CKR04 */ /* and CKE04; CK4RSZ is computed as follows: */ /* CK4RSZ = ( CK4MXD + 1 ) * QAVSIZ + CK4SFT */ /* CK Type 5 parameters: */ /* CK5DTP CK data type 5 ID; */ /* CK5MXD maximum polynomial degree allowed in type 5 */ /* records. */ /* CK5MET number of additional DPs, which are not polynomial */ /* coefficients, located at the beginning of a type 5 */ /* CK record that passed between routines CKR05 and CKE05; */ /* CK5MXP maximum packet size for any subtype. Subtype 2 */ /* has the greatest packet size, since these packets */ /* contain a quaternion, its derivative, an angular */ /* velocity vector, and its derivative. See ck05.inc */ /* for a description of the subtypes. */ /* CK5RSZ maximum size of type 5 CK record passed between CKR05 */ /* and CKE05; CK5RSZ is computed as follows: */ /* CK5RSZ = ( CK5MXD + 1 ) * CK5MXP + CK5MET */ /* Maximum record size that can be handled by CKPFS. This value */ /* must be set to the maximum of all CKxRSZ parameters (currently */ /* CK4RSZ.) */ /* $ Brief_I/O */ /* Variable I/O Description */ /* -------- --- -------------------------------------------------- */ /* HANDLE I File handle. */ /* DESCR I Segment descriptor. */ /* SCLKDP I Pointing request time. */ /* TOL I Lookup tolerance. */ /* NEEDAV I Angular velocity flag. */ /* RECORD O Data record. */ /* FOUND O Flag indicating whether record was found. */ /* $ Detailed_Input */ /* HANDLE, */ /* DESCR are the file handle and segment descriptor for */ /* a CK segment of type 05. */ /* SCLKDP is an encoded spacecraft clock time indicating */ /* the epoch for which pointing is desired. */ /* TOL is a time tolerance, measured in the same units as */ /* encoded spacecraft clock. */ /* When SCLKDP falls within the bounds of one of the */ /* interpolation intervals then the tolerance has no */ /* effect because pointing will be returned at the */ /* request time. */ /* However, if the request time is not in one of the */ /* intervals, then the tolerance is used to determine */ /* if pointing at one of the interval endpoints should */ /* be returned. */ /* NEEDAV is true if angular velocity is requested. */ /* $ Detailed_Output */ /* RECORD is a set of data from the specified segment which, */ /* when evaluated at epoch SCLKDP, will give the */ /* attitude and angular velocity of some body, relative */ /* to the reference frame indicated by DESCR. */ /* The structure of the record is as follows: */ /* +----------------------+ */ /* | evaluation epoch | */ /* +----------------------+ */ /* | subtype code | */ /* +----------------------+ */ /* | number of packets (n)| */ /* +----------------------+ */ /* | nominal SCLK rate | */ /* +----------------------+ */ /* | packet 1 | */ /* +----------------------+ */ /* | packet 2 | */ /* +----------------------+ */ /* . */ /* . */ /* . */ /* +----------------------+ */ /* | packet n | */ /* +----------------------+ */ /* | epochs 1--n | */ /* +----------------------+ */ /* The packet size is a function of the subtype code. */ /* All packets in a record have the same size. */ /* $ Parameters */ /* None. */ /* $ Exceptions */ /* This routine follows the pattern established in the lower-numbered */ /* CK data type readers of not explicitly performing error */ /* diagnoses. Exceptions are listed below nonetheless. */ /* 1) If the input HANDLE does not designate a loaded CK file, the */ /* error will be diagnosed by routines called by this routine. */ /* 2) If the segment specified by DESCR is not of data type 05, */ /* the error 'SPICE(WRONGCKTYPE)' is signaled. */ /* 3) If the input SCLK value is not within the range specified */ /* in the segment descriptor, the error SPICE(TIMEOUTOFBOUNDS) */ /* is signaled. */ /* 4) If the window size is non-positive or greater than the */ /* maximum allowed value, the error SPICE(INVALIDVALUE) is */ /* signaled. */ /* 5) If the window size is not compatible with the segment */ /* subtype, the error SPICE(INVALIDVALUE) is signaled. */ /* 6) If the segment subtype is not recognized, the error */ /* SPICE(NOTSUPPORTED) is signaled. */ /* 7) If the tolerance is negative, the error SPICE(VALUEOUTOFRANGE) */ /* is signaled. */ /* $ Files */ /* See argument HANDLE. */ /* $ Particulars */ /* See the CK Required Reading file for a description of the */ /* structure of a data type 05 segment. */ /* $ Examples */ /* The data returned by the CKRnn 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 CKRxx */ /* routines might be used to "dump" and check segment data for a */ /* particular epoch. */ /* C */ /* C Get a segment applicable to a specified body and epoch. */ /* C */ /* C CALL CKBSS ( INST, SCLKDP, TOL, NEEDAV ) */ /* CALL CKSNS ( HANDLE, DESCR, SEGID, SFND ) */ /* IF ( .NOT. SFND ) THEN */ /* [Handle case of pointing not being found] */ /* END IF */ /* 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. 05 ) THEN */ /* CALL CKR05 ( HANDLE, DESCR, SCLKDP, TOL, NEEDAV, */ /* . RECORD, FOUND ) */ /* IF ( .NOT. FOUND ) THEN */ /* [Handle case of pointing not being found] */ /* END IF */ /* [Look at the RECORD data] */ /* . */ /* . */ /* . */ /* END IF */ /* $ Restrictions */ /* 1) Correctness of inputs must be ensured by the caller of */ /* this routine. */ /* $ Literature_References */ /* None. */ /* $ Author_and_Institution */ /* N.J. Bachman (JPL) */ /* $ Version */ /* - SPICELIB Version 1.1.0, 06-SEP-2002 (NJB) */ /* -& */ /* $ Index_Entries */ /* read record from type_5 ck segment */ /* -& */ /* $ Revisions */ /* -& */ /* SPICELIB functions */ /* Local parameters */ /* Maximum polynomial degree: */ /* Local variables */ /* Saved variables */ /* Initial values */ /* Standard SPICE error handling. */ if (return_()) { return 0; } chkin_("CKR05", (ftnlen)5); /* No pointing found so far. */ *found = FALSE_; /* Unpack the segment descriptor, and get the start and end addresses */ /* of the segment. */ dafus_(descr, &c__2, &c__6, dc, ic); type__ = ic[2]; begin = ic[4]; end = ic[5]; /* Make sure that this really is a type 05 data segment. */ if (type__ != 5) { setmsg_("You are attempting to locate type * data in a type 5 data s" "egment.", (ftnlen)66); errint_("*", &type__, (ftnlen)1); sigerr_("SPICE(WRONGCKTYPE)", (ftnlen)18); chkout_("CKR05", (ftnlen)5); return 0; } /* Check the tolerance value. */ if (*tol < 0.) { setmsg_("Tolerance must be non-negative but was actually *.", (ftnlen) 50); errdp_("*", tol, (ftnlen)1); sigerr_("SPICE(VALUEOUTOFRANGE)", (ftnlen)22); chkout_("CKR05", (ftnlen)5); return 0; } /* Check the request time and tolerance against the bounds in */ /* the segment descriptor. */ if (*sclkdp + *tol < dc[0] || *sclkdp - *tol > dc[1]) { /* The request time is too far outside the segment's coverage */ /* interval for any pointing to satisfy the request. */ chkout_("CKR05", (ftnlen)5); return 0; } /* Set the request time to use for searching. */ t = brcktd_(sclkdp, dc, &dc[1]); /* From this point onward, we assume the segment was constructed */ /* correctly. In particular, we assume: */ /* 1) The segment descriptor's time bounds are in order and are */ /* distinct. */ /* 2) The epochs in the segment are in strictly increasing */ /* order. */ /* 3) The interpolation interval start times in the segment are */ /* in strictly increasing order. */ /* 4) The degree of the interpolating polynomial specified by */ /* the segment is at least 1 and is no larger than MAXDEG. */ i__1 = end - 4; dafgda_(handle, &i__1, &end, contrl); /* Check the FAILED flag just in case HANDLE is not attached to */ /* any DAF file and the error action is not set to ABORT. We */ /* do this only after the first call to DAFGDA, as in CKR03. */ if (failed_()) { chkout_("CKR05", (ftnlen)5); return 0; } rate = contrl[0]; subtyp = i_dnnt(&contrl[1]); wndsiz = i_dnnt(&contrl[2]); nints = i_dnnt(&contrl[3]); n = i_dnnt(&contrl[4]); /* Set the packet size, which is a function of the subtype. */ if (subtyp == 0) { packsz = 8; } else if (subtyp == 1) { packsz = 4; } else if (subtyp == 2) { packsz = 14; } else if (subtyp == 3) { packsz = 7; } else { setmsg_("Unexpected CK type 5 subtype # found in type 5 segment.", ( ftnlen)55); errint_("#", &subtyp, (ftnlen)1); sigerr_("SPICE(NOTSUPPORTED)", (ftnlen)19); chkout_("CKR05", (ftnlen)5); return 0; } /* Check the window size. */ if (wndsiz <= 0) { setmsg_("Window size in type 05 segment was #; must be positive.", ( ftnlen)55); errint_("#", &wndsiz, (ftnlen)1); sigerr_("SPICE(INVALIDVALUE)", (ftnlen)19); chkout_("CKR05", (ftnlen)5); return 0; } if (subtyp == 0 || subtyp == 2) { /* These are the Hermite subtypes. */ maxwnd = 8; if (wndsiz > maxwnd) { setmsg_("Window size in type 05 segment was #; max allowed value" " is # for subtypes 0 and 2 (Hermite, 8 or 14-element pac" "kets).", (ftnlen)117); errint_("#", &wndsiz, (ftnlen)1); errint_("#", &maxwnd, (ftnlen)1); sigerr_("SPICE(INVALIDVALUE)", (ftnlen)19); chkout_("CKR05", (ftnlen)5); return 0; } if (odd_(&wndsiz)) { setmsg_("Window size in type 05 segment was #; must be even for " "subtypes 0 and 2 (Hermite, 8 or 14-element packets).", ( ftnlen)107); errint_("#", &wndsiz, (ftnlen)1); sigerr_("SPICE(INVALIDVALUE)", (ftnlen)19); chkout_("CKR05", (ftnlen)5); return 0; } } else if (subtyp == 1 || subtyp == 3) { /* These are the Lagrange subtypes. */ maxwnd = 16; if (wndsiz > maxwnd) { setmsg_("Window size in type 05 segment was #; max allowed value" " is # for subtypes 1 and 3 (Lagrange, 4 or 7-element pac" "kets).", (ftnlen)117); errint_("#", &wndsiz, (ftnlen)1); errint_("#", &maxwnd, (ftnlen)1); sigerr_("SPICE(INVALIDVALUE)", (ftnlen)19); chkout_("CKR05", (ftnlen)5); return 0; } if (odd_(&wndsiz)) { setmsg_("Window size in type 05 segment was #; must be even for " "subtypes 1 and 3 (Lagrange, 4 or 7-element packets).", ( ftnlen)107); errint_("#", &wndsiz, (ftnlen)1); sigerr_("SPICE(INVALIDVALUE)", (ftnlen)19); chkout_("CKR05", (ftnlen)5); return 0; } } else { setmsg_("This point should not be reached. Getting here may indicate" " that the code needs to updated to handle the new subtype #", (ftnlen)118); errint_("#", &subtyp, (ftnlen)1); sigerr_("SPICE(NOTSUPPORTED)", (ftnlen)19); chkout_("CKR05", (ftnlen)5); return 0; } /* We now need to select the pointing values to interpolate */ /* in order to satisfy the pointing request. The first step */ /* is to use the pointing directories (if any) to locate a set of */ /* epochs bracketing the request time. Note that the request */ /* time might not be bracketed: it could precede the first */ /* epoch or follow the last epoch. */ /* We'll use the variable PGROUP to refer to the set of epochs */ /* to search. The first group consists of the epochs prior to */ /* and including the first pointing directory entry. The last */ /* group consists of the epochs following the last pointing */ /* directory entry. Other groups consist of epochs following */ /* one pointing directory entry up to and including the next */ /* pointing directory entry. */ npdir = (n - 1) / 100; dirbas = begin + n * packsz + n - 1; if (npdir == 0) { /* There's no mystery about which group of epochs to search. */ pgroup = 1; } else { /* There's at least one directory. Find the first directory */ /* whose time is greater than or equal to the request time, if */ /* there is such a directory. We'll search linearly through the */ /* directory entries, reading up to DIRSIZ of them at a time. */ /* Having found the correct set of directory entries, we'll */ /* perform a binary search within that set for the desired entry. */ bufbas = dirbas; npread = min(npdir,100); i__1 = bufbas + 1; i__2 = bufbas + npread; dafgda_(handle, &i__1, &i__2, pbuffr); remain = npdir - npread; while(pbuffr[(i__1 = npread - 1) < 101 && 0 <= i__1 ? i__1 : s_rnge( "pbuffr", i__1, "ckr05_", (ftnlen)633)] < t && remain > 0) { bufbas += npread; npread = min(remain,100); /* Note: NPREAD is always > 0 here. */ i__1 = bufbas + 1; i__2 = bufbas + npread; dafgda_(handle, &i__1, &i__2, pbuffr); remain -= npread; } /* At this point, BUFBAS - DIRBAS is the number of directory */ /* entries preceding the one contained in PBUFFR(1). */ /* PGROUP is one more than the number of directories we've */ /* passed by. */ pgroup = bufbas - dirbas + lstltd_(&t, &npread, pbuffr) + 1; } /* PGROUP now indicates the set of epochs in which to search for the */ /* request epoch. The following cases can occur: */ /* PGROUP = 1 */ /* ========== */ /* NPDIR = 0 */ /* -------- */ /* The request time may precede the first time tag */ /* of the segment, exceed the last time tag, or lie */ /* in the closed interval bounded by these time tags. */ /* NPDIR >= 1 */ /* --------- */ /* The request time may precede the first time tag */ /* of the group but does not exceed the last epoch */ /* of the group. */ /* 1 < PGROUP <= NPDIR */ /* =================== */ /* The request time follows the last time of the */ /* previous group and is less than or equal to */ /* the pointing directory entry at index PGROUP. */ /* 1 < PGROUP = NPDIR + 1 */ /* ====================== */ /* The request time follows the last time of the */ /* last pointing directory entry. The request time */ /* may exceed the last time tag. */ /* Now we'll look up the time tags in the group of epochs */ /* we've identified. */ /* We'll use the variable names PBEGIX and PENDIX to refer to */ /* the indices, relative to the set of time tags, of the first */ /* and last time tags in the set we're going to look up. */ if (pgroup == 1) { pbegix = 1; pendix = min(n,100); } else { /* If the group index is greater than 1, we'll include the last */ /* time tag of the previous group in the set of time tags we look */ /* up. That way, the request time is strictly bracketed on the */ /* low side by the time tag set we look up. */ pbegix = (pgroup - 1) * 100; /* Computing MIN */ i__1 = pbegix + 100; pendix = min(i__1,n); } timbas = dirbas - n; i__1 = timbas + pbegix; i__2 = timbas + pendix; dafgda_(handle, &i__1, &i__2, pbuffr); npread = pendix - pbegix + 1; /* At this point, we'll deal with the cases where T lies outside */ /* of the range of epochs we've buffered. */ if (t < pbuffr[0]) { /* This can happen only if PGROUP = 1 and T precedes all epochs. */ /* If the input request time is too far from PBUFFR(1) on */ /* the low side, we're done. */ if (*sclkdp + *tol < pbuffr[0]) { chkout_("CKR05", (ftnlen)5); return 0; } /* Bracket T to move it within the range of buffered epochs. */ t = pbuffr[0]; } else if (t > pbuffr[(i__1 = npread - 1) < 101 && 0 <= i__1 ? i__1 : s_rnge("pbuffr", i__1, "ckr05_", (ftnlen)748)]) { /* This can happen only if T follows all epochs. */ if (*sclkdp - *tol > pbuffr[(i__1 = npread - 1) < 101 && 0 <= i__1 ? i__1 : s_rnge("pbuffr", i__1, "ckr05_", (ftnlen)752)]) { chkout_("CKR05", (ftnlen)5); return 0; } /* Bracket T to move it within the range of buffered epochs. */ t = pbuffr[(i__1 = npread - 1) < 101 && 0 <= i__1 ? i__1 : s_rnge( "pbuffr", i__1, "ckr05_", (ftnlen)762)]; } /* At this point, */ /* | T - SCLKDP | <= TOL */ /* Also, one of the following is true: */ /* T is the first time of the segment */ /* T is the last time of the segment */ /* T equals SCLKDP */ /* Find two adjacent time tags bounding the request epoch. The */ /* request time cannot be greater than all of time tags in the */ /* group, and it cannot precede the first element of the group. */ i__ = lstltd_(&t, &npread, pbuffr); /* The variables LOW and HIGH are the indices of a pair of time */ /* tags that bracket the request time. Remember that NPREAD could */ /* be equal to 1, in which case we would have LOW = HIGH. */ if (i__ == 0) { /* This can happen only if PGROUP = 1 and T = PBUFFR(1). */ low = 1; lepoch = pbuffr[0]; if (n == 1) { high = 1; } else { high = 2; } hepoch = pbuffr[(i__1 = high - 1) < 101 && 0 <= i__1 ? i__1 : s_rnge( "pbuffr", i__1, "ckr05_", (ftnlen)805)]; } else { low = pbegix + i__ - 1; lepoch = pbuffr[(i__1 = i__ - 1) < 101 && 0 <= i__1 ? i__1 : s_rnge( "pbuffr", i__1, "ckr05_", (ftnlen)810)]; high = low + 1; hepoch = pbuffr[(i__1 = i__) < 101 && 0 <= i__1 ? i__1 : s_rnge("pbu" "ffr", i__1, "ckr05_", (ftnlen)813)]; } /* We now need to find the interpolation interval containing */ /* T, if any. We may be able to use the interpolation */ /* interval found on the previous call to this routine. If */ /* this is the first call or if the previous interval is not */ /* applicable, we'll search for the interval. */ /* First check if the request time falls in the same interval as */ /* it did last time. We need to make sure that we are dealing */ /* with the same segment as well as the same time range. */ /* PREVS is the start time of the interval that satisfied */ /* the previous request for pointing. */ /* PREVN is the start time of the interval that followed */ /* the interval specified above. */ /* PREVNN is the start time of the interval that followed */ /* the interval starting at PREVN. */ /* LHAND is the handle of the file that PREVS and PREVN */ /* were found in. */ /* LBEG, are the beginning and ending addresses of the */ /* LEND segment in the file LHAND that PREVS and PREVN */ /* were found in. */ if (*handle == lhand && begin == lbeg && end == lend && t >= prevs && t < prevn) { start = prevs; nstart = prevn; nnstrt = prevnn; } else { /* Search for the interpolation interval. */ nidir = (nints - 1) / 100; dirbas = end - 5 - nidir; if (nidir == 0) { /* There's no mystery about which group of epochs to search. */ sgroup = 1; } else { /* There's at least one directory. Find the first directory */ /* whose time is greater than or equal to the request time, if */ /* there is such a directory. We'll search linearly through */ /* the directory entries, reading up to DIRSIZ of them at a */ /* time. Having found the correct set of directory entries, */ /* we'll perform a binary search within that set for the */ /* desired entry. */ bufbas = dirbas; nsread = min(nidir,100); remain = nidir - nsread; i__1 = bufbas + 1; i__2 = bufbas + nsread; dafgda_(handle, &i__1, &i__2, sbuffr); while(sbuffr[(i__1 = nsread - 1) < 103 && 0 <= i__1 ? i__1 : s_rnge("sbuffr", i__1, "ckr05_", (ftnlen)885)] < t && remain > 0) { bufbas += nsread; nsread = min(remain,100); remain -= nsread; /* Note: NSREAD is always > 0 here. */ i__1 = bufbas + 1; i__2 = bufbas + nsread; dafgda_(handle, &i__1, &i__2, sbuffr); } /* At this point, BUFBAS - DIRBAS is the number of directory */ /* entries preceding the one contained in SBUFFR(1). */ /* SGROUP is one more than the number of directories we've */ /* passed by. */ sgroup = bufbas - dirbas + lstltd_(&t, &nsread, sbuffr) + 1; } /* SGROUP now indicates the set of interval start times in which */ /* to search for the request epoch. */ /* Now we'll look up the time tags in the group of epochs we've */ /* identified. */ /* We'll use the variable names SBEGIX and SENDIX to refer to the */ /* indices, relative to the set of start times, of the first and */ /* last start times in the set we're going to look up. */ if (sgroup == 1) { sbegix = 1; sendix = min(nints,102); } else { /* Look up the start times for the group of interest. Also */ /* buffer last start time from the previous group. Also, it */ /* turns out to be useful to pick up two extra start */ /* times---the first two start times of the next group---if */ /* they exist. */ sbegix = (sgroup - 1) * 100; /* Computing MIN */ i__1 = sbegix + 102; sendix = min(i__1,nints); } timbas = dirbas - nints; i__1 = timbas + sbegix; i__2 = timbas + sendix; dafgda_(handle, &i__1, &i__2, sbuffr); nsread = sendix - sbegix + 1; /* Find the last interval start time less than or equal to the */ /* request time. We know T is greater than or equal to the */ /* first start time, so I will be > 0. */ nsrch = min(101,nsread); i__ = lstled_(&t, &nsrch, sbuffr); start = sbuffr[(i__1 = i__ - 1) < 103 && 0 <= i__1 ? i__1 : s_rnge( "sbuffr", i__1, "ckr05_", (ftnlen)956)]; /* Let NSTART ("next start") be the start time that follows */ /* START, if START is not the last start time. If NSTART */ /* has a successor, let NNSTRT be that start time. */ if (i__ < nsread) { nstart = sbuffr[(i__1 = i__) < 103 && 0 <= i__1 ? i__1 : s_rnge( "sbuffr", i__1, "ckr05_", (ftnlen)965)]; if (i__ + 1 < nsread) { nnstrt = sbuffr[(i__1 = i__ + 1) < 103 && 0 <= i__1 ? i__1 : s_rnge("sbuffr", i__1, "ckr05_", (ftnlen)969)]; } else { nnstrt = dpmax_(); } } else { nstart = dpmax_(); nnstrt = dpmax_(); } } /* If T does not lie within the interpolation interval starting */ /* at time START, we'll determine whether T is closer to this */ /* interval or the next. If the distance between T and the */ /* closer interval is less than or equal to TOL, we'll map T */ /* to the closer endpoint of the closer interval. Otherwise, */ /* we return without finding pointing. */ if (hepoch == nstart) { /* The first time tag greater than or equal to T is the start */ /* time of the next interpolation interval. */ /* The request time lies between interpolation intervals. */ /* LEPOCH is the last time tag of the first interval; HEPOCH */ /* is the first time tag of the next interval. */ if ((d__1 = t - lepoch, abs(d__1)) <= (d__2 = hepoch - t, abs(d__2))) { /* T is closer to the first interval... */ if ((d__1 = t - lepoch, abs(d__1)) > *tol) { /* ...But T is too far from the interval. */ chkout_("CKR05", (ftnlen)5); return 0; } /* Map T to the right endpoint of the preceding interval. */ t = lepoch; high = low; hepoch = lepoch; } else { /* T is closer to the second interval... */ if ((d__1 = hepoch - t, abs(d__1)) > *tol) { /* ...But T is too far from the interval. */ chkout_("CKR05", (ftnlen)5); return 0; } /* Map T to the left endpoint of the next interval. */ t = hepoch; low = high; lepoch = hepoch; /* Since we're going to be picking time tags from the next */ /* interval, we'll need to adjust START and NSTART. */ start = nstart; nstart = nnstrt; } } /* We now have */ /* LEPOCH < T < HEPOCH */ /* - - */ /* where LEPOCH and HEPOCH are the time tags at indices */ /* LOW and HIGH, respectively. */ /* Now select the set of packets used for interpolation. Note */ /* that the window size is known to be even. */ /* Unlike CK types 8, 9, 12, and 13, for type 05 we adjust */ /* the window size to keep the request time within the central */ /* interval of the window. */ /* The nominal bracketing epochs we've found are the (WNDSIZ/2)nd */ /* and (WNDSIZ/2 + 1)st of the interpolating set. If the request */ /* time is too close to one end of the interpolation interval, we */ /* reduce the window size, after which one endpoint of the window */ /* will coincide with an endpoint of the interpolation interval. */ /* We start out by looking up the set of time tags we'd use */ /* if there were no gaps in the coverage. We then trim our */ /* time tag set to ensure all tags are in the interpolation */ /* interval. It's possible that the interpolation window will */ /* collapse to a single point as a result of this last step. */ /* Let LSIZE be the size of the "left half" of the window: the */ /* size of the set of window epochs to the left of the request time. */ /* We want this size to be WNDSIZ/2, but if not enough states are */ /* available, the set ranges from index 1 to index LOW. */ /* Computing MIN */ i__1 = wndsiz / 2; lsize = min(i__1,low); /* RSIZE is defined analogously for the right half of the window. */ /* Computing MIN */ i__1 = wndsiz / 2, i__2 = n - high + 1; rsize = min(i__1,i__2); /* The window size is simply the sum of LSIZE and RSIZE. */ wndsiz = lsize + rsize; /* FIRST and LAST are the endpoints of the range of indices of */ /* time tags (and packets) we'll collect in the output record. */ first = low - lsize + 1; last = first + wndsiz - 1; /* Buffer the epochs. */ wstart = begin + n * packsz + first - 1; i__1 = wstart + wndsiz - 1; dafgda_(handle, &wstart, &i__1, pbuffr); /* Discard any epochs less than START or greater than or equal */ /* to NSTART. The set of epochs we want ranges from indices */ /* I+1 to J. This range is non-empty unless START and NSTART */ /* are both DPMAX(). */ i__ = lstltd_(&start, &wndsiz, pbuffr); j = lstltd_(&nstart, &wndsiz, pbuffr); if (i__ == j) { /* Fuggedaboudit. */ chkout_("CKR05", (ftnlen)5); return 0; } /* Update FIRST, LAST, and WNDSIZ. */ wndsiz = j - i__; first += i__; last = first + wndsiz - 1; /* Put the subtype into the output record. The size of the group */ /* of packets is derived from the subtype, so we need not include */ /* the size. */ record[0] = t; record[1] = (doublereal) subtyp; record[2] = (doublereal) wndsiz; record[3] = rate; /* Read the packets. */ i__1 = begin + (first - 1) * packsz; i__2 = begin + last * packsz - 1; dafgda_(handle, &i__1, &i__2, &record[4]); /* Finally, add the epochs to the output record. */ i__2 = j - i__; moved_(&pbuffr[(i__1 = i__) < 101 && 0 <= i__1 ? i__1 : s_rnge("pbuffr", i__1, "ckr05_", (ftnlen)1158)], &i__2, &record[wndsiz * packsz + 4]); /* Save the information about the interval and segment. */ lhand = *handle; lbeg = begin; lend = end; prevs = start; prevn = nstart; prevnn = nnstrt; /* Indicate pointing was found. */ *found = TRUE_; chkout_("CKR05", (ftnlen)5); return 0; } /* ckr05_ */
/* $Procedure CKW05 ( Write CK segment, type 5 ) */ /* Subroutine */ int ckw05_(integer *handle, integer *subtyp, integer *degree, doublereal *begtim, doublereal *endtim, integer *inst, char *ref, logical *avflag, char *segid, integer *n, doublereal *sclkdp, doublereal *packts, doublereal *rate, integer *nints, doublereal * starts, ftnlen ref_len, ftnlen segid_len) { /* System generated locals */ integer i__1, i__2; doublereal d__1; /* Local variables */ integer addr__, i__; extern /* Subroutine */ int chkin_(char *, ftnlen), dafps_(integer *, integer *, doublereal *, integer *, doublereal *); doublereal descr[5]; extern /* Subroutine */ int errch_(char *, char *, ftnlen, ftnlen), errdp_(char *, doublereal *, ftnlen), dafada_(doublereal *, integer *); doublereal dc[2]; extern /* Subroutine */ int dafbna_(integer *, doublereal *, char *, ftnlen); integer ic[6]; extern /* Subroutine */ int dafena_(void); extern logical failed_(void); integer chrcod, refcod; extern integer bsrchd_(doublereal *, integer *, doublereal *); extern /* Subroutine */ int namfrm_(char *, integer *, ftnlen); extern integer lastnb_(char *, ftnlen); integer packsz; extern /* Subroutine */ int sigerr_(char *, ftnlen), chkout_(char *, ftnlen), setmsg_(char *, ftnlen), errint_(char *, integer *, ftnlen); extern integer lstltd_(doublereal *, integer *, doublereal *); extern logical vzerog_(doublereal *, integer *), return_(void); integer winsiz; extern logical odd_(integer *); /* $ Abstract */ /* Write a type 5 segment to a CK file. */ /* $ 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 */ /* CK */ /* NAIF_IDS */ /* ROTATION */ /* TIME */ /* $ Keywords */ /* POINTING */ /* FILES */ /* $ Declarations */ /* $ Abstract */ /* Declare parameters specific to CK type 05. */ /* $ 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 */ /* CK */ /* $ Keywords */ /* CK */ /* $ Restrictions */ /* None. */ /* $ Author_and_Institution */ /* N.J. Bachman (JPL) */ /* $ Literature_References */ /* None. */ /* $ Version */ /* - SPICELIB Version 1.0.0, 20-AUG-2002 (NJB) */ /* -& */ /* CK type 5 subtype codes: */ /* Subtype 0: Hermite interpolation, 8-element packets. Quaternion */ /* and quaternion derivatives only, no angular velocity */ /* vector provided. Quaternion elements are listed */ /* first, followed by derivatives. Angular velocity is */ /* derived from the quaternions and quaternion */ /* derivatives. */ /* Subtype 1: Lagrange interpolation, 4-element packets. Quaternion */ /* only. Angular velocity is derived by differentiating */ /* the interpolating polynomials. */ /* Subtype 2: Hermite interpolation, 14-element packets. */ /* Quaternion and angular angular velocity vector, as */ /* well as derivatives of each, are provided. The */ /* quaternion comes first, then quaternion derivatives, */ /* then angular velocity and its derivatives. */ /* Subtype 3: Lagrange interpolation, 7-element packets. Quaternion */ /* and angular velocity vector provided. The quaternion */ /* comes first. */ /* Packet sizes associated with the various subtypes: */ /* End of file ck05.inc. */ /* $ Brief_I/O */ /* Variable I/O Description */ /* -------- --- -------------------------------------------------- */ /* HANDLE I Handle of an CK file open for writing. */ /* SUBTYP I CK type 5 subtype code. */ /* DEGREE I Degree of interpolating polynomials. */ /* BEGTIM I Start time of interval covered by segment. */ /* ENDTIM I End time of interval covered by segment. */ /* INST I NAIF code for a s/c instrument or structure. */ /* REF I Reference frame name. */ /* AVFLAG I True if the segment will contain angular velocity. */ /* SEGID I Segment identifier. */ /* N I Number of packets. */ /* SCLKDP I Encoded SCLK times. */ /* PACKTS I Array of packets. */ /* RATE I Nominal SCLK rate in seconds per tick. */ /* NINTS I Number of intervals. */ /* STARTS I Encoded SCLK interval start times. */ /* MAXDEG P Maximum allowed degree of interpolating polynomial. */ /* $ Detailed_Input */ /* HANDLE is the file handle of a CK file that has been */ /* opened for writing. */ /* SUBTYP is an integer code indicating the subtype of the */ /* the segment to be created. */ /* DEGREE is the degree of the polynomials used to */ /* interpolate the quaternions contained in the input */ /* packets. All components of the quaternions are */ /* interpolated by polynomials of fixed degree. */ /* BEGTIM, */ /* ENDTIM are the beginning and ending encoded SCLK times */ /* for which the segment provides pointing */ /* information. BEGTIM must be less than or equal to */ /* ENDTIM, and at least one data packet must have a */ /* time tag T such that */ /* BEGTIM < T < ENDTIM */ /* - - */ /* INST is the NAIF integer code for the instrument or */ /* structure for which a segment is to be created. */ /* REF is the NAIF name for a reference frame relative to */ /* which the pointing information for INST is */ /* specified. */ /* AVFLAG is a logical flag which indicates whether or not */ /* the segment will contain angular velocity. */ /* SEGID is the segment identifier. A CK segment */ /* identifier may contain up to 40 characters. */ /* N is the number of packets in the input packet */ /* array. */ /* SCLKDP are the encoded spacecraft clock times associated */ /* with each pointing instance. These times must be */ /* strictly increasing. */ /* PACKTS contains a time-ordered array of data packets */ /* representing the orientation of INST relative to */ /* the frame REF. Each packet contains a SPICE-style */ /* quaternion and optionally, depending on the */ /* segment subtype, attitude derivative data, from */ /* which a C-matrix and an angular velocity vector */ /* may be derived. */ /* See the discussion of quaternion styles in */ /* Particulars below. */ /* The C-matrix represented by the Ith data packet is */ /* a rotation matrix that transforms the components */ /* of a vector expressed in the base frame specified */ /* by REF to components expressed in the instrument */ /* fixed frame at the time SCLKDP(I). */ /* Thus, if a vector V has components x, y, z in the */ /* base frame, then V has components x', y', z' */ /* in the instrument fixed frame where: */ /* [ x' ] [ ] [ x ] */ /* | y' | = | CMAT | | y | */ /* [ z' ] [ ] [ z ] */ /* The attitude derivative information in PACKTS(I) */ /* gives the angular velocity of the instrument fixed */ /* frame at time SCLKDP(I) with respect to the */ /* reference frame specified by REF. */ /* The direction of an angular velocity vector gives */ /* the right-handed axis about which the instrument */ /* fixed reference frame is rotating. The magnitude */ /* of the vector is the magnitude of the */ /* instantaneous velocity of the rotation, in radians */ /* per second. */ /* Packet contents and the corresponding */ /* interpolation methods depend on the segment */ /* subtype, and are as follows: */ /* Subtype 0: Hermite interpolation, 8-element */ /* packets. Quaternion and quaternion */ /* derivatives only, no angular */ /* velocity vector provided. */ /* Quaternion elements are listed */ /* first, followed by derivatives. */ /* Angular velocity is derived from */ /* the quaternions and quaternion */ /* derivatives. */ /* Subtype 1: Lagrange interpolation, 4-element */ /* packets. Quaternion only. Angular */ /* velocity is derived by */ /* differentiating the interpolating */ /* polynomials. */ /* Subtype 2: Hermite interpolation, 14-element */ /* packets. Quaternion and angular */ /* angular velocity vector, as well as */ /* derivatives of each, are provided. */ /* The quaternion comes first, then */ /* quaternion derivatives, then */ /* angular velocity and its */ /* derivatives. */ /* Subtype 3: Lagrange interpolation, 7-element */ /* packets. Quaternion and angular */ /* velocity vector provided. The */ /* quaternion comes first. */ /* Angular velocity is always specified relative to */ /* the base frame. */ /* RATE is the nominal rate of the spacecraft clock */ /* associated with INST. Units are seconds per */ /* tick. RATE is used to scale angular velocity */ /* to radians/second. */ /* NINTS is the number of intervals that the pointing */ /* instances are partitioned into. */ /* STARTS are the start times of each of the interpolation */ /* intervals. These times must be strictly increasing */ /* and must coincide with times for which the segment */ /* contains pointing. */ /* $ Detailed_Output */ /* None. See $Particulars for a description of the effect of this */ /* routine. */ /* $ Parameters */ /* MAXDEG is the maximum allowed degree of the interpolating */ /* polynomial. If the value of MAXDEG is increased, */ /* the SPICELIB routine CKPFS must be changed */ /* accordingly. In particular, the size of the */ /* record passed to CKRnn and CKEnn must be */ /* increased, and comments describing the record size */ /* must be changed. */ /* $ Exceptions */ /* If any of the following exceptions occur, this routine will return */ /* without creating a new segment. */ /* 1) If HANDLE is not the handle of a C-kernel opened for writing */ /* the error will be diagnosed by routines called by this */ /* routine. */ /* 2) If the last non-blank character of SEGID occurs past index 40, */ /* the error SPICE(SEGIDTOOLONG) is signaled. */ /* 3) If SEGID contains any nonprintable characters, the error */ /* SPICE(NONPRINTABLECHARS) is signaled. */ /* 4) If the first encoded SCLK time is negative then the error */ /* SPICE(INVALIDSCLKTIME) is signaled. If any subsequent times */ /* are negative the error will be detected in exception (5). */ /* 5) If the encoded SCLK times are not strictly increasing, */ /* the error SPICE(TIMESOUTOFORDER) is signaled. */ /* 6) If the name of the reference frame is not one of those */ /* supported by the routine FRAMEX, the error */ /* SPICE(INVALIDREFFRAME) is signaled. */ /* 7) If the number of packets N is not at least 1, the error */ /* SPICE(TOOFEWPACKETS) will be signaled. */ /* 8) If NINTS, the number of interpolation intervals, is less than */ /* or equal to 0, the error SPICE(INVALIDNUMINTS) is signaled. */ /* 9) If the encoded SCLK interval start times are not strictly */ /* increasing, the error SPICE(TIMESOUTOFORDER) is signaled. */ /* 10) If an interval start time does not coincide with a time for */ /* which there is an actual pointing instance in the segment, */ /* then the error SPICE(INVALIDSTARTTIME) is signaled. */ /* 11) This routine assumes that the rotation between adjacent */ /* quaternions that are stored in the same interval has a */ /* rotation angle of THETA radians, where */ /* 0 < THETA < pi. */ /* _ */ /* The routines that evaluate the data in the segment produced */ /* by this routine cannot distinguish between rotations of THETA */ /* radians, where THETA is in the interval [0, pi), and */ /* rotations of */ /* THETA + 2 * k * pi */ /* radians, where k is any integer. These "large" rotations will */ /* yield invalid results when interpolated. You must ensure that */ /* the data stored in the segment will not be subject to this */ /* sort of ambiguity. */ /* 12) If any quaternion has magnitude zero, the error */ /* SPICE(ZEROQUATERNION) is signaled. */ /* 13) If the interpolation window size implied by DEGREE is not */ /* even, the error SPICE(INVALIDDEGREE) is signaled. The window */ /* size is DEGREE+1 for Lagrange subtypes and is (DEGREE+1)/2 */ /* for Hermite subtypes. */ /* 14) If an unrecognized subtype code is supplied, the error */ /* SPICE(NOTSUPPORTED) is signaled. */ /* 15) If DEGREE is not at least 1 or is greater than MAXDEG, the */ /* error SPICE(INVALIDDEGREE) is signaled. */ /* 16) If the segment descriptor bounds are out of order, the */ /* error SPICE(BADDESCRTIMES) is signaled. */ /* 17) If there is no element of SCLKDP that lies between BEGTIM and */ /* ENDTIM inclusive, the error SPICE(EMPTYSEGMENT) is signaled. */ /* 18) If RATE is zero, the error SPICE(INVALIDVALUE) is signaled. */ /* $ Files */ /* A new type 5 CK segment is written to the CK file attached */ /* to HANDLE. */ /* $ Particulars */ /* This routine writes a CK type 5 data segment to the open CK */ /* file according to the format described in the type 5 section of */ /* the CK Required Reading. The CK file must have been opened with */ /* write access. */ /* Quaternion Styles */ /* ----------------- */ /* There are different "styles" of quaternions used in */ /* science and engineering applications. Quaternion styles */ /* are characterized by */ /* - The order of quaternion elements */ /* - The quaternion multiplication formula */ /* - The convention for associating quaternions */ /* with rotation matrices */ /* Two of the commonly used styles are */ /* - "SPICE" */ /* > Invented by Sir William Rowan Hamilton */ /* > Frequently used in mathematics and physics textbooks */ /* - "Engineering" */ /* > Widely used in aerospace engineering applications */ /* SPICELIB subroutine interfaces ALWAYS use SPICE quaternions. */ /* Quaternions of any other style must be converted to SPICE */ /* quaternions before they are passed to SPICELIB routines. */ /* Relationship between SPICE and Engineering Quaternions */ /* ------------------------------------------------------ */ /* Let M be a rotation matrix such that for any vector V, */ /* M*V */ /* is the result of rotating V by theta radians in the */ /* counterclockwise direction about unit rotation axis vector A. */ /* Then the SPICE quaternions representing M are */ /* (+/-) ( cos(theta/2), */ /* sin(theta/2) A(1), */ /* sin(theta/2) A(2), */ /* sin(theta/2) A(3) ) */ /* while the engineering quaternions representing M are */ /* (+/-) ( -sin(theta/2) A(1), */ /* -sin(theta/2) A(2), */ /* -sin(theta/2) A(3), */ /* cos(theta/2) ) */ /* For both styles of quaternions, if a quaternion q represents */ /* a rotation matrix M, then -q represents M as well. */ /* Given an engineering quaternion */ /* QENG = ( q0, q1, q2, q3 ) */ /* the equivalent SPICE quaternion is */ /* QSPICE = ( q3, -q0, -q1, -q2 ) */ /* Associating SPICE Quaternions with Rotation Matrices */ /* ---------------------------------------------------- */ /* Let FROM and TO be two right-handed reference frames, for */ /* example, an inertial frame and a spacecraft-fixed frame. Let the */ /* symbols */ /* V , V */ /* FROM TO */ /* denote, respectively, an arbitrary vector expressed relative to */ /* the FROM and TO frames. Let M denote the transformation matrix */ /* that transforms vectors from frame FROM to frame TO; then */ /* V = M * V */ /* TO FROM */ /* where the expression on the right hand side represents left */ /* multiplication of the vector by the matrix. */ /* Then if the unit-length SPICE quaternion q represents M, where */ /* q = (q0, q1, q2, q3) */ /* the elements of M are derived from the elements of q as follows: */ /* +- -+ */ /* | 2 2 | */ /* | 1 - 2*( q2 + q3 ) 2*(q1*q2 - q0*q3) 2*(q1*q3 + q0*q2) | */ /* | | */ /* | | */ /* | 2 2 | */ /* M = | 2*(q1*q2 + q0*q3) 1 - 2*( q1 + q3 ) 2*(q2*q3 - q0*q1) | */ /* | | */ /* | | */ /* | 2 2 | */ /* | 2*(q1*q3 - q0*q2) 2*(q2*q3 + q0*q1) 1 - 2*( q1 + q2 ) | */ /* | | */ /* +- -+ */ /* Note that substituting the elements of -q for those of q in the */ /* right hand side leaves each element of M unchanged; this shows */ /* that if a quaternion q represents a matrix M, then so does the */ /* quaternion -q. */ /* To map the rotation matrix M to a unit quaternion, we start by */ /* decomposing the rotation matrix as a sum of symmetric */ /* and skew-symmetric parts: */ /* 2 */ /* M = [ I + (1-cos(theta)) OMEGA ] + [ sin(theta) OMEGA ] */ /* symmetric skew-symmetric */ /* OMEGA is a skew-symmetric matrix of the form */ /* +- -+ */ /* | 0 -n3 n2 | */ /* | | */ /* OMEGA = | n3 0 -n1 | */ /* | | */ /* | -n2 n1 0 | */ /* +- -+ */ /* The vector N of matrix entries (n1, n2, n3) is the rotation axis */ /* of M and theta is M's rotation angle. Note that N and theta */ /* are not unique. */ /* Let */ /* C = cos(theta/2) */ /* S = sin(theta/2) */ /* Then the unit quaternions Q corresponding to M are */ /* Q = +/- ( C, S*n1, S*n2, S*n3 ) */ /* The mappings between quaternions and the corresponding rotations */ /* are carried out by the SPICELIB routines */ /* Q2M {quaternion to matrix} */ /* M2Q {matrix to quaternion} */ /* M2Q always returns a quaternion with scalar part greater than */ /* or equal to zero. */ /* SPICE Quaternion Multiplication Formula */ /* --------------------------------------- */ /* Given a SPICE quaternion */ /* Q = ( q0, q1, q2, q3 ) */ /* corresponding to rotation axis A and angle theta as above, we can */ /* represent Q using "scalar + vector" notation as follows: */ /* s = q0 = cos(theta/2) */ /* v = ( q1, q2, q3 ) = sin(theta/2) * A */ /* Q = s + v */ /* Let Q1 and Q2 be SPICE quaternions with respective scalar */ /* and vector parts s1, s2 and v1, v2: */ /* Q1 = s1 + v1 */ /* Q2 = s2 + v2 */ /* We represent the dot product of v1 and v2 by */ /* <v1, v2> */ /* and the cross product of v1 and v2 by */ /* v1 x v2 */ /* Then the SPICE quaternion product is */ /* Q1*Q2 = s1*s2 - <v1,v2> + s1*v2 + s2*v1 + (v1 x v2) */ /* If Q1 and Q2 represent the rotation matrices M1 and M2 */ /* respectively, then the quaternion product */ /* Q1*Q2 */ /* represents the matrix product */ /* M1*M2 */ /* $ Examples */ /* Suppose that you have data packets and are prepared to produce */ /* a segment of type 5 in a CK file. */ /* The following code fragment could be used to add the new segment */ /* to a previously opened CK file attached to HANDLE. The file must */ /* have been opened with write access. */ /* C */ /* C Create a segment identifier. */ /* C */ /* SEGID = 'MY_SAMPLE_CK_TYPE_5_SEGMENT' */ /* C */ /* C Write the segment. */ /* C */ /* CALL CKW05 ( HANDLE, SUBTYP, DEGREE, BEGTIM, ENDTIM, */ /* . INST, REF, AVFLAG, SEGID, N, */ /* . SCLKDP, PACKTS, RATE, NINTS, STARTS ) */ /* $ Restrictions */ /* None. */ /* $ Literature_References */ /* None. */ /* $ Author_and_Institution */ /* N.J. Bachman (JPL) */ /* W.L. Taber (JPL) */ /* K.R. Gehringer (JPL) */ /* J.M. Lynch (JPL) */ /* $ Version */ /* - SPICELIB Version 2.0.0, 08-FEB-2010 (NJB) */ /* The check for non-unit quaternions has been replaced */ /* with a check for zero-length quaternions. */ /* - SPICELIB Version 1.1.0, 26-FEB-2008 (NJB) */ /* Updated header; added information about SPICE */ /* quaternion conventions. */ /* Minor typo in a long error message was corrected. */ /* - SPICELIB Version 1.0.1, 07-JAN-2005 (NJB) */ /* Description in Detailed_Input header section of */ /* constraints on BEGTIM and ENDTIM was corrected. */ /* - SPICELIB Version 1.0.0, 30-AUG-2002 (NJB) (KRG) (JML) (WLT) */ /* -& */ /* $ Index_Entries */ /* write ck type_5 data segment */ /* -& */ /* $ Revisions */ /* - SPICELIB Version 2.0.0, 08-FEB-2010 (NJB) */ /* The check for non-unit quaternions has been replaced */ /* with a check for zero-length quaternions. */ /* This change was made to accommodate CK generation, */ /* via the non-SPICE utility MEX2KER, for European missions. */ /* -& */ /* SPICELIB functions */ /* Local parameters */ /* Packet structure parameters */ /* Local variables */ /* Standard SPICE error handling. */ if (return_()) { return 0; } else { chkin_("CKW05", (ftnlen)5); } /* Make sure that the number of packets is positive. */ if (*n < 1) { setmsg_("At least 1 packet is required for CK type 5. Number of pack" "ets supplied: #", (ftnlen)75); errint_("#", n, (ftnlen)1); sigerr_("SPICE(TOOFEWPACKETS)", (ftnlen)20); chkout_("CKW05", (ftnlen)5); return 0; } /* Make sure that there is a positive number of interpolation */ /* intervals. */ if (*nints <= 0) { setmsg_("# is an invalid number of interpolation intervals for type " "5.", (ftnlen)61); errint_("#", nints, (ftnlen)1); sigerr_("SPICE(INVALIDNUMINTS)", (ftnlen)21); chkout_("CKW05", (ftnlen)5); return 0; } /* Get the NAIF integer code for the reference frame. */ namfrm_(ref, &refcod, ref_len); if (refcod == 0) { setmsg_("The reference frame # is not supported.", (ftnlen)39); errch_("#", ref, (ftnlen)1, ref_len); sigerr_("SPICE(INVALIDREFFRAME)", (ftnlen)22); chkout_("CKW05", (ftnlen)5); return 0; } /* Check to see if the segment identifier is too long. */ if (lastnb_(segid, segid_len) > 40) { setmsg_("Segment identifier contains more than 40 characters.", ( ftnlen)52); sigerr_("SPICE(SEGIDTOOLONG)", (ftnlen)19); chkout_("CKW05", (ftnlen)5); return 0; } /* Now check that all the characters in the segment identifier */ /* can be printed. */ i__1 = lastnb_(segid, segid_len); for (i__ = 1; i__ <= i__1; ++i__) { chrcod = *(unsigned char *)&segid[i__ - 1]; if (chrcod < 32 || chrcod > 126) { setmsg_("The segment identifier contains nonprintable characters", (ftnlen)55); sigerr_("SPICE(NONPRINTABLECHARS)", (ftnlen)24); chkout_("CKW05", (ftnlen)5); return 0; } } /* Now check that the encoded SCLK times are positive and strictly */ /* increasing. */ /* Check that the first time is nonnegative. */ if (sclkdp[0] < 0.) { setmsg_("The first SCLKDP time: # is negative.", (ftnlen)37); errdp_("#", sclkdp, (ftnlen)1); sigerr_("SPICE(INVALIDSCLKTIME)", (ftnlen)22); chkout_("CKW05", (ftnlen)5); return 0; } /* Now check that the times are ordered properly. */ i__1 = *n; for (i__ = 2; i__ <= i__1; ++i__) { if (sclkdp[i__ - 1] <= sclkdp[i__ - 2]) { setmsg_("The SCLKDP times are not strictly increasing. SCLKDP(#)" " = # and SCLKDP(#) = #.", (ftnlen)78); errint_("#", &i__, (ftnlen)1); errdp_("#", &sclkdp[i__ - 1], (ftnlen)1); i__2 = i__ - 1; errint_("#", &i__2, (ftnlen)1); errdp_("#", &sclkdp[i__ - 2], (ftnlen)1); sigerr_("SPICE(TIMESOUTOFORDER)", (ftnlen)22); chkout_("CKW05", (ftnlen)5); return 0; } } /* Now check that the interval start times are ordered properly. */ i__1 = *nints; for (i__ = 2; i__ <= i__1; ++i__) { if (starts[i__ - 1] <= starts[i__ - 2]) { setmsg_("The interval start times are not strictly increasing. S" "TARTS(#) = # and STARTS(#) = #.", (ftnlen)86); errint_("#", &i__, (ftnlen)1); errdp_("#", &starts[i__ - 1], (ftnlen)1); i__2 = i__ - 1; errint_("#", &i__2, (ftnlen)1); errdp_("#", &starts[i__ - 2], (ftnlen)1); sigerr_("SPICE(TIMESOUTOFORDER)", (ftnlen)22); chkout_("CKW05", (ftnlen)5); return 0; } } /* Now make sure that all of the interval start times coincide with */ /* one of the times associated with the actual pointing. */ i__1 = *nints; for (i__ = 1; i__ <= i__1; ++i__) { /* We know the SCLKDP array is ordered, so a binary search is */ /* ok. */ if (bsrchd_(&starts[i__ - 1], n, sclkdp) == 0) { setmsg_("Interval start time number # is invalid. STARTS(#) = *", (ftnlen)54); errint_("#", &i__, (ftnlen)1); errint_("#", &i__, (ftnlen)1); errdp_("*", &starts[i__ - 1], (ftnlen)1); sigerr_("SPICE(INVALIDSTARTTIME)", (ftnlen)23); chkout_("CKW05", (ftnlen)5); return 0; } } /* Set the window, packet size and angular velocity flag, all of */ /* which are functions of the subtype. */ if (*subtyp == 0) { winsiz = (*degree + 1) / 2; packsz = 8; } else if (*subtyp == 1) { winsiz = *degree + 1; packsz = 4; } else if (*subtyp == 2) { winsiz = (*degree + 1) / 2; packsz = 14; } else if (*subtyp == 3) { winsiz = *degree + 1; packsz = 7; } else { setmsg_("CK type 5 subtype <#> is not supported.", (ftnlen)39); errint_("#", subtyp, (ftnlen)1); sigerr_("SPICE(NOTSUPPORTED)", (ftnlen)19); chkout_("CKW05", (ftnlen)5); return 0; } /* Make sure that the quaternions are non-zero. This is just */ /* a check for uninitialized data. */ i__1 = *n; for (i__ = 1; i__ <= i__1; ++i__) { /* We have to address the quaternion explicitly, since the shape */ /* of the packet array is not known at compile time. */ addr__ = packsz * (i__ - 1) + 1; if (vzerog_(&packts[addr__ - 1], &c__4)) { setmsg_("The quaternion at index # has magnitude zero.", (ftnlen) 45); errint_("#", &i__, (ftnlen)1); sigerr_("SPICE(ZEROQUATERNION)", (ftnlen)21); chkout_("CKW05", (ftnlen)5); return 0; } } /* Make sure that the degree of the interpolating polynomials is */ /* in range. */ if (*degree < 1 || *degree > 15) { setmsg_("The interpolating polynomials have degree #; the valid degr" "ee range is [1, #]", (ftnlen)77); errint_("#", degree, (ftnlen)1); errint_("#", &c__15, (ftnlen)1); sigerr_("SPICE(INVALIDDEGREE)", (ftnlen)20); chkout_("CKW05", (ftnlen)5); return 0; } /* Make sure that the window size is even. If not, the input */ /* DEGREE is incompatible with the subtype. */ if (odd_(&winsiz)) { setmsg_("The interpolating polynomials have degree #; for CK type 5," " the degree must be equivalent to 3 mod 4 for Hermite interp" "olation and odd for for Lagrange interpolation.", (ftnlen)166) ; errint_("#", degree, (ftnlen)1); sigerr_("SPICE(INVALIDDEGREE)", (ftnlen)20); chkout_("CKW05", (ftnlen)5); return 0; } /* If we made it this far, we're ready to start writing the segment. */ /* Create the segment descriptor. */ /* Assign values to the integer components of the segment descriptor. */ ic[0] = *inst; ic[1] = refcod; ic[2] = 5; if (*avflag) { ic[3] = 1; } else { ic[3] = 0; } dc[0] = *begtim; dc[1] = *endtim; /* Make sure the descriptor times are in increasing order. */ if (*endtim < *begtim) { setmsg_("Descriptor bounds are non-increasing: #:#", (ftnlen)41); errdp_("#", begtim, (ftnlen)1); errdp_("#", endtim, (ftnlen)1); sigerr_("SPICE(BADDESCRTIMES)", (ftnlen)20); chkout_("CKW05", (ftnlen)5); return 0; } /* Make sure that at least one time tag lies between BEGTIM and */ /* ENDTIM. The first time tag not less than BEGTIM must exist */ /* and must be less than or equal to ENDTIM. */ i__ = lstltd_(begtim, n, sclkdp); if (i__ == *n) { setmsg_("All time tags are less than segment start time #.", (ftnlen) 49); errdp_("#", begtim, (ftnlen)1); sigerr_("SPICE(EMPTYSEGMENT)", (ftnlen)19); chkout_("CKW05", (ftnlen)5); return 0; } else if (sclkdp[i__] > *endtim) { setmsg_("No time tags lie between the segment start time # and segme" "nt end time #", (ftnlen)72); errdp_("#", begtim, (ftnlen)1); errdp_("#", endtim, (ftnlen)1); sigerr_("SPICE(EMPTYSEGMENT)", (ftnlen)19); chkout_("CKW05", (ftnlen)5); return 0; } /* The clock rate must be non-zero. */ if (*rate == 0.) { setmsg_("The SCLK rate RATE was zero.", (ftnlen)28); sigerr_("SPICE(INVALIDVALUE)", (ftnlen)19); chkout_("CKW05", (ftnlen)5); return 0; } /* Now pack the segment descriptor. */ dafps_(&c__2, &c__6, dc, ic, descr); /* Begin a new segment. */ dafbna_(handle, descr, segid, segid_len); if (failed_()) { chkout_("CKW05", (ftnlen)5); return 0; } /* The type 5 segment structure is eloquently described by this */ /* diagram from the CK Required Reading: */ /* +-----------------------+ */ /* | Packet 1 | */ /* +-----------------------+ */ /* | Packet 2 | */ /* +-----------------------+ */ /* . */ /* . */ /* . */ /* +-----------------------+ */ /* | Packet N | */ /* +-----------------------+ */ /* | Epoch 1 | */ /* +-----------------------+ */ /* | Epoch 2 | */ /* +-----------------------+ */ /* . */ /* . */ /* . */ /* +----------------------------+ */ /* | Epoch N | */ /* +----------------------------+ */ /* | Epoch 100 | (First directory) */ /* +----------------------------+ */ /* . */ /* . */ /* . */ /* +----------------------------+ */ /* | Epoch ((N-1)/100)*100 | (Last directory) */ /* +----------------------------+ */ /* | Start time 1 | */ /* +----------------------------+ */ /* | Start time 2 | */ /* +----------------------------+ */ /* . */ /* . */ /* . */ /* +----------------------------+ */ /* | Start time M | */ /* +----------------------------+ */ /* | Start time 100 | (First interval start */ /* +----------------------------+ time directory) */ /* . */ /* . */ /* . */ /* +----------------------------+ */ /* | Start time ((M-1)/100)*100 | (Last interval start */ /* +----------------------------+ time directory) */ /* | Seconds per tick | */ /* +----------------------------+ */ /* | Subtype code | */ /* +----------------------------+ */ /* | Window size | */ /* +----------------------------+ */ /* | Number of interp intervals | */ /* +----------------------------+ */ /* | Number of packets | */ /* +----------------------------+ */ i__1 = *n * packsz; dafada_(packts, &i__1); dafada_(sclkdp, n); i__1 = (*n - 1) / 100; for (i__ = 1; i__ <= i__1; ++i__) { dafada_(&sclkdp[i__ * 100 - 1], &c__1); } /* Now add the interval start times. */ dafada_(starts, nints); /* And the directory of interval start times. The directory of */ /* start times will simply be every (DIRSIZ)th start time. */ i__1 = (*nints - 1) / 100; for (i__ = 1; i__ <= i__1; ++i__) { dafada_(&starts[i__ * 100 - 1], &c__1); } /* Add the SCLK rate, segment subtype, window size, interval */ /* count, and packet count. */ dafada_(rate, &c__1); d__1 = (doublereal) (*subtyp); dafada_(&d__1, &c__1); d__1 = (doublereal) winsiz; dafada_(&d__1, &c__1); d__1 = (doublereal) (*nints); dafada_(&d__1, &c__1); d__1 = (doublereal) (*n); dafada_(&d__1, &c__1); /* As long as nothing went wrong, end the segment. */ if (! failed_()) { dafena_(); } chkout_("CKW05", (ftnlen)5); return 0; } /* ckw05_ */
/* $Procedure GFPA ( GF, phase angle search ) */ /* Subroutine */ int gfpa_(char *target, char *illmn, char *abcorr, char * obsrvr, char *relate, doublereal *refval, doublereal *adjust, doublereal *step, doublereal *cnfine, integer *mw, integer *nw, doublereal *work, doublereal *result, ftnlen target_len, ftnlen illmn_len, ftnlen abcorr_len, ftnlen obsrvr_len, ftnlen relate_len) { /* System generated locals */ integer work_dim1, work_offset, i__1; /* Builtin functions */ /* Subroutine */ int s_copy(char *, char *, ftnlen, ftnlen); /* Local variables */ extern /* Subroutine */ int chkin_(char *, ftnlen); extern integer sized_(doublereal *); extern logical gfbail_(); logical ok; extern /* Subroutine */ int scardd_(integer *, doublereal *); extern /* Subroutine */ int gfrefn_(), gfrepi_(), gfrepf_(), gfrepu_(), gfstep_(); char qcpars[80*4], qpnams[80*4]; extern logical return_(void); doublereal qdpars[4]; integer qipars[4]; logical qlpars[4]; extern /* Subroutine */ int setmsg_(char *, ftnlen), errint_(char *, integer *, ftnlen), sigerr_(char *, ftnlen), chkout_(char *, ftnlen), gfsstp_(doublereal *), gfevnt_(U_fp, U_fp, char *, integer *, char *, char *, doublereal *, integer *, logical *, char *, doublereal *, doublereal *, doublereal *, doublereal *, logical *, U_fp, U_fp, U_fp, integer *, integer *, doublereal *, logical *, L_fp, doublereal *, ftnlen, ftnlen, ftnlen, ftnlen); extern logical odd_(integer *); doublereal tol; extern /* Subroutine */ int zzholdd_(integer *, integer *, logical *, doublereal *); /* $ Abstract */ /* Determine time intervals for which a specified constraint */ /* on the phase angle between an illumination source, a target, */ /* and observer body centers is met. */ /* $ 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 */ /* NAIF_IDS */ /* SPK */ /* TIME */ /* WINDOWS */ /* $ Keywords */ /* EVENT */ /* GEOMETRY */ /* EPHEMERIS */ /* SEARCH */ /* WINDOW */ /* $ 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 routine intended solely for the support of SPICE */ /* routines. Users should not call this routine directly due to the */ /* volatile nature of this routine. */ /* This file contains parameter declarations for the ZZHOLDD */ /* routine. */ /* $ 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 */ /* None. */ /* $ Declarations */ /* None. */ /* $ Brief_I/O */ /* None. */ /* $ Detailed_Input */ /* None. */ /* $ Detailed_Output */ /* None. */ /* $ Parameters */ /* GEN general value, primarily for testing. */ /* GF_REF user defined GF reference value. */ /* GF_TOL user defined GF convergence tolerance. */ /* GF_DT user defined GF step for numeric differentiation. */ /* $ Exceptions */ /* None. */ /* $ Files */ /* None. */ /* $ Particulars */ /* None. */ /* $ Examples */ /* None. */ /* $ Restrictions */ /* None. */ /* $ Literature_References */ /* None. */ /* $ Author_and_Institution */ /* E.D. Wright (JPL) */ /* $ Version */ /* - SPICELIB Version 1.0.0 03-DEC-2013 (EDW) */ /* -& */ /* OP codes. The values exist in the integer domain */ /* [ -ZZNOP, -1], */ /* Current number of OP codes. */ /* ID codes. The values exist in the integer domain */ /* [ 1, NID], */ /* General use, primarily testing. */ /* The user defined GF reference value. */ /* The user defined GF convergence tolerance. */ /* The user defined GF step for numeric differentiation. */ /* Current number of ID codes, dimension of array */ /* in ZZHOLDD. Bad things can happen if this parameter */ /* does not have the proper value. */ /* End of file zzholdd.inc. */ /* $ Brief_I/O */ /* Variable I/O Description */ /* -------- --- -------------------------------------------------- */ /* LBCELL P SPICE Cell lower bound. */ /* CNVTOL P Default convergence tolerance. */ /* TARGET I Name of the target body. */ /* ILLMN I Name of the illuminating body. */ /* ABCORR I Aberration correction flag. */ /* OBSRVR I Name of the observing body. */ /* RELATE I Relational operator. */ /* REFVAL I Reference value. */ /* ADJUST I Adjustment value for absolute extrema searches. */ /* STEP I Step size used for locating extrema and roots. */ /* CNFINE I SPICE window to which the search is confined. */ /* MW I Workspace window size. */ /* NW I The number of workspace windows needed for */ /* the search. */ /* WORK I-O Array of workspace windows. */ /* RESULT I-O SPICE window containing results. */ /* $ Detailed_Input */ /* TARGET the string name of a target body. Optionally, you may */ /* supply the integer ID code for the object as an */ /* integer string. For example both 'MOON' and '301' */ /* are legitimate strings that indicate the moon is the */ /* target body. */ /* Case and leading or trailing blanks are not significant */ /* in the string TARGET. */ /* ILLMN the string name of the illuminating body. This will */ /* normally be 'SUN' but the algorithm can use any */ /* ephemeris object */ /* Case and leading or trailing blanks are not significant */ /* in the string ILLMN. */ /* ABCORR the string description of the aberration corrections to */ /* apply to the state evaluations to account for one-way */ /* light time and stellar aberration. */ /* This routine accepts only reception mode aberration */ /* corrections. See the header of SPKEZR for a detailed */ /* description of the aberration correction options. */ /* For convenience, the allowed aberation options are */ /* listed below: */ /* 'NONE' Apply no correction. Returns the "true" */ /* geometric state. */ /* 'LT' "Reception" case: correct for */ /* one-way light time using a Newtonian */ /* formulation. */ /* 'LT+S' "Reception" case: correct for */ /* one-way light time and stellar */ /* aberration using a Newtonian */ /* formulation. */ /* 'CN' "Reception" case: converged */ /* Newtonian light time correction. */ /* 'CN+S' "Reception" case: converged */ /* Newtonian light time and stellar */ /* aberration corrections. */ /* Case and leading or trailing blanks are not significant */ /* in the string ABCORR. */ /* OBSRVR the string name of an observing body. Optionally, you */ /* may supply the ID code of the object as an integer */ /* string. For example both "MOON" and "301" are legitimate */ /* strings that indicate the Moon is the observer. */ /* Case and leading or trailing blanks are not significant */ /* in the string OBSRVR. */ /* RELATE the string or character describing the relational */ /* operator that defines the constraint on the */ /* phase angle of the observer-target vector. The result */ /* window found by this routine indicates the time intervals */ /* where the constraint is satisfied. Supported values of */ /* RELATE and corresponding meanings are shown below: */ /* '>' The phase angle value is greater than the */ /* reference value REFVAL. */ /* '=' The phase angle value is equal to the */ /* reference value REFVAL. */ /* '<' The phase angle value is less than the */ /* reference value REFVAL. */ /* 'ABSMAX' The phase angle value is at an absolute */ /* maximum. */ /* 'ABSMIN' The phase angle value is at an absolute */ /* minimum. */ /* 'LOCMAX' The phase angle value is at a local */ /* maximum. */ /* 'LOCMIN' The phase angle value is at a local */ /* minimum. */ /* The caller may indicate that the region of interest */ /* is the set of time intervals where the quantity is */ /* within a specified measure of an absolute extremum. */ /* The argument ADJUST (described below) is used to */ /* specify this measure. */ /* Local extrema are considered to exist only in the */ /* interiors of the intervals comprising the confinement */ /* window: a local extremum cannot exist at a boundary */ /* point of the confinement window. */ /* Case and leading or trailing blanks are not */ /* significant in the string RELATE. */ /* REFVAL the double precision reference value used together with */ /* the argument RELATE to define an equality or inequality */ /* to satisfy by the phase angle of the observer-target */ /* vector. See the discussion of RELATE above for */ /* further information. */ /* The units of REFVAL are radians. */ /* ADJUST a double precision value used to modify searches for */ /* absolute extrema: when RELATE is set to ABSMAX or ABSMIN */ /* and ADJUST is set to a positive value, GFPA finds */ /* times when the phase angle is within */ /* ADJUST radians of the specified extreme value. */ /* For RELATE set to ABSMAX, the RESULT window contains */ /* time intervals when the phase angle has */ /* values between ABSMAX - ADJUST and ABSMAX. */ /* For RELATE set to ABSMIN, the RESULT window contains */ /* time intervals when the phase angle has */ /* values between ABSMIN and ABSMIN + ADJUST. */ /* ADJUST is not used for searches for local extrema, */ /* equality or inequality conditions. */ /* STEP the double precision time step size to use in the search. */ /* STEP must be short enough for a search using this step */ /* size to locate the time intervals where the phase angle */ /* function is monotone increasing or decreasing. However, */ /* STEP must not be *too* short, or the search will take an */ /* unreasonable amount of time. */ /* The choice of STEP affects the completeness but not */ /* the precision of solutions found by this routine; the */ /* precision is controlled by the convergence tolerance. */ /* See the discussion of the parameter CNVTOL for */ /* details. */ /* STEP has units of TDB seconds. */ /* CNFINE a double precision SPICE window that confines the time */ /* period over which the specified search is conducted. */ /* CNFINE may consist of a single interval or a collection */ /* of intervals. */ /* In some cases the confinement window can be used to */ /* greatly reduce the time period that must be searched */ /* for the desired solution. See the Particulars section */ /* below for further discussion. */ /* See the Examples section below for a code example */ /* that shows how to create a confinement window. */ /* CNFINE must be initialized by the caller using the */ /* SPICELIB routine SSIZED. */ /* MW is a parameter specifying the length of the SPICE */ /* windows in the workspace array WORK (see description */ /* below) used by this routine. */ /* MW should be set to a number at least twice as large */ /* as the maximum number of intervals required by any */ /* workspace window. In many cases, it's not necessary to */ /* compute an accurate estimate of how many intervals are */ /* needed; rather, the user can pick a size considerably */ /* larger than what's really required. */ /* However, since excessively large arrays can prevent */ /* applications from compiling, linking, or running */ /* properly, sometimes MW must be set according to */ /* the actual workspace requirement. A rule of thumb */ /* for the number of intervals NINTVLS needed is */ /* NINTVLS = 2*N + ( M / STEP ) */ /* where */ /* N is the number of intervals in the confinement */ /* window */ /* M is the measure of the confinement window, in */ /* units of seconds */ /* STEP is the search step size in seconds */ /* MW should then be set to */ /* 2 * NINTVLS */ /* NW is a parameter specifying the number of SPICE windows */ /* in the workspace array WORK (see description below) */ /* used by this routine. NW should be set to the */ /* parameter NWPA; this parameter is declared in the */ /* include file gf.inc. (The reason this dimension is */ /* an input argument is that this allows run-time */ /* error checking to be performed.) */ /* WORK is an array used to store workspace windows. This */ /* array should be declared by the caller as shown: */ /* INCLUDE 'gf.inc' */ /* ... */ /* DOUBLE PRECISION WORK ( LBCELL : MW, NWPA ) */ /* where MW is a constant declared by the caller and */ /* NWPA is a constant defined in the SPICELIB INCLUDE */ /* file gf.inc. See the discussion of MW above. */ /* WORK need not be initialized by the caller. */ /* RESULT a double precision SPICE window that will contain the */ /* search results. RESULT must be initialized using */ /* a call to SSIZED. RESULT must be declared and initialized */ /* with sufficient size to capture the full set of time */ /* intervals within the search region on which the specified */ /* constraint is satisfied. */ /* If RESULT is non-empty on input, its contents */ /* will be discarded before GFPA conducts its */ /* search. */ /* $ Detailed_Output */ /* WORK the input workspace array, modified by this */ /* routine. */ /* RESULT the SPICE window of intervals, contained within the */ /* confinement window CNFINE, on which the specified */ /* constraint is satisfied. */ /* If the search is for local extrema, or for absolute */ /* extrema with ADJUST set to zero, then normally each */ /* interval of RESULT will be a singleton: the left and */ /* right endpoints of each interval will be identical. */ /* If no times within the confinement window satisfy the */ /* constraint, RESULT will return with a cardinality of */ /* zero. */ /* $ Parameters */ /* LBCELL the integer value defining the lower bound for */ /* SPICE Cell arrays (a SPICE window is a kind of cell). */ /* CNVTOL is the default convergence tolerance used for finding */ /* endpoints of the intervals comprising the result */ /* window. CNVTOL is also used for finding intermediate */ /* results; in particular, CNVTOL is used for finding the */ /* windows on which the phase angle is increasing */ /* or decreasing. CNVTOL is used to determine when binary */ /* searches for roots should terminate: when a root is */ /* bracketed within an interval of length CNVTOL; the */ /* root is considered to have been found. */ /* The accuracy, as opposed to precision, of roots found */ /* by this routine depends on the accuracy of the input */ /* data. In most cases, the accuracy of solutions will be */ /* inferior to their precision. */ /* See INCLUDE file gf.inc for declarations and descriptions of */ /* parameters used throughout the GF system. */ /* $ Exceptions */ /* 1) In order for this routine to produce correct results, */ /* the step size must be appropriate for the problem at hand. */ /* Step sizes that are too large may cause this routine to miss */ /* roots; step sizes that are too small may cause this routine */ /* to run unacceptably slowly and in some cases, find spurious */ /* roots. */ /* This routine does not diagnose invalid step sizes, except */ /* that if the step size is non-positive, the error */ /* SPICE(INVALIDSTEP) is signaled. */ /* 2) Due to numerical errors, in particular, */ /* - truncation error in time values */ /* - finite tolerance value */ /* - errors in computed geometric quantities */ /* it is *normal* for the condition of interest to not always be */ /* satisfied near the endpoints of the intervals comprising the */ /* RESULT window. One technique to handle such a situation, */ /* slightly contract RESULT using the window routine WNCOND. */ /* 3) SPICE(INVALIDDIMENSION) signals if workspace window size, MW, */ /* is not at least 2 and an even value. */ /* 4) SPICE(INVALIDDIMENSION) signals if workspace window count, */ /* NW, is not at least NWPA. */ /* 5) SPICE(INVALIDDIMENSION) signals if result window, RESULT, */ /* is not at least 2 and an even value. */ /* 6) If RESULT has insufficient capacity to contain the */ /* number of intervals on which the specified angle condition */ /* is met, the error will be diagnosed by a routine in the call */ /* tree of this routine. */ /* 7) If an error (typically cell overflow) occurs during */ /* window arithmetic, the error will be diagnosed by a routine */ /* in the call tree of this routine. */ /* 8) If the relational operator RELATE is not recognized, an */ /* error is signaled by a routine in the call tree of this */ /* routine. */ /* 9) If ADJUST is negative an error is signaled from a routine in */ /* the call tree of this routine. */ /* A non-zero value for ADJUST when RELATE has any value other */ /* than "ABSMIN" or "ABSMAX" causes the error SPICE(INVALIDVALUE) */ /* to signal from a routine in the call tree of this routine. */ /* 10) If any of the input body names, TARGET, ILLMN, OBSRVR, do */ /* not map to NAIF ID codes, an error is signaled by a routine */ /* in the call tree of this routine. */ /* 11) If the input body names, TARGET, ILLMN, OBSRVR, are not */ /* distinct, an error is signaled by a routine in the call */ /* tree of this routine. */ /* 12) If required ephemerides or other kernel data are not */ /* available, an error is signaled by a routine in the call tree */ /* of this routine. */ /* 13) An error signals from a routine in the call tree of */ /* this routine for any transmit mode aberration correction. */ /* $ Files */ /* Appropriate SPK and PCK kernels must be loaded by the calling */ /* program before this routine is called. */ /* The following data are required: */ /* - SPK data: the calling application must load ephemeris data */ /* for the targets, observer, and any intermediate objects in */ /* a chain connecting the targets and observer that cover the */ /* time period specified by the window CNFINE. 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 using */ /* FURNSH. */ /* Kernel data are normally loaded once per program run, NOT every */ /* time this routine is called. */ /* $ Particulars */ /* ILLMN OBS */ /* ILLMN as seen * / */ /* from TARG at | / */ /* ET - LT. | / */ /* >|..../< phase angle */ /* | / */ /* . | / */ /* . | / */ /* . * TARG as seen from OBS */ /* SEP . TARG at ET */ /* . / */ /* / */ /* * */ /* This routine determines if the caller-specified constraint */ /* condition on the geometric event (phase angle) is satisfied for */ /* any time intervals within the confinement window CNFINE. If one */ /* or more such time intervals exist, those intervals are added */ /* to the RESULT window. */ /* This routine provides a simpler, but less flexible interface */ /* than does the routine GFEVNT for conducting searches for */ /* illuminator-target-observer phase angle value events. */ /* Applications that require support for progress reporting, */ /* interrupt handling, non-default step or refinement functions */ /* should call GFEVNT rather than this routine. */ /* Below we discuss in greater detail aspects of this routine's */ /* solution process that are relevant to correct and efficient */ /* use of this routine in user applications. */ /* The Search Process */ /* ================== */ /* Regardless of the type of constraint selected by the caller, this */ /* routine starts the search for solutions by determining the time */ /* periods, within the confinement window, over which the */ /* phase angle function is monotone increasing and monotone */ /* decreasing. Each of these time periods is represented by a SPICE */ /* window. Having found these windows, all of the phase angle */ /* function's local extrema within the confinement window are known. */ /* Absolute extrema then can be found very easily. */ /* Within any interval of these "monotone" windows, there will be at */ /* most one solution of any equality constraint. Since the boundary */ /* of the solution set for any inequality constraint is contained in */ /* the union of */ /* - the set of points where an equality constraint is met */ /* - the boundary points of the confinement window */ /* the solutions of both equality and inequality constraints can be */ /* found easily once the monotone windows have been found. */ /* Step Size */ /* ========= */ /* The monotone windows (described above) are found using a two-step */ /* search process. Each interval of the confinement window is */ /* searched as follows: first, the input step size is used to */ /* determine the time separation at which the sign of the rate of */ /* change of phase angle will be sampled. Starting at */ /* the left endpoint of an interval, samples will be taken at each */ /* step. If a change of sign is found, a root has been bracketed; at */ /* that point, the time at which the time derivative of the */ /* phase angle is zero can be found by a refinement process, for */ /* example, using a binary search. */ /* Note that the optimal choice of step size depends on the lengths */ /* of the intervals over which the phase angle function is monotone: */ /* the step size should be shorter than the shortest of these */ /* intervals (within the confinement window). */ /* The optimal step size is *not* necessarily related to the lengths */ /* of the intervals comprising the result window. For example, if */ /* the shortest monotone interval has length 10 days, and if the */ /* shortest result window interval has length 5 minutes, a step size */ /* of 9.9 days is still adequate to find all of the intervals in the */ /* result window. In situations like this, the technique of using */ /* monotone windows yields a dramatic efficiency improvement over a */ /* state-based search that simply tests at each step whether the */ /* specified constraint is satisfied. The latter type of search can */ /* miss solution intervals if the step size is longer than the */ /* shortest solution interval. */ /* Having some knowledge of the relative geometry of the target, */ /* illumination source, and observer can be a valuable aid in */ /* picking a reasonable step size. In general, the user can */ /* compensate for lack of such knowledge by picking a very short */ /* step size; the cost is increased computation time. */ /* Note that the step size is not related to the precision with which */ /* the endpoints of the intervals of the result window are computed. */ /* That precision level is controlled by the convergence tolerance. */ /* Convergence Tolerance */ /* ===================== */ /* As described above, the root-finding process used by this routine */ /* involves first bracketing roots and then using a search process */ /* to locate them. "Roots" are both times when local extrema are */ /* attained and times when the geometric quantity function is equal */ /* to a reference value. All endpoints of the intervals comprising */ /* the result window are either endpoints of intervals of the */ /* confinement window or roots. */ /* Once a root has been bracketed, a refinement process is used to */ /* narrow down the time interval within which the root must lie. */ /* This refinement process terminates when the location of the root */ /* has been determined to within an error margin called the */ /* "convergence tolerance." The default convergence tolerance */ /* used by this routine is set by the parameter CNVTOL (defined */ /* in gf.inc). */ /* The value of CNVTOL is set to a "tight" value so that the */ /* tolerance doesn't become the limiting factor in the accuracy of */ /* solutions found by this routine. In general the accuracy of input */ /* data will be the limiting factor. */ /* The user may change the convergence tolerance from the default */ /* CNVTOL value by calling the routine GFSTOL, e.g. */ /* CALL GFSTOL( tolerance value ) */ /* Call GFSTOL prior to calling this routine. All subsequent */ /* searches will use the updated tolerance value. */ /* Setting the tolerance tighter than CNVTOL is unlikely to be */ /* useful, since the results are unlikely to be more accurate. */ /* Making the tolerance looser will speed up searches somewhat, */ /* since a few convergence steps will be omitted. However, in most */ /* cases, the step size is likely to have a much greater effect */ /* on processing time than would the convergence tolerance. */ /* The Confinement Window */ /* ====================== */ /* The simplest use of the confinement window is to specify a time */ /* interval within which a solution is sought. However, the */ /* confinement window can, in some cases, be used to make searches */ /* more efficient. Sometimes it's possible to do an efficient search */ /* to reduce the size of the time period over which a relatively */ /* slow search of interest must be performed. */ /* $ Examples */ /* The numerical results shown for these examples may differ across */ /* platforms. The results depend on the SPICE kernels used as */ /* input, the compiler and supporting libraries, and the machine */ /* specific arithmetic implementation. */ /* Use the meta-kernel shown below to load the required SPICE */ /* kernels. */ /* KPL/MK */ /* File name: standard.tm */ /* This meta-kernel is intended to support operation of SPICE */ /* example programs. The kernels shown here should not be */ /* assumed to contain adequate or correct versions of data */ /* required by SPICE-based user applications. */ /* In order for an application to use this meta-kernel, the */ /* kernels referenced here must be present in the user's */ /* current working directory. */ /* The names and contents of the kernels referenced */ /* by this meta-kernel are as follows: */ /* File name Contents */ /* --------- -------- */ /* de421.bsp Planetary ephemeris */ /* pck00009.tpc Planet orientation and */ /* radii */ /* naif0009.tls Leapseconds */ /* \begindata */ /* KERNELS_TO_LOAD = ( 'de421.bsp', */ /* 'pck00009.tpc', */ /* 'naif0009.tls' ) */ /* \begintext */ /* Determine the time windows from December 1, 2006 UTC to */ /* January 31, 2007 UTC for which the sun-moon-earth configuration */ /* phase angle satisfies the relation conditions with respect to a */ /* reference value of .57598845 radians (the phase angle at */ /* January 1, 2007 00:00:00.000 UTC, 33.001707 degrees). Also */ /* determine the time windows corresponding to the local maximum and */ /* minimum phase angles, and the absolute maximum and minimum phase */ /* angles during the search interval. The configuration defines the */ /* sun as the illuminator, the moon as the target, and the earth as */ /* the observer. */ /* PROGRAM GFPA_T */ /* IMPLICIT NONE */ /* C */ /* C Include GF parameter declarations: */ /* C */ /* INCLUDE 'gf.inc' */ /* C */ /* C SPICELIB functions */ /* C */ /* DOUBLE PRECISION SPD */ /* DOUBLE PRECISION PHASEQ */ /* INTEGER WNCARD */ /* C */ /* C Local parameters */ /* C */ /* INTEGER LBCELL */ /* PARAMETER ( LBCELL = -5 ) */ /* C */ /* C Use the parameter MAXWIN for both the result window size */ /* C and the workspace size. */ /* C */ /* INTEGER MAXWIN */ /* PARAMETER ( MAXWIN = 1000 ) */ /* C */ /* C Length of strings: */ /* C */ /* INTEGER TIMLEN */ /* PARAMETER ( TIMLEN = 26 ) */ /* INTEGER NLOOPS */ /* PARAMETER ( NLOOPS = 7 ) */ /* C */ /* C Local variables */ /* C */ /* CHARACTER*(TIMLEN) RELATE (NLOOPS) */ /* CHARACTER*(6) ABCORR */ /* CHARACTER*(6) ILLMN */ /* CHARACTER*(6) OBSRVR */ /* CHARACTER*(6) TARGET */ /* CHARACTER*(TIMLEN) TIMSTR */ /* DOUBLE PRECISION CNFINE ( LBCELL : 2 ) */ /* DOUBLE PRECISION RESULT ( LBCELL : MAXWIN ) */ /* DOUBLE PRECISION WORK ( LBCELL : MAXWIN, NWPA ) */ /* DOUBLE PRECISION ADJUST */ /* DOUBLE PRECISION ET0 */ /* DOUBLE PRECISION ET1 */ /* DOUBLE PRECISION FINISH */ /* DOUBLE PRECISION PHASE */ /* DOUBLE PRECISION REFVAL */ /* DOUBLE PRECISION START */ /* DOUBLE PRECISION STEP */ /* INTEGER I */ /* INTEGER J */ /* C */ /* C The relation values for the search. */ /* C */ /* DATA RELATE / '=', */ /* . '<', */ /* . '>', */ /* . 'LOCMIN', */ /* . 'ABSMIN', */ /* . 'LOCMAX', */ /* . 'ABSMAX' / */ /* C */ /* C Load kernels. */ /* C */ /* CALL FURNSH ( 'standard.tm' ) */ /* C */ /* C Initialize windows. */ /* C */ /* CALL SSIZED ( MAXWIN, RESULT ) */ /* CALL SSIZED ( 2, CNFINE ) */ /* C */ /* C Store the time bounds of our search interval in */ /* C the confinement window. */ /* C */ /* CALL STR2ET ( '2006 DEC 01', ET0 ) */ /* CALL STR2ET ( '2007 JAN 31', ET1 ) */ /* CALL WNINSD ( ET0, ET1, CNFINE ) */ /* C */ /* C Search using a step size of 1 day (in units of seconds). */ /* C The reference value is 0.57598845 radians. We're not */ /* C using the adjustment feature, so we set ADJUST to zero. */ /* C */ /* STEP = SPD() */ /* REFVAL = 0.57598845D0 */ /* ADJUST = 0.D0 */ /* C */ /* C Define the values for target, observer, illuminator, and */ /* C aberration correction. */ /* C */ /* TARGET = 'MOON' */ /* ILLMN = 'SUN' */ /* ABCORR = 'LT+S' */ /* OBSRVR = 'EARTH' */ /* DO J=1, NLOOPS */ /* WRITE(*,*) 'Relation condition: ', RELATE(J) */ /* C */ /* C Perform the search. The SPICE window RESULT contains */ /* C the set of times when the condition is met. */ /* C */ /* CALL GFPA ( TARGET, ILLMN, ABCORR, OBSRVR, */ /* . RELATE(J), REFVAL, ADJUST, STEP, */ /* . CNFINE, MAXWIN, NWPA, WORK, */ /* . RESULT ) */ /* C */ /* C Display the results. */ /* C */ /* IF ( WNCARD(RESULT) .EQ. 0 ) THEN */ /* WRITE (*, '(A)') 'Result window is empty.' */ /* ELSE */ /* DO I = 1, WNCARD(RESULT) */ /* C */ /* C Fetch the endpoints of the Ith interval */ /* C of the result window. */ /* C */ /* CALL WNFETD ( RESULT, I, START, FINISH ) */ /* PHASE = PHASEQ( START, TARGET, ILLMN, OBSRVR, */ /* . ABCORR ) */ /* CALL TIMOUT ( START, */ /* . 'YYYY-MON-DD HR:MN:SC.###', */ /* . TIMSTR ) */ /* WRITE (*, '(A,F16.9)') 'Start time = '//TIMSTR, */ /* . PHASE */ /* PHASE = PHASEQ( FINISH, TARGET, ILLMN, OBSRVR, */ /* . ABCORR ) */ /* CALL TIMOUT ( FINISH, */ /* . 'YYYY-MON-DD HR:MN:SC.###', */ /* . TIMSTR ) */ /* WRITE (*, '(A,F16.9)') 'Stop time = '//TIMSTR, */ /* . PHASE */ /* END DO */ /* END IF */ /* WRITE(*,*) ' ' */ /* END DO */ /* END */ /* The program outputs: */ /* Relation condition: = */ /* Start time = 2006-DEC-02 13:31:34.414 0.575988450 */ /* Stop time = 2006-DEC-02 13:31:34.414 0.575988450 */ /* Start time = 2006-DEC-07 14:07:55.470 0.575988450 */ /* Stop time = 2006-DEC-07 14:07:55.470 0.575988450 */ /* Start time = 2006-DEC-31 23:59:59.997 0.575988450 */ /* Stop time = 2006-DEC-31 23:59:59.997 0.575988450 */ /* Start time = 2007-JAN-06 08:16:25.512 0.575988450 */ /* Stop time = 2007-JAN-06 08:16:25.512 0.575988450 */ /* Start time = 2007-JAN-30 11:41:32.557 0.575988450 */ /* Stop time = 2007-JAN-30 11:41:32.557 0.575988450 */ /* Relation condition: < */ /* Start time = 2006-DEC-02 13:31:34.414 0.575988450 */ /* Stop time = 2006-DEC-07 14:07:55.470 0.575988450 */ /* Start time = 2006-DEC-31 23:59:59.997 0.575988450 */ /* Stop time = 2007-JAN-06 08:16:25.512 0.575988450 */ /* Start time = 2007-JAN-30 11:41:32.557 0.575988450 */ /* Stop time = 2007-JAN-31 00:00:00.000 0.468279091 */ /* Relation condition: > */ /* Start time = 2006-DEC-01 00:00:00.000 0.940714974 */ /* Stop time = 2006-DEC-02 13:31:34.414 0.575988450 */ /* Start time = 2006-DEC-07 14:07:55.470 0.575988450 */ /* Stop time = 2006-DEC-31 23:59:59.997 0.575988450 */ /* Start time = 2007-JAN-06 08:16:25.512 0.575988450 */ /* Stop time = 2007-JAN-30 11:41:32.557 0.575988450 */ /* Relation condition: LOCMIN */ /* Start time = 2006-DEC-05 00:16:50.416 0.086121423 */ /* Stop time = 2006-DEC-05 00:16:50.416 0.086121423 */ /* Start time = 2007-JAN-03 14:18:32.086 0.079899769 */ /* Stop time = 2007-JAN-03 14:18:32.086 0.079899769 */ /* Relation condition: ABSMIN */ /* Start time = 2007-JAN-03 14:18:32.086 0.079899769 */ /* Stop time = 2007-JAN-03 14:18:32.086 0.079899769 */ /* Relation condition: LOCMAX */ /* Start time = 2006-DEC-20 14:09:10.496 3.055062862 */ /* Stop time = 2006-DEC-20 14:09:10.496 3.055062862 */ /* Start time = 2007-JAN-19 04:27:54.694 3.074603891 */ /* Stop time = 2007-JAN-19 04:27:54.694 3.074603891 */ /* Relation condition: ABSMAX */ /* Start time = 2007-JAN-19 04:27:54.694 3.074603891 */ /* Stop time = 2007-JAN-19 04:27:54.694 3.074603891 */ /* $ Restrictions */ /* 1) The kernel files to be used by this routine must be loaded */ /* (normally using the SPICELIB routine FURNSH) before this */ /* routine is called. */ /* $ Literature_References */ /* None. */ /* $ Author_and_Institution */ /* E.D. Wright (JPL) */ /* N.J. Bachman (JPL) */ /* $ Version */ /* - SPICELIB Version 1.0.0, 15-JUL-2014 (EDW) (NJB) */ /* -& */ /* $ Index_Entries */ /* GF phase angle search */ /* -& */ /* SPICELIB functions */ /* Routines to set step size, refine transition times */ /* and report work. */ /* Local parameters */ /* Local variables */ /* Quantity definition parameter arrays: */ /* Standard SPICE error handling. */ /* Parameter adjustments */ work_dim1 = *mw + 6; work_offset = work_dim1 - 5; /* Function Body */ if (return_()) { return 0; } /* Check into the error subsystem. */ chkin_("GFPA", (ftnlen)4); /* Confirm minimum window sizes. */ if (*mw < 2 || odd_(mw)) { setmsg_("Workspace window size was #; size must be at least 2 and an" " even value.", (ftnlen)71); errint_("#", mw, (ftnlen)1); sigerr_("SPICE(INVALIDDIMENSION)", (ftnlen)23); chkout_("GFPA", (ftnlen)4); return 0; } if (*nw < 5) { setmsg_("Workspace window count was #; count must be at least #.", ( ftnlen)55); errint_("#", nw, (ftnlen)1); errint_("#", &c__5, (ftnlen)1); sigerr_("SPICE(INVALIDDIMENSION)", (ftnlen)23); chkout_("GFPA", (ftnlen)4); return 0; } /* Check the result window size. */ i__1 = sized_(result); if (sized_(result) < 2 || odd_(&i__1)) { setmsg_("Result window size was #; size must be at least 2 and an ev" "en value.", (ftnlen)68); i__1 = sized_(result); errint_("#", &i__1, (ftnlen)1); sigerr_("SPICE(INVALIDDIMENSION)", (ftnlen)23); chkout_("GFPA", (ftnlen)4); return 0; } /* Set up a call to GFEVNT specific to the phase angle search. */ s_copy(qpnams, "TARGET", (ftnlen)80, (ftnlen)6); s_copy(qcpars, target, (ftnlen)80, target_len); s_copy(qpnams + 80, "OBSERVER", (ftnlen)80, (ftnlen)8); s_copy(qcpars + 80, obsrvr, (ftnlen)80, obsrvr_len); s_copy(qpnams + 160, "ABCORR", (ftnlen)80, (ftnlen)6); s_copy(qcpars + 160, abcorr, (ftnlen)80, abcorr_len); s_copy(qpnams + 240, "ILLUM", (ftnlen)80, (ftnlen)5); s_copy(qcpars + 240, illmn, (ftnlen)80, illmn_len); /* Set the step size. */ gfsstp_(step); /* Retrieve the convergence tolerance, if set. */ zzholdd_(&c_n1, &c__3, &ok, &tol); /* Use the default value CNVTOL if no stored tolerance value. */ if (! ok) { tol = 1e-6; } /* Initialize the RESULT window to empty. */ scardd_(&c__0, result); /* Look for solutions. */ /* Progress report and interrupt options are set to .FALSE. */ gfevnt_((U_fp)gfstep_, (U_fp)gfrefn_, "PHASE ANGLE", &c__4, qpnams, qcpars, qdpars, qipars, qlpars, relate, refval, &tol, adjust, cnfine, &c_false, (U_fp)gfrepi_, (U_fp)gfrepu_, (U_fp)gfrepf_, mw, &c__5, work, &c_false, (L_fp)gfbail_, result, (ftnlen)11, ( ftnlen)80, (ftnlen)80, relate_len); chkout_("GFPA", (ftnlen)4); return 0; } /* gfpa_ */
/* $Procedure SPKW19 ( Write SPK segment, type 19 ) */ /* Subroutine */ int spkw19_(integer *handle, integer *body, integer *center, char *frame, doublereal *first, doublereal *last, char *segid, integer *nintvl, integer *npkts, integer *subtps, integer *degres, doublereal *packts, doublereal *epochs, doublereal *ivlbds, logical * sellst, ftnlen frame_len, ftnlen segid_len) { /* Initialized data */ static integer pktszs[2] = { 12,6 }; /* System generated locals */ integer i__1, i__2; doublereal d__1; /* Builtin functions */ integer s_rnge(char *, integer, char *, integer); /* Local variables */ integer isel, ndir, i__, j, k; extern /* Subroutine */ int chkin_(char *, ftnlen), dafps_(integer *, integer *, doublereal *, integer *, doublereal *); doublereal descr[5]; extern /* Subroutine */ int errch_(char *, char *, ftnlen, ftnlen); integer bepix, eepix; extern /* Subroutine */ int errdp_(char *, doublereal *, ftnlen), dafada_( doublereal *, integer *); doublereal dc[2]; extern /* Subroutine */ int dafbna_(integer *, doublereal *, char *, ftnlen); integer ic[6]; extern /* Subroutine */ int dafena_(void); extern logical failed_(void); integer segbeg, chrcod, refcod, segend, pktbeg; extern /* Subroutine */ int namfrm_(char *, integer *, ftnlen); extern integer lastnb_(char *, ftnlen); integer pktend; extern /* Subroutine */ int sigerr_(char *, ftnlen), chkout_(char *, ftnlen), setmsg_(char *, ftnlen), errint_(char *, integer *, ftnlen); integer minisz; extern logical return_(void); integer pktdsz, winsiz, pktsiz, subtyp; extern logical odd_(integer *); /* $ Abstract */ /* Write a type 19 segment to an SPK file. */ /* $ 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 */ /* DAF */ /* NAIF_IDS */ /* SPC */ /* SPK */ /* TIME */ /* $ Keywords */ /* EPHEMERIS */ /* FILES */ /* $ Declarations */ /* $ Abstract */ /* Declare parameters specific to SPK type 19. */ /* $ 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 */ /* SPK */ /* $ Restrictions */ /* None. */ /* $ Author_and_Institution */ /* N.J. Bachman (JPL) */ /* B.V. Semenov (JPL) */ /* $ Literature_References */ /* None. */ /* $ Version */ /* - SPICELIB Version 1.0.0, 07-MAR-2014 (NJB) (BVS) */ /* -& */ /* Maximum polynomial degree supported by the current */ /* implementation of this SPK type. */ /* The degree is compatible with the maximum degrees */ /* supported by types 13 and 21. */ /* Integer code indicating `true': */ /* Integer code indicating `false': */ /* SPK type 19 subtype codes: */ /* Subtype 0: Hermite interpolation, 12-element packets. */ /* Subtype 1: Lagrange interpolation, 6-element packets. */ /* Packet sizes associated with the various subtypes: */ /* Number of subtypes: */ /* Maximum packet size for type 19: */ /* Minimum packet size for type 19: */ /* The SPKPVN record size declared in spkrec.inc must be at least as */ /* large as the maximum possible size of an SPK type 19 record. */ /* The largest possible SPK type 19 record has subtype 1 (note that */ /* records of subtype 0 have half as many epochs as those of subtype */ /* 1, for a given polynomial degree). A type 1 record contains */ /* - The subtype and packet count */ /* - MAXDEG+1 packets of size S19PS1 */ /* - MAXDEG+1 time tags */ /* End of include file spk19.inc. */ /* $ Abstract */ /* Declare SPK data record size. This record is declared in */ /* SPKPVN and is passed to SPK reader (SPKRxx) and evaluator */ /* (SPKExx) routines. */ /* $ 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 */ /* SPK */ /* $ Restrictions */ /* 1) If new SPK types are added, it may be necessary to */ /* increase the size of this record. The header of SPKPVN */ /* should be updated as well to show the record size */ /* requirement for each data type. */ /* $ Author_and_Institution */ /* N.J. Bachman (JPL) */ /* $ Literature_References */ /* None. */ /* $ Version */ /* - SPICELIB Version 2.0.0, 05-OCT-2012 (NJB) */ /* Updated to support increase of maximum degree to 27 for types */ /* 2, 3, 8, 9, 12, 13, 18, and 19. See SPKPVN for a list */ /* of record size requirements as a function of data type. */ /* - SPICELIB Version 1.0.0, 16-AUG-2002 (NJB) */ /* -& */ /* End include file spkrec.inc */ /* $ Brief_I/O */ /* Variable I/O Description */ /* -------- --- -------------------------------------------------- */ /* HANDLE I Handle of an SPK file open for writing. */ /* BODY I NAIF ID code for an ephemeris object. */ /* CENTER I NAIF ID code for center of motion of BODY. */ /* FRAME I Reference frame name. */ /* FIRST I Start time of interval covered by segment. */ /* LAST I End time of interval covered by segment. */ /* SEGID I Segment identifier. */ /* NINTVL I Number of mini-segments and interpolation */ /* intervals. */ /* NPKTS I Array of packet counts of mini-segments. */ /* SUBTPS I Array of segment subtypes of mini-segments. */ /* DEGRES I Array of polynomial degrees of mini-segments. */ /* PACKTS I Array of data packets of mini-segments. */ /* EPOCHS I Array of epochs of mini-segments. */ /* IVLBDS I Interpolation interval bounds. */ /* SELLST I Interval selection flag. */ /* MAXDEG P Maximum allowed degree of interpolating polynomial. */ /* $ Detailed_Input */ /* HANDLE is the handle of an SPK file that has been opened */ /* for writing. */ /* BODY is the NAIF integer code for an ephemeris object */ /* whose state relative to another body is described */ /* by the segment to be created. */ /* CENTER is the NAIF integer code for the center of motion */ /* of the object identified by BODY. */ /* FRAME is the NAIF name for a reference frame */ /* relative to which the state information for BODY */ /* is specified. */ /* FIRST, */ /* LAST are, respectively, the bounds of the time interval */ /* over which the segment defines the state of BODY. */ /* FIRST must be greater than or equal to the first */ /* interpolation interval start time; LAST must be */ /* less than or equal to the last interpolation */ /* interval stop time. See the description of IVLBDS */ /* below. */ /* SEGID is the segment identifier. An SPK segment */ /* identifier may contain up to 40 characters. */ /* NINTVL is the number of interpolation intervals */ /* associated with the input data. The interpolation */ /* intervals are associated with data sets referred */ /* to as "mini-segments." */ /* The input data comprising each mini-segment are: */ /* - a packet count */ /* - a type 19 subtype */ /* - an interpolating polynomial degree */ /* - a sequence of type 19 data packets */ /* - a sequence of packet epochs */ /* These inputs are described below. */ /* NPKTS is an array of packet counts. The Ith element of */ /* NPKTS is the packet count of the Ith interpolation */ /* interval/mini-segment. */ /* NPKTS has dimension NINTVL. */ /* SUBTPS is an array of type 19 subtypes. The Ith element */ /* of SUBTPS is the subtype of the packets associated */ /* with the Ith interpolation interval/mini-segment. */ /* SUBTPS has dimension NINTVL. */ /* DEGRES is an array of interpolating polynomial degrees. */ /* The Ith element of DEGRES is the polynomial degree */ /* of the packets associated with the Ith */ /* interpolation interval/mini-segment. */ /* For subtype 0, interpolation degrees must be */ /* equivalent to 3 mod 4, that is, they must be in */ /* the set */ /* { 3, 7, 11, ..., MAXDEG } */ /* For subtype 1, interpolation degrees must be odd */ /* and must be in the range 1:MAXDEG. */ /* DEGRES has dimension NINTVL. */ /* PACKTS is an array containing data packets for all input */ /* mini-segments. The packets for a given */ /* mini-segment are stored contiguously in increasing */ /* time order. The order of the sets of packets for */ /* different mini-segments is the same as the order */ /* of their corresponding interpolation intervals. */ /* Each packet represents geometric states of BODY */ /* relative to CENTER, specified relative to FRAME. */ /* The packet structure depends on the segment */ /* subtype as follows: */ /* Type 0 (indicated by code S19TP0): */ /* x, y, z, dx/dt, dy/dt, dz/dt, */ /* vx, vy, vz, dvx/dt, dvy/dt, dvz/dt */ /* where x, y, z represent Cartesian position */ /* components and vx, vy, vz represent Cartesian */ /* velocity components. Note well: vx, vy, and */ /* vz *are not necessarily equal* to the time */ /* derivatives of x, y, and z. This packet */ /* structure mimics that of the Rosetta/MEX orbit */ /* file. */ /* Type 1 (indicated by code S19TP1): */ /* x, y, z, dx/dt, dy/dt, dz/dt */ /* where x, y, z represent Cartesian position */ /* components and vx, vy, vz represent Cartesian */ /* velocity components. */ /* Position units are kilometers, velocity units */ /* are kilometers per second, and acceleration units */ /* are kilometers per second per second. */ /* EPOCHS is an array containing epochs for all input */ /* mini-segments. Each epoch is expressed as seconds */ /* past J2000 TDB. The epochs have a one-to-one */ /* relationship with the packets in the input packet */ /* array. */ /* The epochs for a given mini-segment are stored */ /* contiguously in increasing order. The order of the */ /* sets of epochs for different mini-segments is the */ /* same as the order of their corresponding */ /* interpolation intervals. */ /* For each mini-segment, "padding" is allowed: the */ /* sequence of epochs for that mini-segment may start */ /* before the corresponding interpolation interval */ /* start time and end after the corresponding */ /* interpolation interval stop time. Padding is used */ /* to control behavior of interpolating polynomials */ /* near interpolation interval boundaries. */ /* Due to possible use of padding, the elements of */ /* EPOCHS, taken as a whole, may not be in increasing */ /* order. */ /* IVLBDS is an array of interpolation interval boundary */ /* times. This array is an ordered list of the */ /* interpolation interval start times, to which the */ /* the end time for the last interval is appended. */ /* The Ith interpolation interval is the time */ /* coverage interval of the Ith mini-segment (see the */ /* description of NPKTS above). */ /* For each mini-segment, the corresponding */ /* interpolation interval's start time is greater */ /* than or equal to the mini-segment's first epoch, */ /* and the interval's stop time is less than or equal */ /* to the mini-segment's last epoch. */ /* For each interpolation interval other than the */ /* last, the interval's coverage stop time coincides */ /* with the coverage start time of the next interval. */ /* There are no coverage gaps, and coverage overlap */ /* for adjacent intervals consists of a single epoch. */ /* IVLBDS has dimension NINTVL+1. */ /* SELLST is a logical flag indicating to the SPK type 19 */ /* segment reader SPKR19 how to select the */ /* interpolation interval when a request time */ /* coincides with a time boundary shared by two */ /* interpolation intervals. When SELLST ("select */ /* last") is .TRUE., the later interval is selected; */ /* otherwise the earlier interval is selected. */ /* $ Detailed_Output */ /* None. See $Particulars for a description of the effect of this */ /* routine. */ /* $ Parameters */ /* MAXDEG is the maximum allowed degree of the interpolating */ /* polynomial. */ /* See the INCLUDE file spk19.inc for the value of */ /* MAXDEG. */ /* $ Exceptions */ /* If any of the following exceptions occur, this routine will return */ /* without creating a new segment. */ /* 1) If FIRST is greater than LAST then the error */ /* SPICE(BADDESCRTIMES) will be signaled. */ /* 2) If FRAME is not a recognized name, the error */ /* SPICE(INVALIDREFFRAME) is signaled. */ /* 3) If the last non-blank character of SEGID occurs past index */ /* 40, the error SPICE(SEGIDTOOLONG) is signaled. */ /* 4) If SEGID contains any nonprintable characters, the error */ /* SPICE(NONPRINTABLECHARS) is signaled. */ /* 5) If NINTVL is not at least 1, the error SPICE(INVALIDCOUNT) */ /* is signaled. */ /* 6) If the elements of the array IVLBDS are not in strictly */ /* increasing order, the error SPICE(BOUNDSOUTOFORDER) will be */ /* signaled. */ /* 7) If the first interval start time IVLBDS(1) is greater than */ /* FIRST, or if the last interval end time IVLBDS(N+1) is less */ /* than LAST, the error SPICE(COVERAGEGAP) will be signaled. */ /* 8) If any packet count in the array NPKTS is not at least 2, the */ /* error SPICE(TOOFEWPACKETS) will be signaled. */ /* 9) If any subtype code in the array SUBTPS is not recognized, */ /* the error SPICE(INVALIDSUBTYPE) will be signaled. */ /* 10) If any interpolation degree in the array DEGRES */ /* is not at least 1 or is greater than MAXDEG, the */ /* error SPICE(INVALIDDEGREE) is signaled. */ /* 11) If the window size implied by any element of the array DEGRES */ /* is odd, the error SPICE(BADWINDOWSIZE) is signaled. */ /* 12) If the elements of the array EPOCHS corresponding to a given */ /* mini-segment are not in strictly increasing order, the error */ /* SPICE(TIMESOUTOFORDER) will be signaled. */ /* 13) If the first epoch of a mini-segment exceeds the start */ /* time of the associated interpolation interval, or if the */ /* last epoch of the mini-segment precedes the end time of the */ /* interpolation interval, the error SPICE(BOUNDSDISAGREE) */ /* is signaled. */ /* 14) Any error that occurs while writing the output segment will */ /* be diagnosed by routines in the call tree of this routine. */ /* $ Files */ /* A new type 19 SPK segment is written to the SPK file attached */ /* to HANDLE. */ /* $ Particulars */ /* This routine writes an SPK type 19 data segment to the open SPK */ /* file according to the format described in the type 19 section of */ /* the SPK Required Reading. The SPK file must have been opened with */ /* write access. */ /* $ Examples */ /* Suppose that you have states and are prepared to produce */ /* a segment of type 19 in an SPK file. */ /* The following code fragment could be used to add the new segment */ /* to a previously opened SPK file attached to HANDLE. The file must */ /* have been opened with write access. */ /* C */ /* C Create a segment identifier. */ /* C */ /* SEGID = 'MY_SAMPLE_SPK_TYPE_19_SEGMENT' */ /* C */ /* C Write the segment. */ /* C */ /* CALL SPKW19 ( HANDLE, BODY, CENTER, FRAME, */ /* . FIRST, LAST, SEGID, NINTVL, */ /* . NPKTS, SUBTPS, DEGRES, PACKTS, */ /* . EPOCHS, IVLBDS, SELLST ) */ /* $ Restrictions */ /* None. */ /* $ Literature_References */ /* None. */ /* $ Author_and_Institution */ /* N.J. Bachman (JPL) */ /* B.V. Semenov (JPL) */ /* $ Version */ /* - SPICELIB Version 1.0.0, 05-FEB-2014 (NJB) (BVS) */ /* -& */ /* $ Index_Entries */ /* write spk type_19 ephemeris data segment */ /* -& */ /* SPICELIB functions */ /* Local parameters */ /* Local variables */ /* Saved values */ /* Initial values */ /* Standard SPICE error handling. */ if (return_()) { return 0; } chkin_("SPKW19", (ftnlen)6); /* Start with a parameter compatibility check. */ if (FALSE_) { setmsg_("SPK type 19 record size may be as large as #, but SPKPVN re" "cord size is #.", (ftnlen)74); errint_("#", &c__198, (ftnlen)1); errint_("#", &c__198, (ftnlen)1); sigerr_("SPICE(BUG0)", (ftnlen)11); chkout_("SPKW19", (ftnlen)6); return 0; } /* Make sure the segment descriptor bounds are */ /* correctly ordered. */ if (*last < *first) { setmsg_("Segment start time is #; stop time is #; bounds must be in " "nondecreasing order.", (ftnlen)79); errdp_("#", first, (ftnlen)1); errdp_("#", last, (ftnlen)1); sigerr_("SPICE(BADDESCRTIMES)", (ftnlen)20); chkout_("SPKW19", (ftnlen)6); return 0; } /* Get the NAIF integer code for the reference frame. */ namfrm_(frame, &refcod, frame_len); if (refcod == 0) { setmsg_("The reference frame # is not supported.", (ftnlen)39); errch_("#", frame, (ftnlen)1, frame_len); sigerr_("SPICE(INVALIDREFFRAME)", (ftnlen)22); chkout_("SPKW19", (ftnlen)6); return 0; } /* Check to see if the segment identifier is too long. */ if (lastnb_(segid, segid_len) > 40) { setmsg_("Segment identifier contains more than 40 characters.", ( ftnlen)52); sigerr_("SPICE(SEGIDTOOLONG)", (ftnlen)19); chkout_("SPKW19", (ftnlen)6); return 0; } /* Now check that all the characters in the segment identifier */ /* can be printed. */ i__1 = lastnb_(segid, segid_len); for (i__ = 1; i__ <= i__1; ++i__) { chrcod = *(unsigned char *)&segid[i__ - 1]; if (chrcod < 32 || chrcod > 126) { setmsg_("The segment identifier contains nonprintable characters", (ftnlen)55); sigerr_("SPICE(NONPRINTABLECHARS)", (ftnlen)24); chkout_("SPKW19", (ftnlen)6); return 0; } } /* The mini-segment/interval count must be positive. */ if (*nintvl < 1) { setmsg_("Mini-segment/interval count was #; this count must be posit" "ive.", (ftnlen)63); errint_("#", nintvl, (ftnlen)1); sigerr_("SPICE(INVALIDCOUNT)", (ftnlen)19); chkout_("SPKW19", (ftnlen)6); return 0; } /* Make sure the interval bounds form a strictly */ /* increasing sequence. */ /* Note that there are NINTVL+1 bounds. */ i__1 = *nintvl; for (i__ = 1; i__ <= i__1; ++i__) { if (ivlbds[i__ - 1] >= ivlbds[i__]) { setmsg_("Interval bounds at indices # and # are # and # respecti" "vely. The difference is #. The bounds are required to be" " strictly increasing.", (ftnlen)132); errint_("#", &i__, (ftnlen)1); i__2 = i__ + 1; errint_("#", &i__2, (ftnlen)1); errdp_("#", &ivlbds[i__ - 1], (ftnlen)1); errdp_("#", &ivlbds[i__], (ftnlen)1); d__1 = ivlbds[i__] - ivlbds[i__ - 1]; errdp_("#", &d__1, (ftnlen)1); sigerr_("SPICE(BOUNDSOUTOFORDER)", (ftnlen)23); chkout_("SPKW19", (ftnlen)6); return 0; } } /* Make sure the time span of the descriptor doesn't extend */ /* beyond the span of the interval bounds. */ if (*first < ivlbds[0] || *last > ivlbds[*nintvl]) { setmsg_("First interval start time is #; segment start time is #; se" "gment stop time is #; last interval stop time is #. This seq" "uence of times is required to be non-decreasing: segment cov" "erage must be contained within the union of the interpolatio" "n intervals.", (ftnlen)251); errdp_("#", ivlbds, (ftnlen)1); errdp_("#", first, (ftnlen)1); errdp_("#", last, (ftnlen)1); errdp_("#", &ivlbds[*nintvl], (ftnlen)1); sigerr_("SPICE(COVERAGEGAP)", (ftnlen)18); chkout_("SPKW19", (ftnlen)6); return 0; } /* Check the input data before writing to the file. */ /* This order of operations entails some redundant */ /* calculations, but it allows for rapid error */ /* detection. */ /* Initialize the mini-segment packet array indices, */ /* and those of the mini-segment epoch array as well. */ pktbeg = 0; pktend = 0; bepix = 0; eepix = 0; i__1 = *nintvl; for (i__ = 1; i__ <= i__1; ++i__) { /* First, just make sure the packet count for the current */ /* mini-segment is at least two. This check reduces our chances */ /* of a subscript range violation. */ /* Check the number of packets. */ if (npkts[i__ - 1] < 2) { setmsg_("At least 2 packets are required for SPK type 19. Number" " of packets supplied was # in mini-segment at index #.", ( ftnlen)109); errint_("#", &npkts[i__ - 1], (ftnlen)1); errint_("#", &i__, (ftnlen)1); sigerr_("SPICE(TOOFEWPACKETS)", (ftnlen)20); chkout_("SPKW19", (ftnlen)6); return 0; } /* Set the packet size, which is a function of the subtype. Also */ /* set the window size. First check the subtype, which will be */ /* used as an array index. */ subtyp = subtps[i__ - 1]; if (subtyp < 0 || subtyp > 1) { setmsg_("Unexpected SPK type 19 subtype # found in mini-segment " "#.", (ftnlen)57); errint_("#", &subtyp, (ftnlen)1); errint_("#", &i__, (ftnlen)1); sigerr_("SPICE(INVALIDSUBTYPE)", (ftnlen)21); chkout_("SPKW19", (ftnlen)6); return 0; } pktsiz = pktszs[(i__2 = subtyp) < 2 && 0 <= i__2 ? i__2 : s_rnge( "pktszs", i__2, "spkw19_", (ftnlen)689)]; if (odd_(&subtyp)) { winsiz = degres[i__ - 1] + 1; } else { winsiz = (degres[i__ - 1] + 1) / 2; } /* Make sure that the degree of the interpolating polynomials is */ /* in range. */ if (degres[i__ - 1] < 1 || degres[i__ - 1] > 27) { setmsg_("The interpolating polynomials of mini-segment # have de" "gree #; the valid degree range is [1, #]", (ftnlen)95); errint_("#", &i__, (ftnlen)1); errint_("#", °res[i__ - 1], (ftnlen)1); errint_("#", &c__27, (ftnlen)1); sigerr_("SPICE(INVALIDDEGREE)", (ftnlen)20); chkout_("SPKW19", (ftnlen)6); return 0; } /* Make sure that the window size is even. */ if (odd_(&winsiz)) { setmsg_("The interpolating polynomials of mini-segment # have wi" "ndow size # and degree # for SPK type 19. The mini-segme" "nt subtype is #. The degree must be equivalent to 3 mod " "4 for subtype 0 (Hermite interpolation) and be odd for s" "ubtype 1 (Lagrange interpolation).", (ftnlen)257); errint_("#", &i__, (ftnlen)1); errint_("#", &winsiz, (ftnlen)1); errint_("#", °res[i__ - 1], (ftnlen)1); errint_("#", &subtps[i__ - 1], (ftnlen)1); sigerr_("SPICE(BADWINDOWSIZE)", (ftnlen)20); chkout_("SPKW19", (ftnlen)6); return 0; } /* Make sure the epochs of the Ith mini-segment form a */ /* strictly increasing sequence. */ /* To start out, determine the indices of the epoch sequence */ /* of the Ith mini-segment. We'll call the begin and end */ /* epoch indices BEPIX and EEPIX respectively. */ bepix = eepix + 1; eepix = bepix - 1 + npkts[i__ - 1]; i__2 = npkts[i__ - 1] - 1; for (j = 1; j <= i__2; ++j) { k = bepix + j - 1; if (epochs[k - 1] >= epochs[k]) { setmsg_("In mini-segment #, epoch # having index # in array " "EPOCHS and index # in the mini-segment is greater th" "an or equal to its successor #.", (ftnlen)134); errint_("#", &i__, (ftnlen)1); errdp_("#", &epochs[k - 1], (ftnlen)1); errint_("#", &k, (ftnlen)1); errint_("#", &j, (ftnlen)1); errdp_("#", &epochs[k], (ftnlen)1); sigerr_("SPICE(TIMESOUTOFORDER)", (ftnlen)22); chkout_("SPKW19", (ftnlen)6); return 0; } } /* Make sure that the span of the input epochs of the Ith */ /* mini-segment includes the Ith interpolation interval. */ if (epochs[bepix - 1] > ivlbds[i__ - 1]) { setmsg_("Interpolation interval # start time # precedes mini-seg" "ment's first epoch #.", (ftnlen)76); errint_("#", &i__, (ftnlen)1); errdp_("#", &ivlbds[i__ - 1], (ftnlen)1); errdp_("#", &epochs[bepix - 1], (ftnlen)1); sigerr_("SPICE(BOUNDSDISAGREE)", (ftnlen)21); chkout_("SPKW19", (ftnlen)6); return 0; } else if (epochs[eepix - 1] < ivlbds[i__]) { setmsg_("Interpolation interval # end time # exceeds mini-segmen" "t's last epoch #.", (ftnlen)72); errint_("#", &i__, (ftnlen)1); errdp_("#", &ivlbds[i__], (ftnlen)1); errdp_("#", &epochs[eepix - 1], (ftnlen)1); sigerr_("SPICE(BOUNDSDISAGREE)", (ftnlen)21); chkout_("SPKW19", (ftnlen)6); return 0; } } /* If we made it this far, we're ready to start writing the segment. */ /* The type 19 segment structure is eloquently described by this */ /* diagram from the SPK Required Reading: */ /* +--------------------------------+ */ /* | Interval 1 mini-segment | */ /* +--------------------------------+ */ /* . */ /* . */ /* . */ /* +--------------------------------+ */ /* | Interval N mini-segment | */ /* +--------------------------------+ */ /* | Interval 1 start time | */ /* +--------------------------------+ */ /* . */ /* . */ /* . */ /* +--------------------------------+ */ /* | Interval N start time | */ /* +--------------------------------+ */ /* | Interval N stop time | */ /* +--------------------------------+ */ /* | Interval start 100 | (First interval directory) */ /* +--------------------------------+ */ /* . */ /* . */ /* . */ /* +--------------------------------+ */ /* | Interval start (N/100)*100 | (Last interval directory) */ /* +--------------------------------+ */ /* | Interval 1 start pointer | */ /* +--------------------------------+ */ /* . */ /* . */ /* . */ /* +--------------------------------+ */ /* | Interval N start pointer | */ /* +--------------------------------+ */ /* | Interval N stop pointer + 1 | */ /* +--------------------------------+ */ /* | Boundary choice flag | */ /* +--------------------------------+ */ /* | Number of intervals | */ /* +--------------------------------+ */ /* SPK type 19 mini-segments have the following structure: */ /* +-----------------------+ */ /* | Packet 1 | */ /* +-----------------------+ */ /* . */ /* . */ /* . */ /* +-----------------------+ */ /* | Packet M | */ /* +-----------------------+ */ /* | Epoch 1 | */ /* +-----------------------+ */ /* . */ /* . */ /* . */ /* +-----------------------+ */ /* | Epoch M | */ /* +-----------------------+ */ /* | Epoch 100 | (First time tag directory) */ /* +-----------------------+ */ /* . */ /* . */ /* . */ /* +-----------------------+ */ /* | Epoch ((M-1)/100)*100 | (Last time tag directory) */ /* +-----------------------+ */ /* | Subtype code | */ /* +-----------------------+ */ /* | Window size | */ /* +-----------------------+ */ /* | Number of packets | */ /* +-----------------------+ */ /* Create the segment descriptor. We don't use SPKPDS because */ /* that routine doesn't allow creation of a singleton segment. */ ic[0] = *body; ic[1] = *center; ic[2] = refcod; ic[3] = 19; dc[0] = *first; dc[1] = *last; dafps_(&c__2, &c__6, dc, ic, descr); /* Begin a new segment. */ dafbna_(handle, descr, segid, segid_len); if (failed_()) { chkout_("SPKW19", (ftnlen)6); return 0; } /* Re-initialize the mini-segment packet array indices, */ /* and those of the mini-segment epoch array as well. */ pktbeg = 0; pktend = 0; bepix = 0; eepix = 0; /* Write data for each mini-segment to the file. */ i__1 = *nintvl; for (i__ = 1; i__ <= i__1; ++i__) { /* Set the packet size, which is a function of the subtype. */ subtyp = subtps[i__ - 1]; pktsiz = pktszs[(i__2 = subtyp) < 2 && 0 <= i__2 ? i__2 : s_rnge( "pktszs", i__2, "spkw19_", (ftnlen)931)]; if (odd_(&subtyp)) { winsiz = degres[i__ - 1] + 1; } else { winsiz = (degres[i__ - 1] + 1) / 2; } /* Now that we have the packet size, we can compute */ /* mini-segment packet index range. We'll let PKTDSZ */ /* be the total count of packet data entries for this */ /* mini-segment. */ pktdsz = npkts[i__ - 1] * pktsiz; pktbeg = pktend + 1; pktend = pktbeg - 1 + pktdsz; /* At this point, we're read to start writing the */ /* current mini-segment to the file. Start with the */ /* packet data. */ dafada_(&packts[pktbeg - 1], &pktdsz); /* Write the epochs for this mini-segment. */ bepix = eepix + 1; eepix = bepix - 1 + npkts[i__ - 1]; dafada_(&epochs[bepix - 1], &npkts[i__ - 1]); /* Compute the number of epoch directories for the */ /* current mini-segment. */ ndir = (npkts[i__ - 1] - 1) / 100; /* Write the epoch directories to the segment. */ i__2 = ndir; for (j = 1; j <= i__2; ++j) { k = bepix - 1 + j * 100; dafada_(&epochs[k - 1], &c__1); } /* Write the mini-segment's subtype, window size, and packet */ /* count to the segment. */ d__1 = (doublereal) subtps[i__ - 1]; dafada_(&d__1, &c__1); d__1 = (doublereal) winsiz; dafada_(&d__1, &c__1); d__1 = (doublereal) npkts[i__ - 1]; dafada_(&d__1, &c__1); if (failed_()) { chkout_("SPKW19", (ftnlen)6); return 0; } } /* We've finished writing the mini-segments. */ /* Next write the interpolation interval bounds. */ i__1 = *nintvl + 1; dafada_(ivlbds, &i__1); /* Create and write directories for the interval */ /* bounds. */ /* The directory count is the interval bound count */ /* (N+1), minus 1, divided by the directory size. */ ndir = *nintvl / 100; i__1 = ndir; for (i__ = 1; i__ <= i__1; ++i__) { dafada_(&ivlbds[i__ * 100 - 1], &c__1); } /* Now we compute and write the start/stop pointers */ /* for each mini-segment. */ /* The pointers are relative to the DAF address */ /* preceding the segment. For example, a pointer */ /* to the first DAF address in the segment has */ /* value 1. */ segend = 0; i__1 = *nintvl; for (i__ = 1; i__ <= i__1; ++i__) { /* Set the packet size, which is a function of the subtype. */ pktsiz = pktszs[(i__2 = subtps[i__ - 1]) < 2 && 0 <= i__2 ? i__2 : s_rnge("pktszs", i__2, "spkw19_", (ftnlen)1033)]; /* In order to compute the end pointer of the current */ /* mini-segment, we must compute the size, in terms */ /* of DAF addresses, of this mini-segment. The formula */ /* for the size is */ /* size = n_packets * packet_size */ /* + n_epochs */ /* + n_epoch_directories */ /* + 3 */ /* = n_packets * ( packet_size + 1 ) */ /* + ( n_packets - 1 ) / DIRSIZ */ /* + 3 */ minisz = npkts[i__ - 1] * (pktsiz + 1) + (npkts[i__ - 1] - 1) / 100 + 3; segbeg = segend + 1; segend = segbeg + minisz - 1; /* Write the mini-segment begin pointer. */ /* After the loop terminates, the final end pointer, incremented */ /* by 1, will be written. */ d__1 = (doublereal) segbeg; dafada_(&d__1, &c__1); } /* Write the last mini-segment end pointer, incremented by one. */ /* SEGEND was computed on the last iteration of the above loop. */ d__1 = (doublereal) (segend + 1); dafada_(&d__1, &c__1); /* Write out the interval selection flag. The input */ /* boolean value is represented by a numeric constant. */ if (*sellst) { isel = 1; } else { isel = -1; } d__1 = (doublereal) isel; dafada_(&d__1, &c__1); /* Write the mini-segment/interpolation interval count. */ d__1 = (doublereal) (*nintvl); dafada_(&d__1, &c__1); /* End the segment. */ dafena_(); chkout_("SPKW19", (ftnlen)6); return 0; } /* spkw19_ */