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 * ) °ree, 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