March 14, 2006
Updated kernels. Reduced precision of output formats for compatibility with Fortran version of lessons.
This lesson illustrates how the CSPICE Toolkit can be used to find time
intervals when specified geometric conditions are satisfied.
In this lesson the student is asked to construct a program that finds the time intervals, within a specified time range, when a point target is visible from a specified surface point on an extended body. Possible occultation of the target by a specified second body is to be considered. To simplify the problem, the solution program should assume the location of the surface point is given by an SPK file. It should also assume that a topocentric frame centered at the surface point is defined by a frame kernel.
The lesson introduces the student to variety of CSPICE capabilities which are useful not only for solving the problem at hand, but for solving many other geometric problems. Student activities include, but are not limited to:
2004 MAY 2 TDB 2004 MAY 6 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, and by loading appropriate, alternative SPK and frame kernels.
This lesson breaks down the task of writing the solution program into a series of programming exercises. The exercise topics are:
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 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 frames Program IDL Icy programming exampleThese tutorials are available in printed form and as MS Office or PDF files from the NAIF server at JPL:
http://naif.jpl.nasa.gov/naif/tutorials.html
The Required Reading documents are provided with the Toolkit and are
located under the ``cspice/doc'' directory in the C installation tree.
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 type
Another useful document distributed with the Toolkit is the permuted
index. This is located under the ``cspice/doc'' directory in the C
installation tree. This text document provides a simple mechanism to
discover what CSPICE functions perform a particular function of interest
as well as the name of the source file that contains the function.
The most detailed specification of a given CSPICE function is contained
in the header section of its source code. The source code is distributed
with the Toolkit and is located under
``cspice/src/cspice'' in the C versions. For example the header of str2et_c is contained in the file:
cspice/src/cspice/str2et_c.c
The following kernels are used in examples provided in this lesson:
File Name Type Description ----------------------- ---- -------------------------- de405xs.bsp SPK Planetary Ephemeris SPK, subsetted to cover only time range of interest earthstns_itrf93_050714.bsp SPK DSN station SPK earth_topo_050714.tf FK DSN station frame definitions earth_000101_060525_060303.bpc PCK Binary PCK for Earth ORMM__040501000000_00076XS.BSP SPK MEX Orbiter Trajectory SPK, subsetted to cover only time range of interest naif0008.tls LSK Generic LSK pck00008.tpc PCK Generic PCKThese SPICE kernels are available from the NAIF server at JPL:
ftp://naif.jpl.nasa.gov/pub/naif/toolkit_docs/Lessons/
This section provides a complete summary of the functions, and the
kernels that are suggested for usage in each of the exercises in this
tutorial. (You may wish to not look at this list unless/until you ``get
stuck'' while working on your own.)
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 source code for these utility routines is included at the end of this document.
The 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 function 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 file 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 function 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 file 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 input parameters (such as the target name) 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:
KPL/MK Example meta-kernel for geometric event finding hands-on coding lesson. Version 2.0.0 08-MAR-2006 (NJB) Identify names of kernels to load: \begindata KERNELS_TO_LOAD = ( 'kernels/spk/de405xs.bsp' 'kernels/spk/earthstns_itrf93_050714.bsp' 'kernels/fk/earth_topo_050714.tf' 'kernels/pck/earth_000101_060525_060303.bpc' 'kernels/lsk/naif0008.tls' 'kernels/spk/ORMM__040501000000_00076XS.BSP' 'kernels/pck/pck00008.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 2 TDB' SCVIEW_STOP = '2004 MAY 6 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'. 08-MAR-2006 (NJB) 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 MAY 01 23:58:55.814 (UTC) Start time = 2004 MAY 02 00:00:00.000 (TDB) Stop time = 2004 MAY 05 23:58:55.814 (UTC) Stop time = 2004 MAY 06 00:00:00.000 (TDB) Elevation limit (degrees) = 6.000000 Loaded SPICE Kernels: Kernel name: geomevnt.mk Kernel type: META Kernel source: Kernel name: kernels/spk/de405xs.bsp Kernel type: SPK Kernel source: geomevnt.mk Kernel name: kernels/spk/earthstns_itrf93_050714.bsp Kernel type: SPK Kernel source: geomevnt.mk Kernel name: kernels/fk/earth_topo_050714.tf Kernel type: TEXT Kernel source: geomevnt.mk Kernel name: kernels/pck/earth_000101_060525_060303.bpc Kernel type: PCK Kernel source: geomevnt.mk Kernel name: kernels/lsk/naif0008.tls Kernel type: TEXT Kernel source: geomevnt.mk Kernel name: kernels/spk/ORMM__040501000000_00076XS.BSP Kernel type: SPK Kernel source: geomevnt.mk Kernel name: kernels/pck/pck00008.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. This is a double precision value. 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 02 16:09:14.077 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 02 16:09:14.079 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 2.0.0 08-MAR-2006 (NJB) Added code to map azimuth to range [0, 2*pi). 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; /* Map azimuth into the range 0 : 2*pi if necessary. */ if ( *az < 0. ) { *az += twopi_c(); } 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'. 08-MAR-2006 (NJB) 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 02 16:09:14.077 TDB"; tsttim[1] = "2004 MAY 02 16:09:14.079 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.13e\n" " Azimuth (degrees): %21.13e\n" " Range (km): %21.13e\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 Occulting body = MARS Aberration correction = CN+S Start time = 2004 MAY 01 23:58:55.814 (UTC) Start time = 2004 MAY 02 00:00:00.000 (TDB) Stop time = 2004 MAY 05 23:58:55.814 (UTC) Stop time = 2004 MAY 06 00:00:00.000 (TDB) Elevation limit (degrees) = 6.000000 Loaded SPICE Kernels: Kernel name: geomevnt.mk Kernel type: META Kernel source: Kernel name: kernels/spk/de405xs.bsp Kernel type: SPK Kernel source: geomevnt.mk Kernel name: kernels/spk/earthstns_itrf93_050714.bsp Kernel type: SPK Kernel source: geomevnt.mk Kernel name: kernels/fk/earth_topo_050714.tf Kernel type: TEXT Kernel source: geomevnt.mk Kernel name: kernels/pck/earth_000101_060525_060303.bpc Kernel type: PCK Kernel source: geomevnt.mk Kernel name: kernels/lsk/naif0008.tls Kernel type: TEXT Kernel source: geomevnt.mk Kernel name: kernels/spk/ORMM__040501000000_00076XS.BSP Kernel type: SPK Kernel source: geomevnt.mk Kernel name: kernels/pck/pck00008.tpc Kernel type: TEXT Kernel source: geomevnt.mk srfazl test results: ET = 2004 MAY 02 16:09:14.077 TDB Elevation (degrees): 5.9999949894795e+00 Azimuth (degrees): 6.3919217464494e+01 Range (km): 3.2589389132244e+08 ET = 2004 MAY 02 16:09:14.079 TDB Elevation (degrees): 6.0000010938709e+00 Azimuth (degrees): 6.3919221984349e+01 Range (km): 3.2589389134931e+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. This is a double precision value. 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 02 12:24:55.558 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 02 12:24:55.560 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'. 08-MAR-2004 (NJB) 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 02 16:09:14.077 TDB"; tsttim[1] = "2004 MAY 02 16:09:14.079 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.13e\n" " Azimuth (degrees): %21.13e\n" " Range (km): %21.13e\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 02 12:24:55.558 TDB"; tsttim[1] = "2004 MAY 02 12:24:55.560 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 Occulting body = MARS Aberration correction = CN+S Start time = 2004 MAY 01 23:58:55.814 (UTC) Start time = 2004 MAY 02 00:00:00.000 (TDB) Stop time = 2004 MAY 05 23:58:55.814 (UTC) Stop time = 2004 MAY 06 00:00:00.000 (TDB) Elevation limit (degrees) = 6.000000 Loaded SPICE Kernels: Kernel name: geomevnt.mk Kernel type: META Kernel source: Kernel name: kernels/spk/de405xs.bsp Kernel type: SPK Kernel source: geomevnt.mk Kernel name: kernels/spk/earthstns_itrf93_050714.bsp Kernel type: SPK Kernel source: geomevnt.mk Kernel name: kernels/fk/earth_topo_050714.tf Kernel type: TEXT Kernel source: geomevnt.mk Kernel name: kernels/pck/earth_000101_060525_060303.bpc Kernel type: PCK Kernel source: geomevnt.mk Kernel name: kernels/lsk/naif0008.tls Kernel type: TEXT Kernel source: geomevnt.mk Kernel name: kernels/spk/ORMM__040501000000_00076XS.BSP Kernel type: SPK Kernel source: geomevnt.mk Kernel name: kernels/pck/pck00008.tpc Kernel type: TEXT Kernel source: geomevnt.mk srfazl test results: ET = 2004 MAY 02 16:09:14.077 TDB Elevation (degrees): 5.9999949894795e+00 Azimuth (degrees): 6.3919217464494e+01 Range (km): 3.2589389132244e+08 ET = 2004 MAY 02 16:09:14.079 TDB Elevation (degrees): 6.0000010938709e+00 Azimuth (degrees): 6.3919221984349e+01 Range (km): 3.2589389134931e+08 occpt test results: ET = 2004 MAY 02 12:24:55.558 TDB. Not occulted. ET = 2004 MAY 02 12:24:55.560 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. 08-MAR-2006 (NJB) 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 02 16:09:14.077 TDB"; tsttim[1] = "2004 MAY 02 16:09:14.079 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.13e\n" " Azimuth (degrees): %21.13e\n" " Range (km): %21.13e\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 02 12:24:55.558 TDB"; tsttim[1] = "2004 MAY 02 12:24:55.560 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 MAY 01 23:58:55.814 (UTC) Start time = 2004 MAY 02 00:00:00.000 (TDB) Stop time = 2004 MAY 05 23:58:55.814 (UTC) Stop time = 2004 MAY 06 00:00:00.000 (TDB) Elevation limit (degrees) = 6.000000 Loaded SPICE Kernels: Kernel name: geomevnt.mk Kernel type: META Kernel source: Kernel name: kernels/spk/de405xs.bsp Kernel type: SPK Kernel source: geomevnt.mk Kernel name: kernels/spk/earthstns_itrf93_050714.bsp Kernel type: SPK Kernel source: geomevnt.mk Kernel name: kernels/fk/earth_topo_050714.tf Kernel type: TEXT Kernel source: geomevnt.mk Kernel name: kernels/pck/earth_000101_060525_060303.bpc Kernel type: PCK Kernel source: geomevnt.mk Kernel name: kernels/lsk/naif0008.tls Kernel type: TEXT Kernel source: geomevnt.mk Kernel name: kernels/spk/ORMM__040501000000_00076XS.BSP Kernel type: SPK Kernel source: geomevnt.mk Kernel name: kernels/pck/pck00008.tpc Kernel type: TEXT Kernel source: geomevnt.mk srfazl test results: ET = 2004 MAY 02 16:09:14.077 TDB Elevation (degrees): 5.9999949894795e+00 Azimuth (degrees): 6.3919217464494e+01 Range (km): 3.2589389132244e+08 ET = 2004 MAY 02 16:09:14.079 TDB Elevation (degrees): 6.0000010938709e+00 Azimuth (degrees): 6.3919221984349e+01 Range (km): 3.2589389134931e+08 occpt test results: ET = 2004 MAY 02 12:24:55.558 TDB. Not occulted. ET = 2004 MAY 02 12:24:55.560 TDB. Occulted. Rise and set times of MEX as seen from DSS-14: Target rise time (or window start): 2004 MAY 02 00:00:00.000 (TDB) Target set time: 2004 MAY 02 05:35:03.096 (TDB) Target rise time: 2004 MAY 02 16:09:14.078 (TDB) Target set time: 2004 MAY 03 05:33:57.257 (TDB) Target rise time: 2004 MAY 03 16:08:02.279 (TDB) Target set time: 2004 MAY 04 05:32:50.765 (TDB) Target rise time: 2004 MAY 04 16:06:51.259 (TDB) Target set time: 2004 MAY 05 05:31:43.600 (TDB) Target rise time: 2004 MAY 05 16:05:40.994 (TDB) Target set time (or window end): 2004 MAY 06 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. 08-MAR-2006 (NJB) 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 02 16:09:14.077 TDB"; tsttim[1] = "2004 MAY 02 16:09:14.079 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.13e\n" " Azimuth (degrees): %21.13e\n" " Range (km): %21.13e\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 02 12:24:55.558 TDB"; tsttim[1] = "2004 MAY 02 12:24:55.560 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 MAY 01 23:58:55.814 (UTC) Start time = 2004 MAY 02 00:00:00.000 (TDB) Stop time = 2004 MAY 05 23:58:55.814 (UTC) Stop time = 2004 MAY 06 00:00:00.000 (TDB) Elevation limit (degrees) = 6.000000 Loaded SPICE Kernels: Kernel name: geomevnt.mk Kernel type: META Kernel source: Kernel name: kernels/spk/de405xs.bsp Kernel type: SPK Kernel source: geomevnt.mk Kernel name: kernels/spk/earthstns_itrf93_050714.bsp Kernel type: SPK Kernel source: geomevnt.mk Kernel name: kernels/fk/earth_topo_050714.tf Kernel type: TEXT Kernel source: geomevnt.mk Kernel name: kernels/pck/earth_000101_060525_060303.bpc Kernel type: PCK Kernel source: geomevnt.mk Kernel name: kernels/lsk/naif0008.tls Kernel type: TEXT Kernel source: geomevnt.mk Kernel name: kernels/spk/ORMM__040501000000_00076XS.BSP Kernel type: SPK Kernel source: geomevnt.mk Kernel name: kernels/pck/pck00008.tpc Kernel type: TEXT Kernel source: geomevnt.mk srfazl test results: ET = 2004 MAY 02 16:09:14.077 TDB Elevation (degrees): 5.9999949894795e+00 Azimuth (degrees): 6.3919217464494e+01 Range (km): 3.2589389132244e+08 ET = 2004 MAY 02 16:09:14.079 TDB Elevation (degrees): 6.0000010938709e+00 Azimuth (degrees): 6.3919221984349e+01 Range (km): 3.2589389134931e+08 occpt test results: ET = 2004 MAY 02 12:24:55.558 TDB. Not occulted. ET = 2004 MAY 02 12:24:55.560 TDB. Occulted. Rise and set times of MEX as seen from DSS-14: Target rise time (or window start): 2004 MAY 02 00:00:00.000 (TDB) Target set time: 2004 MAY 02 05:35:03.096 (TDB) Target rise time: 2004 MAY 02 16:09:14.078 (TDB) Target set time: 2004 MAY 03 05:33:57.257 (TDB) Target rise time: 2004 MAY 03 16:08:02.279 (TDB) Target set time: 2004 MAY 04 05:32:50.765 (TDB) Target rise time: 2004 MAY 04 16:06:51.259 (TDB) Target set time: 2004 MAY 05 05:31:43.600 (TDB) Target rise time: 2004 MAY 05 16:05:40.994 (TDB) Target set time (or window end): 2004 MAY 06 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 02 04:49:30.827 (TDB) Occultation egress time: 2004 MAY 02 05:51:17.744 (TDB) Occultation ingress time: 2004 MAY 02 12:24:55.559 (TDB) Occultation egress time: 2004 MAY 02 13:26:26.143 (TDB) Occultation ingress time: 2004 MAY 02 20:00:22.514 (TDB) Occultation egress time: 2004 MAY 02 21:01:38.222 (TDB) Occultation ingress time: 2004 MAY 03 03:35:42.256 (TDB) Occultation egress time: 2004 MAY 03 04:36:42.484 (TDB) Occultation ingress time: 2004 MAY 03 11:11:06.387 (TDB) Occultation egress time: 2004 MAY 03 12:11:49.811 (TDB) Occultation ingress time: 2004 MAY 03 18:46:26.014 (TDB) Occultation egress time: 2004 MAY 03 19:46:54.618 (TDB) Occultation ingress time: 2004 MAY 04 02:21:44.563 (TDB) Occultation egress time: 2004 MAY 04 03:21:56.348 (TDB) Occultation ingress time: 2004 MAY 04 09:57:08.894 (TDB) Occultation egress time: 2004 MAY 04 10:57:04.275 (TDB) Occultation ingress time: 2004 MAY 04 17:32:25.809 (TDB) Occultation egress time: 2004 MAY 04 18:32:05.975 (TDB) Occultation ingress time: 2004 MAY 05 01:07:48.265 (TDB) Occultation egress time: 2004 MAY 05 02:07:11.601 (TDB) Occultation ingress time: 2004 MAY 05 08:43:13.590 (TDB) Occultation egress time: 2004 MAY 05 09:42:21.924 (TDB) Occultation ingress time: 2004 MAY 05 16:18:35.560 (TDB) Occultation egress time: 2004 MAY 05 17:17:27.717 (TDB) Occultation ingress time: 2004 MAY 05 23:54:04.672 (TDB) Occ. egress time (or window end): 2004 MAY 06 00:00:00.000 (TDB) MEX visibility start and stop times as seen from DSS-14: Vis. start time (or window start): 2004 MAY 02 00:00:00.000 (TDB) Visibility end time: 2004 MAY 02 04:49:30.827 (TDB) Visibility start time: 2004 MAY 02 16:09:14.078 (TDB) Visibility end time: 2004 MAY 02 20:00:22.514 (TDB) Visibility start time: 2004 MAY 02 21:01:38.222 (TDB) Visibility end time: 2004 MAY 03 03:35:42.256 (TDB) Visibility start time: 2004 MAY 03 04:36:42.484 (TDB) Visibility end time: 2004 MAY 03 05:33:57.257 (TDB) Visibility start time: 2004 MAY 03 16:08:02.279 (TDB) Visibility end time: 2004 MAY 03 18:46:26.014 (TDB) Visibility start time: 2004 MAY 03 19:46:54.618 (TDB) Visibility end time: 2004 MAY 04 02:21:44.563 (TDB) Visibility start time: 2004 MAY 04 03:21:56.348 (TDB) Visibility end time: 2004 MAY 04 05:32:50.765 (TDB) Visibility start time: 2004 MAY 04 16:06:51.259 (TDB) Visibility end time: 2004 MAY 04 17:32:25.809 (TDB) Visibility start time: 2004 MAY 04 18:32:05.975 (TDB) Visibility end time: 2004 MAY 05 01:07:48.265 (TDB) Visibility start time: 2004 MAY 05 02:07:11.601 (TDB) Visibility end time: 2004 MAY 05 05:31:43.600 (TDB) Visibility start time: 2004 MAY 05 16:05:40.994 (TDB) Visibility end time: 2004 MAY 05 16:18:35.560 (TDB) Visibility start time: 2004 MAY 05 17:17:27.717 (TDB) Vis. end time (or window end): 2004 MAY 05 23:54:04.672 (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 initialized 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" ); }