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