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