/* $Procedure INVORT ( Invert nearly orthogonal matrices ) */ /* Subroutine */ int invort_(doublereal *m, doublereal *mit) { /* Initialized data */ static logical first = TRUE_; /* System generated locals */ integer i__1, i__2; /* Builtin functions */ integer s_rnge(char *, integer, char *, integer); /* Local variables */ doublereal temp[9] /* was [3][3] */; integer i__; doublereal scale; extern /* Subroutine */ int chkin_(char *, ftnlen); static doublereal bound; extern doublereal dpmax_(void); extern /* Subroutine */ int errdp_(char *, doublereal *, ftnlen), xpose_( doublereal *, doublereal *), unorm_(doublereal *, doublereal *, doublereal *); doublereal length; extern /* Subroutine */ int sigerr_(char *, ftnlen), chkout_(char *, ftnlen), vsclip_(doublereal *, doublereal *), setmsg_(char *, ftnlen), errint_(char *, integer *, ftnlen); /* $ Abstract */ /* Construct the inverse of a 3x3 matrix with orthogonal columns */ /* and non-zero norms using a numerical stable algorithm. */ /* $ 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 */ /* MATRIX */ /* $ Declarations */ /* $ Brief_I/O */ /* Variable I/O Description */ /* -------- --- -------------------------------------------------- */ /* M I A 3x3 matrix. */ /* MIT I M after transposition and scaling of rows. */ /* $ Detailed_Input */ /* M is a 3x3 matrix. */ /* $ Detailed_Output */ /* MIT is the matrix obtained by transposing M and dividing */ /* the rows by squares of their norms. */ /* $ Parameters */ /* None. */ /* $ Exceptions */ /* 1) If any of the columns of M have zero length, the error */ /* SPICE(ZEROLENGTHCOLUMN) will be signaled. */ /* 2) If any column is too short to allow computation of the */ /* reciprocal of its length without causing a floating */ /* point overflow, the error SPICE(COLUMNTOOSMALL) will */ /* be signaled. */ /* $ Files */ /* None. */ /* $ Particulars */ /* Suppose that M is the matrix */ /* - - */ /* | A*u B*v C*w | */ /* | 1 1 1 | */ /* | | */ /* | A*u B*v C*w | */ /* | 2 2 2 | */ /* | | */ /* | A*u B*v C*w | */ /* | 3 3 3 | */ /* - - */ /* where the vectors (u , u , u ), (v , v , v ), and (w , w , w ) */ /* 1 2 3 1 2 3 1 2 3 */ /* are unit vectors. This routine produces the matrix: */ /* - - */ /* | a*u a*u a*u | */ /* | 1 2 3 | */ /* | | */ /* | b*v b*v b*v | */ /* | 1 2 3 | */ /* | | */ /* | c*w c*w c*w | */ /* | 1 2 3 | */ /* - - */ /* where a = 1/A, b = 1/B, and c = 1/C. */ /* $ Examples */ /* Suppose that you have a matrix M whose columns are orthogonal */ /* and have non-zero norm (but not necessarily norm 1). Then the */ /* routine INVORT can be used to construct the inverse of M: */ /* CALL INVORT ( M, INVERS ) */ /* This method is numerically more robust than calling the */ /* routine INVERT. */ /* $ Restrictions */ /* None. */ /* $ Literature_References */ /* None. */ /* $ Author_and_Institution */ /* N.J. Bachman (JPL) */ /* W.L. Taber (JPL) */ /* $ Version */ /* - SPICELIB Version 1.1.1, 14-NOV-2013 (EDW) */ /* Edit to Abstract. Eliminated unneeded Revisions section. */ /* - SPICELIB Version 1.1.0, 02-SEP-2005 (NJB) */ /* Updated to remove non-standard use of duplicate arguments */ /* in VSCL call. */ /* - SPICELIB Version 1.0.0, 02-JAN-2002 (WLT) */ /* -& */ /* $ Index_Entries */ /* Transpose a matrix and invert the lengths of the rows */ /* Invert a pseudo orthogonal matrix */ /* -& */ /* SPICELIB functions */ /* Local Variables */ /* Saved variables */ /* Initial values */ /* Use discovery check-in. */ /* The first time through, get a copy of DPMAX. */ if (first) { bound = dpmax_(); first = FALSE_; } /* For each column, construct a scaled copy. However, make sure */ /* everything is do-able before trying something. */ for (i__ = 1; i__ <= 3; ++i__) { unorm_(&m[(i__1 = i__ * 3 - 3) < 9 && 0 <= i__1 ? i__1 : s_rnge("m", i__1, "invort_", (ftnlen)208)], &temp[(i__2 = i__ * 3 - 3) < 9 && 0 <= i__2 ? i__2 : s_rnge("temp", i__2, "invort_", ( ftnlen)208)], &length); if (length == 0.) { chkin_("INVORT", (ftnlen)6); setmsg_("Column # of the input matrix has a norm of zero. ", ( ftnlen)49); errint_("#", &i__, (ftnlen)1); sigerr_("SPICE(ZEROLENGTHCOLUMN)", (ftnlen)23); chkout_("INVORT", (ftnlen)6); return 0; } /* Make sure we can actually rescale the rows. */ if (length < 1.) { if (length * bound < 1.) { chkin_("INVORT", (ftnlen)6); setmsg_("The length of column # is #. This number cannot be " "inverted. For this reason, the scaled transpose of " "the input matrix cannot be formed. ", (ftnlen)138); errint_("#", &i__, (ftnlen)1); errdp_("#", &length, (ftnlen)1); sigerr_("SPICE(COLUMNTOOSMALL)", (ftnlen)21); chkout_("INVORT", (ftnlen)6); return 0; } } scale = 1. / length; vsclip_(&scale, &temp[(i__1 = i__ * 3 - 3) < 9 && 0 <= i__1 ? i__1 : s_rnge("temp", i__1, "invort_", (ftnlen)246)]); } /* If we make it this far, we just need to transpose TEMP into MIT. */ xpose_(temp, mit); return 0; } /* invort_ */
/* $Procedure ZZREFCH1 (Reference frame Change) */ /* Subroutine */ int zzrefch1_(integer *frame1, integer *frame2, doublereal * et, doublereal *rotate) { /* System generated locals */ integer i__1, i__2, i__3, i__4, i__5, i__6, i__7; /* Builtin functions */ integer s_rnge(char *, integer, char *, integer); /* Local variables */ integer node; logical done; integer cent, this__; extern /* Subroutine */ int zzrotgt1_(integer *, doublereal *, doublereal *, integer *, logical *), zznofcon_(doublereal *, integer *, integer *, integer *, integer *, char *, ftnlen); integer i__, j, frame[10]; extern /* Subroutine */ int chkin_(char *, ftnlen), ident_(doublereal *); integer class__; logical found; integer relto; extern /* Subroutine */ int xpose_(doublereal *, doublereal *), zzrxr_( doublereal *, integer *, doublereal *); extern logical failed_(void); integer cmnode; extern integer isrchi_(integer *, integer *, integer *); integer clssid; extern /* Subroutine */ int frinfo_(integer *, integer *, integer *, integer *, logical *); logical gotone; char errmsg[1840]; extern /* Subroutine */ int chkout_(char *, ftnlen), setmsg_(char *, ftnlen), errint_(char *, integer *, ftnlen), sigerr_(char *, ftnlen); extern logical return_(void); doublereal tmprot[9] /* was [3][3] */; integer inc, get; doublereal rot[126] /* was [3][3][14] */; integer put; doublereal rot2[18] /* was [3][3][2] */; /* $ Abstract */ /* Return the transformation matrix from one */ /* frame to another. */ /* $ Disclaimer */ /* THIS SOFTWARE AND ANY RELATED MATERIALS WERE CREATED BY THE */ /* CALIFORNIA INSTITUTE OF TECHNOLOGY (CALTECH) UNDER A U.S. */ /* GOVERNMENT CONTRACT WITH THE NATIONAL AERONAUTICS AND SPACE */ /* ADMINISTRATION (NASA). THE SOFTWARE IS TECHNOLOGY AND SOFTWARE */ /* PUBLICLY AVAILABLE UNDER U.S. EXPORT LAWS AND IS PROVIDED "AS-IS" */ /* TO THE RECIPIENT WITHOUT WARRANTY OF ANY KIND, INCLUDING ANY */ /* WARRANTIES OF PERFORMANCE OR MERCHANTABILITY OR FITNESS FOR A */ /* PARTICULAR USE OR PURPOSE (AS SET FORTH IN UNITED STATES UCC */ /* SECTIONS 2312-2313) OR FOR ANY PURPOSE WHATSOEVER, FOR THE */ /* SOFTWARE AND RELATED MATERIALS, HOWEVER USED. */ /* IN NO EVENT SHALL CALTECH, ITS JET PROPULSION LABORATORY, OR NASA */ /* BE LIABLE FOR ANY DAMAGES AND/OR COSTS, INCLUDING, BUT NOT */ /* LIMITED TO, INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, */ /* INCLUDING ECONOMIC DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS, */ /* REGARDLESS OF WHETHER CALTECH, JPL, OR NASA BE ADVISED, HAVE */ /* REASON TO KNOW, OR, IN FACT, SHALL KNOW OF THE POSSIBILITY. */ /* RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF */ /* THE SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY */ /* CALTECH AND NASA FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE */ /* ACTIONS OF RECIPIENT IN THE USE OF THE SOFTWARE. */ /* $ Required_Reading */ /* None. */ /* $ Keywords */ /* FRAMES */ /* $ Declarations */ /* $ 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. */ /* Include File: SPICELIB Error Handling Parameters */ /* errhnd.inc Version 2 18-JUN-1997 (WLT) */ /* The size of the long error message was */ /* reduced from 25*80 to 23*80 so that it */ /* will be accepted by the Microsoft Power Station */ /* FORTRAN compiler which has an upper bound */ /* of 1900 for the length of a character string. */ /* errhnd.inc Version 1 29-JUL-1997 (NJB) */ /* Maximum length of the long error message: */ /* Maximum length of the short error message: */ /* End Include File: SPICELIB Error Handling Parameters */ /* $ Abstract */ /* The parameters below form an enumerated list of the recognized */ /* frame types. They are: INERTL, PCK, CK, TK, DYN. The meanings */ /* are outlined below. */ /* $ Disclaimer */ /* THIS SOFTWARE AND ANY RELATED MATERIALS WERE CREATED BY THE */ /* CALIFORNIA INSTITUTE OF TECHNOLOGY (CALTECH) UNDER A U.S. */ /* GOVERNMENT CONTRACT WITH THE NATIONAL AERONAUTICS AND SPACE */ /* ADMINISTRATION (NASA). THE SOFTWARE IS TECHNOLOGY AND SOFTWARE */ /* PUBLICLY AVAILABLE UNDER U.S. EXPORT LAWS AND IS PROVIDED "AS-IS" */ /* TO THE RECIPIENT WITHOUT WARRANTY OF ANY KIND, INCLUDING ANY */ /* WARRANTIES OF PERFORMANCE OR MERCHANTABILITY OR FITNESS FOR A */ /* PARTICULAR USE OR PURPOSE (AS SET FORTH IN UNITED STATES UCC */ /* SECTIONS 2312-2313) OR FOR ANY PURPOSE WHATSOEVER, FOR THE */ /* SOFTWARE AND RELATED MATERIALS, HOWEVER USED. */ /* IN NO EVENT SHALL CALTECH, ITS JET PROPULSION LABORATORY, OR NASA */ /* BE LIABLE FOR ANY DAMAGES AND/OR COSTS, INCLUDING, BUT NOT */ /* LIMITED TO, INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, */ /* INCLUDING ECONOMIC DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS, */ /* REGARDLESS OF WHETHER CALTECH, JPL, OR NASA BE ADVISED, HAVE */ /* REASON TO KNOW, OR, IN FACT, SHALL KNOW OF THE POSSIBILITY. */ /* RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF */ /* THE SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY */ /* CALTECH AND NASA FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE */ /* ACTIONS OF RECIPIENT IN THE USE OF THE SOFTWARE. */ /* $ Parameters */ /* INERTL an inertial frame that is listed in the routine */ /* CHGIRF and that requires no external file to */ /* compute the transformation from or to any other */ /* inertial frame. */ /* PCK is a frame that is specified relative to some */ /* INERTL frame and that has an IAU model that */ /* may be retrieved from the PCK system via a call */ /* to the routine TISBOD. */ /* CK is a frame defined by a C-kernel. */ /* TK is a "text kernel" frame. These frames are offset */ /* from their associated "relative" frames by a */ /* constant rotation. */ /* DYN is a "dynamic" frame. These currently are */ /* parameterized, built-in frames where the full frame */ /* definition depends on parameters supplied via a */ /* frame kernel. */ /* $ Author_and_Institution */ /* N.J. Bachman (JPL) */ /* W.L. Taber (JPL) */ /* $ Literature_References */ /* None. */ /* $ Version */ /* - SPICELIB Version 3.0.0, 28-MAY-2004 (NJB) */ /* The parameter DYN was added to support the dynamic frame class. */ /* - SPICELIB Version 2.0.0, 12-DEC-1996 (WLT) */ /* Various unused frames types were removed and the */ /* frame time TK was added. */ /* - SPICELIB Version 1.0.0, 10-DEC-1995 (WLT) */ /* -& */ /* $ Brief_I/O */ /* VARIABLE I/O DESCRIPTION */ /* -------- --- -------------------------------------------------- */ /* FRAME1 I the frame id-code for some reference frame */ /* FRAME2 I the frame id-code for some reference frame */ /* ET I an epoch in TDB seconds past J2000. */ /* ROTATE O a rotation matrix */ /* $ Detailed_Input */ /* FRAME1 is the frame id-code in which some positions */ /* are known. */ /* FRAME2 is the frame id-code for some frame in which you */ /* would like to represent positions. */ /* ET is the epoch at which to compute the transformation */ /* matrix. This epoch should be in TDB seconds past */ /* the ephemeris epoch of J2000. */ /* $ Detailed_Output */ /* ROTATE is a 3 x 3 rotaion matrix that can be used to */ /* transform positions relative to the frame */ /* correspsonding to frame FRAME2 to positions relative */ /* to the frame FRAME2. More explicitely, if POS is */ /* the position of some object relative to the */ /* reference frame of FRAME1 then POS2 is the position */ /* of the same object relative to FRAME2 where POS2 is */ /* computed via the subroutine call below */ /* CALL MXV ( ROTATE, POS, POS2 ) */ /* $ Parameters */ /* None. */ /* $ Exceptions */ /* 1) If either of the reference frames is unrecognized, the error */ /* SPICE(UNKNOWNFRAME) will be signalled. */ /* 2) If the auxillary information needed to compute a non-inertial */ /* frame is not available an error will be diagnosed and signalled */ /* by a routine in the call tree of this routine. */ /* $ Files */ /* None. */ /* $ Particulars */ /* This routine allows you to compute the rotation matrix */ /* between two reference frames. */ /* $ Examples */ /* Suppose that you have a position POS1 at epoch ET */ /* relative to FRAME1 and wish to determine its representation */ /* POS2 relative to FRAME2. The following subroutine calls */ /* would suffice to make this rotation. */ /* CALL REFCHG ( FRAME1, FRAME2, ET, ROTATE ) */ /* CALL MXV ( ROTATE, POS1, POS2 ) */ /* $ Restrictions */ /* None. */ /* $ Literature_References */ /* None. */ /* $ Author_and_Institution */ /* W.L. Taber (JPL) */ /* $ Version */ /* - SPICELIB Version 2.0.0, 14-DEC-2008 (NJB) */ /* Upgraded long error message associated with frame */ /* connection failure. */ /* - SPICELIB Version 1.2.0, 26-APR-2004 (NJB) */ /* Another typo was corrected in the long error message, and */ /* in a comment. */ /* - SPICELIB Version 1.1.0, 23-MAY-2000 (WLT) */ /* A typo was corrected in the long error message. */ /* - SPICELIB Version 1.0.0, 9-JUL-1998 (WLT) */ /* -& */ /* $ Index_Entries */ /* Rotate positions from one frame to another */ /* -& */ /* SPICE functions */ /* Local Paramters */ /* The root of all reference frames is J2000 (Frame ID = 1). */ /* Local Variables */ /* ROT contains the rotations from FRAME1 to FRAME2 */ /* ROT(1...3,1...3,I) has the rotation from FRAME(I) */ /* to FRAME(I+1). We make extra room in ROT because we */ /* plan to add rotations beyond the obvious chain from */ /* FRAME1 to a root node. */ /* ROT2 is used to store intermediate rotation from */ /* FRAME2 to some node in the chain from FRAME1 to PCK or */ /* INERTL frames. */ /* FRAME contains the frames we transform from in going from */ /* FRAME1 to FRAME2. FRAME(1) = FRAME1 by construction. */ /* NODE counts the number of rotations needed to go */ /* from FRAME1 to FRAME2. */ /* Standard SPICE error handling. */ if (return_()) { return 0; } chkin_("ZZREFCH1", (ftnlen)8); /* Do the obvious thing first. If FRAME1 and FRAME2 are the */ /* same then we simply return the identity matrix. */ if (*frame1 == *frame2) { ident_(rotate); chkout_("ZZREFCH1", (ftnlen)8); return 0; } /* Now perform the obvious check to make sure that both */ /* frames are recognized. */ frinfo_(frame1, ¢, &class__, &clssid, &found); if (! found) { setmsg_("The number # is not a recognized id-code for a reference fr" "ame. ", (ftnlen)64); errint_("#", frame1, (ftnlen)1); sigerr_("SPICE(UNKNOWNFRAME)", (ftnlen)19); chkout_("ZZREFCH1", (ftnlen)8); return 0; } frinfo_(frame2, ¢, &class__, &clssid, &found); if (! found) { setmsg_("The number # is not a recognized id-code for a reference fr" "ame. ", (ftnlen)64); errint_("#", frame2, (ftnlen)1); sigerr_("SPICE(UNKNOWNFRAME)", (ftnlen)19); chkout_("ZZREFCH1", (ftnlen)8); return 0; } node = 1; frame[(i__1 = node - 1) < 10 && 0 <= i__1 ? i__1 : s_rnge("frame", i__1, "zzrefch1_", (ftnlen)287)] = *frame1; found = TRUE_; /* Follow the chain of rotations until we run into */ /* one that rotates to J2000 (frame id = 1) or we hit FRAME2. */ while(frame[(i__1 = node - 1) < 10 && 0 <= i__1 ? i__1 : s_rnge("frame", i__1, "zzrefch1_", (ftnlen)293)] != 1 && node < 10 && frame[(i__2 = node - 1) < 10 && 0 <= i__2 ? i__2 : s_rnge("frame", i__2, "zzrefch1_", (ftnlen)293)] != *frame2 && found) { /* Find out what rotation is available for this */ /* frame. */ zzrotgt1_(&frame[(i__1 = node - 1) < 10 && 0 <= i__1 ? i__1 : s_rnge( "frame", i__1, "zzrefch1_", (ftnlen)301)], et, &rot[(i__2 = ( node * 3 + 1) * 3 - 12) < 126 && 0 <= i__2 ? i__2 : s_rnge( "rot", i__2, "zzrefch1_", (ftnlen)301)], &frame[(i__3 = node) < 10 && 0 <= i__3 ? i__3 : s_rnge("frame", i__3, "zzrefch1_", (ftnlen)301)], &found); if (found) { /* We found a rotation matrix. ROT(1,1,NODE) */ /* now contains the rotation from FRAME(NODE) */ /* to FRAME(NODE+1). We need to look up the information */ /* for the next NODE. */ ++node; } } done = frame[(i__1 = node - 1) < 10 && 0 <= i__1 ? i__1 : s_rnge("frame", i__1, "zzrefch1_", (ftnlen)317)] == 1 || frame[(i__2 = node - 1) < 10 && 0 <= i__2 ? i__2 : s_rnge("frame", i__2, "zzrefch1_", ( ftnlen)317)] == *frame2 || ! found; while(! done) { /* The only way to get to this point is to have run out of */ /* room in the array of reference frame rotation */ /* buffers. We will now build the rotation from */ /* the previous NODE to whatever the next node in the */ /* chain is. We'll do this until we get to one of the */ /* root classes or we run into FRAME2. */ zzrotgt1_(&frame[(i__1 = node - 1) < 10 && 0 <= i__1 ? i__1 : s_rnge( "frame", i__1, "zzrefch1_", (ftnlen)331)], et, &rot[(i__2 = ( node * 3 + 1) * 3 - 12) < 126 && 0 <= i__2 ? i__2 : s_rnge( "rot", i__2, "zzrefch1_", (ftnlen)331)], &relto, &found); if (found) { /* Recall that ROT(1,1,NODE-1) contains the rotation */ /* from FRAME(NODE-1) to FRAME(NODE). We are going to replace */ /* FRAME(NODE) with the frame indicated by RELTO. This means */ /* that ROT(1,1,NODE-1) should be replaced with the */ /* rotation from FRAME(NODE) to RELTO. */ frame[(i__1 = node - 1) < 10 && 0 <= i__1 ? i__1 : s_rnge("frame", i__1, "zzrefch1_", (ftnlen)342)] = relto; zzrxr_(&rot[(i__1 = ((node - 1) * 3 + 1) * 3 - 12) < 126 && 0 <= i__1 ? i__1 : s_rnge("rot", i__1, "zzrefch1_", (ftnlen) 343)], &c__2, tmprot); for (i__ = 1; i__ <= 3; ++i__) { for (j = 1; j <= 3; ++j) { rot[(i__1 = i__ + (j + (node - 1) * 3) * 3 - 13) < 126 && 0 <= i__1 ? i__1 : s_rnge("rot", i__1, "zzrefch1_" , (ftnlen)347)] = tmprot[(i__2 = i__ + j * 3 - 4) < 9 && 0 <= i__2 ? i__2 : s_rnge("tmprot", i__2, "zzrefch1_", (ftnlen)347)]; } } } /* We are done if the class of the last frame is J2000 */ /* or if the last frame is FRAME2 or if we simply couldn't get */ /* another rotation. */ done = frame[(i__1 = node - 1) < 10 && 0 <= i__1 ? i__1 : s_rnge( "frame", i__1, "zzrefch1_", (ftnlen)357)] == 1 || frame[(i__2 = node - 1) < 10 && 0 <= i__2 ? i__2 : s_rnge("frame", i__2, "zzrefch1_", (ftnlen)357)] == *frame2 || ! found; } /* Right now we have the following situation. We have in hand */ /* a collection of rotations between frames. (Assuming */ /* that is that NODE .GT. 1. If NODE .EQ. 1 then we have */ /* no rotations computed yet. */ /* ROT(1...3, 1...3, 1 ) rotates FRAME1 to FRAME(2) */ /* ROT(1...3, 1...3, 2 ) rotates FRAME(2) to FRAME(3) */ /* ROT(1...3, 1...3, 3 ) rotates FRAME(3) to FRAME(4) */ /* . */ /* . */ /* . */ /* ROT(1...3, 1...3, NODE-1 ) rotates FRAME(NODE-1) */ /* to FRAME(NODE) */ /* One of the following situations is true. */ /* 1) FRAME(NODE) is the root of all frames, J2000. */ /* 2) FRAME(NODE) is the same as FRAME2 */ /* 3) There is no rotation from FRAME(NODE) to another */ /* more fundamental frame. The chain of rotations */ /* from FRAME1 stops at FRAME(NODE). This means that the */ /* "frame atlas" is incomplete because we can't get to the */ /* root frame. */ /* We now have to do essentially the same thing for FRAME2. */ if (frame[(i__1 = node - 1) < 10 && 0 <= i__1 ? i__1 : s_rnge("frame", i__1, "zzrefch1_", (ftnlen)395)] == *frame2) { /* We can handle this one immediately with the private routine */ /* ZZRXR which multiplies a series of matrices. */ i__1 = node - 1; zzrxr_(rot, &i__1, rotate); chkout_("ZZREFCH1", (ftnlen)8); return 0; } /* We didn't luck out above. So we follow the chain of */ /* rotation for FRAME2. Note that at the moment the */ /* chain of rotations from FRAME2 to other frames */ /* does not share a node in the chain for FRAME1. */ /* ( GOTONE = .FALSE. ) . */ this__ = *frame2; gotone = FALSE_; /* First see if there is any chain to follow. */ done = this__ == 1; /* Set up the matrices ROT2(,,1) and ROT(,,2) and set up */ /* PUT and GET pointers so that we know where to GET the partial */ /* rotation from and where to PUT partial results. */ if (! done) { put = 1; get = 1; inc = 1; } /* Follow the chain of rotations until we run into */ /* one that rotates to the root frame or we land in the */ /* chain of nodes for FRAME1. */ /* Note that this time we will simply keep track of the full */ /* rotation from FRAME2 to the last node. */ while(! done) { /* Find out what rotation is available for this */ /* frame. */ if (this__ == *frame2) { /* This is the first pass, just put the rotation */ /* directly into ROT2(,,PUT). */ zzrotgt1_(&this__, et, &rot2[(i__1 = (put * 3 + 1) * 3 - 12) < 18 && 0 <= i__1 ? i__1 : s_rnge("rot2", i__1, "zzrefch1_", ( ftnlen)452)], &relto, &found); if (found) { this__ = relto; get = put; put += inc; inc = -inc; cmnode = isrchi_(&this__, &node, frame); gotone = cmnode > 0; } } else { /* Fetch the rotation into a temporary spot TMPROT */ zzrotgt1_(&this__, et, tmprot, &relto, &found); if (found) { /* Next multiply TMPROT on the right by the last partial */ /* product (in ROT2(,,GET) ). We do this in line. */ for (i__ = 1; i__ <= 3; ++i__) { for (j = 1; j <= 3; ++j) { rot2[(i__1 = i__ + (j + put * 3) * 3 - 13) < 18 && 0 <= i__1 ? i__1 : s_rnge("rot2", i__1, "zzref" "ch1_", (ftnlen)478)] = tmprot[(i__2 = i__ - 1) < 9 && 0 <= i__2 ? i__2 : s_rnge("tmprot", i__2, "zzrefch1_", (ftnlen)478)] * rot2[(i__3 = (j + get * 3) * 3 - 12) < 18 && 0 <= i__3 ? i__3 : s_rnge("rot2", i__3, "zzrefch1_", ( ftnlen)478)] + tmprot[(i__4 = i__ + 2) < 9 && 0 <= i__4 ? i__4 : s_rnge("tmprot", i__4, "zzrefch1_", (ftnlen)478)] * rot2[(i__5 = (j + get * 3) * 3 - 11) < 18 && 0 <= i__5 ? i__5 : s_rnge("rot2", i__5, "zzrefch1_", (ftnlen) 478)] + tmprot[(i__6 = i__ + 5) < 9 && 0 <= i__6 ? i__6 : s_rnge("tmprot", i__6, "zzrefc" "h1_", (ftnlen)478)] * rot2[(i__7 = (j + get * 3) * 3 - 10) < 18 && 0 <= i__7 ? i__7 : s_rnge("rot2", i__7, "zzrefch1_", (ftnlen)478) ]; } } /* Adjust GET and PUT so that GET points to the slots */ /* where we just stored the result of our multiply and */ /* so that PUT points to the next available storage */ /* locations. */ get = put; put += inc; inc = -inc; this__ = relto; cmnode = isrchi_(&this__, &node, frame); gotone = cmnode > 0; } } /* See if we have a common node and determine whether or not */ /* we are done with this loop. */ done = this__ == 1 || gotone || ! found; } /* There are two possible scenarios. Either the chain of */ /* rotations from FRAME2 ran into a node in the chain for */ /* FRAME1 or it didn't. (The common node might very well be */ /* the root node.) If we didn't run into a common one, then */ /* the two chains don't intersect and there is no way to */ /* get from FRAME1 to FRAME2. */ if (! gotone) { zznofcon_(et, frame1, &frame[(i__1 = node - 1) < 10 && 0 <= i__1 ? i__1 : s_rnge("frame", i__1, "zzrefch1_", (ftnlen)525)], frame2, &this__, errmsg, (ftnlen)1840); if (failed_()) { /* We were unable to create the error message. This */ /* unfortunate situation could arise if a frame kernel */ /* is corrupted. */ chkout_("ZZREFCH1", (ftnlen)8); return 0; } /* The normal case: signal an error with a descriptive long */ /* error message. */ setmsg_(errmsg, (ftnlen)1840); sigerr_("SPICE(NOFRAMECONNECT)", (ftnlen)21); chkout_("ZZREFCH1", (ftnlen)8); return 0; } /* Recall that we have the following. */ /* ROT(1...3, 1...3, 1 ) rotates FRAME(1) to FRAME(2) */ /* ROT(1...3, 1...3, 2 ) rotates FRAME(2) to FRAME(3) */ /* ROT(1...3, 1...3, 3 ) rotates FRAME(3) to FRAME(4) */ /* ROT(1...3, 1...3, CMNODE-1) rotates FRAME(CMNODE-1) */ /* to FRAME(CMNODE) */ /* and that ROT2(1,1,GET) rotates from FRAME2 to CMNODE. */ /* Hence the inverse of ROT2(1,1,GET) rotates from CMNODE */ /* to FRAME2. */ /* If we compute the inverse of ROT2 and store it in */ /* the next available slot of ROT (.i.e. ROT(1,1,CMNODE) */ /* we can simply apply our custom routine that multiplies a */ /* sequence of rotation matrices together to get the */ /* result from FRAME1 to FRAME2. */ xpose_(&rot2[(i__1 = (get * 3 + 1) * 3 - 12) < 18 && 0 <= i__1 ? i__1 : s_rnge("rot2", i__1, "zzrefch1_", (ftnlen)568)], &rot[(i__2 = ( cmnode * 3 + 1) * 3 - 12) < 126 && 0 <= i__2 ? i__2 : s_rnge( "rot", i__2, "zzrefch1_", (ftnlen)568)]); zzrxr_(rot, &cmnode, rotate); chkout_("ZZREFCH1", (ftnlen)8); return 0; } /* zzrefch1_ */
/* $Procedure TWOVEC ( Two vectors defining an orthonormal frame ) */ /* Subroutine */ int twovec_(doublereal *axdef, integer *indexa, doublereal * plndef, integer *indexp, doublereal *mout) { /* Initialized data */ static integer seqnce[5] = { 1,2,3,1,2 }; /* System generated locals */ integer i__1, i__2, i__3; /* Builtin functions */ integer s_rnge(char *, integer, char *, integer); /* Local variables */ extern /* Subroutine */ int vhat_(doublereal *, doublereal *), chkin_( char *, ftnlen), moved_(doublereal *, integer *, doublereal *); doublereal mtemp[9] /* was [3][3] */; integer i1, i2, i3; extern /* Subroutine */ int xpose_(doublereal *, doublereal *), ucrss_( doublereal *, doublereal *, doublereal *), sigerr_(char *, ftnlen) , chkout_(char *, ftnlen), setmsg_(char *, ftnlen), errint_(char * , integer *, ftnlen); extern logical return_(void); /* $ Abstract */ /* Find the transformation to the right-handed frame having a */ /* given vector as a specified axis and having a second given */ /* vector lying in a specified coordinate plane. */ /* $ 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 */ /* AXES, FRAME, ROTATION, TRANSFORMATION */ /* $ Declarations */ /* $ Brief_I/O */ /* VARIABLE I/O DESCRIPTION */ /* -------- --- ------------------------------------------------- */ /* AXDEF I Vector defining a principal axis. */ /* INDEXA I Principal axis number of AXDEF (X=1, Y=2, Z=3). */ /* PLNDEF I Vector defining (with AXDEF) a principal plane. */ /* INDEXP I Second axis number (with INDEXA) of principal */ /* plane. */ /* MOUT O Output rotation matrix. */ /* $ Detailed_Input */ /* AXDEF is a vector defining one of the priciple axes of a */ /* coordinate frame. */ /* INDEXA is a number that determines which of the three */ /* coordinate axes contains AXDEF. */ /* If INDEXA is 1 then AXDEF defines the X axis of the */ /* coordinate frame. */ /* If INDEXA is 2 then AXDEF defines the Y axis of the */ /* coordinate frame. */ /* If INDEXA is 3 then AXDEF defines the Z axis of the */ /* coordinate frame */ /* PLNDEF is a vector defining (with AXDEF) a principal plane of */ /* the coordinate frame. AXDEF and PLNDEF must be */ /* linearly independent. */ /* INDEXP is the second axis of the principal frame determined */ /* by AXDEF and PLNDEF. INDEXA, INDEXP must be different */ /* and be integers from 1 to 3. */ /* If INDEXP is 1, the second axis of the principal */ /* plane is the X-axis. */ /* If INDEXP is 2, the second axis of the principal */ /* plane is the Y-axis. */ /* If INDEXP is 3, the second axis of the principal plane */ /* is the Z-axis. */ /* $ Detailed_Output */ /* MOUT is a rotation matrix that transforms coordinates given */ /* in the input frame to the frame determined by AXDEF, */ /* PLNDEF, INDEXA and INDEXP. */ /* $ Parameters */ /* None. */ /* $ Exceptions */ /* 1) If INDEXA or INDEXP is not in the set {1,2,3} the error */ /* SPICE(BADINDEX) will be signaled. */ /* 2) If INDEXA and INDEXP are the same the error */ /* SPICE(UNDEFINEDFRAME) will be signaled. */ /* 3) If the cross product of the vectors AXDEF and PLNDEF is zero, */ /* the error SPICE(DEPENDENTVECTORS) will be signaled. */ /* $ Files */ /* None. */ /* $ Particulars */ /* Given two linearly independent vectors there is a unique */ /* right-handed coordinate frame having: */ /* AXDEF lying along the INDEXA axis. */ /* PLNDEF lying in the INDEXA-INDEXP coordinate plane. */ /* This routine determines the transformation matrix that transforms */ /* from coordinates used to represent the input vectors to the */ /* the system determined by AXDEF and PLNDEF. Thus a vector */ /* (x,y,z) in the input coordinate system will have coordinates */ /* t */ /* MOUT* (x,y,z) */ /* in the frame determined by AXDEF and PLNDEF. */ /* $ Examples */ /* The rotation matrix TICC from inertial to Sun-Canopus */ /* (celestial) coordinates is found by the call */ /* CALL TWOVEC (Sun vector, 3, Canopus vector, 1, TICC) */ /* $ Restrictions */ /* None. */ /* $ Author_and_Institution */ /* N.J. Bachman (JPL) */ /* W.M. Owen (JPL) */ /* W.L. Taber (JPL) */ /* $ Literature_References */ /* None. */ /* $ Version */ /* - SPICELIB Version 1.1.0, 31-AUG-2005 (NJB) */ /* Updated to remove non-standard use of duplicate arguments */ /* in VSCL call. */ /* - SPICELIB Version 1.0.1, 10-MAR-1992 (WLT) */ /* Comment section for permuted index source lines was added */ /* following the header. */ /* - SPICELIB Version 1.0.0, 31-JAN-1990 (WMO) */ /* -& */ /* $ Index_Entries */ /* define an orthonormal frame from two vectors */ /* -& */ /* $ Revisions */ /* - SPICELIB Version 1.1.0, 31-AUG-2005 (NJB) */ /* Updated to remove non-standard use of duplicate arguments */ /* in VSCL call. */ /* - Beta Version 2.0.0, 10-JAN-1989 (WLT) */ /* Error checking was added and the algorithm somewhat redesigned. */ /* -& */ /* SPICELIB functions */ /* Local variables */ /* Saved variables */ /* Initial values */ /* Standard SPICE error handling */ if (return_()) { return 0; } else { chkin_("TWOVEC", (ftnlen)6); } /* Check for obvious bad inputs. */ if (max(*indexp,*indexa) > 3 || min(*indexp,*indexa) < 1) { setmsg_("The definition indexs must lie in the range from 1 to 3. T" "he value of INDEXA was #. The value of INDEXP was #. ", ( ftnlen)112); errint_("#", indexa, (ftnlen)1); errint_("#", indexp, (ftnlen)1); sigerr_("SPICE(BADINDEX)", (ftnlen)15); chkout_("TWOVEC", (ftnlen)6); return 0; } else if (*indexa == *indexp) { setmsg_("The values of INDEXA and INDEXP were the same, namely #. T" "hey are required to be different.", (ftnlen)92); errint_("#", indexa, (ftnlen)1); sigerr_("SPICE(UNDEFINEDFRAME)", (ftnlen)21); chkout_("TWOVEC", (ftnlen)6); return 0; } /* Get indices for right-handed axes */ /* First AXDEF ... */ i1 = *indexa; /* ... then the other two. */ i2 = seqnce[(i__1 = *indexa) < 5 && 0 <= i__1 ? i__1 : s_rnge("seqnce", i__1, "twovec_", (ftnlen)270)]; i3 = seqnce[(i__1 = *indexa + 1) < 5 && 0 <= i__1 ? i__1 : s_rnge("seqnce" , i__1, "twovec_", (ftnlen)271)]; /* Row I1 contains normalized AXDEF (store in columns for now) */ vhat_(axdef, &mout[(i__1 = i1 * 3 - 3) < 9 && 0 <= i__1 ? i__1 : s_rnge( "mout", i__1, "twovec_", (ftnlen)276)]); /* Obtain rows I2 and I3 using cross products. Which order to use */ /* depends on whether INDEXP = I2 (next axis in right-handed order) */ /* or INDEXP = I3 (previous axis in right-handed order). */ if (*indexp == i2) { ucrss_(axdef, plndef, &mout[(i__1 = i3 * 3 - 3) < 9 && 0 <= i__1 ? i__1 : s_rnge("mout", i__1, "twovec_", (ftnlen)285)]); ucrss_(&mout[(i__1 = i3 * 3 - 3) < 9 && 0 <= i__1 ? i__1 : s_rnge( "mout", i__1, "twovec_", (ftnlen)286)], axdef, &mout[(i__2 = i2 * 3 - 3) < 9 && 0 <= i__2 ? i__2 : s_rnge("mout", i__2, "twovec_", (ftnlen)286)]); } else { ucrss_(plndef, axdef, &mout[(i__1 = i2 * 3 - 3) < 9 && 0 <= i__1 ? i__1 : s_rnge("mout", i__1, "twovec_", (ftnlen)290)]); ucrss_(axdef, &mout[(i__1 = i2 * 3 - 3) < 9 && 0 <= i__1 ? i__1 : s_rnge("mout", i__1, "twovec_", (ftnlen)291)], &mout[(i__2 = i3 * 3 - 3) < 9 && 0 <= i__2 ? i__2 : s_rnge("mout", i__2, "twovec_", (ftnlen)291)]); } /* Finally, check to see that we actually got something non-zero */ /* in one of the one columns of MOUT(1,I2) and MOUT(1,I3) (we need */ /* only check one of them since they are related by a cross product). */ if (mout[(i__1 = i2 * 3 - 3) < 9 && 0 <= i__1 ? i__1 : s_rnge("mout", i__1, "twovec_", (ftnlen)300)] == 0. && mout[(i__2 = i2 * 3 - 2) < 9 && 0 <= i__2 ? i__2 : s_rnge("mout", i__2, "twovec_", (ftnlen) 300)] == 0. && mout[(i__3 = i2 * 3 - 1) < 9 && 0 <= i__3 ? i__3 : s_rnge("mout", i__3, "twovec_", (ftnlen)300)] == 0.) { setmsg_("The input vectors AXDEF and PLNDEF are linearly dependent.", (ftnlen)58); sigerr_("SPICE(DEPENDENTVECTORS)", (ftnlen)23); } /* Transpose MOUT. */ xpose_(mout, mtemp); moved_(mtemp, &c__9, mout); chkout_("TWOVEC", (ftnlen)6); return 0; } /* twovec_ */
/* $Procedure CKFROT ( C-kernel, find rotation ) */ /* Subroutine */ int ckfrot_(integer *inst, doublereal *et, doublereal * rotate, integer *ref, logical *found) { logical have, pfnd, sfnd; doublereal time; extern /* Subroutine */ int sce2c_(integer *, doublereal *, doublereal *); char segid[40]; extern /* Subroutine */ int chkin_(char *, ftnlen); doublereal descr[5]; extern /* Subroutine */ int dafus_(doublereal *, integer *, integer *, doublereal *, integer *), ckbss_(integer *, doublereal *, doublereal *, logical *), ckpfs_(integer *, doublereal *, doublereal *, doublereal *, logical *, doublereal *, doublereal *, doublereal *, logical *), cksns_(integer *, doublereal *, char *, logical *, ftnlen), xpose_(doublereal *, doublereal *); extern logical failed_(void); doublereal av[3]; integer handle; extern /* Subroutine */ int ckhave_(logical *); logical needav; extern /* Subroutine */ int ckmeta_(integer *, char *, integer *, ftnlen); integer sclkid; extern /* Subroutine */ int chkout_(char *, ftnlen); doublereal clkout; extern logical return_(void), zzsclk_(integer *, integer *); doublereal dcd[2]; integer icd[6]; doublereal tol, rot[9] /* was [3][3] */; /* $ Abstract */ /* Find the rotation from a C-kernel Id to the native */ /* frame at the time requested. */ /* $ 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 */ /* $ Brief_I/O */ /* Variable I/O Description */ /* -------- --- -------------------------------------------------- */ /* INST I NAIF instrument ID. */ /* ET I Epoch measured in seconds past J2000. */ /* ROTATE O rotation from CK platform to frame REF. */ /* REF O Reference frame. */ /* FOUND O True when requested pointing is available. */ /* $ Detailed_Input */ /* INST is the unique NAIF integer ID for the spacecraft */ /* instrument for which data is being requested. */ /* ET is the epoch for which the state rotation */ /* is desired. ET should be given in seconds past the */ /* epoch of J2000. */ /* $ Detailed_Output */ /* ROTATE is a rotation matrix that converts */ /* positions relative to the input frame (given by INST) */ /* to positions relative to the frame REF. */ /* Thus, if a state S has components x,y,z,dx,dy,dz */ /* in the frame of INST, frame, then S has components */ /* x', y', z', dx', dy', dz' in frame REF. */ /* [ x' ] [ ] [ x ] */ /* | y' | = | ROTATE | | y | */ /* [ z' ] [ ] [ z ] */ /* REF is the id-code reference frame to which ROTATE will */ /* transform states. */ /* FOUND is true if a record was found to satisfy the pointing */ /* request. FOUND will be false otherwise. */ /* $ Parameters */ /* None. */ /* $ Exceptions */ /* 1) If a C-kernel file is not loaded using CKLPF prior to calling */ /* this routine, an error is signalled by a routine that this */ /* routine calls. */ /* $ Files */ /* CKFROT searches through files loaded by CKLPF to locate a segment */ /* that can satisfy the request for position rotation */ /* for instrument INST at time ET. You must load a C-kernel */ /* file using CKLPF before calling this routine. */ /* $ Particulars */ /* CKFROT searches through files loaded by CKLPF to satisfy a */ /* pointing request. Last-loaded files are searched first, and */ /* individual files are searched in backwards order, giving */ /* priority to segments that were added to a file later than the */ /* others. CKFROT considers only those segments that contain */ /* angular velocity data. */ /* The search ends when a segment is found that can give pointing */ /* for the specified instrument at the request time. */ /* $ Examples */ /* None. */ /* $ Restrictions */ /* A C-kernel file should have been loaded by CKLPF. */ /* In addition it is helpful to load a CK-info file into the */ /* Kernel pool. This file should have the following variables */ /* defined. */ /* CK_<INST>_SCLK = SCLK idcode that yields SCLK mapping for INST. */ /* CK_<INST>_SPK = SPK idcode that yields ephemeris for INST. */ /* where <INST> is the integer string corresponding to INST. */ /* $ Literature_References */ /* None. */ /* $ Author_and_Institution */ /* W.L. Taber (JPL) */ /* $ Version */ /* - SPICELIB Version 1.2.0, 17-FEB-2000 (WLT) */ /* The routine now checks to make sure convert ET to TICKS */ /* and that at least one C-kernel is loaded before trying */ /* to look up the transformation. Also the routine now calls */ /* SCE2C instead of SCE2T. */ /* - SPICELIB Version 1.0.0, 03-MAR-1999 (WLT) */ /* -& */ /* $ Index_Entries */ /* get instrument frame rotation and reference frame */ /* -& */ /* SPICELIB functions */ /* Local parameters */ /* NDC is the number of double precision components in an */ /* unpacked C-kernel segment descriptor. */ /* NIC is the number of integer components in an unpacked */ /* C-kernel segment descriptor. */ /* NC is the number of components in a packed C-kernel */ /* descriptor. All DAF summaries have this formulaic */ /* relationship between the number of its integer and */ /* double precision components and the number of packed */ /* components. */ /* IDLEN is the length of the C-kernel segment identifier. */ /* All DAF names have this formulaic relationship */ /* between the number of summary components and */ /* the length of the name (You will notice that */ /* a name and a summary have the same length in bytes.) */ /* Local variables */ /* Set FOUND to FALSE right now in case we end up */ /* returning before doing any work. */ *found = FALSE_; *ref = 0; /* Standard SPICE error handling. */ if (return_()) { return 0; } else { chkin_("CKFROT", (ftnlen)6); } /* We don't need angular velocity data. */ /* Assume the segment won't be found until it really is. */ needav = FALSE_; tol = 0.; /* Begin a search for this instrument and time, and get the first */ /* applicable segment. */ ckhave_(&have); ckmeta_(inst, "SCLK", &sclkid, (ftnlen)4); if (! have) { chkout_("CKFROT", (ftnlen)6); return 0; } else if (! zzsclk_(inst, &sclkid)) { chkout_("CKFROT", (ftnlen)6); return 0; } sce2c_(&sclkid, et, &time); ckbss_(inst, &time, &tol, &needav); cksns_(&handle, descr, segid, &sfnd, (ftnlen)40); /* Keep trying candidate segments until a segment can produce a */ /* pointing instance within the specified time tolerance of the */ /* input time. */ /* Check FAILED to prevent an infinite loop if an error is detected */ /* by a SPICELIB routine and the error handling is not set to abort. */ while(sfnd && ! failed_()) { ckpfs_(&handle, descr, &time, &tol, &needav, rot, av, &clkout, &pfnd); if (pfnd) { /* Found one. Fetch the ID code of the reference frame */ /* from the descriptor. */ dafus_(descr, &c__2, &c__6, dcd, icd); *ref = icd[1]; *found = TRUE_; /* We now have the rotation matrix from */ /* REF to INS. We invert ROT to get the rotation */ /* from INST to REF. */ xpose_(rot, rotate); chkout_("CKFROT", (ftnlen)6); return 0; } cksns_(&handle, descr, segid, &sfnd, (ftnlen)40); } chkout_("CKFROT", (ftnlen)6); return 0; } /* ckfrot_ */