Geometry Finder Required Reading

Index Page Geometry Finder Required Reading
## Table of Contents
       Geometry Finder Required Reading
          Abstract
             Purpose
             Intended Audience
             References
          Introduction
          Planned enhancements
          Terminology
       GF API Routines
          High-level GF search routines
          Mid-level GF search routines
             Rationale for calling mid-level GF search routines
             Supporting utility routines
             Overriding default functionality
       GF Computational Recipes
          Required SPICE kernels
          A note about CK data availability
          Geometric constraint searches
             Periapse/Apoapse
             View periods
             Sub-observer 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
             Body-centered phase angle without aberration corrections
             Orbital longitude of a satellite
             Approximate times of Cassini Saturn ring occultations
             Angular offset between instrument boresight and velocity
       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
       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 MER-1
             Overview
             Determining SPK and CK coverage at run time
             Speeding up the search
             Pointing issues
             Aberration corrections
             SPICE kernels
             Source code
       Appendix A --- Summary of GF Functions
          Summary of Mnemonics
       Appendix B---Revision History
Top # Geometry Finder Required Reading Last revised on 2009 APR 15 by N. J. Bachman. Top ## Abstract The SPICE Geometry Finder (GF) subsystem finds time windows over which user-specified geometric conditions are met. Top ### Purpose This document is a reference guide for the SPICE GF subsystem. Here you'll find `--` A list of the subsystem's API (application programming interface) routines---these are the routines that may be called directly by SPICE-based user application code `--` Computational ``recipes'' for a variety of GF applications `--` Discussions of concepts essential to understanding the correct use of the GF subsystem `--` Discussion of problems that may arise when using the GF subsystem `--` Extensive example programs, including overview discussion, source code, meta-kernels, and program output Top ### Intended Audience This document addresses the needs of several groups of SPICE users. Users looking for a basic discussion the capabilities of the SPICE GF subsystem should read the introduction below. Users planning to write application code using the GF subsystem may benefit from reading the entire document, but in any case should read the ``GF Concepts'' chapter. This document assumes you already have a strong understanding of SPICE concepts and terminology. Top ### References The references listed below provide essential background for programmers intending to use the GF subsystem. `1.` SPICE Tutorials (available on the NAIF web site) `2.` Cells Required Reading (cells.req) `3.` Windows Required Reading (windows.req) Top ## Introduction Most geometry computations performed with SPICE involve calculating quantities of interest---such as distances, vectors, angles, or orientations---for specified times. The GF subsystem solves the inverse problem: it finds times when specified geometric conditions are met. 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: `--` Angular separation of targets as seen by a specified observer `--` Coordinates of position vectors `--` Coordinates of sub-observer points `--` Coordinates of surface intercept points `--` Distance between target and observer `--` Instrument FOV (Field of view) visibility states (appearance of a specified target within an instrument FOV) `--` Occultation states At the highest level of the SPICE GF subsystem interface, there is a search subroutine for each geometric quantity. The Fortran and C SPICE Toolkits contain additional, lower-level routines that provide functionality such as support for progress reporting and interrupt handling. The full set of interface routines is discussed in the chapter titled ``GF API Routines.'' 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. Top ## Planned enhancements NAIF expects to expand the set of supported quantities in future versions of the CSPICE Toolkit. Planned additions include, but are not limited to: `--` Eclipse events `--` Illumination angles `--` Observer-target range rate `--` Support for user-defined geometric quantities Top ## Terminology Throughout this document we use terms such as SPICE window, root finding, convergence, etc. We include brief explanations of these terms below. Absolute extremum See Global extremum (below). API ``Application programming interface'': a set of routines intended to be called directly by SPICE based user application programs. Also an adjective indicating that a designated routine is a member of the set of API routines, for example ``gfposc_c is a GF API routine.'' Aberration correction Correction for light time or stellar aberration effects. These corrections can involve adjustment of position or direction vectors, orientation of objects, or times. See the header of spkezr_c and the Fundamental Concepts tutorial for details. Bounds Values that constrain the range of values in a specified set of numbers: A is a lower bound for a set S if no member of S is less than A; B is an upper bound for S if no member of S is greater than B. Note that bounds are not equivalent to extrema. Binary state function A function whose range is comprised of only two values, for example 0 and 1 or ``true'' and ``false.'' Boresight A vector or ray used to indicate the ``look direction'' of an instrument. Bracket A number X is bracketed by numbers A and B when X lies between A and B, inclusive. Closed An interval is ``closed'' if it contains its endpoints. Confinement window The time window over which a GF search is to be conducted, or a SPICE window (see below) representing this time window. Converge A sequence of numbers converges if the sequence tends to a limit. Convergence The act of converging; progress toward or completion of the process of locating a root. Convergence tolerance A GF root-finding process is considered to have found a root when the root is bracketed by upper and lower bounds that differ by no more than a specified bound called the ``convergence tolerance.'' Coordinate A spatial parameter belonging to a coordinate system. Coordinate system In SPICE documentation, three-dimensional ``coordinate systems'' are parameterizations of three-dimensional space: they are mappings that label each point in space using an ordered set of three spatial parameters such as (X, Y, Z) or (radius, longitude, latitude). At any point in space, the directions in which the three coordinates increase are mutually orthogonal. Put another way, the Jacobian matrices of these mappings are not orthogonal, but they do have orthogonal sets of rows and columns. (Compare to ``reference frame'' below.) Coverage In SPICE documentation, ``coverage'' refers to the extent of data provided by a set of SPICE kernels: either the time window for which data are available, or less commonly, the set of bodies or instruments for which data are available. Coverage window The time window over which data of interest are available, or a SPICE window (see below) representing this time window. Disjoint Non-intersecting. Domain The set of points on which a function acts: a function ``maps'' elements of its domain to a set called the ``range'' of the function. DSN Deep Space Network. Eclipse An object is ``eclipsed'' or ``in eclipse'' when it intersects the shadow created by the Sun and another object. Endpoints The boundary values of an interval on the real line. The left endpoint of an interval is its smallest value; the right endpoint is its greatest. Ephemeris object Any entity whose position and velocity, relative to a specified center of motion, are given by an SPK file. Extended Object Also extended body or extended target. An object of finite size; an object consisting of more than a single point. In SPICE applications, extended objects are often represented by ellipsoids. Extrema Plural of extremum. Extremum The minimum or maximum value attained by a function. See Global Extremum and Local Extremum. FOV Abbreviation of ``field of view.'' Field of view The spatial region that can be viewed by a remote sensing instrument, or a mathematical model of this region. Often an instrument's field of view is modeled by a cone or a pyramid having a polygonal cross section. Global extremum A global maximum or minimum: the unique greatest or least value attained by a function. It is possible for a function to have multiple locations in its domain at which a global extremum occurs. Instrument In the GF setting, an instrument is usually a camera or other remote-sensing radiation detector whose orientation is given by a reference frame known to the SPICE system and which has a field of view modeled by an IK. Interrupt handler A routine that performs an action in response to an interrupt signal, such as that generated by a user hitting the ``control Y'' key combination at a Unix command line. Inverse problem Inverse problems entail finding times when geometric quantities take on specified values. In general, inverse problems involve finding the set S in the domain of a function such that the function maps S to a specified set. Local extremum A local maximum or local minimum: the greatest or least value attained by a function in a neighborhood of a point in the function's domain. At a point where a local extremum of a function is attained, there is a region or ``neighborhood'' enclosing that point over which the function is bounded by that extreme value. For a local maximum, on this region, the function is no greater than the the local maximum; for a local minimum, the function is no smaller. A function can have multiple local extrema. Measure The measure of a SPICE window is the sum of the lengths of the window's intervals. (This definition is valid because the intervals of a SPICE window are disjoint.) Meta-kernel A SPICE text kernel specifying names of SPICE kernels to load. Number line The ``real line'' (see below). Observer An ephemeris object, the location of which acts as the tail of a position vector. The head of the vector is the location of another ephemeris object called the ``target.'' Observer-target vector A vector emanating from one ephemeris object (the observer) and terminating at another (the target). Occultation Blockage of the apparent figure of one object by another, as seen from a specified vantage point. Range [1] The set of values attained by a function: a function ``maps'' elements of its domain to its range. [2] The Euclidean distance between two objects, usually target and observer. Real line A line representing the real numbers. The real numbers include zero, all positive and negative fractions, and any number that's a limit of some sequence of fractions. In SPICE documentation, real numbers are restricted to those representable by the double precision floating point data type, excluding distinguished values such as +/- Inf and NaN. Reference frame A set of three mutually orthogonal directions in space and an associated center. See the Fundamental Concepts, FK, and Using Frames tutorials, as well as the Frames Required Reading, frames.req, for details. (Compare to ``coordinate system'' above.) Result window In the GF setting, a SPICE window (see below) representing the time window over which a specified geometric condition is satisfied. A result window is an output window returned by a CSPICE GF API search routine. Root Solution of an equation; point satisfying given constraints. In the GF setting, roots are times at which state transitions of interest occur, for example times when a specified occultation starts or stops, or the time at which the distance between two ephemeris objects attains a local minimum. Roots are endpoints of SPICE windows representing search results. Root Finding The process of locating roots; searching for roots. SCLK Spacecraft clock. See the ``LSK and SCLK'' tutorial and the SCLK Required Reading, sclk.req, for details. Search window A confinement window (see above). Singleton A set consisting of a single point. Also short for ``singleton interval.'' Singleton interval An interval having equal left and right endpoints. Singularity A point or region in the domain of a function at which the function is ``badly behaved'': the function is not defined, not continuous, or not differentiable. For example, longitude has a singularity at pi radians. In three dimensional space the singular region of longitude is the half-plane for which Y = 0 and X <= 0. SPICE window Also CSPICE window. An abstract data type used to represent collections of intervals on the real line, especially collections of time intervals; also, an instance of this type. A SPICE window represents a union of zero or more disjoint intervals, arranged in increasing order: the right endpoint of one constituent interval of a window is strictly less than the left endpoint of the next interval. Intervals in a SPICE window may be singletons. SPICE window can be empty. SPICE windows are implemented as structured arrays in Fortran and MATLAB; they're implemented as structures in C and IDL. See the Windows Required Reading, windows.req, for details. Step size The duration between times at which a function is sampled. Sub-observer point The point on the surface of an extended target that is, depending on the user's specification, either closest to the observer, or lies on the line connecting the observer and the target's center. Surface intercept An intersection of a ray and a specified surface. When the vertex of the ray is associated with an observer, usually the surface intercept is understood to be the point of intersection closest to the observer. Target Ephemeris object, the location of which acts as the head of a position vector. The tail of the vector is the location of another ephemeris object called the ``observer.'' TDB Barycentric Dynamical Time. The independent variable used in SPK, PCK, and dynamic FK files and all of the SPICE API routines, except for the CK readers and some time conversion routines. See the Time Required Reading, time.req, and the Fundamental Concepts tutorial for details. In SPICE Toolkit documentation, any reference to ET (ephemeris time) means a TDB time. Ticks Encoded SCLK. Used as the independent variable in CK files. See the ``LSK and SCLK'' tutorial and the SCLK Required Reading, sclk.req, for details. Time interval The set of times between a start time and a stop time, inclusive. The start and stop times are also called ``endpoints.'' Time window A set of zero or more closed, disjoint time intervals arranged in increasing order. Also a SPICE window (see above) representing such a set of time intervals. Tolerance See convergence tolerance. Window A set of zero or more closed, disjoint intervals on the real line, arranged in increasing order. Also a SPICE window (see above). Windows frequently represent time but may be used for other purposes, for example to represent sets of angular intervals on the unit circle. Top # GF API Routines Top ## High-level GF search routines The high-level GF search routines constitute the principal application programming interface to the GF subsystem. 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 meta-kernels 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 high-level GF search routines are: gfdist_c Distance search: find time windows when a given observer-target distance constraint is met. gfoclt_c Occultation or transit search: find time windows when a given type of occultation or transit is in progress. gfposc_c Observer-target position vector coordinate search: find time windows when a given constraint on a specified coordinate (e.g. Cartesian X, Y, Z or planetocentric radius, longitude, or latitude) of an observer-target position vector is met. gfrfov_c Ray in instrument field of view search: find time windows when a given ray emanating from an observer is contained in a specified instrument's field of view. gfsep_c Angular separation search: find time windows when a given constraint on the angular separation of two targets as seen by a specified observer is met. gfsntc_c Ray-surface intercept coordinate search: find time windows when a specified constraint on a coordinate of the surface intercept of a specified ray on a target body is met. gfsubc_c Sub-observer point coordinate search: find time windows when a specified constraint on a coordinate of the sub-observer point on a specified target body is met. gftfov_c Target body in instrument field of view search: find time windows when a given target body appears in a specified instrument's field of view. Top ## Mid-level GF search routines The routines discussed here are provided only in the Fortran and C SPICE Toolkits. (Practical means of implementing these routines in IDL and MATLAB have not been found.) The mid-level GF search routines are: gfevnt_c Scalar quantity search: find times when specified constraints on any scalar quantity, such as distance or angular separation, are met. gffove_c FOV search: find times when a specified target appears in a specified instrument FOV. This routine provides the functionality of both gftfov_c and gfrfov_c. gfocce_c Occultation or transit search: find times when a specified target body occults or is in transit across another, as seen by a specified observer. These routines provide all of the functionality of the high-level search routines, plus several additional features: Progress reporting Applications can control whether a ``percent complete'' progress report is displayed during a GF search. By default, the report is displayed via console I/O. Applications can override the default display by passing custom progress reporting routines as input arguments to mid-level GF search routines. Interrupt handling Applications can control whether mid-level GF search routines test for issuance of an interrupt command and abort if such a command is detected. Applications can override the default interrupt handling behavior by passing a custom interrupt detection routine as an input argument to mid-level GF search routines. Set search step function Applications can override the default search step behavior by passing a custom step size routine as an input argument to mid-level GF search routines. Set refinement function Applications can override the default root refinement algorithm (binary search) by passing a custom root refinement routine as an input argument to mid-level GF search routines. Set convergence tolerance Convergence tolerance is an input argument to mid-level GF search routines. Top ### Rationale for calling mid-level GF search routines The mid-level GF search routines are more complex than their high-level counterparts (considerably so in the case of gfevnt_c). The main reason to use the mid-level routines is to take advantage of their progress reporting and interrupt handling capabilities. 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 mid-level GF search routines. When an interactive SPICE-based 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. Top ### Supporting utility routines When the default GF progress reporting, interrupt handling, and root-finding functionality is desired, a calling application can call existing GF utility routines and, where applicable, pass them as actual input arguments to the mid-level search routines. These utilities are: gfsstp_c Set search step. This routine sets the step size that will be returned by gfstep_c. gfstep_c Get search step. This routine returns step size that was last set by gfsstp_c. gfrefn_c Refine root bracketing interval. This routine returns the midpoint of the input times; this behavior supports root finding by bisection. gfrepi_c Initialize progress report. gfrepu_c Update progress report. gfrepf_c Finalize progress report. gfbail_c Detect interrupt. This function returns a logical value indicating whether an interrupt has been detected. gfinth_c Interrupt hander. This handler should be established via a call to the ANSI C function `signal'. gfclrh_c Clear gfbail_c status. This function should be called after a mid-level GF search routine returns, if interrupt handling is enabled. In CSPICE, the default interrupt handling behavior, when enabled, is to return control to the calling application if the SIGINT signal is detected. See the code examples in the headers of the mid-level GF search routines for details. Top ### Overriding default functionality To override the default progress reporting capability provided by the mid-level 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. 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. In some cases, GF searches can be sped up by increasing the convergence tolerance. The default tolerance value is given by the parameter SPICE_GF_CNVTOL which is defined in the header file
       SpiceGF.h
The cost of increasing the convergence tolerance is decreased accuracy of search results. Top # GF Computational Recipes Below we provide terse descriptions of computational approaches for solving common geometric search problems. 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. Top ## Required SPICE kernels With a few exceptions, the recipes below don't discuss the SPICE kernels required to carry out the described computations. Some general requirements are summarized here: `--` SPK files containing ephemeris data for targets and observers are almost always required; the only exception is the star visibility case where the star's location is modeled as a direction rather than as a position vector. `` When aberration corrections are used, sufficient ephemeris data must be available to propagate states of the observer and targets to the solar system barycenter. The states of the targets must be calculable at light time corrected epochs, so the required coverage will extend beyond the confinement window. `` When stellar aberration corrections are used, coverage for the observer must be available on a window whose intervals are expanded by one second (in both directions) relative to the confinement window. `--` Computations involving target body-fixed, body-centered reference frames require PCK files providing orientation data for those reference frames. Such computations often require PCK files containing size and shape data for the target body as well. In many cases one PCK file can provide both the necessary orientation and size/shape data. `` When required body-fixed, body-centered reference frame specifications are not built into the CSPICE system, those specifications must be provided by FK files. `--` Computations involving topocentric reference frames centered at surface points on extended objects require both SPK and FK files providing state data for the surface point and topocentric frame orientation, respectively. Usually these computations also require a PCK file providing orientation of the extended object. `--` Computations involving instrument pointing and FOV specifications normally require all of the following: CK files, SCLK kernels, LSK files, FK files, and IK files. Top ## A note about CK data availability CK files, particularly those containing reconstructed attitude data, often have coverage gaps. A SPICE-based application program can obtain the time window over which CK data are available by calling the CSPICE routine ckcov_c. 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 round-off errors, and in some cases, to discontinuities in the TDB-to-ticks 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 TDB-to-ticks 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. Top ## Geometric constraint searches Top ### Periapse/Apoapse To find the unique closest approach of an observer to a target over a specified time window, call gfdist_c, specifying the
       "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. Top ### View periods View periods may be defined as time intervals, within a confinement window, during which a target body has elevation greater than a specified limit with respect to the local horizontal plane at a given point on the surface of an extended body. 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. Top ### Sub-observer point Use gfsubc_c to find times when the sub-observer point on an extended target satisfies the constraints
       min_lon < sub-observer longitude < max_lon
       min_lat < sub-observer latitude  < max_lat
Four 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_lon
and the corresponding longitude constraints have the form
             min_lon < sub-observer longitude
       OR    max_lon > sub-observer longitude
In 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. Top ### Instrument boresight intercept Use gfsntc_c to find times when the intercept on an extended target body of a ray emanating from an observing instrument's location and aligned with the instrument's boresight satisfies the constraints
       min_lon < intercept longitude < max_lon
       min_lat < intercept latitude  < max_lat
Four searches are required: one for each constraint. See the discussion of alternate longitude constraints and of search order above in the section titled ``Sub-observer 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 ray-surface intercept exists. High-frequency 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 near-tangent 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 near-tangent ray pointing. Top ### Planet in instrument field of view Use gftfov_c to find times when an ephemeris object is in the FOV of an instrument, provided this FOV can be modeled as one of the shapes supported by the SPICE routine getfov_c. The target shape can be treated as an ellipsoid or a point. gftfov_c may not be suitable for FOV searches involving push-broom cameras. For an alternate approach, see the example program ROVER below for a demonstration of a search involving the MRO HIRISE camera. Top ### Star in instrument field of view Use gfrfov_c to find times when a target modeled as a ray (that is, the direction to the target is available, the distance to the target is not) is in the FOV of an instrument, provided this FOV can be modeled as one of the shapes supported by the SPICE routine getfov_c. Top ### Spacecraft occultation or transit Use gfoclt_c to search for spacecraft occultations or transits. If the spacecraft is the target, the spacecraft shape can be modeled as a point. The blocking body must be modeled as an ellipsoid. gfoclt_c assumes straight-line light paths for occultation searches. This assumption may not be suitable for high-accuracy work. Top ### Natural satellite occultation or transit Use gfoclt_c to search for natural satellite occultations or transits. Both satellite and planet should be modeled as ellipsoids. Top ### Spacecraft eclipse Defining a spacecraft eclipse as the presence of the spacecraft in the shadow created by the Sun and a blocking body, one can observe that eclipses are equivalent to occultations, where the spacecraft is the observer, the Sun is the ``back'' body, and the blocking body is the ``front'' body. 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 straight-line light paths for occultation searches. This assumption may not be suitable for high-accuracy work. Top ### Surface point eclipse Searches for eclipses of a surface point on an extended object can be conducted using gfoclt_c, as long as the position of the surface point is given by an SPK file. Use the SPICE utility PINPOINT to create an SPK file for the surface point if necessary; then proceed as described in the above ``Spacecraft eclipse'' discussion. Top ### Equator crossing Use gfposc_c to find times when one body crosses the equatorial plane of another. The reference frame should be the body-fixed, body-centered frame associated with the body whose equatorial plane is of interest. The coordinate system and coordinate can be set, respectively, to
       "RECTANGULAR"
       "Z"
Other choices such as
       "LATITUDINAL"
       "LATITUDE"
will yield the same results, up to round-off errors. 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 anti-symmetric functions of target and observer. See the Fundamental Concepts SPICE tutorial and the header of spkezr_c for further information on aberration corrections. Top ### Meridian crossing Use gfposc_c to find times when one body crosses a given meridian of the body-fixed, body-centered reference frame of another. 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 set-up 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. 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. Top ### Elongation Use gfsep_c to find times when target body elongation constraints are met, given a target body and observer. The Sun is the second target. Top ### Body-centered phase angle without aberration corrections The body-centered phase angle can be approximated as the angular separation of observer and Sun, as seen from the body of interest, if aberration corrections are ignored. Use gfsep_c to find times when approximate phase angle constraints are met. Refer to the header of gfsep_c for a description of the input arguments discussed below. For this search, the observing body is treated in the gfsep_c call as one of the target bodies: that is, the name of the observer should be used as either of the input arguments `targ1' or `targ2'. The Sun is the other target body. The observer and the Sun both should be modeled as points. The target body should be treated as the observer: the name of the target body should be passed in as the value of the argument `obsrvr'. Top ### Orbital longitude of a satellite This recipe requires the user to create two dynamic reference frame specifications in a frame kernel. See the ``Dynamic Frames'' tutorial and the Frames Required Reading, frames.req, for detailed discussions of this topic. 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 observer-central 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 Sun-Earth 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 two-vector dynamic frame ORBIT_FRAME whose primary axis is aligned with the central body-satellite position vector; this is the frame's +X axis. Associate the secondary axis with the central body-satellite 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 two-vector 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 observer-central 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"
       "LATITUDE"
Aberration corrections should not be used for this application. Top ### Approximate times of Cassini Saturn ring occultations An approximation of Saturn ring occultation ingress and egress times for the Cassini orbiter, as viewed by a given Deep Space Network (DSN) station, can be found using gfoclt_c. 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: `--` Loading a text kernel assigning the desired radii to the kernel variable BODY699_RADII `--` Calling pdpool_c to assign the desired radii to the kernel variable BODY699_RADII Normally the application should restore Saturn's original radii after the second search has been completed. 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 edge-on or nearly edge-on viewing geometry: the ray-spheroid 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 straight-line radiation paths may also be unsuitable for very high-accuracy work. Top ### Angular offset between instrument boresight and velocity Although the GF subsystem doesn't directly support searches involving coordinates of velocity vectors, one can use gfposc_c to find times when the angular separation of a spacecraft-mounted instrument's boresight vector and the instrument's (inertially referenced) velocity satisfies specified constraints. 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. Top # GF Concepts Top ## Time windows Every GF search is performed over a time period represented by a SPICE window called the ``confinement window.'' Every successful GF search produces as a result a SPICE window called the ``result window.'' 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.
       --[----------------------]-------[----]--[----------------]--
Top ### Window manipulation and arithmetic The CSPICE Toolkit provides a set of routines that manipulate SPICE windows. These are described in the Windows Required Reading windows.req. Among the supported window operations are ``set arithmetic'' functions such as union, intersection, difference, and complementing with respect to an interval. 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 half-open or open intervals. Window arithmetic is used to solve for logical combinations of geometric conditions. For example: `--` To find times within a given confinement window when a target is not occulted, use gfoclt_c to find the times when the target is occulted, then subtract the result window from the confinement window. `--` To find times when a target is visible in either of the FOVs of two instruments, conduct visibility searches for each instrument using gftfov_c, then compute the union of the result windows from the two searches. It is often convenient to use the result window produced by one GF search as the input confinement window of another. Often this is both simpler and faster than computing two searches on the original confinement window and then intersecting the result windows. Top ### Result windows are approximate Since result windows are created by a mathematical root finding process, the endpoints---that is, the start and stop times---of the intervals comprising these windows are always approximate. The errors in these endpoint times are due not only to errors in input data and round-off errors introduced by finite-precision arithmetic, but to the fact that the endpoints are determined by an approximation process that terminates when the endpoints are found to be correct within a ``convergence tolerance.'' 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. Top ### Working around result window errors SPICE window ``contraction'' is an operation in which the left endpoints of each of a window's intervals are moved to the right and the right endpoints are moved to the left. Use the CSPICE routine wncond_c to contract a SPICE window. 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 sub-searches. 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. Top ## Events In GF documentation, an instance of a geometric quantity satisfying a specified condition is called an ``event.'' An event can be instantaneous, such as an observer attaining its minimum distance to a target, or it can have finite duration, as does an occultation. Geometric quantities supported by the GF subsystem either have binary states or are numeric functions of time. ``Binary state'' quantities are logical-valued 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 scalar-valued functions of time. Distance, angular separation, and coordinates are numeric quantities. Top ### Constraints Constraints are logical conditions that are specified by a calling SPICE-based application and satisfied over the result window produced by a GF search. 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: = The quantity is equal to a specified value, called the ``reference value.' < The quantity is less than a specified value, called the ``reference value.' > The quantity is greater than a specified value, called the ``reference value.' ABSMAX The quantity attains its absolute (global) maximum. ABSMIN The quantity attains its absolute (global) minimum. LOCMAX The quantity attains a local maximum. LOCMIN The quantity attains a local minimum. ABSMAX, `adjust' !=0 The quantity is within the adjustment amount `adjust' of its absolute (global) maximum. ABSMIN, `adjust' !=0 The quantity is within the adjustment amount `adjust' of its absolute (global) minimum. For a numeric quantity search, the result window is the set of times at which the quantity satisfies the specified relation. 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. Top ## Root finding A search for a specified event comes down to finding the start and stop times of the intervals, within a given confinement window, over which the event occurs---that is, over which the geometric quantity of interest satisfies a constraint specified by the calling application. These start and stop times are the ``roots'' found by a GF search. 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. Top ### Search step size Root bracketing consists of sampling the geometric quantity of interest at evenly spaced times throughout an interval. 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 10-second step:
         2         12        22        32        42        52   57
         |         |         |         |         |         |    |
         v         v         v         v         v         v    v

       --[------------------------------------------------------]---
         ^                                                      ^
         2                                                      57
Note 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 zero-based column counts of the dashes in the diagram. Suppose the quantity we're sampling is of the binary-state 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                                                      57
Above, 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. Top ### Binary state step size selection problems It's clear that for most searches, choosing an extremely small step size will result in a large number of samples being taken. This will result in very---probably unacceptably---slow search execution. 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                                                      57
Above, 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                                                      57
Above, 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. Top ### Numeric quantity step size selection problems The step size issues discussed above apply to numeric quantity searches as well, because each numeric quantity search involves a binary state search to determine times, within the confinement window, when the quantity is decreasing. The state transition times found by this search are times when local extrema are attained. 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. Top ### Search convergence Once a root has been bracketed, a refinement process is used to narrow down the time interval within which the root must lie. This refinement process terminates when the location of the root has been determined to within an error margin called the "convergence tolerance." The high-level GF search routines use a fixed tolerance (see the headers of these routines for details). The 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, mid-level 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. Top ## An important numeric event limitation The algorithm currently used by the GF subsystem to search for numeric events makes a very strong assumption about the underlying numeric quantities:
       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: `--` The GF subsystem cannot correctly solve for times when the numeric quantity of interest takes on a constant value X, if the quantity takes on the value X over a finite (non singleton) interval. The GF subsystem can solve for equality constraints only when the solution consists of a finite set of points. `--` Searches for local extrema may yield extraneous solutions if the numeric quantity of interest is constant on a finite (non singleton) interval. If the search step size is shorter than such an interval, and if the quantity exhibits any noise (such as that caused by round-off errors), then at least one local extremum will be found in the interval. GF users must consider the impact of this assumption on the validity of planned GF applications. Top ## Workspace GF scalar quantity searches require memory to store intermediate results; this memory is called ``workspace.'' Note that GF binary state searches don't require 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. Top ### Workspace window counts Fortran SPICE Toolkit users must declare workspace using two dimensions: workspace window size and workspace window count---the count is the number of windows the workspace can hold. Parameters giving recommended workspace window counts are declared in the SPICELIB include file
       gf.inc
Declaring 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 hard-coded workspace window counts. The reason for treating these counts as passed-in parameters is that this enables run-time 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
Top ### Workspace window interval counts While workspace window count requirements are determined by parameters, maximum workspace window interval counts must be selected by SPICE users. 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. Top ### Estimating the workspace interval count requirement If a confinement window is comprised of N intervals and has measure M seconds, and the search step size is STEP seconds, then a rule of thumb for the number of required workspace intervals NINTVLS is
       NINTVLS  =  2*N  +  ( M / STEP )
In many cases the actual number of intervals needed is much smaller than this estimate. Top # Common GF Problems Here we discuss some common problems that may arise when SPICE-based applications the use the GF subsystem. Top ## A challenge One noteworthy difference between debugging GF search problems and other types of computational problems is that GF searches don't assist the programmer by returning invalid geometric parameters; they just return time windows. While it can be obvious that a given distance or angle is incorrect, it's often much harder to determine, without much investigative work, that a given set of time intervals is incorrect. 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. Top ## Wrong SPICE kernels This is not a GF-specific issue, but it's one of the most common problems that occurs in SPICE applications. Using the correct SPICE kernel versions can make all the difference when trying to determine event times. Top ## Insufficient kernel data As with most work performed with SPICE, it's not uncommon for GF searches to terminate due to missing 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. Top ## Missed events Here are some simple reasons why a GF search might fail to find events that you know did occur: `--` Kernel versions are wrong. For example, an out-of-date predict SPK or CK file can yield completely wrong viewing geometry. `--` The step size is too long. See the discussion of search step size in the ``GF Concepts'' chapter. `` Note that proper understanding of the underlying geometry is crucial for correct step size selection. For example, incorrect assumptions about the period of a numeric quantity can lead to selecting a step size that's too large to capture all of the local extrema of the quantity. `--` The confinement window is incorrect. If the event does occur, but not during the confinement window you're passing to the GF search routine, it won't be found. Top ## Slow performance Slow performance may be due to an excessively small step size. See the step size discussion in the ``GF concepts'' chapter to get an idea of the step size requirements for your search. 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 mid-level 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. Top ## Constraints not met on result window New GF users may be surprised to learn that constraints are not necessarily met by times at the endpoints of, of even slightly inside, the intervals comprising the result window. See the discussion of time windows and window contraction in the ``GF Concepts'' chapter. Top ## Result window intervals appear invalid There are a number of reasons why a GF search can return a result window that appears ``just plain wrong.'' Possible causes include: `--` Invalid SPICE kernels---bad data or wrong versions. `--` Step size is too long, causing events to be missed or multiple events to be seen as a single event. `--` The search is attempting to extract results from noisy data. For example, it's difficult to find correct local extrema of the light-time corrected range rate (note: not yet implemented in SPICE) of the Moon relative to the Earth; near the times when the extrema occur, the variation of the quantity, as SPICE computes it, is on the same scale as the noise in the quantity. `--` Models used by SPICE differ from those expected or those used in a search done using means other than SPICE. For example, in some cases, occultation times computed with spherical target models can differ by tens of minutes from those computed with ellipsoidal models. Top # GF Example Programs The next several sections present example programs that illustrate use of GF routines to solve realistic geometry problems. 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. Top ## Program MEDLEY: Searches for Periapse, Occultation, Rise/Set Top ### Overview This example program demonstrates use of the GF subsystem to perform three relatively simple tasks: `--` Find times of periapse of the Earth relative to the Sun over a specified decade. `--` Find times when Titan is at least partially occulted by Saturn as seen from DSS-14, on a specified day. Occultations of duration less than ten minutes are ignored. `--` Find times when Saturn is visible from DSS-14, over a specified 5-day period. Saturn is considered to be visible when its elevation is above 6 degrees. These periods of visibility are sometimes called ``view periods.'' `` The SPICE system doesn't support modeling of atmospheric effects such as refraction, so the target rise and set times found by this search are approximate. In the interest of brevity, both of the example code and of the discussion, the example program below combines the solutions of the above (unrelated) problems. Top ### Aberration corrections For the Earth-Sun periapse computation, the goal is to find the local minima of distance given by the planetary ephemeris, as opposed to the apparent local minima, so no aberration corrections are used. 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. Top ### SPICE kernels The meta-kernel used for this example is shown below.
       KPL/MK

          File: medley.tm

          Meta-kernel for example program MEDLEY.

          This meta-kernel 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 SPICE-based applications.

          In order for an application to use this meta-kernel, the
          kernels referenced here must be present in the user's
          current working directory.

          The names and contents of the kernels referenced
          by this meta-kernel 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, low-accuracy
                                              Earth orientation

          Version 1.0.0 23-JAN-2009 (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]
Top ### Source code Example source code begins here.
       #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 2009-2019.
          ***************************************************************/

          /*
          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 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 DSS-14, 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 = "DSS-14";

          /*
          Set the front and back targets, their shapes,
          and their body-fixed 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 DSS-14, for the time period
          January 1-5, 2009.
          ***************************************************************/

          /*
          We'll consider Saturn to be visible from DSS-14 when
          Saturn has elevation above 6 degrees in the DSS-14
          topocentric reference frame DSS-14_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 = "DSS-14";
          target = "SATURN";
          frame  = "DSS-14_TOPO";

          /*
          The coordinate system is latitudinal; in this system,
          in the DSS-14_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 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 DSS-14:\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 );
       }
Top ### Results When executed on a PC/Linux/gcc platform, 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 DSS-14:

          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
Top ## Program CASCADE: Fast Search for Solar Eclipse Top ### Overview This example demonstrates a search for a solar eclipse as seen from a specified location on the Earth's surface, during the year 2008. The eclipse search speed is increased by a factor of over 100 by use of a preliminary search to determine a time window during which the apparent angular separation of the Sun and Moon is small enough so that an eclipse could occur. The price we pay to achieve this speed-up 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 DSS-14 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 search---one 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 DSS-14 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. Top ### Specifying the angular separation search parameters In order to perform the angular separation search, we'll need to decide on the search step size and the upper bound of the angular separation. We'll also choose a convenient observation point relative to which the angular separation is defined. 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: DSS-14 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 DSS-14 as the observer. If we use DSS-14 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 DSS-14, 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. Top ### Aberration corrections Normally computations involving apparent geometry of extended objects require correcting 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. Only light time corrections are needed for the occultation search. Top ### SPICE kernels The meta-kernel used for this example is shown below.
       KPL/MK

          File: cascade.tm

          Meta-kernel for example program CASCADE.

          This meta-kernel 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 SPICE-based applications.

          In order for an application to use this meta-kernel, the
          kernels referenced here must be present in the user's
          current working directory.

          The names and contents of the kernels referenced
          by this meta-kernel 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, low-accuracy
                                              Earth orientation

          Version 1.0.0 13-JAN-2009 (NJB)

       \begindata

          KERNELS_TO_LOAD = (
                              'naif0009.tls'
                              'pck00008.tpc'
                              'de421.bsp'
                              'earthstns_itrf93_050714.bsp'
                              'earth_070425_370426_predict.bpc'
                            )
       \begintext

       [End of kernel]
Top ### Source code Example source code begins here.
       #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 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
          body-fixed 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 = "DSS-14";

          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 );
       }
Top ### Results When executed on a PC/Linux/gcc platform, 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 TDB
On 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. Top ## Program ROVER: Mars Reconnaissance Orbiter photographs MER-1 Top ### Overview This program finds an approximate time window, during the month November 2006, over which the MER-1 ("Opportunity") rover is visible within the Mars Reconnaissance Orbiter (MRO) HIRISE field of view (FOV). Since HIRISE was used to photograph MER-1 during this time period, the timing results from this example program can be compared against actual data. Top ### Determining SPK and CK coverage at run time This example involves multiple CK and SPK files. Because the coverage of the CK files has numerous gaps, and because we want the program to determine the times of coverage for all required data, the CSPICE CK and SPK coverage routines ckcov_c and spkcov_c are used. To ensure availability of data, certain modifications of the coverage windows found by these routines are required: `--` Within CK files, CK coverage bounds are represented by encoded SCLK time. In order to conveniently work with these time bounds, they must be converted to Barycentric Dynamical Time (TDB). Each such conversion introduces a small amount of round-off error. These errors may prevent the TDB values from being converted back to encoded SCLK values within the CK coverage window. `` So the MRO spacecraft bus orientation coverage window is contracted slightly (that is, the left endpoint of each interval of the window is moved to the right, and the right endpoint of each interval is moved to the left) to eliminate any CK look-up failures that could result from these round-off errors. `--` The intervals comprising the MER-1 SPK coverage window are contracted on the left to compensate for one-way light time between MER-1 and MRO. This ensures that times at the beginning of these intervals can be adjusted by one-way light time and still be within the actual coverage window for the MER-1 SPK files. `--` The intervals comprising the MRO SPK coverage window are contracted by slightly more than one second on both sides to ensure data availability for stellar aberration computations. Even though we're performing searches involving constraints on observer-target position vectors, the GF subsystem uses the corresponding velocities to conduct these searches. The SPK subsystem's stellar aberration correction velocity computation requires observer acceleration with respect to the solar system barycenter. The acceleration at a given epoch ET is is computed by discrete differentiation using samples taken at ET +/- one second. `` For the problem at hand, it happens that this contraction isn't needed because MRO SPK coverage is not the limiting factor determining the overall coverage window. The contraction is demonstrated in the interest of safety and broader applicability of the example. The intersection of the modified coverage windows yields a window over which all required data are available. Top ### Speeding up the search Because of the minute angular extent of the MRO HIRISE field of view in the MRO downtrack direction, a simple search of the data availability window using the GF "is target in instrument FOV?" routine gftfov_c would be prohibitively slow. So the search is performed in three steps: `1.` The data availability window is searched for times when the observer and target are separated by no more than 500 km. Since the nominal altitude of MRO above Mars' surface is about 300 km, this limit allows for a substantial pointing offset relative to the nadir direction. The result of this search is the ``distance window'' `distwn'. `` The step size for this search can be large, since the epochs of the extrema of the observer-target distance are separated by almost an hour. For safety, a half-hour step is used. `2.` Since the MRO spacecraft's downtrack direction is nominally aligned with the MRO_HIRISE_LOOK_DIRECTION frame's +X axis, the distance window is searched for times when the MER-1 rover crosses the MRO_HIRISE_LOOK_DIRECTION frame's Y-Z plane. `` This search produces a non-empty window of measure zero: the contents of the window are singleton intervals, some of which may lie in the time window during which MER-1 is in the MRO HIRISE FOV. `3.` For each singleton interval in the result window of the Y-Z plane crossing search, we find the angular separation of the MRO-rover vector (which at the epochs of comparison lies in the camera's Y-Z plane) and the HIRISE +Z vector. We compare this angle to the angular half-width of the HIRISE nominal FOV; if the angle is smaller than the half-width, we consider the rover to be visible. Top ### Pointing issues With nominal nadir pointing, the target moves in the downtrack direction with a period matching that of MRO's orbit, so extrema of the target's X coordinate in the HIRISE frame are almost an hour apart. However, if the spacecraft were to rotate rapidly, this effect could dominate that of the spacecraft's orbital motion, creating new extrema. Substantial deviation from the nominal nadir-pointed 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 near-nadir 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 Y-Z plane crossing search. Alternatively, the spacecraft pointing could be analyzed for the time window over which the Y-Z plane crossing search is performed. Top ### Aberration corrections The searches described above involve apparent target geometry, so in all but the distance search, which need not produce highly accurate results, light time and stellar aberration corrections are used. The flag indicating these aberration corrections is
       "LT+S"
Top ### SPICE kernels SPICE kernels for MRO and MER-1 referenced below were obtained from the NAIF PDS archive. The meta-kernel used for this example is shown below.
       KPL/MK

          File: rover.tm

          Meta-kernel for example program ROVER.

          This meta-kernel 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 SPICE-based application.

          In order for an application to use this meta-kernel, the
          kernels referenced here must be present in the user's
          current working directory.

          The names and contents of the kernels referenced
          by this meta-kernel 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                      MER-1 frame specifications
             mer1_surf_rover_ext10_v1.bsp     MER-1 ephemeris
             mer1_surf_rover_ext11_v1.bsp     MER-1 ephemeris
             mer1_ls_040128_iau2000_v1.bsp    MER-1 landing site location

          Version 1.0.0 25-JAN-2009 (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]
Top ### Source code Example source code begins here.
       #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 round-off error in the SCLK-to-TDB
          conversion performed by CKCOV.
          */
          nudge = 1.e-6;
          wncond_c ( nudge, nudge, &ckwmro );

          /*
          Get coverage of both the MRO and MER-1 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 ( "MER-1", &mercde, &found );

          if ( !found )
          {
              setmsg_c ( "Could not map MER-1 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 MER-1 SPK
          window on their left sides to account
          for light time correction. Note that we may look up the
          position of MER-1 relative to MRO even when MER-1 is not
          visible, so the contraction amount must be large enough
          to ensure data availability when MRO and MER-1 are on
          opposite sides of Mars.
          */
          nudge = 5.e-2;
          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 MER-1 and MRO is less than
          500 km. We're not interested in other viewing
          opportunities.
          */
          target = "MER-1";
          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 MER-1 relative to MRO lies on the
          Y-axis of the MRO_HIRISE_LOOK_DIRECTION frame.
          */
          target = "MER-1";
          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"
                   "Y-Z plane crossing search.\n"                 );

          gfposc_c ( target, frame,   abcorr, obsrvr,
                     crdsys, coord,   relate, refval,
                     adjust, step,    MAXIVL, &distwn, &result );

          printf ( "Done.\n" );

          /*
          Display the Y-Z plane crossings for which the magnitude
          of the target's Y angular offset from the camera frame's
          X-Z plane is less than the angular half-width of the HIRISE
          nominal FOV. Look up this half-width here.
          */
          gdpool_c ( "INS-74699_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 ( "INS-74699_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 MER-1 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, &lt            );

                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 X-coordinate (km): %15.6f\n",
                            trgpos[0]                                 );
                   printf ( "     Target Y-coordinate (km): %15.6f\n",
                            trgpos[1]                                 );
                   printf ( "     Target Z-coordinate (km): %15.6f\n",
                            trgpos[2]                                 );
                   printf ( "     Target range        (km): %15.6f\n",
                            vnorm_c(trgpos)                           );

                    printf ( "\n\n" );
                }
             }
          }

          return ( 0 );
       }
When executed on a PC/Linux/gcc platform, 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
       Y-Z plane crossing search.
       Done.

       Times of MER-1 visibility within MRO HIRISE nominal FOV swath:

          2006 NOV 14 15:41:02.511527 TDB

            Frame: MRO_HIRISE_LOOK_DIRECTION

            Target X-coordinate (km):       -0.000001
            Target Y-coordinate (km):       -0.893623
            Target Z-coordinate (km):      278.011537
            Target range        (km):      278.012973

          2006 NOV 30 01:39:40.509680 TDB

            Frame: MRO_HIRISE_LOOK_DIRECTION

            Target X-coordinate (km):        0.000001
            Target Y-coordinate (km):       -0.577715
            Target Z-coordinate (km):      267.423792
            Target range        (km):      267.424416
Top # Appendix A --- Summary of GF Functions Top ## Summary of Mnemonics The following is a complete list of GF API mnemonics and translations, in alphabetical order. Many of the lower-level CSPICE functions have SPICELIB counterparts implemented in Fortran as entry points of another function.
       gfbail_c             GF, test for interrupt
       gfclrh_c             GF, clear interrupt handler
       gfdist_c             GF, distance search
       gfevnt_c             GF, mid-level scalar constraint search
       gffove_c             GF, mid-level FOV intersection search
       gfocce_c             GF, mid-level occultation search
       gfoclt_c             GF, find occultation
       gfposc_c             GF, position coordinate search
       gfrefn_c             GF, refine solution bounds
       gfrepf_c             GF, finalize progress report
       gfrepi_c             GF, initialize progress report
       gfrepu_c             GF, update progress report
       gfrfov_c             GF, ray-FOV intersection search
       gfsep_c              GF, angular separation search
       gfinth_c             GF, interrupt signal handler
       gfsntc_c             GF, surface intercept coordinate search
       gfsstp_c             GF, set search step size
       gfstep_c             GF, get search step size
       gfsubc_c             GF, sub-observer coordinate search
       gftfov_c             GF, target-FOV intersection search
Top # Appendix B---Revision History