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) {