PageRenderTime 52ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/src/ckw03.c

https://github.com/mattbornski/spice
C | 951 lines | 228 code | 250 blank | 473 comment | 32 complexity | 272b1b8a379b669328e96cdfe988cee2 MD5 | raw file
  1. /* ckw03.f -- translated by f2c (version 19980913).
  2. You must link the resulting object file with the libraries:
  3. -lf2c -lm (in that order)
  4. */
  5. #include "f2c.h"
  6. /* Table of constant values */
  7. static integer c__2 = 2;
  8. static integer c__6 = 6;
  9. static integer c__4 = 4;
  10. static integer c__3 = 3;
  11. static integer c__1 = 1;
  12. /* $Procedure CKW03 ( C-Kernel, write segment to C-kernel, data type 3 ) */
  13. /* Subroutine */ int ckw03_(integer *handle, doublereal *begtim, doublereal *
  14. endtim, integer *inst, char *ref, logical *avflag, char *segid,
  15. integer *nrec, doublereal *sclkdp, doublereal *quats, doublereal *
  16. avvs, integer *nints, doublereal *starts, ftnlen ref_len, ftnlen
  17. segid_len)
  18. {
  19. /* System generated locals */
  20. integer i__1, i__2;
  21. doublereal d__1;
  22. /* Local variables */
  23. integer i__;
  24. logical match;
  25. extern /* Subroutine */ int chkin_(char *, ftnlen), dafps_(integer *,
  26. integer *, doublereal *, integer *, doublereal *);
  27. doublereal descr[5];
  28. extern /* Subroutine */ int errch_(char *, char *, ftnlen, ftnlen);
  29. integer nidir, index, value;
  30. extern /* Subroutine */ int errdp_(char *, doublereal *, ftnlen);
  31. integer nrdir;
  32. extern /* Subroutine */ int dafada_(doublereal *, integer *), dafbna_(
  33. integer *, doublereal *, char *, ftnlen), dafena_(void);
  34. extern logical failed_(void);
  35. integer refcod;
  36. extern /* Subroutine */ int namfrm_(char *, integer *, ftnlen);
  37. extern integer lastnb_(char *, ftnlen);
  38. extern /* Subroutine */ int sigerr_(char *, ftnlen), chkout_(char *,
  39. ftnlen), setmsg_(char *, ftnlen), errint_(char *, integer *,
  40. ftnlen);
  41. extern logical vzerog_(doublereal *, integer *), return_(void);
  42. doublereal dcd[2];
  43. integer icd[6];
  44. /* $ Abstract */
  45. /* Add a type 3 segment to a C-kernel. */
  46. /* $ Disclaimer */
  47. /* THIS SOFTWARE AND ANY RELATED MATERIALS WERE CREATED BY THE */
  48. /* CALIFORNIA INSTITUTE OF TECHNOLOGY (CALTECH) UNDER A U.S. */
  49. /* GOVERNMENT CONTRACT WITH THE NATIONAL AERONAUTICS AND SPACE */
  50. /* ADMINISTRATION (NASA). THE SOFTWARE IS TECHNOLOGY AND SOFTWARE */
  51. /* PUBLICLY AVAILABLE UNDER U.S. EXPORT LAWS AND IS PROVIDED "AS-IS" */
  52. /* TO THE RECIPIENT WITHOUT WARRANTY OF ANY KIND, INCLUDING ANY */
  53. /* WARRANTIES OF PERFORMANCE OR MERCHANTABILITY OR FITNESS FOR A */
  54. /* PARTICULAR USE OR PURPOSE (AS SET FORTH IN UNITED STATES UCC */
  55. /* SECTIONS 2312-2313) OR FOR ANY PURPOSE WHATSOEVER, FOR THE */
  56. /* SOFTWARE AND RELATED MATERIALS, HOWEVER USED. */
  57. /* IN NO EVENT SHALL CALTECH, ITS JET PROPULSION LABORATORY, OR NASA */
  58. /* BE LIABLE FOR ANY DAMAGES AND/OR COSTS, INCLUDING, BUT NOT */
  59. /* LIMITED TO, INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, */
  60. /* INCLUDING ECONOMIC DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS, */
  61. /* REGARDLESS OF WHETHER CALTECH, JPL, OR NASA BE ADVISED, HAVE */
  62. /* REASON TO KNOW, OR, IN FACT, SHALL KNOW OF THE POSSIBILITY. */
  63. /* RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF */
  64. /* THE SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY */
  65. /* CALTECH AND NASA FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE */
  66. /* ACTIONS OF RECIPIENT IN THE USE OF THE SOFTWARE. */
  67. /* $ Required_Reading */
  68. /* CK */
  69. /* DAF */
  70. /* ROTATION */
  71. /* SCLK */
  72. /* $ Keywords */
  73. /* POINTING */
  74. /* UTILITY */
  75. /* $ Declarations */
  76. /* $ Brief_I/O */
  77. /* Variable I/O Description */
  78. /* -------- --- -------------------------------------------------- */
  79. /* HANDLE I Handle of an open CK file. */
  80. /* BEGTIM I Beginning encoded SCLK of the segment. */
  81. /* ENDTIM I Ending encoded SCLK of the segment. */
  82. /* INST I NAIF instrument ID code. */
  83. /* REF I Reference frame of the segment. */
  84. /* AVFLAG I True if the segment will contain angular velocity. */
  85. /* SEGID I Segment identifier. */
  86. /* NREC I Number of pointing records. */
  87. /* SCLKDP I Encoded SCLK times. */
  88. /* QUATS I SPICE quaternions representing instrument pointing. */
  89. /* AVVS I Angular velocity vectors. */
  90. /* NINTS I Number of intervals. */
  91. /* STARTS I Encoded SCLK interval start times. */
  92. /* $ Detailed_Input */
  93. /* HANDLE is the handle of the CK file to which the segment will */
  94. /* be written. The file must have been opened with write */
  95. /* access. */
  96. /* BEGTIM, are the beginning and ending encoded SCLK times for */
  97. /* ENDTIM which the segment provides pointing information. */
  98. /* BEGTIM must be less than or equal to the SCLK time */
  99. /* associated with the first pointing instance in the */
  100. /* segment, and ENDTIM must be greater than or equal to */
  101. /* the time associated with the last pointing instance */
  102. /* in the segment. */
  103. /* INST is the NAIF integer ID code for the instrument that */
  104. /* this segment will contain pointing information for. */
  105. /* REF is a character string which specifies the inertial */
  106. /* reference frame of the segment. */
  107. /* The rotation matrices represented by the quaternions */
  108. /* that are to be written to the segment transform the */
  109. /* components of vectors from the inertial reference frame */
  110. /* specified by REF to components in the instrument fixed */
  111. /* frame. Also, the components of the angular velocity */
  112. /* vectors to be written to the segment should be given */
  113. /* with respect to REF. */
  114. /* REF should be the name of one of the frames supported */
  115. /* by the SPICELIB routine FRAMEX. */
  116. /* AVFLAG is a logical flag which indicates whether or not the */
  117. /* segment will contain angular velocity. */
  118. /* SEGID is the segment identifier. A CK segment identifier may */
  119. /* contain up to 40 printable characters and spaces. */
  120. /* NREC is the number of pointing instances in the segment. */
  121. /* SCLKDP are the encoded spacecraft clock times associated with */
  122. /* each pointing instance. These times must be strictly */
  123. /* increasing. */
  124. /* QUATS is an array of SPICE-style quaternions representing */
  125. /* a sequence of C-matrices. See the discussion of */
  126. /* quaternion styles in Particulars below. */
  127. /* The C-matrix represented by the Ith quaternion in */
  128. /* QUATS is a rotation matrix that transforms the */
  129. /* components of a vector expressed in the inertial */
  130. /* frame specified by REF to components expressed in */
  131. /* the instrument fixed frame at the time SCLKDP(I). */
  132. /* Thus, if a vector V has components x, y, z in the */
  133. /* inertial frame, then V has components x', y', z' in */
  134. /* the instrument fixed frame where: */
  135. /* [ x' ] [ ] [ x ] */
  136. /* | y' | = | CMAT | | y | */
  137. /* [ z' ] [ ] [ z ] */
  138. /* AVVS are the angular velocity vectors ( optional ). */
  139. /* The Ith vector in AVVS gives the angular velocity of */
  140. /* the instrument fixed frame at time SCLKDP(I). The */
  141. /* components of the angular velocity vectors should */
  142. /* be given with respect to the inertial reference frame */
  143. /* specified by REF. */
  144. /* The direction of an angular velocity vector gives */
  145. /* the right-handed axis about which the instrument fixed */
  146. /* reference frame is rotating. The magnitude of the */
  147. /* vector is the magnitude of the instantaneous velocity */
  148. /* of the rotation, in radians per second. */
  149. /* If AVFLAG is FALSE then this array is ignored by the */
  150. /* routine; however it still must be supplied as part of */
  151. /* the calling sequence. */
  152. /* NINTS is the number of intervals that the pointing instances */
  153. /* are partitioned into. */
  154. /* STARTS are the start times of each of the interpolation */
  155. /* intervals. These times must be strictly increasing */
  156. /* and must coincide with times for which the segment */
  157. /* contains pointing. */
  158. /* $ Detailed_Output */
  159. /* None. See Files section. */
  160. /* $ Parameters */
  161. /* None. */
  162. /* $ Exceptions */
  163. /* 1) If HANDLE is not the handle of a C-kernel opened for writing */
  164. /* the error will be diagnosed by routines called by this */
  165. /* routine. */
  166. /* 2) If SEGID is more than 40 characters long, the error */
  167. /* SPICE(SEGIDTOOLONG) is signaled. */
  168. /* 3) If SEGID contains any non-printable characters, the error */
  169. /* SPICE(NONPRINTABLECHARS) is signaled. */
  170. /* 4) If the first encoded SCLK time is negative then the error */
  171. /* SPICE(INVALIDSCLKTIME) is signaled. If any subsequent times */
  172. /* are negative the error will be detected in exception (5). */
  173. /* 5) If the encoded SCLK times are not strictly increasing, */
  174. /* the error SPICE(TIMESOUTOFORDER) is signaled. */
  175. /* 6) If BEGTIM is greater than SCLKDP(1) or ENDTIM is less than */
  176. /* SCLKDP(NREC), the error SPICE(INVALIDDESCRTIME) is */
  177. /* signaled. */
  178. /* 7) If the name of the reference frame is not one of those */
  179. /* supported by the routine FRAMEX, the error */
  180. /* SPICE(INVALIDREFFRAME) is signaled. */
  181. /* 8) If NREC, the number of pointing records, is less than or */
  182. /* equal to 0, the error SPICE(INVALIDNUMREC) is signaled. */
  183. /* 9) If NINTS, the number of interpolation intervals, is less than */
  184. /* or equal to 0, the error SPICE(INVALIDNUMINT) is signaled. */
  185. /* 10) If the encoded SCLK interval start times are not strictly */
  186. /* increasing, the error SPICE(TIMESOUTOFORDER) is signaled. */
  187. /* 11) If an interval start time does not coincide with a time for */
  188. /* which there is an actual pointing instance in the segment, */
  189. /* then the error SPICE(INVALIDSTARTTIME) is signaled. */
  190. /* 12) This routine assumes that the rotation between adjacent */
  191. /* quaternions that are stored in the same interval has a */
  192. /* rotation angle of THETA radians, where */
  193. /* 0 < THETA < pi. */
  194. /* _ */
  195. /* The routines that evaluate the data in the segment produced */
  196. /* by this routine cannot distinguish between rotations of THETA */
  197. /* radians, where THETA is in the interval [0, pi), and */
  198. /* rotations of */
  199. /* THETA + 2 * k * pi */
  200. /* radians, where k is any integer. These `large' rotations will */
  201. /* yield invalid results when interpolated. You must ensure that */
  202. /* the data stored in the segment will not be subject to this */
  203. /* sort of ambiguity. */
  204. /* 13) If any quaternion has magnitude zero, the error */
  205. /* SPICE(ZEROQUATERNION) is signaled. */
  206. /* 14) If the start time of the first interval and the time of the */
  207. /* first pointing instance are not the same, the error */
  208. /* SPICE(TIMESDONTMATCH) is signaled. */
  209. /* $ Files */
  210. /* This routine adds a type 3 segment to a C-kernel. The C-kernel */
  211. /* may be either a new one or an existing one opened for writing. */
  212. /* $ Particulars */
  213. /* For a detailed description of a type 3 CK segment please see the */
  214. /* CK Required Reading. */
  215. /* This routine relieves the user from performing the repetitive */
  216. /* calls to the DAF routines necessary to construct a CK segment. */
  217. /* Quaternion Styles */
  218. /* ----------------- */
  219. /* There are different "styles" of quaternions used in */
  220. /* science and engineering applications. Quaternion styles */
  221. /* are characterized by */
  222. /* - The order of quaternion elements */
  223. /* - The quaternion multiplication formula */
  224. /* - The convention for associating quaternions */
  225. /* with rotation matrices */
  226. /* Two of the commonly used styles are */
  227. /* - "SPICE" */
  228. /* > Invented by Sir William Rowan Hamilton */
  229. /* > Frequently used in mathematics and physics textbooks */
  230. /* - "Engineering" */
  231. /* > Widely used in aerospace engineering applications */
  232. /* SPICELIB subroutine interfaces ALWAYS use SPICE quaternions. */
  233. /* Quaternions of any other style must be converted to SPICE */
  234. /* quaternions before they are passed to SPICELIB routines. */
  235. /* Relationship between SPICE and Engineering Quaternions */
  236. /* ------------------------------------------------------ */
  237. /* Let M be a rotation matrix such that for any vector V, */
  238. /* M*V */
  239. /* is the result of rotating V by theta radians in the */
  240. /* counterclockwise direction about unit rotation axis vector A. */
  241. /* Then the SPICE quaternions representing M are */
  242. /* (+/-) ( cos(theta/2), */
  243. /* sin(theta/2) A(1), */
  244. /* sin(theta/2) A(2), */
  245. /* sin(theta/2) A(3) ) */
  246. /* while the engineering quaternions representing M are */
  247. /* (+/-) ( -sin(theta/2) A(1), */
  248. /* -sin(theta/2) A(2), */
  249. /* -sin(theta/2) A(3), */
  250. /* cos(theta/2) ) */
  251. /* For both styles of quaternions, if a quaternion q represents */
  252. /* a rotation matrix M, then -q represents M as well. */
  253. /* Given an engineering quaternion */
  254. /* QENG = ( q0, q1, q2, q3 ) */
  255. /* the equivalent SPICE quaternion is */
  256. /* QSPICE = ( q3, -q0, -q1, -q2 ) */
  257. /* Associating SPICE Quaternions with Rotation Matrices */
  258. /* ---------------------------------------------------- */
  259. /* Let FROM and TO be two right-handed reference frames, for */
  260. /* example, an inertial frame and a spacecraft-fixed frame. Let the */
  261. /* symbols */
  262. /* V , V */
  263. /* FROM TO */
  264. /* denote, respectively, an arbitrary vector expressed relative to */
  265. /* the FROM and TO frames. Let M denote the transformation matrix */
  266. /* that transforms vectors from frame FROM to frame TO; then */
  267. /* V = M * V */
  268. /* TO FROM */
  269. /* where the expression on the right hand side represents left */
  270. /* multiplication of the vector by the matrix. */
  271. /* Then if the unit-length SPICE quaternion q represents M, where */
  272. /* q = (q0, q1, q2, q3) */
  273. /* the elements of M are derived from the elements of q as follows: */
  274. /* +- -+ */
  275. /* | 2 2 | */
  276. /* | 1 - 2*( q2 + q3 ) 2*(q1*q2 - q0*q3) 2*(q1*q3 + q0*q2) | */
  277. /* | | */
  278. /* | | */
  279. /* | 2 2 | */
  280. /* M = | 2*(q1*q2 + q0*q3) 1 - 2*( q1 + q3 ) 2*(q2*q3 - q0*q1) | */
  281. /* | | */
  282. /* | | */
  283. /* | 2 2 | */
  284. /* | 2*(q1*q3 - q0*q2) 2*(q2*q3 + q0*q1) 1 - 2*( q1 + q2 ) | */
  285. /* | | */
  286. /* +- -+ */
  287. /* Note that substituting the elements of -q for those of q in the */
  288. /* right hand side leaves each element of M unchanged; this shows */
  289. /* that if a quaternion q represents a matrix M, then so does the */
  290. /* quaternion -q. */
  291. /* To map the rotation matrix M to a unit quaternion, we start by */
  292. /* decomposing the rotation matrix as a sum of symmetric */
  293. /* and skew-symmetric parts: */
  294. /* 2 */
  295. /* M = [ I + (1-cos(theta)) OMEGA ] + [ sin(theta) OMEGA ] */
  296. /* symmetric skew-symmetric */
  297. /* OMEGA is a skew-symmetric matrix of the form */
  298. /* +- -+ */
  299. /* | 0 -n3 n2 | */
  300. /* | | */
  301. /* OMEGA = | n3 0 -n1 | */
  302. /* | | */
  303. /* | -n2 n1 0 | */
  304. /* +- -+ */
  305. /* The vector N of matrix entries (n1, n2, n3) is the rotation axis */
  306. /* of M and theta is M's rotation angle. Note that N and theta */
  307. /* are not unique. */
  308. /* Let */
  309. /* C = cos(theta/2) */
  310. /* S = sin(theta/2) */
  311. /* Then the unit quaternions Q corresponding to M are */
  312. /* Q = +/- ( C, S*n1, S*n2, S*n3 ) */
  313. /* The mappings between quaternions and the corresponding rotations */
  314. /* are carried out by the SPICELIB routines */
  315. /* Q2M {quaternion to matrix} */
  316. /* M2Q {matrix to quaternion} */
  317. /* M2Q always returns a quaternion with scalar part greater than */
  318. /* or equal to zero. */
  319. /* SPICE Quaternion Multiplication Formula */
  320. /* --------------------------------------- */
  321. /* Given a SPICE quaternion */
  322. /* Q = ( q0, q1, q2, q3 ) */
  323. /* corresponding to rotation axis A and angle theta as above, we can */
  324. /* represent Q using "scalar + vector" notation as follows: */
  325. /* s = q0 = cos(theta/2) */
  326. /* v = ( q1, q2, q3 ) = sin(theta/2) * A */
  327. /* Q = s + v */
  328. /* Let Q1 and Q2 be SPICE quaternions with respective scalar */
  329. /* and vector parts s1, s2 and v1, v2: */
  330. /* Q1 = s1 + v1 */
  331. /* Q2 = s2 + v2 */
  332. /* We represent the dot product of v1 and v2 by */
  333. /* <v1, v2> */
  334. /* and the cross product of v1 and v2 by */
  335. /* v1 x v2 */
  336. /* Then the SPICE quaternion product is */
  337. /* Q1*Q2 = s1*s2 - <v1,v2> + s1*v2 + s2*v1 + (v1 x v2) */
  338. /* If Q1 and Q2 represent the rotation matrices M1 and M2 */
  339. /* respectively, then the quaternion product */
  340. /* Q1*Q2 */
  341. /* represents the matrix product */
  342. /* M1*M2 */
  343. /* $ Examples */
  344. /* C */
  345. /* C This example code fragment writes a type 3 C-kernel segment */
  346. /* C for the Mars Observer spacecraft bus to a previously opened CK */
  347. /* C file attached to HANDLE. */
  348. /* C */
  349. /* C */
  350. /* C Assume arrays of quaternions, angular velocities, and the */
  351. /* C associated SCLK times are produced elsewhere. The software */
  352. /* C that calls CKW03 must then decide how to partition these */
  353. /* C pointing instances into intervals over which linear */
  354. /* C interpolation between adjacent points is valid. */
  355. /* C */
  356. /* . */
  357. /* . */
  358. /* . */
  359. /* C */
  360. /* C The subroutine CKW03 needs the following items for the */
  361. /* C segment descriptor: */
  362. /* C */
  363. /* C 1) SCLK limits of the segment. */
  364. /* C 2) Instrument code. */
  365. /* C 3) Reference frame. */
  366. /* C 4) The angular velocity flag. */
  367. /* C */
  368. /* BEGTIM = SCLK ( 1 ) */
  369. /* ENDTIM = SCLK ( NREC ) */
  370. /* INST = -94000 */
  371. /* REF = 'J2000' */
  372. /* AVFLAG = .TRUE. */
  373. /* SEGID = 'MO SPACECRAFT BUS - DATA TYPE 3' */
  374. /* C */
  375. /* C Write the segment. */
  376. /* C */
  377. /* CALL CKW03 ( HANDLE, BEGTIM, ENDTIM, INST, REF, AVFLAG, */
  378. /* . SEGID, NREC, SCLKDP, QUATS, AVVS, NINTS, */
  379. /* . STARTS ) */
  380. /* $ Restrictions */
  381. /* 1) The creator of the segment is given the responsibility for */
  382. /* determining whether it is reasonable to interpolate between */
  383. /* two given pointing values. */
  384. /* 2) This routine assumes that the rotation between adjacent */
  385. /* quaternions that are stored in the same interval has a */
  386. /* rotation angle of THETA radians, where */
  387. /* 0 < THETA < pi. */
  388. /* _ */
  389. /* The routines that evaluate the data in the segment produced */
  390. /* by this routine cannot distinguish between rotations of THETA */
  391. /* radians, where THETA is in the interval [0, pi), and */
  392. /* rotations of */
  393. /* THETA + 2 * k * pi */
  394. /* radians, where k is any integer. These `large' rotations will */
  395. /* yield invalid results when interpolated. You must ensure that */
  396. /* the data stored in the segment will not be subject to this */
  397. /* sort of ambiguity. */
  398. /* 3) All pointing instances in the segment must belong to one and */
  399. /* only one of the intervals. */
  400. /* $ Literature_References */
  401. /* None. */
  402. /* $ Author_and_Institution */
  403. /* W.L. Taber (JPL) */
  404. /* K.R. Gehringer (JPL) */
  405. /* J.M. Lynch (JPL) */
  406. /* B.V. Semenov (JPL) */
  407. /* $ Version */
  408. /* - SPICELIB Version 3.0.0, 01-JUN-2010 (NJB) */
  409. /* The check for non-unit quaternions has been replaced */
  410. /* with a check for zero-length quaternions. */
  411. /* - SPICELIB Version 2.3.0, 26-FEB-2008 (NJB) */
  412. /* Updated header; added information about SPICE */
  413. /* quaternion conventions. */
  414. /* Minor typo in a long error message was corrected. */
  415. /* - SPICELIB Version 2.2.0, 26-SEP-2005 (BVS) */
  416. /* Added check to ensure that the start time of the first */
  417. /* interval is the same as the time of the first pointing */
  418. /* instance. */
  419. /* - SPICELIB Version 2.1.0, 22-FEB-1999 (WLT) */
  420. /* Added check to make sure that all quaternions are unit */
  421. /* length to single precision. */
  422. /* - SPICELIB Version 2.0.0, 28-DEC-1993 (WLT) */
  423. /* The routine was upgraded to support non-inertial reference */
  424. /* frames. */
  425. /* - SPICELIB Version 1.1.1, 05-SEP-1993 (KRG) */
  426. /* Removed all references to a specific method of opening the CK */
  427. /* file in the $ Brief_I/O, $ Detailed_Input, $ Exceptions, */
  428. /* $ Files, and $ Examples sections of the header. It is assumed */
  429. /* that a person using this routine has some knowledge of the DAF */
  430. /* system and the methods for obtaining file handles. */
  431. /* - SPICELIB Version 1.0.0, 25-NOV-1992 (JML) */
  432. /* -& */
  433. /* $ Index_Entries */
  434. /* write ck type_3 pointing data segment */
  435. /* -& */
  436. /* $ Revisions */
  437. /* - SPICELIB Version 2.2.0, 26-SEP-2005 (BVS) */
  438. /* Added check to ensure that the start time of the first */
  439. /* interval is the same as the time of the first pointing */
  440. /* instance. */
  441. /* - SPICELIB Version 2.1.0, 22-FEB-1999 (WLT) */
  442. /* Added check to make sure that all quaternions are unit */
  443. /* length to single precision. */
  444. /* - SPICELIB Version 1.1.1, 05-SEP-1993 (KRG) */
  445. /* Removed all references to a specific method of opening the CK */
  446. /* file in the $ Brief_I/O, $ Detailed_Input, $ Exceptions, */
  447. /* $ Files, and $ Examples sections of the header. It is assumed */
  448. /* that a person using this routine has some knowledge of the DAF */
  449. /* system and the methods for obtaining file handles. */
  450. /* - SPICELIB Version 1.0.0, 25-NOV-1992 (JML) */
  451. /* -& */
  452. /* SPICELIB functions */
  453. /* Local parameters */
  454. /* SIDLEN is the maximum number of characters allowed in a CK */
  455. /* segment identifier. */
  456. /* NDC is the size of a packed CK segment descriptor. */
  457. /* ND is the number of double precision components in a CK */
  458. /* segment descriptor. */
  459. /* NI is the number of integer components in a CK segment */
  460. /* descriptor. */
  461. /* DTYPE is the data type of the segment that this routine */
  462. /* operates on. */
  463. /* FPRINT is the integer value of the first printable ASCII */
  464. /* character. */
  465. /* LPRINT is the integer value of the last printable ASCII */
  466. /* character. */
  467. /* Local variables */
  468. /* Standard SPICE error handling. */
  469. if (return_()) {
  470. return 0;
  471. }
  472. chkin_("CKW03", (ftnlen)5);
  473. /* The first thing that we will do is create the segment descriptor. */
  474. /* The structure of the segment descriptor is as follows. */
  475. /* DCD( 1 ) and DCD( 2 ) -- SCLK limits of the segment. */
  476. /* ICD( 1 ) -- Instrument code. */
  477. /* ICD( 2 ) -- Reference frame ID. */
  478. /* ICD( 3 ) -- Data type of the segment. */
  479. /* ICD( 4 ) -- Angular rates flag. */
  480. /* ICD( 5 ) -- Beginning address of segment. */
  481. /* ICD( 6 ) -- Ending address of segment. */
  482. /* Make sure that there is a positive number of pointing records. */
  483. if (*nrec <= 0) {
  484. setmsg_("# is an invalid number of pointing instances for type 3.", (
  485. ftnlen)56);
  486. errint_("#", nrec, (ftnlen)1);
  487. sigerr_("SPICE(INVALIDNUMREC)", (ftnlen)20);
  488. chkout_("CKW03", (ftnlen)5);
  489. return 0;
  490. }
  491. /* Make sure that there is a positive number of interpolation */
  492. /* intervals. */
  493. if (*nints <= 0) {
  494. setmsg_("# is an invalid number of interpolation intervals for type "
  495. "3.", (ftnlen)61);
  496. errint_("#", nints, (ftnlen)1);
  497. sigerr_("SPICE(INVALIDNUMINT)", (ftnlen)20);
  498. chkout_("CKW03", (ftnlen)5);
  499. return 0;
  500. }
  501. /* Check that the SCLK bounds on the segment are reasonable. */
  502. if (*begtim > sclkdp[0]) {
  503. setmsg_("The segment begin time is greater than the time associated "
  504. "with the first pointing instance in the segment. DCD(1) = # "
  505. "and SCLKDP(1) = # ", (ftnlen)137);
  506. errdp_("#", begtim, (ftnlen)1);
  507. errdp_("#", sclkdp, (ftnlen)1);
  508. sigerr_("SPICE(INVALIDDESCRTIME)", (ftnlen)23);
  509. chkout_("CKW03", (ftnlen)5);
  510. return 0;
  511. }
  512. if (*endtim < sclkdp[*nrec - 1]) {
  513. setmsg_("The segment end time is less than the time associated with "
  514. "the last pointing instance in the segment. DCD(2) = # and SC"
  515. "LKDP(#) = #", (ftnlen)130);
  516. errdp_("#", endtim, (ftnlen)1);
  517. errint_("#", nrec, (ftnlen)1);
  518. errdp_("#", &sclkdp[*nrec - 1], (ftnlen)1);
  519. sigerr_("SPICE(INVALIDDESCRTIME)", (ftnlen)23);
  520. chkout_("CKW03", (ftnlen)5);
  521. return 0;
  522. }
  523. dcd[0] = *begtim;
  524. dcd[1] = *endtim;
  525. /* Get the NAIF integer code for the reference frame. */
  526. namfrm_(ref, &refcod, ref_len);
  527. if (refcod == 0) {
  528. setmsg_("The reference frame # is not supported.", (ftnlen)39);
  529. errch_("#", ref, (ftnlen)1, ref_len);
  530. sigerr_("SPICE(INVALIDREFFRAME)", (ftnlen)22);
  531. chkout_("CKW03", (ftnlen)5);
  532. return 0;
  533. }
  534. /* Assign values to the integer components of the segment descriptor. */
  535. icd[0] = *inst;
  536. icd[1] = refcod;
  537. icd[2] = 3;
  538. if (*avflag) {
  539. icd[3] = 1;
  540. } else {
  541. icd[3] = 0;
  542. }
  543. /* Now pack the segment descriptor. */
  544. dafps_(&c__2, &c__6, dcd, icd, descr);
  545. /* Check that all the characters in the segid can be printed. */
  546. i__1 = lastnb_(segid, segid_len);
  547. for (i__ = 1; i__ <= i__1; ++i__) {
  548. value = *(unsigned char *)&segid[i__ - 1];
  549. if (value < 32 || value > 126) {
  550. setmsg_("The segment identifier contains nonprintable characters",
  551. (ftnlen)55);
  552. sigerr_("SPICE(NONPRINTABLECHARS)", (ftnlen)24);
  553. chkout_("CKW03", (ftnlen)5);
  554. return 0;
  555. }
  556. }
  557. /* Also check to see if the segment identifier is too long. */
  558. if (lastnb_(segid, segid_len) > 40) {
  559. setmsg_("Segment identifier contains more than 40 characters.", (
  560. ftnlen)52);
  561. sigerr_("SPICE(SEGIDTOOLONG)", (ftnlen)19);
  562. chkout_("CKW03", (ftnlen)5);
  563. return 0;
  564. }
  565. /* Now check that the encoded SCLK times are positive and strictly */
  566. /* increasing. */
  567. /* Check that the first time is nonnegative. */
  568. if (sclkdp[0] < 0.) {
  569. setmsg_("The first SCLKDP time: # is negative.", (ftnlen)37);
  570. errdp_("#", sclkdp, (ftnlen)1);
  571. sigerr_("SPICE(INVALIDSCLKTIME)", (ftnlen)22);
  572. chkout_("CKW03", (ftnlen)5);
  573. return 0;
  574. }
  575. /* Now check that the times are ordered properly. */
  576. i__1 = *nrec;
  577. for (i__ = 2; i__ <= i__1; ++i__) {
  578. if (sclkdp[i__ - 1] <= sclkdp[i__ - 2]) {
  579. setmsg_("The SCLKDP times are not strictly increasing. SCLKDP(#)"
  580. " = # and SCLKDP(#) = #.", (ftnlen)78);
  581. errint_("#", &i__, (ftnlen)1);
  582. errdp_("#", &sclkdp[i__ - 1], (ftnlen)1);
  583. i__2 = i__ - 1;
  584. errint_("#", &i__2, (ftnlen)1);
  585. errdp_("#", &sclkdp[i__ - 2], (ftnlen)1);
  586. sigerr_("SPICE(TIMESOUTOFORDER)", (ftnlen)22);
  587. chkout_("CKW03", (ftnlen)5);
  588. return 0;
  589. }
  590. }
  591. /* Now check that the start time of the first interval is the */
  592. /* same as the time of the first pointing instance. */
  593. if (sclkdp[0] != starts[0]) {
  594. setmsg_("The start time of the first interval # and the time of the "
  595. "first pointing instance # are not the same.", (ftnlen)102);
  596. errdp_("#", starts, (ftnlen)1);
  597. errdp_("#", sclkdp, (ftnlen)1);
  598. sigerr_("SPICE(TIMESDONTMATCH)", (ftnlen)21);
  599. chkout_("CKW03", (ftnlen)5);
  600. return 0;
  601. }
  602. /* Now check that the interval start times are ordered properly. */
  603. i__1 = *nints;
  604. for (i__ = 2; i__ <= i__1; ++i__) {
  605. if (starts[i__ - 1] <= starts[i__ - 2]) {
  606. setmsg_("The interval start times are not strictly increasing. S"
  607. "TARTS(#) = # and STARTS(#) = #.", (ftnlen)86);
  608. errint_("#", &i__, (ftnlen)1);
  609. errdp_("#", &starts[i__ - 1], (ftnlen)1);
  610. i__2 = i__ - 1;
  611. errint_("#", &i__2, (ftnlen)1);
  612. errdp_("#", &starts[i__ - 2], (ftnlen)1);
  613. sigerr_("SPICE(TIMESOUTOFORDER)", (ftnlen)22);
  614. chkout_("CKW03", (ftnlen)5);
  615. return 0;
  616. }
  617. }
  618. /* Now make sure that all of the interval start times coincide with */
  619. /* one of the times associated with the actual pointing. */
  620. index = 0;
  621. i__1 = *nints;
  622. for (i__ = 1; i__ <= i__1; ++i__) {
  623. match = FALSE_;
  624. while(! match && index < *nrec) {
  625. ++index;
  626. match = starts[i__ - 1] == sclkdp[index - 1];
  627. }
  628. if (! match) {
  629. setmsg_("Interval start time number # is invalid. STARTS(#) = *",
  630. (ftnlen)54);
  631. errint_("#", &i__, (ftnlen)1);
  632. errint_("#", &i__, (ftnlen)1);
  633. errdp_("*", &starts[i__ - 1], (ftnlen)1);
  634. sigerr_("SPICE(INVALIDSTARTTIME)", (ftnlen)23);
  635. chkout_("CKW03", (ftnlen)5);
  636. return 0;
  637. }
  638. }
  639. /* Make sure that the quaternions are non-zero. This is just */
  640. /* a check for uninitialized data. */
  641. i__1 = *nrec;
  642. for (i__ = 1; i__ <= i__1; ++i__) {
  643. if (vzerog_(&quats[(i__ << 2) - 4], &c__4)) {
  644. setmsg_("The quaternion at index # has magnitude zero.", (ftnlen)
  645. 45);
  646. errint_("#", &i__, (ftnlen)1);
  647. sigerr_("SPICE(ZEROQUATERNION)", (ftnlen)21);
  648. chkout_("CKW03", (ftnlen)5);
  649. return 0;
  650. }
  651. }
  652. /* No more checks, begin writing the segment. */
  653. dafbna_(handle, descr, segid, segid_len);
  654. if (failed_()) {
  655. chkout_("CKW03", (ftnlen)5);
  656. return 0;
  657. }
  658. /* Now add the quaternions and optionally, the angular velocity */
  659. /* vectors. */
  660. if (*avflag) {
  661. i__1 = *nrec;
  662. for (i__ = 1; i__ <= i__1; ++i__) {
  663. dafada_(&quats[(i__ << 2) - 4], &c__4);
  664. dafada_(&avvs[i__ * 3 - 3], &c__3);
  665. }
  666. } else {
  667. i__1 = *nrec << 2;
  668. dafada_(quats, &i__1);
  669. }
  670. /* Add the SCLK times. */
  671. dafada_(sclkdp, nrec);
  672. /* The time tag directory. The Ith element is defined to be the */
  673. /* (I*100)th SCLK time. */
  674. nrdir = (*nrec - 1) / 100;
  675. index = 100;
  676. i__1 = nrdir;
  677. for (i__ = 1; i__ <= i__1; ++i__) {
  678. dafada_(&sclkdp[index - 1], &c__1);
  679. index += 100;
  680. }
  681. /* Now add the interval start times. */
  682. dafada_(starts, nints);
  683. /* And the directory of interval start times. The directory of */
  684. /* start times will simply be every 100th start time. */
  685. nidir = (*nints - 1) / 100;
  686. index = 100;
  687. i__1 = nidir;
  688. for (i__ = 1; i__ <= i__1; ++i__) {
  689. dafada_(&starts[index - 1], &c__1);
  690. index += 100;
  691. }
  692. /* Finally, the number of intervals and records. */
  693. d__1 = (doublereal) (*nints);
  694. dafada_(&d__1, &c__1);
  695. d__1 = (doublereal) (*nrec);
  696. dafada_(&d__1, &c__1);
  697. /* End the segment. */
  698. dafena_();
  699. chkout_("CKW03", (ftnlen)5);
  700. return 0;
  701. } /* ckw03_ */