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