diff --git a/CHANGELOG.md b/CHANGELOG.md index 0976f09668..531550b8d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,11 @@ release. ## [Unreleased] +### Added + +- CSMCamera can now read and use the body rotation from ALE produced ISDs [#5072](https://github.com/DOI-USGS/ISIS3/pull/5072) +- CSMSkyMap added to CSMCamera for use with local rover projections in ISIS [#5072](https://github.com/DOI-USGS/ISIS3/pull/5072) + ### Fixed - Fixed noproj bug where some temporary files were not deleted after call to cam2cam. Issue: [#4813](https://github.com/USGS-Astrogeology/ISIS3/issues/4813) - Fixed noproj bug where missing shapemodel-related keywords (RayTraceEngine, BulletParts, Tolerance) are dropped when the output label is created. This resulted in the Bullet collision detection engine not being used. Issue: [#5377](https://github.com/USGS-Astrogeology/ISIS3/issues/5377) diff --git a/isis/src/base/apps/csminit/csminit.cpp b/isis/src/base/apps/csminit/csminit.cpp index 007c89f8c9..ca58e98334 100644 --- a/isis/src/base/apps/csminit/csminit.cpp +++ b/isis/src/base/apps/csminit/csminit.cpp @@ -29,8 +29,10 @@ find files of those names at the top level of this repository. **/ #include "Pvl.h" #include "PvlGroup.h" #include "PvlKeyword.h" +#include "SpiceRotation.h" using namespace std; +using json = nlohmann::json; namespace Isis { @@ -417,6 +419,24 @@ namespace Isis { blobLabel += PvlKeyword("PluginName", pluginName); cube->write(csmStateBlob); + // Try to add naif keywords + if (ui.WasEntered("ISD")) { + QString isdFilePath = ui.GetFileName("ISD"); + std::ifstream isdFileStream(isdFilePath.toStdString()); + try { + json isd = json::parse(isdFileStream); + + if (isd.contains("naif_keywords")) { + json aleNaifKeywords = isd["naif_keywords"]; + PvlObject naifKeywords = PvlObject("NaifKeywords", aleNaifKeywords); + *cube->label() += naifKeywords; + } + } + catch (json::parse_error &e) { + // continue if we hit a parse error + } + } + try { CameraFactory::Create(*cube); p.WriteHistory(*cube); diff --git a/isis/src/base/apps/skymap/main.cpp b/isis/src/base/apps/skymap/main.cpp index 92ee5c99aa..edd52a1abd 100644 --- a/isis/src/base/apps/skymap/main.cpp +++ b/isis/src/base/apps/skymap/main.cpp @@ -88,7 +88,9 @@ void IsisMain() { userGrp.addKeyword(PvlKeyword("EquatorialRadius", toString(1.0)), Pvl::Replace); userGrp.addKeyword(PvlKeyword("PolarRadius", toString(1.0)), Pvl::Replace); userGrp.addKeyword(PvlKeyword("LatitudeType", "Planetocentric"), Pvl::Replace); - userGrp.addKeyword(PvlKeyword("LongitudeDirection", "PositiveWest"), Pvl::Replace); + if (!userGrp.hasKeyword("LongitudeDirection")) { + userGrp.addKeyword(PvlKeyword("LongitudeDirection", "PositiveWest"), Pvl::Replace); + } userGrp.addKeyword(PvlKeyword("LongitudeDomain", "360"), Pvl::Replace); if(userGrp.hasKeyword("PixelResolution")) { userGrp.deleteKeyword("PixelResolution"); @@ -102,6 +104,9 @@ void IsisMain() { userGrp.addKeyword(PvlKeyword("MaximumLongitude", toString(maxRa)), Pvl::Replace); userGrp.addKeyword(PvlKeyword("MinimumLatitude", toString(minDec)), Pvl::Replace); userGrp.addKeyword(PvlKeyword("MaximumLatitude", toString(maxDec)), Pvl::Replace); + incam->SetImage(icube->sampleCount() / 2.0, icube->lineCount() / 2.0); + double centerRa = incam->RightAscension(); + userGrp.addKeyword(PvlKeyword("CenterLongitude", toString(centerRa)), Pvl::Replace); } if(ui.GetString("DEFAULTSCALE") == "CAMERA") { double res = incam->RaDecResolution(); @@ -247,6 +252,13 @@ bool sky2map::Xform(double &inSample, double &inLine, if(p_incam->Sample() > p_inputSamples + 0.5) return false; if(p_incam->Line() > p_inputLines + 0.5) return false; + p_incam->SetImage(p_incam->Sample(), p_incam->Line()); + + // Check that the new line and sample projects close to the input Right Ascension + // and Declination + if (abs(p_incam->RightAscension() - lon) > 0.1) return false; + if (abs(p_incam->Declination() - lat) > 0.1) return false; + // Everything is good inSample = p_incam->Sample(); inLine = p_incam->Line(); diff --git a/isis/src/base/apps/skymap/skymap.xml b/isis/src/base/apps/skymap/skymap.xml index 30c181cfa6..a9ee6c45f7 100644 --- a/isis/src/base/apps/skymap/skymap.xml +++ b/isis/src/base/apps/skymap/skymap.xml @@ -29,9 +29,10 @@ MaximumLatitude = Computed from the input camera cube or map file MinimumLongitude = Computed from the input camera cube or map file MaximumLongitude = Computed from the input camera cube or map file + CenterLongitude = Computed from the input camera cube at the center of the image ProjectionName = Projection name in the map file - Scale = Computed from the input camera cube or map file + Scale = Computed from the input camera cube or map file EndGroup @@ -48,6 +49,14 @@ Finally, the user has the option to override the pixel resolution and the ground range (latitude/longitude). These changes can be facilitied through the parameters SCALE, SRA, ERA, SDEC, and EDEC.

+ +

+ In addition, skymap can be used to produce landed mosaics from rovers like MSL. This can be done using ALE to generate an ISD + which can be attached to the cube via csminit. The user would then have to update the LongitudeDirection + their map file to PositiveWest. This converts the projection from a right ascension/declination projection to an azimuth/elevation + projection. Once that is done, the user would run their ISIS cube through skymap and see that the landed + rover data would project relative to other images in the same image sequence. +

@@ -101,6 +110,10 @@ Changed to use TProjection instead of Projection. References #775 + + Updated camera to properly calculate the center longitude. Also + allowed users to select PositiveEast in there mapping file. + diff --git a/isis/src/base/apps/skypt/main.cpp b/isis/src/base/apps/skypt/main.cpp index 3d5d5b9c67..a8bfcc1835 100644 --- a/isis/src/base/apps/skypt/main.cpp +++ b/isis/src/base/apps/skypt/main.cpp @@ -2,6 +2,7 @@ #include "Brick.h" #include "Camera.h" +#include "CSMCamera.h" #include "IException.h" #include "iTime.h" @@ -47,8 +48,13 @@ void IsisMain() { int intLine = (int)(line + 0.5); b.SetBasePosition(intSamp, intLine, 1); cube.read(b); - - double rot = cam->CelestialNorthClockAngle(); + + double rot; + if (cube.hasBlob("CSMState", "String")) { + rot = ((CSMCamera*)cam)->CelestialNorthClockAngle(); + } else { + rot = cam->CelestialNorthClockAngle(); + } // Create group with sky position PvlGroup sp("SkyPoint"); diff --git a/isis/src/base/objs/CSMCamera/CSMCamera.cpp b/isis/src/base/objs/CSMCamera/CSMCamera.cpp index a58b6ff98a..85af2e3927 100644 --- a/isis/src/base/objs/CSMCamera/CSMCamera.cpp +++ b/isis/src/base/objs/CSMCamera/CSMCamera.cpp @@ -7,7 +7,7 @@ find files of those names at the top level of this repository. **/ /* SPDX-License-Identifier: CC0-1.0 */ #include "CSMCamera.h" -#include "CameraSkyMap.h" +#include "CSMSkyMap.h" #include #include @@ -18,10 +18,8 @@ find files of those names at the top level of this repository. **/ #include #include +#include "Affine.h" #include "Blob.h" -#include "CameraDetectorMap.h" -#include "CameraDistortionMap.h" -#include "CameraFocalPlaneMap.h" #include "Constants.h" #include "Displacement.h" #include "Distance.h" @@ -35,6 +33,8 @@ find files of those names at the top level of this repository. **/ #include "NaifStatus.h" #include "SpecialPixel.h" #include "SurfacePoint.h" +#include "Table.h" +#include "SensorUtilities.h" #include "csm/Warning.h" #include "csm/Error.h" @@ -42,10 +42,16 @@ find files of those names at the top level of this repository. **/ #include "csm/Ellipsoid.h" #include "csm/SettableEllipsoid.h" +#include +using json = nlohmann::json; + using namespace std; namespace Isis { +json stateAsJson(std::string modelState); +void sanitize(std::string &input); + /** * Constructor for an ISIS Camera model that uses a Community Sensor Model (CSM) * for the principal transformations. @@ -57,6 +63,7 @@ namespace Isis { Blob state("CSMState", "String"); cube.read(state); PvlObject &blobLabel = state.Label(); + QString pluginName = blobLabel.findKeyword("PluginName")[0]; QString modelName = blobLabel.findKeyword("ModelName")[0]; QString stateString = QString::fromUtf8(state.getBuffer(), state.Size()); @@ -72,7 +79,7 @@ namespace Isis { * @param modelName The name of the CSM::Model that will be created * @param stateString The state string the the CSM::Model will be created from */ - void CSMCamera::init(Cube &cube, QString pluginName, QString modelName, QString stateString){ + void CSMCamera::init(Cube &cube, QString pluginName, QString modelName, QString stateString) { const csm::Plugin *plugin = csm::Plugin::findPlugin(pluginName.toStdString()); if (!plugin) { QStringList availablePlugins; @@ -161,10 +168,15 @@ namespace Isis { imageLocus.direction.z}; // Save off the look vector - m_lookB[0] = locusVec[0]; - m_lookB[1] = locusVec[1]; - m_lookB[2] = locusVec[2]; - m_newLookB = true; + SetLookDirection(locusVec); + if (!m_et) { + m_et = new iTime(); + } + *m_et = m_refTime + m_model->getImageTime(imagePt); + if (target()->isSky()) { + target()->shape()->setHasIntersection(false); + return true; + } // Check for a ground intersection if(!target()->shape()->intersectSurface(obsPosition, locusVec)) { @@ -172,10 +184,6 @@ namespace Isis { } p_pointComputed = true; - if (!m_et) { - m_et = new iTime(); - } - *m_et = m_refTime + m_model->getImageTime(imagePt); return true; } @@ -246,6 +254,106 @@ namespace Isis { } + /** + * Given the ra/dec compute the look direction. + * + * @param ra Right ascension in degrees (sky longitude). + * @param dec Declination in degrees (sky latitude). + * + * @return @b bool True if successful. + */ + bool CSMCamera::SetRightAscensionDeclination(const double ra, const double dec) { + double raRad = ra * DEG2RAD; + double decRad = dec * DEG2RAD; + + // Make the radius bigger, some multiple of the body radius -or- use sensor position at the reference point + SensorUtilities::GroundPt3D sphericalPt = {decRad, raRad, 1}; + SensorUtilities::Vec rectPt = SensorUtilities::sphericalToRect(sphericalPt); + + csm::EcefCoord lookPt = {rectPt.x, rectPt.y, rectPt.z}; + double achievedPrecision = 0; + csm::WarningList warnings; + bool validBackProject; + csm::ImageCoord imagePt; + + try { + imagePt = m_model->groundToImage(lookPt, 0.01, &achievedPrecision, &warnings); + double sample; + double line; + csmToIsisPixel(imagePt, line, sample); + validBackProject = SetImage(sample, line); + } + catch (csm::Error &e) { + validBackProject = false; + } + + return validBackProject; + } + + + /** + * Sets the look direction of the spacecraft. This routine will then attempt to + * intersect the look direction with the target. If successful you can utilize + * the methods which return the lat/lon, phase, incidence, etc. This routine + * returns false if the look direction does not intersect the target. + * + * @param v[] A look vector in camera coordinates. For example, (0,0,1) is + * usually the look direction out of the boresight of a camera. + * + * @return @b bool Indicates whether the given look direction intersects the target. + * + */ + bool CSMCamera::SetLookDirection(const std::vector lookB) { + // The look vector must be in the camera coordinate system + + // This memcpy does: + // m_lookB[0] = lookB[0]; + // m_lookB[1] = lookB[1]; + // m_lookB[2] = lookB[2]; + memcpy(m_lookB, &lookB[0], sizeof(double) * 3); + m_newLookB = true; + + // Don't try to intersect the sky + if (target()->isSky()) { + target()->shape()->setHasIntersection(false); + return false; + } + + return false; + } + + + /** + * Computes the celestial north clock angle at the current + * line/sample or ra/dec. The reference vector is a vecor from the + * current pixel pointed directly "upward". Celetial North + * is a vector from the current pixel poiting towards celetial north. + * The Celestial North Clock Angle is the angle between these two vectors + * on the image. + * + * @return @b double The resultant Celestial North Clock Angle + */ + double CSMCamera::CelestialNorthClockAngle() { + double orgLine = Line(); + double orgSample = Sample(); + double orgDec = Declination(); + double orgRa = RightAscension(); + + SetRightAscensionDeclination(orgRa, orgDec + (2 * RaDecResolution())); + double y = Line() - orgLine; + double x = Sample() - orgSample; + double celestialNorthClockAngle = atan2(-y, x) * 180.0 / Isis::PI; + celestialNorthClockAngle = 90.0 - celestialNorthClockAngle; + + if (celestialNorthClockAngle < 0.0) { + celestialNorthClockAngle += 360.0; + } + + SetImage(orgSample, orgLine); + return celestialNorthClockAngle; + } + + /** * Set the ground point for the Camera Model and then compute the * corresponding image time, look vector, and image coordinate. @@ -335,10 +443,14 @@ namespace Isis { * @returns @b double The line resolution in meters per pixel */ double CSMCamera::LineResolution() { - vector imagePartials = ImagePartials(); - return sqrt(imagePartials[0]*imagePartials[0] + - imagePartials[2]*imagePartials[2] + - imagePartials[4]*imagePartials[4]); + if (HasSurfaceIntersection()) { + vector imagePartials = ImagePartials(); + return sqrt(imagePartials[0]*imagePartials[0] + + imagePartials[2]*imagePartials[2] + + imagePartials[4]*imagePartials[4]); + } + + return Isis::Null; } @@ -352,10 +464,14 @@ namespace Isis { * @returns @b double The sample resolution in meters per pixel */ double CSMCamera::SampleResolution() { - vector imagePartials = ImagePartials(); - return sqrt(imagePartials[1]*imagePartials[1] + - imagePartials[3]*imagePartials[3] + - imagePartials[5]*imagePartials[5]); + if (HasSurfaceIntersection()) { + vector imagePartials = ImagePartials(); + return sqrt(imagePartials[1] * imagePartials[1] + + imagePartials[3] * imagePartials[3] + + imagePartials[5] * imagePartials[5]); + } + + return Isis::Null; } @@ -369,16 +485,20 @@ namespace Isis { * @returns @b double The detector resolution in meters per pixel */ double CSMCamera::DetectorResolution() { - // Redo the line and sample resolution calculations because it avoids - // a call to ImagePartials which could be a costly call - vector imagePartials = ImagePartials(); - double lineRes = sqrt(imagePartials[0]*imagePartials[0] + - imagePartials[2]*imagePartials[2] + - imagePartials[4]*imagePartials[4]); - double sampRes = sqrt(imagePartials[1]*imagePartials[1] + - imagePartials[3]*imagePartials[3] + - imagePartials[5]*imagePartials[5]); - return (sampRes + lineRes) / 2.0; + if (HasSurfaceIntersection()) { + // Redo the line and sample resolution calculations because it avoids + // a call to ImagePartials which could be a costly call + vector imagePartials = ImagePartials(); + double lineRes = sqrt(imagePartials[0]*imagePartials[0] + + imagePartials[2]*imagePartials[2] + + imagePartials[4]*imagePartials[4]); + double sampRes = sqrt(imagePartials[1]*imagePartials[1] + + imagePartials[3]*imagePartials[3] + + imagePartials[5]*imagePartials[5]); + return (sampRes + lineRes) / 2.0; + } + + return Isis::Null; } @@ -990,7 +1110,7 @@ namespace Isis { * positive east, ocentric). * * This is not supported for CSM sensors because we cannot get the position - * of the sun, only the illumination direction. + * of the sun, only the illumination direction * * @param lat Sub-solar latitude * @param lon Sub-solar longitude @@ -1056,7 +1176,6 @@ namespace Isis { throw IException(IException::Programmer, msg, _FILEINFO_); } - /** * Get the SpiceRotation object the contains the orientation of the target body * relative to J2000. @@ -1067,7 +1186,7 @@ namespace Isis { * @returns @b SpiceRotation* A pointer to the SpiceRotation object for the body orientation */ SpiceRotation *CSMCamera::bodyRotation() const { - QString msg = "Target body orientation is not supported for CSM camera models"; + QString msg = "Body orientation is not supported for CSM camera models"; throw IException(IException::Programmer, msg, _FILEINFO_); } @@ -1117,27 +1236,49 @@ namespace Isis { /** * Computes the Right Ascension of the currently set image coordinate. * - * This is not supported for CSM sensors because the CSM API only supports the - * body fixed coordinate system and does not provide rotations to any others. - * * @returns @b double The Right Ascension */ double CSMCamera::RightAscension() { - QString msg = "Right Ascension is not supported for CSM camera models"; - throw IException(IException::Programmer, msg, _FILEINFO_); + double precision; + csm::EcefLocus locus = m_model->imageToRemoteImagingLocus(csm::ImageCoord(p_childLine, p_childSample), 0.00001, &precision); + csm::EcefVector v = locus.direction; + SensorUtilities::GroundPt3D sphere_v = SensorUtilities::rectToSpherical({v.x, v.y, v.z}); + double lon = sphere_v.lon; + if (lon < 0) { + lon += 2 * PI; + } + return lon * RAD2DEG; } /** * Computes the Declination of the currently set image coordinate. * - * This is not supported for CSM sensors because the CSM API only supports the - * body fixed coordinate system and does not provide rotations to any others. - * * @returns @b double The Declination */ double CSMCamera::Declination() { - QString msg = "Declination is not supported for CSM camera models"; - throw IException(IException::Programmer, msg, _FILEINFO_); + double precision; + csm::EcefLocus locus = m_model->imageToRemoteImagingLocus(csm::ImageCoord(p_childLine, p_childSample), 0.00001, &precision); + csm::EcefVector v = locus.direction; + SensorUtilities::GroundPt3D sphere_v = SensorUtilities::rectToSpherical({v.x, v.y, v.z}); + return sphere_v.lat * RAD2DEG; + } + + json stateAsJson(std::string modelState) { + // Remove special characters from string + sanitize(modelState); + + std::size_t foundFirst = modelState.find_first_of("{"); + std::size_t foundLast = modelState.find_last_of("}"); + + if (foundFirst == std::string::npos) { + foundFirst = 0; + } + return json::parse(modelState.begin() + foundFirst, modelState.begin() + foundLast + 1); + } + + void sanitize(std::string &input){ + // Replaces characters from the string that are not printable with newlines + std::replace_if(input.begin(), input.end(), [](int c){return !::isprint(c);}, '\n'); } } diff --git a/isis/src/base/objs/CSMCamera/CSMCamera.h b/isis/src/base/objs/CSMCamera/CSMCamera.h index 8b6b1b789b..14756482ff 100644 --- a/isis/src/base/objs/CSMCamera/CSMCamera.h +++ b/isis/src/base/objs/CSMCamera/CSMCamera.h @@ -81,8 +81,10 @@ namespace Isis { virtual bool SetGround(const SurfacePoint &surfacePt); virtual bool SetUniversalGround(const double latitude, const double longitude); virtual bool SetUniversalGround(const double latitude, const double longitude, double radius); - + virtual bool SetRightAscensionDeclination(const double ra, const double dec); virtual void setTime(const iTime &time); + virtual bool SetLookDirection(const std::vector lookB); + virtual double CelestialNorthClockAngle(); virtual double LineResolution(); virtual double SampleResolution(); @@ -145,6 +147,9 @@ namespace Isis { csm::RasterGM *m_model; //! CSM sensor model iTime m_refTime; //! The reference time that all model image times are relative to + SpiceRotation *m_bodyRotation = NULL; //!< Body spice rotation + SpiceRotation *m_instrumentRotation = NULL; //!< Instrument spice rotation + Longitude *m_solarLongitude = NULL; void isisToCsmPixel(double line, double sample, csm::ImageCoord &csmPixel) const; void csmToIsisPixel(csm::ImageCoord csmPixel, double &line, double &sample) const; diff --git a/isis/src/base/objs/CSMSkyMap/CSMSkyMap.cpp b/isis/src/base/objs/CSMSkyMap/CSMSkyMap.cpp new file mode 100644 index 0000000000..7e8a859513 --- /dev/null +++ b/isis/src/base/objs/CSMSkyMap/CSMSkyMap.cpp @@ -0,0 +1,45 @@ +/** This is free and unencumbered software released into the public domain. +The authors of ISIS do not claim copyright on the contents of this file. +For more details about the LICENSE terms and the AUTHORS, you will +find files of those names at the top level of this repository. **/ + +/* SPDX-License-Identifier: CC0-1.0 */ + +#include "CSMSkyMap.h" +#include "CSMCamera.h" + +namespace Isis { + /** Constructor a map between focal plane x/y and right acension/declination + * + * @param parent parent camera which will use this map + * + */ + CSMSkyMap::CSMSkyMap(Camera *parent) { + p_camera = parent; + p_camera->SetSkyMap(this); + } + + /** + * Compute undistorted focal plane coordinate from ra/dec + * + * @param ra The right ascension angle + * @param dec The declination + * + * @return conversion was successful + * @todo what happens if we are looking behind the focal plane????? + * @todo what happens if we are looking parallel to the focal plane?? + * @todo can lookC[2] == zero imply parallel + * @todo can this all be solved by restricting the physical size of + * the focal plane? + */ + bool CSMSkyMap::SetSky(const double ra, const double dec) { + ((CSMCamera*)p_camera)->SetRightAscensionDeclination(ra, dec); + double lookC[3]; + ((CSMCamera*)p_camera)->LookDirection(lookC); + double scale = p_camera->FocalLength() / lookC[2]; + p_focalPlaneX = lookC[0] * scale; + p_focalPlaneY = lookC[1] * scale; + return true; + } + +}; \ No newline at end of file diff --git a/isis/src/base/objs/CSMSkyMap/CSMSkyMap.h b/isis/src/base/objs/CSMSkyMap/CSMSkyMap.h new file mode 100644 index 0000000000..48c45d7f17 --- /dev/null +++ b/isis/src/base/objs/CSMSkyMap/CSMSkyMap.h @@ -0,0 +1,36 @@ +#ifndef CSMSkyMap_h +#define CSMSkyMap_h +/** This is free and unencumbered software released into the public domain. +The authors of ISIS do not claim copyright on the contents of this file. +For more details about the LICENSE terms and the AUTHORS, you will +find files of those names at the top level of this repository. **/ + +/* SPDX-License-Identifier: CC0-1.0 */ + +#include "CSMCamera.h" +#include "CameraSkyMap.h" + +namespace Isis { + + + /** Convert between undistorted focal plane and ra/dec coordinates + * + * This base class is used to convert between undistorted focal plane + * coordinates (x/y) in millimeters and sky (ra/dec). This + * class handles the case of framing cameras. + * + * @ingroup Camera + * + * @see Camera + * + */ + class CSMSkyMap : public CameraSkyMap { + public: + + CSMSkyMap(Camera *parent); + + virtual bool SetSky(const double ra, const double dec); + }; +}; + +#endif diff --git a/isis/src/base/objs/Camera/Camera.cpp b/isis/src/base/objs/Camera/Camera.cpp index edf22c4bba..3551060501 100644 --- a/isis/src/base/objs/Camera/Camera.cpp +++ b/isis/src/base/objs/Camera/Camera.cpp @@ -462,27 +462,21 @@ namespace Isis { // TODO: we need to validate this pointer (somewhere) ShapeModel *shape = target()->shape(); - //cout << "undistorted focal plane: " << ux << " " << uy << endl; //debug - //cout.precision(15); - //cout << "Backward Time: " << Time().Et() << endl; // Convert undistorted x/y to distorted x/y bool success = p_distortionMap->SetUndistortedFocalPlane(ux, uy); if (success) { double focalPlaneX = p_distortionMap->FocalPlaneX(); double focalPlaneY = p_distortionMap->FocalPlaneY(); - //cout << "focal plane: " << focalPlaneX << " " << focalPlaneY << endl; //debug // Convert distorted x/y to detector position success = p_focalPlaneMap->SetFocalPlane(focalPlaneX, focalPlaneY); if (success) { double detectorSample = p_focalPlaneMap->DetectorSample(); double detectorLine = p_focalPlaneMap->DetectorLine(); - //cout << "detector: " << detectorSample << " " << detectorLine << endl; // Convert detector to parent position success = p_detectorMap->SetDetector(detectorSample, detectorLine); if (success) { double parentSample = p_detectorMap->ParentSample(); double parentLine = p_detectorMap->ParentLine(); - //cout << "cube: " << parentSample << " " << parentLine << endl; //debug if (p_projection == NULL || p_ignoreProjection) { p_childSample = p_alphaCube->BetaSample(parentSample); p_childLine = p_alphaCube->BetaLine(parentLine); diff --git a/isis/src/base/objs/Camera/Camera.h b/isis/src/base/objs/Camera/Camera.h index 83e312cae3..692c51c501 100644 --- a/isis/src/base/objs/Camera/Camera.h +++ b/isis/src/base/objs/Camera/Camera.h @@ -251,7 +251,7 @@ namespace Isis { const double radius); virtual bool SetGround(Latitude latitude, Longitude longitude); virtual bool SetGround(const SurfacePoint & surfacePt); - bool SetRightAscensionDeclination(const double ra, const double dec); + virtual bool SetRightAscensionDeclination(const double ra, const double dec); void LocalPhotometricAngles(Angle & phase, Angle & incidence, Angle & emission, bool &success); diff --git a/isis/src/base/objs/CameraDistortionMap/CameraDistortionMap.cpp b/isis/src/base/objs/CameraDistortionMap/CameraDistortionMap.cpp index 46958d4962..7e7cb47e54 100644 --- a/isis/src/base/objs/CameraDistortionMap/CameraDistortionMap.cpp +++ b/isis/src/base/objs/CameraDistortionMap/CameraDistortionMap.cpp @@ -56,6 +56,7 @@ namespace Isis { * @todo Add latex equation to the documentation */ void CameraDistortionMap::SetDistortion(int naifIkCode) { + p_odk.clear(); QString odkkey = "INS" + toString(naifIkCode) + "_OD_K"; for (int i = 0; i < 3; ++i) { p_odk.push_back(p_camera->Spice::getDouble(odkkey, i)); diff --git a/isis/src/base/objs/CameraDistortionMap/CameraDistortionMap.h b/isis/src/base/objs/CameraDistortionMap/CameraDistortionMap.h index 2739a374f1..2aef97697b 100644 --- a/isis/src/base/objs/CameraDistortionMap/CameraDistortionMap.h +++ b/isis/src/base/objs/CameraDistortionMap/CameraDistortionMap.h @@ -68,7 +68,7 @@ namespace Isis { double p_undistortedFocalPlaneY; //!< Undistorted focal plane y double p_zDirection; //!< Undistorted focal plane z - std::vector p_odk; //!< Vector of distortion coefficients + std::vector p_odk = {}; //!< Vector of distortion coefficients }; }; #endif diff --git a/isis/src/base/objs/CameraSkyMap/CameraSkyMap.h b/isis/src/base/objs/CameraSkyMap/CameraSkyMap.h index 34078e0e5a..2aa34b5c87 100644 --- a/isis/src/base/objs/CameraSkyMap/CameraSkyMap.h +++ b/isis/src/base/objs/CameraSkyMap/CameraSkyMap.h @@ -30,6 +30,7 @@ namespace Isis { */ class CameraSkyMap { public: + CameraSkyMap() = default; CameraSkyMap(Camera *parent); //! Destructor diff --git a/isis/src/base/objs/Sensor/Sensor.cpp b/isis/src/base/objs/Sensor/Sensor.cpp index bc9c27c10c..66babe20a8 100644 --- a/isis/src/base/objs/Sensor/Sensor.cpp +++ b/isis/src/base/objs/Sensor/Sensor.cpp @@ -141,13 +141,13 @@ namespace Isis { * */ bool Sensor::SetLookDirection(const double v[3]) { - //std::cout << "Sensor::SetLookDirection()\n"; + // std::cout << "Sensor::SetLookDirection()\n"; // The look vector must be in the camera coordinate system // copy v to LookC // lookC[0] = v[0]; // lookC[1] = v[1]; - // lookC[2] = v[2]; + // lookC[2] = v[2] vector lookC(v, v + 3); // Convert it to body-fixed @@ -613,7 +613,9 @@ namespace Isis { bool Sensor::SetRightAscensionDeclination(const double ra, const double dec) { double raRad = ra * DEG2RAD; double decRad = dec * DEG2RAD; - SensorUtilities::GroundPt3D sphericalPt = {decRad, raRad, 1.0}; + + // Make the radius bigger, some multiple of the body radius -or- use sensor position at the reference point + SensorUtilities::GroundPt3D sphericalPt = {decRad, raRad, 1}; SensorUtilities::Vec rectPt = SensorUtilities::sphericalToRect(sphericalPt); vector lookC = instrumentRotation()->ReferenceVector(rectPt); diff --git a/isis/src/base/objs/Spice/Spice.cpp b/isis/src/base/objs/Spice/Spice.cpp index d8c01e4355..1e357c77d7 100644 --- a/isis/src/base/objs/Spice/Spice.cpp +++ b/isis/src/base/objs/Spice/Spice.cpp @@ -194,7 +194,7 @@ namespace Isis { // ephemerides. (2008-02-27 (KJB)) if (m_usingNaif) { try { - if (isd == NULL){ + if (isd == NULL) { // try using ALE std::ostringstream kernel_pvl; kernel_pvl << kernels; diff --git a/isis/src/base/objs/SpiceRotation/SpiceRotation.cpp b/isis/src/base/objs/SpiceRotation/SpiceRotation.cpp index 8f4dabcd03..c5b6c55a59 100644 --- a/isis/src/base/objs/SpiceRotation/SpiceRotation.cpp +++ b/isis/src/base/objs/SpiceRotation/SpiceRotation.cpp @@ -491,10 +491,7 @@ namespace Isis { p_hasAngularVelocity = true; } - bool hasConstantFrames = isdRot.find("constant_frames") != isdRot.end(); - - - if (hasConstantFrames) { + if (isdRot.contains("constant_frames")) { p_constantFrames = isdRot["constant_frames"].get>(); p_TC = isdRot["constant_rotation"].get>(); m_orientation = new ale::Orientations(rotationCache, p_cacheTime, avCache, diff --git a/isis/src/base/objs/Target/Target.cpp b/isis/src/base/objs/Target/Target.cpp index ab8eb2d0c3..32689d99d1 100644 --- a/isis/src/base/objs/Target/Target.cpp +++ b/isis/src/base/objs/Target/Target.cpp @@ -108,17 +108,42 @@ namespace Isis { */ Target::Target(Pvl &label) { // Initialize everything to null - m_bodyCode = NULL; - m_systemCode = NULL; + m_bodyCode = new SpiceInt; + m_systemCode = new SpiceInt; m_name = NULL; m_systemName = NULL; m_spice = NULL; + m_radii.resize(3, Distance()); init(); PvlGroup &inst = label.findGroup("Instrument", Pvl::Traverse); QString targetName = inst["TargetName"][0]; setName(targetName); + PvlGroup &kernels = label.findGroup("Kernels", Pvl::Traverse); + + QString trykey = "NaifIkCode"; + + m_systemName = new QString; + + if (kernels.hasKeyword("NaifFrameCode")) { + trykey = "NaifFrameCode"; + } + + if (name().toUpper() == "SKY" && kernels.hasKeyword(trykey)) { + m_radii[0] = m_radii[1] = m_radii[2] = Distance(1000.0, Distance::Meters); + m_sky = true; + int ikCode = toInt(kernels[trykey][0]); + *m_bodyCode = ikCode / 1000; + // Check for override in kernel group + if (kernels.hasKeyword("NaifSpkCode")) { + *m_bodyCode = (int) kernels["NaifSpkCode"]; + } + + *m_systemCode = -1; + (*m_systemName).append("THE COSMOS"); + } + m_shape = ShapeModelFactory::create(this, label); } diff --git a/isis/src/qisis/objs/AdvancedTrackTool/AdvancedTrackTool.cpp b/isis/src/qisis/objs/AdvancedTrackTool/AdvancedTrackTool.cpp index 3251048cd8..5c5ecd12b6 100644 --- a/isis/src/qisis/objs/AdvancedTrackTool/AdvancedTrackTool.cpp +++ b/isis/src/qisis/objs/AdvancedTrackTool/AdvancedTrackTool.cpp @@ -349,141 +349,158 @@ namespace Isis { // Do we have a camera model? if(cvp->camera() != NULL) { if(cvp->camera()->SetImage(sample, line)) { - // Write columns ocentric lat/lon, and radius, only if set image succeeds - double lat = cvp->camera()->UniversalLatitude(); - double lon = cvp->camera()->UniversalLongitude(); - - double radius = cvp->camera()->LocalRadius().meters(); - p_tableWin->table()->item(row, getIndex("Planetocentric Latitude"))-> - setText(QString::number(lat, 'f', 15)); - p_tableWin->table()->item(row, getIndex("360 Positive East Longitude"))-> - setText(QString::number(lon, 'f', 15)); - p_tableWin->table()->item(row, getIndex("Local Radius"))-> - setText(QString::number(radius, 'f', 15)); - - /* 180 Positive East Lon. */ - p_tableWin->table()->item(row, getIndex("180 Positive East Longitude"))-> - setText(QString::number(TProjection::To180Domain(lon), 'f', 15)); - - // Write out the planetographic and positive west values, only if set image succeeds - lon = -lon; - while(lon < 0.0) lon += 360.0; - Distance radii[3]; - cvp->camera()->radii(radii); - lat = TProjection::ToPlanetographic(lat, radii[0].meters(), radii[2].meters()); - p_tableWin->table()->item(row, getIndex("Planetographic Latitude"))-> - setText(QString::number(lat, 'f', 15)); - p_tableWin->table()->item(row, getIndex("360 Positive West Longitude"))-> - setText(QString::number(lon, 'f', 15)); - - /*180 Positive West Lon. */ - p_tableWin->table()->item(row, getIndex("180 Positive West Longitude"))->setText( - QString::number(TProjection::To180Domain(lon), 'f', 15)); - - // Next write out columns, the x/y/z position of the lat/lon, only if set image succeeds - double pos[3]; - cvp->camera()->Coordinate(pos); - p_tableWin->table()->item(row, getIndex("Point X"))->setText(QString::number(pos[0])); - p_tableWin->table()->item(row, getIndex("Point Y"))->setText(QString::number(pos[1])); - p_tableWin->table()->item(row, getIndex("Point Z"))->setText(QString::number(pos[2])); - - // Write out columns resolution, only if set image succeeds - double res = cvp->camera()->PixelResolution(); - if (res != -1.0) { - p_tableWin->table()->item(row, getIndex("Resolution"))->setText(QString::number(res)); + if (cvp->camera()->target()->isSky()) { + double dec = cvp->camera()->Declination(); + double ra = cvp->camera()->RightAscension(); + p_tableWin->table()->item(row, getIndex("Right Ascension"))-> + setText(QString::number(ra, 'f', 15)); + p_tableWin->table()->item(row, getIndex("Declination"))-> + setText(QString::number(dec, 'f', 15)); } else { - p_tableWin->table()->item(row, getIndex("Resolution"))->setText(""); - } + // Write columns ocentric lat/lon, and radius, only if set image succeeds + double lat = cvp->camera()->UniversalLatitude(); + double lon = cvp->camera()->UniversalLongitude(); - // Write out columns, oblique pixel resolution, only if set image succeeds - double obliquePRes = cvp->camera()->ObliquePixelResolution(); - if (obliquePRes != Isis::Null) { - p_tableWin->table()->item(row, getIndex("Oblique Pixel Resolution"))-> - setText(QString::number(obliquePRes)); - } - else { - p_tableWin->table()->item(row, getIndex("Oblique Pixel Resolution"))->setText(""); - } + double radius = cvp->camera()->LocalRadius().meters(); + p_tableWin->table()->item(row, getIndex("Planetocentric Latitude"))-> + setText(QString::number(lat, 'f', 15)); + p_tableWin->table()->item(row, getIndex("360 Positive East Longitude"))-> + setText(QString::number(lon, 'f', 15)); + p_tableWin->table()->item(row, getIndex("Local Radius"))-> + setText(QString::number(radius, 'f', 15)); - // Write out columns photometric angle values, only if set image succeeds - double phase = cvp->camera()->PhaseAngle(); - p_tableWin->table()->item(row, getIndex("Phase"))->setText(QString::number(phase)); - double incidence = cvp->camera()->IncidenceAngle(); - p_tableWin->table()->item(row, getIndex("Incidence"))->setText(QString::number(incidence)); - double emission = cvp->camera()->EmissionAngle(); - p_tableWin->table()->item(row, getIndex("Emission"))->setText(QString::number(emission)); - - // Write out columns local incidence and emission, only if set image - // succeeds. This might fail if there are holes in the DEM. - // Calculates the angles local to the slope for the DEMs, compare against - // the incidence and emission angles calculated for the sphere - Angle phaseAngle, incidenceAngle, emissionAngle; - bool bSuccess = false; - cvp->camera()->LocalPhotometricAngles(phaseAngle, incidenceAngle, emissionAngle, bSuccess); - if(bSuccess) { - p_tableWin->table()->item(row, getIndex("LocalIncidence"))-> - setText(QString::number(incidenceAngle.degrees())); - p_tableWin->table()->item(row, getIndex("LocalEmission"))-> - setText(QString::number(emissionAngle.degrees())); - } - else { - p_tableWin->table()->item(row, getIndex("LocalIncidence"))->setText(""); - p_tableWin->table()->item(row, getIndex("LocalEmission"))->setText(""); - } + /* 180 Positive East Lon. */ + p_tableWin->table()->item(row, getIndex("180 Positive East Longitude"))-> + setText(QString::number(TProjection::To180Domain(lon), 'f', 15)); + + // Write out the planetographic and positive west values, only if set image succeeds + lon = -lon; + while(lon < 0.0) lon += 360.0; + Distance radii[3]; + cvp->camera()->radii(radii); + lat = TProjection::ToPlanetographic(lat, radii[0].meters(), radii[2].meters()); + p_tableWin->table()->item(row, getIndex("Planetographic Latitude"))-> + setText(QString::number(lat, 'f', 15)); + p_tableWin->table()->item(row, getIndex("360 Positive West Longitude"))-> + setText(QString::number(lon, 'f', 15)); - // If set image succeeds, write out columns north azimuth, sun azimuth, solar longitude - // north azimuth is meaningless for ring plane projections - double northAzi = cvp->camera()->NorthAzimuth(); - if (cvp->camera()->target()->shape()->name() != "Plane" - && Isis::IsValidPixel(northAzi)) { - p_tableWin->table()->item(row, getIndex("North Azimuth"))-> - setText(QString::number(northAzi)); - } - else { // north azimuth is meaningless for ring plane projections - p_tableWin->table()->item(row, getIndex("North Azimuth"))->setText(""); - } + /*180 Positive West Lon. */ + p_tableWin->table()->item(row, getIndex("180 Positive West Longitude"))->setText( + QString::number(TProjection::To180Domain(lon), 'f', 15)); + + // Next write out columns, the x/y/z position of the lat/lon, only if set image succeeds + double pos[3]; + cvp->camera()->Coordinate(pos); + p_tableWin->table()->item(row, getIndex("Point X"))->setText(QString::number(pos[0])); + p_tableWin->table()->item(row, getIndex("Point Y"))->setText(QString::number(pos[1])); + p_tableWin->table()->item(row, getIndex("Point Z"))->setText(QString::number(pos[2])); + + // Write out columns resolution, only if set image succeeds + double res = cvp->camera()->PixelResolution(); + if (res != -1.0) { + p_tableWin->table()->item(row, getIndex("Resolution"))->setText(QString::number(res)); + } + else { + p_tableWin->table()->item(row, getIndex("Resolution"))->setText(""); + } - double sunAzi = cvp->camera()->SunAzimuth(); - if (Isis::IsValidPixel(sunAzi)) { - p_tableWin->table()->item(row, getIndex("Sun Azimuth"))-> - setText(QString::number(sunAzi)); - } - else { // sun azimuth is null - p_tableWin->table()->item(row, getIndex("Sun Azimuth"))->setText(""); - } + // Write out columns, oblique pixel resolution, only if set image succeeds + double obliquePRes = cvp->camera()->ObliquePixelResolution(); + if (obliquePRes != Isis::Null) { + p_tableWin->table()->item(row, getIndex("Oblique Pixel Resolution"))-> + setText(QString::number(obliquePRes)); + } + else { + p_tableWin->table()->item(row, getIndex("Oblique Pixel Resolution"))->setText(""); + } - double spacecraftAzi = cvp->camera()->SpacecraftAzimuth(); - if (Isis::IsValidPixel(spacecraftAzi)) { - p_tableWin->table()->item(row, getIndex("Spacecraft Azimuth"))-> - setText(QString::number(spacecraftAzi)); - } - else { // spacecraft azimuth is null - p_tableWin->table()->item(row, getIndex("Spacecraft Azimuth"))->setText(""); - } + // Write out columns photometric angle values, only if set image succeeds + double phase = cvp->camera()->PhaseAngle(); + p_tableWin->table()->item(row, getIndex("Phase"))->setText(QString::number(phase)); + double incidence = cvp->camera()->IncidenceAngle(); + p_tableWin->table()->item(row, getIndex("Incidence"))->setText(QString::number(incidence)); + double emission = cvp->camera()->EmissionAngle(); + p_tableWin->table()->item(row, getIndex("Emission"))->setText(QString::number(emission)); + + // Write out columns local incidence and emission, only if set image + // succeeds. This might fail if there are holes in the DEM. + // Calculates the angles local to the slope for the DEMs, compare against + // the incidence and emission angles calculated for the sphere + Angle phaseAngle, incidenceAngle, emissionAngle; + bool bSuccess = false; + cvp->camera()->LocalPhotometricAngles(phaseAngle, incidenceAngle, emissionAngle, bSuccess); + if(bSuccess) { + p_tableWin->table()->item(row, getIndex("LocalIncidence"))-> + setText(QString::number(incidenceAngle.degrees())); + p_tableWin->table()->item(row, getIndex("LocalEmission"))-> + setText(QString::number(emissionAngle.degrees())); + } + else { + p_tableWin->table()->item(row, getIndex("LocalIncidence"))->setText(""); + p_tableWin->table()->item(row, getIndex("LocalEmission"))->setText(""); + } - // Write out columns solar lon, slant distance, local solar time - try { - double solarLon = cvp->camera()->solarLongitude().degrees(); - p_tableWin->table()->item(row, getIndex("Solar Longitude"))-> - setText(QString::number(solarLon)); - } - catch (IException &e) { - p_tableWin->table()->item(row, getIndex("Solar Longitude"))-> - setText(""); - } + // If set image succeeds, write out columns north azimuth, sun azimuth, solar longitude + // north azimuth is meaningless for ring plane projections + double northAzi = cvp->camera()->NorthAzimuth(); + if (cvp->camera()->target()->shape()->name() != "Plane" + && Isis::IsValidPixel(northAzi)) { + p_tableWin->table()->item(row, getIndex("North Azimuth"))-> + setText(QString::number(northAzi)); + } + else { // north azimuth is meaningless for ring plane projections + p_tableWin->table()->item(row, getIndex("North Azimuth"))->setText(""); + } - double slantDistance = cvp->camera()->SlantDistance(); - p_tableWin->table()->item(row, getIndex("Slant Distance"))-> - setText(QString::number(slantDistance)); - try { - double lst = cvp->camera()->LocalSolarTime(); - p_tableWin->table()->item(row, getIndex("Local Solar Time"))-> - setText(QString::number(lst)); - } - catch (IException &e) { - p_tableWin->table()->item(row, getIndex("Local Solar Time"))-> - setText(""); + + try { + double sunAzi = cvp->camera()->SunAzimuth(); + if (Isis::IsValidPixel(sunAzi)) { + p_tableWin->table()->item(row, getIndex("Sun Azimuth"))-> + setText(QString::number(sunAzi)); + } + else { // sun azimuth is null + p_tableWin->table()->item(row, getIndex("Sun Azimuth"))->setText(""); + } + } + catch(IException &e) { + p_tableWin->table()->item(row, getIndex("Sun Azimuth"))->setText(""); + } + + + double spacecraftAzi = cvp->camera()->SpacecraftAzimuth(); + if (Isis::IsValidPixel(spacecraftAzi)) { + p_tableWin->table()->item(row, getIndex("Spacecraft Azimuth"))-> + setText(QString::number(spacecraftAzi)); + } + else { // spacecraft azimuth is null + p_tableWin->table()->item(row, getIndex("Spacecraft Azimuth"))->setText(""); + } + + // Write out columns solar lon, slant distance, local solar time + try { + double solarLon = cvp->camera()->solarLongitude().degrees(); + p_tableWin->table()->item(row, getIndex("Solar Longitude"))-> + setText(QString::number(solarLon)); + } + catch (IException &e) { + p_tableWin->table()->item(row, getIndex("Solar Longitude"))-> + setText(""); + } + + double slantDistance = cvp->camera()->SlantDistance(); + p_tableWin->table()->item(row, getIndex("Slant Distance"))-> + setText(QString::number(slantDistance)); + try { + double lst = cvp->camera()->LocalSolarTime(); + p_tableWin->table()->item(row, getIndex("Local Solar Time"))-> + setText(QString::number(lst)); + } + catch (IException &e) { + p_tableWin->table()->item(row, getIndex("Local Solar Time"))-> + setText(""); + } } } // end if set image succeeds diff --git a/isis/src/qisis/objs/FindTool/FindTool.cpp b/isis/src/qisis/objs/FindTool/FindTool.cpp index 7a6a17d54b..b241c33186 100644 --- a/isis/src/qisis/objs/FindTool/FindTool.cpp +++ b/isis/src/qisis/objs/FindTool/FindTool.cpp @@ -459,8 +459,16 @@ namespace Isis { if (groundMap) { if ( groundMap->SetImage(samp, line) ) { - p_lat = groundMap->UniversalLatitude(); - p_lon = groundMap->UniversalLongitude(); + if (activeViewport->camera() != NULL) { + if (activeViewport->camera()->target()->isSky()) { + p_lat = activeViewport->camera()->Declination(); + p_lon = activeViewport->camera()->RightAscension(); + } + } + else { + p_lat = groundMap->UniversalLatitude(); + p_lon = groundMap->UniversalLongitude(); + } } } else { @@ -621,6 +629,11 @@ namespace Isis { double lat, double lon) { UniversalGroundMap *groundMap = viewport->universalGroundMap(); Distance viewportResolution; + if (viewport->camera() != NULL){ + if (groundMap->Camera()->target()->isSky()) { + return Distance(groundMap->Camera()->RaDecResolution(), Distance::Units::Meters); + } + } try { if ( groundMap && !IsSpecial(lat) && !IsSpecial(lon) && diff --git a/isis/src/qisis/objs/TrackTool/TrackTool.cpp b/isis/src/qisis/objs/TrackTool/TrackTool.cpp index 5401790737..1873105218 100644 --- a/isis/src/qisis/objs/TrackTool/TrackTool.cpp +++ b/isis/src/qisis/objs/TrackTool/TrackTool.cpp @@ -210,10 +210,18 @@ namespace Isis { if(cvp->camera()->SetImage(sample, line)) { if (cvp->camera()->target()->shape()->name() != "Plane") { - double lat = cvp->camera()->UniversalLatitude(); - double lon = cvp->camera()->UniversalLongitude(); - p_latLabel->setText(QString("Lat %1").arg(lat)); - p_lonLabel->setText(QString("Lon %1").arg(lon)); + if (cvp->camera()->target()->isSky()) { + double dec = cvp->camera()->Declination(); + double ra = cvp->camera()->RightAscension(); + p_latLabel->setText(QString("DEC %1").arg(dec)); + p_lonLabel->setText(QString("RA %1").arg(ra)); + } + else { + double lat = cvp->camera()->UniversalLatitude(); + double lon = cvp->camera()->UniversalLongitude(); + p_latLabel->setText(QString("Lat %1").arg(lat)); + p_lonLabel->setText(QString("Lon %1").arg(lon)); + } } else { double rad = cvp->camera()->LocalRadius().meters(); diff --git a/isis/tests/CSMCameraTests.cpp b/isis/tests/CSMCameraTests.cpp index e840b80f62..f5134d4ae9 100644 --- a/isis/tests/CSMCameraTests.cpp +++ b/isis/tests/CSMCameraTests.cpp @@ -474,9 +474,12 @@ TEST_F(CSMCameraFixture, CameraState) { TEST_F(CSMCameraFixture, SetTime) { + std::string failMsg = "Expected an IException with message \"" + " Setting the image time is not supported for CSM camera models\""; try { testCam->setTime(iTime("2000-01-01T11:58:55.816")); + FAIL() << failMsg; } catch(Isis::IException &e) { @@ -485,17 +488,19 @@ TEST_F(CSMCameraFixture, SetTime) { } catch(...) { - FAIL() << "Expected an IException with message \"" - " Setting the image time is not supported for CSM camera models\""; + FAIL() << failMsg; } } TEST_F(CSMCameraFixture, SubSolarPoint) { + std::string failMsg = "Expected an IException with message \"" + " Sub solar point is not supported for CSM camera models\""; try { double lat, lon; testCam->subSolarPoint(lat ,lon); + FAIL() << failMsg; } catch(Isis::IException &e) { @@ -504,16 +509,18 @@ TEST_F(CSMCameraFixture, SubSolarPoint) { } catch(...) { - FAIL() << "Expected an IException with message \"" - " Sub solar point is not supported for CSM camera models\""; + FAIL() << failMsg; } } TEST_F(CSMCameraFixture, PixelIfovOffsets) { + std::string failMsg = "Expected an IException with message \"" + " Pixel Field of View is not supported for CSM camera models\""; try { testCam->PixelIfovOffsets(); + FAIL() << failMsg; } catch(Isis::IException &e) { @@ -522,17 +529,19 @@ TEST_F(CSMCameraFixture, PixelIfovOffsets) { } catch(...) { - FAIL() << "Expected an IException with message \"" - " Pixel Field of View is not supported for CSM camera models\""; + FAIL() << failMsg; } } TEST_F(CSMCameraFixture, SunPosition) { + std::string failMsg = "Expected an IException with message \"" + " Sun position is not supported for CSM camera models\""; try { double position[3]; testCam->sunPosition(position); + FAIL() << failMsg; } catch(Isis::IException &e) { @@ -541,13 +550,13 @@ TEST_F(CSMCameraFixture, SunPosition) { } catch(...) { - FAIL() << "Expected an IException with message \"" - " Sun position is not supported for CSM camera models\""; + FAIL() << failMsg; } try { testCam->sunPosition(); + FAIL() << failMsg; } catch(Isis::IException &e) { @@ -556,16 +565,18 @@ TEST_F(CSMCameraFixture, SunPosition) { } catch(...) { - FAIL() << "Expected an IException with message \"" - " Sun position is not supported for CSM camera models\""; + FAIL() << failMsg; } } TEST_F(CSMCameraFixture, InstrumentPosition) { + std::string failMsg = "Expected an IException with message \"" + " Instrument position is not supported for CSM camera models\""; try { testCam->instrumentPosition(); + FAIL() << failMsg; } catch(Isis::IException &e) { @@ -574,8 +585,7 @@ TEST_F(CSMCameraFixture, InstrumentPosition) { } catch(...) { - FAIL() << "Expected an IException with message \"" - " Instrument position is not supported for CSM camera models\""; + FAIL() << failMsg; } } @@ -587,7 +597,7 @@ TEST_F(CSMCameraFixture, BodyRotation) { } catch(Isis::IException &e) { - EXPECT_TRUE(e.toString().toLatin1().contains("Target body orientation is not supported " + EXPECT_TRUE(e.toString().toLatin1().contains("Body orientation is not supported " "for CSM camera models")) << e.toString().toStdString(); } catch(...) @@ -653,36 +663,73 @@ TEST_F(CSMCameraFixture, SolarDistance) { TEST_F(CSMCameraFixture, RightAscension) { + // Define some things to match/return + csm::Ellipsoid wgs84; + csm::EcefLocus imageLocus(wgs84.getSemiMajorRadius() + 50000, 0, 0, -1, 0, 0); + + // Setup expected calls/returns + EXPECT_CALL(mockModel, imageToRemoteImagingLocus(::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .Times(1) + .WillRepeatedly(::testing::Return(imageLocus)); + try { - testCam->RightAscension(); + double rightAscension = testCam->RightAscension(); + EXPECT_FLOAT_EQ(rightAscension, 180.0); } - catch(Isis::IException &e) + catch (IException &e) { - EXPECT_TRUE(e.toString().toLatin1().contains("Right Ascension is not supported " - "for CSM camera models")) << e.toString().toStdString(); - } - catch(...) - { - FAIL() << "Expected an IException with message \"" - " Right Ascension is not supported for CSM camera models\""; + FAIL() << "Failed test with [" << e.what() << "]"; } } TEST_F(CSMCameraFixture, Declination) { + // Define some things to match/return + csm::Ellipsoid wgs84; + csm::EcefLocus imageLocus(wgs84.getSemiMajorRadius() + 50000, 0, 0, -1, 0, 0); + + // Setup expected calls/returns + EXPECT_CALL(mockModel, imageToRemoteImagingLocus(::testing::_, ::testing::_, ::testing::_, ::testing::_)) + .Times(1) + .WillRepeatedly(::testing::Return(imageLocus)); + try { - testCam->Declination(); + double declination = testCam->Declination(); + EXPECT_FLOAT_EQ(declination, 0.0); } - catch(Isis::IException &e) + catch (IException &e) { - EXPECT_TRUE(e.toString().toLatin1().contains("Declination is not supported " - "for CSM camera models")) << e.toString().toStdString(); + FAIL() << "Failed test with [" << e.what() << "]"; } - catch(...) +} + +TEST_F(CSMCameraFixture, SetRightAscensionDeclination) { + // Define some things to match/return + csm::Ellipsoid wgs84; + csm::ImageCoord imagePt(4.5, 4.5); + csm::EcefCoord groundPt(1, 0, 0); + csm::EcefLocus imageLocus(wgs84.getSemiMajorRadius() + 50000, 0, 0, -1, 0, 0); + + // Setup expected calls/returns + EXPECT_CALL(mockModel, groundToImage(MatchEcefCoord(groundPt), ::testing::_, ::testing::_, ::testing::_)) + .Times(1) + .WillRepeatedly(::testing::Return(imagePt)); + EXPECT_CALL(mockModel, imageToRemoteImagingLocus(MatchImageCoord(imagePt), ::testing::_, ::testing::_, ::testing::_)) + .Times(1) + .WillRepeatedly(::testing::Return(imageLocus)); + EXPECT_CALL(mockModel, getImageTime) + .Times(1) + .WillRepeatedly(::testing::Return(10.0)); + try { - FAIL() << "Expected an IException with message \"" - " Declination is not supported for CSM camera models\""; + testCam->SetRightAscensionDeclination(0, 0); + EXPECT_FLOAT_EQ(testCam->Sample(), 5); + EXPECT_FLOAT_EQ(testCam->Line(), 5); + } + catch (IException &e) + { + FAIL() << "Failed test with [" << e.what() << "]"; } } diff --git a/isis/tests/FunctionalTestsCampt.cpp b/isis/tests/FunctionalTestsCampt.cpp index 494477fc8a..7f4e0ae6df 100644 --- a/isis/tests/FunctionalTestsCampt.cpp +++ b/isis/tests/FunctionalTestsCampt.cpp @@ -299,8 +299,6 @@ TEST_F(CSMCubeFixture, FunctionalTestCamptCSMCamera) { PvlGroup groundPoint = appLog.findGroup("GroundPoint"); // Check that invalid values are all set to null - EXPECT_TRUE(groundPoint.findKeyword("RightAscension").isNull()); - EXPECT_TRUE(groundPoint.findKeyword("Declination").isNull()); EXPECT_TRUE(groundPoint.findKeyword("SunPosition").isNull(0)); EXPECT_TRUE(groundPoint.findKeyword("SunPosition").isNull(1)); EXPECT_TRUE(groundPoint.findKeyword("SunPosition").isNull(2)); diff --git a/isis/tests/FunctionalTestsCsminit.cpp b/isis/tests/FunctionalTestsCsminit.cpp index feee61084e..d066941190 100644 --- a/isis/tests/FunctionalTestsCsminit.cpp +++ b/isis/tests/FunctionalTestsCsminit.cpp @@ -8,6 +8,7 @@ #include "TestCsmPlugin.h" #include "TempFixtures.h" #include "CameraFixtures.h" +#include "Table.h" #include "TestUtilities.h" #include "TestCsmModel.h" #include "FileName.h" @@ -28,6 +29,7 @@ class CSMPluginFixture : public TempTestingFiles { Pvl label; QString isdPath; QString altIsdPath; + QString bodyRotationIsdPath; QString filename; TestCsmModel model; AlternativeTestCsmModel altModel; @@ -139,6 +141,9 @@ TEST_F(CSMPluginFixture, CSMInitDefault) { ASSERT_TRUE(testCube->hasGroup("Kernels")); PvlGroup &kernGroup = testCube->group("Kernels"); EXPECT_TRUE(kernGroup.hasKeyword("ShapeModel")); + + // Check that the BodyRotation table does not exist + ASSERT_FALSE(testCube->hasTable("BodyRotation")); } TEST_F(CSMPluginFixture, CSMInitRunTwice) {