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; }
/** * 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_); }
//--------------------------------------------------------------------------- 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]); }
//------------------------------------------------------------------------------ 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); } } }
//------------------------------------------------------------------------------ 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; }
//------------------------------------------------------------------------------ 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); } }