1 /*
2 
3 -Procedure spkcvo_c ( SPK, constant velocity observer state )
4 
5 -Abstract
6 
7    Return the state of a specified target relative to an "observer,"
8    where the observer has constant velocity in a specified reference
9    frame.  The observer's state is provided by the calling program
10    rather than by loaded SPK files.
11 
12 -Disclaimer
13 
14    THIS SOFTWARE AND ANY RELATED MATERIALS WERE CREATED BY THE
15    CALIFORNIA INSTITUTE OF TECHNOLOGY (CALTECH) UNDER A U.S.
16    GOVERNMENT CONTRACT WITH THE NATIONAL AERONAUTICS AND SPACE
17    ADMINISTRATION (NASA). THE SOFTWARE IS TECHNOLOGY AND SOFTWARE
18    PUBLICLY AVAILABLE UNDER U.S. EXPORT LAWS AND IS PROVIDED "AS-IS"
19    TO THE RECIPIENT WITHOUT WARRANTY OF ANY KIND, INCLUDING ANY
20    WARRANTIES OF PERFORMANCE OR MERCHANTABILITY OR FITNESS FOR A
21    PARTICULAR USE OR PURPOSE (AS SET FORTH IN UNITED STATES UCC
22    SECTIONS 2312-2313) OR FOR ANY PURPOSE WHATSOEVER, FOR THE
23    SOFTWARE AND RELATED MATERIALS, HOWEVER USED.
24 
25    IN NO EVENT SHALL CALTECH, ITS JET PROPULSION LABORATORY, OR NASA
26    BE LIABLE FOR ANY DAMAGES AND/OR COSTS, INCLUDING, BUT NOT
27    LIMITED TO, INCIDENTAL OR CONSEQUENTIAL DAMAGES OF ANY KIND,
28    INCLUDING ECONOMIC DAMAGE OR INJURY TO PROPERTY AND LOST PROFITS,
29    REGARDLESS OF WHETHER CALTECH, JPL, OR NASA BE ADVISED, HAVE
30    REASON TO KNOW, OR, IN FACT, SHALL KNOW OF THE POSSIBILITY.
31 
32    RECIPIENT BEARS ALL RISK RELATING TO QUALITY AND PERFORMANCE OF
33    THE SOFTWARE AND ANY RELATED MATERIALS, AND AGREES TO INDEMNIFY
34    CALTECH AND NASA FOR ALL THIRD-PARTY CLAIMS RESULTING FROM THE
35    ACTIONS OF RECIPIENT IN THE USE OF THE SOFTWARE.
36 
37 -Required_Reading
38 
39    FRAMES
40    PCK
41    SPK
42    TIME
43 
44 -Keywords
45 
46    EPHEMERIS
47 
48 */
49 
50    #include "SpiceUsr.h"
51    #include "SpiceZfc.h"
52    #include "SpiceZst.h"
53    #include "SpiceZmc.h"
54    #undef   spkcvo_c
55 
56 
spkcvo_c(ConstSpiceChar * target,SpiceDouble et,ConstSpiceChar * outref,ConstSpiceChar * refloc,ConstSpiceChar * abcorr,ConstSpiceDouble obssta[6],SpiceDouble obsepc,ConstSpiceChar * obsctr,ConstSpiceChar * obsref,SpiceDouble state[6],SpiceDouble * lt)57    void spkcvo_c ( ConstSpiceChar       * target,
58                    SpiceDouble            et,
59                    ConstSpiceChar       * outref,
60                    ConstSpiceChar       * refloc,
61                    ConstSpiceChar       * abcorr,
62                    ConstSpiceDouble       obssta [6],
63                    SpiceDouble            obsepc,
64                    ConstSpiceChar       * obsctr,
65                    ConstSpiceChar       * obsref,
66                    SpiceDouble            state  [6],
67                    SpiceDouble          * lt         )
68 /*
69 
70 -Brief_I/O
71 
72    Variable  I/O  Description
73    --------  ---  --------------------------------------------------
74    target     I   Name of target ephemeris object.
75    et         I   Observation epoch.
76    outref     I   Reference frame of output state.
77    refloc     I   Output reference frame evaluation locus.
78    abcorr     I   Aberration correction.
79    obssta     I   Observer state relative to center of motion.
80    obsepc     I   Epoch of observer state.
81    obsctr     I   Center of motion of observer.
82    obsref     I   Frame of observer state.
83    state      O   State of target with respect to observer.
84    lt         O   One way light time between target and
85                   observer.
86 
87 -Detailed_Input
88 
89    target      is the name of a target body. Optionally, you may supply
90                the ID code of the object as an integer string. For
91                example, both "EARTH" and "399" are legitimate strings
92                to supply to indicate the target is earth.
93 
94                Case and leading and trailing blanks are not significant
95                in the string `target'.
96 
97 
98    et          is the ephemeris time at which the state of the target
99                relative to the observer is to be computed. `et' is
100                expressed as seconds past J2000 TDB. `et' refers to time
101                at the observer's location.
102 
103                `et' is independent of the observer epoch `obsepc'.
104 
105 
106    outref      is the name of the reference frame with respect to which
107                the output state is expressed.
108 
109                When `outref' is time-dependent (non-inertial), its
110                orientation relative to the J2000 frame is evaluated in
111                the manner commanded by the input argument `refloc' (see
112                description below).
113 
114                Case and leading and trailing blanks are not significant
115                in the string `outref'.
116 
117 
118    refloc      is a string indicating the output reference frame
119                evaluation locus: this is the location associated
120                with the epoch at which this routine is to evaluate
121                the orientation, relative to the J2000 frame, of the
122                output frame `outref'. The values and meanings of
123                `refloc' are:
124 
125                   "OBSERVER"  Evaluate `outref' at the observer's
126                               epoch `et'.
127 
128                               Normally the locus "OBSERVER" should
129                               be selected when `outref' is centered
130                               at the observer.
131 
132 
133                   "TARGET"    Evaluate `outref' at the target epoch;
134                               letting `lt' be the one-way light time
135                               between the target and observer, the
136                               target epoch is
137 
138                                  et-lt  if reception aberration
139                                         corrections are used
140 
141                                  et+lt  if transmission aberration
142                                         corrections are used
143 
144                                  et     if no aberration corrections
145                                         are used
146 
147                               Normally the locus "TARGET" should
148                               be selected when `outref' is centered
149                               at the target object.
150 
151 
152                   "CENTER"    Evaluate the frame `outref' at the epoch
153                               associated its center. This epoch,
154                               which we'll call `etctr', is determined
155                               as follows:
156 
157                                  Let `ltctr' be the one-way light time
158                                  between the observer and the center
159                                  of `outref'. Then `etctr' is
160 
161                                     et-ltctr  if reception
162                                               aberration corrections
163                                               are used
164 
165                                     et+ltctr  if transmission
166                                               aberration corrections
167                                               are used
168 
169                                     et        if no aberration
170                                               corrections are used
171 
172 
173                               The locus "CENTER" should be selected
174                               when the user intends to obtain
175                               results compatible with those produced
176                               by spkezr_c.
177 
178                When `outref' is inertial, all choices of `refloc'
179                yield the same results.
180 
181                Case and leading and trailing blanks are not
182                significant in the string `refloc'.
183 
184 
185    abcorr      indicates the aberration corrections to be applied to
186                the observer-target state to account for one-way
187                light time and stellar aberration.
188 
189                `abcorr' may be any of the following:
190 
191                   "NONE"     Apply no correction. Return the
192                              geometric state of the target
193                              relative to the observer.
194 
195                The following values of `abcorr' apply to the
196                "reception" case in which photons depart from the
197                target's location at the light-time corrected epoch
198                et-lt and *arrive* at the observer's location at `et':
199 
200                   "LT"       Correct for one-way light time (also
201                              called "planetary aberration") using a
202                              Newtonian formulation. This correction
203                              yields the state of the target at the
204                              moment it emitted photons arriving at
205                              the observer at `et'.
206 
207                              The light time correction uses an
208                              iterative solution of the light time
209                              equation. The solution invoked by the
210                              "LT" option uses one iteration.
211 
212                   "LT+S"     Correct for one-way light time and
213                              stellar aberration using a Newtonian
214                              formulation. This option modifies the
215                              state obtained with the "LT" option to
216                              account for the observer's velocity
217                              relative to the solar system
218                              barycenter. The result is the apparent
219                              state of the target---the position and
220                              velocity of the target as seen by the
221                              observer.
222 
223                   "CN"       Converged Newtonian light time
224                              correction. In solving the light time
225                              equation, the "CN" correction iterates
226                              until the solution converges.
227 
228                   "CN+S"     Converged Newtonian light time
229                              and stellar aberration corrections.
230 
231 
232                The following values of `abcorr' apply to the
233                "transmission" case in which photons *depart* from
234                the observer's location at `et' and arrive at the
235                target's location at the light-time corrected epoch
236                et+lt:
237 
238                   "XLT"      "Transmission" case:  correct for
239                              one-way light time using a Newtonian
240                              formulation. This correction yields the
241                              state of the target at the moment it
242                              receives photons emitted from the
243                              observer's location at `et'.
244 
245                   "XLT+S"    "Transmission" case:  correct for
246                              one-way light time and stellar
247                              aberration using a Newtonian
248                              formulation  This option modifies the
249                              state obtained with the "XLT" option to
250                              account for the observer's velocity
251                              relative to the solar system
252                              barycenter. The position component of
253                              the computed target state indicates the
254                              direction that photons emitted from the
255                              observer's location must be "aimed" to
256                              hit the target.
257 
258                   "XCN"      "Transmission" case:  converged
259                              Newtonian light time correction.
260 
261                   "XCN+S"    "Transmission" case:  converged
262                              Newtonian light time and stellar
263                              aberration corrections.
264 
265 
266                Neither special nor general relativistic effects are
267                accounted for in the aberration corrections applied
268                by this routine.
269 
270                Case and leading and trailing blanks are not
271                significant in the string `abcorr'.
272 
273 
274    obssta      is the geometric state of an observer moving at
275                constant velocity relative to its center of motion
276                `obsctr', expressed in the reference frame `obsref', at
277                the epoch `obsepc'.
278 
279                `obssta' is a six-dimensional vector representing
280                position and velocity in cartesian coordinates: the
281                first three components represent the position of an
282                observer relative to its center of motion; the last
283                three components represent the velocity of the
284                observer.
285 
286                Units are always km and km/sec.
287 
288 
289    obsepc      is the epoch, expressed as seconds past J2000 TDB, at
290                which the observer state `obssta' is applicable. For
291                other epochs, the position of the observer relative
292                to its center of motion is linearly extrapolated
293                using the velocity component of `obssta'.
294 
295                `obsepc' is independent of the epoch `et' at which the
296                state of the target relative to the observer is to be
297                computed.
298 
299    obsctr      is the name of the center of motion of `obssta'. The
300                ephemeris of `obsctr' is provided by loaded SPK files.
301 
302                Optionally, you may supply the integer ID code for
303                the object as an integer string. For example both
304                "MOON" and "301" are legitimate strings that indicate
305                the moon is the center of motion.
306 
307                Case and leading and trailing blanks are not
308                significant in the string `obsctr'.
309 
310 
311    obsref      is the name of the reference frame relative to which
312                the input state `obssta' is expressed. The observer has
313                constant velocity relative to its center of motion
314                in this reference frame.
315 
316                Case and leading and trailing blanks are not
317                significant in the string `obsref'.
318 
319 
320 -Detailed_Output
321 
322 
323    state       is a Cartesian state vector representing the position
324                and velocity of the target relative to the specified
325                observer. `state' is corrected for the specified
326                aberrations and is expressed with respect to the
327                reference frame specified by `outref'. The first three
328                components of `state' represent the x-, y- and
329                z-components of the target's position; the last three
330                components form the corresponding velocity vector.
331 
332                The position component of `state' points from the
333                observer's location at `et' to the aberration-corrected
334                location of the target. Note that the sense of the
335                position vector is independent of the direction of
336                radiation travel implied by the aberration
337                correction.
338 
339                The velocity component of `state' is the derivative
340                with respect to time of the position component of
341                `state'.
342 
343                Units are always km and km/sec.
344 
345                When `state' is expressed in a time-dependent
346                (non-inertial) output frame, the orientation of that
347                frame relative to the J2000 frame is evaluated in the
348                manner indicated by the input argument `refloc' (see
349                description above).
350 
351 
352    lt          is the one-way light time between the observer and
353                target in seconds. If the target state is corrected
354                for aberrations, then `lt' is the one-way light time
355                between the observer and the light time corrected
356                target location.
357 
358 
359 -Parameters
360 
361    None.
362 
363 -Exceptions
364 
365    1)  If either the name of the center of motion or the target
366        cannot be translated to its NAIF ID code, the error
367        SPICE(IDCODENOTFOUND) is signaled.
368 
369    2)  If the reference frame `outref' is unrecognized, the error
370        SPICE(IDCODENOTFOUND) is signaled.
371 
372    3)  If the reference frame `obsref' is unrecognized, the error will
373        be diagnosed by a routine in the call tree of this routine.
374 
375    4)  If the frame evaluation locus `refloc' is not recognized,
376        the error SPICE(NOTSUPPORTED) is signaled.
377 
378    5)  If the loaded kernels provide insufficient data to compute
379        the requested state vector, the deficiency will be diagnosed
380        by a routine in the call tree of this routine.
381 
382    6)  If an error occurs while reading an SPK or other kernel file,
383        the error  will be diagnosed by a routine in the call tree of
384        this routine.
385 
386    7)  If the aberration correction `abcorr' is not recognized,
387        the error will be diagnosed by a routine in the call tree of
388        this routine.
389 
390    8)  If any input string pointer is null, or if the output state
391        pointer is null, the error SPICE(NULLPOINTER) will be signaled.
392 
393    9)  If any input string has length zero, the error SPICE(EMPTYSTRING)
394        will be signaled.
395 
396 -Files
397 
398    Appropriate kernels must be loaded by the calling program before
399    this routine is called.
400 
401    The following data are required:
402 
403       -  SPK data: ephemeris data for the observer center and target
404          must be loaded. If aberration corrections are used, the
405          states of the observer center and target relative to the solar
406          system barycenter must be calculable from the available
407          ephemeris data. Typically ephemeris data are made available
408          by loading one or more SPK files using furnsh_c.
409 
410    The following data may be required:
411 
412       -  PCK data: if the target frame is a PCK frame, rotation data
413          for the target frame must be loaded. These may be provided
414          in a text or binary PCK file.
415 
416       -  Frame data: if a frame definition not built into SPICE is
417          required, for example to convert the observer-target state
418          to the output frame, that definition must be available in
419          the kernel pool. Typically frame definitions are supplied
420          by loading a frame kernel using furnsh_c.
421 
422       -  Additional kernels: if any frame used in this routine's
423          state computation is a CK frame, then at least one CK and
424          corresponding SCLK kernel is required. If dynamic frames
425          are used, additional SPK, PCK, CK, or SCLK kernels may be
426          required.
427 
428    In all cases, kernel data are normally loaded once per program
429    run, NOT every time this routine is called.
430 
431 -Particulars
432 
433    This routine computes observer-target states for observers whose
434    trajectories are not provided by SPK files.
435 
436    Observers supported by this routine must have constant velocity
437    with respect to a specified center of motion, expressed in a
438    caller-specified reference frame. The state of the center of
439    motion relative to the target must be computable using
440    loaded SPK data.
441 
442    For applications in which the observer has zero velocity
443    relative to its center of motion, the CSPICE routine
444 
445       spkcpo_c     { SPK, constant position observer }
446 
447    can be used. spkcpo_c has a simpler interface than that of spkcvo_c.
448 
449    This routine is suitable for computing states of target ephemeris
450    objects, as seen from landmarks on the surface of an extended
451    object, in cases where no SPK data are available for those
452    landmarks.
453 
454    This routine's treatment of the output reference frame differs
455    from that of the principal SPK API routines
456 
457       spkezr_c
458       spkez_c
459       spkpos_c
460       spkezp_c
461 
462    which require both observer and target ephemerides to be provided
463    by loaded SPK files:
464 
465       The SPK API routines listed above evaluate the orientation of the
466       output reference frame (with respect to the J2000 frame) at an
467       epoch corrected for one-way light time between the observer and
468       the center of the output frame. When the center of the output
469       frame is not the target (for example, when the target is on the
470       surface of Mars and the output frame is centered at Mars'
471       center), the epoch of evaluation may not closely match the
472       light-time corrected epoch associated with the target itself. A
473       similar problem may occur when the observer is a surface point on
474       an extended body and the output frame is centered at the body
475       center: the listed routines will correct the orientation of the
476       output frame for one-way light time between the frame center and
477       the observer.
478 
479       This routine allows the caller to dictate how the orientation
480       of the output reference frame is to be evaluated. The caller
481       passes to this routine an input string called the output
482       frame's evaluation "locus." This string specifies the location
483       associated with the output frame's evaluation epoch. The three
484       possible values of the locus are
485 
486          "TARGET"
487          "OBSERVER"
488          "CENTER"
489 
490       The choice of locus has an effect when aberration corrections
491       are used and the output frame is non-inertial.
492 
493       When the locus is "TARGET" and light time corrections are
494       used, the orientation of the output frame is evaluated at the
495       epoch obtained by correcting the observation epoch `et' for
496       one-way light time `lt'. The evaluation epoch will be either
497       et-lt or et+lt for reception or transmission corrections
498       respectively.
499 
500       For remote sensing applications where the target is a surface
501       point on an extended object, and the orientation of that
502       object should be evaluated at the emission time, the locus
503       "TARGET" should be used.
504 
505       When the output frame's orientation should be evaluated at
506       the observation epoch `et', which is the case when the
507       output frame is centered at the observer, the locus
508       "OBSERVER" should be used.
509 
510       The locus option "CENTER" is provided for compatibility
511       with existing SPK state computation APIs such as spkezr_c.
512 
513       Note that the output frame evaluation locus does not affect
514       the computation of light time between the target and
515       observer.
516 
517 
518    The SPK routines that compute observer-target states for
519    combinations of objects having ephemerides provided by the SPK
520    system and objects having constant position or constant velocity
521    are
522 
523       spkcpo_c {SPK, Constant position observer}
524       spkcpt_c {SPK, Constant position target}
525       spkcvo_c {SPK, Constant velocity observer}
526       spkcvt_c {SPK, Constant velocity target}
527 
528 -Examples
529 
530    The numerical results shown for these examples may differ across
531    platforms. The results depend on the SPICE kernels used as
532    input, the compiler and supporting libraries, and the machine
533    specific arithmetic implementation.
534 
535 
536    1) Compute apparent solar azimuth and elevation as seen from a
537       specified surface point on the earth.
538 
539       Task Description
540       ================
541 
542       In this example we'll use the location of the DSN station
543       DSS-14 as our surface point.
544 
545       We'll perform the solar azimuth and elevation computation two
546       ways:
547 
548          - Using a station frame kernel to provide the
549            specification of a topocentric reference frame
550            centered at DSS-14.
551 
552          - Computing inline the transformation from the earth-fixed,
553            earth-centered frame ITRF93 to a topocentric frame
554            centered at DSS-14.
555 
556            Note that results of the two computations will differ
557            slightly. This is due to differences in the orientations
558            of the topocentric frames. There are two sources of the
559            differences:
560 
561               1) The station position is time-dependent due to tectonic
562                  plate motion, and epochs of the station positions used
563                  to specify the axes of the topocentric frame are
564                  different in the two cases. This gives rise to different
565                  orientations of the frame's axes relative to the frame
566                  ITRF93.
567 
568               2) The two computations use different earth radii; this
569                  results in computation of different geodetic latitudes
570                  of the station. This difference also affects the
571                  topocentric frame orientation relative to ITRF93.
572 
573 
574       Kernels
575       =======
576 
577       Use the meta-kernel shown below to load the required SPICE
578       kernels.
579 
580 
581       KPL/MK
582 
583          File name: spkcvo.tm
584 
585          This is the meta-kernel file for the header code example for
586          the subroutine spkcvo_c. These kernel files can be found on
587          the NAIF website.
588 
589          In order for an application to use this meta-kernel, the
590          kernels referenced here must be present in the user's
591          current working directory.
592 
593          The names and contents of the kernels referenced
594          by this meta-kernel are as follows:
595 
596             File name                        Contents
597             ---------                        --------
598             de421.bsp                        Planetary ephemeris
599             pck00010.tpc                     Planet orientation and
600                                              radii
601             naif0010.tls                     Leapseconds
602             earth_720101_070426.bpc          Earth historical
603                                              binary PCK
604             earthstns_itrf93_050714.bsp      DSN station SPK
605             earth_topo_050714.tf             DSN station FK
606             mgs_moc_v20.ti                   MGS MOC instrument
607                                              parameters
608             mgs_sclkscet_00061.tsc           MGS SCLK coefficients
609             mgs_sc_ext12.bc                  MGS s/c bus attitude
610             mgs_ext12_ipng_mgs95j.bsp        MGS ephemeris
611 
612          \begindata
613 
614          KERNELS_TO_LOAD = ( 'de421.bsp',
615                              'pck00010.tpc',
616                              'naif0010.tls',
617                              'earth_720101_070426.bpc',
618                              'earthstns_itrf93_050714.bsp',
619                              'earth_topo_050714.tf',
620                              'mgs_moc_v20.ti',
621                              'mgs_sclkscet_00061.tsc',
622                              'mgs_sc_ext12.bc',
623                              'mgs_ext12_ipng_mgs95j.bsp'  )
624 
625          \begintext
626 
627          End of meta-kernel.
628 
629 
630       Example code begins here.
631 
632          /.
633             Program spkcvo_ex1
634 
635             This program uses spkcvo_c to compute solar azimuth
636             and elevation at a given surface point on the earth.
637 
638          ./
639 
640          #include <stdio.h>
641          #include <string.h>
642          #include <stdlib.h>
643          #include "SpiceUsr.h"
644 
645          int main()
646          {
647             /.
648             Local constants
649             ./
650             #define  META     "spkcvo.tm"
651             #define  FRNMLN   33
652             #define  SHAPLN   33
653             #define  TIMFMT   "YYYY MON DD HR:MN:SC.###### UTC"
654             #define  TIMFM2   "YYYY MON DD HR:MN:SC.###### TDB ::TDB"
655             #define  TIMLEN   41
656 
657             /.
658             Local variables
659             ./
660             SpiceChar             * abcorr;
661             SpiceChar               emitim  [ TIMLEN ];
662             SpiceChar               epcstr  [ TIMLEN ];
663             SpiceChar             * refloc;
664             SpiceChar             * obsctr;
665             SpiceChar             * obsref;
666             SpiceChar             * obstim;
667             SpiceChar             * outref;
668             SpiceChar             * target;
669 
670             SpiceDouble             az;
671             SpiceDouble             el;
672             SpiceDouble             et;
673             SpiceDouble             f;
674             SpiceDouble             lat;
675             SpiceDouble             lon;
676             SpiceDouble             lt0;
677             SpiceDouble             lt1;
678             SpiceDouble             normal [ 3 ] ;
679             SpiceDouble             obsalt;
680             SpiceDouble             obslat;
681             SpiceDouble             obslon;
682             SpiceDouble             obsepc;
683             SpiceDouble             obssta [ 6 ];
684             SpiceDouble             r;
685             SpiceDouble             radii  [ 3 ];
686             SpiceDouble             re;
687             SpiceDouble             rp;
688             SpiceDouble             state0 [ 6 ];
689             SpiceDouble             state1 [ 6 ];
690             SpiceDouble             topvec [ 3 ];
691             SpiceDouble             xform  [ 3 ][ 3 ];
692 
693             SpiceDouble             z [ 3 ]  = { 0.0, 0.0, 1.0 };
694 
695             SpiceInt                n;
696 
697 
698             /.
699             Load SPICE kernels.
700             ./
701             furnsh_c ( META );
702 
703             /.
704             Convert the observation time to seconds past J2000 TDB.
705             ./
706             obstim = "2003 OCT 13 06:00:00.000000 UTC";
707 
708             str2et_c ( obstim, &et );
709 
710             /.
711             Set the target, observer center, and observer frame.
712             ./
713             target = "SUN";
714             obsctr = "EARTH";
715             obsref = "ITRF93";
716 
717             /.
718             Set the state of DSS-14 relative to the earth's
719             center at the J2000 epoch, expressed in the
720             ITRF93 reference frame. Values come from the
721             earth station SPK specified in the meta-kernel.
722 
723             The velocity is non-zero due to tectonic
724             plate motion.
725             ./
726             obsepc    =  0.0;
727 
728             obssta[0] =  -2353.6213656676991;
729             obssta[1] =  -4641.3414911499403;
730             obssta[2] =   3677.0523293197439;
731             obssta[3] =     -0.00000000000057086;
732             obssta[4] =      0.00000000000020549;
733             obssta[5] =     -0.00000000000012171;
734 
735             /.
736             Find the apparent state of the sun relative
737             to the station in the DSS-14_TOPO reference frame.
738             Evaluate the output frame's orientation, that is the
739             orientation of the DSS-14_TOPO frame relative to the
740             J2000 frame, at the observation epoch. This
741             correction is obtained by setting `refloc' to
742             "OBSERVER".
743             ./
744 
745             outref = "DSS-14_TOPO";
746             abcorr = "CN+S";
747 
748             refloc = "OBSERVER";
749 
750             /.
751             Compute the observer-target state.
752             ./
753             spkcvo_c ( target, et,     outref, refloc,
754                        abcorr, obssta, obsepc, obsctr,
755                        obsref, state0, &lt0            );
756 
757             /.
758             Compute planetocentric coordinates of the
759             observer-target position in the local
760             topocentric reference frame DSS-14_TOPO.
761             ./
762             reclat_c ( state0, &r, &lon, &lat );
763 
764             /.
765             Compute solar azimuth. The latitude we've
766             already computed is the elevation. Express
767             both angles in degrees.
768             ./
769             el =   lat * dpr_c();
770             az = - lon * dpr_c();
771 
772             if ( az < 0.0 )
773             {
774                az +=  360.0;
775             }
776 
777             /.
778             Display the computed state, light time. and angles.
779             ./
780             timout_c ( et-lt0, TIMFMT, TIMLEN, emitim );
781             timout_c ( obsepc, TIMFM2, TIMLEN, epcstr );
782 
783             printf ( "\n"
784                      " Frame evaluation locus:     %s\n"
785                      "\n"
786                      " Target:                     %s\n"
787                      " Observation time:           %s\n"
788                      " Observer center:            %s\n"
789                      " Observer-center state time: %s\n"
790                      " Observer frame:             %s\n"
791                      " Emission time:              %s\n"
792                      " Output reference frame:     %s\n"
793                      " Aberration correction:      %s\n"
794                      "\n"
795                      " Observer-target position (km):\n"
796                      "   %20.8f %20.8f %20.8f\n"
797                      " Observer-target velocity (km/s):\n"
798                      "   %20.8f %20.8f %20.8f\n"
799                      " Light time (s):        %20.8f\n",
800 
801                      refloc,    target,    obstim,    obsctr,
802                      epcstr,    obsref,    emitim,    outref,
803                      abcorr,    state0[0], state0[1], state0[2],
804                      state0[3], state0[4], state0[5], lt0   );
805 
806             printf ( "\n"
807                      " Solar azimuth (deg):   %20.8f\n"
808                      " Solar elevation (deg): %20.8f\n",
809                      az, el                             );
810 
811 
812             /.
813             For an arbitrary surface point, we might not
814             have a frame kernel available. In this case
815             we can look up the state in the observer frame
816             using spkcvo_c and then convert the state to
817             the local topocentric frame. We'll first
818             create the transformation matrix for converting
819             vectors in the observer frame to the topocentric
820             frame.
821 
822             First step: find the geodetic (planetodetic)
823             coordinates of the observer. We need the
824             equatorial radius and flattening coefficient
825             of the reference ellipsoid.
826             ./
827             bodvrd_c ( "EARTH", "RADII", 3, &n, radii );
828 
829             re = radii[0];
830             rp = radii[2];
831 
832             f  = ( re - rp ) / re;
833 
834             recgeo_c ( obssta, re, f, &obslon, &obslat, &obsalt );
835 
836             /.
837             Find the outward surface normal on the reference
838             ellipsoid at the observer's longitude and latitude.
839             ./
840             latrec_c ( 1.0, obslon, obslat, normal );
841 
842             /.
843             The topocentric frame has its +Z axis aligned
844             with NORMAL and its +X axis pointed north.
845             The north direction is aligned with the component
846             of the ITRF93 +Z axis orthogonal to the topocentric
847             +Z axis.
848             ./
849             twovec_c ( normal, 3, z, 1, xform );
850 
851             outref = "ITRF93";
852             abcorr = "CN+S";
853 
854             refloc = "OBSERVER";
855 
856             /.
857             Compute the observer-target state.
858             ./
859             spkcvo_c ( target, et,     outref, refloc,
860                        abcorr, obssta, obsepc, obsctr,
861                        obsref, state1, &lt1            );
862             /.
863             Convert the position to the topocentric frame.
864             ./
865             mxv_c ( xform, state1, topvec );
866 
867             /.
868             Compute azimuth and elevation.
869             ./
870             reclat_c ( topvec, &r, &lon, &lat );
871 
872             el =   lat * dpr_c();
873             az = - lon * dpr_c();
874 
875             if ( az < 0.0 )
876             {
877                az +=  360.0;
878             }
879 
880             printf ( "\n\n\n"
881                      " AZ/EL computed without frame kernel:\n\n"
882                      " Distance between last two "
883                      "positions (km):   %20.8f\n",
884                      vdist_c( state0, topvec )   );
885 
886             printf ( "\n"
887                      " Solar azimuth (deg):   %20.8f\n"
888                      " Solar elevation (deg): %20.8f\n"
889                      "\n",
890                      az, el                             );
891 
892             return ( 0 );
893          }
894 
895 
896       When this program was executed on a PC/Linux/gcc
897       platform, the output was:
898 
899 
900          Frame evaluation locus:     OBSERVER
901 
902          Target:                     SUN
903          Observation time:           2003 OCT 13 06:00:00.000000 UTC
904          Observer center:            EARTH
905          Observer-center state time: 2000 JAN 01 12:00:00.000000 TDB
906          Observer frame:             ITRF93
907          Emission time:              2003 OCT 13 05:51:42.068322 UTC
908          Output reference frame:     DSS-14_TOPO
909          Aberration correction:      CN+S
910 
911          Observer-target position (km):
912               62512272.82076501    58967494.42506485  -122059095.46751761
913          Observer-target velocity (km/s):
914                   2475.97326517       -9870.26706232       -3499.90809969
915          Light time (s):                497.93167797
916 
917          Solar azimuth (deg):           316.67141599
918          Solar elevation (deg):         -54.85253168
919 
920 
921 
922          AZ/EL computed without frame kernel:
923 
924          Distance between last two positions (km):             3.07056970
925 
926          Solar azimuth (deg):           316.67141786
927          Solar elevation (deg):         -54.85253216
928 
929 
930 
931 
932    2) Demonstrate applications of the output frame evaluation locus.
933 
934       The following program is not necessarily realistic: for
935       brevity, it combines several unrelated computations.
936 
937       Task Description
938       ================
939 
940       Find the state of the Mars Global Surveyor spacecraft, as seen
941       from a given surface point on earth, corrected for light time
942       and stellar aberration, expressed in the earth fixed reference
943       frame ITRF93. The surface point is the position of the DSN
944       station DSS-14.
945 
946       Contrast the states computed by setting the output frame
947       evaluation locus to "OBSERVER" and to "CENTER". Show that the
948       latter choice produces results very close to those that
949       can be obtained using spkezr_c.
950 
951       Also compute the central meridian longitude on Mars of DSS-14.
952       This computation performs aberration corrections for the center
953       of Mars.
954 
955       Note that in general, the routine subpnt_c should be used for
956       sub-observer point computations when high-accuracy aberration
957       corrections are desired.
958 
959       The observation epoch is 2003 OCT 13 06:00:00 UTC.
960 
961 
962       Kernels
963       =======
964 
965       Use the meta-kernel of example 1 above.
966 
967 
968       Example code begins here.
969 
970 
971          /.
972             Program spkcvo_ex2
973 
974 
975                This program demonstrates the use of spkcvo_c.
976                Computations are performed using all three possible
977                values of the output frame evaluation locus `refloc':
978 
979                   "OBSERVER"
980                   "CENTER"
981                   "TARGET"
982 
983                Several unrelated computations are performed in this
984                program. In particular, computation of the
985                central meridian longitude on Mars is included simply
986                to demonstrate use of the "TARGET" option.
987          ./
988 
989          #include <stdio.h>
990          #include <string.h>
991          #include <stdlib.h>
992          #include "SpiceUsr.h"
993 
994          int main()
995          {
996             /.
997             Local constants
998             ./
999 
1000             #define  META     "spkcvo.tm"
1001             #define  FRNMLN   33
1002             #define  SHAPLN   33
1003             #define  TIMFMT   "YYYY MON DD HR:MN:SC.###### UTC"
1004             #define  TIMFM2   "YYYY MON DD HR:MN:SC.###### TDB ::TDB"
1005             #define  TIMLEN   41
1006 
1007             /.
1008             Local variables
1009             ./
1010             SpiceChar             * abcorr;
1011             SpiceChar               emitim  [ TIMLEN ];
1012             SpiceChar               epcstr  [ TIMLEN ];
1013             SpiceChar             * refloc;
1014             SpiceChar             * obsctr;
1015             SpiceChar             * obsref;
1016             SpiceChar             * obsrvr;
1017             SpiceChar             * obstim;
1018             SpiceChar             * outref;
1019             SpiceChar             * target;
1020 
1021             SpiceDouble             et;
1022             SpiceDouble             lat;
1023             SpiceDouble             lon;
1024             SpiceDouble             lt0;
1025             SpiceDouble             lt1;
1026             SpiceDouble             lt2;
1027             SpiceDouble             lt3;
1028             SpiceDouble             obsepc;
1029             SpiceDouble             obssta [ 6 ];
1030             SpiceDouble             obsvec [ 3 ];
1031             SpiceDouble             r;
1032             SpiceDouble             state0 [ 6 ];
1033             SpiceDouble             state1 [ 6 ];
1034             SpiceDouble             state2 [ 6 ];
1035             SpiceDouble             state3 [ 6 ];
1036 
1037 
1038             /.
1039             Load SPICE kernels.
1040             ./
1041             furnsh_c ( META );
1042 
1043             /.
1044             Convert the observation time to seconds past J2000 TDB.
1045             ./
1046             obstim = "2003 OCT 13 06:00:00.000000 UTC";
1047 
1048             str2et_c ( obstim, &et );
1049 
1050             /.
1051             Set the target, observer center, and observer frame.
1052             ./
1053             target = "MGS";
1054             obsctr = "EARTH";
1055             obsref = "ITRF93";
1056 
1057             /.
1058             Set the state of DSS-14 relative to the earth's
1059             center at the J2000 epoch, expressed in the
1060             ITRF93 reference frame. Values come from the
1061             earth station SPK specified in the meta-kernel.
1062 
1063             The velocity is non-zero due to tectonic
1064             plate motion.
1065             ./
1066             obsepc    =  0.0;
1067 
1068             obssta[0] =  -2353.6213656676991;
1069             obssta[1] =  -4641.3414911499403;
1070             obssta[2] =   3677.0523293197439;
1071             obssta[3] =     -0.00000000000057086;
1072             obssta[4] =      0.00000000000020549;
1073             obssta[5] =     -0.00000000000012171;
1074 
1075             /.
1076             Find the apparent state of the spacecraft relative
1077             to the station in the ITRF93 reference frame.
1078             Evaluate the earth's orientation, that is the
1079             orientation of the ITRF93 frame relative to the
1080             J2000 frame, at the observation epoch. This
1081             correction is obtained by setting `refloc' to
1082             "OBSERVER".
1083             ./
1084 
1085             outref = "ITRF93";
1086             abcorr = "CN+S";
1087 
1088             refloc = "OBSERVER";
1089 
1090             /.
1091             Compute the observer-target state.
1092             ./
1093             spkcvo_c ( target, et,     outref, refloc,
1094                        abcorr, obssta, obsepc, obsctr,
1095                        obsref, state0, &lt0            );
1096 
1097             /.
1098             Display the computed state and light time.
1099             ./
1100             timout_c ( et-lt0, TIMFMT, TIMLEN, emitim );
1101             timout_c ( obsepc, TIMFM2, TIMLEN, epcstr );
1102 
1103             printf ( "\n"
1104                      " Frame evaluation locus:     %s\n"
1105                      "\n"
1106                      " Target:                     %s\n"
1107                      " Observation time:           %s\n"
1108                      " Observer center:            %s\n"
1109                      " Observer-center state time: %s\n"
1110                      " Observer frame:             %s\n"
1111                      " Emission time:              %s\n"
1112                      " Output reference frame:     %s\n"
1113                      " Aberration correction:      %s\n"
1114                      "\n"
1115                      " Observer-target position (km):\n"
1116                      "   %20.8f %20.8f %20.8f\n"
1117                      " Observer-target velocity (km/s):\n"
1118                      "   %20.8f %20.8f %20.8f\n"
1119                      " Light time (s):   %20.8f\n",
1120 
1121                      refloc,    target,    obstim,    obsctr,
1122                      epcstr,    obsref,    emitim,    outref,
1123                      abcorr,    state0[0], state0[1], state0[2],
1124                      state0[3], state0[4], state0[5], lt0   );
1125 
1126             /.
1127             Repeat the computation, this time evaluating the
1128             earth's orientation at the epoch obtained by
1129             subtracting from the observation time the one way
1130             light time from the earth's center.
1131 
1132             This is equivalent to looking up the observer-target
1133             state using spkezr_c.
1134             ./
1135             refloc = "CENTER";
1136 
1137             spkcvo_c ( target, et,     outref, refloc,
1138                        abcorr, obssta, obsepc, obsctr,
1139                        obsref, state1, &lt1            );
1140 
1141             /.
1142             Display the computed state and light time.
1143             ./
1144             timout_c ( et-lt1, TIMFMT, TIMLEN, emitim );
1145 
1146             printf ( "\n\n"
1147                      " Frame evaluation locus:     %s\n"
1148                      "\n"
1149                      " Target:                     %s\n"
1150                      " Observation time:           %s\n"
1151                      " Observer center:            %s\n"
1152                      " Observer-center state time: %s\n"
1153                      " Observer frame:             %s\n"
1154                      " Emission time:              %s\n"
1155                      " Output reference frame:     %s\n"
1156                      " Aberration correction:      %s\n"
1157                      "\n"
1158                      " Observer-target position (km):\n"
1159                      "   %20.8f %20.8f %20.8f\n"
1160                      " Observer-target velocity (km/s):\n"
1161                      "   %20.8f %20.8f %20.8f\n"
1162                      " Light time (s):   %20.8f\n",
1163 
1164                      refloc,    target,    obstim,    obsctr,
1165                      epcstr,    obsref,    emitim,    outref,
1166                      abcorr,    state1[0], state1[1], state1[2],
1167                      state1[3], state1[4], state1[5], lt1      );
1168 
1169             printf ( "\n"
1170                      " Distance between above positions (km):  "
1171                      "       %20.8f\n"
1172                      " Velocity difference magnitude  (km/s):"
1173                      "         %20.8f\n",
1174                      vdist_c( state0,   state1   ),
1175                      vdist_c( state0+3, state1+3 )                     );
1176 
1177             /.
1178             Check: compare the state computed directly above
1179             to one produced by spkezr_c:
1180             ./
1181             obsrvr = "DSS-14";
1182 
1183             spkezr_c ( target,  et,      outref,  abcorr,
1184                        obsrvr,  state2,  &lt2            );
1185 
1186             printf ( "\n\n"
1187                      " State computed using spkezr_c:\n"
1188                      "\n"
1189                      " Target:                 %s\n"
1190                      " Observation time:       %s\n"
1191                      " Output reference frame: %s\n"
1192                      " Aberration correction:  %s\n"
1193                      " Observer:               %s\n"
1194                      "\n"
1195                      " Observer-target position (km):\n"
1196                      "   %20.8f %20.8f %20.8f\n"
1197                      " Observer-target velocity (km/s):\n"
1198                      "   %20.8f %20.8f %20.8f\n"
1199                      " Light time (s): %20.8f\n",
1200 
1201                      target,    obstim,    outref,
1202                      abcorr,    obsrvr,
1203                      state2[0], state2[1], state2[2],
1204                      state2[3], state2[4], state2[5], lt2   );
1205 
1206             printf ( "\n"
1207                      " Distance between last two "
1208                      "positions (km):   %20.8f\n"
1209                      " Velocity difference magnitude    "
1210                      " (km/s):   %20.8f\n",
1211                      vdist_c( state1,   state2   ),
1212                      vdist_c( state1+3, state2+3 )          );
1213 
1214             /.
1215             Finally, compute an observer-target state in
1216             a frame centered at the target.
1217             This state can be used to compute the sub-observer
1218             longitude. The reference frame is the Mars-fixed
1219             frame IAU_MARS.
1220             ./
1221 
1222             target = "MARS";
1223             outref = "IAU_MARS";
1224 
1225             refloc = "TARGET";
1226 
1227             spkcvo_c ( target, et,     outref, refloc,
1228                        abcorr, obssta, obsepc, obsctr,
1229                        obsref, state3, &lt3            );
1230 
1231             /.
1232             Central meridian longitude is the longitude of the
1233             observer relative to the target center, so we must
1234             negate the position portion of the state we just
1235             computed.
1236             ./
1237             vminus_c ( state3, obsvec );
1238 
1239             reclat_c ( obsvec, &r, &lon, &lat );
1240 
1241             printf ( "\n\n"
1242                      " Frame evaluation locus:     %s\n"
1243                      "\n"
1244                      " Target:                     %s\n"
1245                      " Observation time:           %s\n"
1246                      " Observer center:            %s\n"
1247                      " Observer-center state time: %s\n"
1248                      " Observer frame:             %s\n"
1249                      " Emission time:              %s\n"
1250                      " Output reference frame:     %s\n"
1251                      " Aberration correction:      %s\n"
1252                      "\n"
1253                      " Observer-target position (km):\n"
1254                      "   %20.8f %20.8f %20.8f\n"
1255                      " Observer-target velocity (km/s):\n"
1256                      "   %20.8f %20.8f %20.8f\n"
1257                      " Light time (s):   %20.8f\n",
1258 
1259                      refloc,    target,    obstim,    obsctr,
1260                      epcstr,    obsref,    emitim,    outref,
1261                      abcorr,    state3[0], state3[1], state3[2],
1262                      state3[3], state3[4], state3[5], lt3   );
1263 
1264             printf ( "\n"
1265                      " Central meridian\n"
1266                      " longitude (deg):  %20.8f\n\n\n",
1267                      lon * dpr_c()                       );
1268 
1269 
1270             return ( 0 );
1271          }
1272 
1273 
1274       When this program was executed on a PC/Linux/gcc
1275       platform, the output was:
1276 
1277 
1278          Frame evaluation locus:     OBSERVER
1279 
1280          Target:                     MGS
1281          Observation time:           2003 OCT 13 06:00:00.000000 UTC
1282          Observer center:            EARTH
1283          Observer-center state time: 2000 JAN 01 12:00:00.000000 TDB
1284          Observer frame:             ITRF93
1285          Emission time:              2003 OCT 13 05:55:44.201144 UTC
1286          Output reference frame:     ITRF93
1287          Aberration correction:      CN+S
1288 
1289          Observer-target position (km):
1290              -53720675.37940782   -51381249.05338467   -18838416.34716543
1291          Observer-target velocity (km/s):
1292                  -3751.69274754        3911.73417167          -2.17503628
1293          Light time (s):           255.79885530
1294 
1295 
1296          Frame evaluation locus:     CENTER
1297 
1298          Target:                     MGS
1299          Observation time:           2003 OCT 13 06:00:00.000000 UTC
1300          Observer center:            EARTH
1301          Observer-center state time: 2000 JAN 01 12:00:00.000000 TDB
1302          Observer frame:             ITRF93
1303          Emission time:              2003 OCT 13 05:55:44.201144 UTC
1304          Output reference frame:     ITRF93
1305          Aberration correction:      CN+S
1306 
1307          Observer-target position (km):
1308              -53720595.74378239   -51381332.31467460   -18838416.34737090
1309          Observer-target velocity (km/s):
1310                  -3751.69880992        3911.72835653          -2.17503628
1311          Light time (s):           255.79885530
1312 
1313          Distance between above positions (km):                 115.21404098
1314          Velocity difference magnitude  (km/s):                   0.00840050
1315 
1316 
1317          State computed using spkezr_c:
1318 
1319          Target:                 MGS
1320          Observation time:       2003 OCT 13 06:00:00.000000 UTC
1321          Output reference frame: ITRF93
1322          Aberration correction:  CN+S
1323          Observer:               DSS-14
1324 
1325          Observer-target position (km):
1326              -53720595.74378239   -51381332.31467460   -18838416.34737090
1327          Observer-target velocity (km/s):
1328                  -3751.69880992        3911.72835653          -2.17503628
1329          Light time (s):         255.79885530
1330 
1331          Distance between last two positions (km):             0.00000000
1332          Velocity difference magnitude     (km/s):             0.00000000
1333 
1334 
1335          Frame evaluation locus:     TARGET
1336 
1337          Target:                     MARS
1338          Observation time:           2003 OCT 13 06:00:00.000000 UTC
1339          Observer center:            EARTH
1340          Observer-center state time: 2000 JAN 01 12:00:00.000000 TDB
1341          Observer frame:             ITRF93
1342          Emission time:              2003 OCT 13 05:55:44.201144 UTC
1343          Output reference frame:     IAU_MARS
1344          Aberration correction:      CN+S
1345 
1346          Observer-target position (km):
1347              -71445232.12767348     2312773.74169024    27766441.52046534
1348          Observer-target velocity (km/s):
1349                    155.65895286        5061.78618477           5.09447029
1350          Light time (s):           255.79702283
1351 
1352          Central meridian
1353          longitude (deg):           -1.85409037
1354 
1355 
1356 
1357 -Restrictions
1358 
1359    1)  This routine may not be suitable for work with stars or other
1360        objects having large distances from the observer, due to loss
1361        of precision in position vectors.
1362 
1363 -Literature_References
1364 
1365    None.
1366 
1367 -Author_and_Institution
1368 
1369    N.J. Bachman    (JPL)
1370    S.C. Krening    (JPL)
1371    B.V. Semenov    (JPL)
1372 
1373 -Version
1374 
1375    -CSPICE Version 1.0.1, 09-SEP-2015 (NJB)
1376 
1377        The Exceptions section of the header was updated
1378        to mention exceptions involving null pointers and
1379        empty input strings.
1380 
1381    -CSPICE Version 1.0.0, 27-MAR-2012 (NJB) (SCK) (BVS)
1382 
1383 -Index_Entries
1384 
1385    state relative to constant_velocity_observer
1386    state relative to constant_velocity surface_point
1387    state relative to surface_point on extended_object
1388    state relative to landmark on extended_object
1389 
1390 -&
1391 */
1392 
1393 { /* Begin spkcvo_c */
1394 
1395 
1396 
1397    /*
1398    Participate in error tracing.
1399    */
1400    chkin_c ( "spkcvo_c" );
1401 
1402    /*
1403    Check the input state pointer.
1404    */
1405    CHKPTR ( CHK_STANDARD, "spkcvo_c", obssta );
1406 
1407    /*
1408    Check the input strings.
1409    */
1410    CHKFSTR ( CHK_STANDARD, "spkcvo_c", target );
1411    CHKFSTR ( CHK_STANDARD, "spkcvo_c", outref );
1412    CHKFSTR ( CHK_STANDARD, "spkcvo_c", refloc );
1413    CHKFSTR ( CHK_STANDARD, "spkcvo_c", abcorr );
1414    CHKFSTR ( CHK_STANDARD, "spkcvo_c", obsctr );
1415    CHKFSTR ( CHK_STANDARD, "spkcvo_c", obsref );
1416 
1417    /*
1418    Check the output pointers.
1419    */
1420    CHKPTR ( CHK_STANDARD, "spkcvo_c", state );
1421    CHKPTR ( CHK_STANDARD, "spkcvo_c", lt    );
1422 
1423    /*
1424    Let the f2c'd routine do the work.
1425    */
1426    spkcvo_ ( ( char       * ) target,
1427              ( doublereal * ) &et,
1428              ( char       * ) outref,
1429              ( char       * ) refloc,
1430              ( char       * ) abcorr,
1431              ( doublereal * ) obssta,
1432              ( doublereal * ) &obsepc,
1433              ( char       * ) obsctr,
1434              ( char       * ) obsref,
1435              ( doublereal * ) state,
1436              ( doublereal * ) lt,
1437              ( ftnlen       ) strlen(target),
1438              ( ftnlen       ) strlen(outref),
1439              ( ftnlen       ) strlen(refloc),
1440              ( ftnlen       ) strlen(abcorr),
1441              ( ftnlen       ) strlen(obsctr),
1442              ( ftnlen       ) strlen(obsref)  );
1443 
1444    chkout_c ( "spkcvo_c" );
1445 
1446 } /* End spkcvo_c */
1447