diff --git a/include/openspace/tests/test_spicemanager.inl b/include/openspace/tests/test_spicemanager.inl index b73417e9c9..e12173c3f4 100644 --- a/include/openspace/tests/test_spicemanager.inl +++ b/include/openspace/tests/test_spicemanager.inl @@ -173,7 +173,7 @@ TEST_F(SpiceManagerTest, getValueFromID_1D){ std::string value1D = "MAG_NORTH_POLE_LAT"; double return1D; - bool found = openspace::SpiceManager::ref().getValueFromID(target, value1D, return1D); + bool found = openspace::SpiceManager::ref().getValue(target, value1D, return1D); ASSERT_TRUE(found) << "Could not retrieve value"; EXPECT_EQ(return1D, 78.565) << "Value not found / differs from expected return"; unload_c(PCK.c_str()); @@ -186,7 +186,7 @@ TEST_F(SpiceManagerTest, getValueFromID_3D){ std::string value3D = "RADII"; glm::dvec3 return3D; - openspace::SpiceManager::ref().getValueFromID(target, value3D, return3D); + openspace::SpiceManager::ref().getValue(target, value3D, return3D); EXPECT_EQ(return3D.x, 6378.14) << "Value not found / differs from expected return"; EXPECT_EQ(return3D.y, 6378.14) << "Value not found / differs from expected return"; @@ -200,16 +200,15 @@ TEST_F(SpiceManagerTest, getValueFromID_ND){ std::string target = "SATURN"; std::string valueND = "RING6_A"; - std::vector returnND; - unsigned int nr = 5; - bool found = openspace::SpiceManager::ref().getValueFromID(target, valueND, returnND, nr); + std::vector returnND(5); + bool found = openspace::SpiceManager::ref().getValue(target, valueND, returnND); ASSERT_TRUE(found) << "Could not retrieve value for specified kernel"; std::vector controlVec{ 189870.0, 256900.0, 9000.0, 9000.0, 0.000003 }; ASSERT_EQ(controlVec.size(), returnND.size()) << "Vectors differ in size"; - for (unsigned int i = 0; i < nr; ++i){ + for (unsigned int i = 0; i < returnND.size(); ++i){ EXPECT_EQ(controlVec[i], returnND[i]) << "Vector value not equal"; } unload_c(PCK.c_str()); @@ -223,7 +222,8 @@ TEST_F(SpiceManagerTest, stringToEphemerisTime){ char date[SRCLEN] = "Thu Mar 20 12:53:29 PST 1997"; str2et_c(date, &control_ephemerisTime); - ephemerisTime = openspace::SpiceManager::ref().convertStringToTdbSeconds(date); + bool success = openspace::SpiceManager::ref().getETfromDate(date, ephemerisTime); + EXPECT_EQ(success, true); EXPECT_EQ(ephemerisTime, control_ephemerisTime) << "Ephemeries times differ / not found"; unload_c(LSK.c_str()); diff --git a/include/openspace/util/spicemanager.h b/include/openspace/util/spicemanager.h index ba444f2568..dfe4f87e48 100644 --- a/include/openspace/util/spicemanager.h +++ b/include/openspace/util/spicemanager.h @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -122,62 +123,196 @@ public: * \return true if the body was found, false * otherwise */ - bool getNaifIdForBody(const std::string& body, int& id) const; - - /** - * Fetch from the kernel pool the double precision values of an - * item associated with a body. - * For further details, please refer to 'bodvrd_c' in SPICE Docummentation - * - * \param bodyName Body name. - * \param kernelPoolValueName Item for which values are desired. ("RADII", "NUT_PREC_ANGLES", etc. ) - * \return Whether the function succeeded or not - */ - bool getValueFromID(const std::string& bodyname, - const std::string& kernelPoolValueName, - double& value) const; - /* Overloaded method for 3dim vectors, see above specification.*/ - bool getValueFromID(const std::string& bodyname, - const std::string& kernelPoolValueName, - glm::dvec3& value) const; - /* Overloaded method for 4dim vectors, see above specification.*/ - bool getValueFromID(const std::string& bodyname, - const std::string& kernelPoolValueName, - glm::dvec4& value) const; - /* Overloaded method for Ndim vectors, see above specification.*/ - bool getValueFromID(const std::string& bodyname, - const std::string& kernelPoolValueName, - std::vector& values, unsigned int num) const; - -// Converting between UTC and Ephemeris Time (LSK) ------------------------------------- // - + bool getNaifId(const std::string& body, int& id) const; /** - * Convert a string representing an epoch to a double precision - * value representing the number of TDB seconds past the J2000 - * epoch corresponding to the input epoch. - * For further details, please refer to 'str2et_c' in SPICE Docummentation - * - * \param epochString, A string representing an epoch. - * \return Corresponding ephemeris time, equivalent value in seconds past J2000, TDB. + * Retrieves a single value for a certain body. This method + * succeeds iff body is the name of a valid body, value + * is a value associated with the body, and the value consists of only a single + * double value. If all conditions are true, the value is retrieved using + * the method bodvrd_c and stored in v + * http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/bodvrd_c.html. If one of + * the conditions is false an error is logged and the value v is + * unchanged. + * \param body The name of the body whose value should be retrieved + * \param value The value of that should be retrieved, this value is case-sensitive + * \param v The destination for the retrieved value + * \return true if the body named a valid body, + * value is a valid item for the body and the retrieved + * value is only a single value. false otherwise */ - double convertStringToTdbSeconds(const std::string& epochString) const; + bool getValue(const std::string& body, const std::string& value, double& v) const; /** - * Convert the number of TDB seconds past the J2000 epoch into a human readable - * string representation. Fur further details, please refer to 'timout_c' in SPICE - * Documentation - * - * \param seconds The number of seconds that have passed since the J2000 epoch - * \param format The output format of the string - * (see ftp://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/timout_c.html) - * \return The formatted date string + * Retrieves a single value for a certain body with a NAIF ID of + * id. This method succeeds iff id is the ID of a valid + * body, value is a value associated with the body, and the value + * consists of only a single double value. If all conditions are true, + * the value is retrieved using the method bodvrd_c and stored in + * v + * http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/bodvrd_c.html. If one of + * the conditions is false an error is logged and the value v is + * unchanged. For a description on NAIF IDs, see + * http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/req/naif_ids.html. + * \param id The NAIF ID of the body whose information should be retrieved + * \param value The value of that should be retrieved, this value is case-sensitive + * \param v The destination for the retrieved value + * \return true if the body named a valid body, + * value is a valid item for the body and the retrieved + * value is only a single value. false otherwise */ - std::string convertTdbSecondsToString(double seconds, const std::string& format) const; + bool getValue(int id, const std::string& value, double& v) const; - std::string ephemerisTimeToString(const double et) const; + /** + * Retrieves a value with three components for a certain + * body. This method succeeds iff body is the name of a + * valid body, value is a value associated with the body, and the value + * consists of three double values. If all conditions are true, the value + * is retrieved using the method bodvrd_c and stored in v + * http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/bodvrd_c.html. If one of + * the conditions is false an error is logged and the value v is + * unchanged. + * \param body The name of the body whose value should be retrieved + * \param value The value of that should be retrieved, this value is case-sensitive + * \param v The destination for the retrieved values + * \return true if the body named a valid body, + * value is a valid item for the body and the retrieved + * value is only a single value. false otherwise + */ + bool getValue(const std::string& body, const std::string& value, glm::dvec3& v) const; -// Computing Positions of Spacecraft and Natural Bodies(SPK) ---------------------------- // + /** + * Retrieves a value with three components for a certain body with a + * NAIF ID of id. This method succeeds id is the ID of a + * valid body, value is a value associated with the body, and the value + * consists of three double values. If all conditions are true, the value + * is retrieved using the method bodvrd_c and stored in v + * http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/bodvrd_c.html. If one of + * the conditions is false an error is logged and the value v is + * unchanged. For a description on NAIF IDs, see + * http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/req/naif_ids.html. + * \param id The NAIF ID of the body whose information should be retrieved + * \param value The value of that should be retrieved, this value is case-sensitive + * \param v The destination for the retrieved values + * \return true if the body named a valid body, + * value is a valid item for the body and the retrieved + * value is only a single value. false otherwise + */ + bool getValue(int id, const std::string& value, glm::dvec3& v) const; + + /** + * Retrieves a value with four components for a certain + * body. This method succeeds iff body is the name of a + * valid body, value is a value associated with the body, and the value + * consists of four double values. If all conditions are true, the value + * is retrieved using the method bodvrd_c and stored in v + * http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/bodvrd_c.html. If one of + * the conditions is false an error is logged and the value v is + * unchanged. + * \param body The name of the body whose value should be retrieved + * \param value The value of that should be retrieved, this value is case-sensitive + * \param v The destination for the retrieved values + * \return true if the body named a valid body, + * value is a valid item for the body and the retrieved + * value is only a single value. false otherwise + */ + bool getValue(const std::string& body, const std::string& value, glm::dvec4& v) const; + + /** + * Retrieves a value with four components for a certain body with a + * NAIF ID of id. This method succeeds id is the ID of a + * valid body, value is a value associated with the body, and the value + * consists of four double values. If all conditions are true, the value + * is retrieved using the method bodvrd_c and stored in v + * http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/bodvrd_c.html. If one of + * the conditions is false an error is logged and the value v is + * unchanged. For a description on NAIF IDs, see + * http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/req/naif_ids.html. + * \param id The NAIF ID of the body whose information should be retrieved + * \param value The value of that should be retrieved, this value is case-sensitive + * \param v The destination for the retrieved values + * \return true if the body named a valid body, + * value is a valid item for the body and the retrieved + * value is only a single value. false otherwise + */ + bool getValue(int id, const std::string& value, glm::dvec4& v) const; + + /** + * Retrieves a value with an arbitrary number of components for a certain + * body. This method succeeds body is a valid body, + * value is a value associated with the body, and the value consists of a + * number of double values. The requested number is equal to the + * size of the passed vector v which means that this vector + * has to be preallocated. If all conditions are true, the value is retrieved using + * the method bodvrd_c and stored in v + * http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/bodvrd_c.html. If one of + * the conditions is false an error is logged and the value v is + * unchanged. + * \param body The body whose information should be retrieved + * \param value The value of that should be retrieved, this value is case-sensitive + * \param v The destination for the retrieved values. The size of this vector + * determines how many values will be retrieved + * \return true if the body named a valid body, + * value is a valid item for the body and the retrieved + * value is only a single value. false otherwise + */ + bool getValue(const std::string& body, const std::string& value, + std::vector& v) const; + + /** + * Retrieves a value with an arbitrary number of components for a certain + * body with a NAIF ID of id. This method succeeds id is the + * ID of a valid body, value is a value associated with the body, and the + * value consists of a number of double values. The requested number is + * equal to the size of the passed vector v which means that + * this vector has to be preallocated. If all conditions are true, the value is + * retrieved using the method bodvrd_c and stored in v + * http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/bodvrd_c.html. If one of + * the conditions is false an error is logged and the value v is + * unchanged. For a description on NAIF IDs, see + * http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/req/naif_ids.html. + * \param id The NAIF ID of the body whose information should be retrieved + * \param value The value of that should be retrieved, this value is case-sensitive + * \param v The destination for the retrieved values. The size of this vector + * determines how many values will be retrieved + * \return true if the body named a valid body, + * value is a valid item for the body and the retrieved + * value is only a single value. false otherwise + */ + bool getValue(int id, const std::string& value, std::vector& v) const; + + /** + * Converts the epochString representing a date to a double precision + * value representing the ephemerisTime; that is the number of TDB + * seconds past the J2000 epoch. For further details, please refer to + * http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/str2et_c.html. If an error + * occurs, an error is logged, the method returns false and the + * ephemerisTime remains unchanged. + * \param epochString A string representing an epoch + * \param ephemerisTime The destination for the converted time; the number of TDB + * seconds past the J2000 epoch, representing the passed epochString + * \return true if the epochString is a valid string and + * the conversion succeeded, false otherwise + */ + bool getETfromDate(const std::string& epochString, double& ephemerisTime) const; + + /** + * Converts the passed ephemerisTime into a human-readable + * date string with a specific format. For details on the + * formatting, refer to + * http://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/cspice/timout_c.html. In case of + * an error, date will not be modified, an error will be logged and the + * method returns false. + * \param ephemerisTime The ephemeris time, that is the number of TDB seconds past the + * J2000 epoch + * \param date The destination for the converted date. This will only be changed if + * the conversion succeeded + * \param format The format string describing the output format for the + * date + * \return true if the conversion succeeded, false otherwise + */ + bool getDateFromET(double ephemerisTime, std::string& date, + const std::string& format = "YYYY MON DDTHR:MN:SC.### ::RND"); /** * Return the position of a target body relative to an observing diff --git a/src/util/spicemanager.cpp b/src/util/spicemanager.cpp index a92b026885..20ad4d193c 100644 --- a/src/util/spicemanager.cpp +++ b/src/util/spicemanager.cpp @@ -30,6 +30,8 @@ #include #include +#include + //#ifdef WIN32 //#include //#endif @@ -130,145 +132,151 @@ bool SpiceManager::hasValue(int naifId, const std::string& item) const { bool SpiceManager::hasValue(const std::string& body, const std::string& item) const { int id; - bool success = getNaifIdForBody(body, id); + bool success = getNaifId(body, id); if (success) return hasValue(id, item); else return false; } -bool SpiceManager::getNaifIdForBody(const std::string& body, int& id) const { +bool SpiceManager::getNaifId(const std::string& body, int& id) const { SpiceBoolean success; bods2c_c(body.c_str(), &id, &success); return (success == SPICETRUE); } -// 1D -bool SpiceManager::getValueFromID(const std::string& bodyname, - const std::string& kernelPoolValue, - double& value) const{ - int n; - int code; - int found; - - bodn2c_c(bodyname.c_str(), &code, &found); - if (!found) return false; - bodvrd_c(bodyname.c_str(), kernelPoolValue.c_str(), 1, &n, &value); - - return true; -} -// 2D -/* -bool SpiceManager::getValueFromID(const std::string& bodyname, - const std::string& kernelPoolValueName, - glm::dvec2& value) const{ - int n; - double val[2]; - int code; - int found; - - bodn2c_c(bodyname.c_str(), &code, &found); - if (!found) return false; - bodvrd_c(bodyname.c_str(), kernelPoolValueName.c_str(), 2, &n, val); - - value[0] = val[0]; - value[1] = val[1]; - - return true; - -} -*/ -// 3D -bool SpiceManager::getValueFromID(const std::string& bodyname, - const std::string& kernelPoolValueName, - glm::dvec3& value) const{ - int n; - double val[3]; - int code; - int found; - - bodn2c_c(bodyname.c_str(), &code, &found); - if (!found) return false; - bodvrd_c(bodyname.c_str(), kernelPoolValueName.c_str(), 3, &n, val); - - memcpy(&value, val, sizeof(double)* 3); - - return true; -} -// 4D -/* -bool SpiceManager::getValueFromID(const std::string& bodyname, - const std::string& kernelPoolValueName, - glm::dvec4& value) const{ - int n; - double val[4]; - int code; - int found; - - bodn2c_c(bodyname.c_str(), &code, &found); - if (!found) return false; - bodvrd_c(bodyname.c_str(), kernelPoolValueName.c_str(), 4, &n, val); - - value[0] = val[0]; - value[1] = val[1]; - value[2] = val[2]; - value[3] = val[3]; - - return true; -} -*/ -// ND -bool SpiceManager::getValueFromID(const std::string& bodyname, - const std::string& kernelPoolValueName, - std::vector& values, - unsigned int num) const{ - int n; - double *val; - val = (double*)malloc(num*sizeof(double)); - int code; - int found; - - bodn2c_c(bodyname.c_str(), &code, &found); - if (!found) return false; - bodvrd_c(bodyname.c_str(), kernelPoolValueName.c_str(), num, &n, val); - - for (int i = 0; i < num; i++){ - values.push_back(val[i]); - } - - return true; -} - -double SpiceManager::convertStringToTdbSeconds(const std::string& epochString) const{ - double et; - str2et_c(epochString.c_str(), &et); - return et; -} - -std::string SpiceManager::ephemerisTimeToString(const double et) const{ - char utcstr[40]; - timout_c(et, "YYYY MON DD HR:MN:SC.### ::RND", 32, utcstr); - return std::string(utcstr); -} - -std::string SpiceManager::convertTdbSecondsToString(double seconds, - const std::string& format) const +bool SpiceManager::getValue(const std::string& body, const std::string& value, + double& v) const { - const int bufferSize = 128; - SpiceChar buffer[bufferSize]; - timout_c(seconds, format.c_str(), bufferSize - 1, buffer); + int n; + bodvrd_c(body.c_str(), value.c_str(), 1, &n, &v); int failed = failed_c(); if (failed) { char msg[1024]; getmsg_c("LONG", 1024, msg); - //LERROR("Error retrieving position of target '" + target + "'"); + LERROR("Error getting value '" << value << "' for body '" << body << "'"); LERROR("Spice reported: " + std::string(msg)); reset_c(); - return ""; + return false; } - return std::string(buffer); + return true; +} + +bool SpiceManager::getValue(int id, const std::string& value, double& v) const { + return getValue(std::to_string(id), value, v); +} + +bool SpiceManager::getValue(const std::string& body, const std::string& value, + glm::dvec3& v) const +{ + int n; + bodvrd_c(body.c_str(), value.c_str(), 3, &n, glm::value_ptr(v)); + + int failed = failed_c(); + if (failed) { + char msg[1024]; + getmsg_c("LONG", 1024, msg); + LERROR("Error getting value '" << value << "' for body '" << body << "'"); + LERROR("Spice reported: " + std::string(msg)); + reset_c(); + return false; + } + + return true; +} + +bool SpiceManager::getValue(int id, const std::string& value, glm::dvec3& v) const +{ + return getValue(std::to_string(id), value, v); +} + +bool SpiceManager::getValue(const std::string& body, const std::string& value, + glm::dvec4& v) const +{ + int n; + bodvrd_c(body.c_str(), value.c_str(), 4, &n, glm::value_ptr(v)); + + int failed = failed_c(); + if (failed) { + char msg[1024]; + getmsg_c("LONG", 1024, msg); + LERROR("Error getting value '" << value << "' for body '" << body << "'"); + LERROR("Spice reported: " + std::string(msg)); + reset_c(); + return false; + } + + return true; +} + +bool SpiceManager::getValue(int id, const std::string& value, glm::dvec4& v) const +{ + return getValue(std::to_string(id), value, v); +} + +bool SpiceManager::getValue(const std::string& body, const std::string& value, + std::vector& v) const +{ + assert(v.size() > 0); + int n; + bodvrd_c(body.c_str(), value.c_str(), static_cast(v.size()), &n, &v[0]); + + int failed = failed_c(); + if (failed) { + char msg[1024]; + getmsg_c("LONG", 1024, msg); + LERROR("Error getting value '" << value << "' for body '" << body << "'"); + LERROR("Spice reported: " + std::string(msg)); + reset_c(); + return false; + } + + return true; +} + +bool SpiceManager::getValue(int id, const std::string& value, + std::vector& v) const +{ + return getValue(std::to_string(id), value, v); +} + +bool SpiceManager::getETfromDate(const std::string& epochString, + double& ephemerisTime) const +{ + str2et_c(epochString.c_str(), &ephemerisTime); + int failed = failed_c(); + if (failed) { + char msg[1024]; + getmsg_c("LONG", 1024, msg); + LERROR("Error converting date '" + epochString+ "'"); + LERROR("Spice reported: " + std::string(msg)); + reset_c(); + return false; + } + return true; +} + +bool SpiceManager::getDateFromET(double ephemerisTime, std::string& date, + const std::string& format) +{ + static const int BufferSize = 256; + SpiceChar buffer[BufferSize]; + + timout_c(ephemerisTime, format.c_str(), BufferSize - 1, buffer); + int failed = failed_c(); + if (failed) { + char msg[1024]; + getmsg_c("LONG", 1024, msg); + LERROR("Error converting ephemeris time to date with format '" + format + "'"); + LERROR("Spice reported: " + std::string(msg)); + reset_c(); + return false; + } + + date = std::string(buffer); + return true; } bool SpiceManager::getTargetPosition(const std::string& target, diff --git a/src/util/time.cpp b/src/util/time.cpp index 6520e3f4c5..38443ac42a 100644 --- a/src/util/time.cpp +++ b/src/util/time.cpp @@ -193,11 +193,13 @@ double Time::deltaTime() const { } void Time::setTime(std::string time) { - _time = SpiceManager::ref().convertStringToTdbSeconds(std::move(time)); + SpiceManager::ref().getETfromDate(std::move(time), _time); } std::string Time::currentTimeUTC() const { - return SpiceManager::ref().convertTdbSecondsToString(_time, "YYYY-MM-DDTHR:MN:SC.#####"); + std::string date; + SpiceManager::ref().getDateFromET(_time, date); + return std::move(date); } scripting::ScriptEngine::LuaLibrary Time::luaLibrary() { scripting::ScriptEngine::LuaLibrary timeLibrary = {