diff --git a/isis/src/base/apps/appjit/LineScanCameraRotation.cpp b/isis/src/base/apps/appjit/LineScanCameraRotation.cpp index 9de4057b1b..245429100a 100644 --- a/isis/src/base/apps/appjit/LineScanCameraRotation.cpp +++ b/isis/src/base/apps/appjit/LineScanCameraRotation.cpp @@ -5,6 +5,8 @@ #include #include +#include + #include "Cube.h" #include "LineScanCameraRotation.h" #include "Quaternion.h" @@ -121,6 +123,7 @@ namespace Isis { SpiceRotation *prot = p_spi->bodyRotation(); SpiceRotation *crot = p_spi->instrumentRotation(); + std::vector rotationCache; for(std::vector::iterator i = p_cacheTime.begin(); i < p_cacheTime.end(); i++) { double et = *i; @@ -155,8 +158,23 @@ namespace Isis { // Put CI into parent cache to use the parent class methods on it mxmt_c((SpiceDouble( *)[3]) &CI[0], (SpiceDouble( *)[3]) &IB[0], (SpiceDouble( *)[3]) &CI[0]); - p_cache.push_back(CI); + rotationCache.push_back(ale::Rotation(CI)); + } + + if (m_orientation) { + delete m_orientation; + m_orientation = NULL; } + + if (ConstantRotation().size() > 1) { + m_orientation = new ale::Orientations(rotationCache, p_cacheTime, std::vector(), + ale::Rotation(ConstantMatrix()), ConstantFrameChain(), TimeFrameChain()); + } + else { + m_orientation = new ale::Orientations(rotationCache, p_cacheTime, std::vector(), + ale::Rotation(1,0,0,0), ConstantFrameChain(), TimeFrameChain()); + } + p_cachesLoaded = true; SetSource(Memcache); @@ -185,9 +203,6 @@ namespace Isis { throw IException(IException::Programmer, msg, _FILEINFO_); } - // Clear existing matrices from cache - p_cache.clear(); - // Create polynomials fit to angles & use to reload cache Isis::PolynomialUnivariate function1(p_degree); Isis::PolynomialUnivariate function2(p_degree); @@ -218,6 +233,7 @@ namespace Isis { std::vector CJ; CJ.resize(9); + std::vector rotationCache; for(std::vector::size_type pos = 0; pos < p_cacheTime.size(); pos++) { double et = p_cacheTime.at(pos); rtime = (et - GetBaseTime()) / GetTimeScale(); @@ -242,7 +258,21 @@ namespace Isis { mxm_c((SpiceDouble( *)[3]) & (p_cacheIB.at(pos))[0], (SpiceDouble( *)[3]) & (prot->Matrix())[0], IJ); mxm_c(CI, IJ, (SpiceDouble( *)[3]) &CJ[0]); - p_cache.push_back(CJ); // J2000 to constant frame + rotationCache.push_back(ale::Rotation(CJ)); + } + + if (m_orientation) { + delete m_orientation; + m_orientation = NULL; + } + + if (ConstantRotation().size() > 1) { + m_orientation = new ale::Orientations(rotationCache, p_cacheTime, std::vector(), + ale::Rotation(ConstantMatrix()), ConstantFrameChain(), TimeFrameChain()); + } + else { + m_orientation = new ale::Orientations(rotationCache, p_cacheTime, std::vector(), + ale::Rotation(1,0,0,0), ConstantFrameChain(), TimeFrameChain()); } // Set source to cache to get updated values diff --git a/isis/src/base/apps/appjit/LineScanCameraRotation.h b/isis/src/base/apps/appjit/LineScanCameraRotation.h index 44b402d213..45234f94b2 100644 --- a/isis/src/base/apps/appjit/LineScanCameraRotation.h +++ b/isis/src/base/apps/appjit/LineScanCameraRotation.h @@ -103,11 +103,9 @@ namespace Isis { class LineScanCameraRotation : public Isis::SpiceRotation { public: //! Constructors -// LineScanCameraRotation( int frameCode, SpiceRotation *crot, SpiceRotation *prot, SpicePosition *spos ); LineScanCameraRotation(int frameCode, Isis::Cube &cube, std::vector timeCache, double tol); //! Destructor -// virtual ~LineScanCameraRotation() { }; virtual ~LineScanCameraRotation(); void LoadCache(); diff --git a/isis/src/base/objs/CameraPointInfo/CameraPointInfo.truth b/isis/src/base/objs/CameraPointInfo/CameraPointInfo.truth index 09a4c92a81..fada81e861 100644 --- a/isis/src/base/objs/CameraPointInfo/CameraPointInfo.truth +++ b/isis/src/base/objs/CameraPointInfo/CameraPointInfo.truth @@ -6,8 +6,8 @@ Group = GroundPoint Declination = 67.288137235407 PlanetocentricLatitude = -85.539935681585 PlanetographicLatitude = -85.539935681585 - PositiveEast360Longitude = 27.089555271673 - PositiveEast180Longitude = 27.089555271673 + PositiveEast360Longitude = 27.089555271672 + PositiveEast180Longitude = 27.089555271672 PositiveWest360Longitude = 332.91044472833 PositiveWest180Longitude = -27.089555271672 BodyFixedCoordinate = (120.6493939079, 61.711663528734, @@ -21,13 +21,13 @@ Group = GroundPoint ObliqueSampleResolution = 187.44583818806 # Spacecraft Information - SpacecraftPosition = (216.77599432924, 54.260221515166, + SpacecraftPosition = (216.77599432924, 54.260221515165, -2462.1104393388) SpacecraftAzimuth = 38.331 SlantDistance = 731.11938668312 TargetCenterDistance = 2472.2305351357 SubSpacecraftLatitude = -84.813985589411 - SubSpacecraftLongitude = 14.052715974499 + SubSpacecraftLongitude = 14.052715974498 SpacecraftAltitude = 735.29826910549 OffNadirAngle = 3.124 SubSpacecraftGroundAzimuth = 296.906 @@ -84,13 +84,13 @@ Group = GroundPoint ObliqueSampleResolution = 187.61662252249 # Spacecraft Information - SpacecraftPosition = (216.77599432924, 54.260221515166, + SpacecraftPosition = (216.77599432924, 54.260221515165, -2462.1104393388) SpacecraftAzimuth = 284.604 SlantDistance = 733.84767049682 TargetCenterDistance = 2472.2305351357 SubSpacecraftLatitude = -84.813985589411 - SubSpacecraftLongitude = 14.052715974499 + SubSpacecraftLongitude = 14.052715974498 SpacecraftAltitude = 735.29826910549 OffNadirAngle = 0.773 SubSpacecraftGroundAzimuth = 195.221 diff --git a/isis/src/base/objs/SpiceRotation/SpiceRotation.cpp b/isis/src/base/objs/SpiceRotation/SpiceRotation.cpp index d21091e021..6507d47d1e 100644 --- a/isis/src/base/objs/SpiceRotation/SpiceRotation.cpp +++ b/isis/src/base/objs/SpiceRotation/SpiceRotation.cpp @@ -73,6 +73,7 @@ namespace Isis { p_fullCacheSize = 0; m_frameType = UNKNOWN; m_tOrientationAvailable = false; + m_orientation = NULL; } @@ -112,6 +113,7 @@ namespace Isis { p_fullCacheSize = 0; m_frameType = DYN; m_tOrientationAvailable = false; + m_orientation = NULL; // Determine the axis for the velocity vector QString key = "INS" + toString(frameCode) + "_TRANSX"; @@ -140,8 +142,6 @@ namespace Isis { */ SpiceRotation::SpiceRotation(const SpiceRotation &rotToCopy) { p_cacheTime = rotToCopy.p_cacheTime; - p_cache = rotToCopy.p_cache; - p_cacheAv = rotToCopy.p_cacheAv; p_av = rotToCopy.p_av; p_degree = rotToCopy.p_degree; p_axis1 = rotToCopy.p_axis1; @@ -181,6 +181,13 @@ namespace Isis { p_hasAngularVelocity = rotToCopy.p_hasAngularVelocity; m_frameType = rotToCopy.m_frameType; + if (rotToCopy.m_orientation) { + m_orientation = new ale::Orientations; + *m_orientation = *rotToCopy.m_orientation; + } + else { + m_orientation = NULL; + } } @@ -188,6 +195,10 @@ namespace Isis { * Destructor for SpiceRotation object. */ SpiceRotation::~SpiceRotation() { + if (m_orientation) { + delete m_orientation; + m_orientation = NULL; + } } @@ -280,7 +291,7 @@ namespace Isis { } // Set the quaternion for this rotation -// p_quaternion.Set ( p_CJ ); +// p_quaternion.Set ( p_CJ ); } @@ -300,7 +311,7 @@ namespace Isis { * @return @b bool Indicates whether this rotation is cached. */ bool SpiceRotation::IsCached() const { - return (p_cache.size() > 0); + return (m_orientation != NULL); } @@ -361,6 +372,11 @@ namespace Isis { p_fullCacheEndTime = endTime; p_fullCacheSize = size; + if (m_orientation != NULL) { + delete m_orientation; + m_orientation = NULL; + } + // Make sure the constant frame is loaded. This method also does the frame trace. if (p_timeFrames.size() == 0) InitConstantRotation(startTime); @@ -373,12 +389,29 @@ namespace Isis { int cacheSize = p_cacheTime.size(); // Loop and load the cache + std::vector rotationCache; + std::vector< std::vector > cache; + std::vector avCache; for (int i = 0; i < cacheSize; i++) { double et = p_cacheTime[i]; SetEphemerisTime(et); - p_cache.push_back(p_CJ); - if (p_hasAngularVelocity) p_cacheAv.push_back(p_av); + rotationCache.push_back(ale::Rotation(p_CJ)); + cache.push_back(p_CJ); + + if (p_hasAngularVelocity) { + avCache.push_back(ale::Vec3d(p_av)); + } } + + if (p_TC.size() > 1) { + m_orientation = new ale::Orientations(rotationCache, p_cacheTime, avCache, + ale::Rotation(p_TC), p_constantFrames, p_timeFrames); + } + else { + m_orientation = new ale::Orientations(rotationCache, p_cacheTime, avCache, + ale::Rotation(1,0,0,0), p_constantFrames, p_timeFrames); + } + p_source = Memcache; // Downsize already loaded caches (both time and quats) @@ -422,11 +455,14 @@ namespace Isis { p_timeFrames.clear(); p_TC.clear(); - p_cache.clear(); p_cacheTime.clear(); - p_cacheAv.clear(); p_hasAngularVelocity = false; m_frameType = CK; + + if (m_orientation) { + delete m_orientation; + m_orientation = NULL; + } // Load the full cache time information from the label if available p_fullCacheStartTime = isdRot["ck_table_start_time"].get(); @@ -435,33 +471,40 @@ namespace Isis { p_cacheTime = isdRot["ephemeris_times"].get>(); p_timeFrames = isdRot["time_dependent_frames"].get>(); + std::vector rotationCache; for (auto it = isdRot["quaternions"].begin(); it != isdRot["quaternions"].end(); it++) { - std::vector quat = {it->at(0).get(), it->at(1).get(), it->at(2).get(), it->at(3).get()}; - Quaternion q(quat); - std::vector CJ = q.ToMatrix(); - p_cache.push_back(CJ); + std::vector quat = {it->at(0).get(), it->at(1).get(), it->at(2).get(), it->at(3).get()}; + Quaternion q(quat); + std::vector CJ = q.ToMatrix(); + rotationCache.push_back(ale::Rotation(CJ)); } + std::vector avCache; if (isdRot["angular_velocities"].size() != 0) { for (auto it = isdRot["angular_velocities"].begin(); it != isdRot["angular_velocities"].end(); it++) { - std::vector av = {it->at(0).get(), it->at(1).get(), it->at(2).get()}; - p_cacheAv.push_back(av); + std::vector av = {it->at(0).get(), it->at(1).get(), it->at(2).get()}; + avCache.push_back(ale::Vec3d(av)); } p_hasAngularVelocity = true; } bool hasConstantFrames = isdRot.find("constant_frames") != isdRot.end(); + if (hasConstantFrames) { p_constantFrames = isdRot["constant_frames"].get>(); - p_TC = isdRot["constant_rotation"].get>(); - + p_TC = isdRot["constant_rotation"].get>(); + m_orientation = new ale::Orientations(rotationCache, p_cacheTime, avCache, + ale::Rotation(p_TC), p_constantFrames, p_timeFrames); } else { p_TC.resize(9); ident_c((SpiceDouble( *)[3]) &p_TC[0]); + m_orientation = new ale::Orientations(rotationCache, p_cacheTime, avCache, + ale::Rotation(1,0,0,0), p_constantFrames, p_timeFrames); } + p_source = Memcache; SetEphemerisTime(p_cacheTime[0]); } @@ -495,11 +538,15 @@ namespace Isis { // Clear any existing cached data to make it reentrant (KJB 2011-07-20). p_timeFrames.clear(); p_TC.clear(); - p_cache.clear(); p_cacheTime.clear(); - p_cacheAv.clear(); + p_hasAngularVelocity = false; + if (m_orientation) { + delete m_orientation; + m_orientation = NULL; + } + // Load the constant and time-based frame traces and the constant rotation if (table.Label().hasKeyword("TimeDependentFrames")) { PvlKeyword labelTimeFrames = table.Label()["TimeDependentFrames"]; @@ -559,6 +606,9 @@ namespace Isis { // establish the type of cache and then use the appropriate loop. // list table of quaternion and time + + std::vector rotationCache; + std::vector avCache; if (recFields == 5) { for (int r = 0; r < table.Records(); r++) { TableRecord &rec = table[r]; @@ -575,9 +625,18 @@ namespace Isis { Quaternion q(j2000Quat); std::vector CJ = q.ToMatrix(); - p_cache.push_back(CJ); + rotationCache.push_back(ale::Rotation(CJ)); + p_cacheTime.push_back((double)rec[4]); } + if (p_TC.size() > 1) { + m_orientation = new ale::Orientations(rotationCache, p_cacheTime, avCache, + ale::Rotation(p_TC), p_constantFrames, p_timeFrames); + } + else { + m_orientation = new ale::Orientations(rotationCache, p_cacheTime, avCache, + ale::Rotation(1,0,0,0), p_constantFrames, p_timeFrames); + } p_source = Memcache; } @@ -599,17 +658,25 @@ namespace Isis { Quaternion q(j2000Quat); std::vector CJ = q.ToMatrix(); - p_cache.push_back(CJ); + rotationCache.push_back(ale::Rotation(CJ)); std::vector av; av.push_back((double)rec[4]); av.push_back((double)rec[5]); av.push_back((double)rec[6]); - p_cacheAv.push_back(av); - + avCache.push_back(ale::Vec3d(av)); p_cacheTime.push_back((double)rec[7]); p_hasAngularVelocity = true; } + + if (p_TC.size() > 1) { + m_orientation = new ale::Orientations(rotationCache, p_cacheTime, avCache, + ale::Rotation(p_TC), p_constantFrames, p_timeFrames); + } + else { + m_orientation = new ale::Orientations(rotationCache, p_cacheTime, avCache, + ale::Rotation(1,0,0,0), p_constantFrames, p_timeFrames); + } p_source = Memcache; } @@ -638,7 +705,9 @@ namespace Isis { SetPolynomial(coeffAng1, coeffAng2, coeffAng3); p_source = PolyFunction; if (degree > 0) p_hasAngularVelocity = true; - if (degree == 0 && p_cacheAv.size() > 0) p_hasAngularVelocity = true; + if (degree == 0 && m_orientation->getAngularVelocities().size() > 0) { + p_hasAngularVelocity = true; + } } else { QString msg = "Expecting either three, five, or eight fields in the SpiceRotation table"; @@ -661,15 +730,11 @@ namespace Isis { double et = p_et; p_et = -DBL_MAX; + std::vector rotationCache; + std::vector avCache; if (p_source == PolyFunction) { // Clear existing matrices from cache p_cacheTime.clear(); - p_cache.clear(); - - // Clear the angular velocity cache if we can calculate it instead. It can't be calculated - // for functions of degree 0 (framing cameras), so keep the original av. It is better than - // nothing. - if (p_degree > 0 && p_cacheAv.size() > 1) p_cacheAv.clear(); // Load the time cache first p_minimizeCache = No; @@ -679,25 +744,23 @@ namespace Isis { // Load the matrix and av caches for (std::vector::size_type pos = 0; pos < p_cacheTime.size(); pos++) { SetEphemerisTime(p_cacheTime.at(pos)); - p_cache.push_back(p_CJ); - p_cacheAv.push_back(p_av); + rotationCache.push_back(ale::Rotation(p_CJ)); + avCache.push_back(ale::Vec3d(p_av)); } } else { // Load the matrix for the single updated time instance SetEphemerisTime(p_cacheTime[0]); - p_cache.push_back(p_CJ); + rotationCache.push_back(ale::Rotation(p_CJ)); + avCache.push_back(ale::Vec3d(p_av)); } } else if (p_source == PolyFunctionOverSpice) { SpiceRotation tempRot(*this); - std::vector::size_type maxSize = p_fullCacheSize; // Clear the existing caches - p_cache.clear(); p_cacheTime.clear(); - p_cacheAv.clear(); // Reload the time cache first p_minimizeCache = No; @@ -705,8 +768,11 @@ namespace Isis { for (std::vector::size_type pos = 0; pos < maxSize; pos++) { tempRot.SetEphemerisTime(p_cacheTime.at(pos)); - p_cache.push_back(tempRot.TimeBasedMatrix()); - if (p_hasAngularVelocity) p_cacheAv.push_back(tempRot.AngularVelocity()); + std::vector CJ = tempRot.TimeBasedMatrix(); + rotationCache.push_back(ale::Rotation(CJ)); + if (p_hasAngularVelocity){ + avCache.push_back(ale::Vec3d(tempRot.AngularVelocity())); + } } } else { //(p_source < PolyFunction) @@ -714,6 +780,20 @@ namespace Isis { throw IException(IException::Programmer, msg, _FILEINFO_); } + if (m_orientation) { + delete m_orientation; + m_orientation = NULL; + } + + if (p_TC.size() > 1) { + m_orientation = new ale::Orientations(rotationCache, p_cacheTime, avCache, + ale::Rotation(p_TC), p_constantFrames, p_timeFrames); + } + else { + m_orientation = new ale::Orientations(rotationCache, p_cacheTime, avCache, + ale::Rotation(1,0,0,0), p_constantFrames, p_timeFrames); + } + // Set source to cache and reset current et // Make sure source is Memcache now p_source = Memcache; @@ -813,18 +893,30 @@ namespace Isis { record += t; Table table(tableName, record); - for (int i = 0; i < (int)p_cache.size(); i++) { - Quaternion q(p_cache[i]); - std::vector v = q.GetQuaternion(); - record[0] = v[0]; - record[1] = v[1]; - record[2] = v[2]; - record[3] = v[3]; + std::vector rots = m_orientation->getRotations(); + std::vector angularVelocities = m_orientation->getAngularVelocities(); + for (int i = 0; i < (int) p_cacheTime.size(); i++) { + std::vector quat = rots[i].toQuaternion(); + + // If the first component is less than zero, multiply the whole quaternion by -1. This + // matches NAIF. + if (quat[0] < 0) { + quat[0] = -1 * quat[0]; + quat[1] = -1 * quat[1]; + quat[2] = -1 * quat[2]; + quat[3] = -1 * quat[3]; + } - if (p_hasAngularVelocity) { - record[4] = p_cacheAv[i][0]; - record[5] = p_cacheAv[i][1]; - record[6] = p_cacheAv[i][2]; + record[0] = quat[0]; + record[1] = quat[1]; + record[2] = quat[2]; + record[3] = quat[3]; + + if (angularVelocities.size() > 0 && p_hasAngularVelocity ) { + ale::Vec3d angularVelocity = angularVelocities[i]; + record[4] = angularVelocity.x; + record[5] = angularVelocity.y; + record[6] = angularVelocity.z; } record[timePos] = p_cacheTime[i]; @@ -1222,7 +1314,7 @@ namespace Isis { * Set the rotation angles (phi, delta, and w) for the current time to define the * time-based matrix CJ. This method was created for unitTests and should not * be used otherwise. It only works for cached data with a cache size of 1. - * + * * @param[in] angles The angles defining the rotation (phi, delta, and w) in radians * @param[in] axis3 The rotation axis for the third angle * @param[in] axis2 The rotation axis for the second angle @@ -1230,7 +1322,22 @@ namespace Isis { */ void SpiceRotation::SetAngles(std::vector angles, int axis3, int axis2, int axis1) { eul2m_c(angles[2], angles[1], angles[0], axis3, axis2, axis1, (SpiceDouble (*)[3]) &(p_CJ[0])); - p_cache[0] = p_CJ; + + if (m_orientation) { + delete m_orientation; + m_orientation = NULL; + } + std::vector rotationCache; + rotationCache.push_back(ale::Rotation(p_CJ)); + if (p_TC.size() > 1) { + m_orientation = new ale::Orientations(rotationCache, p_cacheTime, std::vector(), + ale::Rotation(p_TC), p_constantFrames, p_timeFrames); + } + else { + m_orientation = new ale::Orientations(rotationCache, p_cacheTime, std::vector(), + ale::Rotation(1,0,0,0), p_constantFrames, p_timeFrames); + } + // Reset to get the new values p_et = -DBL_MAX; SetEphemerisTime(p_et); @@ -1629,10 +1736,11 @@ namespace Isis { } // Adjust degree of polynomial on available data - if (p_cache.size() == 1) { + int size = m_orientation->getRotations().size(); + if (size == 1) { p_degree = 0; } - else if (p_cache.size() == 2) { + else if (size == 2) { p_degree = 1; } @@ -1648,7 +1756,7 @@ namespace Isis { Isis::PolynomialUnivariate function1(p_degree); //!< Basis function fit to 1st rotation angle Isis::PolynomialUnivariate function2(p_degree); //!< Basis function fit to 2nd rotation angle Isis::PolynomialUnivariate function3(p_degree); //!< Basis function fit to 3rd rotation angle - // + LeastSquares *fitAng1 = new LeastSquares(function1); LeastSquares *fitAng2 = new LeastSquares(function2); LeastSquares *fitAng3 = new LeastSquares(function3); @@ -1657,7 +1765,7 @@ namespace Isis { ComputeBaseTime(); std::vector time; - if (p_cache.size() == 1) { + if (size == 1) { double t = p_cacheTime.at(0); SetEphemerisTime(t); std::vector angles = Angles(p_axis3, p_axis2, p_axis1); @@ -1665,8 +1773,8 @@ namespace Isis { coeffAng2.push_back(angles[1]); coeffAng3.push_back(angles[2]); } - else if (p_cache.size() == 2) { -// Load the times and get the corresponding rotation angles + else if (size == 2) { + // Load the times and get the corresponding rotation angles p_degree = 1; double t1 = p_cacheTime.at(0); SetEphemerisTime(t1); @@ -2368,8 +2476,7 @@ namespace Isis { // Multiple ck case, type 5 ck case, or PolyFunctionOverSpice // final step -- downsize loaded cache and reload - if (p_fullCacheSize != (int) p_cache.size()) { - + if (p_fullCacheSize != (int) p_cacheTime.size()) { QString msg = "Full cache size does NOT match cache size in LoadTimeCache -- should never happen"; throw IException(IException::Programmer, msg, _FILEINFO_); @@ -2377,20 +2484,24 @@ namespace Isis { SpiceDouble timeSclkdp[p_fullCacheSize]; SpiceDouble quats[p_fullCacheSize][4]; - double avvs[p_fullCacheSize][3];// Angular velocity vector + double avvs[p_fullCacheSize][3]; // Angular velocity vector // We will treat et as the sclock time and avoid converting back and forth + std::vector fullRotationCache = m_orientation->getRotations(); + std::vector angularVelocities = m_orientation->getAngularVelocities(); for (int r = 0; r < p_fullCacheSize; r++) { timeSclkdp[r] = p_cacheTime[r]; - SpiceDouble CJ[9] = { p_cache[r][0], p_cache[r][1], p_cache[r][2], - p_cache[r][3], p_cache[r][4], p_cache[r][5], - p_cache[r][6], p_cache[r][7], p_cache[r][8] + std::vector rotationMatrix = fullRotationCache[r].toRotationMatrix(); + SpiceDouble CJ[9] = { rotationMatrix[0], rotationMatrix[1], rotationMatrix[2], + rotationMatrix[3], rotationMatrix[4], rotationMatrix[5], + rotationMatrix[6], rotationMatrix[7], rotationMatrix[8] }; m2q_c(CJ, quats[r]); if (p_hasAngularVelocity) { - vequ_c((SpiceDouble *) &p_cacheAv[r][0], avvs[r]); + ale::Vec3d angularVelocity = angularVelocities[r]; + vequ_c((SpiceDouble *) &angularVelocity.x, avvs[r]); } - } + } double cubeStarts = timeSclkdp[0]; //,timsSclkdp[ckBlob.Records()-1] }; double radTol = 0.000000017453; //.000001 degrees Make this instrument dependent TODO @@ -2405,11 +2516,17 @@ namespace Isis { // Clear full cache and load with downsized version p_cacheTime.clear(); - p_cache.clear(); - p_cacheAv.clear(); std::vector av; av.resize(3); + if (m_orientation) { + delete m_orientation; + m_orientation = NULL; + } + + std::vector rotationCache; + std::vector avCache; + for (int r = 0; r < sizOut; r++) { SpiceDouble et; // sct2e_c(spcode, timeSclkdp[r], &et); @@ -2417,11 +2534,19 @@ namespace Isis { p_cacheTime.push_back(et); std::vector CJ(9); q2m_c(quats[r], (SpiceDouble( *)[3]) &CJ[0]); - p_cache.push_back(CJ); + rotationCache.push_back(CJ); vequ_c(avvs[r], (SpiceDouble *) &av[0]); - p_cacheAv.push_back(av); + avCache.push_back(av); } + if (p_TC.size() > 1 ) { + m_orientation = new ale::Orientations(rotationCache, p_cacheTime, avCache, + ale::Rotation(p_TC), p_constantFrames, p_timeFrames); + } + else { + m_orientation = new ale::Orientations(rotationCache, p_cacheTime, std::vector(), + ale::Rotation(1,0,0,0), p_constantFrames, p_timeFrames); + } timeLoaded = true; p_minimizeCache = Done; } @@ -2998,7 +3123,9 @@ namespace Isis { std::vector SpiceRotation::Extrapolate(double timeEt) { NaifStatus::CheckErrors(); - if (!p_hasAngularVelocity) return p_CJ; + if (!p_hasAngularVelocity){ + return p_CJ; + } double diffTime = timeEt - p_et; std::vector CJ(9, 0.0); @@ -3126,54 +3253,26 @@ namespace Isis { * @see SpiceRotation::SetEphemerisTime */ void SpiceRotation::setEphemerisTimeMemcache() { - // If the cache has only one rotation, set it + // If the cache has only one rotation, set it NaifStatus::CheckErrors(); - if (p_cache.size() == 1) { - p_CJ = p_cache[0]; + if (p_cacheTime.size() == 1) { + p_CJ = m_orientation->getRotations()[0].toRotationMatrix(); if (p_hasAngularVelocity) { - p_av = p_cacheAv[0]; + ale::Vec3d av = m_orientation->getAngularVelocities()[0]; + p_av[0] = av.x; + p_av[1] = av.y; + p_av[2] = av.z; } } // Otherwise determine the interval to interpolate else { - std::vector::iterator pos; - pos = upper_bound(p_cacheTime.begin(), p_cacheTime.end(), p_et); - - int cacheIndex; - - if (pos != p_cacheTime.end()) { - cacheIndex = distance(p_cacheTime.begin(), pos); - cacheIndex--; - } - else { - cacheIndex = p_cacheTime.size() - 2; - } - - if (cacheIndex < 0) cacheIndex = 0; - - // Interpolate the rotation - double mult = (p_et - p_cacheTime[cacheIndex]) / - (p_cacheTime[cacheIndex+1] - p_cacheTime[cacheIndex]); - /* Quaternion Q2 (p_cache[cacheIndex+1]); - Quaternion Q1 (p_cache[cacheIndex]);*/ - std::vector CJ2(p_cache[cacheIndex+1]); - std::vector CJ1(p_cache[cacheIndex]); - SpiceDouble J2J1[3][3]; - mtxm_c((SpiceDouble( *)[3]) &CJ2[0], (SpiceDouble( *)[3]) &CJ1[0], J2J1); - SpiceDouble axis[3]; - SpiceDouble angle; - raxisa_c(J2J1, axis, &angle); - SpiceDouble delta[3][3]; - axisar_c(axis, angle * (SpiceDouble)mult, delta); - mxmt_c((SpiceDouble *) &CJ1[0], delta, (SpiceDouble( *) [3]) &p_CJ[0]); + p_CJ = m_orientation->interpolateTimeDep(p_et).toRotationMatrix(); if (p_hasAngularVelocity) { - double v1[3], v2[3]; // Vectors surrounding desired time - vequ_c((SpiceDouble *) &p_cacheAv[cacheIndex][0], v1); - vequ_c((SpiceDouble *) &p_cacheAv[cacheIndex+1][0], v2); - vscl_c((1. - mult), v1, v1); - vscl_c(mult, v2, v2); - vadd_c(v1, v2, (SpiceDouble *) &p_av[0]); + ale::Vec3d av = m_orientation->interpolateAV(p_et); + p_av[0] = av.x; + p_av[1] = av.y; + p_av[2] = av.z; } } NaifStatus::CheckErrors(); @@ -3347,10 +3446,15 @@ namespace Isis { (SpiceDouble( *)[3]) &p_CJ[0]); if (p_hasAngularVelocity) { - if ( p_degree == 0) - p_av = p_cacheAv[0]; - else + if ( p_degree == 0){ + ale::Vec3d av = m_orientation->getAngularVelocities()[0]; + p_av[0] = av.x; + p_av[1] = av.y; + p_av[2] = av.z; + } + else { ComputeAv(); + } } NaifStatus::CheckErrors(); } diff --git a/isis/src/base/objs/SpiceRotation/SpiceRotation.h b/isis/src/base/objs/SpiceRotation/SpiceRotation.h index 8effc6eef7..8525bf3ce7 100644 --- a/isis/src/base/objs/SpiceRotation/SpiceRotation.h +++ b/isis/src/base/objs/SpiceRotation/SpiceRotation.h @@ -25,18 +25,16 @@ #include #include -//#include -//#include -//#include - #include - +#include #include "Angle.h" #include "Table.h" #include "PolynomialUnivariate.h" #include "Quaternion.h" + + #define J2000Code 1 namespace Isis { @@ -426,7 +424,10 @@ namespace Isis { void checkForBinaryPck(); int cacheSize() { - return p_cache.size(); + if (m_orientation) { + return m_orientation->getRotations().size(); + } + return 0; } protected: @@ -438,16 +439,12 @@ namespace Isis { void setEphemerisTimePolyFunctionOverSpice(); void setEphemerisTimePckPolyFunction(); std::vector p_cacheTime; //!< iTime for corresponding rotation - std::vector > p_cache; /**< Cached rotations, stored as - rotation matrix from J2000 - to 1st constant frame (CJ) or - coefficients of polynomial - fit to rotation angles.*/ int p_degree; //!< Degree of fit polynomial for angles int p_axis1; //!< Axis of rotation for angle 1 of rotation int p_axis2; //!< Axis of rotation for angle 2 of rotation int p_axis3; //!< Axis of rotation for angle 3 of rotation - + ale::Orientations *m_orientation; //! Cached orientation information + private: // method void setFrameType(); @@ -494,8 +491,6 @@ namespace Isis { J2000 to target) to the target frame*/ std::vector p_CJ; /**< Rotation matrix from J2000 to first constant rotation*/ - std::vector > p_cacheAv; - //!< Cached angular velocities for corresponding rotactions in p_cache std::vector p_av; //!< Angular velocity for rotation at time p_et bool p_hasAngularVelocity; /**< Flag indicating whether the rotation includes angular velocity*/ @@ -603,6 +598,7 @@ namespace Isis { static const double m_centScale; //! Seconds per day for scaling time in seconds to get target body w static const double m_dayScale; + }; }; diff --git a/isis/src/base/objs/SpiceRotation/SpiceRotation.truth b/isis/src/base/objs/SpiceRotation/SpiceRotation.truth index de5c26eef0..98ce29c88c 100644 --- a/isis/src/base/objs/SpiceRotation/SpiceRotation.truth +++ b/isis/src/base/objs/SpiceRotation/SpiceRotation.truth @@ -643,17 +643,17 @@ CJ(0) = -1 0 0 0 -1 0 0 0 1 Time = 1 -CJ(1) = 0 1 0 - -1 0 0 +CJ(1) = 2.220446e-16 1 0 + -1 2.220446e-16 0 0 0 1 Time = 2 -CJ(2) = 0 1 0 - 1 0 0 +CJ(2) = 2.220446e-16 1 0 + 1 -2.220446e-16 0 0 0 -1 Time = 3 -CJ(3) = -8.6595606e-17 2.220446e-16 -1 - -1 8.6595606e-17 8.6595606e-17 - 8.6595606e-17 1 5.5511151e-17 +CJ(3) = 0 0 -1 + -1 0 0 + 0 1 0 Testing loading cache from ALE ISD with time dependent quaternions and AV ... @@ -668,17 +668,17 @@ CJ(0) = -1 0 0 0 0 1 0 -1 0 Time = 1 -CJ(1) = 0 1 0 +CJ(1) = 2.220446e-16 1 0 0 0 1 - -1 0 0 + -1 2.220446e-16 0 Time = 2 -CJ(2) = 0 1 0 +CJ(2) = 2.220446e-16 1 0 0 0 -1 - 1 0 0 + 1 -2.220446e-16 0 Time = 3 -CJ(3) = -8.6595606e-17 2.220446e-16 -1 - 8.6595606e-17 1 5.5511151e-17 - -1 8.6595606e-17 8.6595606e-17 +CJ(3) = 0 0 -1 + 0 1 0 + -1 0 0 Testing exceptions... diff --git a/isis/src/cassini/objs/VimsCamera/VimsCamera.truth b/isis/src/cassini/objs/VimsCamera/VimsCamera.truth index f1470f78f3..a30ee9f929 100644 --- a/isis/src/cassini/objs/VimsCamera/VimsCamera.truth +++ b/isis/src/cassini/objs/VimsCamera/VimsCamera.truth @@ -83,8 +83,8 @@ DeltaSample = 0.000000000 DeltaLine = 0.000000000 For center pixel position ... -Latitude off by: -0.6341295293990541 -Longitude off by: -0.1227893986467734 +Latitude OK +Longitude OK FileName: CM_1515945709_1.ir.cub CK Frame: -82371 @@ -141,8 +141,8 @@ DeltaSample = 0.000000000 DeltaLine = 0.000000000 For center pixel position ... -Latitude off by: 0.0229595838205015 -Longitude off by: 0.0098872441018614 +Latitude OK +Longitude OK FileName: C1465336166_1.ir.cub CK Frame: -82371 diff --git a/isis/src/cassini/objs/VimsCamera/unitTest.cpp b/isis/src/cassini/objs/VimsCamera/unitTest.cpp index 34b49866a4..4e20eb64a7 100644 --- a/isis/src/cassini/objs/VimsCamera/unitTest.cpp +++ b/isis/src/cassini/objs/VimsCamera/unitTest.cpp @@ -86,15 +86,15 @@ int main(void) { double knownLat[5] = { -0.4635396765968510, -34.8446732028169848, - -40.8016661988669753, + -41.4357957282659370, -42.7683454790732966, - -37.4368893866915258 + -37.4139298028795153 }; double knownLon[5] = { 198.1302329741679102, 123.5608203785339327, - 131.8443786754731661, + 131.7215892768255969, 202.6731689530125493, - 213.5879007185106673 + 213.5977879626166782 }; vector< pair > corners; diff --git a/isis/src/hayabusa/objs/HayabusaNirsCamera/unitTest.cpp b/isis/src/hayabusa/objs/HayabusaNirsCamera/unitTest.cpp index 64530ab4b1..37983725e0 100644 --- a/isis/src/hayabusa/objs/HayabusaNirsCamera/unitTest.cpp +++ b/isis/src/hayabusa/objs/HayabusaNirsCamera/unitTest.cpp @@ -42,8 +42,8 @@ int main(void) { // These should be lat/lon at center of image. To obtain these numbers for a new cube/camera, // set both the known lat and known lon to zero and copy the unit test output "Latitude off by: " // and "Longitude off by: " values directly into these variables. - double knownLat = 36.1707660310976067; - double knownLon = 345.6570666219602685; + double knownLat = 36.1707660328875136; + double knownLon = 345.6570666260113853; Cube c("$hayabusa/testData/2392975548_lvl3_0.refl.cub", "r"); HayabusaNirsCamera *cam = (HayabusaNirsCamera *) CameraFactory::Create(c); diff --git a/isis/src/newhorizons/objs/NewHorizonsLeisaCamera/unitTest.cpp b/isis/src/newhorizons/objs/NewHorizonsLeisaCamera/unitTest.cpp index 8f39797846..9ac1d95d5f 100644 --- a/isis/src/newhorizons/objs/NewHorizonsLeisaCamera/unitTest.cpp +++ b/isis/src/newhorizons/objs/NewHorizonsLeisaCamera/unitTest.cpp @@ -42,8 +42,8 @@ int main(void) { // These should be lat/lon at center of image. To obtain these numbers for a new cube/camera, // set both the known lat and known lon to zero and copy the unit test output "Latitude off by: " // and "Longitude off by: " values directly into these variables. -- in progress - double knownLat = 12.5782232447537350; - double knownLon = 23.5337593470261517; + double knownLat = 12.5782232447537528; + double knownLon = 23.5337593470257218; Cube c("$newhorizons/testData/lsb_0034933739_0x53c_sci_1.cub", "r"); NewHorizonsLeisaCamera *cam = (NewHorizonsLeisaCamera *) CameraFactory::Create(c); diff --git a/isis/src/newhorizons/objs/NewHorizonsLorriCamera/NewHorizonsLorriCamera.truth b/isis/src/newhorizons/objs/NewHorizonsLorriCamera/NewHorizonsLorriCamera.truth index 5799b481cf..3347067082 100644 --- a/isis/src/newhorizons/objs/NewHorizonsLorriCamera/NewHorizonsLorriCamera.truth +++ b/isis/src/newhorizons/objs/NewHorizonsLorriCamera/NewHorizonsLorriCamera.truth @@ -41,16 +41,16 @@ Declination: -16.043606158 PlanetocentricLatitude: -8.271158614 PositiveEast360Longitude: 210.202299602 EphemerisTime: 225787161.551323384 -NorthAzimuth: 359.217580727 -SunAzimuth: 82.539531219 -SpacecraftAzimuth: 251.351022349 +NorthAzimuth: 359.217580725 +SunAzimuth: 82.539531222 +SpacecraftAzimuth: 251.351022345 OffNadirAngle: -0.287902823 CelestialNorthClockAngle: 81.991210878 RaDecResolution: 0.000283854 -BodyFixedCoordinate: -1562.244751303 -BodyFixedCoordinate: -909.332100893 +BodyFixedCoordinate: -1562.244751304 +BodyFixedCoordinate: -909.332100894 BodyFixedCoordinate: -262.774167442 -LocalRadius: 1826620.868095986 +LocalRadius: 1826620.868096882 SampleResolution: 15054.295387028 LineResolution: 15054.295387028 ObliqueDetectorResolution: 15055.846913180 @@ -65,21 +65,21 @@ Declination: -16.043606158 PlanetocentricLatitude: -8.271158614 PositiveEast360Longitude: 210.202299602 EphemerisTime: 225792161.551323384 -NorthAzimuth: 359.217580727 -SunAzimuth: 82.539531219 -SpacecraftAzimuth: 251.351022349 +NorthAzimuth: 359.217580725 +SunAzimuth: 82.539531222 +SpacecraftAzimuth: 251.351022345 OffNadirAngle: -0.287902823 CelestialNorthClockAngle: 81.991210878 RaDecResolution: 0.000283854 -BodyFixedCoordinate: -1562.244751303 -BodyFixedCoordinate: -909.332100893 +BodyFixedCoordinate: -1562.244751304 +BodyFixedCoordinate: -909.332100894 BodyFixedCoordinate: -262.774167442 -LocalRadius: 1826620.868095986 +LocalRadius: 1826620.868096882 SampleResolution: 15054.295387028 LineResolution: 15054.295387028 ObliqueDetectorResolution: 15055.846913180 ObliqueLineResolution: 15055.846913180 ObliqueSampleResolution: 15055.846913180 ObliquePixelResolution: 15055.846913180 -Latitude off by: 0.0255589466259298 -Longitude off by: 0.0032366246724109 +Latitude off by: 0.0255589466344581 +Longitude off by: 0.0032366246865934 diff --git a/isis/src/newhorizons/objs/NewHorizonsMvicFrameCamera/NewHorizonsMvicFrameCamera.truth b/isis/src/newhorizons/objs/NewHorizonsMvicFrameCamera/NewHorizonsMvicFrameCamera.truth index 004e9e4621..bbca485900 100644 --- a/isis/src/newhorizons/objs/NewHorizonsMvicFrameCamera/NewHorizonsMvicFrameCamera.truth +++ b/isis/src/newhorizons/objs/NewHorizonsMvicFrameCamera/NewHorizonsMvicFrameCamera.truth @@ -33,6 +33,6 @@ DeltaSample = ERROR DeltaLine = ERROR For center pixel position ... -Latitude off by: 36.4971027901168554 -Longitude off by: -4.0083142273843686 +Latitude OK +Longitude OK **PROGRAMMER ERROR** Band number out of array bounds in NewHorizonsMvicFrameCamera::SetBand legal bands are [1-9], input was [10]. diff --git a/isis/src/newhorizons/objs/NewHorizonsMvicFrameCamera/unitTest.cpp b/isis/src/newhorizons/objs/NewHorizonsMvicFrameCamera/unitTest.cpp index 804636836f..aeadeade6f 100644 --- a/isis/src/newhorizons/objs/NewHorizonsMvicFrameCamera/unitTest.cpp +++ b/isis/src/newhorizons/objs/NewHorizonsMvicFrameCamera/unitTest.cpp @@ -44,8 +44,8 @@ int main(void) { // These should be lat/lon at center of image. To obtain these numbers for a new cube/camera, // set both the known lat and known lon to zero and copy the unit test output "Latitude off by: " // and "Longitude off by: " values directly into these variables. - double knownLat = -6.0432183248466513; - double knownLon = 7.5037820678308149; + double knownLat = 30.4538844652774969; + double knownLon = 3.4954678404272648; Cube c("$newhorizons/testData/mpf_0035126517_0x539_sci_1.cub", "r"); NewHorizonsMvicFrameCamera *cam = (NewHorizonsMvicFrameCamera *) CameraFactory::Create(c); diff --git a/isis/src/newhorizons/objs/NewHorizonsMvicTdiCamera/NewHorizonsMvicTdiCamera.truth b/isis/src/newhorizons/objs/NewHorizonsMvicTdiCamera/NewHorizonsMvicTdiCamera.truth index 48e41653f2..731555f2ac 100644 --- a/isis/src/newhorizons/objs/NewHorizonsMvicTdiCamera/NewHorizonsMvicTdiCamera.truth +++ b/isis/src/newhorizons/objs/NewHorizonsMvicTdiCamera/NewHorizonsMvicTdiCamera.truth @@ -46,7 +46,7 @@ RaDecResolution: 0.001130898 BodyFixedCoordinate: 1687.667621071 BodyFixedCoordinate: -623.152655611 BodyFixedCoordinate: -322.959465020 -LocalRadius: 1827797.594771857 +LocalRadius: 1827797.594771894 SampleResolution: 52846.204303124 LineResolution: 52846.204303124 ObliqueDetectorResolution: 53252.158923802 @@ -68,7 +68,7 @@ RaDecResolution: 0.001130898 BodyFixedCoordinate: 1687.667621071 BodyFixedCoordinate: -623.152655611 BodyFixedCoordinate: -322.959465020 -LocalRadius: 1827797.594771857 +LocalRadius: 1827797.594771894 SampleResolution: 52846.204303124 LineResolution: 52846.204303124 ObliqueDetectorResolution: 53252.158923802 diff --git a/isis/src/newhorizons/objs/NewHorizonsMvicTdiCamera/unitTest.cpp b/isis/src/newhorizons/objs/NewHorizonsMvicTdiCamera/unitTest.cpp index e3253b3355..e836a56d5a 100644 --- a/isis/src/newhorizons/objs/NewHorizonsMvicTdiCamera/unitTest.cpp +++ b/isis/src/newhorizons/objs/NewHorizonsMvicTdiCamera/unitTest.cpp @@ -160,14 +160,14 @@ int main(void) { cout << "ObliqueSampleResolution: " << cam->ObliqueSampleResolution() << endl; } - if (abs(cam->UniversalLatitude() - knownLat) < 6E-14) { + if (abs(cam->UniversalLatitude() - knownLat) < 7E-12) { cout << "Latitude OK" << endl; } else { cout << setprecision(16) << "Latitude off by: " << cam->UniversalLatitude() - knownLat << endl; } - if (abs(cam->UniversalLongitude() - knownLon) < 6E-14) { + if (abs(cam->UniversalLongitude() - knownLon) < 7E-12) { cout << "Longitude OK" << endl; } else { diff --git a/isis/src/rosetta/objs/RosettaOsirisCamera/unitTest.cpp b/isis/src/rosetta/objs/RosettaOsirisCamera/unitTest.cpp index 88f4bc3335..6b483df3d2 100644 --- a/isis/src/rosetta/objs/RosettaOsirisCamera/unitTest.cpp +++ b/isis/src/rosetta/objs/RosettaOsirisCamera/unitTest.cpp @@ -145,8 +145,8 @@ int main(void) { // These should be lat/lon at center of image. To obtain these numbers for a new cube/camera, // set both the known lat and known lon to zero and copy the unit test output "Latitude off by: " // and "Longitude off by: " values directly into these variables. - double knownLat = 66.7031631205835680; - double knownLon = 95.7688045622468422; + double knownLat = 66.7031631205829569; + double knownLon = 95.7688045622462880; Cube c(testNACFile, "r"); RosettaOsirisCamera *cam = (RosettaOsirisCamera *) CameraFactory::Create(c); diff --git a/isis/tests/CamptFunctionalTests.cpp b/isis/tests/CamptFunctionalTests.cpp index 7ac21e86a5..9b31e1aad3 100644 --- a/isis/tests/CamptFunctionalTests.cpp +++ b/isis/tests/CamptFunctionalTests.cpp @@ -121,7 +121,7 @@ TEST_F(DefaultCube, FunctionalTestCamptDefaultParameters) { EXPECT_NEAR( (double) groundPoint.findKeyword("Phase"), 80.528381932125, 1e-8); EXPECT_NEAR( (double) groundPoint.findKeyword("Incidence"), 70.127983116628, 1e-8); EXPECT_NEAR( (double) groundPoint.findKeyword("Emission"), 12.133564327344, 1e-8); - EXPECT_NEAR( (double) groundPoint.findKeyword("NorthAzimuth"), 332.65918493997, 1e-8); + EXPECT_NEAR( (double) groundPoint.findKeyword("NorthAzimuth"), 332.65918493997, 2e-8); EXPECT_NEAR( (double) groundPoint.findKeyword("EphemerisTime"), -709401200.26114, 1e-8); EXPECT_PRED_FORMAT2(AssertQStringsEqual, groundPoint.findKeyword("UTC"), "1977-07-09T20:05:51.5549999");