1 /* 2 3 -Procedure pxfrm2_c ( Position Transform Matrix, Different Epochs ) 4 5 -Abstract 6 7 Return the 3x3 matrix that transforms position vectors from one 8 specified frame at a specified epoch to another specified 9 frame at another specified epoch. 10 11 -Disclaimer 12 13 THIS SOFTWARE AND ANY RELATED MATERIALS WERE CREATED BY THE 14 CALIFORNIA INSTITUTE OF TECHNOLOGY (CALTECH) UNDER A U.S. 15 GOVERNMENT CONTRACT WITH THE NATIONAL AERONAUTICS AND SPACE 16 ADMINISTRATION (NASA). THE SOFTWARE IS TECHNOLOGY AND SOFTWARE 17 PUBLICLY AVAILABLE UNDER U.S. EXPORT LAWS AND IS PROVIDED "AS-IS" 18 TO THE RECIPIENT WITHOUT WARRANTY OF ANY KIND, INCLUDING ANY 19 WARRANTIES OF PERFORMANCE OR MERCHANTABILITY OR FITNESS FOR A 20 PARTICULAR USE OR PURPOSE (AS SET FORTH IN UNITED STATES UCC 21 SECTIONS 2312-2313) OR FOR ANY PURPOSE WHATSOEVER, FOR THE 22 SOFTWARE AND RELATED MATERIALS, HOWEVER USED. 23 24 IN NO EVENT SHALL CALTECH, ITS JET PROPULSION LABORATORY, OR NASA 25 BE LIABLE FOR ANY DAMAGES AND/OR COSTS, INCLUDING, BUT NOT 26 LIMITED TO, INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND, 27 INCLUDING ECONOMIC DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS, 28 REGARDLESS OF WHETHER CALTECH, JPL, OR NASA BE ADVISED, HAVE 29 REASON TO KNOW, OR, IN FACT, SHALL KNOW OF THE POSSIBILITY. 30 31 RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF 32 THE SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY 33 CALTECH AND NASA FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE 34 ACTIONS OF RECIPIENT IN THE USE OF THE SOFTWARE. 35 36 -Required_Reading 37 38 FRAMES 39 40 -Keywords 41 42 FRAMES 43 TRANSFORM 44 45 */ 46 47 #include "SpiceUsr.h" 48 #include "SpiceZfc.h" 49 #include "SpiceZmc.h" 50 #include "SpiceZst.h" 51 pxfrm2_c(ConstSpiceChar * from,ConstSpiceChar * to,SpiceDouble etfrom,SpiceDouble etto,SpiceDouble rotate[3][3])52 void pxfrm2_c ( ConstSpiceChar * from, 53 ConstSpiceChar * to, 54 SpiceDouble etfrom, 55 SpiceDouble etto, 56 SpiceDouble rotate[3][3] ) 57 58 /* 59 60 -Brief_I/O 61 62 VARIABLE I/O DESCRIPTION 63 -------- --- -------------------------------------------------- 64 from I Name of the frame to transform from. 65 to I Name of the frame to transform to. 66 etfrom I Evaluation time of `from' frame. 67 etto I Evaluation time of `to' frame. 68 rotate O A position transformation matrix from 69 frame `from' to frame `to'. 70 71 -Detailed_Input 72 73 from is the name of a reference frame recognized by 74 cspice that corresponds to the input `etfrom'. 75 76 77 to is the name of a reference frame recognized by 78 cspice that corresponds to the desired output 79 at `etto'. 80 81 82 etfrom is the epoch in ephemeris seconds past the epoch 83 of J2000 (TDB) corresponding to the `from' reference 84 frame. 85 86 87 etto is the epoch in ephemeris seconds past the epoch 88 of J2000 (TDB) that corresponds to the `to' reference 89 frame. 90 91 -Detailed_Output 92 93 rotate is the transformation matrix that relates the reference 94 frame `from' at epoch `etfrom' to the frame `to' at epoch 95 `etto'. 96 97 If (x, y, z) is a position relative to the reference 98 frame `from' at time `etfrom' then the vector ( x', y', 99 z') is the same position relative to the frame `to' at 100 epoch `etto'. Here the vector ( x', y', z' ) is defined 101 by the equation: 102 103 - - - - - - 104 | x' | | | | x | 105 | y' | = | rotate | | y | 106 | z' | | | | z | 107 - - - - - - 108 -Parameters 109 110 None. 111 112 113 -Exceptions 114 115 1) If sufficient information has not been supplied via loaded 116 SPICE kernels to compute the transformation between the 117 two frames, the error will be diagnosed by a routine 118 in the call tree to this routine. 119 120 2) If either frame `from' or `to' is not recognized the error 121 'SPICE(UNKNOWNFRAME)' will be signaled. 122 123 -Files 124 125 Appropriate kernels must be loaded by the calling program before 126 this routine is called. Kernels that may be required include 127 SPK files, PCK files, frame kernels, C-kernels, and SCLK kernels. 128 129 Such kernel data are normally loaded once per program 130 run, NOT every time this routine is called. 131 132 -Particulars 133 134 The routine `pxfrm2_c' is most commonly used to transform a 135 position between time-dependant reference frames. 136 137 For more examples of where to use `pxfrm2_c', please see: 138 139 sincpt_c 140 surfpt_c 141 subslr_c 142 ilumin_c 143 144 -Examples 145 146 The numerical results shown for these examples may differ across 147 platforms. The results depend on the SPICE kernels used as 148 input, the compiler and supporting libraries, and the machine 149 specific arithmetic implementation. 150 151 1) Suppose that MGS has taken a picture of Mars at time `etrec' with 152 the MOC narrow angle camera. We want to know the latitude and 153 longitude associated with two pixels projected to Mars' 154 surface: the boresight and one along the boundary of the 155 field of view (FOV). Due to light time, the photons taken in 156 the picture left Mars at time `etemit', when Mars was at a 157 different state than at time `etrec'. 158 159 In order to solve this problem, we could use the `sincpt_c' 160 routine for both pixels, but this would be slow. Instead, we 161 will assume that the light time for each pixel is the same. We 162 will call `sincpt_c' once to get the light time and surface point 163 associated with the boresight. Then, we will rotate one of the 164 FOV boundary vectors from the camera frame at `etrec' to the 165 body-fixed Mars frame at `etemit', and call the faster routine 166 `surfpt_c' to retrieve the surface point for one of the FOV 167 boundary vectors. 168 169 This example problem could be extended to find the latitude 170 and longitude associated with every pixel in an instrument's 171 field of view, but this example is simplified to only solve 172 for two pixels: the boresight and one along the boundary of 173 the field of view. 174 175 Assumptions: 176 177 1) The light times from the surface points in the camera's 178 field of view to the camera are equal. 179 180 2) The camera offset from the center of gravity of the 181 spacecraft is zero. If the data are more accurate 182 and precise, this assumption can be easily discarded. 183 184 3) An ellipsoid shape model for the target body is 185 sufficient. 186 187 4) The boundary field of view vector returned from `getfov_c' 188 is associated with a boundary field of view pixel. If 189 this example were extended to include a geometric camera 190 model, this assumption would not be needed since the 191 direction vectors associated with each pixel would be 192 calculated from the geometric camera model. 193 194 Use the meta-kernel shown below to load the required SPICE 195 kernels. 196 197 KPL/MK 198 199 File name: mgs_ex.tm 200 201 This is the meta-kernel file for the example problem for 202 the subroutine PXFRM2. These kernel files can be found in 203 the NAIF archives. 204 205 In order for an application to use this meta-kernel, the 206 kernels referenced here must be present in the user's 207 current working directory. 208 209 The names and contents of the kernels referenced 210 by this meta-kernel are as follows: 211 212 File name Contents 213 --------- -------- 214 de421.bsp Planetary ephemeris 215 pck00009.tpc Planet orientation and 216 radii 217 naif0009.tls Leapseconds 218 mgs_ext12_ipng_mgs95j.bsp MGS ephemeris 219 mgs_moc_v20.ti MGS MOC instrument 220 parameters 221 mgs_sclkscet_00061.tsc MGS SCLK coefficients 222 mgs_sc_ext12.bc MGS s/c bus attitude 223 224 \begindata 225 226 KERNELS_TO_LOAD = ( 'de421.bsp', 227 'pck00009.tpc', 228 'naif0009.tls', 229 'mgs_ext12_ipng_mgs95j.bsp', 230 'mgs_moc_v20.ti', 231 'mgs_sclkscet_00061.tsc', 232 'mgs_sc_ext12.bc' ) 233 234 \begintext 235 236 End of meta-kernel. 237 238 Example code begins here. 239 240 #include <stdio.h> 241 #include <math.h> 242 #include "SpiceUsr.h" 243 244 int main() 245 { 246 /. 247 Constants 248 249 ABCORR is the desired light time and stellar 250 aberration correction setting. 251 252 METAKR is the name of the meta-kernel. 253 ./ 254 255 #define ABCORR "CN+S" 256 #define METAKR "mgs_ex.tm" 257 #define FRMNLN 32 258 #define NCORNR 4 259 #define SHPLEN 80 260 261 /. 262 Local variables 263 ./ 264 SpiceBoolean found; 265 266 /. 267 MGS_MOC_NA is the name of the camera that took 268 the picture being analyzed. 269 ./ 270 SpiceChar *camera = "MGS_MOC_NA"; 271 272 /. 273 The variable `obsref' is the observer reference frame 274 on MGS. 275 ./ 276 SpiceChar obsref [FRMNLN] ; 277 SpiceChar shape [SHPLEN] ; 278 279 SpiceDouble bounds [NCORNR][3]; 280 SpiceDouble bndvec [3]; 281 SpiceDouble bsight [3]; 282 SpiceDouble dist; 283 284 /. 285 The variable `etemit' is the time at which the photons were 286 emitted from Mars, and `etrec' is the time at 287 which the picture was taken by MGS. 288 ./ 289 SpiceDouble etemit; 290 SpiceDouble etrec; 291 292 /. 293 The variables `lat' and `lon' and the latitude and longitude 294 associated with one of the boundary FOV vectors. 295 ./ 296 SpiceDouble lat; 297 SpiceDouble lon; 298 299 /. 300 The variable `pmgsmr' is the opposite of the apparent 301 position of Mars with respect to MGS. 302 ./ 303 SpiceDouble pmgsmr [3]; 304 305 /. 306 The variable `radii' is a vector of the semi-axes of Mars. 307 ./ 308 SpiceDouble radii [3]; 309 SpiceDouble radius; 310 311 /. 312 The variable `rotate' is a position transformation matrix 313 from the camera frame at `etrec' to the IAU_MARS frame 314 at `etemit'. 315 ./ 316 SpiceDouble rotate [3][3]; 317 SpiceDouble spoint [3]; 318 SpiceDouble srfvec [3]; 319 SpiceDouble tmp [3]; 320 321 SpiceInt camid; 322 SpiceInt dim; 323 SpiceInt n; 324 325 326 /. ------------------ Program Setup ------------------ 327 328 Load kernels. 329 ./ 330 furnsh_c ( METAKR ); 331 332 /. 333 Convert the time the picture was taken from a 334 UTC time string to seconds past J2000, TDB. 335 ./ 336 str2et_c ( "2003 OCT 13 06:00:00 UTC", &etrec ); 337 338 /. 339 Assume the one-way light times from different 340 surface points on Mars to MGS within the camera's 341 FOV are equal. This means the photons that make 342 up different pixels were all emitted from Mars at 343 `etemit' and received by the MGS MOC camera at `etrec'. It 344 would be slow to process images using `sincpt_c' for every 345 pixel. Instead, we will use `sincpt_c' on the 346 boresight pixel and use `surfpt_c' for one of the FOV 347 boundary pixels. If this example program were extended 348 to include all of the camera's pixels, `surfpt_c' would 349 be used for the remaining pixels. 350 351 Get the MGS MOC Narrow angle camera (MGS_MOC_NA) 352 ID code. Then look up the field of view (FOV) 353 parameters by calling `getfov_c'. 354 ./ 355 356 bodn2c_c ( camera, &camid, &found ); 357 if ( !found ) 358 { 359 setmsg_c ("Could not find ID code for instrument #." ); 360 errch_c ("#", camera ); 361 sigerr_c ("SPICE(NOTRANSLATION)"); 362 } 363 364 /. 365 `getfov_c' will return the name of the camera-fixed frame 366 in the string `obsref', the camera boresight vector in 367 the array `bsight', and the FOV corner vectors in the 368 array `bounds'. 369 ./ 370 371 getfov_c ( camid, NCORNR, SHPLEN, FRMNLN, shape, 372 obsref, bsight, &n, bounds ); 373 374 printf( "Observation Reference Frame: %s\n", obsref ); 375 376 /. ----------- Boresight Surface Intercept ----------- 377 378 Retrieve the time, surface intercept point, and vector 379 from MGS to the boresight surface intercept point 380 in IAU_MARS coordinates. 381 ./ 382 sincpt_c ( "Ellipsoid", "Mars", etrec, "IAU_MARS", 383 ABCORR, "MGS", obsref, 384 bsight, spoint, &etemit, srfvec, &found ); 385 if ( !found ) 386 { 387 setmsg_c("Intercept not found for the boresight vector."); 388 sigerr_c("SPICE(NOINTERCEPT)"); 389 } 390 391 /. 392 Convert the intersection point of the boresight 393 vector and Mars from rectangular into latitudinal 394 coordinates. Convert radians to degrees. 395 ./ 396 reclat_c ( spoint, &radius, &lon, &lat ); 397 398 lon *= dpr_c(); 399 lat *= dpr_c(); 400 401 printf( "Boresight surface intercept coordinates:\n" 402 " Radius (km) : %f\n" 403 " Latitude (deg): %f\n" 404 " Longitude (deg): %f\n", 405 radius, lat, lon ); 406 407 /.---- A Boundary FOV Surface Intercept (`surfpt_c') ----- 408 409 Now we will transform one of the FOV corner vectors into the 410 IAU_MARS frame so the surface intercept point can be 411 calculated using surfpt_c, which is faster than subpnt_c. 412 413 If this example program were extended to include all 414 of the pixels in the camera's FOV, a few steps, such as 415 finding the rotation matrix from the camera frame to the 416 IAU_MARS frame, looking up the radii values for Mars, 417 and finding the position of MGS with respect to Mars could 418 be done once and used for every pixel. 419 420 Find the rotation matrix from the ray's reference 421 frame at the time the photons were received (etrec) 422 to IAU_MARS at the time the photons were emitted 423 (etemit). 424 ./ 425 pxfrm2_c ( obsref, "IAU_MARS", etrec, etemit, rotate ); 426 427 /. 428 Look up the radii values for Mars. 429 ./ 430 bodvrd_c ( "MARS", "RADII", 3, &dim, radii ); 431 432 /. 433 Find the position of the center of Mars with respect 434 to MGS. The position of the observer with respect 435 to Mars is required for the call to `surfpt_c'. Note: 436 the apparent position of MGS with respect to Mars is 437 not the same as the negative of Mars with respect to MGS. 438 ./ 439 vsub_c ( spoint, srfvec, pmgsmr ); 440 441 /. 442 The selected boundary FOV pixel must be rotated into the 443 IAU_MARS reference frame. 444 ./ 445 mxv_c ( rotate, bounds[1], bndvec ); 446 447 /. 448 Calculate the surface point of the boundary FOV 449 vector. 450 ./ 451 surfpt_c ( pmgsmr, bndvec, radii[0], radii[1], radii[2], 452 spoint, &found ); 453 454 if ( !found ) 455 { 456 setmsg_c ("Could not calculate surface point."); 457 sigerr_c ("SPICE(NOTFOUND)"); 458 } 459 vequ_c ( spoint, tmp ); 460 461 /. 462 Convert the intersection point of the boundary 463 FOV vector and Mars from rectangular into 464 latitudinal coordinates. Convert radians 465 to degrees. 466 ./ 467 reclat_c ( spoint, &radius, &lon, &lat ); 468 469 lon *= dpr_c(); 470 lat *= dpr_c(); 471 472 printf( "Boundary vector surface intercept coordinates " 473 "using SURFPT:\n" 474 " Radius (km) : %f\n" 475 " Latitude (deg): %f\n" 476 " Longitude (deg): %f\n" 477 " Emit time using boresight LT (s): %10.8f\n", 478 radius, lat, lon, etemit); 479 480 /. ---- A Boundary FOV Surface Intercept Verification ---- 481 482 For verification only, we will calculate the surface 483 intercept coordinates for the selected boundary vector using 484 `sincpt_c' and compare to the faster `surfpt_c' method. 485 ./ 486 sincpt_c ( "Ellipsoid", "Mars", etrec, "IAU_MARS", 487 ABCORR, "MGS", obsref, bounds[1], 488 spoint, &etemit, srfvec, &found ); 489 490 if ( !found ) 491 { 492 setmsg_c("Intercept not found for the boresight vector."); 493 sigerr_c("SPICE(NOINTERCEPT)"); 494 } 495 496 /. 497 Convert the intersection point of the selected boundary 498 vector and Mars from rectangular into latitudinal 499 coordinates. Convert radians to degrees. 500 ./ 501 reclat_c ( spoint, &radius, &lon, &lat ); 502 503 lon *= dpr_c(); 504 lat *= dpr_c(); 505 506 printf( "Boundary vector surface intercept coordinates " 507 "using surfpt_c:\n" 508 " Radius (km) : %f\n" 509 " Latitude (deg): %f\n" 510 " Longitude (deg): %f\n" 511 " Emit time using boundary LT (s): %10.8f\n", 512 radius, lat, lon, etemit); 513 514 /. 515 We expect this to be a very small distance. 516 ./ 517 dist = vdist_c ( tmp, spoint ); 518 519 printf( "Distance between surface points of the selected " 520 "boundary vector using surfpt_c and sincpt_c:\n" 521 " Distance (mm): %f\n", dist*pow(10,6) ); 522 523 return(0); 524 525 } 526 527 When this program was executed using gcc on a PC Linux 528 64 bit environment, the output was: 529 530 Observation Reference Frame: MGS_MOC_NA 531 Boresight surface intercept coordinates: 532 Radius (km) : 3384.940410 533 Latitude (deg): -48.479580 534 Longitude (deg): -123.436454 535 Boundary vector surface intercept coordinates using surfpt_c: 536 Radius (km) : 3384.939699 537 Latitude (deg): -48.481636 538 Longitude (deg): -123.398822 539 Emit time using boresight LT (s): 119296864.18105948 540 Boundary vector surface intercept coordinates using surfpt_c: 541 Radius (km) : 3384.939699 542 Latitude (deg): -48.481636 543 Longitude (deg): -123.398823 544 Emit time using boundary LT (s): 119296864.18105949 545 Distance between surface points of the selected boundary vector 546 using surfpt_c and sincpt_c: 547 Distance (mm): 32.642059 548 549 550 -Restrictions 551 552 None. 553 554 -Literature_References 555 556 None. 557 558 -Author_and_Institution 559 560 S. C. Krening (JPL) 561 W. L. Taber (JPL) 562 563 -Version 564 565 -CSPICE Version 1.0.0 1-FEB-2012 (SCK) (WLT) 566 567 -Index_Entries 568 569 Position transformation matrix for different epochs 570 571 -& 572 */ 573 574 { /* Begin pxfrm2_c */ 575 576 /* 577 Static local variables 578 */ 579 580 /* 581 Local variables 582 */ 583 584 /* 585 Participate in error tracing. 586 */ 587 if ( return_c() ) 588 { 589 return; 590 } 591 chkin_c ( "pxfrm2_c" ); 592 593 /* 594 Check the input strings to make sure the pointers are non-null 595 and the string lengths are non-zero. 596 */ 597 CHKFSTR ( CHK_STANDARD, "pxfrm2_c", from ); 598 CHKFSTR ( CHK_STANDARD, "pxfrm2_c", to ); 599 600 /* 601 Call the f2c'd routine. 602 */ 603 pxfrm2_ ( ( char * ) from, 604 ( char * ) to, 605 ( doublereal * ) &etfrom, 606 ( doublereal * ) &etto, 607 ( doublereal * ) rotate, 608 ( ftnlen ) strlen(from), 609 ( ftnlen ) strlen(to) ); 610 611 /* 612 Transpose the output to obtain row-major order. 613 */ 614 xpose_c ( rotate, rotate ); 615 616 617 chkout_c ( "pxfrm2_c" ); 618 619 } /* End pxfrm2_c */ 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640