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" );
}