Geometry Finder Required Reading 
Table of ContentsGeometry Finder Required Reading Abstract Purpose Intended Audience References Introduction Planned enhancements Terminology GF Concepts Time windows Window manipulation and arithmetic Result windows are approximate Working around result window errors Events Constraints Root finding Search step size Binary state step size selection problems Numeric quantity step size selection problems Search convergence An important numeric event limitation Workspace Workspace window counts Workspace window interval counts Estimating the workspace interval count requirement GF API Routines Highlevel GF search routines Midlevel GF search routines Rationale for calling midlevel GF search routines Supporting utility routines Overriding default behavior GF Computational Recipes Required SPICE kernels A note about CK data availability Geometric constraint searches Periapse/Apoapse View periods Subobserver point Instrument boresight intercept Planet in instrument field of view Star in instrument field of view Spacecraft occultation or transit Natural satellite occultation or transit Spacecraft eclipse Surface point eclipse Equator crossing Meridian crossing Elongation Orbital longitude of a satellite Approximate times of Cassini Saturn ring occultations Angular offset between instrument boresight and velocity Common GF Problems A challenge Wrong SPICE kernels Insufficient kernel data Missed events Slow performance Constraints not met on result window Result window intervals appear invalid GF Example Programs Program MEDLEY: Searches for Periapse, Occultation, Rise/Set Overview Aberration corrections SPICE kernels Source code Results Program CASCADE: Fast Search for Solar Eclipse Overview Specifying the angular separation search parameters Aberration corrections SPICE kernels Source code Results Program ROVER: Mars Reconnaissance Orbiter photographs MER1 Overview Determining SPK and CK coverage at run time Speeding up the search Pointing issues Aberration corrections SPICE kernels Source code Results Appendix A  Summary of GF Functions Summary of Mnemonics Appendix B  Revision History 2017 JUN 19 by N. J. Bachman 2012 OCT 01 by E. D. Wright. 2010 MAY 13 by E. D. Wright. 2009 APR 15 by N. J. Bachman. Geometry Finder Required Reading
Abstract
Purpose
Intended Audience
This document assumes you already have a strong understanding of SPICE concepts and terminology. References
Introduction
For example, the GF subsystem can solve the problem:
Within the time interval January 1 2009 to January 1 2010, find the time periods when the light time corrected distance between the centers of the Earth and Moon is less than 400000 kilometers.The GF subsystem works with a small set of geometric quantities:
All language versions of the SPICE Toolkit contain complete example programs in the GF module headers or corresponding HTML Reference Guide pages. Extensive example programs are presented at the end of this document. Much of the capability of the GF subsystem derives from the wide range of input data (particularly FK files) and input parameters it supports. But in many cases it may not be immediately obvious how to select or create the necessary SPICE kernels and how to apply the small set of GF API routines to accomplish a given search task. The ``GF Computational Recipes'' chapter below provides many short descriptions of how to use the GF subsystem to search for geometric events that are frequently of interest. Because the main function of the GF subsystem is, at its heart, solving equations, the details of the subsystem's behavior are more complex than is the case for most other SPICE subsystems. Understanding how to call the GF routines is not sufficient to guarantee correct results. So SPICE application programmers are encouraged to read the ``GF Concepts'' chapter below. Planned enhancements
Terminology
GF ConceptsTime windows
In SPICE documentation, a ``time window'' is a set of zero or more closed, disjoint time intervals, arranged in increasing order. The intervals may be singletons: they can have equal left and right endpoints. The term ``SPICE window'' refers to both the abstract data type used to represent time windows and instances of this type. In Fortran and MATLAB, SPICE windows are implemented via structured arrays (arrays whose internal organization adheres to certain rules); in C and IDL they are represented by structures. By ``closed'' we mean that the intervals of a SPICE window are topologically closed: that is, the intervals always include their endpoints. We'll use diagrams like the one below to depict time windows. The dashed line represents the real line; the bracketed regions signify the time intervals comprising the window.
[][][] Window manipulation and arithmetic
Arithmetic on SPICE windows differs a bit from standard set arithmetic because all windows resulting from window operations remain closed. For example, when you subtract a SPICE window from another, the result is a union of closed intervals. Standard set arithmetic would produce a result containing halfopen or open intervals. Window arithmetic is used to solve for logical combinations of geometric conditions. For example:
Result windows are approximate
A consequence of the errors in the computed endpoints is that the geometric constraint that is supposed to be satisfied for every time within the result window FREQUENTLY IS NOT SATISFIED at one or more endpoints of the intervals of this window. In fact, it is common for there to be a small time region surrounding an interval endpoint on which the constraint of interest is not satisfied. For the same reason, it is just as likely that the constraint of interest is satisfied on a small time region extending beyond an interval endpoint of the result window. This is perhaps a less obvious error, but it is nevertheless an error because the result window is ideally the exact set of times, within the confinement window, on which the constraint is satisfied. In this case the result window is not the maximal subset of the confinement window on which the constraint is satisfied. One application for which result window errors are particularly striking is that of searches for time windows satisfying longitude or right ascension constraints. For example, a small error in the window over which a given longitude is between 180 and 150 degrees can easily include some times at which the longitude is between 179 and 180 degrees. Working around result window errors
In many cases, it makes sense to contract a result window slightly to remove portions of the window on which a constraint is not satisfied. Usually it suffices to contract a window by an amount on the order of the convergence tolerance. In the case of result windows produced by longitude or right ascension searches, a somewhat larger contraction is needed because these result windows are actually the product of multiple subsearches. When an application performs set arithmetic on result windows, usually contraction should be performed only on the final result. Contracting intermediate results can be a mistake. For example, contracting a window before computing its complement introduces an error in the complement: the complement then includes more of the original window than just its endpoints. Contraction should not be performed on result windows comprised of singleton intervals: the result of such contractions would be an empty window. Searches for local or absolute extrema are examples of the type that produces a window of singleton intervals. Events
Geometric quantities supported by the GF subsystem either have binary states or are numeric functions of time. ``Binary state'' quantities are logicalvalued functions of time; they're either true or false for a given time value. For example, ``target A is fully occulted by target B as seen from observer C'' is either true or false at any given time. Occultation and FOV visibility are binary state quantities. ``Numeric'' quantities are scalarvalued functions of time. Distance, angular separation, and coordinates are numeric quantities. Constraints
The only supported constraint applicable to binary state quantities is ``the state is true." Note that SPICE window arithmetic serves to produce the window on which a binary state is false. Supported constraints on numeric quantities are mathematical relations, such as equalities, inequalities, and attainment of local or global maxima or minima. These are often called ``numeric constraints'' ``scalar constraints,'' or ``relational constraints.'' Specifically, these relations are:
Note that the ``greater than or equal to (>=)'' and ``less than or equal to (<=)'' operators are not supported. Since result windows are approximate, the distinction between the solutions that could be found using these operators and those found using strict inequality operators is usually not meaningful. The case where there is a significant distinction is that in which a function takes on the constant value X on one or more intervals, and the reference value is set to X. However, as discussed below, the GF subsystem cannot solve for this constraint. Root finding
Because GF searches are ``global'' in the sense that they attempt to find all roots within the confinement window, each search involves two basic steps: bracketing the roots and refining the roots. Note that the most elementary root finding techniques deal with finding roots that are already bracketed. Searches for roots are conducted independently over each interval comprising the confinement window. For simplicity, and without loss of generality, we'll describe the processes below for confinement windows consisting of a single interval. Search step size
An example is shown below: we have a confinement window consisting of an interval having a start time of 2 seconds past J2000 TDB, a stop time of 57 seconds past J2000 TDB, and a step size of 10 TDB seconds. Sampling with 10second step:
2 12 22 32 42 52 57        v v v v v v v [] ^ ^ 2 57Note that a sample is always taken at the end of the interval. The reader may note that the unlikely TDB time values used here correspond to the zerobased column counts of the dashes in the diagram. Suppose the quantity we're sampling is of the binarystate variety. Each sample has the value ``true'' or ``false.'' Suppose the diagram below indicates the state of the quantity as a function of time. At the top of the diagram are the values of the state samples:
F T T T F F F 2 12 22 32 42 52 57        v v v v v v v TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT FFF FFFFFFFFFFFFFFFFF [] ^ ^ 2 57Above, the samples indicate that state transitions must occur between the times 2 and 12 TDB seconds past J2000 TDB, and also between 32 and 42 seconds past J2000 TDB. So these pairs of times bracket, respectively, the start and stop times of our ``event.'' Given the bracketing times, the GF system can refine the actual times of the state transitions, producing estimates that are accurate to within a given convergence tolerance. Binary state step size selection problems
Step sizes that are too large may result in fast search completion, but they'll produce erroneous results. As an example, suppose we repeat the previous search using a 40 second step. The samples we'd find are shown below.
F F F 2 42 57    v v v TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT FFF FFFFFFFFFFFFFFFFF [] ^ ^ 2 57Above, the samples indicate that no state transitions occur: the state is always ``false.'' The GF subsystem will fail to detect the event and will return an empty result window. Another example: suppose we use a 10 second step size and our binary state quantity has the profile shown below:
F T T T T F F 2 12 22 32 42 52 57        v v v v v v v TTTTTTTTTTTTTTTTTTT TTTTTTTTTTTTTT FFF FFFFFFF FFFFFFFFFFFFF [] ^ ^ 2 57Above, the samples indicate that state transitions must occur between the times 2 and 12 TDB seconds past J2000 TDB, and also between 42 and 52 seconds past J2000 TDB. The GF subsystem thinks that only one long event has occurred because the state transitions in the middle of the search interval were missed. We can conclude that for binary state searches, the step size must be short enough to capture the relevant behavior of the underlying geometric quantity: the step size must be shorter than any event of interest, and it must be shorter than any gap between events of interest. Numeric quantity step size selection problems
So for numeric quantity searches, the step size must be small enough so that all (relevant) local extrema can be found: the step size must be smaller than the minimum time between consecutive epochs at which local extrema of the numeric quantity occur. Search convergence
The highlevel GF search routines use a fixed tolerance in units of seconds SPICE_GF_CNVTOL which is defined in the header file
SpiceGF.hThe default value is "tight" so that the tolerance doesn't become the limiting factor in the accuracy of solutions. In general the accuracy of input data will be the limiting factor. To use a different tolerance value, midlevel GF search routines (available only in the Fortran and C SPICE Toolkits) must be called. Making the tolerance tighter than the default is unlikely to be useful, since the results are unlikely to be more accurate. Making the tolerance looser will speed up searches somewhat, since a few convergence steps will be omitted. However, in most cases, the step size is likely to have a much greater effect on processing time than would the convergence tolerance. Please remember the condition satisfying convergence
 t2  t1  =< SPICE_GF_CNVTOLdoes not imply (ignoring incompatibility of units)
 f(t2)  f(t1)  =< SPICE_GF_CNVTOLfor scalar function ``f(t).'' The GF subsystem measures convergence using time (units of TDB seconds) not using the scalar quantity (units of kilometers or radians or whatever). An important numeric event limitation
Each numeric quantity is piecewise monotone.That is, each interval of the confinement window can be divided into a finite set of intervals over which the quantity is always increasing or always decreasing. The authors believe this is a reasonable assumption for most numeric quantities involving solar system geometry. However, this not a valid assumption for all numeric quantities supported by SPICE. For example, spacecraft orientation definitely can, and often does, violate this assumption. There are two practical consequences of this assumption:
Workspace
Workspace is used to store multiple SPICE windows, all of which have the same size. The windows' size requirement is determined by the number of time intervals they must be able to hold. GF users decide the amount of workspace to provide: in Fortran, callers of the GF search API routines declare workspace arrays, while GF APIs of SPICE Toolkits for other languages dynamically allocate memory based on the workspace window interval count specified by calling applications via an input argument. Workspace window counts
gf.incDeclaring workspace window counts to be larger than the actual required number is not an error. Readers may note that the SPICELIB GF interfaces could have relied on hardcoded workspace window counts. The reason for treating these counts as passedin parameters is that this enables runtime error checking on the counts. SPICE Toolkits implemented in languages other than Fortran handle workspace window counts automatically. However, users of these Toolkits may wish to be aware of these window count requirements because they affect the total amount of dynamically allocated memory used by the GF API routines. Parameters giving workspace window counts are declared in the CSPICE header file
SpiceGF.h Workspace window interval counts
For most searches, it's safe to choose a workspace interval count that's much larger than the actual requirement. For example, one can choose an interval count of 200000 for a search that really requires only 200 intervals. This approach is used in most GF example programs that appear in SPICE documentation. The only drawback to the approach of picking a large, default workspace size is that if it's taken to extremes, applications may use so much memory so that they fail to link or run, or so that they run inefficiently. If an initial guess at the workspace size requirement fails, one usually can simply increase the workspace size and repeat the search. However, some applications call for a more accurate method of estimating workspace interval count requirements. The actual requirement is that the interval count must be large enough to hold the windows, restricted to the confinement interval, over which the quantity of interest is monotonically increasing or decreasing. Note that the number of intervals comprising the confinement window affects the amount of required space. Estimating the workspace interval count requirement
NINTVLS = 2*N + ( M / STEP )In many cases the actual number of intervals needed is much smaller than this estimate. GF API RoutinesHighlevel GF search routines
The routines described here are supported in all language versions of the SPICE Toolkit. All of the routines listed below have extensive header documentation. Each header describes all input and output arguments and includes one or more example programs accompanied by example metakernels and corresponding program outputs. Additional, more extensive code examples are presented at the end of this document. The ``GF Computational Recipes'' chapter below provides hints on how to solve various geometric search problems using these routines. The highlevel GF search routines are:
Midlevel GF search routines
The midlevel GF search routines are:
Rationale for calling midlevel GF search routines
GF searches can take a long time to complete, particularly when the confinement window is large and the step size is small. It may not be obvious to a user whether a running search is making progress at a reasonable rate. The default GF progress report, which when enabled updates approximately once per second, helps to answer this question. If progress reporting is used in a GUI application, reports produced by the default mechanism are probably undesirable. In this case, application programs can pass custom progress reporting routines to the midlevel GF search routines. When an interactive SPICEbased application runs a GF search, the user may want to abort the search without terminating the program, possibly because terminating the program would result in substantial loss of work. The GF interrupt handling capability allows an application program to quickly abort GF searches and have the GF system return control to the application. Supporting utility routines
Overriding default behavior
To override the default progress reporting capability provided by the midlevel GF search routines, an application must pass in custom routines in place of gfrepi_c, grrepu_c, and gfrepf_c. Each of the custom routines must have an argument list that exactly matches that of the default routine it overrides; see the headers of the default routines for details. Note that the application must override all of the progress reporting routines in a given call, if it overrides any one of them. To override the default interrupt handling capability, an application must pass in a custom routine in place of gfbail_c. The custom routine must have an argument list that exactly matches that of gfbail_c. Step Size and Refinement Functions The need to override the step size and refinement functions is expected to be quite unusual; it should be attempted only by programmers having a detailed knowledge of the GF search algorithms and the code that implements them. GF Computational Recipes
The ``recipes'' below are very abbreviated; they're intended to be helpful to experienced SPICE users. New users are encouraged to first familiarize themselves with the example programs in the GF API headers and in this document. Users should consult the headers of the pertinent SPICE routines for details on the use of those routines. Note that for valid comparison of GF results against those obtained by alternate means, inputs such as kernel data, aberration corrections, reference frames, coordinate systems, confinement windows, and time systems used to represent time windows must be compatible. Required SPICE kernels
A note about CK data availability
When the caller of ckcov_c requests that interval endpoints in the CK coverage time window be expressed as TDB seconds, ckcov_c must convert these endpoints from encoded SCLK (ticks) to TDB. Due to roundoff errors, and in some cases, to discontinuities in the TDBtoticks mapping, the TDB values obtained via this call may not be translatable to tick values within the actual coverage window of the CK file. For safety, applications obtaining TDB coverage windows via ckcov_c should call the CSPICE window routine wncond_c to contract those windows by a duration large enough to ensure that the entire, contracted coverage window is usable. For an SCLK kernel that provides a continuous TDBtoticks mapping, a contraction duration (having units of TDB seconds) equivalent to one tick normally should suffice, as long as the nominal tick duration is at least one microsecond. For SCLK kernels having discontinuities, the required contraction duration can be determined by analyzing the possible mapping errors caused by those discontinuities; alternatively, it can be determined by trial and error. If a search is performed and required CK data are unavailable, SPICE routines will signal an error. Geometric constraint searchesPeriapse/Apoapse
"ABSMIN"(absolute minimum) relational operator. To find all of the ``close approaches'' of an observer to a target over a specified time window, use the
"LOCMIN"(local minimum) relational operator. For apoapse events, use the absolute or local maximum operators instead:
"ABSMAX" "LOCMAX"See the example program MEDLEY below for details. View periods
Compute view periods using gfposc_c. See the example program MEDLEY below for details. In the gfposc_c call, aberration corrections should be set to be compatible with the direction of radiation travel: either ``reception'' or ``transmission'' corrections can be selected. Normally both light time and stellar aberration corrections should be used; the aberration correction input string should be either of
"LT+S" "XLT+S"To find the time window when the target is ``visible'' for both reception and transmission, run the search twice, using both aberration correction choices. The result window from the first search can be used as the confinement window for the second. SPICE doesn't have the capability of modeling atmospheric effects, so for observers on bodies having atmospheres, view periods found using the GF subsystem will be subject to errors due to this deficiency. ``Usable'' view periods may be a subset of those found by GF searches, since there may be pointing limitations on the antenna or instrument viewing the target. Subobserver point
min_lon < subobserver longitude < max_lon min_lat < subobserver latitude < max_latFour searches are required: one for each constraint. The searches can be cascaded: the result window for one search can be used as the confinement window for the next. If the longitude interval of interest includes 180 degrees, then
min_lon > max_lonand the corresponding longitude constraints have the form
min_lon < subobserver longitude OR max_lon > subobserver longitudeIn this case the solution window for the longitude constraints is the union of the solution windows for the two constraints shown above; use wnunid_c to compute this union. The union can then be used as the confinement window for a latitude search. The case of a right ascension interval containing 0 degrees is handled analogously. The order of the searches can be important: often constraints on one of the coordinates produce a smaller result window than constraints on the other. For example, for a polar orbiter, latitude constraints may be satisfied over a small fraction of the search window, so searching for times when the latitude constraints are met would yield a small window over which the longitude searches would be conducted. For an equatorial orbiter, the situation would be reversed. Instrument boresight intercept
min_lon < intercept longitude < max_lon min_lat < intercept latitude < max_latFour searches are required: one for each constraint. See the discussion of alternate longitude constraints and of search order above in the section titled ``Subobserver point.'' Note that pointing stability can be an issue for boresight intercept searches: the pointing must be stable enough so that the GF system can compute the time window, within the confinement window, during which the raysurface intercept exists. Highfrequency pointing excursions can cause this ``existence window'' computation to produce invalid results, which in turn will cause the requested coordinate constraint searches to either fail before completion or to complete but produce invalid results. gfsntc_c should not be used for neartangent ray direction cases. gfsntc_c contracts the existence window described above by a fraction of a second to avoid geometric singularities; this affords more robust search behavior for normal cases but prevents gfsntc_c from producing accurate results for neartangent ray pointing. Planet in instrument field of view
gftfov_c may not be suitable for FOV searches involving pushbroom cameras. For an alternate approach, see the example program ROVER below for a demonstration of a search involving the MRO HIRISE camera. Star in instrument field of view
Spacecraft occultation or transit
gfoclt_c assumes straightline light paths for occultation searches. This assumption may not be suitable for highaccuracy work. Natural satellite occultation or transit
Spacecraft eclipse
Use gfoclt_c to search for spacecraft eclipses. Both the Sun and the blocking body should be modeled as ellipsoids. Set the occultation type to
"ANY"to search for times when the spacecraft is in penumbral or umbral eclipse; set the occultation type to
"FULL"to search for times when the spacecraft is in umbral eclipse. gfoclt_c assumes straightline light paths for occultation searches. This assumption may not be suitable for highaccuracy work. Surface point eclipse
Equator crossing
The reference frame should be the bodyfixed, bodycentered frame associated with the body whose equatorial plane is of interest. The coordinate system and coordinate can be set, respectively, to
"RECTANGULAR" "Z"Use the relational description "Z = 0" for the search. Other choices such as
"LATITUDINAL" "LATITUDE"will yield the same results, up to roundoff errors. Use the relational description "LATITUDE = 0" for the search. Note that for a given pair of bodies, when aberration corrections are used, the choice of observer and target affects the result, since aberration corrections are not antisymmetric functions of target and observer. See the Fundamental Concepts SPICE tutorial and the header of spkezr_c for further information on aberration corrections. Meridian crossing
Care must be taken to identify the appropriate coordinate system: is longitude positive East or positive West? For the positive East longitude case, the coordinate system and coordinate can be set to
"LATITUDINAL" "LONGITUDE"respectively. For the positive West longitude case, planetographic longitude can be used, but in some cases, additional setup is required. If the central body is not the Earth, Moon, Sun, or a body with retrograde spin, the selections
"PLANETOGRAPHIC" "LONGITUDE"can be used as is. Use the relational description "LONGITUDE = value" for the search, where value is the angular value for the meridian, expressed in radians. The Earth, Moon, Sun, and bodies with retrograde spin are special cases, because for these objects planetographic longitude is positive East by default. However, this default can be overridden via kernel pool assignments: an application can force planetographic longitude for a given body to increase in the desired sense. See the header of recpgr_c for details. If these assignments are made, then the above choices of coordinate system and coordinate will work for these special cases as well. See the notes on aberration corrections in the section titled ``Equator crossing'' above. Elongation
Orbital longitude of a satellite
The participants in this geometric relationship are an observer, a central body, and a satellite orbiting the central body. For this geometric case, ``orbital longitude'' is measured in the orbital plane of the satellite, in the positive sense about the satellite's angular velocity vector, with the zero longitude direction aligned with the orthogonal projection of the observercentral body vector onto the satellite's orbital plane. This definition is applicable, for example, when the Earth is the observer, Mars is the central body, and Phobos is the satellite. There is a different definition of orbital longitude for the case where the target is a planet, asteroid, or comet and the Earth is the observer: for this case, the SunEarth vector points in direction of zero longitude. We won't address this case, but it can be handled by a simple modification of the ORBITAL_LONG_FRAME we describe below. The first step is to specify a twovector dynamic frame ORBIT_FRAME whose primary axis is aligned with the central bodysatellite position vector; this is the frame's +X axis. Associate the secondary axis with the central bodysatellite velocity vector; this is the frame's +Y axis. The +Z axis of ORBIT_FRAME is then aligned with the instantaneous angular velocity of the satellite's orbit. Next, specify a twovector dynamic frame ORBITAL_LONG_FRAME whose primary axis is aligned with the +Z axis of ORBIT_FRAME; this is the +Z axis of ORBITAL_LONG_FRAME. Associate the secondary axis of ORBITAL_LONG_FRAME with the observercentral body position vector; this is the +X axis of ORBITAL_LONG_FRAME. Finally, call gfposc_c to search for times when the satellite's orbital longitude satisfies constraints of interest. For these searches, the observer is the central body, the target is the satellite, the reference frame is ORBITAL_LONG_FRAME, and the coordinate system and coordinate are, respectively, set to:
"LATITUDINAL" "LONGITUDE"Aberration corrections should not be used for this application. Approximate times of Cassini Saturn ring occultations
For the purpose of this search, the ring boundaries can be approximated using two extremely flat spheroids, both of which are aligned, as is Saturn, with the IAU_SATURN reference frame. The large and small spheroids have equatorial radii equal to, respectively, the radii of the outer and inner ring boundaries. The polar radii can be set to 1 cm. Two searches using gfoclt_c are required: the first search finds the time window when the orbiter is occulted by the larger spheroid. The result window from that search can be used as the confinement window for the second search, which finds the time window when the orbiter is occulted by the inner spheroid. Subtracting the result window of the second search from that of the first yields a window representing the time period of the ring occultations. To avoid having to create new SPICE kernels representing the trajectories, orientations, sizes, shapes, names, and ID codes of the spheroids, one simply creates them by temporarily changing the radii of Saturn. The radii of the spheroids can be set before each gfoclt_c call by either:
For each of the searches, the DSN station is the observer, Saturn (with modified radii) is the ``front'' target body, and the Cassini orbiter is the ``back'' target body. The aberration correction should be set to
"CN"The method described here will not work for edgeon or nearly edgeon viewing geometry: the rayspheroid intercept computation fails to model the real occultation geometry in the first case and is too unstable to provide accurate results in the second. The assumption of straightline radiation paths may also be unsuitable for very highaccuracy work. Angular offset between instrument boresight and velocity
The first step is to create an SPK file for an artificial object whose position relative to the spacecraft's center of mass is parallel to the instrument's boresight direction. The SPICE utility PINPOINT can be used to create such an SPK file. Next, create a specification for a dynamic reference frame whose +Z axis is aligned with the spacecraft velocity vector. The view frame example in the Dynamic Frames tutorial demonstrates this. The colatitude of the vector from the spacecraft to the artificial object, expressed in the view frame, is the desired angular separation. An application program can call gfposc_c with the coordinate system and coordinate, respectively, set to
"SPHERICAL" "COLATITUDE"to conduct the search. Common GF Problems
A challenge
The conclusion to draw is that preventing problems by correctly setting up one's work is even more important for GF searches than for other types of computations. Wrong SPICE kernels
Insufficient kernel data
Some of the common short error messages indicating missing data are:
SPICE(NOTRANSLATION) SPICE(NOFRAME) SPICE(NOFRAMECONNECT) SPICE(FRAMEDATANOTFOUND) SPICE(SPKINSUFFDATA) SPICE(KERNELVARNOTFOUND)In many cases, a careful reading of the SPICE long error message will indicate the cause of the problem. Since it can be frustrating (or worse) to have a search run for a long time, and then have the search terminate due to missing data, we recommend that users verify that the required data are present before starting a search. The section titled ``Required SPICE kernels'' in the chapter ``GF Computational Recipes'' may be helpful. Often it's worthwhile to manually verify the coverage of the SPK and CK files intended to be used in a search; this can be done using the SPICE utilities BRIEF and CKBRIEF. See the user's guides brief.ug and ckbrief.ug for details. It can be very useful for an application to determine a time window over which required SPK and CK data are available. See the discussion and example code dealing with this task in the ROVER code example below. Missed events
Slow performance
Slow performance is not necessarily indicative of an error. For a long search, it may not be evident just how slow the performance really is; one may only know that whatever fraction of the search has been completed has already taken a long time. Users of the Fortran and C SPICE Toolkits can use the midlevel search routines and enable progress reporting to determine a search's rate of progress. All SPICE users can shorten the confinement window until a search completes in a short time, then extrapolate the time required for the entire search. Constraints not met on result window
See the discussion of time windows and window contraction in the ``GF Concepts'' chapter. Result window intervals appear invalid
Possible causes include:
GF Example Programs
All functions used in the examples are from CSPICE. The numerical results shown for these examples may differ across platforms. The results depend on the SPICE kernels used as input, the compiler and supporting libraries, and the machine specific arithmetic implementation. Program MEDLEY: Searches for Periapse, Occultation, Rise/SetOverview
Aberration corrections
For the occultation search, only light time corrections are needed. Normally computations involving apparent geometry of extended objects require correction of target positions for light time and stellar aberration, so the aberration correction flag
"LT+S"would be used. However, stellar aberration corrections are unnecessary for occultation computations, since the respective stellar aberration corrections for the two targets are identical at the point of tangency of the figures of the targets. For this reason the GF occultation function gfoclt_c ignores the stellar aberration correction token
"+S"if it's provided. For the view period search, the apparent position of Saturn is used, so both light time and stellar aberration corrections are applied. SPICE kernels
KPL/MK File: medley.tm Metakernel for example program MEDLEY. This metakernel is intended to support operation of SPICE example programs. The kernels shown here should not be assumed to contain adequate or correct versions of data required by a user's own SPICEbased applications. In order for an application to use this metakernel, the kernels referenced here must be present in the user's current working directory. The names and contents of the kernels referenced by this metakernel are as follows: File name Contents   naif0009.tls Leapseconds pck00008.tpc Planet orientation and radii de421.bsp Planetary ephemeris sat288.bsp Saturn satellite ephemeris earthstns_itrf93_050714.bsp DSN station locations earth_topo_050714.tf DSN station topocentric frame specifications earth_070425_370426_predict.bpc Long term, lowaccuracy Earth orientation Version 1.0.0 23JAN2009 (NJB) \begindata KERNELS_TO_LOAD = ( 'naif0009.tls' 'pck00008.tpc' 'de421.bsp' 'sat288.bsp' 'earthstns_itrf93_050714.bsp' 'earth_topo_050714.tf' 'earth_070425_370426_predict.bpc' ) \begintext [End of kernel] Source code
#include <stdio.h> #include <string.h> #include "SpiceUsr.h" int main() { /* PROGRAM MEDLEY */ /* Local constants */ #define META "medley.tm" #define MAXWIN 200000 #define MAXIVL ( MAXWIN / 2 ) #define TIMFMT "YYYY MON DD HR:MN:SC.###### TDB::RND::TDB" #define TIMLEN 36 /* Local variables */ SPICEDOUBLE_CELL ( cnfine, MAXWIN ); SPICEDOUBLE_CELL ( result, MAXWIN ); SpiceChar * abcorr; SpiceChar begstr [ TIMLEN ]; SpiceChar * back; SpiceChar * bframe; SpiceChar * bshape; SpiceChar * crdsys; SpiceChar * coord; SpiceChar endstr [ TIMLEN ]; SpiceChar * frame; SpiceChar * fframe; SpiceChar * front; SpiceChar * fshape; SpiceChar * obsrvr; SpiceChar * relate; SpiceChar * target; SpiceDouble adjust; SpiceDouble et0; SpiceDouble et1; SpiceDouble finish; SpiceDouble refval; SpiceDouble start; SpiceDouble step; SpiceInt i; /* Set up: load kernels for all tasks. */ furnsh_c ( META ); /*************************************************************** First task: find closest approaches of the Earth to the Sun during the time period 20092019. ***************************************************************/ /* Create a confinement window for the distance search. This window contains the start and stop times of the search interval. */ str2et_c ( "2009 JAN 1", &et0 ); str2et_c ( "2019 JAN 1", &et1 ); wninsd_c ( et0, et1, &cnfine ); /* Set the observer and target. */ obsrvr = "EARTH"; target = "SUN"; /* We're looking for the distance given by the planetary ephemeris, not the apparent distance, so we'll use geometric states. */ abcorr = "NONE"; /* The relational operator for this search is "local minimum." The reference value is unused; simply initialize it to zero. */ relate = "locmin"; refval = 0.0; /* Set the step size for this search. The step must be shorter than the shortest interval over which the distance is increasing or decreasing. We pick a conservative value: 100 days. Units expected by SPICE are TDB seconds. */ step = 100 * spd_c(); /* The adjustment value isn't used for this search; set it to 0. */ adjust = 0.0; /* The number of intervals to be accommodated in the workspace windows to be dynamically allocated by gfdist_c is specified by the parameter MAXIVL. Execute the search. */ printf ( "\nStarting distance search.\n" ); gfdist_c ( target, abcorr, obsrvr, relate, refval, adjust, step, MAXIVL, &cnfine, &result ); printf ( "Done.\n" ); /* Display the times of the local minima of distance. */ printf ( "\nTimes of closest approach of Earth to Sun:\n\n" ); for ( i = 0; i < wncard_c( &result ); i++ ) { /* Fetch the start and stop times of the Ith interval from the window `result'. */ wnfetd_c ( &result, i, &start, &finish ); /* The result window's intervals are singletons, so we display only the start times. */ timout_c ( start, TIMFMT, TIMLEN, begstr ); printf ( " %s %s\n", begstr, endstr ); } /*************************************************************** Second task: find occultations of Titan by Saturn, as seen from DSS14, for the time period January, 2009. ***************************************************************/ /* Find times when Titan is at least partially occulted by Saturn as seen by the observer. The occultation type 'ANY' indicates that any overlap of the back target by the front will be considered an occultation. Create a confinement window for the occultation search. This window contains the start and stop times of the search interval. Empty the window `cnfine', then insert the new time bounds. */ scard_c ( 0, &cnfine ); str2et_c ( "2009 JAN 1", &et0 ); str2et_c ( "2010 JAN 1", &et1 ); wninsd_c ( et0, et1, &cnfine ); /* The step size for the occultation search must be short enough to catch any occultation of interest. We'll look for occultations lasting at least one hour. Units are seconds. */ step = 3600.0; /* Set the observer for the occultation search. */ obsrvr = "DSS14"; /* Set the front and back targets, their shapes, and their bodyfixed reference frame names. */ front = "SATURN"; fshape = "ELLIPSOID"; fframe = "IAU_SATURN"; back = "TITAN"; bshape = "ELLIPSOID"; bframe = "IAU_TITAN"; /* Occultations occur when one apparent object is behind another. Normally we'd use light time and stellar aberration corrections for this case, but stellar aberration corrections are not needed for accurate occultation computations, since at ingress or egress, the respective corrections for target and observer are equal along the direction from the observer to the point of tangency of the figures of the targets. So only light time corrections are used. */ abcorr = "LT"; /* Note that GFOCLT, like the other GF binary state search routines, doesn't use a workspace array, hence there are no workspace dimension inputs. */ printf ( "\n\nStarting Titan occultation search.\n" ); gfoclt_c ( "ANY", front, fshape, fframe, back, bshape, bframe, abcorr, obsrvr, step, &cnfine, &result ); printf ( "Done.\n" ); if ( wncard_c( &result ) == 0 ) { printf ( "\nNo occultations were found.\n" ); } else { printf ( "\nTimes of occultation of Titan by Saturn:\n\n" ); for ( i = 0; i < wncard_c( &result ); i++ ) { /* Fetch the start and stop times of the Ith interval from the window `result'. */ wnfetd_c ( &result, i, &start, &finish ); timout_c ( start, TIMFMT, TIMLEN, begstr ); timout_c ( finish, TIMFMT, TIMLEN, endstr ); printf ( " %s %s\n", begstr, endstr ); } } /*************************************************************** Third task: find view periods (periods of visibility) for Saturn, as seen from DSS14, for the time period January 15, 2009. ***************************************************************/ /* We'll consider Saturn to be visible from DSS14 when Saturn has elevation above 6 degrees in the DSS14 topocentric reference frame DSS14_TOPO. Create a confinement window for the view period search. This window contains the start and stop times of the search interval. Empty the window `cnfine', then insert the new time bounds. */ scard_c ( 0, &cnfine ); str2et_c ( "2009 JAN 1", &et0 ); str2et_c ( "2009 JAN 5", &et1 ); wninsd_c ( et0, et1, &cnfine ); /* Set the observer, target and reference frame. */ obsrvr = "DSS14"; target = "SATURN"; frame = "DSS14_TOPO"; /* The coordinate system is latitudinal; in this system, in the DSS14_TOPO frame, the coordinate "latitude" is equivalent to elevation. */ crdsys = "LATITUDINAL"; coord = "LATITUDE"; /* The relational operator for this search is "greater than" and the reference value is 6 degrees (converted to radians). */ relate = ">"; refval = 6.0 * rpd_c(); /* We're looking for the apparent position of Saturn, so apply corrections for light time and stellar aberration. */ abcorr = "LT+S"; /* Set the step size for this search. The step must be shorter than the shortest interval over which the elevation is increasing or decreasing. We pick a conservative value: 6 hours. Units expected by SPICE are TDB seconds. */ step = spd_c() / 4; /* The adjustment value isn't used for this search; set it to 0. */ adjust = 0.0; /* The number of intervals to be accommodated in the workspace windows to be dynamically allocated by gfposc_c is specified by the parameter MAXIVL. Execute the search. */ printf ( "\n\nStarting elevation search.\n" ); gfposc_c ( target, frame, abcorr, obsrvr, crdsys, coord, relate, refval, adjust, step, MAXIVL, &cnfine, &result ); printf ( "Done.\n" ); /* Display the times of rise and set. */ printf ( "\nTimes of Saturn rise/set as seen from DSS14:\n\n" ); for ( i = 0; i < wncard_c( &result ); i++ ) { /* Fetch the start and stop times of the Ith interval from the window `result'. */ wnfetd_c ( &result, i, &start, &finish ); timout_c ( start, TIMFMT, TIMLEN, begstr ); timout_c ( finish, TIMFMT, TIMLEN, endstr ); printf ( " %s %s\n", begstr, endstr ); } printf ( "\n" ); return ( 0 ); } Results
The output from this program was as follows:
Starting distance search. Done. Times of closest approach of Earth to Sun: 2009 JAN 04 15:30:45.589082 TDB 2010 JAN 03 00:10:21.610041 TDB 2011 JAN 03 18:33:04.989377 TDB 2012 JAN 05 00:32:57.166524 TDB 2013 JAN 02 04:38:41.978883 TDB 2014 JAN 04 11:59:41.025358 TDB 2015 JAN 04 06:37:17.796385 TDB 2016 JAN 02 22:49:53.333439 TDB 2017 JAN 04 14:18:58.873657 TDB 2018 JAN 03 05:35:52.459640 TDB Starting Titan occultation search. Done. Times of occultation of Titan by Saturn: 2009 JAN 15 17:17:13.408673 TDB 2009 JAN 15 23:24:45.666928 TDB 2009 JAN 31 15:31:34.392257 TDB 2009 JAN 31 21:17:02.978691 TDB 2009 FEB 16 13:38:51.079255 TDB 2009 FEB 16 18:34:44.780780 TDB 2009 MAR 04 12:01:10.277826 TDB 2009 MAR 04 15:11:39.545971 TDB 2009 JUL 25 23:54:05.774966 TDB 2009 JUL 26 04:00:27.167482 TDB 2009 AUG 10 23:28:28.728724 TDB 2009 AUG 11 05:13:21.654337 TDB 2009 AUG 26 23:41:29.894421 TDB 2009 AUG 27 06:07:25.788109 TDB 2009 SEP 12 00:24:15.048030 TDB 2009 SEP 12 06:43:07.257580 TDB 2009 SEP 28 01:35:28.489195 TDB 2009 SEP 28 06:53:19.855589 TDB 2009 OCT 14 03:32:20.159136 TDB 2009 OCT 14 06:11:58.766312 TDB Starting elevation search. Done. Times of Saturn rise/set as seen from DSS14: 2009 JAN 01 06:52:14.372881 TDB 2009 JAN 01 18:20:41.050047 TDB 2009 JAN 02 06:48:17.641267 TDB 2009 JAN 02 18:16:45.859623 TDB 2009 JAN 03 06:44:20.383435 TDB 2009 JAN 03 18:12:50.385687 TDB 2009 JAN 04 06:40:22.601451 TDB 2009 JAN 04 18:08:54.628325 TDB Program CASCADE: Fast Search for Solar EclipseOverview
The price we pay to achieve this speedup is that we must perform a little analysis of the observation geometry in order to decide how to perform the preliminary search. In this example, we use DSN station DSS14 as the observer. We have an SPK file providing the geocentric station location in the ITRF93 terrestrial reference frame, so we're able to treat the observer as a SPICE ephemeris object. For an arbitrary surface point, we could use the SPICE utility PINPOINT to create an SPK file containing that point's geocentric location. We consider a solar eclipse to be any (partial or full) occultation of the apparent Sun by the apparent Moon, so we perform the eclipse search using the GF occultation search routine gfoclt_c. We're interested in detecting any occultation lasting a minute or more, so we use a step size of 60 seconds for this search. Since we're searching over a time span of one year, this search, if performed over the entire search interval, would require over 31 million occultation tests. To accelerate the search, we'll first narrow down the search period using a more rapid searchone for which we can use a step size of days, not seconds. We know an occultation can occur only when the angular separation of the Sun and Moon as seen from DSS14 is small. If we can quickly find the time window over which the angular separation of the apparent figures of the Sun and Moon is less than a small upper bound, we can then gain speed by performing the slower occultation search only over this small window. Specifying the angular separation search parameters
Recall that GF searches involving a scalar quantity, such as angular separation, have search step size requirements based on the separation in time of the local extrema of the quantity: except for longitude searches, the step must be smaller than the minimum time separation between the epochs of the extrema (minima and maxima) of the quantity, taken over the search interval. When these extrema are widely separated, a large step size can be used. So that we can pick a useful lower bound on the time separation of the extrema of angular separation, we want to define angular separation in such a way that this function is easy to analyze. There are two candidate observers we could use to define the angular separation of Sun and Moon: DSS14 and the center of the Earth. If we use the center of the Earth, the relative angular velocity of the targets has only small relative variations in magnitude, except in the vicinity of its extrema, and we can be confident that we won't find any unexpected extrema of angular separation; however the angular separation we compute is slightly different than what we'd find using DSS14 as the observer. If we use DSS14 as the observer, we must consider whether the motion of the station relative to the center of the Earth introduces any additional extrema of angular separation beyond those occurring when the observer is the Earth's center. Since we can easily bound the angular separation error caused by using the Earth's center as the observer, we'll choose this observer, thus simplifying our analysis. The maximum angular separation error caused by this choice is roughly 1 degree; we'll conservatively pick 2 degrees as the error bound. If we pick a generous limit of 1 degree for angular separation of the figures of the Sun and Moon as seen from DSS14, adding 2 degrees to this yields the 3 degree bound we'll use for the angular separation search. The angular separation of Sun and Moon as seen from the center of the Earth has a period of about four weeks. The local minima and maxima of the separation are separated by roughly two weeks. Since we don't want to perform a detailed analysis of the minimum time separation of the extrema, we simply pick a value that's guaranteed to be smaller than this minimum duration but large enough to be helpful: 5 days. If we were to perform this search repeatedly, it could be useful to analyze the problem further in order to compute a tighter angular separation bound and a smaller step size. Aberration corrections
"LT+S"would be used. However, stellar aberration corrections are unnecessary for occultation computations, since the respective stellar aberration corrections for the two targets are identical at the point of tangency of the figures of the targets. For this reason the GF occultation function gfoclt_c ignores the stellar aberration correction token
"+S"if it's provided. Only light time corrections are needed for the occultation search. SPICE kernels
KPL/MK File: cascade.tm Metakernel for example program CASCADE. This metakernel is intended to support operation of SPICE example programs. The kernels shown here should not be assumed to contain adequate or correct versions of data required by a user's SPICEbased applications. In order for an application to use this metakernel, the kernels referenced here must be present in the user's current working directory. The names and contents of the kernels referenced by this metakernel are as follows: File name Contents   de421.bsp Planetary ephemeris pck00008.tpc Planet orientation and radii naif0009.tls Leapseconds earthstns_itrf93_050714.bsp DSN station locations earth_070425_370426_predict.bpc Long term, lowaccuracy Earth orientation Version 1.0.0 13JAN2009 (NJB) \begindata KERNELS_TO_LOAD = ( 'naif0009.tls' 'pck00008.tpc' 'de421.bsp' 'earthstns_itrf93_050714.bsp' 'earth_070425_370426_predict.bpc' ) \begintext [End of kernel] Source code
#include <stdio.h> #include <string.h> #include "SpiceUsr.h" int main() { /* PROGRAM CASCADE */ /* Local constants */ #define META "cascade.tm" #define MAXWIN 200000 #define MAXIVL ( MAXWIN / 2 ) #define TIMFMT "YYYY MON DD HR:MN:SC.###### TDB::RND::TDB" #define TIMLEN 36 /* Local variables */ SPICEDOUBLE_CELL ( cnfine, MAXWIN ); SPICEDOUBLE_CELL ( result, MAXWIN ); SpiceChar * abcorr; SpiceChar begstr [ TIMLEN ]; SpiceChar endstr [ TIMLEN ]; SpiceChar * obsrvr; SpiceChar * relate; SpiceDouble adjust; SpiceDouble avg; SpiceDouble et0; SpiceDouble et1; SpiceDouble finish; SpiceDouble limit; SpiceDouble measur [2]; SpiceDouble start; SpiceDouble stddev; SpiceDouble step; SpiceInt i; SpiceInt longidx; SpiceInt shortidx; /* Load kernels. */ furnsh_c ( META ); /* Create a confinement window for an angular separation search. This window contains the start and stop times of the search interval. */ str2et_c ( "2008 JAN 1", &et0 ); str2et_c ( "2009 JAN 1", &et1 ); wninsd_c ( et0, et1, &cnfine ); /* Save the measure of this window. */ measur[0] = et1  et0; /* Set the observer for the angular separation search. */ obsrvr = "EARTH"; /* We don't need high precision for the angular separation search: we could use uncorrected states, which are be computed more quickly than aberration corrected states. But for simplicity of the code, we'll use the same aberration corrections for the angular separation and occultation searches. Use light time correction. Stellar aberration correction is not helpful for occultation searches, so the stellar aberration flag "+S" is ignored by gfoclt_c. */ abcorr = "LT"; /* Find times when the angular separation of the Sun and Moon is below the specified limit, as seen by the observer. We can use the centers of the objects for this search. Set the angular separation limit of 3 degrees. Units accepted by SPICE are radians, so do the conversion here. */ limit = 3.0 * rpd_c(); /* The relational operator for this search is "less than." */ relate = "<"; /* Set the step size for this search. The step must be shorter than the shortest interval over which the angular separation is increasing or decreasing. We pick a conservative value: 5 days. Units expected by SPICE are TDB seconds. */ step = 5.0 * spd_c(); /* The adjustment value isn't used for this search; set it to 0. */ adjust = 0.0; /* Execute the search. Note that we can leave the bodyfixed frame arguments blank, since they're not used for point targets. */ printf ( "\nStarting angular separation search.\n" ); gfsep_c ( "MOON", "POINT", " ", "SUN", "POINT", " ", abcorr, obsrvr, relate, limit, adjust, step, MAXIVL, &cnfine, &result ); printf ( "Done.\n" ); /* Use the result window from this search as the confinement window for the occultation search. */ copy_c ( &result, &cnfine ); /* Save the measure of this window. This window contains multiple intervals, so we sum their lengths. We could do this in a loop, but it's even easier to call the window summary routine wnsumd_c. */ wnsumd_c ( &cnfine, measur+1, &avg, &stddev, &shortidx, &longidx ); printf ( "\nRatio of measure of short confinement " "window to original:\n" ); if ( measur[0] == 0.0 ) { sigerr_c ( "SPICE(DIVIDEBYZERO" ); } printf ( "%f\n", measur[1] / measur[0] ); /* Find times when the Sun is at least partially occulted by the Moon as seen by the observer. The occultation type "ANY" indicates that any overlap of the back target by the front will be considered an occultation. The step size for the occultation search must be short enough to catch any occultation of interest. We choose 60 seconds. */ step = 60.0; /* Set the observer for the occultation search. */ obsrvr = "DSS14"; printf ( "\nStarting occultation search.\n" ); gfoclt_c ( "ANY", "MOON", "ELLIPSOID", "IAU_MOON", "SUN", "ELLIPSOID", "IAU_SUN", abcorr, obsrvr, step, &cnfine, &result ); printf ( "Done.\n\n" ); if ( wncard_c( &result ) == 0 ) { printf ( "No occultations were found.\n" ); } else { printf ( "Occultations:\n" ); for ( i = 0; i < wncard_c( &result ); i++ ) { /* Fetch the start and stop times of the Ith interval from the window `result'. */ wnfetd_c ( &result, i, &start, &finish ); timout_c ( start, TIMFMT, TIMLEN, begstr ); timout_c ( finish, TIMFMT, TIMLEN, endstr ); printf ( " %s %s\n", begstr, endstr ); } } printf ( "\n" ); return ( 0 ); } Results
The output from this program was as follows:
Starting angular separation search. Done. Ratio of measure of short confinement window to original: 0.004972 Starting occultation search. Done. Occultations: 2008 AUG 01 08:40:50.967887 TDB 2008 AUG 01 10:00:42.048379 TDBOn this platform, the (wall clock) run time was about 0.75 seconds. When the angular separation search was removed (this can be done by commenting out the copy_c call in the source code), the run time was about 130 seconds. Program ROVER: Mars Reconnaissance Orbiter photographs MER1Overview
Determining SPK and CK coverage at run time
Speeding up the search
Pointing issues
Substantial deviation from the nominal nadirpointed spacecraft orientation could also prevent the HIRISE FOV from ``seeing'' the target. Based on prior knowledge, we expect this search to find two solutions. The results of the search will show that the solutions are the ones we want: we have nearnadir pointing at the visibility epochs in each case. In a more realistic setting, we would need to ensure that no valid solutions were missed. This could be done by reducing the step size for the MRO_HIRISE_LOOK_DIRECTION frame's YZ plane crossing search. Alternatively, the spacecraft pointing could be analyzed for the time window over which the YZ plane crossing search is performed. Aberration corrections
"LT+S" SPICE kernels
The metakernel used for this example is shown below.
KPL/MK File: rover.tm Metakernel for example program ROVER. This metakernel is intended to support operation of SPICE example programs. The kernels shown here should not be assumed to contain adequate or correct versions of data required by a user's SPICEbased application. In order for an application to use this metakernel, the kernels referenced here must be present in the user's current working directory. The names and contents of the kernels referenced by this metakernel are as follows: File name Contents   de421.bsp Planetary ephemeris pck00008.tpc Planet orientation and radii naif0009.tls Leapseconds mro_v11.tf MRO frame specifications mro_hirise_v10.ti MRO HIRISE instrument parameters mro_sc_psp_061031_061106.bc MRO orientation mro_sc_psp_061107_061113.bc MRO orientation mro_sc_psp_061114_061120.bc MRO orientation mro_sc_psp_061121_061127.bc MRO orientation mro_sc_psp_061128_061204.bc MRO orientation mro_sclkscet_00026_65536.tsc MRO SCLK parameters and correlation data mro_psp1.bsp MRO ephemeris mer1_v10.tf MER1 frame specifications mer1_surf_rover_ext10_v1.bsp MER1 ephemeris mer1_surf_rover_ext11_v1.bsp MER1 ephemeris mer1_ls_040128_iau2000_v1.bsp MER1 landing site location Version 1.0.0 25JAN2009 (NJB) \begindata KERNELS_TO_LOAD = ( 'naif0009.tls' 'pck00008.tpc' 'de421.bsp' 'mro_v11.tf' 'mro_hirise_v10.ti' 'mro_sc_psp_061031_061106.bc' 'mro_sc_psp_061107_061113.bc' 'mro_sc_psp_061114_061120.bc' 'mro_sc_psp_061121_061127.bc' 'mro_sc_psp_061128_061204.bc' 'mro_sclkscet_00026_65536.tsc' 'mro_psp1.bsp' 'mer1_v10.tf' 'mer1_surf_rover_ext10_v1.bsp' 'mer1_surf_rover_ext11_v1.bsp' 'mer1_ls_040128_iau2000_v1.bsp' ) \begintext [End of kernel] Source code
#include <stdlib.h> #include <stdio.h> #include <string.h> #include <math.h> #include "SpiceUsr.h" int main() { /* PROGRAM ROVER */ /* Local constants */ #define FILSIZ 256 #define META "rover.tm" #define MAXWIN 200000 #define MAXIVL ( MAXWIN / 2 ) #define TIMFMT "YYYY MON DD HR:MN:SC.###### TDB::RND::TDB" #define TIMLEN 36 #define TYPLEN 11 #define UNTLEN 26 /* Local variables */ SPICEDOUBLE_CELL ( ckwmro, MAXWIN ); SPICEDOUBLE_CELL ( cnfine, MAXWIN ); SPICEDOUBLE_CELL ( distwn, MAXWIN ); SPICEDOUBLE_CELL ( result, MAXWIN ); SPICEDOUBLE_CELL ( spwmer, MAXWIN ); SPICEDOUBLE_CELL ( spwmro, MAXWIN ); SpiceBoolean found; SpiceChar * abcorr; SpiceChar begstr [ TIMLEN ]; SpiceChar ckname [ FILSIZ ]; SpiceChar * coord; SpiceChar * crdsys; SpiceChar endstr [ TIMLEN ]; SpiceChar ftype [ TYPLEN ]; SpiceChar * frame; SpiceChar * obsrvr; SpiceChar * relate; SpiceChar source [ FILSIZ ]; SpiceChar spknam [ FILSIZ ]; SpiceChar * target; SpiceChar timstr [ TIMLEN ]; SpiceChar units [ UNTLEN ]; SpiceDouble adjust; SpiceDouble avg; SpiceDouble finish; SpiceDouble hfov; SpiceDouble lt; SpiceDouble measur; SpiceDouble nudge; SpiceDouble refang; SpiceDouble refval; SpiceDouble start; SpiceDouble stddev; SpiceDouble step; SpiceDouble trgpos [3]; SpiceInt handle; SpiceInt i; SpiceInt longidx; SpiceInt mercde; SpiceInt mrobus; SpiceInt mrocde; SpiceInt n; SpiceInt shortidx; /* Load kernels. */ furnsh_c ( META ); /* Get the count of loaded CKs. */ ktotal_c ( "CK", &n ); /* For each loaded CK, get the coverage, if any, for the MRO s/c bus. Combine this coverage with that already found. */ mrobus = 74000; for ( i = 0; i < n; i++ ) { kdata_c ( i, "CK", FILSIZ, TYPLEN, FILSIZ, ckname, ftype, source, &handle, &found ); /* Get coverage at the interpolation interval level. Angular velocity is not required. Tolerance is 0 seconds. Return the window times as TDB values. */ ckcov_c ( ckname, mrobus, SPICEFALSE, "INTERVAL", 0.0, "TDB", &ckwmro ); } /* Contract each interval of the coverage window by 1 microsecond on both sides to protect against roundoff error in the SCLKtoTDB conversion performed by CKCOV. */ nudge = 1.e6; wncond_c ( nudge, nudge, &ckwmro ); /* Get coverage of both the MRO and MER1 SPK files. */ ktotal_c ( "SPK", &n ); bodn2c_c ( "MRO", &mrocde, &found ); if ( !found ) { setmsg_c ( "Could not map MRO to an id code" ); sigerr_c ( "SPICE(NOTRANSLATION)" ); } bodn2c_c ( "MER1", &mercde, &found ); if ( !found ) { setmsg_c ( "Could not map MER1 to an id code" ); sigerr_c ( "SPICE(NOTRANSLATION)" ); } for ( i = 0; i < n; i++ ) { kdata_c ( i, "SPK", FILSIZ, TYPLEN, FILSIZ, spknam, ftype, source, &handle, &found ); spkcov_c ( spknam, mrocde, &spwmro ); spkcov_c ( spknam, mercde, &spwmer ); } /* Contract the intervals of the MER1 SPK window on their left sides to account for light time correction. Note that we may look up the position of MER1 relative to MRO even when MER1 is not visible, so the contraction amount must be large enough to ensure data availability when MRO and MER1 are on opposite sides of Mars. */ nudge = 5.e2; wncond_c ( nudge, 0.0, &spwmer ); /* Let the confinement window be the intersection of the CK and SPK kernel coverage windows. */ wnintd_c ( &ckwmro, &spwmro, &result ); wnintd_c ( &spwmer, &result, &cnfine ); /* Contract the confinement window by a bit more than 1 second on both sides to account for the times at which data will be required to compute observer acceleration. */ nudge = 1.001; wncond_c ( nudge, nudge, &cnfine ); printf ( "\n" ); if ( wncard_c( &cnfine ) == 0 ) { printf ( "The coverage window is empty.\n" ); } else { printf ( "Common MRO CK, MRO SPK and " "MER SPK coverage:\n" ); for ( i = 0; i < wncard_c( &cnfine ); i++ ) { /* Fetch the start and stop times of the Ith interval from the window `cnfine'. */ wnfetd_c ( &cnfine, i, &start, &finish ); timout_c ( start, TIMFMT, TIMLEN, begstr ); timout_c ( finish, TIMFMT, TIMLEN, endstr ); printf ( " %s %s\n", begstr, endstr ); } } wnsumd_c ( &cnfine, &measur, &avg, &stddev, &shortidx, &longidx ); printf ( "Measure of coverage window (sec): %15.6f\n", measur ); /* Find times during our coverage window when the distance between MER1 and MRO is less than 500 km. We're not interested in other viewing opportunities. */ target = "MER1"; obsrvr = "MRO"; abcorr = "NONE"; relate = "<"; refval = 500.0; adjust = 0.0; /* Pick a time step smaller than half the orbital period, but large enough for a fast search. Units are seconds. Store the resulting window in DISTWN. */ step = 1800.0; printf ( "\nStarting distance search.\n" ); gfdist_c ( target, abcorr, obsrvr, relate, refval, adjust, step, MAXIVL, &cnfine, &distwn ); printf ( "Done.\n" ); wnsumd_c ( &distwn, &measur, &avg, &stddev, &shortidx, &longidx ); printf ( "Measure of distance window (sec): %15.6f\n", measur ); /* Find times during the window DISTWN when the apparent position of MER1 relative to MRO lies on the Yaxis of the MRO_HIRISE_LOOK_DIRECTION frame. */ target = "MER1"; obsrvr = "MRO"; frame = "MRO_HIRISE_LOOK_DIRECTION"; abcorr = "LT+S"; crdsys = "RECTANGULAR"; coord = "X"; relate = "="; refval = 0.0; adjust = 0.0; /* Pick a time step small enough so that the search is unlikely to miss the events, but large enough for a fast search. Set the step to 1/2 hour. Units are seconds. */ step = 1800.0; printf ( "\nStarting MRO_HIRISE_LOOK_DIRECTION frame's\n" "YZ plane crossing search.\n" ); gfposc_c ( target, frame, abcorr, obsrvr, crdsys, coord, relate, refval, adjust, step, MAXIVL, &distwn, &result ); printf ( "Done.\n" ); /* Display the YZ plane crossings for which the magnitude of the target's Y angular offset from the camera frame's XZ plane is less than the angular halfwidth of the HIRISE nominal FOV. Look up this halfwidth here. */ gdpool_c ( "INS74699_FOV_REF_ANGLE", 0, 1, &n, &refang, &found ); if ( !found ) { printf ( "Could not find data for HIRISE nominal FOV.\n" ); exit(1); } /* Look up units for the angle; convert the angle to radians. */ gcpool_c ( "INS74699_FOV_ANGLE_UNITS", 0, 1, UNTLEN, &n, units, &found ); if ( !found ) { printf ( "Could not find units for HIRISE nominal FOV.\n" ); exit(1); } convrt_c ( refang, units, "RADIANS", &hfov ); if ( wncard_c(&result) == 0 ) { printf ( "The visibility window is empty.\n" ); } else { printf ( "\nTimes of MER1 visibility within " "MRO HIRISE nominal FOV swath:\n\n" ); for ( i = 0; i < wncard_c( &result ); i++ ) { /* Fetch the start and stop times of the Ith interval from the window `result'. */ wnfetd_c ( &result, i, &start, &finish ); spkpos_c ( target, start, frame, abcorr, obsrvr, trgpos, < ); if ( fabs( atan2( trgpos[1], trgpos[2] ) ) < hfov ) { /* The target lies within the nominal HIRISE swath. */ timout_c ( start, TIMFMT, TIMLEN, timstr ); printf ( " %s\n\n", timstr ); printf ( " Frame: %s\n\n", frame ); printf ( " Target Xcoordinate (km): %15.6f\n", trgpos[0] ); printf ( " Target Ycoordinate (km): %15.6f\n", trgpos[1] ); printf ( " Target Zcoordinate (km): %15.6f\n", trgpos[2] ); printf ( " Target range (km): %15.6f\n", vnorm_c(trgpos) ); printf ( "\n\n" ); } } } return ( 0 ); } Results
The output from this program was as follows:
Common MRO CK, MRO SPK and MER SPK coverage: 2006 OCT 31 00:01:06.180062 TDB 2006 NOV 06 22:21:31.968150 TDB 2006 NOV 06 22:24:36.379454 TDB 2006 NOV 15 16:38:42.527264 TDB 2006 NOV 15 16:45:46.551315 TDB 2006 NOV 15 16:46:00.550204 TDB 2006 NOV 15 16:53:51.675814 TDB 2006 NOV 15 23:09:04.754778 TDB 2006 NOV 15 23:13:33.469771 TDB 2006 DEC 05 00:02:04.052144 TDB Measure of coverage window (sec): 3022709.596123 Starting distance search. Done. Measure of distance window (sec): 6455.262006 Starting MRO_HIRISE_LOOK_DIRECTION frame's YZ plane crossing search. Done. Times of MER1 visibility within MRO HIRISE nominal FOV swath: 2006 NOV 14 15:41:02.511527 TDB Frame: MRO_HIRISE_LOOK_DIRECTION Target Xcoordinate (km): 0.000001 Target Ycoordinate (km): 0.893623 Target Zcoordinate (km): 278.011537 Target range (km): 278.012973 2006 NOV 30 01:39:40.509680 TDB Frame: MRO_HIRISE_LOOK_DIRECTION Target Xcoordinate (km): 0.000001 Target Ycoordinate (km): 0.577715 Target Zcoordinate (km): 267.423792 Target range (km): 267.424416 Appendix A  Summary of GF FunctionsSummary of Mnemonics
Many of the lowerlevel CSPICE functions have SPICELIB counterparts implemented in Fortran as entry points of another function.
gfbail_c Test for interrupt gfclrh_c Clear interrupt handler gfdist_c Distance search gfevnt_c Midlevel scalar constraint search gffove_c Midlevel FOV intersection search gfilum_c Illumination angle search gfinth_c Interrupt signal handler gfocce_c Midlevel occultation search gfoclt_c Find occultation gfpa_c Phase angle search gfposc_c Position coordinate search gfrefn_c Refine solution bounds gfrepf_c Finalize progress report gfrepi_c Initialize progress report gfrepu_c Update progress report gfrfov_c RayFOV intersection search gfrr_c Range rate search gfsep_c Angular separation search gfsntc_c Surface intercept coordinate search gfsstp_c Set search step size gfstep_c Get search step size gfstol_c Set/reset GF search tolerance gfsubc_c Subobserver coordinate search gftfov_c TargetFOV intersection search gfudb_c User defined boolean function search gfuds_c User defined scalar function search Appendix B  Revision History2017 JUN 19 by N. J. Bachman
2012 OCT 01 by E. D. Wright.
Edits to description of orbital longitude. 2010 MAY 13 by E. D. Wright.
2009 APR 15 by N. J. Bachman.
