diff --git a/isis/src/base/objs/Spice/Spice.cpp b/isis/src/base/objs/Spice/Spice.cpp index 142bb7a0f2..7f57b208f7 100644 --- a/isis/src/base/objs/Spice/Spice.cpp +++ b/isis/src/base/objs/Spice/Spice.cpp @@ -80,7 +80,7 @@ namespace Isis { Pvl &lab = *cube.label(); PvlGroup kernels = lab.findGroup("Kernels", Pvl::Traverse); bool hasTables = (kernels["TargetPosition"][0] == "Table"); - init(cube, !hasTables); + init(lab, !hasTables); } /** @@ -90,7 +90,18 @@ namespace Isis { * @param noTables Indicates the use of tables. */ Spice::Spice(Cube &cube, bool noTables) { - init(cube, noTables); + init(*cube.label(), noTables); + } + + + /** + * Constructs a Spice Object + * + * @param lab Isis Cube Pvl Lavel + * @param isd ALE Json ISD + */ + Spice::Spice(Pvl &lab, json isd) { + init(lab, true, isd); } /** @@ -106,9 +117,9 @@ namespace Isis { * @internal * @history 2011-02-08 Jeannie Walldren - Initialize pointers to null. */ - void Spice::init(Cube &cube, bool noTables) { + void Spice::init(Pvl &lab, bool noTables, json isd) { NaifStatus::CheckErrors(); - + // Initialize members m_solarLongitude = new Longitude; m_et = NULL; @@ -142,8 +153,6 @@ namespace Isis { // m_sky = false; - Pvl &lab = *cube.label(); - // Get the kernel group and load main kernels PvlGroup kernels = lab.findGroup("Kernels", Pvl::Traverse); @@ -166,7 +175,6 @@ namespace Isis { m_usingNaif = !lab.hasObject("NaifKeywords") || noTables; m_usingAle = false; - json isd; // Modified to load planetary ephemeris SPKs before s/c SPKs since some // missions (e.g., MESSENGER) may augment the s/c SPK with new planet // ephemerides. (2008-02-27 (KJB)) @@ -178,15 +186,18 @@ namespace Isis { QString msg = "Falling back to ISIS generation of nadir pointing"; throw IException(IException::Programmer, msg, _FILEINFO_); } + + if (isd == NULL){ + // try using ALE + std::ostringstream kernel_pvl; + kernel_pvl << kernels; - // try using ALE - std::ostringstream kernel_pvl; - kernel_pvl << kernels; + json props; + props["kernels"] = kernel_pvl.str(); - json props; - props["kernels"] = kernel_pvl.str(); + isd = ale::load(lab.fileName().toStdString(), props.dump(), "isis"); + } - isd = ale::load(cube.fileName().toStdString(), props.dump(), "isis"); json aleNaifKeywords = isd["NaifKeywords"]; m_naifKeywords = new PvlObject("NaifKeywords", aleNaifKeywords); @@ -230,7 +241,6 @@ namespace Isis { load(kernels["Extra"], noTables); } } - // Moved the construction of the Target after the NAIF kenels have been loaded or the // NAIF keywords have been pulled from the cube labels, so we can find target body codes @@ -367,7 +377,7 @@ namespace Isis { m_sunPosition = new SpicePosition(10, m_target->naifBodyCode()); // Check to see if we have nadir pointing that needs to be computed & - // See if we have table blobs to load + // See if we have table blobs to load if (kernels["TargetPosition"][0].toUpper() == "TABLE") { Table t("SunPosition", lab.fileName(), lab); m_sunPosition->LoadCache(t); @@ -387,7 +397,6 @@ namespace Isis { m_bodyRotation->LoadCache(isd["BodyRotation"]); solarLongitude(); } - // We can't assume InstrumentPointing & InstrumentPosition exist, old // files may be around with the old keywords, SpacecraftPointing & // SpacecraftPosition. The old keywords were in existance before the @@ -433,8 +442,7 @@ namespace Isis { } NaifStatus::CheckErrors(); - } - + } /** * Loads/furnishes NAIF kernel(s) @@ -1338,6 +1346,17 @@ namespace Isis { QString Spice::targetName() const { return m_target->name(); } + + + double Spice::sunToBodyDist() const { + std::vector sunPosition = m_sunPosition->Coordinate(); + std::vector bodyRotation = m_bodyRotation->Matrix(); + + double sunPosFromTarget[3]; + mxv_c(&bodyRotation[0], &sunPosition[0], sunPosFromTarget); + + return vnorm_c(sunPosFromTarget); + } /** @@ -1354,7 +1373,7 @@ namespace Isis { return; } - if (m_usingAle){ + if (m_usingAle) { double og_time = m_bodyRotation->EphemerisTime(); m_bodyRotation->SetEphemerisTime(et.Et()); m_sunPosition->SetEphemerisTime(et.Et()); diff --git a/isis/src/base/objs/Spice/Spice.h b/isis/src/base/objs/Spice/Spice.h index e265068027..1ced98ccd6 100644 --- a/isis/src/base/objs/Spice/Spice.h +++ b/isis/src/base/objs/Spice/Spice.h @@ -296,6 +296,7 @@ namespace Isis { // constructors Spice(Cube &cube); Spice(Cube &cube, bool noTables); + Spice(Pvl &lab, nlohmann::json); // destructor virtual ~Spice(); @@ -306,6 +307,8 @@ namespace Isis { void instrumentBodyFixedPosition(double p[3]) const; void sunPosition(double p[3]) const; double targetCenterDistance() const; + double sunToBodyDist() const; + Longitude solarLongitude(); void instrumentBodyFixedVelocity(double v[3]) const; iTime time() const; @@ -392,8 +395,8 @@ namespace Isis { // Don't allow copies Spice(const Spice &other); Spice &operator=(const Spice &other); - - void init(Cube &cube, bool noTables); + + void init(Pvl &pvl, bool noTables, nlohmann::json isd = NULL); void load(PvlKeyword &key, bool notab); void computeSolarLongitude(iTime et); diff --git a/isis/src/lro/apps/lronaccal/main.cpp b/isis/src/lro/apps/lronaccal/main.cpp index f6bc844b7c..3048bf76d8 100644 --- a/isis/src/lro/apps/lronaccal/main.cpp +++ b/isis/src/lro/apps/lronaccal/main.cpp @@ -196,33 +196,45 @@ void IsisMain() { Pvl radPvl(radFileName.expanded()); if(g_iof) { + iTime startTime((QString) inst["StartTime"]); + try { - iTime startTime((QString) inst["StartTime"]); - double etStart = startTime.Et(); - // Get the distance between the Moon and the Sun at the given time in - // Astronomical Units (AU) - QString bspKernel1 = p.MissionData("lro", "/kernels/tspk/moon_pa_de421_1900-2050.bpc", false); - QString bspKernel2 = p.MissionData("lro", "/kernels/tspk/de421.bsp", false); - furnsh_c(bspKernel1.toLatin1().data()); - furnsh_c(bspKernel2.toLatin1().data()); - QString pckKernel1 = p.MissionData("base", "/kernels/pck/pck?????.tpc", true); - QString pckKernel2 = p.MissionData("lro", "/kernels/pck/moon_080317.tf", false); - QString pckKernel3 = p.MissionData("lro", "/kernels/pck/moon_assoc_me.tf", false); - furnsh_c(pckKernel1.toLatin1().data()); - furnsh_c(pckKernel2.toLatin1().data()); - furnsh_c(pckKernel3.toLatin1().data()); - double sunpos[6], lt; - spkezr_c("sun", etStart, "MOON_ME", "LT+S", "MOON", sunpos, <); - g_solarDistance = vnorm_c(sunpos) / KM_PER_AU; - unload_c(bspKernel1.toLatin1().data()); - unload_c(bspKernel2.toLatin1().data()); - unload_c(pckKernel1.toLatin1().data()); - unload_c(pckKernel2.toLatin1().data()); - unload_c(pckKernel3.toLatin1().data()); + Camera *cam; + cam = iCube->camera(); + cam->setTime(startTime); + g_solarDistance = cam->sunToBodyDist() / KM_PER_AU; + } catch(IException &e) { - QString msg = "Unable to find the necessary SPICE kernels for converting to IOF"; - throw IException(e, IException::User, msg, _FILEINFO_); + // Failed to instantiate a camera, try furnishing kernels directly + try { + + double etStart = startTime.Et(); + // Get the distance between the Moon and the Sun at the given time in + // Astronomical Units (AU) + QString bspKernel1 = p.MissionData("lro", "/kernels/tspk/moon_pa_de421_1900-2050.bpc", false); + QString bspKernel2 = p.MissionData("lro", "/kernels/tspk/de421.bsp", false); + furnsh_c(bspKernel1.toLatin1().data()); + furnsh_c(bspKernel2.toLatin1().data()); + QString pckKernel1 = p.MissionData("base", "/kernels/pck/pck?????.tpc", true); + QString pckKernel2 = p.MissionData("lro", "/kernels/pck/moon_080317.tf", false); + QString pckKernel3 = p.MissionData("lro", "/kernels/pck/moon_assoc_me.tf", false); + furnsh_c(pckKernel1.toLatin1().data()); + furnsh_c(pckKernel2.toLatin1().data()); + furnsh_c(pckKernel3.toLatin1().data()); + double sunpos[6], lt; + spkezr_c("sun", etStart, "MOON_ME", "LT+S", "MOON", sunpos, <); + g_solarDistance = vnorm_c(sunpos) / KM_PER_AU; + unload_c(bspKernel1.toLatin1().data()); + unload_c(bspKernel2.toLatin1().data()); + unload_c(pckKernel1.toLatin1().data()); + unload_c(pckKernel2.toLatin1().data()); + unload_c(pckKernel3.toLatin1().data()); + } + catch(IException &e) { + QString msg = "Unable to find the necessary SPICE kernels for converting to IOF"; + throw IException(e, IException::User, msg, _FILEINFO_); + } } g_iofLeft = radPvl["IOF_LEFT"]; g_iofRight = radPvl["IOF_RIGHT"]; diff --git a/isis/tests/SpiceTests.cpp b/isis/tests/SpiceTests.cpp new file mode 100644 index 0000000000..1f84c99b2f --- /dev/null +++ b/isis/tests/SpiceTests.cpp @@ -0,0 +1,194 @@ +#include "Spice.h" +#include "IException.h" +#include "Pvl.h" +#include "Distance.h" +#include "iTime.h" +#include "Longitude.h" + +#include +#include + +#include +using json = nlohmann::json; + +#include "gmock/gmock.h" + +using namespace Isis; + +class ConstVelIsd : public ::testing::Test { + protected: + json constVelIsdStr; + Pvl isisLabel; + + void SetUp() { + constVelIsdStr = json::parse(R"( + {"CameraVersion": 2, + "NaifKeywords": { + "BODY301_RADII": [ 1000, 2000, 3000 ], + "BODY_FRAME_CODE": 31001, + "BODY_CODE": 301, + "INS-85600_FOCAL_LENGTH" : 699.62, + "INS-85600_CK_FRAME_ID": -85000, + "FRAME_-85600_NAME": "LRO_LROCNACL" + }, + "InstrumentPointing": { + "TimeDependentFrames": [-85600, -85000, 1], + "CkTableStartTime": 100, + "CkTableEndTime": 100.1, + "CkTableOriginalSize": 2, + "EphemerisTimes": [ + 100, + 100.1 + ], + "Quaternions": [ + [0.0, -0.660435174378928, 0, 0.750883067090392], + [0.0, -0.660435174378928, 0, 0.750883067090392] + ], + "AngularVelocity": [ + [0, 0, 0], + [0, 0, 0] + ], + "ConstantFrames": [-85600], + "ConstantRotation": [1, 0, 0, 0, 1, 0, 0, 0, 1] + }, + "BodyRotation": { + "TimeDependentFrames": [31006, 1], + "CkTableStartTime": 100, + "CkTableEndTime": 100.1, + "CkTableOriginalSize": 2, + "EphemerisTimes": [ + 100, + 100.1 + ], + "Quaternions": [ + [ 0, 0.8509035, 0, 0.525322 ], + [ 0, 0.8509035, 0, 0.525322 ] + ], + "AngularVelocity": [ + [0, 0, 0], + [0, 0, 0] + ], + "ConstantFrames": [31001, 31007, 31006], + "ConstantRotation": [-0.4480736, 0, 0.8939967, 0, 1, 0, -0.8939967, 0, -0.4480736] + }, + "InstrumentPosition": { + "SpkTableStartTime": 100, + "SpkTableEndTime": 100.1, + "SpkTableOriginalSize": 2, + "EphemerisTimes": [ + 100, + 100.1 + ], + "Positions": [ + [1000, 0, 0], + [1000, 0, 0] + ], + "Velocities": [ + [0, 0, 0], + [0, 0, 0] + ] + }, + "SunPosition": { + "SpkTableStartTime": 100, + "SpkTableEndTime": 100.1, + "SpkTableOriginalSize": 2, + "EphemerisTimes": [ + 100, + 100.1 + ], + "Positions": [ + [0, 20, 0] + ], + "Velocities": [ + [10,10,10] + ] + } + })"); + + std::istringstream isisLabelStr(R"( + Object = IsisCube + Object = Core + StartByte = 65537 + Format = Tile + TileSamples = 128 + TileLines = 128 + + Group = Dimensions + Samples = 126 + Lines = 126 + Bands = 2 + End_Group + + Group = Pixels + Type = Real + ByteOrder = Lsb + Base = 0.0 + Multiplier = 1.0 + End_Group + End_Object + + Group = Kernels + NaifFrameCode = 310019 + LeapSecond = NULL + TargetAttitudeShape = NULL + TargetPosition = NULL + InstrumentPointing = NULL + Instrument = NULL + SpacecraftClock = NULL + InstrumentPosition = NULL + InstrumentAddendum = NULL + ShapeModel = NULL + InstrumentPositionQuality = NULL + InstrumentPointingQuality = NULL + CameraVersion = NULL + End_Group + + Group = Instrument + SpacecraftName = NULL + InstrumentId = NULL + TargetName = NULL + End_Group + End_Object + + Object = Label + Bytes = 65536 + End_Object + + Object = History + Name = IsisCube + StartByte = 196609 + Bytes = 695 + End_Object + End + )"); + + isisLabelStr >> isisLabel; + + } +}; + +TEST_F(ConstVelIsd, TestSpiceFromIsd) { + Spice testSpice(isisLabel, constVelIsdStr); + testSpice.setTime(100); + + EXPECT_DOUBLE_EQ(testSpice.time().Et(), 100); + + EXPECT_DOUBLE_EQ(testSpice.getDouble("INS-85600_FOCAL_LENGTH"), 699.62); + EXPECT_STREQ(testSpice.getString("FRAME_-85600_NAME").toStdString().c_str(), "LRO_LROCNACL"); + EXPECT_EQ(testSpice.getInteger("INS-85600_CK_FRAME_ID"), -85000); + + Distance radii[3]; + testSpice.radii(radii); + EXPECT_DOUBLE_EQ(radii[0].kilometers(), 1000); + EXPECT_DOUBLE_EQ(radii[1].kilometers(), 2000); + EXPECT_DOUBLE_EQ(radii[2].kilometers(), 3000); + + EXPECT_DOUBLE_EQ(testSpice.solarLongitude().positiveEast(), 3.1415926535897931); + +} + +TEST_F(ConstVelIsd, SunToBodyDist) { + Spice testSpice(isisLabel, constVelIsdStr); + EXPECT_DOUBLE_EQ(testSpice.sunToBodyDist(), 20); +} +