March 30, 2005
Updated to correct minor bugs in Fortran utilities: umbrella functions MODRIS and MODOCP, as well as entries in these functions SETRIS and SETOCP, now return the value .FALSE. Fortran callers of SETRIS and SETOCP were updated to use function call syntax.
June 1, 2004
Updated to include code to test routines written by student: srfazl and occpt.
May 7, 2004
This lesson illustrates how the CSPICE Toolkit can be used to find
time intervals when specified geometric conditions are satisfied. The
student is asked to construct a program that finds the times within a
specified time range when a point target is visible from a specified
surface point on an extended body. As a concrete example, the student
is asked to find the complete set of times within the interval
2004 MAY 1 TDB 2004 MAY 5 TDBwhen the Mars Express Orbiter is visible from the DSN station DSS-14. The program is to consider occultation of the spacecraft by Mars and by the earth. We'll consider the spacecraft occulted by the earth if its elevation is below six degrees when measured in the topocentric frame DSS-14_TOPO, which is centered at DSS-14.
Although we've identified a specific set of objects participating in our observation geometry problem, the solution program should be written in such a way that these selections could be changed simply by modifying a meta-kernel read by the program.
In this lesson, we use the terms ``event finding'' or ``root finding'' to designate the process of solving for the set of times when a specified geometric condition is met. Rather than ask the student to devise event finding algorithms, we provide the student with functions to perform this task. See the section titled ``Utility routines'' below for details.
The utility routines provided here are not part of the CSPICE Toolkit. NAIF plans to include event finding software in a future Toolkit release. The planned CSPICE Toolkit subsystem dealing with event finding is called the ``Geometry Finder.'' The Geometry Finder's function API will not closely resemble the event finding interface presented here. However, the event finding utilities comprise a small part of the overall set of routines the student will use in this lesson. Aside from these few utilities, the other functions presented in this lesson are in common use among CSPICE programmers.
One set of CSPICE functions that are particularly relevant to event finding are the CSPICE window manipulation functions. In addition to this lesson, the ``Other Stuff'' hands-on programming lesson contains an exercise dealing with CSPICE window functions. The student may wish to complete that exercise in addition to this lesson.
This lesson consists of a series of programming exercises. In each exercise, the student writes a portion of the program constituting the complete problem solution. The exercise topics are:
This section provides a list of SPICE documents that are referred to
in this lesson.
Of these documents, the ``Tutorials'' contains the highest level descriptions with the fewest details while the ``Required Reading'' documents contain much more detailed specifications. The most complete specifications are provided in the ``Headers'' -- the comments in the top section of each CSPICE source file.
The following SPICE tutorials may be particularly useful as references
for this lesson:
Name Lesson steps/routines that it describes --------------- ----------------------------------------- Time Conversion between UTC and ET Intro to Kernel Files Loading SPICE kernels SPK Computing positions and velocities Frames Computing transformations between framesThese tutorials are available in printed form and as MS Office or PDF files from the NAIF server at JPL:
ftp://naif.jpl.nasa.gov/pub/naif/toolkit_docs/Tutorials
The Required Reading documents are provided with the Toolkit and are
located under ``toolkit/doc'' or ``cspice/doc'' directory in the
FORTRAN and C Toolkit installation trees.
Name Functions/routines that it describes --------------- ----------------------------------------- cells.req The SPICE cell data type error.req SPICE error handling frames.req Using reference frames kernel.req Loading SPICE kernels naif_ids.req Body and reference frame names sets.req The SPICE set data type spk.req Computing positions and velocities time.req UTC to ET time conversion windows.req The SPICE window data typeAnother very useful document, also distributed with the Toolkit, is the ``Permuted Index'', called ``cspice.idx''; the Permuted index is located under ``doc'' directory in the Toolkit installation tree.
This text document provides an easy way to find which SPICE routine(s) performs a particular function in which you are interested. It also provides the name of the source file that contains this function.
The most detailed specification of a given SPICE FORTRAN or C routine
is contained in the header section of its source code. The source code
is distributed with the Toolkit and is located under
``toolkit/src/spicelib'' in FORTRAN and under ``cspice/src/cspice'' in
C Toolkits.
For example the source code of the STR2ET/str2et_c routine is
toolkit/src/spicelib/str2et.forin the FORTRAN Toolkit and in
cspice/src/cspice/str2et_c.cin the C Toolkit.
Since some of the FORTRAN routines are entry points they are usually part of a source file that has different name. The ``Permuted Index'' document mentioned above can be used to locate the name of their source file.
The following kernels are used in examples provided in this lesson:
File Name Type Description ----------------------- ---- -------------------------- de405s.bsp SPK Planet Ephemeris SPK dsnstns.bsp SPK DSN station SPK DSN_topo.frm FK DSN station frame definitions earth_031228_231229_predict.bpc PCK Binary predict PCK for earth ORMM__040501000000_00069.BSP SPK MEX Orbiter Trajectory SPK naif0007.tls LSK Generic LSK pck00007.tpc PCK Generic PCKThese SPICE kernels are available from the NAIF server at JPL:
ftp://naif.jpl.nasa.gov/pub/naif/misc/lessons/events
The following CSPICE routines are used in the solution programs to be
written by the student, or in the supporting utility routines provided
in this lesson:
Name Function that it performs ---------- --------------------------------------------------- appndd_c Appends an item to a d.p. cell badkpv_c Checks a kernel variable definition card_c Return cardinality of d.p. cell chkin_c SPICE call tree tracing check-in chkout_c SPICE call tree tracing check-out cnmfrm_c Map a body name to an associated frame rpd_c Return number of degrees per radian errch_c Substitute a character string into an error message errdp_c Substitute a d.p. number into an error message furnsh_c Loads kernels, individually or listed in meta-kernel gcpool_c Fetch string values from the kernel pool gdpool_c Fetch d.p. values from the kernel pool kdata_c Return info on specified loaded kernel ktotal_c Return the count of loaded kernels of a given type reclat_c Transform from rectangular to latitudinal coordinates return_c Test whether CSPICE routines should return on entry rpd_c Return number of radians per degree setmsg_c Set the SPICE long error message sigerr_c Signal a SPICE error spkpos_c Computes positions of ephemeris objects str2et_c Converts a time string to ET seconds past J2000 srfxpt_c Find intersection of ray and ellipsoidal target body timout_c Format a time string for output vnorm_c Find the norm of a 3-vector wndifd_c Find the difference of two d.p. windows wnfetd_c Fetch a specified interval from a d.p. window wninsd_c Insert an interval into a d.p. windowThe most detailed documentation source for these routines is their headers.
The following utility routines are used in the solution programs to be
written by the student, or in the supporting utility routines provided
in this lesson:
Name Function that it performs ---------- --------------------------------------------------- fndevt Find set of times of state transitions makwin Convert state transition set to CSPICE window modocp Umbrella file for occultation utilities modris Umbrella file for rise-set utilities setocp Set parameter values for occultation utilities setris Set parameter values for rise-set utilities stocp Indicate whether target is occulted stris Indicate whether target elevation is above limitThe function fndevt is the key root-finding utility. Given a SpiceBoolean function of time f(t), and a time interval, fndevt finds the set of times within the interval at which the value returned by f(t) changes.
In this context, we call f(t) a ``state function'' and the epochs at which the value of f(t) changes ``epochs of state transitions'' or simply ``state transitions.''
fndevt stores the state transition epochs it finds in a CSPICE set, which is an output argument.
The utility makwin converts the set returned by fndevt into a CSPICE window whose intervals represent the time periods when the state returned by f(t) is SPICETRUE.
The purpose of the suite of routines contained in the module modris is to enable a user to define and use a ``state function'' that indicates when a target is above a specified elevation limit, as seen by an observer at a surface location on an extended body. The module contains an initialization function setris that allows a user to set parameters defining the geometry of interest and a state function stris that uses values established by setris to decide whether the target is above the elevation limit at a specified time. The function stris computes target elevation using the function srfazl, which is supplied by the student.
In the same vein, the purpose of the suite of routines contained in the module modocp is to enable a user to define and use a ``state function'' that indicates when a point target is occulted by a specified extended body, as seen by a specified observer. The module contains an initialization function setocp that allows a user to set parameters defining the geometry of interest and a state function stocp that uses values established by setocp to decide whether the target is occulted at a specified time. The function stocp tests for occultation using the function occpt, which is supplied by the student.
Write a program that loads SPICE kernels and reads input values
required to solve the point target visibility problem.
Create a SPICE text kernel (``meta-kernel'') containing information required to initialize the program. The program is to read both command inputs and SPICE kernel names from this SPICE text kernel. The following items are to be read from the kernel:
The student is introduced to flexible, robust techniques for
introducing data into CSPICE based programs.
The student is exposed to the following SPICE components:
A possible solution would consist of the following steps:
Preparation:
The meta-kernel we created for the solution to this exercise is named
'geomevnt.mk'. Its contents follow:
Example meta-kernel for geometric event finding hands-on coding lesson. Version 1.0.0 07-MAY-2004 (NJB) Identify names of kernels to load: \begindata KERNELS_TO_LOAD = ( 'kernels/spk/de405s.bsp' 'kernels/spk/dsnstns.bsp' 'kernels/fk/DSN_topo.frm' 'kernels/pck/earth_031228_231229_predict.bpc' 'kernels/lsk/naif0007.tls' 'kernels/spk/ORMM__040501000000_00069.BSP' 'kernels/pck/pck00007.tpc' ) \begintext Set values of other inputs: surface point target occulting body aberration correction search interval start time search interval stop time elevation limit The kernel variable names used here are examples; the programmer may choose other names. The names must be no longer than 32 characters and are case-sensitive. These names must be referenced in calls to the kernel pool fetch routines. \begindata SCVIEW_SRFPT = 'DSS-14' SCVIEW_TARGET = 'MEX' SCVIEW_OCCBDY = 'MARS' SCVIEW_ABCORR = 'CN+S' SCVIEW_START = '2004 MAY 1 TDB' SCVIEW_STOP = '2004 MAY 5 TDB' SCVIEW_ELVLIM = 6.0 \begintext
The example program below shows one possible solution.
#include <stdio.h> #include <math.h> #include "SpiceUsr.h" /* PROGRAM SCVIEW Find the view periods for a point target as seen from a specified surface location. Exclude periods when target is occulted by extended bodies other than the one associated with the viewing location. Display the windows of visibility. The following items are loaded from a SPICE text kernel: - Observer (surface point) name - Target name - Occulting body name - Aberration correction specification - Start time string - Stop time #include <string.h> - Elevation limit (in degrees) This program assumes all necessary kernels and kernel variable definitions are specified in a SPICE meta-kernel. The meta-kernel name is assumed to be 'geomevnt.mk'. 07-MAY-2004 (NJB) 31-OCT-2002 (NJB) */ int main() { /* Local constants */ /* The meta-kernel: */ #define META "geomevnt.mk" /* Labels of kernel pool items: */ #define CORLBL "SCVIEW_ABCORR" #define ELVLBL "SCVIEW_ELVLIM" #define OCCLBL "SCVIEW_OCCBDY" #define SRFLBL "SCVIEW_SRFPT" #define STPLBL "SCVIEW_STOP" #define STRLBL "SCVIEW_START" #define TRGLBL "SCVIEW_TARGET" /* String lengths and other bounds: */ #define CORLEN 11 #define FILSIZ 256 #define LNSIZE 201 #define NAMLEN 33 #define TIMLEN 51 #define TYPLEN 51 /* Local variables */ SpiceBoolean found; SpiceChar abcorr [ CORLEN ]; SpiceChar file [ FILSIZ ]; SpiceChar filtyp [ TYPLEN ]; SpiceChar occbdy [ NAMLEN ]; SpiceChar source [ FILSIZ ]; SpiceChar srfpt [ NAMLEN ]; SpiceChar start [ TIMLEN ]; SpiceChar stop [ TIMLEN ]; SpiceChar target [ NAMLEN ]; SpiceChar timstr [ TIMLEN ]; SpiceDouble elvlim; SpiceDouble etbeg; SpiceDouble etend; SpiceDouble revlim; SpiceInt handle; SpiceInt i; SpiceInt n; SpiceInt nker; /* Load the meta-kernel. */ furnsh_c ( META ); /* Look up observation location, target, name of the occulting body, aberration correction, start and stop times, and elevation limit. We simplify error checking by using badkpv_c. badkpv_c tests whether a kernel variable having specified attributes is present in the kernel pool. The fourth argument of badkpv_c is the expected dimension; the last indicates the expected data type. Read the header of badkpv_c for details. */ badkpv_c ( "scview", SRFLBL, "=", 1, 1, 'C' ); badkpv_c ( "scview", OCCLBL, "=", 1, 1, 'C' ); badkpv_c ( "scview", TRGLBL, "=", 1, 1, 'C' ); badkpv_c ( "scview", CORLBL, "=", 1, 1, 'C' ); badkpv_c ( "scview", STRLBL, "=", 1, 1, 'C' ); badkpv_c ( "scview", STPLBL, "=", 1, 1, 'C' ); badkpv_c ( "scview", ELVLBL, "=", 1, 1, 'N' ); /* Now we know the kernel variables of interest have been defined; look up the values. We don't need to check the found flag because badkpv_c has ensured that each item will be found. */ gcpool_c ( SRFLBL, 0, 1, NAMLEN, &n, srfpt, &found ); gcpool_c ( OCCLBL, 0, 1, NAMLEN, &n, occbdy, &found ); gcpool_c ( TRGLBL, 0, 1, NAMLEN, &n, target, &found ); gcpool_c ( CORLBL, 0, 1, CORLEN, &n, abcorr, &found ); gcpool_c ( STRLBL, 0, 1, TIMLEN, &n, start, &found ); gcpool_c ( STPLBL, 0, 1, TIMLEN, &n, stop, &found ); gdpool_c ( ELVLBL, 0, 1, &n, &elvlim, &found ); revlim = rpd_c() * elvlim; /* Display to standard output a banner for the output report: */ printf ( "\n%s\n\n", "Inputs for geometric event finding program" ); printf ( " Target = %s\n", target ); printf ( " Observation surface location = %s\n", srfpt ); printf ( " Occulting body = %s\n", occbdy ); printf ( " Aberration correction = %s\n", abcorr ); /* Convert the start and stop times to ET. */ str2et_c ( start, &etbeg ); str2et_c ( stop, &etend ); /* Display the start time as both calendar ET and calendar UTC using the formats shown below. 2004 MAY 06 20:15:00.000 (UTC) 2004 MAY 06 20:15:00.000 (TDB) */ timout_c ( etbeg, "YYYY MON DD HR:MN:SC.### (UTC)", TIMLEN, timstr ); printf ( " Start time = %s\n", timstr ); timout_c ( etbeg, "YYYY MON DD HR:MN:SC.### (TDB) ::TDB", TIMLEN, timstr ); printf ( " Start time = %s\n", timstr ); timout_c ( etend, "YYYY MON DD HR:MN:SC.### (UTC)", TIMLEN, timstr ); printf ( " Stop time = %s\n", timstr ); timout_c ( etend, "YYYY MON DD HR:MN:SC.### (TDB) ::TDB", TIMLEN, timstr ); printf ( " Stop time = %s\n", timstr ); /* Display the elevation limit in degrees. */ printf ( " Elevation limit (degrees) = %f\n", elvlim ); /* Display the names of the SPICE kernels we've loaded. */ printf ( "\n" "Loaded SPICE Kernels:\n" ); ktotal_c ( "ALL", &nker ); for ( i = 0; i < nker; i++ ) { kdata_c ( i, "ALL", FILSIZ, TYPLEN, FILSIZ, file, filtyp, source, &handle, &found ); /* Due to the way we've constructed the loop, there's no need to check the 'found' flag. */ printf ( "\n" " Kernel name: %s\n" " Kernel type: %s\n" " Kernel source: %s\n", file, filtyp, source ); } return ( 0 ); }
Numerical results shown for this example may differ across platforms
since the results depend on the SPICE kernels used as input and on the
host platform's arithmetic implementation.
After compiling the program, execute it. The output is:
Inputs for geometric event finding program Target = MEX Observation surface location = DSS-14 Occulting body = MARS Aberration correction = CN+S Start time = 2004 APR 30 23:58:55.814 (UTC) Start time = 2004 MAY 01 00:00:00.000 (TDB) Stop time = 2004 MAY 04 23:58:55.814 (UTC) Stop time = 2004 MAY 05 00:00:00.000 (TDB) Elevation limit (degrees) = 6.000000 Loaded SPICE Kernels: Kernel name: geomevnt.mk Kernel type: META Kernel source: Kernel name: de405s.bsp Kernel type: SPK Kernel source: geomevnt.mk Kernel name: dsnstns.bsp Kernel type: SPK Kernel source: geomevnt.mk Kernel name: DSN_topo.frm Kernel type: TEXT Kernel source: geomevnt.mk Kernel name: earth_031228_231229_predict.bpc Kernel type: PCK Kernel source: geomevnt.mk Kernel name: naif0007.tls Kernel type: TEXT Kernel source: geomevnt.mk Kernel name: ORMM__040501000000_00069.BSP Kernel type: SPK Kernel source: geomevnt.mk Kernel name: pck00007.tpc Kernel type: TEXT Kernel source: geomevnt.mk
Write a function to find the azimuth and elevation of a target as seen
from a specified location on the surface of an extended body. Also
return the range to the target.
The output angles are measured relative to a topocentric frame centered at the surface location. Angular units are radians.
In the topocentric frame, elevation is equivalent to latitude, and azimuth is the negative of longitude.
The function is to have the exact signature shown below:
void srfazl ( ConstSpiceChar * srfpt, SpiceDouble et, ConstSpiceChar * abcorr, ConstSpiceChar * targ, SpiceDouble * az, SpiceDouble * el, SpiceDouble * r )The meanings of the arguments are as follows:
srfpt Name of surface point, e.g. "DSS-14" et Computation epoch, seconds past J2000 TDB. abcorr Aberration correction flag: "NONE", "LT+S", etc. targ Target name. az Azimuth in radians. el Elevation in radians. r Range in kilometers.This function will be used by the supplied event finding utilities to find times when the target is above the specified elevation limit.
Test the routine by calling it twice and displaying the outputs. The first call should use the input values:
srfpt "DSS-14" et Double precision count of seconds past J2000 TDB corresponding to 2004 MAY 01 16:10:26.686 TDB abcorr "CN+S" targ "MEX"The second call should use the same inputs as the first, except that the time should be the double precision count of seconds past J2000 TDB corresponding to 2004 MAY 01 16:10:26.688 TDB.
The two times are intended to bracket a spacecraft ``rise'' event: the target spacecraft should have elevation below the specified limit at the first time and above the limit at the second.
This exercise introduces the student to elementary geometry
computations using CSPICE. The student uses spkpos_c to look up
position vectors and reclat_c to convert from rectangular to
latitudinal coordinates.
When the CSPICE event finding software is delivered, computations of this type usually will not have to be performed by users in the course of solving event-finding problems: the CSPICE event finding software will do the job behind the scenes. However, this exercise is meant to provide the student with some insight into the geometry computations involved in an event finding system.
A possible solution would consist of the following steps:
Write the srfazl function:
The example program below shows one possible implementation of the
function srfazl.
#include "SpiceUsr.h" void srfazl ( ConstSpiceChar * srfpt, SpiceDouble et, ConstSpiceChar * abcorr, ConstSpiceChar * targ, SpiceDouble * az, SpiceDouble * el, SpiceDouble * r ) /* Find the azimuth and elevation of a target as seen from a specified location on the surface of an extended body. Also return the range to the target and the one-way light time. The output angles are measured relative to a topocentric frame centered at the surface location. Angular units are radians. Subroutine arguments: srfpt is a string giving the name of the surface point of interest. A topocentric frame is defined at this point. et is the epoch at which the location of the target is to be found. et is given in seconds past J2000 (TDB). abcorr indicates the aberration correction. Values and meanings are: "NONE" No correction. Use geometric states. The following are for the "reception" case where radiation travels from the target to the surface point and arrives at et: "LT" Correct for one-way light time. "LT+S" Correct for one-way light time and stellar aberration. "CN" Converged Newtonian light time correction. "CN+S" Converged Newtonian light time and stellar aberration corrections. The following are for the "transmission" case where radiation travels from the surface point to the target, departing the surface location at et: "XLT" Correct for one-way light time. "XLT+S" Correct for one-way light time and stellar aberration. "XCN" Converged Newtonian light time correction. "XCN+S" Converged Newtonian light time and stellar aberration corrections. targ is a string containing the target name. az, el are the azimuth and elevation of the target vector at et. Azimuth and elevation are given with respect to a right-handed frame with z-axis equal to the local surface normal, x-axis orthogonal to the z-axis and pointing north, and the y-axis equal to z cross x. Azimuth is the angle between the x-axis and the projection of the target vector onto the topocentric x-y plane. Azimuth increases in the clockwise direction. Elevation is the angle between the target vector and the x-y plane. Both angles are given in radians. r is the range to the target, in km. -Version Events Code Lesson 1.0.1 07-MAY-2004 (NJB) Description of erstwhile output argument `lt' was removed. Events Code Lesson 1.0.0 04-MAY-2004 (NJB) Modified to use cnmfrm_c.c. RS Code Lesson 1.0.0 31-OCT-2002 (NJB) */ { /* Local constants */ #define FRNMLN 33 /* Local variables */ SpiceBoolean found; SpiceChar frname [FRNMLN]; SpiceDouble lon; SpiceDouble lt; SpiceDouble trgpos[3]; SpiceInt frcode; if ( return_c() ) { return; } chkin_c ( "srfazl" ); /* Look up the topocentric reference frame associated with the surface point. The definition of this frame is supplied in a frame kernel loaded by the calling program. */ cnmfrm_c ( srfpt, FRNMLN, &frcode, frname, &found ); if ( !found ) { setmsg_c ( "No frame is associated with body #." "This can be due to a required frame " "kernel not having been loaded." ); errch_c ( "#", srfpt ); sigerr_c ( "SPICE(NOTDEFINED)" ); chkout_c ( "srfazl" ); return; } /* Find the position of the target as seen from the observer at 'et'. Use the specified aberration corrections. Ask for the position vector in the topocentric frame associated with the surface point. */ spkpos_c ( targ, et, frname, abcorr, srfpt, trgpos, < ); /* Elevation is the angular separation of the surface point-target vector from the x-y plane of the topocentric frame; this is simply latitude. Azimuth is the negative of the longitude angle. Note lon is a local variable; r and el are pointer arguments of this function. */ reclat_c ( trgpos, r, &lon, el ); *az = -lon; chkout_c ( "srfazl" ); }
The example program below shows one possible solution.
#include <stdio.h> #include <math.h> #include "SpiceUsr.h" /* PROGRAM SCVIEW Find the view periods for a point target as seen from a specified surface location. Exclude periods when target is occulted by extended bodies other than the one associated with the viewing location. Display the windows of visibility. The following items are loaded from a SPICE text kernel: - Observer (surface point) name - Target name - Occulting body name - Aberration correction specification - Start time string - Stop time #include <string.h> - Elevation limit (in degrees) This program assumes all necessary kernels and kernel variable definitions are specified in a SPICE meta-kernel. The meta-kernel name is assumed to be 'geomevnt.mk'. 07-MAY-2004 (NJB) 31-OCT-2002 (NJB) */ int main() { /* Prototypes */ void srfazl ( ConstSpiceChar * srfpt, SpiceDouble et, ConstSpiceChar * abcorr, ConstSpiceChar * targ, SpiceDouble * az, SpiceDouble * el, SpiceDouble * r ); /* Local constants */ /* The meta-kernel: */ #define META "geomevnt.mk" /* Labels of kernel pool items: */ #define CORLBL "SCVIEW_ABCORR" #define ELVLBL "SCVIEW_ELVLIM" #define OCCLBL "SCVIEW_OCCBDY" #define SRFLBL "SCVIEW_SRFPT" #define STPLBL "SCVIEW_STOP" #define STRLBL "SCVIEW_START" #define TRGLBL "SCVIEW_TARGET" /* String lengths and other bounds: */ #define CORLEN 11 #define FILSIZ 256 #define LNSIZE 201 #define NAMLEN 33 #define TIMLEN 51 #define TYPLEN 51 /* Local variables */ SpiceBoolean found; SpiceChar abcorr [ CORLEN ]; SpiceChar file [ FILSIZ ]; SpiceChar filtyp [ TYPLEN ]; SpiceChar occbdy [ NAMLEN ]; SpiceChar source [ FILSIZ ]; SpiceChar srfpt [ NAMLEN ]; SpiceChar start [ TIMLEN ]; SpiceChar stop [ TIMLEN ]; SpiceChar target [ NAMLEN ]; SpiceChar timstr [ TIMLEN ]; SpiceChar * tsttim [2]; SpiceDouble az; SpiceDouble el; SpiceDouble elvlim; SpiceDouble et; SpiceDouble etbeg; SpiceDouble etend; SpiceDouble r; SpiceDouble revlim; SpiceInt handle; SpiceInt i; SpiceInt n; SpiceInt nker; /* Load the meta-kernel. */ furnsh_c ( META ); /* Look up observation location, target, name of the occulting body, aberration correction, start and stop times, and elevation limit. We simplify error checking by using badkpv_c. badkpv_c tests whether a kernel variable having specified attributes is present in the kernel pool. The fourth argument of badkpv_c is the expected dimension; the last indicates the expected data type. Read the header of badkpv_c for details. */ badkpv_c ( "scview", SRFLBL, "=", 1, 1, 'C' ); badkpv_c ( "scview", OCCLBL, "=", 1, 1, 'C' ); badkpv_c ( "scview", TRGLBL, "=", 1, 1, 'C' ); badkpv_c ( "scview", CORLBL, "=", 1, 1, 'C' ); badkpv_c ( "scview", STRLBL, "=", 1, 1, 'C' ); badkpv_c ( "scview", STPLBL, "=", 1, 1, 'C' ); badkpv_c ( "scview", ELVLBL, "=", 1, 1, 'N' ); /* Now we know the kernel variables of interest have been defined; look up the values. We don't need to check the found flag because badkpv_c has ensured that each item will be found. */ gcpool_c ( SRFLBL, 0, 1, NAMLEN, &n, srfpt, &found ); gcpool_c ( OCCLBL, 0, 1, NAMLEN, &n, occbdy, &found ); gcpool_c ( TRGLBL, 0, 1, NAMLEN, &n, target, &found ); gcpool_c ( CORLBL, 0, 1, CORLEN, &n, abcorr, &found ); gcpool_c ( STRLBL, 0, 1, TIMLEN, &n, start, &found ); gcpool_c ( STPLBL, 0, 1, TIMLEN, &n, stop, &found ); gdpool_c ( ELVLBL, 0, 1, &n, &elvlim, &found ); revlim = rpd_c() * elvlim; /* Display to standard output a banner for the output report: */ printf ( "\n%s\n\n", "Inputs for geometric event finding program" ); printf ( " Target = %s\n", target ); printf ( " Observation surface location = %s\n", srfpt ); printf ( " Occulting body = %s\n", occbdy ); printf ( " Aberration correction = %s\n", abcorr ); /* Convert the start and stop times to ET. */ str2et_c ( start, &etbeg ); str2et_c ( stop, &etend ); /* Display the start time as both calendar ET and calendar UTC using the formats shown below. 2004 MAY 06 20:15:00.000 (UTC) 2004 MAY 06 20:15:00.000 (TDB) */ timout_c ( etbeg, "YYYY MON DD HR:MN:SC.### (UTC)", TIMLEN, timstr ); printf ( " Start time = %s\n", timstr ); timout_c ( etbeg, "YYYY MON DD HR:MN:SC.### (TDB) ::TDB", TIMLEN, timstr ); printf ( " Start time = %s\n", timstr ); timout_c ( etend, "YYYY MON DD HR:MN:SC.### (UTC)", TIMLEN, timstr ); printf ( " Stop time = %s\n", timstr ); timout_c ( etend, "YYYY MON DD HR:MN:SC.### (TDB) ::TDB", TIMLEN, timstr ); printf ( " Stop time = %s\n", timstr ); /* Display the elevation limit in degrees. */ printf ( " Elevation limit (degrees) = %f\n", elvlim ); /* Display the names of the SPICE kernels we've loaded. */ printf ( "\n" "Loaded SPICE Kernels:\n" ); ktotal_c ( "ALL", &nker ); for ( i = 0; i < nker; i++ ) { kdata_c ( i, "ALL", FILSIZ, TYPLEN, FILSIZ, file, filtyp, source, &handle, &found ); /* Due to the way we've constructed the loop, there's no need to check the 'found' flag. */ printf ( "\n" " Kernel name: %s\n" " Kernel type: %s\n" " Kernel source: %s\n", file, filtyp, source ); } printf ( "\n" "srfazl test results:\n" "\n" ); /* Test srfazl: make two calls at times bracketing a spacecraft "rise" event. */ tsttim[0] = "2004 MAY 01 16:10:26.686 TDB"; tsttim[1] = "2004 MAY 01 16:10:26.688 TDB"; for ( i = 0; i < 2; i++ ) { /* Convert the TDB calendar time to seconds past J2000. Find the azimuth, elevation, and range at this time. */ str2et_c ( tsttim[i], &et ); srfazl ( srfpt, et, abcorr, target, &az, &el, &r ); /* Display the time and srfazl outputs. Convert radians to degrees for output using the CSPICE function dpr_c(). */ printf ( " ET = %s\n" " Elevation (degrees): %21.16e\n" " Azimuth (degrees): %21.16e\n" " Range (km): %21.16e\n" "\n", tsttim[i], el * dpr_c(), az * dpr_c(), r ); } return ( 0 ); }
Numerical results shown for this example may differ across platforms
since the results depend on the SPICE kernels used as input and on the
host platform's arithmetic implementation.
Inputs for geometric event finding program Target = MEX Observation surface location = DSS-14 Aberration correction = CN+S Start time = 2004 APR 30 23:58:55.814 (UTC) Start time = 2004 MAY 01 00:00:00.000 (TDB) Stop time = 2004 MAY 04 23:58:55.814 (UTC) Stop time = 2004 MAY 05 00:00:00.000 (TDB) Elevation limit (degrees) = 6.000000 Loaded SPICE Kernels: Kernel name: geomevnt.mk Kernel type: META Kernel source: Kernel name: de405s.bsp Kernel type: SPK Kernel source: geomevnt.mk Kernel name: dsnstns.bsp Kernel type: SPK Kernel source: geomevnt.mk Kernel name: DSN_topo.frm Kernel type: TEXT Kernel source: geomevnt.mk Kernel name: earth_031228_231229_predict.bpc Kernel type: PCK Kernel source: geomevnt.mk Kernel name: naif0007.tls Kernel type: TEXT Kernel source: geomevnt.mk Kernel name: ORMM__040501000000_00069.BSP Kernel type: SPK Kernel source: geomevnt.mk Kernel name: pck00007.tpc Kernel type: TEXT Kernel source: geomevnt.mk srfazl test results: ET = 2004 MAY 01 16:10:26.686 TDB Elevation (degrees): 5.9999951213034e+00 Azimuth (degrees): 6.3942106540558e+01 Range (km): 3.2480333721584e+08 ET = 2004 MAY 01 16:10:26.688 TDB Elevation (degrees): 6.0000012274140e+00 Azimuth (degrees): 6.3942111060397e+01 Range (km): 3.2480333724230e+08
Write a SpiceBoolean function to test when a point target is occulted
by a specified extended body, as seen from a specified observing body.
The function is to have the exact signature shown below:
SpiceBoolean occpt ( ConstSpiceChar * target, ConstSpiceChar * occbdy, SpiceDouble et, ConstSpiceChar * abcorr, ConstSpiceChar * obsrvr );The meanings of the arguments are as follows:
target Target name. occbdy Occulting body name. et Computation epoch, seconds past J2000 TDB. abcorr Aberration correction flag: "none", "lt+s", etc. obsrvr Observing body name. occpt SpiceBoolean function value: SPICETRUE if the target is occulted; SPICEFALSE otherwise.This function will be used by the supplied event finding utilities to find times when the target is occulted by the specified occulting body.
Test the routine by calling it twice and displaying the outputs. The first call should use the input values:
target "MEX" occbdy "MARS" et Double precision count of seconds past J2000 TDB corresponding to 2004 MAY 01 13:38:36.740 TDB abcorr "CN+S" obsrvr "DSS-14"The second call should use the same inputs as the first, except that the time should be the double precision count of seconds past J2000 TDB corresponding to 2004 MAY 01 13:38:36.742 TDB.
The two times are intended to bracket a spacecraft occultation ingress event: the aberration-corrected target spacecraft location should be visible at the first time and occulted at the second.
This exercise introduces the student to further elementary geometry
computations using CSPICE. The student uses spkpos_c to look up
position vectors and srfxpt_c to test whether a specified ray
intersects an extended body modeled as a triaxial ellipsoid.
This exercise is meant to provide the student with further understanding of the geometry computations involved in an event finding system.
A possible solution would consist of the following steps:
Write the occpt function:
The example program below shows one possible solution.
#include "SpiceUsr.h" SpiceBoolean occpt ( ConstSpiceChar * target, ConstSpiceChar * occbdy, SpiceDouble et, ConstSpiceChar * abcorr, ConstSpiceChar * obsrvr ) /* Determine whether a point target is occulted by extended body, as seen from a specified observation location. Subroutine arguments: target is a string giving the name of the target body of interest occbdy is a string giving the name of a potentially occulting extended body. et is the epoch at which the visibility computation is to be performed. et is given in seconds past J2000 (TDB). abcorr indicates the aberration correction. Values and meanings are: "NONE" No correction. Use geometric states. The following are for the "reception" case where radiation travels from the target body and arrives at the observer at ET: "LT" Correct for one-way light time. "LT+S" Correct for one-way light time and stellar aberration. "CN" Converged Newtonian light time correction. "CN+S" Converged Newtonian light time and stellar aberration corrections. The following are for the "transmission" case where radiation travels from the observer to the target body, departing the observer's location at et: "XLT" Correct for one-way light time. "XLT+S" Correct for one-way light time and stellar aberration. "XCN" Converged Newtonian light time correction. "XCN+S" Converged Newtonian light time and stellar aberration corrections. obsrvr is a string containing the observer's name. The function returns SPICETRUE if the target is occulted and SPICEFALSE otherwise. 07-MAY-2004 (NJB) Updated to use srfxpt_c. 31-OCT-2002 (NJB) */ { /* Local constants */ #define FRNMLN 33 /* Local variables */ SpiceBoolean found; SpiceDouble dist; SpiceDouble obspos [3]; SpiceDouble trgepc; SpiceDouble trglt; SpiceDouble trgpos [3]; SpiceDouble xpt [3]; if ( return_c() ) { return ( SPICEFALSE ); } chkin_c ( "occpt" ); /* Find the position of the target relative to the observer, using the specified aberration corrections. Use the J2000 reference frame. */ spkpos_c ( target, et, "J2000", abcorr, obsrvr, trgpos, &trglt ); /* Determine the surface intercept (if any) with the occulting body of the ray emanating from the observer and pointing toward the target. */ srfxpt_c ( "Ellipsoid", occbdy, et, abcorr, obsrvr, "J2000", trgpos, xpt, &dist, &trgepc, obspos, &found ); if ( !found ) { /* If there's no intercept, the target is not occulted. We're done. */ chkout_c ( "occpt" ); return ( SPICEFALSE ); } /* At this point, we know there's an intercept. If the target lies between the observer and the intercept point, the target is still visible. Otherwise, the target is occulted. */ chkout_c ( "occpt" ); return ( ( SpiceBoolean ) ( vnorm_c(trgpos) > dist ) ); }
The example program below shows one possible solution.
#include <stdio.h> #include <math.h> #include "SpiceUsr.h" /* PROGRAM SCVIEW Find the view periods for a point target as seen from a specified surface location. Exclude periods when target is occulted by extended bodies other than the one associated with the viewing location. Display the windows of visibility. The following items are loaded from a SPICE text kernel: - Observer (surface point) name - Target name - Occulting body name - Aberration correction specification - Start time string - Stop time #include <string.h> - Elevation limit (in degrees) This program assumes all necessary kernels and kernel variable definitions are specified in a SPICE meta-kernel. The meta-kernel name is assumed to be 'geomevnt.mk'. 07-MAY-2004 (NJB) 31-OCT-2002 (NJB) */ int main() { /* Prototypes */ SpiceBoolean occpt ( ConstSpiceChar * target, ConstSpiceChar * occbdy, SpiceDouble et, ConstSpiceChar * abcorr, ConstSpiceChar * obsrvr ); void srfazl ( ConstSpiceChar * srfpt, SpiceDouble et, ConstSpiceChar * abcorr, ConstSpiceChar * targ, SpiceDouble * az, SpiceDouble * el, SpiceDouble * r ); /* Local constants */ /* The meta-kernel: */ #define META "geomevnt.mk" /* Labels of kernel pool items: */ #define CORLBL "SCVIEW_ABCORR" #define ELVLBL "SCVIEW_ELVLIM" #define OCCLBL "SCVIEW_OCCBDY" #define SRFLBL "SCVIEW_SRFPT" #define STPLBL "SCVIEW_STOP" #define STRLBL "SCVIEW_START" #define TRGLBL "SCVIEW_TARGET" /* STEPSZ is the step size, measured in seconds, used to search for times bracketing a state transition. */ #define STEPSZ (300.0) /* Maximum number of events we can handle in our event set: */ #define MAXEVT 1000 /* Maximum result window size: */ #define MAXWIN ( 2 * MAXEVT ) /* String lengths and other bounds: */ #define CORLEN 11 #define FILSIZ 256 #define LNSIZE 201 #define NAMLEN 33 #define TIMLEN 51 #define TYPLEN 51 /* Local variables */ SpiceBoolean found; SpiceBoolean hidden; SpiceChar abcorr [ CORLEN ]; SpiceChar file [ FILSIZ ]; SpiceChar filtyp [ TYPLEN ]; SpiceChar occbdy [ NAMLEN ]; SpiceChar source [ FILSIZ ]; SpiceChar srfpt [ NAMLEN ]; SpiceChar start [ TIMLEN ]; SpiceChar stop [ TIMLEN ]; SpiceChar target [ NAMLEN ]; SpiceChar timstr [ TIMLEN ]; SpiceChar * tsttim [2]; SpiceDouble az; SpiceDouble el; SpiceDouble elvlim; SpiceDouble et; SpiceDouble etbeg; SpiceDouble etend; SpiceDouble r; SpiceDouble revlim; SpiceInt handle; SpiceInt i; SpiceInt n; SpiceInt nker; /* Load the meta-kernel. */ furnsh_c ( META ); /* Look up observation location, target, name of the occulting body, aberration correction, start and stop times, and elevation limit. We simplify error checking by using badkpv_c. badkpv_c tests whether a kernel variable having specified attributes is present in the kernel pool. The fourth argument of badkpv_c is the expected dimension; the last indicates the expected data type. Read the header of badkpv_c for details. */ badkpv_c ( "scview", SRFLBL, "=", 1, 1, 'C' ); badkpv_c ( "scview", OCCLBL, "=", 1, 1, 'C' ); badkpv_c ( "scview", TRGLBL, "=", 1, 1, 'C' ); badkpv_c ( "scview", CORLBL, "=", 1, 1, 'C' ); badkpv_c ( "scview", STRLBL, "=", 1, 1, 'C' ); badkpv_c ( "scview", STPLBL, "=", 1, 1, 'C' ); badkpv_c ( "scview", ELVLBL, "=", 1, 1, 'N' ); /* Now we know the kernel variables of interest have been defined; look up the values. We don't need to check the found flag because badkpv_c has ensured that each item will be found. */ gcpool_c ( SRFLBL, 0, 1, NAMLEN, &n, srfpt, &found ); gcpool_c ( OCCLBL, 0, 1, NAMLEN, &n, occbdy, &found ); gcpool_c ( TRGLBL, 0, 1, NAMLEN, &n, target, &found ); gcpool_c ( CORLBL, 0, 1, CORLEN, &n, abcorr, &found ); gcpool_c ( STRLBL, 0, 1, TIMLEN, &n, start, &found ); gcpool_c ( STPLBL, 0, 1, TIMLEN, &n, stop, &found ); gdpool_c ( ELVLBL, 0, 1, &n, &elvlim, &found ); revlim = rpd_c() * elvlim; /* Display to standard output a banner for the output report: */ printf ( "\n%s\n\n", "Inputs for geometric event finding program" ); printf ( " Target = %s\n", target ); printf ( " Observation surface location = %s\n", srfpt ); printf ( " Occulting body = %s\n", occbdy ); printf ( " Aberration correction = %s\n", abcorr ); /* Convert the start and stop times to ET. */ str2et_c ( start, &etbeg ); str2et_c ( stop, &etend ); /* Display the start time as both calendar ET and calendar UTC using the formats shown below. 2004 MAY 06 20:15:00.000 (UTC) 2004 MAY 06 20:15:00.000 (TDB) */ timout_c ( etbeg, "YYYY MON DD HR:MN:SC.### (UTC)", TIMLEN, timstr ); printf ( " Start time = %s\n", timstr ); timout_c ( etbeg, "YYYY MON DD HR:MN:SC.### (TDB) ::TDB", TIMLEN, timstr ); printf ( " Start time = %s\n", timstr ); timout_c ( etend, "YYYY MON DD HR:MN:SC.### (UTC)", TIMLEN, timstr ); printf ( " Stop time = %s\n", timstr ); timout_c ( etend, "YYYY MON DD HR:MN:SC.### (TDB) ::TDB", TIMLEN, timstr ); printf ( " Stop time = %s\n", timstr ); /* Display the elevation limit in degrees. */ printf ( " Elevation limit (degrees) = %f\n", elvlim ); /* Display the names of the SPICE kernels we've loaded. */ printf ( "\n" "Loaded SPICE Kernels:\n" ); ktotal_c ( "ALL", &nker ); for ( i = 0; i < nker; i++ ) { kdata_c ( i, "ALL", FILSIZ, TYPLEN, FILSIZ, file, filtyp, source, &handle, &found ); /* Due to the way we've constructed the loop, there's no need to check the 'found' flag. */ printf ( "\n" " Kernel name: %s\n" " Kernel type: %s\n" " Kernel source: %s\n", file, filtyp, source ); } /* Test srfazl: make two calls at times bracketing a spacecraft "rise" event. */ printf ( "\n" "srfazl test results:\n" "\n" ); tsttim[0] = "2004 MAY 01 16:10:26.686 TDB"; tsttim[1] = "2004 MAY 01 16:10:26.688 TDB"; for ( i = 0; i < 2; i++ ) { /* Convert the TDB calendar time to seconds past J2000. Find the azimuth, elevation, and range at this time. */ str2et_c ( tsttim[i], &et ); srfazl ( srfpt, et, abcorr, target, &az, &el, &r ); /* Display the time and outputs from srfazl. Convert radians to degrees for output using the CSPICE function dpr_c(). */ printf ( " ET = %s\n" " Elevation (degrees): %21.16e\n" " Azimuth (degrees): %21.16e\n" " Range (km): %21.16e\n" "\n", tsttim[i], el * dpr_c(), az * dpr_c(), r ); } /* Test occpt: make two calls at times bracketing a spacecraft occultation ingress event. */ printf ( "occpt test results:\n" "\n" ); tsttim[0] = "2004 MAY 01 13:38:36.740 TDB"; tsttim[1] = "2004 MAY 01 13:38:36.742 TDB"; for ( i = 0; i < 2; i++ ) { /* Convert the TDB calendar time to seconds past J2000. */ str2et_c ( tsttim[i], &et ); hidden = occpt ( target, occbdy, et, abcorr, srfpt ); /* Display the time and occultation state. */ if ( hidden ) { printf ( " ET = %s. Occulted.\n", tsttim[i] ); } else { printf ( " ET = %s. Not occulted.\n", tsttim[i] ); } } printf ( "\n" ); return ( 0 ); }
Numerical results shown for this example may differ across platforms
since the results depend on the SPICE kernels used as input and on the
host platform's arithmetic implementation.
Inputs for geometric event finding program Target = MEX Observation surface location = DSS-14 Aberration correction = CN+S Start time = 2004 APR 30 23:58:55.814 (UTC) Start time = 2004 MAY 01 00:00:00.000 (TDB) Stop time = 2004 MAY 04 23:58:55.814 (UTC) Stop time = 2004 MAY 05 00:00:00.000 (TDB) Elevation limit (degrees) = 6.000000 Loaded SPICE Kernels: Kernel name: geomevnt.mk Kernel type: META Kernel source: Kernel name: de405s.bsp Kernel type: SPK Kernel source: geomevnt.mk Kernel name: dsnstns.bsp Kernel type: SPK Kernel source: geomevnt.mk Kernel name: DSN_topo.frm Kernel type: TEXT Kernel source: geomevnt.mk Kernel name: earth_031228_231229_predict.bpc Kernel type: PCK Kernel source: geomevnt.mk Kernel name: naif0007.tls Kernel type: TEXT Kernel source: geomevnt.mk Kernel name: ORMM__040501000000_00069.BSP Kernel type: SPK Kernel source: geomevnt.mk Kernel name: pck00007.tpc Kernel type: TEXT Kernel source: geomevnt.mk srfazl test results: ET = 2004 MAY 01 16:10:26.686 TDB Elevation (degrees): 5.9999951213034e+00 Azimuth (degrees): 6.3942106540558e+01 Range (km): 3.2480333721584e+08 ET = 2004 MAY 01 16:10:26.688 TDB Elevation (degrees): 6.0000012274140e+00 Azimuth (degrees): 6.3942111060397e+01 Range (km): 3.2480333724230e+08 occpt test results: ET = 2004 MAY 01 13:38:36.740 TDB. Not occulted. ET = 2004 MAY 01 13:38:36.742 TDB. Occulted.
Extend the program of the previous chapter to find times when the
target object is above the 6 degree elevation limit in the topocentric
frame associated with the specified surface point.
Store the set of time intervals when the target is visible in a CSPICE window. We'll call this the ``result window.''
Display each of the intervals in the result window as a pair of start and stop times. Express each time as a TDB calendar date using the same format as in the previous program.
The student is introduced to topocentric frames and the CSPICE calls
required to compute azimuth and elevation of a vector expressed in a
topocentric frame.
The student is introduced to a few of the most used CSPICE cell, set and window functions.
The student is introduced to some elementary root-finding techniques. Some aspects of root-finding are widely applicable, such as selecting a search step size or a root-finding convergence tolerance. In addition, manipulation of CSPICE cells, sets, and windows is quite useful for solving more complex root-finding problems, such as finding times when Boolean combinations of geometric criteria are satisfied.
The non-CSPICE utility routines presented here are not emphasized, in part because these utilities unofficial, and more importantly because the planned CSPICE geometric event finding software will replace the utilities presented here.
A possible solution would consist of the following steps:
fndevt ( etbeg, etend, stepsz, &stris, &evtset );
makwin ( etbeg, etend, &stris, &evtset, &riswin );
The example program below shows one possible solution.
#include <stdio.h> #include <math.h> #include "SpiceUsr.h" /* PROGRAM SCVIEW Find the view periods for a point target as seen from a specified surface location. Exclude periods when target is occulted by extended bodies other than the one associated with the viewing location. Display the windows of visibility. The following items are loaded from a SPICE text kernel: - Observer (surface point) name - Target name - Occulting body name - Aberration correction specification - Start time string - Stop time #include <string.h> - Elevation limit (in degrees) This program assumes all necessary kernels and kernel variable definitions are specified in a SPICE meta-kernel. The meta-kernel name is assumed to be 'geomevnt.mk'. Find and display the window of times when the target is above the elevation limit in the observer's topocentric reference frame. 07-MAY-2004 (NJB) 31-OCT-2002 (NJB) */ int main() { /* Prototypes */ void fndevt ( SpiceDouble etbeg, SpiceDouble etend, SpiceDouble step, SpiceBoolean (* statef)(SpiceDouble), SpiceCell * xset ); void makwin ( SpiceDouble etbeg, SpiceDouble etend, SpiceBoolean (* fstate)(SpiceDouble), SpiceCell * evtset, SpiceCell * evtwin ); SpiceBoolean occpt ( ConstSpiceChar * target, ConstSpiceChar * occbdy, SpiceDouble et, ConstSpiceChar * abcorr, ConstSpiceChar * obsrvr ); void setris ( ConstSpiceChar * srfpt, ConstSpiceChar * abcorr, ConstSpiceChar * target, SpiceDouble revlim ); void srfazl ( ConstSpiceChar * srfpt, SpiceDouble et, ConstSpiceChar * abcorr, ConstSpiceChar * targ, SpiceDouble * az, SpiceDouble * el, SpiceDouble * r ); SpiceBoolean stris ( SpiceDouble et ); /* Local constants */ /* The meta-kernel: */ #define META "geomevnt.mk" /* Labels of kernel pool items: */ #define CORLBL "SCVIEW_ABCORR" #define ELVLBL "SCVIEW_ELVLIM" #define OCCLBL "SCVIEW_OCCBDY" #define SRFLBL "SCVIEW_SRFPT" #define STPLBL "SCVIEW_STOP" #define STRLBL "SCVIEW_START" #define TRGLBL "SCVIEW_TARGET" /* STEPSZ is the step size, measured in seconds, used to search for times bracketing a state transition. */ #define STEPSZ (300.0) /* Maximum number of events we can handle in our event set: */ #define MAXEVT 1000 /* Maximum result window size: */ #define MAXWIN ( 2 * MAXEVT ) /* String lengths and other bounds: */ #define CORLEN 11 #define FILSIZ 256 #define LNSIZE 201 #define NAMLEN 33 #define TIMLEN 51 #define TYPLEN 51 /* Local variables */ SpiceBoolean found; SpiceBoolean hidden; SpiceChar abcorr [ CORLEN ]; SpiceChar file [ FILSIZ ]; SpiceChar filtyp [ TYPLEN ]; SpiceChar occbdy [ NAMLEN ]; SpiceChar source [ FILSIZ ]; SpiceChar srfpt [ NAMLEN ]; SpiceChar start [ TIMLEN ]; SpiceChar stop [ TIMLEN ]; SpiceChar target [ NAMLEN ]; SpiceChar timstr [ TIMLEN ]; SpiceChar * tsttim [2]; /* The event set. */ SPICEDOUBLE_CELL ( evtset, MAXEVT ); /* Windows to hold sets of times when - target is occulted - target is above the elevation limit - target is visible */ SPICEDOUBLE_CELL ( riswin, MAXWIN ); SpiceDouble az; SpiceDouble el; SpiceDouble elvlim; SpiceDouble et; SpiceDouble etbeg; SpiceDouble etend; SpiceDouble intbeg; SpiceDouble intend; SpiceDouble r; SpiceDouble revlim; SpiceInt handle; SpiceInt i; SpiceInt n; SpiceInt nker; SpiceInt winsiz; /* Load the meta-kernel. */ furnsh_c ( META ); /* Look up observation location, target, name of the occulting body, aberration correction, start and stop times, and elevation limit. We simplify error checking by using badkpv_c. badkpv_c tests whether a kernel variable having specified attributes is present in the kernel pool. The fourth argument of badkpv_c is the expected dimension; the last indicates the expected data type. Read the header of badkpv_c for details. */ badkpv_c ( "scview", SRFLBL, "=", 1, 1, 'C' ); badkpv_c ( "scview", TRGLBL, "=", 1, 1, 'C' ); badkpv_c ( "scview", OCCLBL, "=", 1, 1, 'C' ); badkpv_c ( "scview", CORLBL, "=", 1, 1, 'C' ); badkpv_c ( "scview", STRLBL, "=", 1, 1, 'C' ); badkpv_c ( "scview", STPLBL, "=", 1, 1, 'C' ); badkpv_c ( "scview", ELVLBL, "=", 1, 1, 'N' ); /* Now we know the kernel variables of interest have been defined; look up the values. We don't need to check the found flag because badkpv_c has ensured the item will be found. */ gcpool_c ( SRFLBL, 0, 1, NAMLEN, &n, srfpt, &found ); gcpool_c ( TRGLBL, 0, 1, NAMLEN, &n, target, &found ); gcpool_c ( OCCLBL, 0, 1, NAMLEN, &n, occbdy, &found ); gcpool_c ( CORLBL, 0, 1, CORLEN, &n, abcorr, &found ); gcpool_c ( STRLBL, 0, 1, TIMLEN, &n, start, &found ); gcpool_c ( STPLBL, 0, 1, TIMLEN, &n, stop, &found ); gdpool_c ( ELVLBL, 0, 1, &n, &elvlim, &found ); revlim = rpd_c() * elvlim; /* Display to standard output a banner for the output report: */ printf ( "\n%s\n\n", "Inputs for geometric event finding program" ); printf ( " Target = %s\n", target ); printf ( " Observation surface location = %s\n", srfpt ); printf ( " Occulting body = %s\n", occbdy ); printf ( " Aberration correction = %s\n", abcorr ); /* Convert the start and stop times to ET. */ str2et_c ( start, &etbeg ); str2et_c ( stop, &etend ); /* Display the start time as both calendar ET and calendar UTC using the formats shown below. 2004 MAY 06 20:15:00.000 (UTC) 2004 MAY 06 20:15:00.000 (TDB) */ timout_c ( etbeg, "YYYY MON DD HR:MN:SC.### (UTC)", TIMLEN, timstr ); printf ( " Start time = %s\n", timstr ); timout_c ( etbeg, "YYYY MON DD HR:MN:SC.### (TDB) ::TDB", TIMLEN, timstr ); printf ( " Start time = %s\n", timstr ); timout_c ( etend, "YYYY MON DD HR:MN:SC.### (UTC)", TIMLEN, timstr ); printf ( " Stop time = %s\n", timstr ); timout_c ( etend, "YYYY MON DD HR:MN:SC.### (TDB) ::TDB", TIMLEN, timstr ); printf ( " Stop time = %s\n", timstr ); /* Display the elevation limit in degrees. */ printf ( " Elevation limit (degrees) = %f\n", elvlim ); /* Display the names of the SPICE kernels we've loaded. */ printf ( "\n" "Loaded SPICE Kernels:\n" ); ktotal_c ( "ALL", &nker ); for ( i = 0; i < nker; i++ ) { kdata_c ( i, "ALL", FILSIZ, TYPLEN, FILSIZ, file, filtyp, source, &handle, &found ); /* Due to the way we've constructed the loop, there's no need to check the 'found' flag. */ printf ( "\n" " Kernel name: %s\n" " Kernel type: %s\n" " Kernel source: %s\n", file, filtyp, source ); } /* Test srfazl: make two calls at times bracketing a spacecraft "rise" event. */ printf ( "\n" "srfazl test results:\n" "\n" ); tsttim[0] = "2004 MAY 01 16:10:26.686 TDB"; tsttim[1] = "2004 MAY 01 16:10:26.688 TDB"; for ( i = 0; i < 2; i++ ) { /* Convert the TDB calendar time to seconds past J2000. Find the azimuth, elevation, and range at this time. */ str2et_c ( tsttim[i], &et ); srfazl ( srfpt, et, abcorr, target, &az, &el, &r ); /* Display the time and outputs from srfazl. Convert radians to degrees for output using the CSPICE function dpr_c(). */ printf ( " ET = %s\n" " Elevation (degrees): %21.16e\n" " Azimuth (degrees): %21.16e\n" " Range (km): %21.16e\n" "\n", tsttim[i], el * dpr_c(), az * dpr_c(), r ); } /* Test occpt: make two calls at times bracketing a spacecraft occultation ingress event. */ printf ( "occpt test results:\n" "\n" ); tsttim[0] = "2004 MAY 01 13:38:36.740 TDB"; tsttim[1] = "2004 MAY 01 13:38:36.742 TDB"; for ( i = 0; i < 2; i++ ) { /* Convert the TDB calendar time to seconds past J2000. */ str2et_c ( tsttim[i], &et ); hidden = occpt ( target, occbdy, et, abcorr, srfpt ); /* Display the time and occultation state. */ if ( hidden ) { printf ( " ET = %s. Occulted.\n", tsttim[i] ); } else { printf ( " ET = %s. Not occulted.\n", tsttim[i] ); } } printf ( "\n" ); /* Set the parameters required by the rise/set state routine. */ setris ( srfpt, abcorr, target, revlim ); /* Locate the epochs where the target passes through elevation zero. The SpiceBoolean function stris determines the "state" of the target: SPICETRUE when the target's elevation is positive, SPICEFALSE otherwise. */ fndevt ( etbeg, etend, STEPSZ, &stris, &evtset ); /* Use the transition set to create a window of time intervals when the target is above the elevation limit at the surface point. */ makwin ( etbeg, etend, &stris, &evtset, &riswin ); /* Display the rise and set times. */ printf ( "Rise and set times of %s as seen from %s:" "\n\n", target, srfpt ); winsiz = card_c ( &riswin ) / 2; for ( i = 0; i < winsiz; i++ ) { /* Fetch the Ith interval from the window. */ wnfetd_c ( &riswin, i, &intbeg, &intend ); /* Convert the transition time to a TDB calendar string. */ timout_c ( intbeg, "YYYY MON DD HR:MN:SC.### (TDB) ::TDB", TIMLEN, timstr ); /* Write the string to standard output. */ if ( i == 0 ) { printf ( "Target rise time (or window start): %s\n", timstr ); } else { printf ( "Target rise time: %s\n", timstr ); } timout_c ( intend, "YYYY MON DD HR:MN:SC.### (TDB) ::TDB", TIMLEN, timstr ); /* Write the string to standard output. */ if ( i == winsiz-1 ) { printf ( "Target set time (or window end): %s\n", timstr ); } else { printf ( "Target set time: %s\n", timstr ); } printf ( "\n" ); } return ( 0 ); }
Numerical results shown for this example may differ across platforms
since the results depend on the SPICE kernels used as input and on the
host platform's arithmetic implementation.
After compiling the program, execute it. The output is:
Inputs for geometric event finding program Target = MEX Observation surface location = DSS-14 Occulting body = MARS Aberration correction = CN+S Start time = 2004 APR 30 23:58:55.814 (UTC) Start time = 2004 MAY 01 00:00:00.000 (TDB) Stop time = 2004 MAY 04 23:58:55.814 (UTC) Stop time = 2004 MAY 05 00:00:00.000 (TDB) Elevation limit (degrees) = 6.000000 Loaded SPICE Kernels: Kernel name: geomevnt.mk Kernel type: META Kernel source: Kernel name: de405s.bsp Kernel type: SPK Kernel source: geomevnt.mk Kernel name: dsnstns.bsp Kernel type: SPK Kernel source: geomevnt.mk Kernel name: DSN_topo.frm Kernel type: TEXT Kernel source: geomevnt.mk Kernel name: earth_031228_231229_predict.bpc Kernel type: PCK Kernel source: geomevnt.mk Kernel name: naif0007.tls Kernel type: TEXT Kernel source: geomevnt.mk Kernel name: ORMM__040501000000_00069.BSP Kernel type: SPK Kernel source: geomevnt.mk Kernel name: pck00007.tpc Kernel type: TEXT Kernel source: geomevnt.mk srfazl test results: ET = 2004 MAY 01 16:10:26.686 TDB Elevation (degrees): 5.9999951213034e+00 Azimuth (degrees): 6.3942106540558e+01 Range (km): 3.2480333721584e+08 ET = 2004 MAY 01 16:10:26.688 TDB Elevation (degrees): 6.0000012274140e+00 Azimuth (degrees): 6.3942111060397e+01 Range (km): 3.2480333724230e+08 occpt test results: ET = 2004 MAY 01 13:38:36.740 TDB. Not occulted. ET = 2004 MAY 01 13:38:36.742 TDB. Occulted. Rise and set times of MEX as seen from DSS-14: Target rise time (or window start): 2004 MAY 01 00:00:00.000 (TDB) Target set time: 2004 MAY 01 05:36:08.338 (TDB) Target rise time: 2004 MAY 01 16:10:26.687 (TDB) Target set time: 2004 MAY 02 05:35:03.020 (TDB) Target rise time: 2004 MAY 02 16:09:14.024 (TDB) Target set time: 2004 MAY 03 05:33:57.180 (TDB) Target rise time: 2004 MAY 03 16:08:02.224 (TDB) Target set time: 2004 MAY 04 05:32:50.686 (TDB) Target rise time: 2004 MAY 04 16:06:51.203 (TDB) Target set time (or window end): 2004 MAY 05 00:00:00.000 (TDB)
Extend the program of the previous chapter to find times when the
target object is:
Display each of the intervals in the result window as a pair of start and stop times. Express each time as a TDB calendar date using the same format as in the previous program.
The student gains further experience with the CSPICE cell, set and
window functions, and with root finding techniques.
A possible solution would consist of the following steps:
fndevt ( etbeg, etend, stepsz, &stocp, &evtset );
makwin ( etbeg, etend, &stocp, &evtset, &occwin );
#include <stdio.h> #include <math.h> #include "SpiceUsr.h" /* PROGRAM SCVIEW Find the view periods for a point target as seen from a specified surface location. Exclude periods when target is occulted by extended bodies other than the one associated with the viewing location. Display the windows of visibility. The following items are loaded from a SPICE text kernel: - Observer (surface point) name - Target name - Occulting body name - Aberration correction specification - Start time string - Stop time #include <string.h> - Elevation limit (in degrees) This program assumes all necessary kernels and kernel variable definitions are specified in a SPICE meta-kernel. The meta-kernel name is assumed to be 'geomevnt.mk'. Find and display the window of times when the target is occulted as seen from the observer's location. Find and display the window of times when the target is above the elevation limit and not occulted. 07-MAY-2004 (NJB) 31-OCT-2002 (NJB) */ int main() { /* Prototypes */ void fndevt ( SpiceDouble etbeg, SpiceDouble etend, SpiceDouble step, SpiceBoolean (* statef)(SpiceDouble), SpiceCell * xset ); void makwin ( SpiceDouble etbeg, SpiceDouble etend, SpiceBoolean (* fstate)(SpiceDouble), SpiceCell * evtset, SpiceCell * evtwin ); SpiceBoolean occpt ( ConstSpiceChar * target, ConstSpiceChar * occbdy, SpiceDouble et, ConstSpiceChar * abcorr, ConstSpiceChar * obsrvr ); void setocp ( ConstSpiceChar * target, ConstSpiceChar * occbdy, ConstSpiceChar * abcorr, ConstSpiceChar * obsrvr ); void setris ( ConstSpiceChar * srfpt, ConstSpiceChar * abcorr, ConstSpiceChar * target, SpiceDouble revlim ); void srfazl ( ConstSpiceChar * srfpt, SpiceDouble et, ConstSpiceChar * abcorr, ConstSpiceChar * targ, SpiceDouble * az, SpiceDouble * el, SpiceDouble * r ); SpiceBoolean stocp ( SpiceDouble et ); SpiceBoolean stris ( SpiceDouble et ); /* Local constants */ /* The meta-kernel: */ #define META "geomevnt.mk" /* Labels of kernel pool items: */ #define CORLBL "SCVIEW_ABCORR" #define ELVLBL "SCVIEW_ELVLIM" #define OCCLBL "SCVIEW_OCCBDY" #define SRFLBL "SCVIEW_SRFPT" #define STPLBL "SCVIEW_STOP" #define STRLBL "SCVIEW_START" #define TRGLBL "SCVIEW_TARGET" /* STEPSZ is the step size, measured in seconds, used to search for times bracketing a state transition. */ #define STEPSZ (300.0) /* Maximum number of events we can handle in our event set: */ #define MAXEVT 1000 /* Maximum result window size: */ #define MAXWIN ( 2 * MAXEVT ) /* String lengths and other bounds: */ #define CORLEN 11 #define FILSIZ 256 #define LNSIZE 201 #define NAMLEN 33 #define TIMLEN 51 #define TYPLEN 51 /* Local variables */ SpiceBoolean found; SpiceBoolean hidden; SpiceChar abcorr [ CORLEN ]; SpiceChar file [ FILSIZ ]; SpiceChar filtyp [ TYPLEN ]; SpiceChar occbdy [ NAMLEN ]; SpiceChar source [ FILSIZ ]; SpiceChar srfpt [ NAMLEN ]; SpiceChar start [ TIMLEN ]; SpiceChar stop [ TIMLEN ]; SpiceChar target [ NAMLEN ]; SpiceChar timstr [ TIMLEN ]; SpiceChar * tsttim [2]; /* The event set. */ SPICEDOUBLE_CELL ( evtset, MAXEVT ); /* Windows to hold sets of times when - target is occulted - target is above the elevation limit - target is visible */ SPICEDOUBLE_CELL ( occwin, MAXWIN ); SPICEDOUBLE_CELL ( riswin, MAXWIN ); SPICEDOUBLE_CELL ( viswin, MAXWIN ); SpiceDouble az; SpiceDouble el; SpiceDouble elvlim; SpiceDouble et; SpiceDouble etbeg; SpiceDouble etend; SpiceDouble intbeg; SpiceDouble intend; SpiceDouble r; SpiceDouble revlim; SpiceInt handle; SpiceInt i; SpiceInt n; SpiceInt nker; SpiceInt winsiz; /* Load the meta-kernel. */ furnsh_c ( META ); /* Look up observation location, target, name of the occulting body, aberration correction, start and stop times, and elevation limit. We simplify error checking by using badkpv_c. badkpv_c tests whether a kernel variable having specified attributes is present in the kernel pool. The fourth argument of badkpv_c is the expected dimension; the last indicates the expected data type. Read the header of badkpv_c for details. */ badkpv_c ( "scview", SRFLBL, "=", 1, 1, 'C' ); badkpv_c ( "scview", TRGLBL, "=", 1, 1, 'C' ); badkpv_c ( "scview", OCCLBL, "=", 1, 1, 'C' ); badkpv_c ( "scview", CORLBL, "=", 1, 1, 'C' ); badkpv_c ( "scview", STRLBL, "=", 1, 1, 'C' ); badkpv_c ( "scview", STPLBL, "=", 1, 1, 'C' ); badkpv_c ( "scview", ELVLBL, "=", 1, 1, 'N' ); /* Now we know the kernel variables of interest have been defined; look up the values. We don't need to check the found flag because badkpv_c has ensured the item will be found. */ gcpool_c ( SRFLBL, 0, 1, NAMLEN, &n, srfpt, &found ); gcpool_c ( TRGLBL, 0, 1, NAMLEN, &n, target, &found ); gcpool_c ( OCCLBL, 0, 1, NAMLEN, &n, occbdy, &found ); gcpool_c ( CORLBL, 0, 1, CORLEN, &n, abcorr, &found ); gcpool_c ( STRLBL, 0, 1, TIMLEN, &n, start, &found ); gcpool_c ( STPLBL, 0, 1, TIMLEN, &n, stop, &found ); gdpool_c ( ELVLBL, 0, 1, &n, &elvlim, &found ); revlim = rpd_c() * elvlim; /* Display to standard output a banner for the output report: */ printf ( "\n%s\n\n", "Inputs for geometric event finding program" ); printf ( " Target = %s\n", target ); printf ( " Observation surface location = %s\n", srfpt ); printf ( " Occulting body = %s\n", occbdy ); printf ( " Aberration correction = %s\n", abcorr ); /* Convert the start and stop times to ET. */ str2et_c ( start, &etbeg ); str2et_c ( stop, &etend ); /* Display the start time as both calendar ET and calendar UTC using the formats shown below. 2004 MAY 06 20:15:00.000 (UTC) 2004 MAY 06 20:15:00.000 (TDB) */ timout_c ( etbeg, "YYYY MON DD HR:MN:SC.### (UTC)", TIMLEN, timstr ); printf ( " Start time = %s\n", timstr ); timout_c ( etbeg, "YYYY MON DD HR:MN:SC.### (TDB) ::TDB", TIMLEN, timstr ); printf ( " Start time = %s\n", timstr ); timout_c ( etend, "YYYY MON DD HR:MN:SC.### (UTC)", TIMLEN, timstr ); printf ( " Stop time = %s\n", timstr ); timout_c ( etend, "YYYY MON DD HR:MN:SC.### (TDB) ::TDB", TIMLEN, timstr ); printf ( " Stop time = %s\n", timstr ); /* Display the elevation limit in degrees. */ printf ( " Elevation limit (degrees) = %f\n", elvlim ); /* Display the names of the SPICE kernels we've loaded. */ printf ( "\n" "Loaded SPICE Kernels:\n" ); ktotal_c ( "ALL", &nker ); for ( i = 0; i < nker; i++ ) { kdata_c ( i, "ALL", FILSIZ, TYPLEN, FILSIZ, file, filtyp, source, &handle, &found ); /* Due to the way we've constructed the loop, there's no need to check the 'found' flag. */ printf ( "\n" " Kernel name: %s\n" " Kernel type: %s\n" " Kernel source: %s\n", file, filtyp, source ); } /* Test srfazl: make two calls at times bracketing a spacecraft "rise" event. */ printf ( "\n" "srfazl test results:\n" "\n" ); tsttim[0] = "2004 MAY 01 16:10:26.686 TDB"; tsttim[1] = "2004 MAY 01 16:10:26.688 TDB"; for ( i = 0; i < 2; i++ ) { /* Convert the TDB calendar time to seconds past J2000. Find the azimuth, elevation, and range at this time. */ str2et_c ( tsttim[i], &et ); srfazl ( srfpt, et, abcorr, target, &az, &el, &r ); /* Display the time and outputs from srfazl. Convert radians to degrees for output using the CSPICE function dpr_c(). */ printf ( " ET = %s\n" " Elevation (degrees): %21.16e\n" " Azimuth (degrees): %21.16e\n" " Range (km): %21.16e\n" "\n", tsttim[i], el * dpr_c(), az * dpr_c(), r ); } /* Test occpt: make two calls at times bracketing a spacecraft occultation ingress event. */ printf ( "occpt test results:\n" "\n" ); tsttim[0] = "2004 MAY 01 13:38:36.740 TDB"; tsttim[1] = "2004 MAY 01 13:38:36.742 TDB"; for ( i = 0; i < 2; i++ ) { /* Convert the TDB calendar time to seconds past J2000. */ str2et_c ( tsttim[i], &et ); hidden = occpt ( target, occbdy, et, abcorr, srfpt ); /* Display the time and occultation state. */ if ( hidden ) { printf ( " ET = %s. Occulted.\n", tsttim[i] ); } else { printf ( " ET = %s. Not occulted.\n", tsttim[i] ); } } printf ( "\n" ); /* Set the parameters required by the rise/set state routine. */ setris ( srfpt, abcorr, target, revlim ); /* Locate the epochs where the target passes through elevation zero. The SpiceBoolean function stris determines the "state" of the target: SPICETRUE when the target's elevation is positive, SPICEFALSE otherwise. */ fndevt ( etbeg, etend, STEPSZ, &stris, &evtset ); /* Use the transition set to create a window of time intervals when the target is above the elevation limit at the surface point. */ makwin ( etbeg, etend, &stris, &evtset, &riswin ); /* Display the rise and set times. */ printf ( "\n\n" "Rise and set times of %s as seen from %s:" "\n\n", target, srfpt ); winsiz = card_c ( &riswin ) / 2; for ( i = 0; i < winsiz; i++ ) { /* Fetch the Ith interval from the window. */ wnfetd_c ( &riswin, i, &intbeg, &intend ); /* Convert the transition time to a TDB calendar string. */ timout_c ( intbeg, "YYYY MON DD HR:MN:SC.### (TDB) ::TDB", TIMLEN, timstr ); /* Write the string to standard output. */ if ( i == 0 ) { printf ( "Target rise time (or window start): %s\n", timstr ); } else { printf ( "Target rise time: %s\n", timstr ); } timout_c ( intend, "YYYY MON DD HR:MN:SC.### (TDB) ::TDB", TIMLEN, timstr ); /* Write the string to standard output. */ if ( i == winsiz-1 ) { printf ( "Target set time (or window end): %s\n", timstr ); } else { printf ( "Target set time: %s\n", timstr ); } printf ( "\n" ); } /* Now find the window of times when the target is occulted by the designated blocking body. Initialize the occultation finding utilities. */ setocp ( target, occbdy, abcorr, srfpt ); /* Locate the epochs where the target passes into or out of occultation by the occulting body. These epochs will be returned as a CSPICE set. */ fndevt ( etbeg, etend, STEPSZ, &stocp, &evtset ); /* Make the set into a window of times when the target is occulted. */ makwin ( etbeg, etend, &stocp, &evtset, &occwin ); /* Display the set of times when the target is occulted. */ printf ( "\n\n" "%s occultation of %s ---\n" "Ingress and egress times as seen from %s:\n\n", occbdy, target, srfpt ); winsiz = card_c ( &occwin ) / 2; for ( i = 0; i < winsiz; i++ ) { wnfetd_c ( &occwin, i, &intbeg, &intend ); /* Convert the transition times to TDB calendar strings. */ timout_c ( intbeg, "YYYY MON DD HR:MN:SC.### (TDB) ::TDB", TIMLEN, timstr ); /* Write the string to standard output. */ if ( i == 0 ) { printf ( "Occ. ingress time (or window start): %s\n", timstr ); } else { printf ( "Occultation ingress time: %s\n", timstr ); } timout_c ( intend, "YYYY MON DD HR:MN:SC.### (TDB) ::TDB", TIMLEN, timstr ); /* Write the string to standard output. */ if ( i == winsiz-1 ) { printf ( "Occ. egress time (or window end): %s\n", timstr ); } else { printf ( "Occultation egress time: %s\n", timstr ); } printf ( "\n" ); } /* Find the visibility window by subtracting the occultation window from the rise-set window. Display the result. */ wndifd_c ( &riswin, &occwin, &viswin ); /* Display the set of times when the target is visible. */ printf ( "\n\n" "%s visibility start and stop times " "as seen from %s:\n\n", target, srfpt ); winsiz = card_c ( &viswin ) / 2; for ( i = 0; i < winsiz; i++ ) { wnfetd_c ( &viswin, i, &intbeg, &intend ); /* Convert the transition times to TDB calendar strings. */ timout_c ( intbeg, "YYYY MON DD HR:MN:SC.### (TDB) ::TDB", TIMLEN, timstr ); /* Write the string to standard output. */ if ( i == 0 ) { printf ( "Vis. start time (or window start): %s\n", timstr ); } else { printf ( "Visibility start time: %s\n", timstr ); } timout_c ( intend, "YYYY MON DD HR:MN:SC.### (TDB) ::TDB", TIMLEN, timstr ); /* Write the string to standard output. */ if ( i == winsiz-1 ) { printf ( "Vis. end time (or window end): %s\n", timstr ); } else { printf ( "Visibility end time: %s\n", timstr ); } timout_c ( intend, "YYYY MON DD HR:MN:SC.### (TDB) ::TDB", TIMLEN, timstr ); printf ( "\n" ); } return ( 0 ); }
Numerical results shown for this example may differ across platforms
since the results depend on the SPICE kernels used as input and on the
host platform's arithmetic implementation.
After compiling the program, execute it. The output is:
Inputs for geometric event finding program Target = MEX Observation surface location = DSS-14 Occulting body = MARS Aberration correction = CN+S Start time = 2004 APR 30 23:58:55.814 (UTC) Start time = 2004 MAY 01 00:00:00.000 (TDB) Stop time = 2004 MAY 04 23:58:55.814 (UTC) Stop time = 2004 MAY 05 00:00:00.000 (TDB) Elevation limit (degrees) = 6.000000 Loaded SPICE Kernels: Kernel name: geomevnt.mk Kernel type: META Kernel source: Kernel name: de405s.bsp Kernel type: SPK Kernel source: geomevnt.mk Kernel name: dsnstns.bsp Kernel type: SPK Kernel source: geomevnt.mk Kernel name: DSN_topo.frm Kernel type: TEXT Kernel source: geomevnt.mk Kernel name: earth_031228_231229_predict.bpc Kernel type: PCK Kernel source: geomevnt.mk Kernel name: naif0007.tls Kernel type: TEXT Kernel source: geomevnt.mk Kernel name: ORMM__040501000000_00069.BSP Kernel type: SPK Kernel source: geomevnt.mk Kernel name: pck00007.tpc Kernel type: TEXT Kernel source: geomevnt.mk srfazl test results: ET = 2004 MAY 01 16:10:26.686 TDB Elevation (degrees): 5.9999951213034e+00 Azimuth (degrees): 6.3942106540558e+01 Range (km): 3.2480333721584e+08 ET = 2004 MAY 01 16:10:26.688 TDB Elevation (degrees): 6.0000012274140e+00 Azimuth (degrees): 6.3942111060397e+01 Range (km): 3.2480333724230e+08 occpt test results: ET = 2004 MAY 01 13:38:36.740 TDB. Not occulted. ET = 2004 MAY 01 13:38:36.742 TDB. Occulted. Rise and set times of MEX as seen from DSS-14: Target rise time (or window start): 2004 MAY 01 00:00:00.000 (TDB) Target set time: 2004 MAY 01 05:36:08.338 (TDB) Target rise time: 2004 MAY 01 16:10:26.687 (TDB) Target set time: 2004 MAY 02 05:35:03.020 (TDB) Target rise time: 2004 MAY 02 16:09:14.024 (TDB) Target set time: 2004 MAY 03 05:33:57.180 (TDB) Target rise time: 2004 MAY 03 16:08:02.224 (TDB) Target set time: 2004 MAY 04 05:32:50.686 (TDB) Target rise time: 2004 MAY 04 16:06:51.203 (TDB) Target set time (or window end): 2004 MAY 05 00:00:00.000 (TDB) MARS occultation of MEX --- Ingress and egress times as seen from DSS-14: Occ. ingress time (or window start): 2004 MAY 01 06:03:15.313 (TDB) Occultation egress time: 2004 MAY 01 07:05:45.105 (TDB) Occultation ingress time: 2004 MAY 01 13:38:36.741 (TDB) Occultation egress time: 2004 MAY 01 14:40:51.279 (TDB) Occultation ingress time: 2004 MAY 01 21:14:05.206 (TDB) Occultation egress time: 2004 MAY 01 22:16:04.347 (TDB) Occultation ingress time: 2004 MAY 02 04:49:26.607 (TDB) Occultation egress time: 2004 MAY 02 05:51:12.175 (TDB) Occultation ingress time: 2004 MAY 02 12:24:51.007 (TDB) Occultation egress time: 2004 MAY 02 13:26:20.244 (TDB) Occultation ingress time: 2004 MAY 02 20:00:17.624 (TDB) Occultation egress time: 2004 MAY 02 21:01:31.988 (TDB) Occultation ingress time: 2004 MAY 03 03:35:37.097 (TDB) Occultation egress time: 2004 MAY 03 04:36:36.001 (TDB) Occultation ingress time: 2004 MAY 03 11:11:00.963 (TDB) Occultation egress time: 2004 MAY 03 12:11:43.066 (TDB) Occultation ingress time: 2004 MAY 03 18:46:20.320 (TDB) Occultation egress time: 2004 MAY 03 19:46:47.607 (TDB) Occultation ingress time: 2004 MAY 04 02:21:38.679 (TDB) Occultation egress time: 2004 MAY 04 03:21:49.169 (TDB) Occultation ingress time: 2004 MAY 04 09:57:02.737 (TDB) Occultation egress time: 2004 MAY 04 10:56:56.827 (TDB) Occultation ingress time: 2004 MAY 04 17:32:19.374 (TDB) Occ. egress time (or window end): 2004 MAY 04 18:31:58.252 (TDB) MEX visibility start and stop times as seen from DSS-14: Vis. start time (or window start): 2004 MAY 01 00:00:00.000 (TDB) Visibility end time: 2004 MAY 01 05:36:08.338 (TDB) Visibility start time: 2004 MAY 01 16:10:26.687 (TDB) Visibility end time: 2004 MAY 01 21:14:05.206 (TDB) Visibility start time: 2004 MAY 01 22:16:04.347 (TDB) Visibility end time: 2004 MAY 02 04:49:26.607 (TDB) Visibility start time: 2004 MAY 02 16:09:14.024 (TDB) Visibility end time: 2004 MAY 02 20:00:17.624 (TDB) Visibility start time: 2004 MAY 02 21:01:31.988 (TDB) Visibility end time: 2004 MAY 03 03:35:37.097 (TDB) Visibility start time: 2004 MAY 03 04:36:36.001 (TDB) Visibility end time: 2004 MAY 03 05:33:57.180 (TDB) Visibility start time: 2004 MAY 03 16:08:02.224 (TDB) Visibility end time: 2004 MAY 03 18:46:20.320 (TDB) Visibility start time: 2004 MAY 03 19:46:47.607 (TDB) Visibility end time: 2004 MAY 04 02:21:38.679 (TDB) Visibility start time: 2004 MAY 04 03:21:49.169 (TDB) Visibility end time: 2004 MAY 04 05:32:50.686 (TDB) Visibility start time: 2004 MAY 04 16:06:51.203 (TDB) Visibility end time: 2004 MAY 04 17:32:19.374 (TDB) Visibility start time: 2004 MAY 04 18:31:58.252 (TDB) Vis. end time (or window end): 2004 MAY 05 00:00:00.000 (TDB)
#include "SpiceUsr.h" #include "SpiceZmc.h" /* Routines for rise-set state function computation. */ /* Constants */ #define NAMLEN 33 #define CORLEN 11 /* File scope variables: */ static SpiceChar svcorr [CORLEN]; static SpiceChar svsfpt [NAMLEN]; static SpiceChar svtarg [NAMLEN]; static SpiceDouble svlim; /* Save function arguments to be used while searching. */ void setris ( ConstSpiceChar * srfpt, ConstSpiceChar * abcorr, ConstSpiceChar * target, SpiceDouble revlim ) { strncpy ( svcorr, abcorr, CORLEN ); strncpy ( svsfpt, srfpt, NAMLEN ); strncpy ( svtarg, target, NAMLEN ); /* Insert null terminators for safety. */ svcorr[CORLEN-1] = NULLCHAR; svsfpt[NAMLEN-1] = NULLCHAR; svtarg[NAMLEN-1] = NULLCHAR; svlim = revlim; } /* Logical function to indicate "state" of target: the state is SPICETRUE when the target has a positive elevation in the topocentric frame at the saved surface point; otherwise the state is SPICEFALSE. */ SpiceBoolean stris ( SpiceDouble et ) { /* Prototypes */ void srfazl ( ConstSpiceChar * srfpt, SpiceDouble et, ConstSpiceChar * abcorr, ConstSpiceChar * targ, SpiceDouble * az, SpiceDouble * el, SpiceDouble * r ); /* Local variables */ SpiceDouble az; SpiceDouble el; SpiceDouble r; /* Find the azimuth and elevation of the saved target at et; indicate whether the elevation is above the elevation limit. */ srfazl ( svsfpt, et, svcorr, svtarg, &az, &el, &r ); return ( (SpiceBoolean)( el > svlim ) ); }
#include "SpiceUsr.h" #include "SpiceZmc.h" /* Routines for point target occultation state function computation. */ /* Constants */ #define NAMLEN 33 #define CORLEN 11 /* File scope variables: */ static SpiceChar svcorr [CORLEN]; static SpiceChar svobsv [NAMLEN]; static SpiceChar svocbd [NAMLEN]; static SpiceChar svtarg [NAMLEN]; /* Save function arguments to be used while searching. */ void setocp ( ConstSpiceChar * target, ConstSpiceChar * occbdy, ConstSpiceChar * abcorr, ConstSpiceChar * obsrvr ) { strncpy ( svcorr, abcorr, CORLEN ); strncpy ( svocbd, occbdy, NAMLEN ); strncpy ( svtarg, target, NAMLEN ); strncpy ( svobsv, obsrvr, NAMLEN ); svcorr[CORLEN-1] = NULLCHAR; svocbd[NAMLEN-1] = NULLCHAR; svtarg[NAMLEN-1] = NULLCHAR; svobsv[NAMLEN-1] = NULLCHAR; } /* Logical function to indicate "state" of target: the state is SPICETRUE when the target has a positive elevation in the topocentric frame at the saved surface point; otherwise the state is SPICEFALSE. */ SpiceBoolean stocp ( SpiceDouble et ) { /* Prototypes */ SpiceBoolean occpt ( ConstSpiceChar * target, ConstSpiceChar * occbdy, SpiceDouble et, ConstSpiceChar * abcorr, ConstSpiceChar * obsrvr ); return ( occpt( svtarg, svocbd, et, svcorr, svobsv ) ); }
#include "SpiceUsr.h" void fndevt ( SpiceDouble etbeg, SpiceDouble etend, SpiceDouble step, SpiceBoolean (* statef) ( SpiceDouble ), SpiceCell * xset ) /* Find locations of state changes for a boolean function. 31-OCT-2002 (NJB) */ { /* Local constants */ #define CNVLIM (1.0e-6) #define MAXITR 100 /* Local variables */ SpiceBoolean lstate; SpiceBoolean mstate; SpiceBoolean ustate; SpiceDouble delta; SpiceDouble lower; SpiceDouble lpt; SpiceDouble midpt; SpiceDouble upper; SpiceDouble upt; SpiceInt nitr; if ( return_c() ) { return; } chkin_c ( "fndevt" ); /* Set the cardinality of the input cell to zero. */ scard_c ( 0, xset ); /* If the input interval is empty, we're done. */ if ( etend <= etbeg ) { chkout_c ( "fndevt" ); return; } /* The step size must be at least as large as the convergence limit. */ if ( step <= CNVLIM ) { setmsg_c ( "STEP must be > the convergence limit #; " "actual value was #." ); errdp_c ( "#", CNVLIM ); errdp_c ( "#", step ); sigerr_c ( "SPICE(INVALIDVALUE)" ); chkout_c ( "fndevt" ); return; } /* Obtain the initial state; save this as the "lower" state. */ lstate = (*statef) ( etbeg ); /* Step along the input interval, looking for state changes. */ lpt = etbeg; upt = brcktd_c ( etbeg + step, etbeg, etend ); while ( lpt < etend ) { /* Find the state at the epoch upt. First, check that upt is actually greater than lpt. */ if ( upt <= lpt ) { /* We're not getting anywhere; the step is too small. */ setmsg_c ( "Upper bracketing epoch UPT = #; " "lower epoch LPT = #. This condition " "arises when the step size is too small." ); errdp_c ( "#", lpt ); errdp_c ( "#", upt ); sigerr_c ( "SPICE(STEPTOOSMALL)" ); chkout_c ( "fndevt" ); return; } /* Find the state at the upper bound of our step interval. */ ustate = (*statef)( upt ); if ( ustate != lstate ) { /* There's a state change between the right endpoint upt and the left endpoint lpt. Do a binary search to locate the epoch at which the state changes. Note: uniqueness of the root is not guaranteed; it's up to the caller to choose step small enough to ensure that only one root can occur in a time interval of length step. */ lower = brcktd_c ( lpt, etbeg, etend ); upper = brcktd_c ( upt, etbeg, etend ); midpt = ( lower + upper ) / 2; mstate = (*statef) ( midpt ); nitr = 0; delta = upper - lower; while ( ( delta > CNVLIM ) && ( nitr <= MAXITR ) ) { /* Adjust our search interval so the length is reduced by a factor of two and so that the location of the state change remains between lower and upper. */ if ( mstate == ustate ) { /* The state is the same at the midpoint and the upper bound, so a state change must occur between the lower bound and the midpoint. Make the midpoint the new upper bound. */ upper = midpt; } else { /* There is a state change between the midpoint and the upper bound; the state at the midpoint matches the state at the lower bound. Make the midpoint the new lower bound. */ lower = midpt; } midpt = ( lower + upper ) / 2; mstate = (*statef) ( midpt ); delta = upper - lower; nitr++; /* At this point, the state at lower matches the state at lpt (lstate), and the state at upper matches the state at upt (ustate). */ } /* If we dropped out of the loop because we hit the iteration limit, we have a problem. */ if ( delta > CNVLIM ) { setmsg_c ( "Binary search failed to converge. " "ETBEG = #, LOWER = #, MIDPT = #, " "UPPER = #, ETEND = #" ); errdp_c ( "#", etbeg ); errdp_c ( "#", lower ); errdp_c ( "#", midpt ); errdp_c ( "#", upper ); errdp_c ( "#", etend ); sigerr_c ( "SPICE(NOCONVERGENCE)" ); chkout_c ( "fndevt" ); return; } /* The epoch of the state transition has been determined to within CNVLIM. We'll use upper as the epoch of the transition. This ensures that the state at the transition epoch is ustate. */ appndd_c ( upper, xset ); /* upper becomes the left endpoint of the next interval. The state at the right interval endpoint upt becomes the state at the left endpoint of the next interval. Calculate upt at the next step. We look up ustate at the top of the loop. */ lpt = upper; lstate = ustate; upt = brcktd_c ( lpt + step, etbeg, etend ); } else { /* No state change was found on this step. upt becomes the lower bound of the next search interval. lstate remains unchanged. We look up ustate at the top of the loop. */ lpt = upt; upt = brcktd_c ( lpt + step, etbeg, etend ); } } /* The left endpoint equals the right endpoint of our search interval, so there are no more state changes to be found. */ chkout_c ( "fndevt" ); }
#include "SpiceUsr.h" void makwin ( SpiceDouble etbeg, SpiceDouble etend, SpiceBoolean (* fstate)( SpiceDouble ), SpiceCell * evtset, SpiceCell * evtwin ) /* Utility program for creating a window representing time intervals when a specified binary state function returns SPICETRUE. Subroutine arguments: etbeg is the start time of a time interval on which the binary state function fstate is defined. etend is the end time corresponding to etbeg. fstate is a binary state function of ET that returns a value of type SpiceBoolean. evtset is a CSPICE set containing epochs of state transitions. The members of evtset must lie in the interval [etbeg, etend] evtwin is a CSPICE window constructed by this routine. evtwin contains subintervals of the interval [etbeg, etend] on which fstate(et) is SPICETRUE. evtwin must be intialized by the caller of this routine. */ { /* Local variables */ SpiceInt card; SpiceInt i; chkin_c ( "makwin" ); /* Empty the output window. */ scard_c ( 0, evtwin ); /* Get a local copy of the cardinality of the event set. */ card = card_c ( evtset ); /* If fstate is SPICETRUE at etbeg, then the first state transition is at the right endpoint of the first window interval, and every subsequent even-numbered transition marks the start of a window interval. Otherwise, every odd-numbered transition marks the start of a window interval. */ if ( (*fstate)(etbeg) ) { /* The first window interval starts at etbeg. */ if ( card == 0 ) { /* The function is SPICETRUE the whole time. The window consists of the single interval [etbeg, etend] */ wninsd_c ( etbeg, etend, evtwin ); } else { /* Insert the first interval into the window. */ wninsd_c( etbeg, SPICE_CELL_ELEM_D(evtset,0), evtwin ); /* Insert into our window any remaining intervals bounded by transitions. */ i = 1; while ( i+1 < card ) { wninsd_c ( SPICE_CELL_ELEM_D( evtset, i ), SPICE_CELL_ELEM_D( evtset, i+1 ), evtwin ); i += 2; } if ( i == card-1 ) { /* The last interval begins at the [card-1] element of evtset and ends at etend. */ wninsd_c ( SPICE_CELL_ELEM_D(evtset, card-1), etend, evtwin ); } } /* We've handled the case where fstate is SPICETRUE at etbeg. */ } else { /* The first interval starts at element [0] of evtset. */ i = 0; while ( i+1 < card ) { wninsd_c ( SPICE_CELL_ELEM_D( evtset, i ), SPICE_CELL_ELEM_D( evtset, i+1 ), evtwin ); i += 2; } if ( i == card-1 ) { /* The last interval begins at the [card-1] element of evtset and ends at etend. */ wninsd_c ( SPICE_CELL_ELEM_D(evtset, card-1), etend, evtwin ); } /* We've handled the case where fstate is SPICEFALSE at etbeg. */ } /* evtwin is ready for use. */ chkout_c ( "makwin" ); }