Esempio n. 1
0
bool spice_error(int error_detail) {
  SpiceInt buffer_size = 1024;
  char error_message[buffer_size];


  if (failed_c()) {
    
    switch(error_detail) {
      
      case ALL :
        //TODO: Neat way to concat all error messages.
        //reset_c();
        break;

      case SHORT :
        getmsg_c("SHORT", buffer_size, error_message);
        reset_c();
        rb_raise(rb_spice_error, "%s\n", error_message);
        break;

      case LONG :
        getmsg_c("LONG", buffer_size, error_message);
        reset_c();
        rb_raise(rb_spice_error, "%s\n", error_message);
        break;

      case EXPLAIN :
        getmsg_c("EXPLAIN", buffer_size, error_message);
        reset_c();
        rb_raise(rb_spice_error, "%s\n", error_message);
        break;

      default :
        reset_c();
        break;
    }
  }
  
  return false;
}
Esempio n. 2
0
  /** 
   * This method looks for any naif errors that might have occurred. It 
   * then compares the error to a list of known naif errors and converts
   * the error into an iException.
   * 
   * @param resetNaif True if the NAIF error status should be reset (naif calls valid)
   */
  void NaifStatus::CheckErrors(bool resetNaif) {
    if(!initialized) {
      SpiceChar returnAct[32] = "RETURN";
      SpiceChar printAct[32] = "NONE";
      erract_c ( "SET", sizeof(returnAct), returnAct); // Reset action to return
      errprt_c ( "SET", sizeof(printAct), printAct);   // ... and print nothing
      initialized = true;
    }

    // Do nothing if NAIF didn't fail
    //getmsg_c("", 0, NULL);
    if(!failed_c()) return;

    // This method has been documented with the information provided
    //   from the NAIF documentation at:
    //    naif/cspice61/packages/cspice/doc/html/req/error.html


    // This message is a character string containing a very terse, usually 
    // abbreviated, description of the problem. The message is a character 
    // string of length not more than 25 characters. It always has the form:
    // SPICE(...)
    // Short error messages used in CSPICE are CONSTANT, since they are 
    // intended to be used in code. That is, they don't contain any data which 
    // varies with the specific instance of the error they indicate.
    // Because of the brief format of the short error messages, it is practical 
    // to use them in a test to determine which type of error has occurred. 
    const int SHORT_DESC_LEN = 26;
    SpiceChar naifShort[SHORT_DESC_LEN];
    getmsg_c("SHORT", SHORT_DESC_LEN, naifShort);

    // This message may be up to 1840 characters long. The CSPICE error handling 
    // mechanism makes no use of its contents. Its purpose is to provide human-readable 
    // information about errors. Long error messages generated by CSPICE routines often 
    // contain data relevant to the specific error they describe.
    const int LONG_DESC_LEN = 1841;
    SpiceChar naifLong[LONG_DESC_LEN];
    getmsg_c("LONG", LONG_DESC_LEN, naifLong);

    // Search for known naif errors...
    iString errMsg;

    Pvl error;
    PvlGroup errorDescription("ErrorDescription");
    errorDescription.AddKeyword(PvlKeyword("ShortMessage", naifShort));
    errorDescription.AddKeyword(PvlKeyword("LongMessage", naifLong));
    error.AddGroup(errorDescription);

    PvlTranslationManager trans(error, "$base/translations/NaifErrors.trn");

    try {
      errMsg = trans.Translate("ShortMessage");
    }
    catch(iException &e) {
      e.Clear();
      errMsg = "An unknown NAIF error has been encountered.";
    }

    try {
      errMsg += " " + trans.Translate("LongMessage");
    }
    catch(iException &e) {
      e.Clear();
    }

    // Now process the error
    if(resetNaif) {
      reset_c();
    }

    errMsg += " The short explanation ";
    errMsg += "provided by NAIF is [" + iString(naifShort) + "]. "; 
    errMsg += "The Naif error is [" + iString(naifLong) + "]";

    throw iException::Message(iException::Spice, errMsg, _FILEINFO_);
  }
Esempio n. 3
0
//---------------------------------------------------------------------------
void SpiceAttitudeKernelReader::GetTargetOrientation(const wxString &objectName,
                                                     Integer           naifID,
                                                     Integer           forFrameNaifId,
                                                     const A1Mjd       &atTime,
//                                                     Real              tolerance,
                                                     Rmatrix33         &r33,
                                                     Rvector3          &angVel,
                                                     const wxString &referenceFrame)
{
   #ifdef DEBUG_CK_READING
      MessageInterface::ShowMessage(wxT("Entering GetTargetOrientation for object %s, with NAIF ID %d, at time %12.10f, with frame = %s\n"),
         objectName.c_str(), naifID, atTime.Get(), referenceFrame.c_str());
   #endif
   wxString objectNameToUse = objectName;

   objectNameToUse       = GmatStringUtil::ToUpper(objectNameToUse);
   objectNameSPICE       = objectNameToUse.char_str();
   naifIDSPICE           = naifID;
   frameNaifIDSPICE      = forFrameNaifId;
   referenceFrameSPICE   = referenceFrame.char_str();
   etSPICE               = A1ToSpiceTime(atTime.Get());

//   boddef_c(objectNameSPICE, naifIDSPICE);        // CSPICE method to set NAIF ID for an object - is this valid for spacecraft?
   // Convert the time (in TDB) to spacecaft ticks
   SpiceDouble scTime;
   sce2c_c(naifIDSPICE, etSPICE, &scTime);
   if (failed_c())
   {
      ConstSpiceChar option[] = "LONG"; // retrieve long error message, for now
      SpiceInt       numChar  = MAX_LONG_MESSAGE_VALUE;
      //SpiceChar      err[MAX_LONG_MESSAGE_VALUE];
      SpiceChar      *err = new SpiceChar[MAX_LONG_MESSAGE_VALUE];
      getmsg_c(option, numChar, err);
      wxString errStr(wxString::FromAscii(err));
      wxString errmsg = wxT("Error getting spacecraft time (ticks) for object \"");
      errmsg += objectName + wxT("\".  Message received from CSPICE is: ");
      errmsg += errStr + wxT("\n");
      reset_c();
      delete [] err;
      throw UtilityException(errmsg);
   }
   // get the tolerance in spacecraft clock ticks
   wxString    tolerance = wxT("01");  // this should probably be user input, or set as a constant
   ConstSpiceChar *tol = tolerance.char_str();
   SpiceDouble    tolTicks;
   sctiks_c(naifIDSPICE, tol, &tolTicks);
   if (failed_c())
   {
      ConstSpiceChar option[] = "LONG"; // retrieve long error message, for now
      SpiceInt       numChar  = MAX_LONG_MESSAGE_VALUE;
      //SpiceChar      err[MAX_LONG_MESSAGE_VALUE];
      SpiceChar      *err = new SpiceChar[MAX_LONG_MESSAGE_VALUE];
      getmsg_c(option, numChar, err);
      wxString errStr(wxString::FromAscii(err));
      wxString errmsg = wxT("Error getting tolerance (ticks) for object \"");
      errmsg += objectName + wxT("\".  Message received from CSPICE is: ");
      errmsg += errStr + wxT("\n");
      reset_c();
      delete [] err;
      throw UtilityException(errmsg);
   }
   #ifdef DEBUG_CK_READING
      MessageInterface::ShowMessage(wxT("First, check for coverage for object \"%s\", with NAIF ID %d\n"),
         objectName.c_str(), naifID);
   #endif
   Real beginCov = 0.0;
   Real endCov   = 0.0;
   GetCoverageStartAndEnd(loadedKernels, forFrameNaifId, beginCov, endCov, false);

   // Now get the C-matrix and angular velocity at the requested time
   SpiceDouble    cmat[3][3];
   SpiceDouble    av[3];
   SpiceBoolean   found;
   SpiceDouble    clkout;
   #ifdef DEBUG_CK_READING
      MessageInterface::ShowMessage(wxT("about to call ckgpav: \n"));
      MessageInterface::ShowMessage(wxT("   NAIF ID  = %d\n")
                                    wxT("   etSPICE  = %12.10f\n")
                                    wxT("   scTime   = %12.10fn")
                                    wxT("   tolTicks = %12.10f\n")
                                    wxT("   refFrame = %s\n"),
         (Integer) naifIDSPICE, (Real) etSPICE, (Real) scTime, (Real) tolTicks,
         referenceFrame.c_str());
   #endif
   ckgpav_c(frameNaifIDSPICE, scTime, tolTicks, referenceFrameSPICE, cmat, av, &clkout, &found);
//   ckgpav_c(naifIDSPICE, scTime, tolTicks, referenceFrameSPICE, cmat, av, &clkout, &found);
   if (failed_c())
   {
      ConstSpiceChar option[] = "LONG"; // retrieve long error message, for now
      SpiceInt       numChar  = MAX_LONG_MESSAGE_VALUE;
      //SpiceChar      err[MAX_LONG_MESSAGE_VALUE];
      SpiceChar      *err = new SpiceChar[MAX_LONG_MESSAGE_VALUE];
      getmsg_c(option, numChar, err);
      wxString errStr(wxString::FromAscii(err));
      wxString errmsg = wxT("Error getting C-matrix and/or angular velocity for object \"");
      errmsg += objectName + wxT("\".  Message received from CSPICE is: ");
      errmsg += errStr + wxT("\n");
      reset_c();
      delete [] err;
      throw UtilityException(errmsg);
   }
   if (found == SPICEFALSE)
   {
      wxString errmsg = wxT("Pointing data for object ");
      errmsg += objectName + wxT(" not found on loaded CK/SCLK kernels.\n");
      throw UtilityException(errmsg);
   }
   #ifdef DEBUG_CK_READING
      MessageInterface::ShowMessage(wxT("results from ckgpav: \n"));
      MessageInterface::ShowMessage(wxT("   cosMat = %12.10f  %12.10f  %12.10f\n")
                                    wxT("            %12.10f  %12.10f  %12.10f\n")
                                    wxT("            %12.10f  %12.10f  %12.10f\n"),
                                    (Real)cmat[0][0], (Real)cmat[0][1], (Real)cmat[0][2],
                                    (Real)cmat[1][0], (Real)cmat[1][1], (Real)cmat[1][2],
                                    (Real)cmat[2][0], (Real)cmat[2][1], (Real)cmat[2][2]);
      MessageInterface::ShowMessage(wxT("   angvel = %12.10f  %12.10f  %12.10f\n"),
                                   (Real)av[0], (Real)av[1], (Real)av[2]);
      MessageInterface::ShowMessage(wxT("   and clkout = %12.10f\n"), (Real) clkout);
   #endif
   // Set output values
   r33.Set(cmat[0][0], cmat[0][1], cmat[0][2],
           cmat[1][0], cmat[1][1], cmat[1][2],
           cmat[2][0], cmat[2][1], cmat[2][2]);
   angVel.Set(av[0], av[1], av[2]);

}
Esempio n. 4
0
//------------------------------------------------------------------------------
void  SpiceAttitudeKernelReader::GetCoverageStartAndEnd(StringArray       &kernels,
                                                        Integer           forNaifId,
                                                        Real              &start,
                                                        Real              &end,
                                                        bool              needAngVel)
{
   // first check to see if a kernel specified is not loaded; if not,
   // try to load it
   for (unsigned int ii = 0; ii < kernels.size(); ii++)
      if (!IsLoaded(kernels.at(ii)))   LoadKernel(kernels.at(ii));

   SpiceInt         idSpice     = forNaifId;
   SpiceInt         arclen      = 4;
   SpiceInt         typlen      = 5;
   bool             firstInt    = true;
   bool             idOnKernel  = false;
   char             kStr[5]     = "    ";
   char             aStr[4]     = "   ";
   char             levelStr[8] = "SEGMENT";
   char             timeStr[4]  = "TDB";
   SpiceBoolean     needAv      = needAngVel;
   ConstSpiceChar   *kernelName = NULL;
   ConstSpiceChar   *level      = levelStr;
   ConstSpiceChar   *timeSys    = timeStr;
   SpiceDouble      tol         = 0.0;
   SpiceInt         objId       = 0;
   SpiceInt         numInt      = 0;
   SpiceChar        *kernelType;
   SpiceChar        *arch;
   SpiceDouble      b;
   SpiceDouble      e;
   Real             bA1;
   Real             eA1;
   SPICEINT_CELL(ids, 200);
   SPICEDOUBLE_CELL(cover, 200000);

   // look through each kernel
   for (unsigned int ii = 0; ii < kernels.size(); ii++)
   {
      #ifdef DEBUG_CK_COVERAGE
         MessageInterface::ShowMessage(wxT("Checking coverage for ID %d on kernel %s\n"),
               forNaifId, (kernels.at(ii)).c_str());
      #endif
      kernelName = kernels[ii].char_str();
      // check the type of kernel
      arch        = aStr;
      kernelType  = kStr;
      getfat_c(kernelName, arclen, typlen, arch, kernelType);
      if (failed_c())
      {
         ConstSpiceChar option[] = "LONG";
         SpiceInt       numChar  = MAX_LONG_MESSAGE_VALUE;
         SpiceChar      err[MAX_LONG_MESSAGE_VALUE];
         getmsg_c(option, numChar, err);
         wxString errStr(wxString::FromAscii( err));
         wxString errmsg = wxT("Error determining type of kernel \"");
         errmsg += kernels.at(ii) + wxT("\".  Message received from CSPICE is: ");
         errmsg += errStr + wxT("\n");
         reset_c();
         throw UtilityException(errmsg);
      }
      #ifdef DEBUG_CK_COVERAGE
         MessageInterface::ShowMessage(wxT("Kernel is of type %s\n"),
               kernelType);
      #endif
      // only deal with CK kernels
      if (eqstr_c(kernelType, "ck") || eqstr_c(kernelType, "CK"))
      {
         ckobj_c(kernelName, &ids);
         // get the list of objects (IDs) for which data exists in the CK kernel
         for (SpiceInt jj = 0;  jj < card_c(&ids);  jj++)
         {
            objId = SPICE_CELL_ELEM_I(&ids,jj);
            #ifdef DEBUG_CK_COVERAGE
               MessageInterface::ShowMessage(wxT("Kernel contains data for object %d\n"),
                     (Integer) objId);
            #endif
            // look to see if this kernel contains data for the object we're interested in
            if (objId == idSpice)
            {
               idOnKernel = true;
               break;
            }
//            if (objId == (idSpice * 1000))
//            {
//               idSpice     = idSpice * 1000;
//               naifIDSPICE = idSpice; // not the way to do this - should pass it back
//               idOnKernel  = true;
//               break;
//            }
         }
         // only deal with kernels containing data for the object we're interested in
         if (idOnKernel)
         {
            #ifdef DEBUG_CK_COVERAGE
               MessageInterface::ShowMessage(wxT("Checking kernel %s for data for object %d\n"),
                     (kernels.at(ii)).c_str(), (Integer) objId);
            #endif
            scard_c(0, &cover);   // reset the coverage cell
            ckcov_c (kernelName, idSpice, needAv, level, tol, timeSys, &cover);
            if (failed_c())
            {
               ConstSpiceChar option[] = "LONG";
               SpiceInt       numChar  = MAX_LONG_MESSAGE_VALUE;
               SpiceChar      err[MAX_LONG_MESSAGE_VALUE];
               getmsg_c(option, numChar, err);
               wxString errStr(wxString::FromAscii(err));
               wxString errmsg = wxT("Error determining coverage for CK kernel \"");
               errmsg += kernels.at(ii) + wxT("\".  Message received from CSPICE is: ");
               errmsg += errStr + wxT("\n");
               reset_c();
               throw UtilityException(errmsg);
            }
            numInt = wncard_c(&cover);
            #ifdef DEBUG_CK_COVERAGE
               MessageInterface::ShowMessage(wxT("Number of intervals found =  %d\n"),
                     (Integer) numInt);
            #endif
            if ((firstInt) && (numInt > 0))
            {
               wnfetd_c(&cover, 0, &b, &e);
               if (failed_c())
               {
                  ConstSpiceChar option[] = "LONG";
                  SpiceInt       numChar  = MAX_LONG_MESSAGE_VALUE;
                  SpiceChar      err[MAX_LONG_MESSAGE_VALUE];
                  getmsg_c(option, numChar, err);
                  wxString errStr(wxString::FromAscii(err));
                  wxString errmsg = wxT("Error getting interval times for CK kernel \"");
                  errmsg += kernels.at(ii) + wxT("\".  Message received from CSPICE is: ");
                  errmsg += errStr + wxT("\n");
                  reset_c();
                  throw UtilityException(errmsg);
               }
               start    = SpiceTimeToA1(b);
               end      = SpiceTimeToA1(e);
               firstInt = false;
            }
            for (SpiceInt jj = 0; jj < numInt; jj++)
            {
               wnfetd_c(&cover, jj, &b, &e);
               bA1 = SpiceTimeToA1(b);
               eA1 = SpiceTimeToA1(e);
               if (bA1 < start)  start = bA1;
               if (eA1 > end)    end   = eA1;
            }
         }

      }
   }
   if (firstInt)
   {
      char           itsName[256];
      SpiceChar      *itsNameSPICE = itsName;
      SpiceBoolean   found2;
      bodc2n_c(naifIDSPICE, 256, itsNameSPICE, &found2);
      if (found2 == SPICEFALSE)
      {
         wxString errmsg = wxT("Error - unable to find name for body in SPICE kernel pool");
         throw UtilityException(errmsg);
      }
      else
      {
         wxString nameStr = wxString::FromAscii(itsNameSPICE);
         wxString errmsg = wxT("Error - no data available for body ");
         errmsg += nameStr + wxT(" on specified CK kernels");
         throw UtilityException(errmsg);
      }
   }
}
Esempio n. 5
0
//------------------------------------------------------------------------------
Rvector6 SpiceOrbitKernelReader::GetTargetState(const wxString &targetName,
                                 const Integer     targetNAIFId,
                                 const A1Mjd       &atTime,
                                 const wxString &observingBodyName,
                                 const wxString &referenceFrame,
                                 const wxString &aberration)
{
   #ifdef DEBUG_SPK_READING
      MessageInterface::ShowMessage(
            wxT("Entering SPKReader::GetTargetState with target = %s, naifId = %d, time = %12.10f, observer = %s\n"),
            targetName.c_str(), targetNAIFId, atTime.Get(), observingBodyName.c_str());
      Real start, end;
      GetCoverageStartAndEnd(loadedKernels, targetNAIFId, start, end);
      MessageInterface::ShowMessage(wxT("   coverage for object %s : %12.10f --> %12.10f\n"),
            targetName.c_str(), start, end);
   #endif
   wxString targetNameToUse = GmatStringUtil::ToUpper(targetName);
   if (targetNameToUse == wxT("LUNA"))  // We use Luna, instead of Moon, for GMAT
      targetNameToUse        = wxT("MOON");
   if (targetNameToUse == wxT("SOLARSYSTEMBARYCENTER"))
      targetNameToUse = wxT("SSB");
   objectNameSPICE           = targetNameToUse.char_str();
   observingBodyNameSPICE    = observingBodyName.char_str();
   referenceFrameSPICE       = referenceFrame.char_str();
   aberrationSPICE           = aberration.char_str();
   // convert time to Ephemeris Time (TDB)
   etSPICE                   = A1ToSpiceTime(atTime.Get());
   naifIDSPICE               = targetNAIFId;
   boddef_c(objectNameSPICE, naifIDSPICE);        // CSPICE method to set NAIF ID for an object

   #ifdef DEBUG_SPK_READING
      MessageInterface::ShowMessage(wxT("SET NAIF Id for object %s to %d\n"),
            targetNameToUse.c_str(), targetNAIFId);
//      MessageInterface::ShowMessage(
//            wxT("In SPKReader::Converted (to TBD) time = %12.10f\n"), etMjdAtTime);
//      MessageInterface::ShowMessage(wxT("  then the full JD = %12.10f\n"),
//            (etMjdAtTime + GmatTimeConstants::JD_JAN_5_1941));
      MessageInterface::ShowMessage(wxT("So time passed to SPICE is %12.14f\n"), (Real) etSPICE);
   #endif
   SpiceDouble state[6];
   SpiceDouble oneWayLightTime;
   spkezr_c(objectNameSPICE, etSPICE, referenceFrameSPICE, aberrationSPICE,
            observingBodyNameSPICE, state, &oneWayLightTime);
#ifdef DEBUG_SPK_PLANETS
   Real        ttMjdAtTime   = TimeConverterUtil::Convert(atTime.Get(), TimeConverterUtil::A1MJD,
                               TimeConverterUtil::TTMJD, GmatTimeConstants::JD_JAN_5_1941);
//   Real etJd                 = etMjdAtTime + GmatTimeConstants::JD_JAN_5_1941;
   Real ttJd                 = ttMjdAtTime + GmatTimeConstants::JD_JAN_5_1941;
   MessageInterface::ShowMessage(wxT("Asking CSPICE for state of body %s, with observer %s, referenceFrame %s, and aberration correction %s\n"),
         objectNameSPICE, observingBodyNameSPICE, referenceFrameSPICE, aberrationSPICE);
   MessageInterface::ShowMessage(
         wxT("           Body: %s   TT Time:  %12.10f  TDB Time: %12.10f   state:  %12.10f  %12.10f  %12.10f  %12.10f  %12.10f  %12.10f\n"),
         targetName.c_str(), ttJd, /*etJd,*/ state[0], state[1], state[2], state[3], state[4], state[5]);
#endif
   if (failed_c())
   {
//      ConstSpiceChar option[] = wxT("SHORT"); // retrieve short error message, for now
//      SpiceInt       numChar  = MAX_SHORT_MESSAGE;
//      SpiceChar      err[MAX_SHORT_MESSAGE];
      ConstSpiceChar option[] = "LONG"; // retrieve long error message, for now
      SpiceInt       numChar  = MAX_LONG_MESSAGE_VALUE;
      //SpiceChar      err[MAX_LONG_MESSAGE_VALUE];
      SpiceChar      *err = new SpiceChar[MAX_LONG_MESSAGE_VALUE];
      getmsg_c(option, numChar, err);
      wxString errStr(wxString::FromAscii(err));
      wxString errmsg = wxT("Error getting state for body \"");
      errmsg += targetName + wxT("\".  Message received from CSPICE is: ");
      errmsg += errStr + wxT("\n");
      reset_c();
      delete [] err;
      throw UtilityException(errmsg);
   }
   #ifdef DEBUG_SPK_READING
      MessageInterface::ShowMessage(
            wxT("In SPKReader::Called spkezr_c and got state out\n"));
   #endif


   Rvector6 r6(state[0],state[1],state[2],state[3],state[4],state[5]);
   return r6;
}
Esempio n. 6
0
//------------------------------------------------------------------------------
void  SpiceOrbitKernelReader::GetCoverageStartAndEnd(StringArray       &kernels,
                                                     Integer           forNaifId,
                                                     Real              &start,
                                                     Real              &end)
{
   // first check to see if a kernel specified is not loaded; if not,
   // try to load it
   for (unsigned int ii = 0; ii < kernels.size(); ii++)
      if (!IsLoaded(kernels.at(ii)))   LoadKernel(kernels.at(ii));

   SpiceInt         idSpice     = forNaifId;
   SpiceInt         arclen      = 4;
   SpiceInt         typlen      = 5;
   bool             firstInt    = true;
   bool             idOnKernel  = false;
   ConstSpiceChar   *kernelName = NULL;
   SpiceInt         objId       = 0;
   SpiceInt         numInt      = 0;
   SpiceChar        *kernelType;
   SpiceChar        *arch;
   SpiceDouble      b;
   SpiceDouble      e;
   Real             bA1;
   Real             eA1;
   SPICEINT_CELL(ids, 200);
   SPICEDOUBLE_CELL(cover, 200000);
   char             kStr[5] = "    ";
   char             aStr[4] = "   ";

   // look through each kernel
   for (unsigned int ii = 0; ii < kernels.size(); ii++)
   {
      #ifdef DEBUG_SPK_COVERAGE
         MessageInterface::ShowMessage(wxT("Checking coverage for ID %d on kernel %s\n"),
               forNaifId, (kernels.at(ii)).c_str());
      #endif
      kernelName = kernels[ii].char_str();
      // check the type of kernel
      arch        = aStr;
      kernelType  = kStr;
      getfat_c(kernelName, arclen, typlen, arch, kernelType);
      if (failed_c())
      {
         ConstSpiceChar option[] = "LONG";
         SpiceInt       numChar  = MAX_LONG_MESSAGE_VALUE;
         //SpiceChar      err[MAX_LONG_MESSAGE_VALUE];
         SpiceChar      *err = new SpiceChar[MAX_LONG_MESSAGE_VALUE];
         getmsg_c(option, numChar, err);
         wxString errStr(wxString::FromAscii(err));
         wxString errmsg = wxT("Error determining type of kernel \"");
         errmsg += kernels.at(ii) + wxT("\".  Message received from CSPICE is: ");
         errmsg += errStr + wxT("\n");
         reset_c();
         delete [] err;
         throw UtilityException(errmsg);
      }
      #ifdef DEBUG_SPK_COVERAGE
         MessageInterface::ShowMessage(wxT("Kernel is of type %s\n"),
               kernelType);
      #endif
      // only deal with SPK kernels
      if (eqstr_c( kernelType, "spk" ))
      {
         spkobj_c(kernelName, &ids);
         // get the list of objects (IDs) for which data exists in the SPK kernel
         for (SpiceInt jj = 0;  jj < card_c(&ids);  jj++)
         {
            objId = SPICE_CELL_ELEM_I(&ids,jj);
            #ifdef DEBUG_SPK_COVERAGE
               MessageInterface::ShowMessage(wxT("Kernel contains data for object %d\n"),
                     (Integer) objId);
            #endif
            // look to see if this kernel contains data for the object we're interested in
            if (objId == idSpice)
            {
               idOnKernel = true;
               break;
            }
         }
         // only deal with kernels containing data for the object we're interested in
         if (idOnKernel)
         {
            #ifdef DEBUG_SPK_COVERAGE
               MessageInterface::ShowMessage(wxT("Checking kernel %s for data for object %d\n"),
                     (kernels.at(ii)).c_str(), (Integer) objId);
            #endif
            scard_c(0, &cover);   // reset the coverage cell
            spkcov_c (kernelName, idSpice, &cover);
            if (failed_c())
            {
               ConstSpiceChar option[] = "LONG";
               SpiceInt       numChar  = MAX_LONG_MESSAGE_VALUE;
               //SpiceChar      err[MAX_LONG_MESSAGE_VALUE];
               SpiceChar      *err = new SpiceChar[MAX_LONG_MESSAGE_VALUE];
               getmsg_c(option, numChar, err);
               wxString errStr(wxString::FromAscii(err));
               wxString errmsg = wxT("Error determining coverage for SPK kernel \"");
               errmsg += kernels.at(ii) + wxT("\".  Message received from CSPICE is: ");
               errmsg += errStr + wxT("\n");
               reset_c();
               delete [] err;
               throw UtilityException(errmsg);
            }
            numInt = wncard_c(&cover);
            #ifdef DEBUG_SPK_COVERAGE
               MessageInterface::ShowMessage(wxT("Number of intervals found =  %d\n"),
                     (Integer) numInt);
            #endif
            if ((firstInt) && (numInt > 0))
            {
               wnfetd_c(&cover, 0, &b, &e);
               if (failed_c())
               {
                  ConstSpiceChar option[] = "LONG";
                  SpiceInt       numChar  = MAX_LONG_MESSAGE_VALUE;
                  //SpiceChar      err[MAX_LONG_MESSAGE_VALUE];
                  SpiceChar      *err = new SpiceChar[MAX_LONG_MESSAGE_VALUE];
                  getmsg_c(option, numChar, err);
                  wxString errStr(wxString::FromAscii(err));
                  wxString errmsg = wxT("Error getting interval times for SPK kernel \"");
                  errmsg += kernels.at(ii) + wxT("\".  Message received from CSPICE is: ");
                  errmsg += errStr + wxT("\n");
                  reset_c();
                  delete [] err;
                  throw UtilityException(errmsg);
               }
               start    = SpiceTimeToA1(b);
               end      = SpiceTimeToA1(e);
               firstInt = false;
            }
            for (SpiceInt jj = 0; jj < numInt; jj++)
            {
               wnfetd_c(&cover, jj, &b, &e);
               bA1 = SpiceTimeToA1(b);
               eA1 = SpiceTimeToA1(e);
               if (bA1 < start)  start = bA1;
               if (eA1 > end)    end   = eA1;
            }
         }

      }
   }
   if (firstInt)
   {
      wxString errmsg(wxT(""));
      errmsg << wxT("Error - no data available for body with NAIF ID ") << forNaifId << wxT(" on specified SPK kernels\n");
      throw UtilityException(errmsg);
   }
}