1 /*
2 
3 -Procedure ckw05_c ( Write CK segment, type 5 )
4 
5 -Abstract
6 
7    Write a type 5 segment to a CK file.
8 
9 -Disclaimer
10 
11    THIS SOFTWARE AND ANY RELATED MATERIALS WERE CREATED BY THE
12    CALIFORNIA INSTITUTE OF TECHNOLOGY (CALTECH) UNDER A U.S.
13    GOVERNMENT CONTRACT WITH THE NATIONAL AERONAUTICS AND SPACE
14    ADMINISTRATION (NASA). THE SOFTWARE IS TECHNOLOGY AND SOFTWARE
15    PUBLICLY AVAILABLE UNDER U.S. EXPORT LAWS AND IS PROVIDED "AS-IS"
16    TO THE RECIPIENT WITHOUT WARRANTY OF ANY KIND, INCLUDING ANY
17    WARRANTIES OF PERFORMANCE OR MERCHANTABILITY OR FITNESS FOR A
18    PARTICULAR USE OR PURPOSE (AS SET FORTH IN UNITED STATES UCC
19    SECTIONS 2312-2313) OR FOR ANY PURPOSE WHATSOEVER, FOR THE
20    SOFTWARE AND RELATED MATERIALS, HOWEVER USED.
21 
22    IN NO EVENT SHALL CALTECH, ITS JET PROPULSION LABORATORY, OR NASA
23    BE LIABLE FOR ANY DAMAGES AND/OR COSTS, INCLUDING, BUT NOT
24    LIMITED TO, INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND,
25    INCLUDING ECONOMIC DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS,
26    REGARDLESS OF WHETHER CALTECH, JPL, OR NASA BE ADVISED, HAVE
27    REASON TO KNOW, OR, IN FACT, SHALL KNOW OF THE POSSIBILITY.
28 
29    RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF
30    THE SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY
31    CALTECH AND NASA FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE
32    ACTIONS OF RECIPIENT IN THE USE OF THE SOFTWARE.
33 
34 -Required_Reading
35 
36    CK
37    NAIF_IDS
38    ROTATION
39    TIME
40 
41 -Keywords
42 
43    POINTING
44    FILES
45 
46 */
47 
48    #include "SpiceUsr.h"
49    #include "SpiceZfc.h"
50    #include "SpiceZst.h"
51    #include "SpiceZmc.h"
52    #undef ckw05_c
53 
54 
ckw05_c(SpiceInt handle,SpiceCK05Subtype subtyp,SpiceInt degree,SpiceDouble begtim,SpiceDouble endtim,SpiceInt inst,ConstSpiceChar * ref,SpiceBoolean avflag,ConstSpiceChar * segid,SpiceInt n,ConstSpiceDouble sclkdp[],const void * packts,SpiceDouble rate,SpiceInt nints,ConstSpiceDouble starts[])55    void ckw05_c ( SpiceInt            handle,
56                   SpiceCK05Subtype    subtyp,
57                   SpiceInt            degree,
58                   SpiceDouble         begtim,
59                   SpiceDouble         endtim,
60                   SpiceInt            inst,
61                   ConstSpiceChar    * ref,
62                   SpiceBoolean        avflag,
63                   ConstSpiceChar    * segid,
64                   SpiceInt            n,
65                   ConstSpiceDouble    sclkdp [],
66                   const void        * packts,
67                   SpiceDouble         rate,
68                   SpiceInt            nints,
69                   ConstSpiceDouble    starts []    )
70 
71 /*
72 
73 -Brief_I/O
74 
75    Variable  I/O  Description
76    --------  ---  --------------------------------------------------
77    handle     I   Handle of an open CK file.
78    subtyp     I   CK type 5 subtype code.
79    degree     I   Degree of interpolating polynomials.
80    begtim     I   The beginning encoded SCLK of the segment.
81    endtim     I   The ending encoded SCLK of the segment.
82    inst       I   The NAIF instrument ID code.
83    ref        I   The reference frame of the segment.
84    avflag     I   True if the segment will contain angular velocity.
85    segid      I   Segment identifier.
86    n          I   Number of packets.
87    sclkdp     I   Encoded SCLK times.
88    packts     I   Array of packets.
89    rate       I   Nominal SCLK rate in seconds per tick.
90    nints      I   Number of intervals.
91    starts     I   Encoded SCLK interval start times.
92    MAXDEG     P   Maximum allowed degree of interpolating polynomial.
93 
94 -Detailed_Input
95 
96 
97    handle     is the handle of the CK file to which the segment will be
98               written. The file must have been opened with write
99               access.
100 
101    subtyp     is an integer code indicating the subtype of the
102               segment to be created.
103 
104    degree     is the degree of the polynomials used to interpolate the
105               quaternions contained in the input packets.  All
106               components of the quaternions are interpolated by
107               polynomials of fixed degree.
108 
109    begtim,
110    endtim     are the beginning and ending encoded SCLK times
111               for which the segment provides pointing information.
112               begtim must be less than or equal to endtim, and at least
113               one data packet must have a time tag t such that
114 
115                         begtim  <  t  <  endtim
116                                 -     -
117 
118    inst       is the NAIF integer ID code for the instrument.
119 
120    ref        is a character string which specifies the
121               reference frame of the segment. This should be one of
122               the frames supported by the SPICELIB routine NAMFRM
123               which is an entry point of FRAMEX.
124 
125               The rotation matrices represented by the quaternions
126               that are to be written to the segment transform the
127               components of vectors from the inertial reference frame
128               specified by ref to components in the instrument fixed
129               frame. Also, the components of the angular velocity
130               vectors to be written to the segment should be given
131               with respect to ref.
132 
133               ref should be the name of one of the frames supported
134               by the SPICELIB routine NAMFRM.
135 
136 
137    avflag     is a boolean flag which indicates whether or not the
138               segment will contain angular velocity.
139 
140    segid      is the segment identifier.  A CK segment identifier may
141               contain up to 40 characters, excluding the terminating
142               null.
143 
144    packts     contains a time-ordered array of data packets
145               representing the orientation of inst relative to the
146               frame ref.  Each packet contains a SPICE-style quaternion
147               and optionally, depending on the segment subtype,
148               attitude derivative data, from which a C-matrix and an
149               angular velocity vector may be derived.
150 
151               See the discussion of "Quaternion Styles" in the
152               Particulars section below.
153 
154               The C-matrix represented by the Ith data packet is a
155               rotation matrix that transforms the components of a
156               vector expressed in the base frame specified by ref to
157               components expressed in the instrument fixed frame at the
158               time sclkdp(I).
159 
160               Thus, if a vector v has components x, y, z in the base
161               frame, then v has components x', y', z' in the instrument
162               fixed frame where:
163 
164                  [ x' ]     [          ] [ x ]
165                  | y' |  =  |   cmat   | | y |
166                  [ z' ]     [          ] [ z ]
167 
168 
169               The attitude derivative information in packts[i] gives
170               the angular velocity of the instrument fixed frame at
171               time sclkdp[i] with respect to the reference frame
172               specified by ref.
173 
174               The direction of an angular velocity vector gives the
175               right-handed axis about which the instrument fixed
176               reference frame is rotating. The magnitude of the vector
177               is the magnitude of the instantaneous velocity of the
178               rotation, in radians per second.
179 
180               Packet contents and the corresponding interpolation
181               methods depend on the segment subtype, and are as
182               follows:
183 
184                  Subtype 0:  Hermite interpolation, 8-element packets.
185                              Quaternion and quaternion derivatives
186                              only, no angular velocity vector provided.
187                              Quaternion elements are listed first,
188                              followed by derivatives. Angular velocity
189                              is derived from the quaternions and
190                              quaternion derivatives.
191 
192                  Subtype 1:  Lagrange interpolation, 4-element packets.
193                              Quaternion only. Angular velocity is
194                              derived by differentiating the
195                              interpolating polynomials.
196 
197                  Subtype 2:  Hermite interpolation, 14-element packets.
198                              Quaternion and angular angular velocity
199                              vector, as well as derivatives of each,
200                              are provided. The quaternion comes first,
201                              then quaternion derivatives, then angular
202                              velocity and its derivatives.
203 
204                  Subtype 3:  Lagrange interpolation, 7-element packets.
205                              Quaternion and angular velocity vector
206                              provided. The quaternion comes first.
207 
208               Angular velocity is always specified relative to the base
209               frame.
210 
211    rate       is the nominal rate of the spacecraft clock associated
212               with inst.  Units are seconds per tick.  rate is used to
213               scale angular velocity to radians/second.
214 
215    nints      is the number of intervals that the pointing instances
216               are partitioned into.
217 
218    starts     are the start times of each of the interpolation
219               intervals. These times must be strictly increasing and
220               must coincide with times for which the segment contains
221               pointing.
222 
223 -Detailed_Output
224 
225    None.  See Files section.
226 
227 -Parameters
228 
229    MAXDEG     is the maximum allowed degree of the interpolating
230               polynomial.  If the value of MAXDEG is increased, the
231               CSPICE routine ckpfs_ must be changed accordingly.  In
232               particular, the size of the record passed to ckrNN_ and
233               ckeNN_ must be increased, and comments describing the
234               record size must be changed.
235 
236 -Exceptions
237 
238    If any of the following exceptions occur, this routine will return
239    without creating a new segment.
240 
241    1)  If handle is not the handle of a C-kernel opened for writing
242        the error will be diagnosed by routines called by this
243        routine.
244 
245    2)  If the last non-blank character of segid occurs past index 40,
246        the error SPICE(SEGIDTOOLONG) is signaled.
247 
248    3)  If segid contains any nonprintable characters, the error
249        SPICE(NONPRINTABLECHARS) is signaled.
250 
251    4)  If the first encoded SCLK time is negative then the error
252        SPICE(INVALIDSCLKTIME) is signaled. If any subsequent times
253        are negative the error will be detected in exception (5).
254 
255    5)  If the encoded SCLK times are not strictly increasing,
256        the error SPICE(TIMESOUTOFORDER) is signaled.
257 
258    6)  If the name of the reference frame is not one of those
259        supported by the routine framex_, the error
260        SPICE(INVALIDREFFRAME) is signaled.
261 
262    7)  If the number of packets n is not at least 1, the error
263        SPICE(TOOFEWPACKETS) will be signaled.
264 
265    8)  If nints, the number of interpolation intervals, is less than
266        or equal to 0, the error SPICE(INVALIDNUMINTS) is signaled.
267 
268    9)  If the encoded SCLK interval start times are not strictly
269        increasing, the error SPICE(TIMESOUTOFORDER) is signaled.
270 
271   10)  If an interval start time does not coincide with a time for
272        which there is an actual pointing instance in the segment,
273        then the error SPICE(INVALIDSTARTTIME) is signaled.
274 
275   11)  This routine assumes that the rotation between adjacent
276        quaternions that are stored in the same interval has a
277        rotation angle of theta radians, where
278 
279           0  <  theta  <  pi.
280              _
281 
282        The routines that evaluate the data in the segment produced
283        by this routine cannot distinguish between rotations of theta
284        radians, where theta is in the interval [0, pi), and
285        rotations of
286 
287           theta   +   2 * k * pi
288 
289        radians, where k is any integer.  These "large" rotations will
290        yield invalid results when interpolated.  You must ensure that
291        the data stored in the segment will not be subject to this
292        sort of ambiguity.
293 
294   12)  If any quaternion is the zero vector, the error
295        SPICE(ZEROQUATERNION) is signaled.
296 
297   13)  If the interpolation window size implied by degree is not
298        even, the error SPICE(INVALIDDEGREE) is signaled.  The window
299        size is degree+1 for Lagrange subtypes and is (degree+1)/2
300        for Hermite subtypes.
301 
302   14)  If an unrecognized subtype code is supplied, the error
303        SPICE(NOTSUPPORTED) is signaled.
304 
305   15)  If degree is not at least 1 or is greater than MAXDEG, the
306        error SPICE(INVALIDDEGREE) is signaled.
307 
308   16)  If the segment descriptor bounds are out of order, the
309        error SPICE(BADDESCRTIMES) is signaled.
310 
311   17)  If there is no element of SCLKDP that lies between BEGTIM and
312        ENDTIM inclusive, the error SPICE(EMPTYSEGMENT) is signaled.
313 
314   18)  If RATE is zero, the error SPICE(INVALIDVALUE) is signaled.
315 
316   18)  If either the input frame or segment ID have null string
317        pointers, the error SPICE(NULLPOINTER) is signaled.
318 
319   19)  If either the input frame or segment ID are zero-length
320        strings, the error SPICE(EMPTYSTRING) is signaled.
321 
322 
323 -Files
324 
325    A new type 5 CK segment is written to the CK file attached
326    to handle.
327 
328 -Particulars
329 
330    This routine writes a CK type 5 data segment to the open CK
331    file according to the format described in the type 5 section of
332    the CK Required Reading. The CK file must have been opened with
333    write access.
334 
335 
336    Quaternion Styles
337    -----------------
338 
339    There are different "styles" of quaternions used in
340    science and engineering applications. Quaternion styles
341    are characterized by
342 
343       - The order of quaternion elements
344 
345       - The quaternion multiplication formula
346 
347       - The convention for associating quaternions
348         with rotation matrices
349 
350    Two of the commonly used styles are
351 
352       - "SPICE"
353 
354          > Invented by Sir William Rowan Hamilton
355          > Frequently used in mathematics and physics textbooks
356 
357       - "Engineering"
358 
359          > Widely used in aerospace engineering applications
360 
361 
362    CSPICE function interfaces ALWAYS use SPICE quaternions.
363    Quaternions of any other style must be converted to SPICE
364    quaternions before they are passed to CSPICE functions.
365 
366 
367    Relationship between SPICE and Engineering Quaternions
368    ------------------------------------------------------
369 
370    Let M be a rotation matrix such that for any vector V,
371 
372       M*V
373 
374    is the result of rotating V by theta radians in the
375    counterclockwise direction about unit rotation axis vector A.
376    Then the SPICE quaternions representing M are
377 
378       (+/-) (  cos(theta/2),
379                sin(theta/2) A(1),
380                sin(theta/2) A(2),
381                sin(theta/2) A(3)  )
382 
383    while the engineering quaternions representing M are
384 
385       (+/-) ( -sin(theta/2) A(1),
386               -sin(theta/2) A(2),
387               -sin(theta/2) A(3),
388                cos(theta/2)       )
389 
390    For both styles of quaternions, if a quaternion q represents
391    a rotation matrix M, then -q represents M as well.
392 
393    Given an engineering quaternion
394 
395       QENG   = ( q0,  q1,  q2,  q3 )
396 
397    the equivalent SPICE quaternion is
398 
399       QSPICE = ( q3, -q0, -q1, -q2 )
400 
401 
402    Associating SPICE Quaternions with Rotation Matrices
403    ----------------------------------------------------
404 
405    Let FROM and TO be two right-handed reference frames, for
406    example, an inertial frame and a spacecraft-fixed frame. Let the
407    symbols
408 
409       V    ,   V
410        FROM     TO
411 
412    denote, respectively, an arbitrary vector expressed relative to
413    the FROM and TO frames. Let M denote the transformation matrix
414    that transforms vectors from frame FROM to frame TO; then
415 
416       V   =  M * V
417        TO         FROM
418 
419    where the expression on the right hand side represents left
420    multiplication of the vector by the matrix.
421 
422    Then if the unit-length SPICE quaternion q represents M, where
423 
424       q = (q0, q1, q2, q3)
425 
426    the elements of M are derived from the elements of q as follows:
427 
428         +-                                                         -+
429         |           2    2                                          |
430         | 1 - 2*( q2 + q3 )   2*(q1*q2 - q0*q3)   2*(q1*q3 + q0*q2) |
431         |                                                           |
432         |                                                           |
433         |                               2    2                      |
434     M = | 2*(q1*q2 + q0*q3)   1 - 2*( q1 + q3 )   2*(q2*q3 - q0*q1) |
435         |                                                           |
436         |                                                           |
437         |                                                   2    2  |
438         | 2*(q1*q3 - q0*q2)   2*(q2*q3 + q0*q1)   1 - 2*( q1 + q2 ) |
439         |                                                           |
440         +-                                                         -+
441 
442    Note that substituting the elements of -q for those of q in the
443    right hand side leaves each element of M unchanged; this shows
444    that if a quaternion q represents a matrix M, then so does the
445    quaternion -q.
446 
447    To map the rotation matrix M to a unit quaternion, we start by
448    decomposing the rotation matrix as a sum of symmetric
449    and skew-symmetric parts:
450 
451                                       2
452       M = [ I  +  (1-cos(theta)) OMEGA  ] + [ sin(theta) OMEGA ]
453 
454                    symmetric                   skew-symmetric
455 
456 
457    OMEGA is a skew-symmetric matrix of the form
458 
459                  +-             -+
460                  |  0   -n3   n2 |
461                  |               |
462        OMEGA  =  |  n3   0   -n1 |
463                  |               |
464                  | -n2   n1   0  |
465                  +-             -+
466 
467    The vector N of matrix entries (n1, n2, n3) is the rotation axis
468    of M and theta is M's rotation angle.  Note that N and theta
469    are not unique.
470 
471    Let
472 
473       C = cos(theta/2)
474       S = sin(theta/2)
475 
476    Then the unit quaternions Q corresponding to M are
477 
478       Q = +/- ( C, S*n1, S*n2, S*n3 )
479 
480    The mappings between quaternions and the corresponding rotations
481    are carried out by the CSPICE routines
482 
483       q2m_c {quaternion to matrix}
484       m2q_c {matrix to quaternion}
485 
486    m2q_c always returns a quaternion with scalar part greater than
487    or equal to zero.
488 
489 
490    SPICE Quaternion Multiplication Formula
491    ---------------------------------------
492 
493    Given a SPICE quaternion
494 
495       Q = ( q0, q1, q2, q3 )
496 
497    corresponding to rotation axis A and angle theta as above, we can
498    represent Q using "scalar + vector" notation as follows:
499 
500       s =   q0           = cos(theta/2)
501 
502       v = ( q1, q2, q3 ) = sin(theta/2) * A
503 
504       Q = s + v
505 
506    Let Q1 and Q2 be SPICE quaternions with respective scalar
507    and vector parts s1, s2 and v1, v2:
508 
509       Q1 = s1 + v1
510       Q2 = s2 + v2
511 
512    We represent the dot product of v1 and v2 by
513 
514       <v1, v2>
515 
516    and the cross product of v1 and v2 by
517 
518       v1 x v2
519 
520    Then the SPICE quaternion product is
521 
522       Q1*Q2 = s1*s2 - <v1,v2>  + s1*v2 + s2*v1 + (v1 x v2)
523 
524    If Q1 and Q2 represent the rotation matrices M1 and M2
525    respectively, then the quaternion product
526 
527       Q1*Q2
528 
529    represents the matrix product
530 
531       M1*M2
532 
533 
534 -Examples
535 
536    This example code fragment writes a type 5 C-kernel segment
537    for the Mars Express spacecraft bus to a previously opened CK
538    file attached to handle.
539 
540       /.
541       Include CSPICE interface definitions.
542       ./
543       #include "SpiceUsr.h"
544                 .
545                 .
546                 .
547       /.
548       Assume arrays of quaternions, angular velocities, and the
549       associated SCLK times are produced elsewhere.  The software
550       that calls ckw05_c must then decide how to partition these
551       pointing instances into intervals over which linear
552       interpolation between adjacent points is valid.
553       ./
554                  .
555                  .
556                  .
557 
558       /.
559       The subroutine ckw05_c needs the following items for the
560       segment descriptor:
561 
562          1) SCLK limits of the segment.
563          2) Instrument code.
564          3) Reference frame.
565          4) The angular velocity flag.
566 
567       ./
568 
569       begtim = sclk [      0 ];
570       endtim = sclk [ nrec-1 ];
571 
572       inst   =  -41000;
573       ref    =  "J2000";
574       avflag =  SPICETRUE;
575 
576       segid  = "MEX spacecraft bus - data type 5";
577 
578       /.
579       Write the segment.
580       ./
581       ckw05_c ( handle,  subtyp,  degree,  begtim,  endtim,  inst,
582                 ref,     avflag,  segid,   n,       sclkdp,  packts,
583                 rate,    nints,   starts                             );
584                 .
585                 .
586                 .
587       /.
588       After all segments are written, close the C-kernel.
589       ./
590       ckcls_c ( handle );
591 
592 
593 -Restrictions
594 
595    None.
596 
597 -Literature_References
598 
599    None.
600 
601 -Author_and_Institution
602 
603    N.J. Bachman    (JPL)
604    W.L. Taber      (JPL)
605    K.R. Gehringer  (JPL)
606    J.M. Lynch      (JPL)
607 
608 -Version
609 
610    -CSPICE Version 2.0.0, 01-JUN-2010 (NJB)
611 
612       The check for non-unit quaternions has been replaced
613       with a check for zero-length quaternions. (The
614       implementation of the check is located in ckw05_.)
615 
616    -CSPICE Version 1.0.2, 27-FEB-2008 (NJB)
617 
618       Updated header; added information about SPICE
619       quaternion conventions.
620 
621    -CSPICE Version 1.0.1, 07-JAN-2005 (NJB)
622 
623       Description in Detailed_Input header section of
624       constraints on BEGTIM and ENDTIM was corrected
625 
626    -CSPICE Version 1.0.0, 30-AUG-2002 (NJB) (WLT) (KRG) (JML)
627 
628 -Index_Entries
629 
630    write ck type_5 data segment
631 
632 -&
633 */
634 
635 { /* Begin ckw05_c */
636 
637 
638 
639    /*
640    Local variables
641    */
642    logical                 avf;
643 
644    SpiceInt                locSubtype;
645 
646 
647 
648 
649    /*
650    Participate in error tracingx.
651    */
652    if ( return_c() )
653    {
654       return;
655    }
656    chkin_c ( "ckw05_c" );
657 
658 
659    /*
660    Check the input strings to make sure the pointers
661    are non-null and the string lengths are non-zero.
662    */
663    CHKFSTR ( CHK_STANDARD, "ckw05_c", ref   );
664    CHKFSTR ( CHK_STANDARD, "ckw05_c", segid );
665 
666 
667    /*
668    Get a type logical copy of the a.v. flag.  Get a type SpiceInt
669    copy of the CK type 5 subtype.
670    */
671    avf        = (logical)  avflag;
672 
673    locSubtype = (SpiceInt) subtyp;
674 
675 
676    /*
677    Write the segment.  Note that the packet array
678    DOES NOT require transposition!
679    */
680    ckw05_( ( integer    * ) &handle,
681            ( integer    * ) &locSubtype,
682            ( integer    * ) &degree,
683            ( doublereal * ) &begtim,
684            ( doublereal * ) &endtim,
685            ( integer    * ) &inst,
686            ( char       * ) ref,
687            ( logical    * ) &avf,
688            ( char       * ) segid,
689            ( integer    * ) &n,
690            ( doublereal * ) sclkdp,
691            ( doublereal * ) packts,
692            ( doublereal * ) &rate,
693            ( integer    * ) &nints,
694            ( doublereal * ) starts,
695            ( ftnlen       ) strlen(ref),
696            ( ftnlen       ) strlen(segid)  );
697 
698 
699    chkout_c ( "ckw05_c" );
700 
701 } /* End ckw05_c */
702