diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9874efdf37a12684a28f2f6334a53172a088826b..4d6c8d9a515c4fc63b2075c4269a701409cd9542 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -37,10 +37,13 @@ release.
### Added
- Added a new dark current correction to hical that works with the higher temperatures recent images are captured at. Use the new config file, $ISISDATA/mro/calibration/hical.0023_darkrate.conf, to enable the new dark current correction over the old dark current correction. Runs of hical without the new dark current correction will also produce an extra line in the output log indicating that the ZeroDarkRate module is disabled. [#4324](https://github.com/USGS-Astrogeology/ISIS3/issues/4324)
+- Added the ability to bundle adjust CSM models in jigsaw. Use the new CSMSOLVESET, CSMSOLVETYPE, and CSMSOLVELIST arguments to specify what you solve for. [#4537](https://github.com/USGS-Astrogeology/ISIS3/pull/4537)
### Changed
- Added the ability to export footprint information from a CaSSIS ISIS Cube label to the generated output PDS4 label in tgocassisrdrgen. [#4473](https://github.com/USGS-Astrogeology/ISIS3/issues/4473)
- isisVarInit.py no longer writes a "cat" statement by default to the activate scripts which cause the ISIS version information to be written on conda activate. This can be included in those scripts via a command line option to isisVarInit.py. Also, a quiet option is provided to isisVarInit.py to suppress its own writing to standard out, if needed.
+- Changed how the images.csv file is output in jigsaw when there are multiple models. Now each sensor model will have its own images.csv file so that column headers can all be correct. For example, a solution involving LRONAC pairs and Apollo Metric images would generate three images.csv files: LRONAC Left, LRONAC Right, and Apollo Metric. [#4324](https://github.com/USGS-Astrogeology/ISIS3/issues/4324)
+- Changed the API of many Bundle utility classes as part of CSM support in jigsaw. [#4324](https://github.com/USGS-Astrogeology/ISIS3/issues/4324)
### Fixed
- Fixed logging in FindFeatures where we were trying to get a non-existent Pvl group from the Pvl log. [#4375](https://github.com/USGS-Astrogeology/ISIS3/issues/4375)
diff --git a/isis/CMakeLists.txt b/isis/CMakeLists.txt
index 84505bb84e59595126d78c7c259a17bd5a6de6a7..ff358769104aaf77ff6197f3b14969a7c020db50 100644
--- a/isis/CMakeLists.txt
+++ b/isis/CMakeLists.txt
@@ -303,7 +303,6 @@ endif(APPLE)
if(pybindings)
find_package(Python REQUIRED)
- find_package(Sip REQUIRED)
endif()
# Iterate through all variables and extract the libraries and include directories
@@ -356,70 +355,6 @@ list(REMOVE_DUPLICATES ALLLIBDIRS)
list(REMOVE_DUPLICATES ALLLIBS)
list(REMOVE_DUPLICATES ALLINCDIRS)
-#===============================================================================
-#===============================================================================
-
-# Set python bindings configuration and set target for generating C++ files
-if(pybindings)
- message("Configuring Python Bindings")
-
- if (NOT DEFINED PYINSTALL_DIR)
- set(PYINSTALL_DIR ${PYTHON_SITE_PACKAGES_DIR})
- endif()
- message(STATUS "PYTHON BINDINGS INSTALL DIR: ${PYINSTALL_DIR}")
-
- # We need to get the locations for sip files, modules, etc.
- set(ISIS_SIP_DIR "${CMAKE_SOURCE_DIR}/sipfiles")
- set(ISIS_SIP_MODULE "${CMAKE_SOURCE_DIR}/sipfiles/master.sip")
- set(SIP_BUILD_FILE "isispy.sbf")
- set(ISIS_SIP_CODE_DIR ${CMAKE_BINARY_DIR}/sipsrc)
-
- # Create the output directory for the new .CPP files
- execute_process(COMMAND mkdir -p "${ISIS_SIP_CODE_DIR}")
-
- # get list of output files exepected from sip
-
- # get the PYQT configuration based flags from Python
- execute_process(COMMAND ${PYTHON_EXECUTABLE} -c
- "from PyQt5.QtCore import PYQT_CONFIGURATION as qtconfigdict;print(qtconfigdict['sip_flags'])"
- OUTPUT_VARIABLE PYQT_SIP_FLAGS)
-
- # CMAKE doesn't handle spaces from python well when piping that into the
- # command because of white space and a trailing new line,
- # so we turn it into a list
- message(STATUS "Getting SIP config...")
- message(STATUS "Attempting 'python -c \"from PyQt5.QtCore import PYQT_CONFIGURATION as qtconfigdict; print(qtconfigdict['sip_flags'])\"'")
-
- if (${PYQT_SIP_FLAGS} STREQUAL "")
- message(FATAL_ERROR "print(qtconfigdict['sip_flags']) returned empty string, is sip installed? Python binding can be disabled with pybindings=OFF")
- endif()
- string(STRIP ${PYQT_SIP_FLAGS} PYQT_SIP_FLAGS)
- string(REPLACE " " ";" PYQT_SIP_FLAGS ${PYQT_SIP_FLAGS})
-
- message(STATUS "FLAGS: ${PYQT_SIP_FLAGS}")
- message(STATUS "Generating C++ code from sip files")
- message(STATUS "SIP BUILD FILE: ${SIP_BUILD_FILE}")
- message(STATUS "SIP MODULE: ${ISIS_SIP_MODULE}")
- message(STATUS "SIP GENERATED CODE DIR: ${ISIS_SIP_CODE_DIR}")
-
- execute_process(COMMAND ${SIP_BINARY_PATH} -e -o -c ${ISIS_SIP_CODE_DIR} -I ${SIP_DEFAULT_SIP_DIR}/PyQt5 ${PYQT_SIP_FLAGS} ${ISIS_SIP_MODULE})
-
- # add target so users can run the command after initial configuration
- add_custom_target(sipfiles
- COMMAND ${SIP_BINARY_PATH} -e -o -c ${ISIS_SIP_CODE_DIR} -I ${SIP_DEFAULT_SIP_DIR}/PyQt5 ${PYQT_SIP_FLAGS} ${ISIS_SIP_MODULE}
- COMMENT "Generating C++ code from sip files")
-
- file(GLOB SIP_GENERATED_SOURCE_FILES ${ISIS_SIP_CODE_DIR}/*.cpp)
- add_library(isispy MODULE ${SIP_GENERATED_SOURCE_FILES})
- target_link_libraries(isispy ${ALLLIBS})
- target_link_libraries(isispy isis)
- set_target_properties(isispy PROPERTIES LINK_DEPENDS isis INSTALL_RPATH ${CMAKE_INSTALL_PREFIX})
- add_dependencies(isispy sipfiles)
-
- install(TARGETS isispy DESTINATION ${PYINSTALL_DIR})
-endif()
-
-
#===============================================================================
#===============================================================================
diff --git a/isis/appdata/serialnumbers/CsmSerialNumber.trn b/isis/appdata/serialnumbers/CsmSerialNumber.trn
new file mode 100644
index 0000000000000000000000000000000000000000..257e18b84ba3469ff7273370f69c890792f48fd8
--- /dev/null
+++ b/isis/appdata/serialnumbers/CsmSerialNumber.trn
@@ -0,0 +1,30 @@
+Group = Keyword1
+ Auto
+ InputKey = CSMPlatformId
+ InputGroup = "IsisCube,CsmInfo"
+ InputPosition = (IsisCube, CsmInfo)
+ OutputName = Keyword1
+ OutputPosition = (Group, SerialNumberKeywords)
+ Translation = (* , *)
+End_Group
+
+Group = Keyword2
+ Auto
+ InputKey = CSMInstrumentId
+ InputGroup = "IsisCube,CsmInfo"
+ InputPosition = (IsisCube, CsmInfo)
+ OutputName = Keyword2
+ OutputPosition = (Group, SerialNumberKeywords)
+ Translation = (*, *)
+End_Group
+
+Group = Keyword3
+ Auto
+ InputKey = ReferenceTime
+ InputGroup = "IsisCube,CsmInfo"
+ InputPosition = (IsisCube, CsmInfo)
+ OutputName = Keyword3
+ OutputPosition = (Group, SerialNumberKeywords)
+ Translation = (*, *)
+End_Group
+End
diff --git a/isis/cmake/FindSip.cmake b/isis/cmake/FindSip.cmake
deleted file mode 100644
index 8ede37c8d7bc7d514e664f475be47d1ce9129b3c..0000000000000000000000000000000000000000
--- a/isis/cmake/FindSip.cmake
+++ /dev/null
@@ -1,44 +0,0 @@
-# Borrowed mostly from the QGIS project: https://github.com/qgis/QGIS
-#
-# SIP_VERSION - The version of SIP found expressed as a 6 digit hex number
-# suitable for comparison as a string.
-#
-# SIP_VERSION_STR - The version of SIP found as a human readable string.
-#
-# SIP_BINARY_PATH - Path and filename of the SIP command line executable.
-#
-# SIP_INCLUDE_DIR - Directory holding the SIP C++ header file.
-#
-# SIP_DEFAULT_SIP_DIR - Default directory where .sip files should be installed
-# into.
-
-IF(SIP_VERSION)
- # Already in cache, be silent
- SET(SIP_FOUND TRUE)
-ELSE(SIP_VERSION)
-
- FIND_FILE(_find_sip_py FindSip.py PATHS ${CMAKE_MODULE_PATH})
-
- EXECUTE_PROCESS(COMMAND ${PYTHON_EXECUTABLE} ${_find_sip_py} OUTPUT_VARIABLE sip_config)
- IF(sip_config)
- STRING(REGEX REPLACE "^sip_version:([^\n]+).*$" "\\1" SIP_VERSION ${sip_config})
- STRING(REGEX REPLACE ".*\nsip_version_num:([^\n]+).*$" "\\1" SIP_VERSION_NUM ${sip_config})
- STRING(REGEX REPLACE ".*\nsip_version_str:([^\n]+).*$" "\\1" SIP_VERSION_STR ${sip_config})
- STRING(REGEX REPLACE ".*\nsip_bin:([^\n]+).*$" "\\1" SIP_BINARY_PATH ${sip_config})
- STRING(REGEX REPLACE ".*\ndefault_sip_dir:([^\n]+).*$" "\\1" SIP_DEFAULT_SIP_DIR ${sip_config})
- STRING(REGEX REPLACE ".*\nsip_inc_dir:([^\n]+).*$" "\\1" SIP_INCLUDE_DIR ${sip_config})
- STRING(REGEX REPLACE ".*\nsip_mod_dir:([^\n]+).*$" "\\1" SIP_MOD_DIR ${sip_config})
- SET(SIP_FOUND TRUE)
- ENDIF(sip_config)
-
- IF(SIP_FOUND)
- IF(NOT SIP_FIND_QUIETLY)
- MESSAGE(STATUS "Found SIP version: ${SIP_VERSION_STR}")
- ENDIF(NOT SIP_FIND_QUIETLY)
- ELSE(SIP_FOUND)
- IF(SIP_FIND_REQUIRED)
- MESSAGE(FATAL_ERROR "Could not find SIP")
- ENDIF(SIP_FIND_REQUIRED)
- ENDIF(SIP_FOUND)
-
-ENDIF(SIP_VERSION)
diff --git a/isis/cmake/FindSip.py b/isis/cmake/FindSip.py
deleted file mode 100644
index 8cbb00fa5caa49ba7b30156ad3a2278d158060b7..0000000000000000000000000000000000000000
--- a/isis/cmake/FindSip.py
+++ /dev/null
@@ -1,13 +0,0 @@
-# Borrowed mostly from the QGIS project: https://github.com/qgis/QGIS
-
-
-import sipconfig
-
-sipcfg = sipconfig.Configuration()
-print("sip_version:%06.0x" % sipcfg.sip_version)
-print("sip_version_num:%d" % sipcfg.sip_version)
-print("sip_version_str:%s" % sipcfg.sip_version_str)
-print("sip_bin:%s" % sipcfg.sip_bin)
-print("default_sip_dir:%s" % sipcfg.default_sip_dir)
-print("sip_inc_dir:%s" % sipcfg.sip_inc_dir)
-print("sip_mod_dir:%s" % sipcfg.sip_mod_dir)
diff --git a/isis/sipfiles/BundleAdjust.sip b/isis/sipfiles/BundleAdjust.sip
deleted file mode 100644
index 76c089a58b46af14503639c8b1252eec837aa503..0000000000000000000000000000000000000000
--- a/isis/sipfiles/BundleAdjust.sip
+++ /dev/null
@@ -1,42 +0,0 @@
-// SIP Wrapper to the ISIS bundle class
-%Include type_conversions.sip
-
-
-namespace Isis {
- class BundleAdjust : public QObject {
- %TypeHeaderCode
- #include "BundleAdjust.h"
- #include "IException.h"
- %End
-
- public:
- // Stuff in the square brackets [] indicate the C++ interface while the sip
- // function name indicates the C python function interface
- BundleAdjust(PyObject* settings, const QString &cnetFile, const QString &cubeList, bool printSummary = true) throw(Isis::IException) [(QSharedPointer, QString, QString, bool)];
- %MethodCode
- int sipErr = 0;
- QSharedPointer *wrappedSettings = new QSharedPointer();
-
- Isis::BundleSettings *settings = (Isis::BundleSettings*) sipConvertToType(a0, sipType_Isis_BundleSettings, NULL, SIP_NOT_NONE, NULL, &sipErr);
- wrappedSettings->reset(settings);
- try {
- sipCpp = new sipIsis_BundleAdjust(*wrappedSettings, *a1, *a2, a3);
- }
- catch (Isis::IException &error) {
- PyErr_SetString(sipException_Isis_IException, error.what());
- return NULL;
- }
- %End
-
- Isis::BundleSolutionInfo* solveCholeskyBR();
- %MethodCode
- try {
- return sipConvertFromType(sipCpp->solveCholeskyBR(), sipType_Isis_BundleSolutionInfo, NULL);
- }
- catch (Isis::IException &error) {
- PyErr_SetString(sipException_Isis_IException, error.what());
- return NULL;
- }
- %End
- };
-};
diff --git a/isis/sipfiles/BundleControlPoint.sip b/isis/sipfiles/BundleControlPoint.sip
deleted file mode 100644
index 934b00bc9426ee359e0df5212b041f4614dc29f3..0000000000000000000000000000000000000000
--- a/isis/sipfiles/BundleControlPoint.sip
+++ /dev/null
@@ -1,68 +0,0 @@
-namespace Isis {
- class BundleControlPoint {
-
- %TypeHeaderCode
- #include "BundleControlPoint.h"
- #include
- %End
-
- public:
-
- SIP_PYTYPE measures() throw(Isis::IException);
- %MethodCode
- size_t size = sipCpp->size();
-
- PyObject *l = PyList_New(size);
- for (size_t i = 0; i < size; ++i) {
- Isis::BundleMeasure* cppMeasure = sipCpp->at(i).data();
-
- PyObject *pyMeasure = sipConvertFromType((void*)(cppMeasure), sipType_Isis_BundleMeasure, NULL);
- PyList_SetItem(l, i, pyMeasure);
- }
-
- return l;
-
- %End
-
- // BundleControlPoint(ControlPoint *point); // default constructor
- BundleControlPoint(const Isis::BundleControlPoint &src) throw(Isis::IException);
- ~BundleControlPoint();
-
- // copy
- void copy(const Isis::BundleControlPoint &src) throw(Isis::IException);
-
- // mutators
- // QSharedPointer addMeasure(ControlMeasure *controlMeasure);
- void computeResiduals() throw(Isis::IException);
- void setNumberOfRejectedMeasures(int numRejected) throw(Isis::IException);
- void setRejected(bool reject) throw(Isis::IException);
- void setWeights(const QSharedPointer settings, double metersToRadians) throw(Isis::IException);
- void zeroNumberOfRejectedMeasures() throw(Isis::IException);
-
- // accessors
- bool isRejected() const throw(Isis::IException);
- int numberOfMeasures() const throw(Isis::IException);
- int numberOfRejectedMeasures() const throw(Isis::IException);
- double residualRms() const throw(Isis::IException);
- QString id() const throw(Isis::IException);
- Isis::ControlPoint::PointType type() const throw(Isis::IException);
-
- // string format methods
- QString formatBundleOutputSummaryString(bool errorPropagation) const throw(Isis::IException);
- QString formatBundleOutputDetailString(bool errorPropagation, double RTM, bool solveRadius=false) throw(Isis::IException) /KeywordArgs="Optional"/;
- QString formatValue(double value, int fieldWidth, int precision) throw(Isis::IException);
- QString formatAprioriSigmaString(int type, int fieldWidth, int precision, bool solveRadius=false) throw(Isis::IException) /KeywordArgs="Optional"/;
- QString formatLatitudeAprioriSigmaString(int fieldWidth, int precision) const throw(Isis::IException);
- QString formatLongitudeAprioriSigmaString(int fieldWidth, int precision) const throw(Isis::IException);
- QString formatRadiusAprioriSigmaString(int fieldWidth, int precision, bool solveRadius=false) throw(Isis::IException) /KeywordArgs="Optional"/;
- QString formatAdjustedSigmaString(int type, int fieldWidth, int precision,
- bool errorPropagation) const throw(Isis::IException);
- QString formatLatitudeAdjustedSigmaString(int fieldWidth, int precision,
- bool errorPropagation) const throw(Isis::IException);
- QString formatLongitudeAdjustedSigmaString(int fieldWidth, int precision,
- bool errorPropagation) const throw(Isis::IException);
- QString formatRadiusAdjustedSigmaString(int fieldWidth, int precision,
- bool errorPropagation) const throw(Isis::IException);
-
- };
-};
diff --git a/isis/sipfiles/BundleImage.sip b/isis/sipfiles/BundleImage.sip
deleted file mode 100644
index bf8d975d4c0a4b5153298bcd2170bd53cba8449c..0000000000000000000000000000000000000000
--- a/isis/sipfiles/BundleImage.sip
+++ /dev/null
@@ -1,16 +0,0 @@
-namespace Isis {
- class BundleImage /NoDefaultCtors/ {
- %TypeHeaderCode
- #include "BundleImage.h"
- %End
- %InstanceCode
- sipCpp = new Isis::BundleImage(NULL, "", "");
- %End
- public:
-
-
- // QSharedPointer parentObservation();
- QString serialNumber() throw(Isis::IException);
- QString fileName() throw(Isis::IException);
- };
-};
diff --git a/isis/sipfiles/BundleMeasure.sip b/isis/sipfiles/BundleMeasure.sip
deleted file mode 100644
index fd2a02942c43eeb0ffa8b4eed656df4059059041..0000000000000000000000000000000000000000
--- a/isis/sipfiles/BundleMeasure.sip
+++ /dev/null
@@ -1,30 +0,0 @@
-%Include type_conversions.sip
-
-namespace Isis {
- class BundleMeasure /NoDefaultCtors/ {
- %TypeHeaderCode
- #include "BundleMeasure.h"
- %End
-
- public:
-
- bool isRejected() const throw(Isis::IException);
- // Camera *camera() const;
- // Isis::BundleControlPoint *parentControlPoint();
- QSharedPointer parentBundleImage() throw(Isis::IException);
- // QSharedPointer parentBundleObservation();
- // const QSharedPointer observationSolveSettings();
-
- double sample() const throw(Isis::IException);
- double sampleResidual() const throw(Isis::IException);
- double line() const throw(Isis::IException);
- double lineResidual() const throw(Isis::IException);
- double residualMagnitude() const throw(Isis::IException);
- QString cubeSerialNumber() const throw(Isis::IException);
- double focalPlaneComputedX() const throw(Isis::IException);
- double focalPlaneComputedY() const throw(Isis::IException);
- double focalPlaneMeasuredX() const throw(Isis::IException);
- double focalPlaneMeasuredY() const throw(Isis::IException);
- int observationIndex() const throw(Isis::IException);
- };
-};
diff --git a/isis/sipfiles/BundleObservationSolveSettings.sip b/isis/sipfiles/BundleObservationSolveSettings.sip
deleted file mode 100644
index 89b28277c0d18004d5feb9c4c3f7542cb84cf7b6..0000000000000000000000000000000000000000
--- a/isis/sipfiles/BundleObservationSolveSettings.sip
+++ /dev/null
@@ -1,59 +0,0 @@
-
-%Import QtCore/QtCoremod.sip
-%Import QtXml/QtXmlmod.sip
-
-namespace Isis{
- class BundleObservationSolveSettings {
- %TypeHeaderCode
- #include "BundleObservationSolveSettings.h"
- %End
- public:
-
- enum InstrumentPointingSolveOption {
- NoPointingFactors = 0, /**< Solve for none of the pointing factors.*/
- AnglesOnly = 1, /**< Solve for pointing angles: right ascension, declination
- and, optionally, twist.*/
- AnglesVelocity = 2, //!< Solve for pointing angles and their angular velocities.
- AnglesVelocityAcceleration = 3, /**< Solve for pointing angles, their velocities and their
- accelerations.*/
- AllPointingCoefficients = 4 /**< Solve for all coefficients in the polynomials fit to
- the pointing angles.*/
- };
-
- //! Options for how to solve for instrument position
- enum InstrumentPositionSolveOption {
- NoPositionFactors = 0, /**< Solve for none of the position factors.*/
- PositionOnly = 1, /**< Solve for instrument positions only.*/
- PositionVelocity = 2, /**< Solve for instrument positions and velocities.*/
- PositionVelocityAcceleration = 3, /**< Solve for instrument positions, velocities, and
- accelerations.*/
- AllPositionCoefficients = 4 /**< Solve for all coefficients in the polynomials fit to
- the instrument positions.*/
- };
-
- BundleObservationSolveSettings() throw(Isis::IException);
- InstrumentPositionSolveOption stringToInstrumentPositionSolveOption(QString option) throw(Isis::IException);
- InstrumentPointingSolveOption stringToInstrumentPointingSolveOption(QString option) throw(Isis::IException);
-
- void setInstrumentPositionSettings(InstrumentPositionSolveOption option,
- int spkDegree = 2,
- int spkSolveDegree = 2,
- bool positionOverHermite = false,
- double positionAprioriSigma = -1.0,
- double velocityAprioriSigma = -1.0,
- double accelerationAprioriSigma = -1.0) throw(Isis::IException) /KeywordArgs="Optional"/;
-
-
- void setInstrumentPointingSettings(InstrumentPointingSolveOption option,
- bool solveTwist,
- int ckDegree = 2,
- int ckSolveDegree = 2,
- bool solvePolynomialOverExisting = false,
- double anglesAprioriSigma = -1.0,
- double angularVelocityAprioriSigma = -1.0,
- double angularAccelerationAprioriSigma = -1.0) throw(Isis::IException) /KeywordArgs="Optional"/;
-
-
-
- };
-};
diff --git a/isis/sipfiles/BundleResults.sip b/isis/sipfiles/BundleResults.sip
deleted file mode 100644
index 777ae54aedd4579a6d2b6f4e3311083cf0a911ac..0000000000000000000000000000000000000000
--- a/isis/sipfiles/BundleResults.sip
+++ /dev/null
@@ -1,125 +0,0 @@
-%Include Statistics.sip
-%Include type_conversions.sip
-
-
-namespace Isis {
- class BundleResults : public QObject {
- %TypeHeaderCode
- #include "BundleResults.h"
- %End
-
- public:
- BundleResults(const Isis::BundleResults &src);
- void initialize();
-
- void resizeSigmaStatisticsVectors(int numberImages);
- // void setRmsImageResidualLists(QList rmsImageLineResiduals,
- // QList rmsImageSampleResiduals,
- // QList rmsImageResiduals);
- // void setRmsImageResidualLists(QVector rmsImageLineResiduals,
- // QVector rmsImageSampleResiduals,
- // QVector rmsImageResiduals);
- // void setSigmaLatitudeRange(Distance minLatDist, Distance maxLatDist,
- // QString minLatPointId, QString maxLatPointId);
- // void setSigmaLongitudeRange(Distance minLonDist, Distance maxLonDist,
- // QString minLonPointId, QString maxLonPointId);
- // void setSigmaRadiusRange(Distance minRadDist, Distance maxRadDist,
- // QString minRadPointId, QString maxRadPointId);
- void setRmsFromSigmaStatistics(double rmsFromSigmaLatStats,
- double rmsFromSigmaLonStats,
- double rmsFromSigmaRadStats);
-
- void printMaximumLikelihoodTierInformation() throw(Isis::IException);
- void incrementMaximumLikelihoodModelIndex() throw(Isis::IException);
-
- void incrementFixedPoints() throw(Isis::IException);
- int numberFixedPoints() const throw(Isis::IException);
- void incrementHeldImages() throw(Isis::IException);
- int numberHeldImages() const throw(Isis::IException);
- void incrementIgnoredPoints() throw(Isis::IException);
- int numberIgnoredPoints() const throw(Isis::IException); // currently unused ???
- void setRejectionLimit(double rejectionLimit) throw(Isis::IException);
- void setRmsXYResiduals(double rx, double ry, double rxy) throw(Isis::IException);
-
- void setNumberRejectedObservations(int numberObservations) throw(Isis::IException);
- void setNumberObservations(int numberObservations) throw(Isis::IException);
- void setNumberImageParameters(int numberParameters) throw(Isis::IException); // ??? this is the same value an m_nRank
- void resetNumberConstrainedPointParameters() throw(Isis::IException);
- void incrementNumberConstrainedPointParameters(int incrementAmount) throw(Isis::IException);
- void resetNumberConstrainedImageParameters() throw(Isis::IException);
- void incrementNumberConstrainedImageParameters(int incrementAmount) throw(Isis::IException);
- void resetNumberConstrainedTargetParameters() throw(Isis::IException);
- void incrementNumberConstrainedTargetParameters(int incrementAmount) throw(Isis::IException);
- void setNumberUnknownParameters(int numberParameters) throw(Isis::IException);
- void computeDegreesOfFreedom() throw(Isis::IException);
-
- void computeSigma0(double dvtpv, Isis::BundleSettings::ConvergenceCriteria criteria) throw(Isis::IException);
- void setDegreesOfFreedom(double degreesOfFreedom) throw(Isis::IException);
- void setSigma0(double sigma0) throw(Isis::IException);
- void setElapsedTime(double time) throw(Isis::IException);
- void setElapsedTimeErrorProp(double time) throw(Isis::IException);
- void setRadiansToMeters(double rtm) throw(Isis::IException);
- void setConverged(bool converged) throw(Isis::IException); // or initialze method
- // void setBundleControlPoints(QVector controlPoints);
- // void setOutputControlNet(QSharedPointer outNet);
- void setIterations(int iterations) throw(Isis::IException);
- // void setObservations(BundleObservationVector observations) throw(Isis::IException);
-
- QList rmsImageSampleResiduals() const throw(Isis::IException);
- QList rmsImageLineResiduals() const throw(Isis::IException);
- QList rmsImageResiduals() const throw(Isis::IException);
- QVector rmsImageXSigmas() const throw(Isis::IException); // currently unused ???
- QVector rmsImageYSigmas() const throw(Isis::IException); // currently unused ???
- QVector rmsImageZSigmas() const throw(Isis::IException); // currently unused ???
- QVector rmsImageRASigmas() const throw(Isis::IException); // currently unused ???
- QVector rmsImageDECSigmas() const throw(Isis::IException); // currently unused ???
- QVector rmsImageTWISTSigmas() const throw(Isis::IException); // currently unused ???
-
- // Distance minSigmaLatitudeDistance() const throw(Isis::IException);
- // Distance maxSigmaLatitudeDistance() const throw(Isis::IException);
- // Distance minSigmaLongitudeDistance() const throw(Isis::IException);
- // Distance maxSigmaLongitudeDistance() const throw(Isis::IException);
- // Distance minSigmaRadiusDistance() const throw(Isis::IException);
- // Distance maxSigmaRadiusDistance() const throw(Isis::IException);
-
- QString maxSigmaLatitudePointId() const throw(Isis::IException);
- QString minSigmaLatitudePointId() const throw(Isis::IException);
- QString minSigmaLongitudePointId() const throw(Isis::IException);
- QString maxSigmaLongitudePointId() const throw(Isis::IException);
- QString minSigmaRadiusPointId() const throw(Isis::IException);
- QString maxSigmaRadiusPointId() const throw(Isis::IException);
- double sigmaLatitudeStatisticsRms() const throw(Isis::IException);
- double sigmaLongitudeStatisticsRms() const throw(Isis::IException);
- double sigmaRadiusStatisticsRms() const throw(Isis::IException);
- double rmsRx() const throw(Isis::IException); // currently unused ???
- double rmsRy() const throw(Isis::IException); // currently unused ???
- double rmsRxy() const throw(Isis::IException); // currently unused ???
- double rejectionLimit() const throw(Isis::IException);
- double radiansToMeters() const throw(Isis::IException);
- int numberRejectedObservations() const throw(Isis::IException);
- int numberObservations() const throw(Isis::IException);
-
- int numberImageParameters() const throw(Isis::IException); // ??? this is the same value an m_nRank
- int numberConstrainedPointParameters() const throw(Isis::IException);
- int numberConstrainedImageParameters() const throw(Isis::IException);
- int numberConstrainedTargetParameters() const throw(Isis::IException);
- int numberUnknownParameters() const throw(Isis::IException);
- int degreesOfFreedom() const throw(Isis::IException);
- double sigma0() const throw(Isis::IException);
- double elapsedTime() const throw(Isis::IException);
- double elapsedTimeErrorProp() const throw(Isis::IException);
- bool converged() const throw(Isis::IException); // or initialze method
-
- QVector > &bundleControlPoints();
- QSharedPointer outputControlNet() const throw(Isis::IException);
-
- int iterations() const throw(Isis::IException);
-
- int numberMaximumLikelihoodModels() const throw(Isis::IException);
- int maximumLikelihoodModelIndex() const throw(Isis::IException);
- double maximumLikelihoodMedianR2Residuals() const throw(Isis::IException);
- double maximumLikelihoodModelQuantile(int modelIndex) const throw(Isis::IException);
-
- };
-
-};
diff --git a/isis/sipfiles/BundleSettings.sip b/isis/sipfiles/BundleSettings.sip
deleted file mode 100644
index b6f9799ab4ee37c1413122dbb13b4cd5c1959683..0000000000000000000000000000000000000000
--- a/isis/sipfiles/BundleSettings.sip
+++ /dev/null
@@ -1,113 +0,0 @@
-%Include BundleObservationSolveSettings.sip
-%Include MaximumLikelihoodWFunctions.sip
-
-%Include type_conversions.sip
-
-namespace Isis {
-
- class BundleSettings {
- %TypeHeaderCode
- #include "BundleSettings.h"
- #include "BundleObservationSolveSettings.h"
- #include
- %End
- public:
-
- enum ConvergenceCriteria {
- Sigma0, /**< The value of sigma0 will be used to determine that the bundle
- adjustment has converged.*/
- ParameterCorrections /**< All parameter corrections will be used to determine that the
- bundle adjustment has converged.*/
- };
-
- // enum MaximumLikelihoodModel {
- // NoMaximumLikelihoodEstimator,
- // Huber,
- // ModifiedHuber,
- // Welsch,
- // Chen
- // };
-
- BundleSettings() throw(Isis::IException);
-
- void setValidateNetwork(bool) throw(Isis::IException);
-
- void setSolveOptions(bool solveObservationMode = false,
- bool updateCubeLabel = false,
- bool errorPropagation = false,
- bool solveRadius = false,
- double globalLatitudeAprioriSigma = Isis::Null,
- double globalLongitudeAprioriSigma = Isis::Null,
- double globalRadiusAprioriSigma = Isis::Null) throw(Isis::IException) /KeywordArgs="Optional"/;
-
- void setOutlierRejection(bool outlierRejection,
- double multiplier = 1.0) throw(Isis::IException);
-
- bool solveObservationMode() const throw(Isis::IException);
- bool solveRadius() const throw(Isis::IException);
- bool updateCubeLabel() const throw(Isis::IException);
- bool errorPropagation() const throw(Isis::IException);
- bool outlierRejection() const throw(Isis::IException);
- double outlierRejectionMultiplier() const throw(Isis::IException);
- double globalLatitudeAprioriSigma() const throw(Isis::IException);
- double globalLongitudeAprioriSigma() const throw(Isis::IException);
- double globalRadiusAprioriSigma() const throw(Isis::IException);
-
- int numberSolveSettings() const throw(Isis::IException);
- Isis::BundleObservationSolveSettings observationSolveSettings(QString instrumentId) const throw(Isis::IException);
- Isis::BundleObservationSolveSettings observationSolveSettings(int n) const throw(Isis::IException);
-
- void setObservationSolveOptions(QList);
- // %MethodCode
- // Py_ssize_t size = PyList_Size(a0);
- // QList *cppSettingsList = new QList();
- // int sipErr = 0;
- // for(int i = 0; i < size; i++) {
- // PyObject *pyStat = PyList_GET_ITEM(a0, i);
- // Isis::BundleObservationSolveSettings *settings = (Isis::BundleObservationSolveSettings*)sipConvertToType(pyStat, sipType_Isis_BundleObservationSolveSettings, NULL, SIP_NOT_NONE, NULL, &sipErr);
- // cppSettingsList->append(*settings);
- // }
- //
- // sipCpp->setObservationSolveOptions(*cppSettingsList);
- // %End
-
- SIP_PYLIST maximumLikelihoodEstimatorModels() const throw(Isis::IException);
- %MethodCode // convert QList to Python list if tuples
- typedef Isis::MaximumLikelihoodWFunctions::Model Model;
- size_t size = sipCpp->maximumLikelihoodEstimatorModels().size();
- PyObject *l = PyList_New(size);
- for (size_t i = 0; i < size; ++i) {
- // get the two items from the QPair
- Model *model = new Model(sipCpp->maximumLikelihoodEstimatorModels()[i].first);
- double doubl = sipCpp->maximumLikelihoodEstimatorModels()[i].second;
-
- // Convert the two items to PyObjects
- PyObject *first = sipConvertFromType((void*)(model), sipType_Isis_MaximumLikelihoodWFunctions_Model, NULL);
- PyObject *second = PyFloat_FromDouble(doubl);
-
- // set the tuple items
- PyObject *tuple = PyTuple_New(2);
- PyTuple_SetItem(tuple, 0, first);
- PyTuple_SetItem(tuple, 1, second);
-
- // Add new tuple to list
- PyList_SetItem(l, i, tuple);
- }
- return l;
- %End
-
-
- int numberTargetBodyParameters() const throw(Isis::IException);
- bool solveTargetBody() const throw(Isis::IException);
- bool solvePoleRA() const throw(Isis::IException);
- bool solvePoleRAVelocity() const throw(Isis::IException);
- bool solvePoleDec() const throw(Isis::IException);
- bool solvePoleDecVelocity() const throw(Isis::IException);
- bool solvePM() const throw(Isis::IException);
- bool solvePMVelocity() const throw(Isis::IException);
- bool solvePMAcceleration() const throw(Isis::IException);
- bool solveTriaxialRadii() const throw(Isis::IException);
- bool solveMeanRadius() const throw(Isis::IException);
-
- };
-};
diff --git a/isis/sipfiles/BundleSolutionInfo.sip b/isis/sipfiles/BundleSolutionInfo.sip
deleted file mode 100644
index a43fba1bd763c1169b861bc4bccdda657682f149..0000000000000000000000000000000000000000
--- a/isis/sipfiles/BundleSolutionInfo.sip
+++ /dev/null
@@ -1,26 +0,0 @@
-
-%Include type_conversions.sip
-
-namespace Isis{
-
-class BundleSolutionInfo : public QObject {
- %TypeHeaderCode
- #include "BundleSolutionInfo.h"
- %End
-
- public:
- // do constructor since at the moment there doesn't seem to be a reason to contruct it directly in the python side
- void setOutputStatistics(Isis::BundleResults statisticsResults) throw(Isis::IException);
- void setRunTime(QString runTime) throw(Isis::IException);
-
- QString id() const throw(Isis::IException);
- QSharedPointer bundleSettings() throw(Isis::IException);
- Isis::BundleResults bundleResults() throw(Isis::IException);
- QString runTime() const throw(Isis::IException);
-
- bool outputText() throw(Isis::IException);
- bool outputPointsCSV() throw(Isis::IException);
- bool outputResiduals() throw(Isis::IException);
-
- }; // end namespace Isis
-};
diff --git a/isis/sipfiles/ControlNet.sip b/isis/sipfiles/ControlNet.sip
deleted file mode 100644
index 73408334cfc579dcb622c8376853677b9ff805d2..0000000000000000000000000000000000000000
--- a/isis/sipfiles/ControlNet.sip
+++ /dev/null
@@ -1,31 +0,0 @@
-namespace Isis {
- class ControlNet : public QObject {
- %TypeHeaderCode
- #include "ControlNet.h"
- %End
- public:
- ControlNet() throw(Isis::IException);
- ControlNet(const Isis::ControlNet &other) throw(Isis::IException);
-
- void clear() throw(Isis::IException);
-
- void Write(const QString &filename, bool pvl = false) throw(Isis::IException);
-
- double GetMaximumResidual() throw(Isis::IException);
- QString GetNetworkId() const throw(Isis::IException);
- int GetNumEditLockMeasures() throw(Isis::IException);
- int GetNumEditLockPoints() throw(Isis::IException);
- int GetNumIgnoredMeasures() throw(Isis::IException);
- int GetNumberOfValidMeasuresInImage(const QString &serialNumber) throw(Isis::IException);
- int GetNumberOfJigsawRejectedMeasuresInImage(const QString &serialNumber) throw(Isis::IException);
- void ClearJigsawRejected() throw(Isis::IException);
- void IncrementNumberOfRejectedMeasuresInImage(const QString &serialNumber) throw(Isis::IException);
- void DecrementNumberOfRejectedMeasuresInImage(const QString &serialNumber) throw(Isis::IException);
- int GetNumMeasures() const throw(Isis::IException);
- int GetNumPoints() const throw(Isis::IException);
- int GetNumValidMeasures() throw(Isis::IException);
- int GetNumValidPoints() throw(Isis::IException);
- QString GetTarget() const throw(Isis::IException);
- QString GetUserName() const throw(Isis::IException);
- };
-};
diff --git a/isis/sipfiles/ControlPoint.sip b/isis/sipfiles/ControlPoint.sip
deleted file mode 100644
index 8dd80250aa2d52a8f4348137ae41d44a05a76e34..0000000000000000000000000000000000000000
--- a/isis/sipfiles/ControlPoint.sip
+++ /dev/null
@@ -1,302 +0,0 @@
-namespace Isis {
-
- class ControlPoint : public QObject {
- %TypeHeaderCode
- #include "ControlPoint.h"
- %End
- public:
- enum PointType {
- Fixed = 0,
- Constrained = 1,
- Free = 2
- };
-
-
- enum Status {
- Failure,
- Success,
- PointLocked
- };
-
- enum ConstraintStatus {
- LatitudeConstrained = 0,
- LongitudeConstrained = 1,
- RadiusConstrained = 2,
-// XConstrained = 3,
-// YConstrained = 4,
-// ZConstrained = 5;
- };
-
- // This stuff input to jigsaw
- // How did apriori source get computed??
- struct SurfacePointSource {
- enum Source {
- None,
- User,
- AverageOfMeasures,
- Reference,
- Basemap,
- BundleSolution
- };
- };
-
- struct RadiusSource {
- enum Source {
- None,
- User,
- AverageOfMeasures,
- Ellipsoid,
- DEM,
- BundleSolution
- };
- };
-
- ControlPoint() throw(Isis::IException);
- ControlPoint(const QString &id) throw(Isis::IException);
-
- // Isis::ControlNet *Parent() { return parentNetwork; }
-
- // void Load(PvlObject &p) throw(Isis::IException);
-
- // void Add(ControlMeasure *measure) throw(Isis::IException);
- // int Delete(ControlMeasure *measure) throw(Isis::IException);
- // int Delete(QString serialNumber) throw(Isis::IException);
- // int Delete(int index) throw(Isis::IException);
- // Status ResetApriori() throw(Isis::IException);
-
- // const Isis::ControlMeasure *GetMeasure(QString serialNumber) const throw(Isis::IException);
- // ControlMeasure *GetMeasure(QString serialNumber) throw(Isis::IException);
-
- // const ControlMeasure *GetMeasure(int index) const throw(Isis::IException);
- // ControlMeasure *GetMeasure(int index) throw(Isis::IException);
-
- // const ControlMeasure *GetRefMeasure() const throw(Isis::IException);
- // ControlMeasure *GetRefMeasure() throw(Isis::IException);
-
- // Status SetChooserName(QString name) throw(Isis::IException);
- // Status SetDateTime(QString newDateTime) throw(Isis::IException);
- // Status SetEditLock(bool editLock) throw(Isis::IException);
- // Status SetId(QString id) throw(Isis::IException);
- // Status SetRefMeasure(ControlMeasure *cm) throw(Isis::IException);
- // Status SetRefMeasure(int index) throw(Isis::IException);
- // Status SetRefMeasure(QString sn) throw(Isis::IException);
- // Status SetRejected(bool rejected) throw(Isis::IException);
- // Status SetIgnored(bool newIgnoreStatus) throw(Isis::IException);
- // Status SetAdjustedSurfacePoint(SurfacePoint newSurfacePoint) throw(Isis::IException);
- // Status SetType(PointType newType) throw(Isis::IException);
- //
- // Status SetAprioriRadiusSource(RadiusSource::Source source) throw(Isis::IException);
- // Status SetAprioriRadiusSourceFile(QString sourceFile) throw(Isis::IException);
- // Status SetAprioriSurfacePoint(SurfacePoint aprioriSP) throw(Isis::IException);
- // Status SetAprioriSurfacePointSource(SurfacePointSource::Source source) throw(Isis::IException);
- // Status SetAprioriSurfacePointSourceFile(QString sourceFile) throw(Isis::IException);
-
- // Status UpdateSphericalPointCoordinates(const Latitude &lat, const Longitude &lon,
- // const Distance &radius) throw(Isis::IException);
-
- // Status ComputeApriori() throw(Isis::IException);
- // Status ComputeResiduals() throw(Isis::IException);
- // Status ComputeResiduals_Millimeters() throw(Isis::IException);
- //
- // SurfacePoint GetAdjustedSurfacePoint() const throw(Isis::IException);
- // SurfacePoint GetBestSurfacePoint() const throw(Isis::IException);
-
- QString GetChooserName() const throw(Isis::IException);
- QString GetDateTime() const throw(Isis::IException);
- bool IsEditLocked() const throw(Isis::IException);
- bool IsRejected() const throw(Isis::IException);
- QString GetId() const throw(Isis::IException);
- bool IsIgnored() const throw(Isis::IException);
- bool IsValid() const throw(Isis::IException);
- bool IsInvalid() const throw(Isis::IException);
- bool IsFixed() const throw(Isis::IException);
-
- bool HasAprioriCoordinates() throw(Isis::IException);
- bool IsConstrained() throw(Isis::IException);
- bool IsLatitudeConstrained() throw(Isis::IException);
- bool IsLongitudeConstrained() throw(Isis::IException);
- bool IsRadiusConstrained() throw(Isis::IException);
- int NumberOfConstrainedCoordinates() throw(Isis::IException);
-
- static QString PointTypeToString(PointType type) throw(Isis::IException);
- static PointType StringToPointType(QString pointTypeString) throw(Isis::IException);
-
- QString GetPointTypeString() const throw(Isis::IException);
- // PointType GetType() const throw(Isis::IException);
-
- static QString RadiusSourceToString(RadiusSource::Source source) throw(Isis::IException);
- static RadiusSource::Source StringToRadiusSource(QString str) throw(Isis::IException);
- QString GetRadiusSourceString() const throw(Isis::IException);
- static QString SurfacePointSourceToString(SurfacePointSource::Source source) throw(Isis::IException);
- // static SurfacePointSource::Source StringToSurfacePointSource(QString str) throw(Isis::IException);
- QString GetSurfacePointSourceString() const throw(Isis::IException);
-
- // SurfacePoint GetAprioriSurfacePoint() const throw(Isis::IException);
- // RadiusSource::Source GetAprioriRadiusSource() const throw(Isis::IException);
- // QString GetAprioriRadiusSourceFile() const throw(Isis::IException);
- // SurfacePointSource::Source GetAprioriSurfacePointSource() const throw(Isis::IException);
- // QString GetAprioriSurfacePointSourceFile() const throw(Isis::IException);
-
- int GetNumMeasures() const throw(Isis::IException);
- int GetNumValidMeasures() const throw(Isis::IException);
- int GetNumLockedMeasures() const throw(Isis::IException);
- bool HasSerialNumber(QString serialNumber) const throw(Isis::IException);
- // int IndexOf(ControlMeasure *, bool throws = true) const throw(Isis::IException);
- int IndexOf(QString sn, bool throws = true) const throw(Isis::IException);
- int IndexOfRefMeasure() const throw(Isis::IException);
- bool IsReferenceExplicit() const throw(Isis::IException);
- QString GetReferenceSN() const throw(Isis::IException);
-
- // Statistics GetStatistic(double(ControlMeasure::*statFunc)() const) const throw(Isis::IException);
- // Statistics GetStatistic(long dataType) const throw(Isis::IException);
-
- // QList< ControlMeasure * > getMeasures(bool excludeIgnored = false) const throw(Isis::IException);
- // QList< QString > getCubeSerialNumbers() const throw(Isis::IException);
-
- // const ControlMeasure *operator[](QString serialNumber) const throw(Isis::IException);
- // ControlMeasure *operator[](QString serialNumber) throw(Isis::IException);
-
- // const ControlMeasure *operator[](int index) const throw(Isis::IException);
- // ControlMeasure *operator[](int index) throw(Isis::IException);
-
- // bool operator!=(const ControlPoint &pPoint) const throw(Isis::IException);
- // bool operator==(const ControlPoint &pPoint) const throw(Isis::IException);
- // const ControlPoint &operator=(const ControlPoint &pPoint) throw(Isis::IException);
-
- // The next 7 methods are specifically to support BundleAdjust
- void ZeroNumberOfRejectedMeasures() throw(Isis::IException);
- void SetNumberOfRejectedMeasures(int numRejected) throw(Isis::IException);
- int GetNumberOfRejectedMeasures() const throw(Isis::IException);
- double GetSampleResidualRms() const throw(Isis::IException);
- double GetLineResidualRms() const throw(Isis::IException);
- double GetResidualRms() const throw(Isis::IException);
- void ClearJigsawRejected() throw(Isis::IException);
-
- // ControlPointFileEntryV0002 ToFileEntry() const throw(Isis::IException);
-
- private:
- // void SetExplicitReference(ControlMeasure *measure) throw(Isis::IException);
- void ValidateMeasure(QString serialNumber) const throw(Isis::IException);
- // void AddMeasure(ControlMeasure *measure) throw(Isis::IException);
- void PointModified() throw(Isis::IException);
-
-
- // private:
- // ControlNet *parentNetwork;
- //
- // //!< List of Control Measures
- // QHash< QString, ControlMeasure * > * measures;
- //
- // QStringList *cubeSerials;
- //
- // ControlMeasure *referenceMeasure;
- //
- // /**
- // * This is the control point ID. This is supposed to be a unique
- // * identifier for control points. This often has a number in it, and
- // * looks like "T0052" where the next one is "T0053" and so on.
- // */
- // QString id;
- //
- // /**
- // * This is the user name of the person who last modified this control
- // * point. Modifications are things like updating the surface point, but
- // * not things like updating the last modified time. The calculations
- // * relating to this control point have to actually change for this to
- // * be updated. This is an empty string if we need to dynamically
- // * get the username of the caller when asked for (or written to file).
- // */
- // QString chooserName;
- //
- // /**
- // * This is the last modified date and time. This is updated automatically
- // * and works virtually in the same way as chooserName.
- // */
- // QString dateTime;
- //
- // /**
- // * What this control point is tying together.
- // * @see PointType
- // */
- // PointType type;
- //
- // /**
- // * If we forced a build that we would normally have thrown an exception
- // * for then this is set to true. Otherwise, and most of the time, this
- // * is false.
- // */
- // bool invalid;
- //
- // /**
- // * This stores the edit lock state.
- // * @see SetEditLock
- // */
- // bool editLock;
- //
- // /**
- // * This stores the jigsaw rejected state.
- // * @see SetJigsawReject
- // */
- // bool jigsawRejected;
- //
- // /**
- // * This stores the constraint status of the a priori SurfacePoint
- // * @todo Eventually add x, y, and z
- // */
- // std::bitset<6> constraintStatus;
- //
- // /**
- // * This indicates if a program has explicitely set the reference in this
- // * point or the implicit reference is still the current reference. This
- // * is useful for programs that want to choose the reference for all
- // * points where this hasn't happened yet.
- // */
- // bool referenceExplicitlySet;
- //
- // /**
- // * True if we should preserve but ignore the entire control point and its
- // * measures.
- // */
- // bool ignore;
- //
- // //! Where the apriori surface point originated from
- // SurfacePointSource::Source aprioriSurfacePointSource;
- //
- // //! FileName where the apriori surface point originated from
- // QString aprioriSurfacePointSourceFile;
- //
- // /**
- // * Where the apriori surface point's radius originated from, most commonly
- // * used by jigsaw.
- // */
- // RadiusSource::Source aprioriRadiusSource;
- //
- // /**
- // * The name of the file that derives the apriori surface point's radius
- // */
- // QString aprioriRadiusSourceFile;
- //
- // /**
- // * The apriori surface point. This is the "known truth" or trustworthy
- // * point that should not be modified unless done very explicitely. This
- // * comes from places like hand picking where you really don't want the
- // * surface point to vary far from this point, but some variation is
- // * okay (1/10th of a pixel is fair for human accuracy for example). Very
- // * often this point does not exist.
- // */
- // SurfacePoint aprioriSurfacePoint;
- //
- // /**
- // * This is the calculated, or aposterori, surface point. This is what most
- // * programs should be working with and updating.
- // */
- // SurfacePoint adjustedSurfacePoint;
- //
- // /**
- // * This parameter is used and maintained by BundleAdjust for the jigsaw
- // * application. It is stored here because ControlPoint contains the index
- // * of the measures.
- // */
- // int numberOfRejectedMeasures;
- };
-};
diff --git a/isis/sipfiles/MaximumLikelihoodWFunctions.sip b/isis/sipfiles/MaximumLikelihoodWFunctions.sip
deleted file mode 100644
index cbc668d80d58796b89d7039716272285704aad0e..0000000000000000000000000000000000000000
--- a/isis/sipfiles/MaximumLikelihoodWFunctions.sip
+++ /dev/null
@@ -1,52 +0,0 @@
-namespace Isis {
-
- class MaximumLikelihoodWFunctions {
- %TypeHeaderCode
- #include "MaximumLikelihoodWFunctions.h"
- %End
-
- public:
-
- enum Model {
- Huber,
- HuberModified,
- Welsch,
- Chen
- };
-
- static QString modelToString(Model model) throw(Isis::IException);
- static Isis::MaximumLikelihoodWFunctions::Model stringToModel(QString modelName) throw(Isis::IException);
-
- MaximumLikelihoodWFunctions() throw(Isis::IException);
- MaximumLikelihoodWFunctions(Model modelSelection) throw(Isis::IException);
- MaximumLikelihoodWFunctions(Model modelSelection, double tweakingConstant) throw(Isis::IException);
- MaximumLikelihoodWFunctions(const Isis::MaximumLikelihoodWFunctions &other) throw(Isis::IException);
-
- void setModel(Model modelSelection) throw(Isis::IException); // uses default tweaking constant
- void setTweakingConstantDefault() throw(Isis::IException);
-
- void setModel(Model modelSelection, double tweakingConstant) throw(Isis::IException);
- void setTweakingConstant(double tweakingConstant) throw(Isis::IException);
-
- Model model() const throw(Isis::IException);
- double tweakingConstant() const throw(Isis::IException);
-
- // the W functions provide an additional weighting factor W which is used
- // to 're-weight' each observation dynamically during an adjustment, the
- // scalar functions provide access to various flavors of this scalar (as
- // a function of the residual divided by the residuals sigma)
-
- double sqrtWeightScaler(double residualZScore) throw(Isis::IException); //it is often convient to use square roots of
- //weights when building normals, this function
- // provides the scaler for the square root of
- // the weight directly
- double tweakingConstantQuantile() throw(Isis::IException); // returns which quantile of the residuals is recommended to
- // use as the tweaking constant, this varies as a function of
- // the model being employed
-
- QString weightedResidualCutoff() throw(Isis::IException);
-
- QDataStream &write(QDataStream &stream) const throw(Isis::IException);
- QDataStream &read(QDataStream &stream) throw(Isis::IException);
- };
-};
diff --git a/isis/sipfiles/Statistics.sip b/isis/sipfiles/Statistics.sip
deleted file mode 100644
index 089b76a636977a614cae8812eacdf742b74263e7..0000000000000000000000000000000000000000
--- a/isis/sipfiles/Statistics.sip
+++ /dev/null
@@ -1,41 +0,0 @@
-
-namespace Isis {
- class Statistics : public QObject {
- %TypeHeaderCode
- #include "Statistics.h"
- %End
- public:
- Statistics(const Isis::Statistics &other) throw(Isis::IException);
-
- void Reset() throw(Isis::IException);
-
- void AddData(const double *data, const unsigned int count) throw(Isis::IException);
- void AddData(const double data) throw(Isis::IException);
-
- void RemoveData(const double *data, const unsigned int count) throw(Isis::IException);
- void RemoveData(const double data) throw(Isis::IException);
-
- double ValidMinimum() const throw(Isis::IException);
- double ValidMaximum() const throw(Isis::IException);
- bool InRange(const double value) throw(Isis::IException);
- bool AboveRange(const double value) throw(Isis::IException);
- bool BelowRange(const double value) throw(Isis::IException);
-
- double Average() const throw(Isis::IException);
- double StandardDeviation() const throw(Isis::IException);
- double Variance() const throw(Isis::IException);
- double Sum() const throw(Isis::IException);
- double SumSquare() const throw(Isis::IException);
- double Rms() const throw(Isis::IException);
-
- double Minimum() const throw(Isis::IException);
- double Maximum() const throw(Isis::IException);
- double ChebyshevMinimum(const double percent = 99.5) const throw(Isis::IException);
- double ChebyshevMaximum(const double percent = 99.5) const throw(Isis::IException);
- double BestMinimum(const double percent = 99.5) const throw(Isis::IException);
- double BestMaximum(const double percent = 99.5) const throw(Isis::IException);
- double ZScore(const double value) const throw(Isis::IException);
-
- bool RemovedData() const throw(Isis::IException);
- };
-};
diff --git a/isis/sipfiles/master.sip b/isis/sipfiles/master.sip
deleted file mode 100644
index 2cdb950c9cb1b90d2b3d9339ffc009ad26cbee7c..0000000000000000000000000000000000000000
--- a/isis/sipfiles/master.sip
+++ /dev/null
@@ -1,75 +0,0 @@
-%Module(name=libisispy,
- version=0,
- keyword_arguments="Optional")
-
-%ExportedHeaderCode
- #include
- #include
- #include
- #include
- #include
-
- using namespace std;
-
- // Wraps glob to return a STD vector to avoid dealing with C style globbing
- inline vector glob(const QString& pat){
- glob_t glob_result;
- glob(pat.toLatin1().data(),GLOB_TILDE,NULL,&glob_result);
- vector ret;
- for(unsigned int i=0;i libs = glob(pat);
- QLibrary lib_loader;
-
- for (vector::const_iterator i = libs.begin(); i != libs.end(); ++i) {
- // Strip extension
- QFileInfo file(*i);
- QString lib_dir = file.path() + "/" + file.completeBaseName();
-
- lib_loader.setFileName(lib_dir);
-
- // Load hint required for symbols to be accessible to other libraries loaded later
- lib_loader.setLoadHints(QLibrary::ExportExternalSymbolsHint);
-
- bool load_ok = lib_loader.load();
-
- // if verbose is true, print out load info
- if (verbose) {
- if (load_ok) {
- cout << "Loaded " + lib_dir.toStdString() + " : OK" << endl;
- }
- else if (!load_ok) {
- cout << "Loaded " + lib_dir.toStdString() + " : FAILED" << endl
- << lib_loader.errorString().toStdString() << endl;
- }
- }
- }
- }
-%End
-
-%Include type_conversions.sip
-
-%Include ControlPoint.sip
-%Include BundleMeasure.sip
-%Include BundleControlPoint.sip
-%Include BundleImage.sip
-%Include ControlNet.sip
-%Include Statistics.sip
-%Include BundleResults.sip
-%Include BundleSolutionInfo.sip
-%Include BundleObservationSolveSettings.sip
-%Include BundleSettings.sip
-%Include BundleAdjust.sip
-%Include MaximumLikelihoodWFunctions.sip
diff --git a/isis/sipfiles/type_conversions.sip b/isis/sipfiles/type_conversions.sip
deleted file mode 100644
index 7a337c444f80e475d9510e0081d7551d46f24f74..0000000000000000000000000000000000000000
--- a/isis/sipfiles/type_conversions.sip
+++ /dev/null
@@ -1,292 +0,0 @@
-
-%Import QtCore/QtCoremod.sip
-%Import QtXml/QtXmlmod.sip
-
-
-
-%Exception Isis::IException(SIP_Exception) /PyName=IException/
-{
-%TypeHeaderCode
-#include "IException.h"
-%End
-%RaiseCode
- const char *detail = sipExceptionRef.what();
-
- SIP_BLOCK_THREADS
- PyErr_SetString(sipException_Isis_IException, detail);
- SIP_UNBLOCK_THREADS
-%End
-};
-
-
-%MappedType QVector >
-{
- %TypeHeaderCode
- #include "BundleControlPoint.h"
- #include
- %End
-
- %ConvertFromTypeCode
- size_t size = sipCpp->size();
- PyObject *l = PyList_New(size);
- for (size_t i = 0; i < size; ++i) {
-
- Isis::BundleControlPoint* cppCPoint = sipCpp->at(i).data();
-
- PyObject *pyCPoint = sipConvertFromType((void*)(cppCPoint), sipType_Isis_BundleControlPoint, NULL);
- PyList_SetItem(l, i, pyCPoint);
- }
-
- return l;
- %End
-
- %ConvertToTypeCode
- Py_ssize_t size = PyList_Size(sipPy);
- QVector > *cppPointList = new QVector > ();
- int sipErr = 0;
- for(int i = 0; i < size; i++) {
- PyObject *pyCPoint = PyList_GET_ITEM(sipPy, i);
- Isis::BundleControlPoint *cppCPoint = (Isis::BundleControlPoint*)sipConvertToType(pyCPoint, sipType_Isis_BundleControlPoint, NULL, SIP_NOT_NONE, NULL, &sipErr);
- cppPointList->append(QSharedPointer(cppCPoint));
- }
-
- *sipCppPtr = cppPointList;
- return sipGetState(sipTransferObj);
- %End
-
-};
-
-%MappedType QList
-{
- %TypeHeaderCode
- #include "Statistics.h"
- #include
- %End
-
- %ConvertFromTypeCode
- size_t size = sipCpp->size();
- PyObject *l = PyList_New(size);
- for (size_t i = 0; i < size; ++i) {
- Isis::Statistics* cppStats = new Isis::Statistics(sipCpp->at(i));
- PyObject *pyStats = sipConvertFromType((void*)(cppStats), sipType_Isis_Statistics, NULL);
- PyList_SetItem(l, i, pyStats);
- }
-
- return l;
- %End
-
- %ConvertToTypeCode
- Py_ssize_t size = PyList_Size(sipPy);
- QList *cppStatList = new QList();
- int sipErr = 0;
- for(int i = 0; i < size; i++) {
- PyObject *pyStat = PyList_GET_ITEM(sipPy, i);
- Isis::Statistics *stats = (Isis::Statistics*)sipConvertToType(pyStat, sipType_Isis_Statistics, NULL, SIP_NOT_NONE, NULL, &sipErr);
- cppStatList->append(*stats);
- }
-
- *sipCppPtr = cppStatList;
- return sipGetState(sipTransferObj);
- %End
-};
-
-
-
-%MappedType QList
-{
- %TypeHeaderCode
- #include "BundleObservationSolveSettings.h"
- #include
- %End
-
- %ConvertFromTypeCode
- PyObject *l;
-
- // Create the Python list of the correct length.
- if ((l = PyList_New(sipCpp->size())) == NULL)
- return NULL;
-
- for (int i = 0; i < sipCpp->size(); ++i) {
- Isis::BundleObservationSolveSettings *settings = new Isis::BundleObservationSolveSettings(sipCpp->at(i));
-
- PyObject *pySettings = sipConvertFromType((void*)(settings), sipType_Isis_BundleObservationSolveSettings, NULL);
- PyList_SetItem(l, i, pySettings);
- }
-
- return l;
- %End
-
-
- %ConvertToTypeCode
- if (!sipIsErr) {
- if (!PyList_Check(sipPy))
- return 0;
-
- for (int i = 0; i < PyList_GET_SIZE(sipPy); ++i)
- if (!sipCanConvertToType(PyList_GET_ITEM(sipPy, i),
- sipType_Isis_BundleObservationSolveSettings, SIP_NOT_NONE))
- return 0;
-
- return 1;
- }
-
- Py_ssize_t size = PyList_Size(sipPy);
-
- QList *cppSettingsList = new QList();
- int state;
-
- for(Py_ssize_t i = 0; i < size; i++) {
- PyObject *pySettings = PyList_GET_ITEM(sipPy, i);
- Isis::BundleObservationSolveSettings *settings;
-
- settings = (Isis::BundleObservationSolveSettings*)sipConvertToType(pySettings, sipType_Isis_BundleObservationSolveSettings, 0, SIP_NOT_NONE, &state, sipIsErr);
-
- if (*sipIsErr) {
- sipReleaseType(pySettings, sipType_Isis_BundleObservationSolveSettings, state);
- delete cppSettingsList;
- return 0;
- }
-
- cppSettingsList->append(*settings);
- sipReleaseType(pySettings, sipType_Isis_BundleObservationSolveSettings, state);
- }
-
- *sipCppPtr = cppSettingsList;
- return sipGetState(sipTransferObj);
- %End
-};
-
-// convert Bundlesettings wrapped in a QSharedPointer in Isis
-%MappedType QSharedPointer
-{
- %TypeHeaderCode
- #include "BundleImage.h"
- #include
- %End
-
- %ConvertFromTypeCode
- Isis::BundleImage *cpp = sipCpp->data();
- PyObject *py = sipConvertFromType(cpp, sipType_Isis_BundleImage, NULL);
- return py;
- %End
-
- %ConvertToTypeCode
- int sipErr = 0;
- QSharedPointer* cpp_qsp = new QSharedPointer();
- Isis::BundleImage *cpp = (Isis::BundleImage*)sipConvertToType(sipPy, sipType_Isis_BundleImage, NULL, SIP_NOT_NONE, NULL, &sipErr);
- cpp_qsp->reset(cpp);
- *sipCppPtr = cpp_qsp;
-
- return sipGetState(sipTransferObj);
- %End
-};
-
-
-// convert Bundlesettings wrapped in a QSharedPointer in Isis
-%MappedType QSharedPointer
-{
- %TypeHeaderCode
- #include "BundleSettings.h"
- #include
- using namespace std;
- %End
-
- %ConvertFromTypeCode
- Isis::BundleSettings *settings = sipCpp->data();
- PyObject *pySettings = sipConvertFromType(settings, sipType_Isis_BundleSettings, NULL);
- return pySettings;
- %End
-
- %ConvertToTypeCode
- int sipErr = 0;
- QSharedPointer* wrappedSettings = new QSharedPointer();
-
- Isis::BundleSettings *settings = (BundleSettings*) sipConvertToType(sipPy, sipType_Isis_BundleSettings, NULL, SIP_NOT_NONE, NULL, &sipErr);
- wrappedSettings->reset(settings);
- *sipCppPtr = wrappedSettings;
-
- return sipGetState(sipTransferObj);
- %End
-};
-
-
-// convert Bundlesettings wrapped in a QSharedPointer in Isis
-%MappedType QSharedPointer
-{
- %TypeHeaderCode
- #include "ControlNet.h"
- #include
- using namespace std;
- %End
-
- %ConvertFromTypeCode
- PyObject *pySettings = sipConvertFromType(sipCpp, sipType_Isis_ControlNet, NULL);
- return pySettings;
- %End
-
- %ConvertToTypeCode
- int sipErr = 0;
- QSharedPointer *qspControlNet = NULL;
- if (!sipCanConvertToType(sipPy, sipType_Isis_ControlNet, SIP_NOT_NONE)) {
- sipErr = 1;
- }
- else {
- Isis::ControlNet *cppControlNet = (Isis::ControlNet*)sipConvertToType(sipPy, sipType_Isis_ControlNet, NULL, SIP_NOT_NONE, NULL, &sipErr);
- qspControlNet->reset(cppControlNet);
- }
-
- *sipCppPtr = qspControlNet;
- return sipGetState(sipTransferObj);
- %End
-};
-
-
-
-// Convert a python str object to a std::string.
-%MappedType std::string
-{
- %TypeHeaderCode
- #include
- %End
-
- %ConvertFromTypeCode
- // convert an std::string to a Python (unicode) string
- PyObject* newstring;
- newstring = PyUnicode_DecodeUTF8(sipCpp->c_str(), sipCpp->length(), NULL);
- if(newstring == NULL) {
- PyErr_Clear();
- newstring = PyBytes_FromString(sipCpp->c_str());
- }
- return newstring;
- %End
-
- %ConvertToTypeCode
- // Allow a Python string (or a unicode string) whenever a string is
- // expected.
- // If argument is a Unicode string, just decode it to UTF-8
- // If argument is a Python string, assume it's UTF-8
- if (sipIsErr == NULL)
- return (PyBytes_Check(sipPy) || PyUnicode_Check(sipPy));
-
- if (sipPy == Py_None)
- {
- *sipCppPtr = new std::string;
- return 1;
- }
-
- if (PyUnicode_Check(sipPy))
- {
- PyObject* s = PyUnicode_AsEncodedString(sipPy, "UTF-8", "");
- *sipCppPtr = new std::string(PyBytes_AS_STRING(s));
- Py_DECREF(s);
- return 1;
- }
-
- if (PyBytes_Check(sipPy))
- {
- *sipCppPtr = new std::string(PyBytes_AS_STRING(sipPy));
- return 1;
- }
- return 0;
- %End
-};
diff --git a/isis/src/base/apps/csminit/csminit.xml b/isis/src/base/apps/csminit/csminit.xml
index bcddb1d95c054dd300b7be597cceba98e00a0ff2..f932a25a148a98ad28c18eb6b9528995a7fc2424 100644
--- a/isis/src/base/apps/csminit/csminit.xml
+++ b/isis/src/base/apps/csminit/csminit.xml
@@ -18,8 +18,31 @@
Information about the CSM model will also be added to the CsmInfo group on
- the cube label. These are just for users to reference and are not used
- programmatically.
+ the cube label. The group includes names, units, and types for model
+ parameters.
+
+
+Group = CsmInfo
+CSMPlatformID = Mars_Reconnaissance_Orbiter
+CSMInstrumentId = "CONTEXT CAMERA"
+ReferenceTime = 2014-05-21T15:48:56Z
+ModelParameterNames = ("IT Pos. Bias ", "CT Pos. Bias ",
+ "Rad Pos. Bias ", "IT Vel. Bias ",
+ "CT Vel. Bias ", "Rad Vel. Bias ",
+ "Omega Bias ", "Phi Bias ",
+ "Kappa Bias ", "Omega Rate ",
+ "Phi Rate ", "Kappa Rate ",
+ "Omega Accl ", "Phi Accl ",
+ "Kappa Accl ", "Focal Bias ")
+ModelParameterUnits = (m, m, m, m, m, m, m, m, m, m, m, m, m, m, m, m)
+ModelParameterTypes = (REAL, REAL, REAL, REAL, REAL, REAL, REAL, REAL,
+ REAL, REAL, REAL, REAL, REAL, REAL, REAL, REAL)
+End_Group
+
+
+ The ModelParameter keywords contain information that can be used
+ when running jigsaw. This information is unique for each model. For
+ more detail, see the CSMSOLVELIST parameter in the jigsaw documentation.
This program can be run on any Cube file, but if the Cube has spice data
@@ -148,4 +171,17 @@
+
+ Simple csminit Example
+
+ This example uses a calibrated MRO CTX image and an isd generated using ALE or Abstraction Layer for Ephemerides.
+
+
+ csminit from= F02_036648_2021_XN_22N022W.cal.csm.cub isd= F02_036648_2021_XN_22N022W.cal.csm.json
+
+
+ Simple csminit example
+
+
+
diff --git a/isis/src/base/objs/CSMCamera/CSMCamera.cpp b/isis/src/base/objs/CSMCamera/CSMCamera.cpp
index 427d44a69029c9d1e1d1972db584e311cadc5b8c..dbe20dce35ae01825ab75ff1b2381de24bd91696 100644
--- a/isis/src/base/objs/CSMCamera/CSMCamera.cpp
+++ b/isis/src/base/objs/CSMCamera/CSMCamera.cpp
@@ -7,7 +7,6 @@ find files of those names at the top level of this repository. **/
/* SPDX-License-Identifier: CC0-1.0 */
#include "CSMCamera.h"
-#include "CameraGroundMap.h"
#include "CameraSkyMap.h"
#include
@@ -24,6 +23,8 @@ find files of those names at the top level of this repository. **/
#include "CameraDistortionMap.h"
#include "CameraFocalPlaneMap.h"
#include "Constants.h"
+#include "Displacement.h"
+#include "Distance.h"
#include "FileName.h"
#include "IException.h"
#include "IString.h"
@@ -33,6 +34,7 @@ find files of those names at the top level of this repository. **/
#include "LinearAlgebra.h"
#include "NaifStatus.h"
#include "SpecialPixel.h"
+#include "SurfacePoint.h"
#include "csm/Warning.h"
#include "csm/Error.h"
@@ -84,7 +86,7 @@ namespace Isis {
throw IException(IException::User, msg, _FILEINFO_);
}
if (!plugin->canModelBeConstructedFromState(modelName.toStdString(), stateString.toStdString())) {
- QString msg = "CSM state string attached to image [" + cube.fileName() + "]. cannot "
+ QString msg = "CSM state string attached to image [" + cube.fileName() + "] cannot "
"be converted to a [" + modelName + "] using [" + pluginName + "].";
throw IException(IException::Programmer, msg, _FILEINFO_);
}
@@ -119,11 +121,14 @@ namespace Isis {
* @returns @b bool If the image coordinate was set successfully
*/
bool CSMCamera::SetImage(const double sample, const double line) {
+ // Save off the line & sample
+ p_childSample = sample;
+ p_childLine = line;
+
csm::ImageCoord imagePt;
isisToCsmPixel(p_alphaCube->AlphaLine(line), p_alphaCube->AlphaSample(sample), imagePt);
double achievedPrecision = 0;
csm::WarningList warnings;
-
csm::EcefLocus imageLocus;
try {
imageLocus = m_model->imageToRemoteImagingLocus(imagePt,
@@ -154,18 +159,19 @@ namespace Isis {
std::vector locusVec = {imageLocus.direction.x,
imageLocus.direction.y,
imageLocus.direction.z};
- if(!target()->shape()->intersectSurface(obsPosition, locusVec)) {
- return false;
- }
- // If we are here then everything went well so save the pixel and return true
+ // Save off the look vector
m_lookB[0] = locusVec[0];
m_lookB[1] = locusVec[1];
m_lookB[2] = locusVec[2];
m_newLookB = true;
+
+ // Check for a ground intersection
+ if(!target()->shape()->intersectSurface(obsPosition, locusVec)) {
+ return false;
+ }
+
p_pointComputed = true;
- p_childSample = sample;
- p_childLine = line;
if (!m_et) {
m_et = new iTime();
}
@@ -231,7 +237,7 @@ namespace Isis {
latitude = Latitude(0.,Angle::Degrees);
}
- if (!localRadius.isValid()) {
+ if (!localRadius.isValid()) {
target()->shape()->clearSurfacePoint();
return false;
}
@@ -597,6 +603,52 @@ namespace Isis {
}
+ /**
+ * Compute the partial derivatives of the sample, line with
+ * respect to the x, y, z coordinates of the ground point.
+ *
+ * The resultant partials are
+ * line WRT x
+ * line WRT y
+ * line WRT z
+ * sample WRT x
+ * sample WRT y
+ * sample WRT z
+ *
+ * @return @b std::vector The partial derivatives of the
+ * sample, line with respect to
+ * the ground coordinate.
+ */
+ vector CSMCamera::GroundPartials() {
+ return GroundPartials(GetSurfacePoint());
+ }
+
+
+ /**
+ * Compute the partial derivatives of the sample, line with
+ * respect to the x, y, z coordinates of the ground point.
+ *
+ * The resultant partials are
+ * line WRT x
+ * line WRT y
+ * line WRT z
+ * sample WRT x
+ * sample WRT y
+ * sample WRT z
+ *
+ * @param groundPoint The ground point to compute the partials at
+ *
+ * @return @b std::vector The partial derivatives of the
+ * sample, line with respect to
+ * the ground coordinate.
+ */
+ vector CSMCamera::GroundPartials(SurfacePoint groundPoint) {
+ csm::EcefCoord groundCoord = isisToCsmGround(groundPoint);
+ vector groundPartials = m_model->computeGroundPartials(groundCoord);
+ return groundPartials;
+ }
+
+
/**
* Set the Target object for the camera model.
*
@@ -738,8 +790,8 @@ namespace Isis {
/**
- * Compute the slant distance form the sensor to the ground point at the
- * currently set time.
+ * Compute the slant distance from the sensor to the ground
+ * point at the currently set time.
*
* @returns @b double The distance from the sensor to the ground point in kilometers
*/
@@ -774,6 +826,151 @@ namespace Isis {
}
+ /**
+ * Get the indices of the parameters that belong to a set.
+ *
+ * @param paramSet The set of indices to get
+ *
+ * @returns @b std::vector Vector of the parameter indices
+ */
+ std::vector CSMCamera::getParameterIndices(csm::param::Set paramSet) const {
+ return m_model->getParameterSetIndices(paramSet);
+ }
+
+
+ /**
+ * Get the indices of all parameters of a specific type
+ *
+ * @param paramType The type of parameters to get the indices of
+ *
+ * @return @b std::vector Vector of the parameter indices
+ */
+ std::vector CSMCamera::getParameterIndices(csm::param::Type paramType) const {
+ std::vector parameterIndices;
+ for (int i = 0; i < m_model->getNumParameters(); i++) {
+ if (m_model->getParameterType(i) == paramType) {
+ parameterIndices.push_back(i);
+ }
+ }
+ return parameterIndices;
+ }
+
+
+ /**
+ * Get the indices of a list of parameters
+ *
+ * @param paramType The list of parameters to get the indices of
+ *
+ * @return @b std::vector Vector of the parameter indices in the same order as the input list
+ */
+ std::vector CSMCamera::getParameterIndices(QStringList paramList) const {
+ std::vector parameterIndices;
+ QStringList failedParams;
+ for (int i = 0; i < paramList.size(); i++) {
+ bool found = false;
+ for (int j = 0; j < m_model->getNumParameters(); j++) {
+ if (QString::compare(QString::fromStdString(m_model->getParameterName(j)).trimmed(),
+ paramList[i].trimmed(),
+ Qt::CaseInsensitive) == 0) {
+ parameterIndices.push_back(j);
+ found = true;
+ break;
+ }
+ }
+
+ if (!found) {
+ failedParams.push_back(paramList[i]);
+ }
+ }
+
+ if (!failedParams.empty()) {
+ QString msg = "Failed to find indices for the following parameters [" +
+ failedParams.join(",") + "].";
+ throw IException(IException::User, msg, _FILEINFO_);
+ }
+ return parameterIndices;
+ }
+
+
+ /**
+ * Adjust the value of a parameter.
+ *
+ * @param index The index of the parameter to update
+ * @param correction Value to add to the parameter's current value
+ */
+ void CSMCamera::applyParameterCorrection(int index, double correction) {
+ double currentValue = m_model->getParameterValue(index);
+ m_model->setParameterValue(index, currentValue + correction);
+ }
+
+
+ /**
+ * Get the covariance between two parameters.
+ *
+ * @param index1 The index of the first parameter
+ * @param index2 The index of the second parameter
+ */
+ double CSMCamera::getParameterCovariance(int index1, int index2) {
+ return m_model->getParameterCovariance(index1, index2);
+ }
+
+
+ vector CSMCamera::getSensorPartials(int index, SurfacePoint groundPoint) {
+ // csm::SensorPartials holds (line, sample) in order for each parameter
+ csm::EcefCoord groundCoord = isisToCsmGround(groundPoint);
+ std::pair partials = m_model->computeSensorPartials(index, groundCoord);
+ vector partialsVector = {partials.first, partials.second};
+
+ return partialsVector;
+ }
+
+
+ /**
+ * Get the name of the parameter.
+ *
+ * @param index The index of parameter
+ *
+ * @returns @b QString name of the parameter at index
+ */
+ QString CSMCamera::getParameterName(int index) {
+ return QString::fromStdString(m_model->getParameterName(index));
+ }
+
+
+ /**
+ * Get the value of a parameter.
+ *
+ * @param index The index of the parameter
+ *
+ * @returns @b double value of the parameter at index
+ */
+ double CSMCamera::getParameterValue(int index) {
+ return m_model->getParameterValue(index);
+ }
+
+
+ /**
+ * Get the units of the parameter at a particular index.
+ *
+ * @param index The index of parameter
+ *
+ * @returns @b QString units of the parameter at index
+ */
+ QString CSMCamera::getParameterUnits(int index) {
+ return QString::fromStdString(m_model->getParameterUnits(index));
+ }
+
+
+ /**
+ * Get the CSM Model state string to re-create the CSM Model.
+ *
+ * @returns @b QString The CSM Model state string
+ */
+ QString CSMCamera::getModelState() const {
+ return QString::fromStdString(m_model->getModelState());
+ }
+
+
/**
* Set the time and update the sensor position and orientation.
*
diff --git a/isis/src/base/objs/CSMCamera/CSMCamera.h b/isis/src/base/objs/CSMCamera/CSMCamera.h
index a2d50664b1577673a0693bbbd579e7e6753d6917..1d896ee93b598dcff4781201c997e432a7b3475d 100644
--- a/isis/src/base/objs/CSMCamera/CSMCamera.h
+++ b/isis/src/base/objs/CSMCamera/CSMCamera.h
@@ -16,6 +16,7 @@ find files of those names at the top level of this repository. **/
#include
#include
+#include
#include "csm/csm.h"
#include "csm/RasterGM.h"
@@ -37,7 +38,7 @@ namespace Isis {
* @return CameraType Camera::Point
*/
virtual CameraType GetCameraType() const {
- return Point;
+ return Csm;
}
/**
@@ -116,6 +117,21 @@ namespace Isis {
virtual double RightAscension();
virtual double Declination();
+ std::vector getParameterIndices(csm::param::Set paramSet) const;
+ std::vector getParameterIndices(csm::param::Type paramType) const;
+ std::vector getParameterIndices(QStringList paramList) const;
+ void applyParameterCorrection(int index, double correction);
+ double getParameterCovariance(int index1, int index2);
+ QString getParameterName(int index);
+ QString getParameterUnits(int index);
+ double getParameterValue(int index);
+
+ std::vector getSensorPartials(int index, SurfacePoint groundPoint);
+ virtual std::vector GroundPartials(SurfacePoint groundPoint);
+ virtual std::vector GroundPartials();
+
+ QString getModelState() const;
+
protected:
void setTarget(Pvl label);
@@ -137,7 +153,6 @@ namespace Isis {
virtual std::vector ImagePartials(SurfacePoint groundPoint);
virtual std::vector ImagePartials();
-
};
};
#endif
diff --git a/isis/src/base/objs/Camera/Camera.cpp b/isis/src/base/objs/Camera/Camera.cpp
index b648a04f873d0bd1b8796b68ca9aff0a56c4bef2..dc3a052ec7f151fd72cc8922c8448b7a8dfde0ca 100644
--- a/isis/src/base/objs/Camera/Camera.cpp
+++ b/isis/src/base/objs/Camera/Camera.cpp
@@ -1657,8 +1657,8 @@ namespace Isis {
// get a normalized surface spacecraft vector
SpiceDouble surfSpaceVect[3], unitizedSurfSpaceVect[3], dist;
- std::vector sB = bodyRotation()->ReferenceVector(
- instrumentPosition()->Coordinate());
+ std::vector sB(3, Isis::Null);
+ instrumentBodyFixedPosition(&sB[0]);
SpiceDouble pB[3];
SurfacePoint surfacePoint = GetSurfacePoint();
diff --git a/isis/src/base/objs/Camera/Camera.h b/isis/src/base/objs/Camera/Camera.h
index f1b8ac11a0f0274e8351d6bba54b1515861187b9..12b8e5ec11ae49ee78f25fc207cee261c79b4bcd 100644
--- a/isis/src/base/objs/Camera/Camera.h
+++ b/isis/src/base/objs/Camera/Camera.h
@@ -361,6 +361,7 @@ namespace Isis {
Radar, //!< Radar Camera
Point, //!< Point Camera
RollingShutter, //!< RollingShutter
+ Csm //!< Community Sensor Model Camera
};
/**
diff --git a/isis/src/base/objs/SerialNumber/SerialNumber.cpp b/isis/src/base/objs/SerialNumber/SerialNumber.cpp
index 1b52ee098c46a829e70bedbb2181437257504cd7..f9ee7cd1527d66b375e388fc2600e6fe63fad4d7 100644
--- a/isis/src/base/objs/SerialNumber/SerialNumber.cpp
+++ b/isis/src/base/objs/SerialNumber/SerialNumber.cpp
@@ -58,7 +58,7 @@ namespace Isis {
sn = "Unknown";
}
}
-
+
return sn;
}
@@ -97,48 +97,56 @@ namespace Isis {
PvlGroup SerialNumber::FindSerialTranslation(Pvl &label) {
Pvl outLabel;
- // Get the mission name
- static QString missionTransFile = "$ISISROOT/appdata/translations/MissionName2DataDir.trn";
- static PvlToPvlTranslationManager missionXlater(missionTransFile);
- missionXlater.SetLabel(label);
- QString mission = missionXlater.Translate("MissionName");
-
- // Get the instrument name
- static QString instTransFile = "$ISISROOT/appdata/translations/Instruments.trn";
- static PvlToPvlTranslationManager instrumentXlater(instTransFile);
- instrumentXlater.SetLabel(label);
- QString instrument = instrumentXlater.Translate("InstrumentName");
-
- // We want to use this instrument's translation manager. It's much faster for
- // SerialNumberList if we keep the translation manager in memory, so re-reading
- // from the disk is not necessary every time. To do this, we'll use a map to store
- // the translation managers with a string identifier to find them. This identifier
- // needs to have the mission name and the instrument name.
-
- // Create the static map to keep the translation managers in memory
- static std::map missionTranslators;
-
- // Determine the key for this translation manager - must have both mission and instrument
- QString key = mission + "_" + instrument;
-
- // Try to find an existing translation manager with the key
- std::map::iterator translationIterator = missionTranslators.find(key);
-
- // If we don't succeed, create one
- if(translationIterator == missionTranslators.end()) {
- // Get the file
-
- FileName snFile((QString) "$ISISROOT/appdata/translations/" + mission + instrument + "SerialNumber.trn");
-
- // use the translation file to generate keywords
- missionTranslators.insert(
- std::pair(key, PvlToPvlTranslationManager(snFile.expanded()))
- );
-
- translationIterator = missionTranslators.find(key);
+ // check if label has CSM information
+ if(label.findObject("IsisCube").hasGroup("CsmInfo")) {
+ static QString csmTransFile = "$ISISROOT/appdata/translations/CsmSerialNumber.trn";
+ PvlToPvlTranslationManager csmTranslator(label, csmTransFile);
+ csmTranslator.Auto(outLabel);
+ }
+ else {
+ // Get the mission name
+ static QString missionTransFile = "$ISISROOT/appdata/translations/MissionName2DataDir.trn";
+ static PvlToPvlTranslationManager missionXlater(missionTransFile);
+ missionXlater.SetLabel(label);
+ QString mission = missionXlater.Translate("MissionName");
+
+ // Get the instrument name
+ static QString instTransFile = "$ISISROOT/appdata/translations/Instruments.trn";
+ static PvlToPvlTranslationManager instrumentXlater(instTransFile);
+ instrumentXlater.SetLabel(label);
+ QString instrument = instrumentXlater.Translate("InstrumentName");
+
+ // We want to use this instrument's translation manager. It's much faster for
+ // SerialNumberList if we keep the translation manager in memory, so re-reading
+ // from the disk is not necessary every time. To do this, we'll use a map to store
+ // the translation managers with a string identifier to find them. This identifier
+ // needs to have the mission name and the instrument name.
+
+ // Create the static map to keep the translation managers in memory
+ static std::map missionTranslators;
+
+ // Determine the key for this translation manager - must have both mission and instrument
+ QString key = mission + "_" + instrument;
+
+ // Try to find an existing translation manager with the key
+ std::map::iterator translationIterator = missionTranslators.find(key);
+
+ // If we don't succeed, create one
+ if(translationIterator == missionTranslators.end()) {
+ // Get the file
+
+ FileName snFile((QString) "$ISISROOT/appdata/translations/" + mission + instrument + "SerialNumber.trn");
+
+ // use the translation file to generate keywords
+ missionTranslators.insert(
+ std::pair(key, PvlToPvlTranslationManager(snFile.expanded()))
+ );
+
+ translationIterator = missionTranslators.find(key);
+ }
+ translationIterator->second.SetLabel(label);
+ translationIterator->second.Auto(outLabel);
}
- translationIterator->second.SetLabel(label);
- translationIterator->second.Auto(outLabel);
PvlGroup snGroup = outLabel.findGroup("SerialNumberKeywords");
snGroup += PvlKeyword("ObservationKeys", toString(snGroup.keywords()));
diff --git a/isis/src/base/objs/SerialNumberList/SerialNumberList.cpp b/isis/src/base/objs/SerialNumberList/SerialNumberList.cpp
index 72464e07713bdc259640af1cb819a135445f6810..20de49511394cd05ccac62def13bf474dd7643c9 100644
--- a/isis/src/base/objs/SerialNumberList/SerialNumberList.cpp
+++ b/isis/src/base/objs/SerialNumberList/SerialNumberList.cpp
@@ -181,9 +181,19 @@ namespace Isis {
nextpair.serialNumber = sn;
nextpair.observationNumber = on;
- // Need to obtain the SpacecraftName and InstrumentId from the Instrument
+ // If a CSM cube, obtain the CSMPlatformID and CSMInstrumentId from the CsmInfo
// group for use in bundle adjustment
- if (cubeObj.hasGroup("Instrument")) {
+ if (cubeObj.hasGroup("CsmInfo")) {
+ PvlGroup csmGroup = cubeObj.findGroup("CsmInfo");
+ if (csmGroup.hasKeyword("CSMPlatformID") && csmGroup.hasKeyword("CSMInstrumentId")) {
+ nextpair.spacecraftName = cubeObj.findGroup("CsmInfo")["CSMPlatformID"][0];
+ nextpair.instrumentId = cubeObj.findGroup("CsmInfo")["CSMInstrumentId"][0];
+ }
+ }
+
+ // Otherwise obtain the SpacecraftName and InstrumentId from the Instrument
+ // group for use in bundle adjustment
+ else if (cubeObj.hasGroup("Instrument")) {
PvlGroup instGroup = cubeObj.findGroup("Instrument");
if (instGroup.hasKeyword("SpacecraftName") && instGroup.hasKeyword("InstrumentId")) {
nextpair.spacecraftName = cubeObj.findGroup("Instrument")["SpacecraftName"][0];
@@ -287,18 +297,31 @@ namespace Isis {
throw IException(IException::User, msg, _FILEINFO_);
}
- // Need to obtain the SpacecraftName and InstrumentId from the Instrument
- // group for use in bundle adjustment
- if (!cubeObj.hasGroup("Instrument")) {
- QString msg = "Unable to find Instrument group in " + filename
- + " needed for performing bundle adjustment.";
- throw IException(IException::User, msg, _FILEINFO_);
+ // Check if it is not a CSM label before checking SpacecraftName and InstrumentId
+ if (!cubeObj.hasGroup("CsmInfo")) {
+
+ // Need to obtain the SpacecraftName and InstrumentId from the Instrument
+ // group for use in bundle adjustment
+ if (!cubeObj.hasGroup("Instrument")) {
+ QString msg = "Unable to find Instrument group in " + filename
+ + " needed for performing bundle adjustment.";
+ throw IException(IException::User, msg, _FILEINFO_);
+ }
+ PvlGroup instGroup = cubeObj.findGroup("Instrument");
+ if (!instGroup.hasKeyword("SpacecraftName") || !instGroup.hasKeyword("InstrumentId")) {
+ QString msg = "Unable to find SpacecraftName or InstrumentId keywords in " + filename
+ + " needed for performing bundle adjustment.";
+ throw IException(IException::User, msg, _FILEINFO_);
+ }
}
- PvlGroup instGroup = cubeObj.findGroup("Instrument");
- if (!instGroup.hasKeyword("SpacecraftName") || !instGroup.hasKeyword("InstrumentId")) {
- QString msg = "Unable to find SpacecraftName or InstrumentId keywords in " + filename
- + " needed for performing bundle adjustment.";
- throw IException(IException::User, msg, _FILEINFO_);
+ // Check if CSM label has CSMPlatformID and CSMInstrumentId
+ else {
+ PvlGroup csmGroup = cubeObj.findGroup("CSMInfo");
+ if (!csmGroup.hasKeyword("CSMPlatformID") || !csmGroup.hasKeyword("CSMInstrumentId")) {
+ QString msg = "Unable to find CSMPlatformID or CSMInstrumentId keywords in " + filename
+ + " needed for performing bundle adjustment.";
+ throw IException(IException::User, msg, _FILEINFO_);
+ }
}
Pair nextpair;
@@ -306,9 +329,19 @@ namespace Isis {
nextpair.serialNumber = serialNumber;
nextpair.observationNumber = observationNumber;
- // Need to obtain the SpacecraftName and InstrumentId from the Instrument
+ // If a CSM cube, obtain the CSMPlatformID and CSMInstrumentId from the CsmInfo
+ // group for use in bundle adjustment
+ if (cubeObj.hasGroup("CsmInfo")) {
+ PvlGroup csmGroup = cubeObj.findGroup("CsmInfo");
+ if (csmGroup.hasKeyword("CSMPlatformID") && csmGroup.hasKeyword("CSMInstrumentId")) {
+ nextpair.spacecraftName = cubeObj.findGroup("CsmInfo")["CSMPlatformID"][0];
+ nextpair.instrumentId = cubeObj.findGroup("CsmInfo")["CSMInstrumentId"][0];
+ }
+ }
+
+ // Otherwise obtain the SpacecraftName and InstrumentId from the Instrument
// group for use in bundle adjustment
- if (cubeObj.hasGroup("Instrument")) {
+ else if (cubeObj.hasGroup("Instrument")) {
PvlGroup instGroup = cubeObj.findGroup("Instrument");
if (instGroup.hasKeyword("SpacecraftName") && instGroup.hasKeyword("InstrumentId")) {
nextpair.spacecraftName = cubeObj.findGroup("Instrument")["SpacecraftName"][0];
diff --git a/isis/src/base/objs/SpiceRotation/SpiceRotation.cpp b/isis/src/base/objs/SpiceRotation/SpiceRotation.cpp
index b62a9fe940af551b5a8a85748b2d86e6d1573be0..5de9bc33de4fbbc212b0921447180894a0408250 100644
--- a/isis/src/base/objs/SpiceRotation/SpiceRotation.cpp
+++ b/isis/src/base/objs/SpiceRotation/SpiceRotation.cpp
@@ -307,6 +307,7 @@ namespace Isis {
return p_et;
}
+
/**
* Accessor method to get current time bias.
*
diff --git a/isis/src/control/apps/jigsaw/jigsaw.cpp b/isis/src/control/apps/jigsaw/jigsaw.cpp
index 6038368ef2dcf822350f84b117789a19fed78b69..00591a8573886d1731a06950355794f109394098 100644
--- a/isis/src/control/apps/jigsaw/jigsaw.cpp
+++ b/isis/src/control/apps/jigsaw/jigsaw.cpp
@@ -14,6 +14,7 @@ find files of those names at the top level of this repository. **/
#include
#include
+#include "Blob.h"
#include "BundleAdjust.h"
#include "BundleObservationSolveSettings.h"
#include "BundleResults.h"
@@ -148,15 +149,26 @@ namespace Isis {
break;
}
- // Get Kernel group and add or replace LastModifiedInstrumentPointing
- // keyword.
- Table cmatrix = bundleAdjustment->cMatrix(i);
+ // Update the image parameters
QString jigComment = "Jigged = " + Isis::iTime::CurrentLocalTime();
- cmatrix.Label().addComment(jigComment);
- Table spvector = bundleAdjustment->spVector(i);
- spvector.Label().addComment(jigComment);
- c->write(cmatrix);
- c->write(spvector);
+ if (c->hasBlob("CSMState", "String")) {
+ Blob csmStateBlob("CSMState", "String");
+ // Read the BLOB from the cube to propagate things like the model
+ // and plugin name
+ c->read(csmStateBlob);
+ std::string modelState = bundleAdjustment->modelState(i).toStdString();
+ csmStateBlob.setData(modelState.c_str(), modelState.size());
+ csmStateBlob.Label().addComment(jigComment);
+ c->write(csmStateBlob);
+ }
+ else {
+ Table cmatrix = bundleAdjustment->cMatrix(i);
+ cmatrix.Label().addComment(jigComment);
+ Table spvector = bundleAdjustment->spVector(i);
+ spvector.Label().addComment(jigComment);
+ c->write(cmatrix);
+ c->write(spvector);
+ }
p.WriteHistory(*c);
}
gp += PvlKeyword("Status", "Camera pointing updated");
@@ -443,6 +455,29 @@ namespace Isis {
positionVelocityAprioriSigma,
positionAccelerationAprioriSigma);
+ if ((ui.WasEntered("CSMSOLVESET") && ui.WasEntered("CSMSOLVETYPE")) ||
+ (ui.WasEntered("CSMSOLVESET") && ui.WasEntered("CSMSOLVELIST")) ||
+ (ui.WasEntered("CSMSOLVETYPE") && ui.WasEntered("CSMSOLVELIST")) ) {
+ QString msg = "Only one of CSMSOLVESET, CSMSOLVETYPE, and CSMSOLVELIST "
+ "can be specified at a time.";
+ throw IException(IException::User, msg, _FILEINFO_);
+ }
+
+ if (ui.WasEntered("CSMSOLVESET")) {
+ observationSolveSettings.setCSMSolveSet(
+ BundleObservationSolveSettings::stringToCSMSolveSet(ui.GetString("CSMSOLVESET")));
+ }
+ else if (ui.WasEntered("CSMSOLVETYPE")) {
+ observationSolveSettings.setCSMSolveType(
+ BundleObservationSolveSettings::stringToCSMSolveType(ui.GetString("CSMSOLVETYPE")));
+ }
+ else if (ui.WasEntered("CSMSOLVELIST")) {
+ std::vector csmParamVector;
+ ui.GetString("CSMSOLVELIST", csmParamVector);
+ QStringList csmParamList = QStringList::fromVector(QVector::fromStdVector(csmParamVector));
+ observationSolveSettings.setCSMSolveParameterList(csmParamList);
+ }
+
// add all image observation numbers to this BOSS.
for (int sn = 0; sn < cubeSNs.size(); sn++) {
observationSolveSettings.addObservationNumber(cubeSNs.observationNumber(sn));
@@ -450,6 +485,7 @@ namespace Isis {
// append the GUI acquired solve parameters to BOSS list.
observationSolveSettingsList.append(observationSolveSettings);
+
}
diff --git a/isis/src/control/apps/jigsaw/jigsaw.xml b/isis/src/control/apps/jigsaw/jigsaw.xml
index a3bdb4520e190a8edf57d6e2b51750494c41280e..563ec4ef8bbfa7e83137278197f504e8784a3e0e 100644
--- a/isis/src/control/apps/jigsaw/jigsaw.xml
+++ b/isis/src/control/apps/jigsaw/jigsaw.xml
@@ -1018,7 +1018,85 @@
No
-
+
+
+
+
+ none
+ string
+ Specify a set of a CSM parameters to solve for.
+
+ Specify one of the parameter sets from the CSM GeometricModel API to solve for.
+ All parameters belonging to the specified set will be solved for.
+
+
+ CSMSOLVETYPE
+ CSMSOLVELIST
+
+
+
+
+
+
+
+
+
+ string
+ Specify a type of a CSM parameters to solve for.
+
+ Specify a parameter type from the CSM GeometricModel API to solve for.
+ All parameters of the specified type will be solved for.
+
+
+ CSMSOLVESET
+ CSMSOLVELIST
+
+
+
+
+
+
+
+ Solve for fixed CSM parameters. These parameters are generally not adjusted
+ but do have uncertainty which can help constrain the solutions and improve
+ a posteriori uncertainties for other parameters.
+
+
+
+
+
+ string
+ Specify an explicit list of CSM parameters to solve for.
+
+ All CSM parameters in this list will be solved for. Trailing and leading whitespace
+ will be stripped off. Use standard ISIS parameter array notation to specify multiple
+ parameters.
+
+
+ CSMSOLVESET
+ CSMSOLVETYPE
+
+
+
@@ -1342,6 +1420,21 @@
+
+ Solve with CSM parameters
+
+ This is an example where the cubes in the network have been run through csminit.
+ When specified in CSMSOLVELIST, parameters described in the CsmInfo group can
+ be adjusted during the bundle.
+
+
+ jigsaw fromlis=cubes.lis cnet=input.net onet=output.net radius=yes csmsolvelist="(Omega Bias, Phi Bias, Kappa Bias)" control_point_coordinate_type_bundle=rectangular control_point_coordinate_type_reports=rectangular point_x_sigma=50 point_y_sigma=50 point_z_sigma=50
+
+
+ jigsaw CSM example
+
+
+ Add items to glossary, example(s) and tips on how to analyze the
diff --git a/isis/src/control/apps/jigsaw/tsts/Makefile b/isis/src/control/apps/jigsaw/tsts/Makefile
deleted file mode 100644
index 46d84c74c297304e943452a44e06b111f179a92b..0000000000000000000000000000000000000000
--- a/isis/src/control/apps/jigsaw/tsts/Makefile
+++ /dev/null
@@ -1,4 +0,0 @@
-BLANKS = "%-6s"
-LENGTH = "%-40s"
-
-include $(ISISROOT)/make/isismake.tststree
diff --git a/isis/src/control/apps/jigsaw/tsts/radar/Makefile b/isis/src/control/apps/jigsaw/tsts/radar/Makefile
deleted file mode 100644
index cfb8dbf6b25e4315e7d049cc17e92b65b3a80b24..0000000000000000000000000000000000000000
--- a/isis/src/control/apps/jigsaw/tsts/radar/Makefile
+++ /dev/null
@@ -1,61 +0,0 @@
-APPNAME = jigsaw
-# These tests exercise the bundle adjustment of images from the MiniRF radar instrument onboard LRO.
-# Test 1: solving for position only, with error propagation
-# Test 2: solving for position, velocity, acceleration, using polynomial over a constant hermite
-# spline, with error propagation
-
-# The "cat bundleout.txt" command in these tests uses sed to do the following (in order):
-# 1. remove cube filename paths
-# 2. remove net filename paths
-# 3. remove digits beyond the fifth decimal place of decimal numbers
-# 4. remove date and time
-#
-# 2014-07-23 Jeannie Backer - Commented out references to bundleout_images.csv.
-# Removed default parameters.
-# 2016-08-11 Jeannie Backer - Updated documentation
-# 2016-10-05 Ian Humphrey - Removed no longer relevant RM command to remove inverseMatrix.dat
-# as jigsaw no longer generates this file during error propagation.
-# References #4315.
-
-include $(ISISROOT)/make/isismake.tsts
-
-commands:
- $(LS) -1 $(INPUT)/*.cub > $(OUTPUT)/cube.lis;
- $(APPNAME) fromlist=$(OUTPUT)/cube.lis \
- cnet=$(INPUT)/Cabeus_Orbit400_withSS_AprioriPts.net \
- onet=$(OUTPUT)/radar_sparse_poh_out.net \
- maxits=10 \
- errorprop=yes \
- bundleout_txt=no \
- spsolve=accelerations \
- camsolve=no > /dev/null;
- $(CAT) residuals.csv | $(SED) 's/,[^,]*\/\([^,\/]*\.cub\)/,\1/g'\
- > $(OUTPUT)/radar_sparse_poh_residuals.csv;
-# $(CAT) bundleout_images.csv \
-# | perl -pe 's/(^|,|: )([^,:]+\/)([^,\/:]*\.)(net|cub)/\1\3\4/g' 2>/dev/null \
-# | $(SED) 's/\([0-9]*\.[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]\)\([0-9]*\)/\1/g' \
-# > $(OUTPUT)/radar_sparse_poh_bundleout_images.csv;
-# $(RM) bundleout_images.csv > /dev/null;
- $(MV) bundleout_points.csv $(OUTPUT)/radar_sparse_poh_bundleout_points.csv > /dev/null;
- $(RM) print.prt > /dev/null;
- $(RM) residuals.csv > /dev/null;
- $(APPNAME) fromlist=$(OUTPUT)/cube.lis \
- cnet=$(INPUT)/Cabeus_Orbit400_withSS_AprioriPts.net \
- onet=$(OUTPUT)/radar_sparse_out.net \
- maxits=10 \
- errorprop=yes \
- spsolve=position \
- overhermite=yes \
- bundleout_txt=no \
- camsolve=no > /dev/null;
- $(CAT) residuals.csv | $(SED) 's/,[^,]*\/\([^,\/]*\.cub\)/,\1/g'\
- > $(OUTPUT)/radar_sparse_residuals.csv
- $(CAT) bundleout_images.csv \
- | perl -pe 's/(^|,|: )([^,:]+\/)([^,\/:]*\.)(net|cub)/\1\3\4/g' 2>/dev/null \
- | $(SED) 's/\([0-9]*\.[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]\)\([0-9]*\)/\1/g' \
- > $(OUTPUT)/radar_sparse_bundleout_images.csv
- $(RM) bundleout_images.csv > /dev/null;
- $(MV) bundleout_points.csv $(OUTPUT)/radar_sparse_bundleout_points.csv > /dev/null;
- $(RM) $(OUTPUT)/cube.lis > /dev/null;
- $(RM) print.prt > /dev/null;
- $(RM) residuals.csv > /dev/null;
diff --git a/isis/src/control/apps/jigsaw/tsts/scconfig/Makefile b/isis/src/control/apps/jigsaw/tsts/scconfig/Makefile
deleted file mode 100644
index 04e419b82455bfcc5740819ba3c3c0c775e3285d..0000000000000000000000000000000000000000
--- a/isis/src/control/apps/jigsaw/tsts/scconfig/Makefile
+++ /dev/null
@@ -1,21 +0,0 @@
-APPNAME = jigsaw
-
-include $(ISISROOT)/make/isismake.tsts
-
-commands:
- $(LS) -1 $(INPUT)/*cub > $(OUTPUT)/cubes.lis;
- $(APPNAME) fromlist=$(OUTPUT)/cubes.lis \
- cnet=$(INPUT)/themis_dayir_VO_arcadia_extract_hand.net \
- onet=$(OUTPUT)/themis_dayir_VO_arcadia_extract_hand_jig.net \
- scconfig=$(INPUT)/themis_vo.pvl \
- radius=true \
- point_radius_sigma=50\
- bundleout_txt=no \
- output_csv=no \
- residuals_csv=no > /dev/null;
- $(CAT) bundleout_images.csv \
- | perl -pe 's/(^|,|: )([^,:]+\/)([^,\/:]*\.)(net|cub)/\1\3\4/g' 2> /dev/null \
- > $(OUTPUT)/bundleout_scconfig_images.csv;
- $(RM) $(OUTPUT)/cubes.lis > /dev/null;
- $(RM) $(OUTPUT)/*.net > /dev/null;
- $(RM) *.csv > /dev/null;
diff --git a/isis/src/control/apps/jigsaw/tsts/scconfigHeld/Makefile b/isis/src/control/apps/jigsaw/tsts/scconfigHeld/Makefile
deleted file mode 100644
index 2fa5a950457f865b8ef53596fe56272aff04e6d6..0000000000000000000000000000000000000000
--- a/isis/src/control/apps/jigsaw/tsts/scconfigHeld/Makefile
+++ /dev/null
@@ -1,22 +0,0 @@
-APPNAME = jigsaw
-
-include $(ISISROOT)/make/isismake.tsts
-
-commands:
- $(LS) -1 $(INPUT)/*cub > $(OUTPUT)/cubes.lis;
- $(LS) $(INPUT)/I28234014RDR.cub > $(OUTPUT)/hold.lis;
- $(APPNAME) fromlist=$(OUTPUT)/cubes.lis \
- heldlist=$(OUTPUT)/hold.lis \
- cnet=$(INPUT)/themis_dayir_VO_arcadia_extract_hand.net \
- onet=$(OUTPUT)/themis_dayir_VO_arcadia_extract_hand_jig.net \
- scconfig=$(INPUT)/themis_vo.pvl \
- bundleout_txt=no \
- output_csv=no \
- residuals_csv=no > /dev/null;
- $(CAT) bundleout_images.csv \
- | perl -pe 's/(^|,|: )([^,:]+\/)([^,\/:]*\.)(net|cub)/\1\3\4/g' 2> /dev/null \
- > $(OUTPUT)/bundleout_scconfig_images.csv;
- $(RM) $(OUTPUT)/cubes.lis > /dev/null;
- $(RM) $(OUTPUT)/hold.lis > /dev/null;
- $(RM) $(OUTPUT)/*.net > /dev/null;
- $(RM) *.csv > /dev/null;
diff --git a/isis/src/control/objs/BundleAdjust/BundleAdjust.cpp b/isis/src/control/objs/BundleAdjust/BundleAdjust.cpp
index 6c0084f574061f43b6e6b162697489f30aa73d23..52c5b84d9d4a207c140ea72c8f8938735b2fcaf6 100644
--- a/isis/src/control/objs/BundleAdjust/BundleAdjust.cpp
+++ b/isis/src/control/objs/BundleAdjust/BundleAdjust.cpp
@@ -28,6 +28,7 @@ find files of those names at the top level of this repository. **/
// Isis lib
#include "Application.h"
#include "BundleObservation.h"
+#include "IsisBundleObservation.h"
#include "BundleObservationSolveSettings.h"
#include "BundleResults.h"
#include "BundleSettings.h"
@@ -38,6 +39,7 @@ find files of those names at the top level of this repository. **/
#include "CameraDistortionMap.h"
#include "CameraFocalPlaneMap.h"
#include "CameraGroundMap.h"
+#include "CSMCamera.h"
#include "Control.h"
#include "ControlPoint.h"
#include "CorrelationMatrix.h"
@@ -434,14 +436,6 @@ namespace Isis {
}
}
- // initialize exterior orientation (spice) for all BundleImages in all BundleObservations
- // TODO!!! - should these initializations just be done when we add the new observation above?
- m_bundleObservations.initializeExteriorOrientation();
-
- if (m_bundleSettings->solveTargetBody()) {
- m_bundleObservations.initializeBodyRotation();
- }
-
// set up vector of BundleControlPoints
int numControlPoints = m_controlNet->GetNumPoints();
for (int i = 0; i < numControlPoints; i++) {
@@ -503,12 +497,12 @@ namespace Isis {
if (m_bundleSettings->solveTargetBody()) {
m_rank += m_bundleSettings->numberTargetBodyParameters();
-
+
if (m_bundleTargetBody->solveMeanRadius() || m_bundleTargetBody->solveTriaxialRadii()) {
outputBundleStatus("Warning: Solving for the target body radii (triaxial or mean) "
"is NOT possible and likely increases error in the solve.\n");
}
-
+
if (m_bundleTargetBody->solveMeanRadius()){
// Check if MeanRadiusValue is abnormal compared to observation
bool isMeanRadiusValid = true;
@@ -975,7 +969,6 @@ namespace Isis {
cholmod_free_factor(&m_L, &m_cholmodCommon);
}
-
iterationSummary();
m_iteration++;
@@ -1658,7 +1651,6 @@ namespace Isis {
outputBundleStatus("\nTriplet allocation failure\n");
return false;
}
-
m_cholmodTriplet->nnz = 0;
}
@@ -1865,23 +1857,7 @@ namespace Isis {
BundleMeasure &measure,
BundleControlPoint &point) {
- // These vectors are either body-fixed latitudinal (lat/lon/radius) or rectangular (x/y/z)
- // depending on the value of coordinate type in SurfacePoint
- std::vector lookBWRTCoord1;
- std::vector lookBWRTCoord2;
- std::vector lookBWRTCoord3;
-
- Camera *measureCamera = NULL;
-
- double measuredX, computedX, measuredY, computedY;
- double deltaX, deltaY;
- double observationSigma;
- double observationWeight;
-
- measureCamera = measure.camera();
-
- const BundleObservationSolveSettingsQsp observationSolveSettings =
- measure.observationSolveSettings();
+ Camera *measureCamera = measure.camera();
BundleObservationQsp observation = measure.parentBundleObservation();
int numImagePartials = observation->numberParameters();
@@ -1894,17 +1870,8 @@ namespace Isis {
m_previousNumberImagePartials = numImagePartials;
}
- // clear partial derivative matrices and vectors
- if (m_bundleSettings->solveTargetBody()) {
- coeffTarget.clear();
- }
-
- coeffImage.clear();
- coeffPoint3D.clear();
- coeffRHS.clear();
-
- // no need to call SetImage for framing camera ( CameraType = 0 )
- if (measureCamera->GetCameraType() != 0) {
+ // No need to call SetImage for framing camera
+ if (measureCamera->GetCameraType() != Camera::Framing) {
// Set the Spice to the measured point. A framing camera exposes the entire image at one time.
// It will have a single set of Spice for the entire image. Scanning cameras may populate a single
// image with multiple exposures, each with a unique set of Spice. SetImage needs to be called
@@ -1912,225 +1879,59 @@ namespace Isis {
measureCamera->SetImage(measure.sample(), measure.line());
}
- // REMOVE
- SurfacePoint surfacePoint = point.adjustedSurfacePoint();
- // REMOVE
-
- // Compute the look vector in instrument coordinates based on time of observation and apriori
- // lat/lon/radius. As of 05/15/2019, this call no longer does the back-of-planet test. An optional
- // bool argument was added CameraGroundMap::GetXY to turn off the test.
- if (!(measureCamera->GroundMap()->GetXY(point.adjustedSurfacePoint(),
- &computedX, &computedY, false))) {
- QString msg = "Unable to map apriori surface point for measure ";
- msg += measure.cubeSerialNumber() + " on point " + point.id() + " into focal plane";
- throw IException(IException::User, msg, _FILEINFO_);
- }
-
- // Retrieve the coordinate type (latitudinal or rectangular) and compute the partials for
- // the fixed point with respect to each coordinate in Body-Fixed
- SurfacePoint::CoordinateType type = m_bundleSettings->controlPointCoordTypeBundle();
- lookBWRTCoord1 = point.adjustedSurfacePoint().Partial(type, SurfacePoint::One);
- lookBWRTCoord2 = point.adjustedSurfacePoint().Partial(type, SurfacePoint::Two);
- lookBWRTCoord3 = point.adjustedSurfacePoint().Partial(type, SurfacePoint::Three);
-
- int index = 0;
- if (m_bundleSettings->solveTargetBody() && m_bundleSettings->solvePoleRA()) {
- measureCamera->GroundMap()->GetdXYdTOrientation(SpiceRotation::WRT_RightAscension, 0,
- &coeffTarget(0, index),
- &coeffTarget(1, index));
- index++;
- }
-
- if (m_bundleSettings->solveTargetBody() && m_bundleSettings->solvePoleRAVelocity()) {
- measureCamera->GroundMap()->GetdXYdTOrientation(SpiceRotation::WRT_RightAscension, 1,
- &coeffTarget(0, index),
- &coeffTarget(1, index));
- index++;
- }
-
- if (m_bundleSettings->solveTargetBody() && m_bundleSettings->solvePoleDec()) {
- measureCamera->GroundMap()->GetdXYdTOrientation(SpiceRotation::WRT_Declination, 0,
- &coeffTarget(0, index),
- &coeffTarget(1, index));
- index++;
- }
-
- if (m_bundleSettings->solveTargetBody() && m_bundleSettings->solvePoleDecVelocity()) {
- measureCamera->GroundMap()->GetdXYdTOrientation(SpiceRotation::WRT_Declination, 1,
- &coeffTarget(0, index),
- &coeffTarget(1, index));
- index++;
- }
-
- if (m_bundleSettings->solveTargetBody() && m_bundleSettings->solvePM()) {
- measureCamera->GroundMap()->GetdXYdTOrientation(SpiceRotation::WRT_Twist, 0,
- &coeffTarget(0, index),
- &coeffTarget(1, index));
- index++;
- }
-
- if (m_bundleSettings->solveTargetBody() && m_bundleSettings->solvePMVelocity()) {
- measureCamera->GroundMap()->GetdXYdTOrientation(SpiceRotation::WRT_Twist, 1,
- &coeffTarget(0, index),
- &coeffTarget(1, index));
- index++;
- }
-
- if (m_bundleSettings->solveTargetBody() && m_bundleTargetBody->solveMeanRadius()) {
- std::vector lookBWRTMeanRadius =
- measureCamera->GroundMap()->MeanRadiusPartial(surfacePoint,
- m_bundleTargetBody->meanRadius());
-
- measureCamera->GroundMap()->GetdXYdPoint(lookBWRTMeanRadius, &coeffTarget(0, index),
- &coeffTarget(1, index));
- index++;
- }
-
- if (m_bundleSettings->solveTargetBody() && m_bundleTargetBody->solveTriaxialRadii()) {
-
- std::vector lookBWRTRadiusA =
- measureCamera->GroundMap()->EllipsoidPartial(surfacePoint,
- CameraGroundMap::WRT_MajorAxis);
-
- measureCamera->GroundMap()->GetdXYdPoint(lookBWRTRadiusA, &coeffTarget(0, index),
- &coeffTarget(1, index));
- index++;
-
- std::vector lookBWRTRadiusB =
- measureCamera->GroundMap()->EllipsoidPartial(surfacePoint,
- CameraGroundMap::WRT_MinorAxis);
-
- measureCamera->GroundMap()->GetdXYdPoint(lookBWRTRadiusB, &coeffTarget(0, index),
- &coeffTarget(1, index));
- index++;
-
- std::vector lookBWRTRadiusC =
- measureCamera->GroundMap()->EllipsoidPartial(surfacePoint,
- CameraGroundMap::WRT_PolarAxis);
-
- measureCamera->GroundMap()->GetdXYdPoint(lookBWRTRadiusC, &coeffTarget(0, index),
- &coeffTarget(1, index));
- index++;
- }
-
- index = 0;
-
- if (observationSolveSettings->instrumentPositionSolveOption() !=
- BundleObservationSolveSettings::NoPositionFactors) {
-
- int numCamPositionCoefficients =
- observationSolveSettings->numberCameraPositionCoefficientsSolved();
-
- // Add the partial for the x coordinate of the position (differentiating
- // point(x,y,z) - spacecraftPosition(x,y,z) in J2000
- for (int cameraCoef = 0; cameraCoef < numCamPositionCoefficients; cameraCoef++) {
- measureCamera->GroundMap()->GetdXYdPosition(SpicePosition::WRT_X, cameraCoef,
- &coeffImage(0, index),
- &coeffImage(1, index));
- index++;
- }
-
- // Add the partial for the y coordinate of the position
- for (int cameraCoef = 0; cameraCoef < numCamPositionCoefficients; cameraCoef++) {
- measureCamera->GroundMap()->GetdXYdPosition(SpicePosition::WRT_Y, cameraCoef,
- &coeffImage(0, index),
- &coeffImage(1, index));
- index++;
- }
-
- // Add the partial for the z coordinate of the position
- for (int cameraCoef = 0; cameraCoef < numCamPositionCoefficients; cameraCoef++) {
- measureCamera->GroundMap()->GetdXYdPosition(SpicePosition::WRT_Z, cameraCoef,
- &coeffImage(0, index),
- &coeffImage(1, index));
- index++;
+ // CSM Cameras do not have a ground map
+ if (measureCamera->GetCameraType() != Camera::Csm) {
+ // Compute the look vector in instrument coordinates based on time of observation and apriori
+ // lat/lon/radius. As of 05/15/2019, this call no longer does the back-of-planet test. An optional
+ // bool argument was added CameraGroundMap::GetXY to turn off the test.
+ double computedX, computedY;
+ if (!(measureCamera->GroundMap()->GetXY(point.adjustedSurfacePoint(),
+ &computedX, &computedY, false))) {
+ QString msg = "Unable to map apriori surface point for measure ";
+ msg += measure.cubeSerialNumber() + " on point " + point.id() + " into focal plane";
+ throw IException(IException::User, msg, _FILEINFO_);
}
-
}
- if (observationSolveSettings->instrumentPointingSolveOption() !=
- BundleObservationSolveSettings::NoPointingFactors) {
-
- int numCamAngleCoefficients =
- observationSolveSettings->numberCameraAngleCoefficientsSolved();
-
- // Add the partials for ra
- for (int cameraCoef = 0; cameraCoef < numCamAngleCoefficients; cameraCoef++) {
- measureCamera->GroundMap()->GetdXYdOrientation(SpiceRotation::WRT_RightAscension,
- cameraCoef, &coeffImage(0, index),
- &coeffImage(1, index));
- index++;
- }
-
- // Add the partials for dec
- for (int cameraCoef = 0; cameraCoef < numCamAngleCoefficients; cameraCoef++) {
- measureCamera->GroundMap()->GetdXYdOrientation(SpiceRotation::WRT_Declination,
- cameraCoef, &coeffImage(0, index),
- &coeffImage(1, index));
- index++;
- }
-
- // Add the partial for twist if necessary
- if (observationSolveSettings->solveTwist()) {
- for (int cameraCoef = 0; cameraCoef < numCamAngleCoefficients; cameraCoef++) {
- measureCamera->GroundMap()->GetdXYdOrientation(SpiceRotation::WRT_Twist,
- cameraCoef, &coeffImage(0, index),
- &coeffImage(1, index));
- index++;
- }
- }
+ if (m_bundleSettings->solveTargetBody()) {
+ observation->computeTargetPartials(coeffTarget, measure, m_bundleSettings, m_bundleTargetBody);
}
+ observation->computeImagePartials(coeffImage, measure);
+
// Complete partials calculations for 3D point (latitudinal or rectangular)
- measureCamera->GroundMap()->GetdXYdPoint(lookBWRTCoord1,
- &coeffPoint3D(0, 0),
- &coeffPoint3D(1, 0));
- measureCamera->GroundMap()->GetdXYdPoint(lookBWRTCoord2,
- &coeffPoint3D(0, 1),
- &coeffPoint3D(1, 1));
- measureCamera->GroundMap()->GetdXYdPoint(lookBWRTCoord3,
- &coeffPoint3D(0, 2),
- &coeffPoint3D(1, 2));
+ // Retrieve the coordinate type (latitudinal or rectangular) and compute the partials for
+ // the fixed point with respect to each coordinate in Body-Fixed
+ SurfacePoint::CoordinateType coordType = m_bundleSettings->controlPointCoordTypeBundle();
+ observation->computePoint3DPartials(coeffPoint3D, measure, coordType);
// right-hand side (measured - computed)
- measuredX = measure.focalPlaneMeasuredX();
- measuredY = measure.focalPlaneMeasuredY();
-
- deltaX = measuredX - computedX;
- deltaY = measuredY - computedY;
+ observation->computeRHSPartials(coeffRHS, measure);
- coeffRHS(0) = deltaX;
- coeffRHS(1) = deltaY;
+ double deltaX = coeffRHS(0);
+ double deltaY = coeffRHS(1);
- // residual prob distribution is calculated even if there is no maximum likelihood estimation
- double obsValue = deltaX / measureCamera->PixelPitch();
- m_bundleResults.addResidualsProbabilityDistributionObservation(obsValue);
-
- obsValue = deltaY / measureCamera->PixelPitch();
- m_bundleResults.addResidualsProbabilityDistributionObservation(obsValue);
-
- observationSigma = 1.4 * measureCamera->PixelPitch();
- observationWeight = 1.0 / observationSigma;
+ m_bundleResults.addResidualsProbabilityDistributionObservation(observation->computeObservationValue(measure, deltaX));
+ m_bundleResults.addResidualsProbabilityDistributionObservation(observation->computeObservationValue(measure, deltaY));
if (m_bundleResults.numberMaximumLikelihoodModels()
> m_bundleResults.maximumLikelihoodModelIndex()) {
- // if maximum likelihood estimation is being used
- double residualR2ZScore
- = sqrt(deltaX * deltaX + deltaY * deltaY) / observationSigma / sqrt(2.0);
- //dynamically build the cumulative probability distribution of the R^2 residual Z Scores
+ // If maximum likelihood estimation is being used
+ double residualR2ZScore = sqrt(deltaX * deltaX + deltaY * deltaY) / sqrt(2.0);
+
+ // Dynamically build the cumulative probability distribution of the R^2 residual Z Scores
m_bundleResults.addProbabilityDistributionObservation(residualR2ZScore);
+
int currentModelIndex = m_bundleResults.maximumLikelihoodModelIndex();
- observationWeight *= m_bundleResults.maximumLikelihoodModelWFunc(currentModelIndex)
+ double observationWeight = m_bundleResults.maximumLikelihoodModelWFunc(currentModelIndex)
.sqrtWeightScaler(residualR2ZScore);
- }
+ coeffImage *= observationWeight;
+ coeffPoint3D *= observationWeight;
+ coeffRHS *= observationWeight;
- // multiply coefficients by observation weight
- coeffImage *= observationWeight;
- coeffPoint3D *= observationWeight;
- coeffRHS *= observationWeight;
-
- if (m_bundleSettings->solveTargetBody()) {
- coeffTarget *= observationWeight;
+ if (m_bundleSettings->solveTargetBody()) {
+ coeffTarget *= observationWeight;
+ }
}
return true;
@@ -2138,7 +1939,7 @@ namespace Isis {
/**
- * apply parameter corrections for solution.
+ * Apply parameter corrections for solution.
*/
void BundleAdjust::applyParameterCorrections() {
emit(statusBarUpdate("Updating Parameters"));
@@ -2165,7 +1966,10 @@ namespace Isis {
observation->applyParameterCorrections(subrange(m_imageSolution,t,t+numParameters));
if (m_bundleSettings->solveTargetBody()) {
- observation->updateBodyRotation();
+ // TODO: needs to be updated for ISIS vs. CSM CSM has no updateBodyRotation]
+ // TODO: this is no good.
+ QSharedPointer isisObservation = qSharedPointerDynamicCast(observation);
+ isisObservation->updateBodyRotation();
}
t += numParameters;
@@ -3015,7 +2819,10 @@ namespace Isis {
/**
- * Return a table cmatrix for the ith cube in the cube list given to the constructor.
+ * Return the updated instrument pointing table for the ith cube in the cube
+ * list given to the constructor.
+ *
+ * This is only valid for ISIS camera model cubes
*
* @param i The index of the cube
*
@@ -3025,9 +2832,12 @@ namespace Isis {
return m_controlNet->Camera(i)->instrumentRotation()->Cache("InstrumentPointing");
}
+
/**
- * Return a table spacecraft vector for the ith cube in the cube list given to the
- * constructor.
+ * Return the updated instrument position table for the ith cube in the cube
+ * list given to the constructor.
+ *
+ * This is only valid for ISIS camera model cubes
*
* @param i The index of the cube
*
@@ -3038,6 +2848,27 @@ namespace Isis {
}
+ /**
+ * Return the updated model state for the ith cube in the cube list given to the
+ * constructor. This is only valid for CSM cubes.
+ *
+ * @param i The index of the cube to get the model state for
+ *
+ * @return @b QString The updated CSM model state string
+ */
+ QString BundleAdjust::modelState(int i) {
+ Camera *imageCam = m_controlNet->Camera(i);
+ if (imageCam->GetCameraType() != Camera::Csm) {
+ QString msg = "Cannot get model state for image [" + toString(i) +
+ "] because it is not a CSM camera model.";
+ throw IException(IException::Programmer, msg, _FILEINFO_);
+ }
+
+ CSMCamera *csmCamera = dynamic_cast(imageCam);
+ return csmCamera->getModelState();
+ }
+
+
/**
* Creates an iteration summary and an iteration group for the solution summary
*
diff --git a/isis/src/control/objs/BundleAdjust/BundleAdjust.h b/isis/src/control/objs/BundleAdjust/BundleAdjust.h
index 1fcf848fa513fa2e7d7ecde2d6667711e35f084f..ed24111697871be79a10c8099f67ab289b2d4a6e 100644
--- a/isis/src/control/objs/BundleAdjust/BundleAdjust.h
+++ b/isis/src/control/objs/BundleAdjust/BundleAdjust.h
@@ -362,6 +362,7 @@ namespace Isis {
bool isConverged();
Table cMatrix(int index);
Table spVector(int index);
+ QString modelState(int index);
int numberOfImages() const;
double iteration() const;
diff --git a/isis/src/control/objs/BundleAdjust/unitTest.cpp b/isis/src/control/objs/BundleAdjust/unitTest.cpp
index 1f3855ecbc636e6875986b3dbe3c8d5cd3777d8b..a8872cd280ce83e9f0dd164cccab7546742b9e7c 100644
--- a/isis/src/control/objs/BundleAdjust/unitTest.cpp
+++ b/isis/src/control/objs/BundleAdjust/unitTest.cpp
@@ -24,43 +24,3 @@ int main(int argc, char *argv[]) {
e.print();
}
}
-
-#if 0
-Code not currently covered by jigsaw app tests
-
-These methods are never called
- static void cholmodErrorHandler();
- BundleAdjust(BundleSettings bundleSettings, QString &cnet, SerialNumberList &snlist, bool bPrintSummary);
- BundleAdjust(BundleSettings bundleSettings, Control &cnet, SerialNumberList &snlist, bool bPrintSummary);
- BundleAdjust(BundleSettings bundleSettings, ControlNet &cnet, SerialNumberList &snlist, bool bPrintSummary);
- BundleAdjust(BundleSettings bundleSettings, Control &cnet, QList &imgLists, bool bPrintSummary);
- ~BundleAdjust();
- bool BundleAdjust::freeCHOLMODLibraryVariables();
-
-
-These have partial coverage
- void BundleAdjust::init(Progress *progress) {
- (pCamera==false) for Camera *pCamera = m_controlNet->Camera(0);
- (m_bodyRadii[0] < 0 && pCamera==true)
- (image==false) for BundleImage* image = new BundleImage(camera, serialNumber, fileName);
- (m_bundleSettings.validateNetwork()==false) -- this is never the case for jigsaw, need to test elsewhere
-
-
-Errors:
- void BundleAdjust::init(Progress *progress) {
- (image==false) for BundleImage* image = new BundleImage(camera, serialNumber, fileName);
- QString msg = "In BundleAdjust::init(): image " + fileName + "is null" + "\n";
- (observation==false) for BundleObservation *observation = m_bundleObservations.addNew(image, observationNumber, instrumentId, m_bundleSettings);
- QString msg = "In BundleAdjust::init(): observation " + observationNumber + "is null" + "\n";
-
-
- bool BundleAdjust::validateNetwork() {
- ( numMeasures <= 1 ) for int numMeasures = m_controlNet->GetNumberOfValidMeasuresInImage(m_serialNumberList->SerialNumber(i));
- ( nimagesWithInsufficientMeasures > 0 )
- QString msg = "Images with one or less measures:\n";
-
- void BundleAdjust::checkHeldList() {
- (m_serialNumberList->HasSerialNumber(m_heldImageSerialNumberList->SerialNumber(ih))==false)
- QString msg = "Held image not in FROMLIST";
-
-#endif
diff --git a/isis/src/control/objs/BundleResults/unitTest.cpp b/isis/src/control/objs/BundleResults/unitTest.cpp
index 543730ea904aaa928f5853531718a4ff8a0197aa..74659cf7b6382710078ec81055287544d928205f 100755
--- a/isis/src/control/objs/BundleResults/unitTest.cpp
+++ b/isis/src/control/objs/BundleResults/unitTest.cpp
@@ -17,7 +17,7 @@ find files of those names at the top level of this repository. **/
#include
#include "BundleControlPoint.h"
-#include "BundleObservation.h"
+#include "IsisBundleObservation.h"
#include "BundleObservationVector.h"
#include "BundleResults.h"
#include "Camera.h"
@@ -58,20 +58,19 @@ namespace Isis {
BundleResultsXmlHandlerTester(Project *project, XmlStackedHandlerReader *reader,
FileName xmlFile) : BundleResults(project, reader) {
- QString xmlPath(xmlFile.expanded());
- QFile file(xmlPath);
+ m_file.setFileName(xmlFile.expanded());
- if (!file.open(QFile::ReadOnly) ) {
+ if (!m_file.open(QFile::ReadOnly) ) {
throw IException(IException::Io,
- QString("Unable to open xml file, [%1], with read access").arg(xmlPath),
+ QString("Unable to open xml file, [%1], with read access").arg(xmlFile.expanded()),
_FILEINFO_);
}
- QXmlInputSource xmlInputSource(&file);
+ QXmlInputSource xmlInputSource(&m_file);
bool success = reader->parse(xmlInputSource);
if (!success) {
throw IException(IException::Unknown,
- QString("Failed to parse xml file, [%1]").arg(xmlPath),
+ QString("Failed to parse xml file, [%1]").arg(m_file.fileName()),
_FILEINFO_);
}
@@ -81,8 +80,13 @@ namespace Isis {
* Destroys the tester object
*/
~BundleResultsXmlHandlerTester() {
+ if (m_file.exists()) {
+ m_file.remove();
+ }
}
+ QFile m_file;
+
};
}
@@ -250,7 +254,14 @@ int main(int argc, char *argv[]) {
QVector bundleControlPointVector;
bundleControlPointVector.append(freeBundleControlPoint);
bundleControlPointVector.append(fixedBundleControlPoint);
+
+ // Need to create a camera
+ QString inputFile = "$ISISTESTDATA/isis/src/mgs/unitTestData/ab102401.lev2.cub";
+ Cube cube;
+ cube.open(inputFile);
Camera *camera = NULL;
+ camera = cube.camera();
+
BundleImage bundleImage(camera,
"TestImageSerialNumber",
"TestImageFileName");
diff --git a/isis/src/control/objs/BundleSettings/BundleSettings.cpp b/isis/src/control/objs/BundleSettings/BundleSettings.cpp
index 5d59ee3d680b33952ef032545e5fb1c569939385..87100ff498ba218a6cf3cc8cbba637a3b395c19a 100644
--- a/isis/src/control/objs/BundleSettings/BundleSettings.cpp
+++ b/isis/src/control/objs/BundleSettings/BundleSettings.cpp
@@ -541,9 +541,6 @@ namespace Isis {
}
}
return defaultSolveSettings;
- //QString msg = "Unable to find BundleObservationSolveSettings for observation number ["
- // + observationNumber + "].";
- // throw IException(IException::Unknown, msg, _FILEINFO_);
}
diff --git a/isis/src/control/objs/BundleSolutionInfo/BundleSolutionInfo.cpp b/isis/src/control/objs/BundleSolutionInfo/BundleSolutionInfo.cpp
index a818ed20e50f0f1b59c28829e3c5e12b0c7ee7e9..a18844c3d0514e44dc04b926e7b0fd5c71490365 100755
--- a/isis/src/control/objs/BundleSolutionInfo/BundleSolutionInfo.cpp
+++ b/isis/src/control/objs/BundleSolutionInfo/BundleSolutionInfo.cpp
@@ -392,6 +392,7 @@ namespace Isis {
/**
* @brief Outputs the header for the bundleout_images.csv file
* @param fpOut The output file stream.
+ * @param observation An observation for the instrument that this header is for.
* @return True if the write is successful, False otherwise.
*
* @internal
@@ -399,7 +400,7 @@ namespace Isis {
* than the other headers. The number of TWIST headers will be the same
* as each of the other angle headers. Fixes #4557.
*/
- bool BundleSolutionInfo::outputImagesCSVHeader(std::ofstream &fpOut) {
+ bool BundleSolutionInfo::outputImagesCSVHeader(std::ofstream &fpOut, BundleObservationQsp observation) {
if (!fpOut) {
return false;
@@ -415,78 +416,11 @@ namespace Isis {
outputColumns.push_back("rms,");
outputColumns.push_back("rms,");
- BundleObservationSolveSettings obsSettings = m_settings->observationSolveSettings(0);
+ QStringList observationParameters = observation->parameterList();
- int numberCamPosCoefSolved = obsSettings.numberCameraPositionCoefficientsSolved();
- int numberCamAngleCoefSolved = obsSettings.numberCameraAngleCoefficientsSolved();
-
- int nCoeff = 1;
- if (numberCamPosCoefSolved > 0)
- nCoeff = numberCamPosCoefSolved;
-
- for (int i = 0; i < nCoeff; i++) {
- for (int j = 0; j < 5; j++) {
- if (nCoeff == 1)
- outputColumns.push_back("X,");
- else {
- QString str = "X(t" + toString(i) + "),";
- outputColumns.push_back(str);
- }
- }
- }
- for (int i = 0; i < nCoeff; i++) {
- for (int j = 0; j < 5; j++) {
- if (nCoeff == 1)
- outputColumns.push_back("Y,");
- else {
- QString str = "Y(t" + toString(i) + "),";
- outputColumns.push_back(str);
- }
- }
- }
- for (int i = 0; i < nCoeff; i++) {
- for (int j = 0; j < 5; j++) {
- if (nCoeff == 1) {
- outputColumns.push_back("Z,");
- }
- else {
- QString str = "Z(t" + toString(i) + "),";
- outputColumns.push_back(str);
- }
- }
- if (!i)
- break;
- }
-
- for (int i = 0; i < numberCamAngleCoefSolved; i++) {
+ for (int i = 0; i < observationParameters.size(); i++) {
for (int j = 0; j < 5; j++) {
- if (numberCamAngleCoefSolved == 1)
- outputColumns.push_back("RA,");
- else {
- QString str = "RA(t" + toString(i) + "),";
- outputColumns.push_back(str);
- }
- }
- }
- for (int i = 0; i < numberCamAngleCoefSolved; i++) {
- for (int j = 0; j < 5; j++) {
- if (numberCamAngleCoefSolved == 1)
- outputColumns.push_back("DEC,");
- else {
- QString str = "DEC(t" + toString(i) + "),";
- outputColumns.push_back(str);
- }
- }
- }
- for (int i = 0; i < numberCamAngleCoefSolved; i++) {
- for (int j = 0; j < 5; j++) {
- if (numberCamAngleCoefSolved == 1) {
- outputColumns.push_back("TWIST,");
- }
- else {
- QString str = "TWIST(t" + toString(i) + "),";
- outputColumns.push_back(str);
- }
+ outputColumns.push_back(observationParameters[i] + ",");
}
}
@@ -501,23 +435,13 @@ namespace Isis {
fpOut << buf;
outputColumns.clear();
- outputColumns.push_back("Filename,");
+ outputColumns.push_back("Filename,");
outputColumns.push_back("sample res,");
outputColumns.push_back("line res,");
outputColumns.push_back("total res,");
- // Initially account for X,Y,Z (3)
- int nparams = 3;
- // See how many position coeffients we solved for to make more headers (t0, t1, ...)
- if (numberCamPosCoefSolved)
- nparams = 3 * numberCamPosCoefSolved;
-
- // Initially account for RA,DEC,TWIST (3)
- int numCameraAnglesSolved = 3;
- // See how many angle coefficients we solved for to make more headers (t0, t1, ...)
- nparams += numCameraAnglesSolved*numberCamAngleCoefSolved;
- for (int i = 0; i < nparams; i++) {
+ for (int i = 0; i < observationParameters.size(); i++) {
outputColumns.push_back("Initial,");
outputColumns.push_back("Correction,");
outputColumns.push_back("Final,");
@@ -1161,82 +1085,110 @@ namespace Isis {
bool BundleSolutionInfo::outputImagesCSV() {
char buf[1056];
- int imgIndex = 0;
QList rmsImageSampleResiduals = m_statisticsResults->rmsImageSampleResiduals();
QList rmsImageLineResiduals = m_statisticsResults->rmsImageLineResiduals();
QList rmsImageResiduals = m_statisticsResults->rmsImageResiduals();
- QString ofname = "bundleout_images.csv";
- ofname = m_settings->outputFilePrefix() + ofname;
- m_csvSavedImagesFilename = ofname;
-
- std::ofstream fpOut(ofname.toLatin1().data(), std::ios::out);
- if (!fpOut) {
- return false;
+ bool errorProp = false;
+ if (m_statisticsResults->converged() && m_settings->errorPropagation()) {
+ errorProp = true;
}
+ QList outputCsvFileNames;
+ QList instrumentIds = m_statisticsResults->observations().instrumentIds();
+ // If there's just a single instrumentId just call it bundleout_images.csv
+ if (instrumentIds.size() == 1) {
+ QString ofname = "bundleout_images.csv";
+ ofname = m_settings->outputFilePrefix() + ofname;
+ m_csvSavedImagesFilename = ofname;
+ outputCsvFileNames.push_back(ofname);
+ }
+ // Otherwise append the instrument IDs so it's bundleout_images_spacecraft_sensor.csv
+ else {
+ for (int i = 0; i < instrumentIds.size(); i++) {
+ QString updatedInstrumentId = instrumentIds[i];
+ // Replace and "/" or " " characters with "_" to make the filename safer
+ // This line must be separate to avoid modifying the instrumentId in the list
+ // we will iterate over later
+ updatedInstrumentId.replace("/", "_").replace(" ", "_");
+ QString ofname = "bundleout_images_" + updatedInstrumentId + ".csv";
+ ofname = m_settings->outputFilePrefix() + ofname;
+ m_csvSavedImagesFilename = ofname;
+ outputCsvFileNames.push_back(ofname);
+ }
+ }
- BundleObservationQsp observation;
+ for (int i = 0; i < instrumentIds.size(); i++) {
- int nObservations = m_statisticsResults->observations().size();
+ std::ofstream fpOut(outputCsvFileNames[i].toLatin1().data(), std::ios::out);
+ if (!fpOut) {
+ return false;
+ }
- outputImagesCSVHeader(fpOut);
+ QList observations =
+ m_statisticsResults->observations().observationsByInstId(instrumentIds[i]);
- bool errorProp = false;
- if (m_statisticsResults->converged() && m_settings->errorPropagation()) {
- errorProp = true;
- }
+ int nObservations = observations.size();
- for (int i = 0; i < nObservations;i++ ) {
- observation = m_statisticsResults->observations().at(i);
+ outputImagesCSVHeader(fpOut, observations.front());
- if(!observation) {
- continue;
- }
+ for (int j = 0; j < nObservations; j++ ) {
+ BundleObservationQsp observation = observations[j];
- int numImages = observation->size();
+ // We need the image index, not the observation index,
+ // so count all of the images prior to this observation
+ int observationIndex = observation->index();
+ int imgIndex = 0;
+ for (int obsIndex = 0; obsIndex < observationIndex; obsIndex++) {
+ imgIndex += m_statisticsResults->observations().at(obsIndex)->size();
+ }
- for (int j = 0; j < numImages; j++) {
+ if(!observation) {
+ continue;
+ }
- BundleImageQsp image = observation->at(j);
+ int numImages = observation->size();
+ for (int k = 0; k < numImages; k++) {
+ BundleImageQsp image = observation->at(k);
- sprintf(buf, "%s", image->fileName().toLatin1().data());
- fpOut << buf;
- sprintf(buf,",");
- fpOut << buf;
+ sprintf(buf, "%s", image->fileName().toLatin1().data());
+ fpOut << buf;
+ sprintf(buf,",");
+ fpOut << buf;
- fpOut << toString(rmsImageSampleResiduals[imgIndex].Rms()).toLatin1().data();
- sprintf(buf,",");
- fpOut << buf;
+ fpOut << toString(rmsImageSampleResiduals[imgIndex].Rms()).toLatin1().data();
+ sprintf(buf,",");
+ fpOut << buf;
- fpOut << toString(rmsImageLineResiduals[imgIndex].Rms()).toLatin1().data();
- sprintf(buf,",");
- fpOut << buf;
+ fpOut << toString(rmsImageLineResiduals[imgIndex].Rms()).toLatin1().data();
+ sprintf(buf,",");
+ fpOut << buf;
- fpOut << toString(rmsImageResiduals[imgIndex].Rms()).toLatin1().data();
- sprintf(buf,",");
- fpOut << buf;
+ fpOut << toString(rmsImageResiduals[imgIndex].Rms()).toLatin1().data();
+ sprintf(buf,",");
+ fpOut << buf;
- QString observationString =
- observation->bundleOutputCSV(errorProp);
+ QString observationString =
+ observation->bundleOutputCSV(errorProp);
- //Removes trailing commas
- if (observationString.right(1)==",") {
- observationString.truncate(observationString.length()-1);
- }
+ //Removes trailing commas
+ if (observationString.right(1)==",") {
+ observationString.truncate(observationString.length()-1);
+ }
- fpOut << (const char*) observationString.toLatin1().data();
+ fpOut << (const char*) observationString.toLatin1().data();
- sprintf(buf,"\n");
- fpOut << buf;
- imgIndex++;
+ sprintf(buf,"\n");
+ fpOut << buf;
+ imgIndex++;
+ }
}
- }
+ fpOut.close();
+ }
- fpOut.close();
return true;
}
diff --git a/isis/src/control/objs/BundleSolutionInfo/BundleSolutionInfo.h b/isis/src/control/objs/BundleSolutionInfo/BundleSolutionInfo.h
index f34e7b3e0d6331362caea8e1beb251b877c47998..1a145c7d0afd750c8827e304e583569809645cfa 100755
--- a/isis/src/control/objs/BundleSolutionInfo/BundleSolutionInfo.h
+++ b/isis/src/control/objs/BundleSolutionInfo/BundleSolutionInfo.h
@@ -13,6 +13,7 @@ find files of those names at the top level of this repository. **/
#include
#include
+#include "BundleObservation.h"
#include "BundleSettings.h"
#include "SurfacePoint.h"
@@ -195,7 +196,7 @@ namespace Isis {
QString name() const;
- bool outputImagesCSVHeader(std::ofstream &fpOut);
+ bool outputImagesCSVHeader(std::ofstream &fpOut, BundleObservationQsp observations);
bool outputHeader(std::ofstream &fpOut);
bool outputText();
bool outputImagesCSV();
diff --git a/isis/src/control/objs/BundleSolutionInfo/BundleSolutionInfo.truth b/isis/src/control/objs/BundleSolutionInfo/BundleSolutionInfo.truth
index 43b5106ed80dc31c723c17e6594a928b701c4b52..2763b3088a98ecbe3d0a7ab8cb64624bfb65bc8d 100644
--- a/isis/src/control/objs/BundleSolutionInfo/BundleSolutionInfo.truth
+++ b/isis/src/control/objs/BundleSolutionInfo/BundleSolutionInfo.truth
@@ -424,12 +424,12 @@ Serializing test XML object to file...
- X (km)
- Y (km)
- Z (km)
- RA (dd)
- DEC (dd)
- TWI (dd)
+ X
+ Y
+ Z
+ RA
+ DEC
+ TWIST
@@ -528,12 +528,12 @@ Testing XML: Object deserialized as (should match object above):
- X (km)
- Y (km)
- Z (km)
- RA (dd)
- DEC (dd)
- TWI (dd)
+ X
+ Y
+ Z
+ RA
+ DEC
+ TWIST
diff --git a/isis/src/control/objs/BundleSolutionInfo/unitTest.cpp b/isis/src/control/objs/BundleSolutionInfo/unitTest.cpp
index 17d0ebf79e88d701d8c9c596413a2b4ca7a0844b..91ec517712ee0c5f978cc2b8b0d379f70e5a25ed 100755
--- a/isis/src/control/objs/BundleSolutionInfo/unitTest.cpp
+++ b/isis/src/control/objs/BundleSolutionInfo/unitTest.cpp
@@ -139,7 +139,14 @@ int main(int argc, char *argv[]) {
QVector bundleControlPointVector;
bundleControlPointVector.append(freeBundleControlPoint);
bundleControlPointVector.append(fixedBundleControlPoint);
+
+ // Need to create a camera
+ QString inputFile = "$ISISTESTDATA/isis/src/mgs/unitTestData/ab102401.lev2.cub";
+ Cube cube;
+ cube.open(inputFile);
Camera *camera = NULL;
+ camera = cube.camera();
+
BundleImage bundleImage(camera,
"Ignored",
"TestImageFileName");
diff --git a/isis/src/control/objs/BundleUtilities/BundleObservation.cpp b/isis/src/control/objs/BundleUtilities/BundleObservation.cpp
index 4b1817bf7d9a55b6952d80ac90195e4ce458baa7..5ea21f532c1e19e0ce0ff778c43016e96801964a 100644
--- a/isis/src/control/objs/BundleUtilities/BundleObservation.cpp
+++ b/isis/src/control/objs/BundleUtilities/BundleObservation.cpp
@@ -31,15 +31,11 @@ namespace Isis {
BundleObservation::BundleObservation() {
m_serialNumbers.clear();
m_imageNames.clear();
- m_parameterNamesList.clear();
m_observationNumber = "";
m_instrumentId = "";
- m_instrumentRotation = NULL;
- m_instrumentPosition = NULL;
m_index = 0;
m_weights.clear();
m_corrections.clear();
-// m_solution.clear();
m_aprioriSigmas.clear();
m_adjustedSigmas.clear();
}
@@ -58,48 +54,22 @@ namespace Isis {
QString instrumentId, BundleTargetBodyQsp bundleTargetBody) {
m_serialNumbers.clear();
m_imageNames.clear();
- m_parameterNamesList.clear();
m_observationNumber = "";
m_instrumentId = "";
- m_instrumentRotation = NULL;
- m_instrumentPosition = NULL;
m_index = 0;
m_weights.clear();
m_corrections.clear();
-// m_solution.clear();
m_aprioriSigmas.clear();
m_adjustedSigmas.clear();
m_observationNumber = observationNumber;
m_instrumentId = instrumentId;
- m_bundleTargetBody = bundleTargetBody;
-
if (image) {
append(image);
m_serialNumbers.append(image->serialNumber());
m_imageNames.append(image->fileName());
m_cubeSerialNumberToBundleImageMap.insert(image->serialNumber(), image);
-
- // set the observations spice position and rotation objects from the primary image in the
- // observation (this is, by design at the moment, the first image added to the observation)
- // if the image, camera, or instrument position/orientation is null, then set to null
- m_instrumentPosition = (image->camera() ?
- (image->camera()->instrumentPosition() ?
- image->camera()->instrumentPosition() : NULL)
- : NULL);
- m_instrumentRotation = (image->camera() ?
- (image->camera()->instrumentRotation() ?
- image->camera()->instrumentRotation() : NULL)
- : NULL);
-
- // set the observations target body spice rotation object from the primary image in the
- // observation (this is, by design at the moment, the first image added to the observation)
- // if the image, camera, or instrument position/orientation is null, then set to null
-// m_bodyRotation = (image->camera() ?
-// (image->camera()->bodyRotation() ?
-// image->camera()->bodyRotation() : NULL)
-// : NULL);
}
}
@@ -116,11 +86,6 @@ namespace Isis {
m_observationNumber = src.m_observationNumber;
m_instrumentId = src.m_instrumentId;
- m_instrumentPosition = src.m_instrumentPosition;
- m_instrumentRotation = src.m_instrumentRotation;
-
- m_solveSettings = src.m_solveSettings;
-
m_index = src.m_index;
}
@@ -152,11 +117,8 @@ namespace Isis {
m_observationNumber = src.m_observationNumber;
m_instrumentId = src.m_instrumentId;
- m_instrumentPosition = src.m_instrumentPosition;
- m_instrumentRotation = src.m_instrumentRotation;
-
- m_solveSettings = src.m_solveSettings;
}
+
return *this;
}
@@ -197,52 +159,6 @@ namespace Isis {
}
- /**
- * Set solve parameters
- *
- * @param solveSettings The solve settings to use
- *
- * @return @b bool Returns true if settings were successfully set
- *
- * @internal
- * @todo initParameterWeights() doesn't return false, so this methods always
- * returns true.
- */
- bool BundleObservation::setSolveSettings(BundleObservationSolveSettings solveSettings) {
- m_solveSettings = BundleObservationSolveSettingsQsp(
- new BundleObservationSolveSettings(solveSettings));
-
- // initialize solution parameters for this observation
- int nCameraAngleCoefficients = m_solveSettings->numberCameraAngleCoefficientsSolved();
- int nCameraPositionCoefficients = m_solveSettings->numberCameraPositionCoefficientsSolved();
-
- int nParameters = 3*nCameraPositionCoefficients + 2*nCameraAngleCoefficients;
- if (nCameraAngleCoefficients >= 1 && m_solveSettings->solveTwist()) {
- nParameters += nCameraAngleCoefficients;
- }
- // size vectors and set to zero
- m_weights.resize(nParameters);
- m_weights.clear();
- m_corrections.resize(nParameters);
- m_corrections.clear();
-// m_solution.resize(nParameters);
-// m_solution.clear();
- m_adjustedSigmas.resize(nParameters);
- m_adjustedSigmas.clear();
- m_aprioriSigmas.resize(nParameters);
- for ( int i = 0; i < nParameters; i++) // initialize apriori sigmas to -1.0
- m_aprioriSigmas[i] = Isis::Null;
-
- if (!initParameterWeights()) {
- // TODO: some message here!!!!!!!!!!!
- // TODO: do we need this??? initParameterWeights() never returns false...
- return false;
- }
-
- return true;
- }
-
-
/**
* Accesses the instrument id
*
@@ -253,26 +169,6 @@ namespace Isis {
}
- /**
- * Accesses the instrument's spice rotation
- *
- * @return @b SpiceRotation* Returns the SpiceRotation for this observation
- */
- SpiceRotation *BundleObservation::spiceRotation() {
- return m_instrumentRotation;
- }
-
-
- /**
- * Accesses the instrument's spice position
- *
- * @return @b SpicePosition* Returns the SpicePosition for this observation
- */
- SpicePosition *BundleObservation::spicePosition() {
- return m_instrumentPosition;
- }
-
-
/**
* Accesses the solve parameter weights
*
@@ -293,15 +189,6 @@ namespace Isis {
}
- /**
- * @internal
- * @todo
- */
-// LinearAlgebra::Vector &BundleObservation::parameterSolution() {
-// return m_solution;
-// }
-
-
/**
* Accesses the a priori sigmas
*
@@ -322,456 +209,6 @@ namespace Isis {
}
- /**
- * Accesses the solve settings
- *
- * @return @b const BundleObservationSolveSettingsQsp Returns a pointer to the solve
- * settings for this BundleObservation
- */
- const BundleObservationSolveSettingsQsp BundleObservation::solveSettings() {
- return m_solveSettings;
- }
-
-
- /**
- * Initializes the exterior orientation
- *
- * @return @b bool Returns true upon successful intialization
- *
- * @internal
- * @todo Should this always return true?
- */
- bool BundleObservation::initializeExteriorOrientation() {
-
- if (m_solveSettings->instrumentPositionSolveOption() !=
- BundleObservationSolveSettings::NoPositionFactors) {
-
- double positionBaseTime = 0.0;
- double positiontimeScale = 0.0;
- std::vector posPoly1, posPoly2, posPoly3;
-
- for (int i = 0; i < size(); i++) {
- BundleImageQsp image = at(i);
- SpicePosition *spicePosition = image->camera()->instrumentPosition();
-
- if (i > 0) {
- spicePosition->SetPolynomialDegree(m_solveSettings->spkSolveDegree());
- spicePosition->SetOverrideBaseTime(positionBaseTime, positiontimeScale);
- spicePosition->SetPolynomial(posPoly1, posPoly2, posPoly3,
- m_solveSettings->positionInterpolationType());
- }
- else {
- // first, set the degree of the spk polynomial to be fit for a priori values
- spicePosition->SetPolynomialDegree(m_solveSettings->spkDegree());
-
- // now, set what kind of interpolation to use (SPICE, memcache, hermitecache, polynomial
- // function, or polynomial function over constant hermite spline)
- // TODO: verify - I think this actually performs the a priori fit
- spicePosition->SetPolynomial(m_solveSettings->positionInterpolationType());
-
- // finally, set the degree of the spk polynomial actually used in the bundle adjustment
- spicePosition->SetPolynomialDegree(m_solveSettings->spkSolveDegree());
-
- if (m_instrumentPosition) { // ??? TODO: why is this different from rotation code below???
- positionBaseTime = m_instrumentPosition->GetBaseTime();
- positiontimeScale = m_instrumentPosition->GetTimeScale();
- m_instrumentPosition->GetPolynomial(posPoly1, posPoly2, posPoly3);
- }
- }
- }
- }
-
- if (m_solveSettings->instrumentPointingSolveOption() !=
- BundleObservationSolveSettings::NoPointingFactors) {
-
- double rotationBaseTime = 0.0;
- double rotationtimeScale = 0.0;
- std::vector anglePoly1, anglePoly2, anglePoly3;
-
- for (int i = 0; i < size(); i++) {
- BundleImageQsp image = at(i);
- SpiceRotation *spicerotation = image->camera()->instrumentRotation();
-
- if (i > 0) {
- spicerotation->SetPolynomialDegree(m_solveSettings->ckSolveDegree());
- spicerotation->SetOverrideBaseTime(rotationBaseTime, rotationtimeScale);
- spicerotation->SetPolynomial(anglePoly1, anglePoly2, anglePoly3,
- m_solveSettings->pointingInterpolationType());
- }
- else {
- // first, set the degree of the spk polynomial to be fit for a priori values
- spicerotation->SetPolynomialDegree(m_solveSettings->ckDegree());
-
- // now, set what kind of interpolation to use (SPICE, memcache, hermitecache, polynomial
- // function, or polynomial function over constant hermite spline)
- // TODO: verify - I think this actually performs the a priori fit
- spicerotation->SetPolynomial(m_solveSettings->pointingInterpolationType());
-
- // finally, set the degree of the spk polynomial actually used in the bundle adjustment
- spicerotation->SetPolynomialDegree(m_solveSettings->ckSolveDegree());
-
- rotationBaseTime = spicerotation->GetBaseTime();
- rotationtimeScale = spicerotation->GetTimeScale();
- spicerotation->GetPolynomial(anglePoly1, anglePoly2, anglePoly3);
- }
- }
- }
-
- return true;
- }
-
-
- /**
- * Intializes the body rotation
- *
- * @todo check to make sure m_bundleTargetBody is valid
- */
- void BundleObservation::initializeBodyRotation() {
- std::vector raCoefs = m_bundleTargetBody->poleRaCoefs();
- std::vector decCoefs = m_bundleTargetBody->poleDecCoefs();
- std::vector pmCoefs = m_bundleTargetBody->pmCoefs();
-
- for (int i = 0; i < size(); i++) {
- BundleImageQsp image = at(i);
- image->camera()->bodyRotation()->setPckPolynomial(raCoefs, decCoefs, pmCoefs);
- }
- }
-
-
- /**
- * Updates the body rotation
- *
- * @internal
- * @todo Is this a duplicate of initializeBodyRotation?
- */
- void BundleObservation::updateBodyRotation() {
- std::vector raCoefs = m_bundleTargetBody->poleRaCoefs();
- std::vector decCoefs = m_bundleTargetBody->poleDecCoefs();
- std::vector pmCoefs = m_bundleTargetBody->pmCoefs();
-
- for (int i = 0; i < size(); i++) {
- BundleImageQsp image = at(i);
- image->camera()->bodyRotation()->setPckPolynomial(raCoefs, decCoefs, pmCoefs);
- }
- }
-
-
-/*
- bool BundleObservation::initializeExteriorOrientation() {
-
- if (m_solveSettings->instrumentPositionSolveOption() !=
- BundleObservationSolveSettings::NoPositionFactors) {
-
- for (int i = 0; i < size(); i++) {
- BundleImageQsp image = at(i);
- SpicePosition *spiceposition = image->camera()->instrumentPosition();
-
- // first, set the degree of the spk polynomial to be fit for a priori values
- spiceposition->SetPolynomialDegree(m_solveSettings->spkDegree());
-
- // now, set what kind of interpolation to use (SPICE, memcache, hermitecache, polynomial
- // function, or polynomial function over constant hermite spline)
- // TODO: verify - I think this actually performs the a priori fit
- spiceposition->SetPolynomial(m_solveSettings->positionInterpolationType());
-
- // finally, set the degree of the spk polynomial actually used in the bundle adjustment
- spiceposition->SetPolynomialDegree(m_solveSettings->spkSolveDegree());
- }
- }
-
- if (m_solveSettings->instrumentPointingSolveOption() !=
- BundleObservationSolveSettings::NoPointingFactors) {
-
- for (int i = 0; i < size(); i++) {
- BundleImageQsp image = at(i);
- SpiceRotation *spicerotation = image->camera()->instrumentRotation();
-
- // first, set the degree of the spk polynomial to be fit for a priori values
- spicerotation->SetPolynomialDegree(m_solveSettings->ckDegree());
-
- // now, set what kind of interpolation to use (SPICE, memcache, hermitecache, polynomial
- // function, or polynomial function over constant hermite spline)
- // TODO: verify - I think this actually performs the a priori fit
- spicerotation->SetPolynomial(m_solveSettings->pointingInterpolationType());
-
- // finally, set the degree of the spk polynomial actually used in the bundle adjustment
- spicerotation->SetPolynomialDegree(m_solveSettings->ckSolveDegree());
- }
- }
-
- return true;
- }
-*/
-
-
- /**
- * Initializes the paramater weights for solving
- *
- * @return @b bool Returns true upon successful intialization
- *
- * @internal
- * @todo Don't like this, don't like this, don't like this, don't like this, don't like this.
- * By the way, this seems klunky to me, would like to come up with a better way.
- * Also, apriori sigmas are in two places, the BundleObservationSolveSettings AND in the
- * the BundleObservation class too - this is unnecessary should only be in the
- * BundleObservationSolveSettings. But, they are split into position and pointing.
- *
- * @todo always returns true?
- */
- bool BundleObservation::initParameterWeights() {
-
- // weights for
- double posWeight = 0.0; // position
- double velWeight = 0.0; // velocity
- double accWeight = 0.0; // acceleration
- double angWeight = 0.0; // angles
- double angVelWeight = 0.0; // angular velocity
- double angAccWeight = 0.0; // angular acceleration
-
- QList aprioriPointingSigmas = m_solveSettings->aprioriPointingSigmas();
- QList aprioriPositionSigmas = m_solveSettings->aprioriPositionSigmas();
-
- int nCamPosCoeffsSolved = 3 *m_solveSettings->numberCameraPositionCoefficientsSolved();
-
- int nCamAngleCoeffsSolved;
- if (m_solveSettings->solveTwist()) {
- nCamAngleCoeffsSolved = 3 *m_solveSettings->numberCameraAngleCoefficientsSolved();
- }
- else {
- nCamAngleCoeffsSolved = 2 *m_solveSettings->numberCameraAngleCoefficientsSolved();
- }
-
- if (aprioriPositionSigmas.size() >= 1 && aprioriPositionSigmas.at(0) > 0.0) {
- posWeight = aprioriPositionSigmas.at(0);
- posWeight = 1.0 / (posWeight *posWeight * 1.0e-6);
- }
- if (aprioriPositionSigmas.size() >= 2 && aprioriPositionSigmas.at(1) > 0.0) {
- velWeight = aprioriPositionSigmas.at(1);
- velWeight = 1.0 / (velWeight *velWeight * 1.0e-6);
- }
- if (aprioriPositionSigmas.size() >= 3 && aprioriPositionSigmas.at(2) > 0.0) {
- accWeight = aprioriPositionSigmas.at(2);
- accWeight = 1.0 / (accWeight *accWeight * 1.0e-6);
- }
-
- if (aprioriPointingSigmas.size() >= 1 && aprioriPointingSigmas.at(0) > 0.0) {
- angWeight = aprioriPointingSigmas.at(0);
- angWeight = 1.0 / (angWeight *angWeight * DEG2RAD * DEG2RAD);
- }
- if (aprioriPointingSigmas.size() >= 2 && aprioriPointingSigmas.at(1) > 0.0) {
- angVelWeight = aprioriPointingSigmas.at(1);
- angVelWeight = 1.0 / (angVelWeight * angVelWeight * DEG2RAD * DEG2RAD);
- }
- if (aprioriPointingSigmas.size() >= 3 && aprioriPointingSigmas.at(2) > 0.0) {
- angAccWeight = aprioriPointingSigmas.at(2);
- angAccWeight = 1.0 / (angAccWeight * angAccWeight * DEG2RAD * DEG2RAD);
- }
-
- int nSpkTerms = m_solveSettings->spkSolveDegree()+1;
- nSpkTerms = m_solveSettings->numberCameraPositionCoefficientsSolved();
- for ( int i = 0; i < nCamPosCoeffsSolved; i++) {
- if (i % nSpkTerms == 0) {
- m_aprioriSigmas[i] = aprioriPositionSigmas.at(0);
- m_weights[i] = posWeight;
- }
- if (i % nSpkTerms == 1) {
- m_aprioriSigmas[i] = aprioriPositionSigmas.at(1);
- m_weights[i] = velWeight;
- }
- if (i % nSpkTerms == 2) {
- m_aprioriSigmas[i] = aprioriPositionSigmas.at(2);
- m_weights[i] = accWeight;
- }
- }
-
- int nCkTerms = m_solveSettings->ckSolveDegree()+1;
- nCkTerms = m_solveSettings->numberCameraAngleCoefficientsSolved();
- for ( int i = 0; i < nCamAngleCoeffsSolved; i++) {
- if (i % nCkTerms == 0) {
- m_aprioriSigmas[nCamPosCoeffsSolved + i] = aprioriPointingSigmas.at(0);
- m_weights[nCamPosCoeffsSolved + i] = angWeight;
- }
- if (i % nCkTerms == 1) {
- m_aprioriSigmas[nCamPosCoeffsSolved + i] = aprioriPointingSigmas.at(1);
- m_weights[nCamPosCoeffsSolved + i] = angVelWeight;
- }
- if (i % nCkTerms == 2) {
- m_aprioriSigmas[nCamPosCoeffsSolved + i] = aprioriPointingSigmas.at(2);
- m_weights[nCamPosCoeffsSolved + i] = angAccWeight;
- }
- }
-
-// for ( int i = 0; i < (int)m_weights.size(); i++ )
-// std::cout << m_weights[i] << std::endl;
-
- return true;
- }
-
-
- /**
- * Applies the parameter corrections
- *
- * @param corrections Vector of corrections to apply
- *
- * @throws IException::Unknown "Instrument position is NULL, but position solve option is
- * [not NoPositionFactors]"
- * @throws IException::Unknown "Instrument position is NULL, but pointing solve option is
- * [not NoPointingFactors]"
- * @throws IException::Unknown "Unable to apply parameter corrections to BundleObservation."
- *
- * @return @b bool Returns true upon successful application of corrections
- *
- * @internal
- * @todo always returns true?
- */
- bool BundleObservation::applyParameterCorrections(LinearAlgebra::Vector corrections) {
-
- int index = 0;
-
- try {
- int nCameraAngleCoefficients = m_solveSettings->numberCameraAngleCoefficientsSolved();
- int nCameraPositionCoefficients = m_solveSettings->numberCameraPositionCoefficientsSolved();
-
- BundleObservationSolveSettings::InstrumentPositionSolveOption positionOption
- = m_solveSettings->instrumentPositionSolveOption();
- if (positionOption != BundleObservationSolveSettings::NoPositionFactors) {
-
- if (!m_instrumentPosition) {
- QString msg = "Instrument position is NULL, but position solve option is ";
- msg.append(BundleObservationSolveSettings::instrumentPositionSolveOptionToString(
- positionOption));
- throw IException(IException::Unknown, msg, _FILEINFO_);
- }
-
- std::vector coefX(nCameraPositionCoefficients);
- std::vector coefY(nCameraPositionCoefficients);
- std::vector coefZ(nCameraPositionCoefficients);
-
- m_instrumentPosition->GetPolynomial(coefX, coefY, coefZ);
-
- // update X coordinate coefficient(s) and sum parameter correction
- for (int i = 0; i < nCameraPositionCoefficients; i++) {
- coefX[i] += corrections(index);
- index++;
- }
-
- // update Y coordinate coefficient(s) and sum parameter correction
- for (int i = 0; i < nCameraPositionCoefficients; i++) {
- coefY[i] += corrections(index);
- index++;
- }
-
- // update Z coordinate coefficient(s) and sum parameter correction
- for (int i = 0; i < nCameraPositionCoefficients; i++) {
- coefZ[i] += corrections(index);
- index++;
- }
-
- // apply updates to all images in observation
- for (int i = 0; i < size(); i++) {
- BundleImageQsp image = at(i);
- SpicePosition *spiceposition = image->camera()->instrumentPosition();
- spiceposition->SetPolynomial(coefX, coefY, coefZ,
- m_solveSettings->positionInterpolationType());
- }
- }
-
- BundleObservationSolveSettings::InstrumentPointingSolveOption pointingOption
- = m_solveSettings->instrumentPointingSolveOption();
- if (pointingOption != BundleObservationSolveSettings::NoPointingFactors) {
-
- if (!m_instrumentRotation) {
- QString msg = "Instrument rotation is NULL, but pointing solve option is ";
- msg.append(BundleObservationSolveSettings::instrumentPointingSolveOptionToString(
- pointingOption));
- throw IException(IException::Unknown, msg, _FILEINFO_);
- }
-
- std::vector coefRA(nCameraPositionCoefficients);
- std::vector coefDEC(nCameraPositionCoefficients);
- std::vector coefTWI(nCameraPositionCoefficients);
-
- m_instrumentRotation->GetPolynomial(coefRA, coefDEC, coefTWI);
-
- // update RA coefficient(s)
- for (int i = 0; i < nCameraAngleCoefficients; i++) {
- coefRA[i] += corrections(index);
- index++;
- }
-
- // update DEC coefficient(s)
- for (int i = 0; i < nCameraAngleCoefficients; i++) {
- coefDEC[i] += corrections(index);
- index++;
- }
-
- if (m_solveSettings->solveTwist()) {
- // update TWIST coefficient(s)
- for (int i = 0; i < nCameraAngleCoefficients; i++) {
- coefTWI[i] += corrections(index);
- index++;
- }
- }
-
- // apply updates to all images in observation
- for (int i = 0; i < size(); i++) {
- BundleImageQsp image = at(i);
- SpiceRotation *spiceRotation = image->camera()->instrumentRotation();
- spiceRotation->SetPolynomial(coefRA, coefDEC, coefTWI,
- m_solveSettings->pointingInterpolationType());
- }
- }
-
- // update corrections
- m_corrections += corrections;
-
- }
- catch (IException &e) {
- QString msg = "Unable to apply parameter corrections to BundleObservation.";
- throw IException(e, IException::Unknown, msg, _FILEINFO_);
- }
- return true;
- }
-
-
- /**
- * Returns the number of position parameters there are
- *
- * @return @b int Returns the number of position parameters
- */
- int BundleObservation::numberPositionParameters() {
- return 3.0 * m_solveSettings->numberCameraPositionCoefficientsSolved();
- }
-
-
- /**
- * Returns the number of pointing parameters being solved for
- *
- * @return @b int Returns the number of pointing parameters
- */
- int BundleObservation::numberPointingParameters() {
- int angleCoefficients = m_solveSettings->numberCameraAngleCoefficientsSolved();
-
- if (m_solveSettings->solveTwist()) {
- return 3.0 * angleCoefficients;
- }
- return 2.0 * angleCoefficients;
- }
-
-
- /**
- * Returns the number of total parameters there are for solving
- *
- * The total number of parameters is equal to the number of position parameters and number of
- * pointing parameters
- *
- * @return @b int Returns the number of parameters there are
- */
- int BundleObservation::numberParameters() {
- return numberPositionParameters() + numberPointingParameters();
- }
-
-
/**
* Sets the index for the observation
*
@@ -791,800 +228,6 @@ namespace Isis {
return m_index;
}
- /**
- * @brief Creates and returns a formatted QString representing the bundle coefficients and
- * parameters
- *
- * @depricated The function formatBundleOutputString is depricated as of ISIS 3.9
- * and will be removed in ISIS 4.0
- *
- * @param errorPropagation Boolean indicating whether or not to attach more information
- * (corrections, sigmas, adjusted sigmas...) to the output QString
- * @param imageCSV Boolean which is set to true if the function is being
- * called from BundleSolutionInfo::outputImagesCSV(). It is set to false by default
- * for backwards compatibility.
- *
- * @return @b QString Returns a formatted QString representing the BundleObservation
- *
- * @internal
- * @history 2016-10-26 Ian Humphrey - Default values are now provided for parameters that are
- * not being solved. Fixes #4464.
- */
-QString BundleObservation::formatBundleOutputString(bool errorPropagation, bool imageCSV) {
-
- std::cerr << "The function formatBundleOutputString is depricated as of ISIS 3.9"
- "and will be removed in ISIS 4.0" << std::endl;
-
- std::vector coefX;
- std::vector coefY;
- std::vector coefZ;
- std::vector coefRA;
- std::vector coefDEC;
- std::vector coefTWI;
-
- int nPositionCoefficients = m_solveSettings->numberCameraPositionCoefficientsSolved();
- int nPointingCoefficients = m_solveSettings->numberCameraAngleCoefficientsSolved();
-
- // Indicate if we need to obtain default position or pointing values
- bool useDefaultPosition = false;
- bool useDefaultPointing = false;
- // Indicate if we need to use default values when not solving twist
- bool useDefaultTwist = !(m_solveSettings->solveTwist());
-
- // If we aren't solving for position, set the number of coefficients to 1 so we can output the
- // instrumentPosition's center coordinate values for X, Y, and Z
- if (nPositionCoefficients == 0) {
- nPositionCoefficients = 1;
- useDefaultPosition = true;
- }
- // If we arent' solving for pointing, set the number of coefficients to 1 so we can output the
- // instrumentPointing's center angles for RA, DEC, and TWI
- if (nPointingCoefficients == 0) {
- nPointingCoefficients = 1;
- useDefaultPointing = true;
- }
-
- // Force number of position and pointing parameters to each be 3 (X,Y,Z; RA,DEC,TWI)
- // so we can always output a value for them
- int nPositionParameters = 3 * nPositionCoefficients;
- int nPointingParameters = 3 * nPointingCoefficients;
- int nParameters = nPositionParameters + nPointingParameters;
-
- coefX.resize(nPositionCoefficients);
- coefY.resize(nPositionCoefficients);
- coefZ.resize(nPositionCoefficients);
- coefRA.resize(nPointingCoefficients);
- coefDEC.resize(nPointingCoefficients);
- coefTWI.resize(nPointingCoefficients);
-
- if (m_instrumentPosition) {
- if (!useDefaultPosition) {
- m_instrumentPosition->GetPolynomial(coefX, coefY, coefZ);
- }
- // Use the position's center coordinate if not solving for spacecraft position
- else {
- const std::vector centerCoord = m_instrumentPosition->GetCenterCoordinate();
- coefX[0] = centerCoord[0];
- coefY[0] = centerCoord[1];
- coefZ[0] = centerCoord[2];
- }
- }
-
- if (m_instrumentRotation) {
- if (!useDefaultPointing) {
- m_instrumentRotation->GetPolynomial(coefRA, coefDEC, coefTWI);
- }
- // Use the pointing's center angles if not solving for pointing (rotation)
- else {
- const std::vector centerAngles = m_instrumentRotation->GetCenterAngles();
- coefRA[0] = centerAngles[0];
- coefDEC[0] = centerAngles[1];
- coefTWI[0] = centerAngles[2];
- }
- }
-
- // for convenience, create vectors of parameters names and values in the correct sequence
- std::vector finalParameterValues;
- QStringList parameterNamesList;
-
- if (!imageCSV) {
-
- QString str("%1(t%2)");
-
- if (nPositionCoefficients > 0) {
- for (int i = 0; i < nPositionCoefficients; i++) {
- finalParameterValues.push_back(coefX[i]);
- if (i == 0)
- parameterNamesList.append( str.arg(" X ").arg("0") );
- else
- parameterNamesList.append( str.arg(" ").arg(i) );
- }
- for (int i = 0; i < nPositionCoefficients; i++) {
- finalParameterValues.push_back(coefY[i]);
- if (i == 0)
- parameterNamesList.append( str.arg(" Y ").arg("0") );
- else
- parameterNamesList.append( str.arg(" ").arg(i) );
- }
- for (int i = 0; i < nPositionCoefficients; i++) {
- finalParameterValues.push_back(coefZ[i]);
- if (i == 0)
- parameterNamesList.append( str.arg(" Z ").arg("0") );
- else
- parameterNamesList.append( str.arg(" ").arg(i) );
- }
- }
- if (nPointingCoefficients > 0) {
- for (int i = 0; i < nPointingCoefficients; i++) {
- finalParameterValues.push_back(coefRA[i] * RAD2DEG);
- if (i == 0)
- parameterNamesList.append( str.arg(" RA ").arg("0") );
- else
- parameterNamesList.append( str.arg(" ").arg(i) );
- }
- for (int i = 0; i < nPointingCoefficients; i++) {
- finalParameterValues.push_back(coefDEC[i] * RAD2DEG);
- if (i == 0)
- parameterNamesList.append( str.arg("DEC ").arg("0") );
- else
- parameterNamesList.append( str.arg(" ").arg(i) );
- }
- for (int i = 0; i < nPointingCoefficients; i++) {
- finalParameterValues.push_back(coefTWI[i] * RAD2DEG);
- if (i == 0)
- parameterNamesList.append( str.arg("TWI ").arg("0") );
- else
- parameterNamesList.append( str.arg(" ").arg(i) );
- }
- }
-
- }// end if(!imageCSV)
-
- else {
- if (nPositionCoefficients > 0) {
- for (int i = 0; i < nPositionCoefficients; i++) {
- finalParameterValues.push_back(coefX[i]);
- }
- for (int i = 0; i < nPositionCoefficients; i++) {
- finalParameterValues.push_back(coefY[i]);
- }
- for (int i = 0; i < nPositionCoefficients; i++) {
- finalParameterValues.push_back(coefZ[i]);
- }
- }
- if (nPointingCoefficients > 0) {
- for (int i = 0; i < nPointingCoefficients; i++) {
- finalParameterValues.push_back(coefRA[i] * RAD2DEG);
- }
- for (int i = 0; i < nPointingCoefficients; i++) {
- finalParameterValues.push_back(coefDEC[i] * RAD2DEG);
- }
- for (int i = 0; i < nPointingCoefficients; i++) {
- finalParameterValues.push_back(coefTWI[i] * RAD2DEG);
- }
- }
- }//end else
-
- // Save the list of parameter names we've accumulated above
- m_parameterNamesList = parameterNamesList;
-
- QString finalqStr = "";
- QString qStr = "";
-
- // Set up default values when we are using default position
- QString sigma = "N/A";
- QString adjustedSigma = "N/A";
- double correction = 0.0;
-
- // this implies we're writing to bundleout.txt
- if (!imageCSV) {
- // position parameters
- for (int i = 0; i < nPositionParameters; i++) {
- // If not using the default position, we can correctly access sigmas and corrections
- // members
- if (!useDefaultPosition) {
- correction = m_corrections(i);
- adjustedSigma = QString::number(m_adjustedSigmas[i], 'f', 8);
- sigma = ( IsSpecial(m_aprioriSigmas[i]) ? "FREE" : toString(m_aprioriSigmas[i], 8) );
- }
- if (errorPropagation) {
- qStr = QString("%1%2%3%4%5%6\n").
- arg( parameterNamesList.at(i) ).
- arg(finalParameterValues[i] - correction, 17, 'f', 8).
- arg(correction, 21, 'f', 8).
- arg(finalParameterValues[i], 20, 'f', 8).
- arg(sigma, 18).
- arg(adjustedSigma, 18);
- }
- else {
- qStr = QString("%1%2%3%4%5%6\n").
- arg( parameterNamesList.at(i) ).
- arg(finalParameterValues[i] - correction, 17, 'f', 8).
- arg(correction, 21, 'f', 8).
- arg(finalParameterValues[i], 20, 'f', 8).
- arg(sigma, 18).
- arg("N/A", 18);
- }
- finalqStr += qStr;
- }
-
- // We need to use an offset of -3 (1 coef; X,Y,Z) if we used the default center coordinate
- // (i.e. we did not solve for position), as m_corrections and m_*sigmas are populated
- // according to which parameters are solved
- int offset = 0;
- if (useDefaultPosition) {
- offset = 3;
- }
- // pointing parameters
- for (int i = nPositionParameters; i < nParameters; i++) {
- if (!useDefaultPointing) {
- // If solving camera and not solving for twist, provide default values for twist to
- // prevent bad indexing into m_corrections and m_*sigmas
- // TWIST is last parameter, which corresponds to nParameters - nPointingCoefficients
- if ( (i >= nParameters - nPointingCoefficients) && useDefaultTwist) {
- correction = 0.0;
- adjustedSigma = "N/A";
- sigma = "N/A";
- }
- else {
- correction = m_corrections(i - offset);
- adjustedSigma = QString::number(m_adjustedSigmas(i-offset) * RAD2DEG, 'f', 8);
- sigma = ( IsSpecial(m_aprioriSigmas[i - offset]) ? "FREE" :
- toString(m_aprioriSigmas[i-offset], 8) );
- }
- }
- // We are using default pointing, so provide default correction and sigma values to output
- else {
- correction = 0.0;
- adjustedSigma = "N/A";
- sigma = "N/A";
- }
- if (errorPropagation) {
- qStr = QString("%1%2%3%4%5%6\n").
- arg( parameterNamesList.at(i) ).
- arg( (finalParameterValues[i] - correction * RAD2DEG), 17, 'f', 8).
- arg(correction * RAD2DEG, 21, 'f', 8).
- arg(finalParameterValues[i], 20, 'f', 8).
- arg(sigma, 18).
- arg(adjustedSigma, 18);
- }
- else {
- qStr = QString("%1%2%3%4%5%6\n").
- arg( parameterNamesList.at(i) ).
- arg( (finalParameterValues[i] - correction * RAD2DEG), 17, 'f', 8).
- arg(correction * RAD2DEG, 21, 'f', 8).
- arg(finalParameterValues[i], 20, 'f', 8).
- arg(sigma, 18).
- arg("N/A", 18);
- }
- finalqStr += qStr;
- }
-
- }
- // this implies we're writing to images.csv
- else {
- // position parameters
- for (int i = 0; i < nPositionParameters; i++) {
- if (!useDefaultPosition) {
- correction = m_corrections(i);
- adjustedSigma = QString::number(m_adjustedSigmas[i], 'f', 8);
- sigma = ( IsSpecial(m_aprioriSigmas[i]) ? "FREE" : toString(m_aprioriSigmas[i], 8) );
- }
- // Provide default values for position if not solving position
- else {
- correction = 0.0;
- adjustedSigma = "N/A";
- sigma = "N/A";
- }
- qStr = "";
- if (errorPropagation) {
- qStr += toString(finalParameterValues[i] - correction) + ",";
- qStr += toString(correction) + ",";
- qStr += toString(finalParameterValues[i]) + ",";
- qStr += sigma + ",";
- qStr += adjustedSigma + ",";
- }
- else {
- qStr += toString(finalParameterValues[i] - correction) + ",";
- qStr += toString(correction) + ",";
- qStr += toString(finalParameterValues[i]) + ",";
- qStr += sigma + ",";
- qStr += "N/A,";
- }
- finalqStr += qStr;
- }
-
- // If not solving position, we need to offset access to correction and sigma members by -3
- // (X,Y,Z) since m_corrections and m_*sigmas are populated according to which parameters are
- // solved
- int offset = 0;
- if (useDefaultPosition) {
- offset = 3;
- }
- // pointing parameters
- for (int i = nPositionParameters; i < nParameters; i++) {
- if (!useDefaultPointing) {
- // Use default values if solving camera but not solving for TWIST to prevent bad indexing
- // into m_corrections and m_*sigmas
- if ( (i >= nParameters - nPointingCoefficients) && useDefaultTwist) {
- correction = 0.0;
- adjustedSigma = "N/A";
- sigma = "N/A";
- }
- else {
- correction = m_corrections(i - offset);
- adjustedSigma = QString::number(m_adjustedSigmas(i-offset) * RAD2DEG, 'f', 8);
- sigma = ( IsSpecial(m_aprioriSigmas[i-offset]) ? "FREE" :
- toString(m_aprioriSigmas[i-offset], 8) );
- }
- }
- // Provide default values for pointing if not solving pointing
- else {
- correction = 0.0;
- adjustedSigma = "N/A";
- sigma = "N/A";
- }
- qStr = "";
- if (errorPropagation) {
- qStr += toString(finalParameterValues[i] - correction * RAD2DEG) + ",";
- qStr += toString(correction * RAD2DEG) + ",";
- qStr += toString(finalParameterValues[i]) + ",";
- qStr += sigma + ",";
- qStr += adjustedSigma + ",";
- }
- else {
- qStr += toString(finalParameterValues[i] - correction * RAD2DEG) + ",";
- qStr += toString(correction * RAD2DEG) + ",";
- qStr += toString(finalParameterValues[i]) + ",";
- qStr += sigma + ",";
- qStr += "N/A,";
- }
- finalqStr += qStr;
- }
- }
-
- return finalqStr;
-}
-
-
- /**
- * @brief Fetches data for the log file output methods.
- *
- * @param finalParameterValues Reference to QVector of calculated
- * position and pointing
- * @param nPositionCoefficients Reference to int of the number of position coefficients
- * @param nPointingCoefficients Reference to int of the number of pointing coefficients
- * @param useDefaultPosition Reference to boolean of whether to use default position
- * @param useDefaultPointing Reference to boolean of whether to use default pointing
- * @param useDefaultTwist Reference to bollean of whether to use defualt twist
- */
- void BundleObservation::bundleOutputFetchData(QVector &finalParameterValues,
- int &nPositionCoefficients, int &nPointingCoefficients,
- bool &useDefaultPosition,
- bool &useDefaultPointing, bool &useDefaultTwist) {
-
- std::vector coefX,coefY,coefZ,coefRA,coefDEC,coefTWI;
- nPositionCoefficients = m_solveSettings->numberCameraPositionCoefficientsSolved();
- nPointingCoefficients = m_solveSettings->numberCameraAngleCoefficientsSolved();
-
- // Indicate if we need to obtain default position or pointing values
- useDefaultPosition = false;
- useDefaultPointing = false;
- // Indicate if we need to use default values when not solving twist
- useDefaultTwist = !(m_solveSettings->solveTwist());
-
- // If we aren't solving for position, set the number of coefficients to 1 so we
- // can output the instrumentPosition's center coordinate values for X, Y, and Z
- if (nPositionCoefficients == 0) {
- nPositionCoefficients = 1;
- useDefaultPosition = true;
- }
-
- // If we arent' solving for pointing, set the number of coefficients to 1 so we
- // can output the instrumentPointing's center angles for RA, DEC, and TWI
- if (nPointingCoefficients == 0) {
- nPointingCoefficients = 1;
- useDefaultPointing = true;
- }
-
- coefX.resize(nPositionCoefficients);
- coefY.resize(nPositionCoefficients);
- coefZ.resize(nPositionCoefficients);
- coefRA.resize(nPointingCoefficients);
- coefDEC.resize(nPointingCoefficients);
- coefTWI.resize(nPointingCoefficients);
-
- if (m_instrumentPosition) {
- if (!useDefaultPosition) {
- m_instrumentPosition->GetPolynomial(coefX,coefY,coefZ);
- }
- // Use the position's center coordinate if not solving for spacecraft position
- else {
- const std::vector centerCoord = m_instrumentPosition->GetCenterCoordinate();
- coefX[0] = centerCoord[0];
- coefY[0] = centerCoord[1];
- coefZ[0] = centerCoord[2];
- }
- }
-
- if (m_instrumentRotation) {
- if (!useDefaultPointing) {
- m_instrumentRotation->GetPolynomial(coefRA,coefDEC,coefTWI);
- }
- // Use the pointing's center angles if not solving for pointing (rotation)
- else {
- const std::vector centerAngles = m_instrumentRotation->GetCenterAngles();
- coefRA[0] = centerAngles[0];
- coefDEC[0] = centerAngles[1];
- coefTWI[0] = centerAngles[2];
- }
- }
-
- // Combine all vectors into one
- if (nPositionCoefficients > 0) {
- for (int i=0; i < nPositionCoefficients; i++) {
- finalParameterValues.append(coefX[i]);
- }
- for (int i=0; i < nPositionCoefficients; i++) {
- finalParameterValues.append(coefY[i]);
- }
- for (int i=0; i < nPositionCoefficients; i++) {
- finalParameterValues.append(coefZ[i]);
- }
- }
- if (nPointingCoefficients > 0) {
- for (int i=0; i < nPointingCoefficients; i++) {
- finalParameterValues.append(coefRA[i]);
- }
- for (int i=0; i < nPointingCoefficients; i++) {
- finalParameterValues.append(coefDEC[i]);
- }
- for (int i=0; i < nPointingCoefficients; i++) {
- finalParameterValues.append(coefTWI[i]);
- }
- }
-
- }
-
-
- /**
- * @brief Takes in an open std::ofstream and writes out information which goes into the
- * bundleout.txt file.
- *
- * @param fpOut The open std::ofstream object which is passed in from
- * BundleSolutionInfo::outputText()
- * @param errorPropagation Boolean indicating whether or not to attach more information
- * (corrections, sigmas, adjusted sigmas...) to the output.
- */
- void BundleObservation::bundleOutputString(std::ostream &fpOut, bool errorPropagation) {
-
- char buf[4096];
-
- QVector finalParameterValues;
- int nPositionCoefficients, nPointingCoefficients;
- bool useDefaultPosition, useDefaultPointing,useDefaultTwist;
-
- bundleOutputFetchData(finalParameterValues,
- nPositionCoefficients,nPointingCoefficients,
- useDefaultPosition,useDefaultPointing,useDefaultTwist);
-
- int nPositionParameters = 3 * nPositionCoefficients;
- int nPointingParameters = 3 * nPointingCoefficients;
- int nParameters = nPositionParameters + nPointingParameters;
-
- // for convenience, create vectors of parameters names and values in the correct sequence
- QStringList parameterNamesListX,parameterNamesListY,parameterNamesListZ,
- parameterNamesListRA,parameterNamesListDEC,parameterNamesListTWI,
- parameterNamesList;
- QStringList correctionUnitListX,correctionUnitListY,correctionUnitListZ,
- correctionUnitListRA,correctionUnitListDEC,correctionUnitListTWI,
- correctionUnitList;
-
- QString str("%1(%2) ");
- QString str2("%1(%2) ");
- QString strN("%1(%2)");
-
-
- if (nPositionCoefficients > 0) {
- for (int j = 0; j < nPositionCoefficients;j++) {
- if (j == 0) {
- parameterNamesListX.append(str.arg(" X ").arg("km"));
- parameterNamesListY.append(str.arg(" Y ").arg("km"));
- parameterNamesListZ.append(str.arg(" Z ").arg("km"));
- correctionUnitListX.append("m");
- correctionUnitListY.append("m");
- correctionUnitListZ.append("m");
- } //end inner-if
-
- else if (j==1) {
- parameterNamesListX.append( str2.arg(" ").arg("km/s") );
- parameterNamesListY.append( str2.arg(" ").arg("km/s") );
- parameterNamesListZ.append( str2.arg(" ").arg("km/s") );
- correctionUnitListX.append("m/s");
- correctionUnitListY.append("m/s");
- correctionUnitListZ.append("m/s");
- }
- else {
- QString str("%1(%2)");
- parameterNamesListX.append(strN.arg(" ").arg("km/s^"+toString(j) ) );
- parameterNamesListY.append(strN.arg(" ").arg("km/s^"+toString(j) ) );
- parameterNamesListZ.append(strN.arg(" ").arg("km/s^"+toString(j) ) );
- correctionUnitListX.append("m/s^"+toString(j));
- correctionUnitListY.append("m/s^"+toString(j));
- correctionUnitListZ.append("m/s^"+toString(j));
- }
- }//end for
- }//end outer-if
-
- if (nPointingCoefficients > 0) {
- for (int j = 0; j < nPointingCoefficients;j++) {
- if (j == 0) {
- parameterNamesListRA.append(str.arg(" RA ").arg("dd"));
- parameterNamesListDEC.append(str.arg("DEC ").arg("dd"));
- parameterNamesListTWI.append(str.arg("TWI ").arg("dd"));
- correctionUnitListRA.append("dd");
- correctionUnitListDEC.append("dd");
- correctionUnitListTWI.append("dd");
- } //end inner-if
-
- else if (j==1) {
- parameterNamesListRA.append( str2.arg(" ").arg("dd/s") );
- parameterNamesListDEC.append( str2.arg(" ").arg("dd/s") );
- parameterNamesListTWI.append( str2.arg(" ").arg("dd/s") );
- correctionUnitListRA.append("dd/s");
- correctionUnitListDEC.append("dd/s");
- correctionUnitListTWI.append("dd/s");
- }
- else {
- parameterNamesListRA.append(strN.arg(" ").arg("dd/s^"+toString(j) ) );
- parameterNamesListDEC.append(strN.arg(" ").arg("dd/s^"+toString(j) ) );
- parameterNamesListTWI.append(strN.arg(" ").arg("dd/s^"+toString(j) ) );
- correctionUnitListRA.append("dd/s^"+toString(j));
- correctionUnitListDEC.append("dd/s^"+toString(j));
- correctionUnitListTWI.append("dd/s^"+toString(j));
- }
- }//end for
- }// end outer-if
-
- //Put all of the parameter names together into one QStringList
- parameterNamesList.append(parameterNamesListX);
- parameterNamesList.append(parameterNamesListY);
- parameterNamesList.append(parameterNamesListZ);
- parameterNamesList.append(parameterNamesListRA);
- parameterNamesList.append(parameterNamesListDEC);
- parameterNamesList.append(parameterNamesListTWI);
-
- //Put all of the correction unit names together into one QStringList
- correctionUnitList.append(correctionUnitListX);
- correctionUnitList.append(correctionUnitListY);
- correctionUnitList.append(correctionUnitListZ);
- correctionUnitList.append(correctionUnitListDEC);
- correctionUnitList.append(correctionUnitListRA);
- correctionUnitList.append(correctionUnitListTWI);
-
- // Save the list of parameter names we've accumulated above
- m_parameterNamesList = parameterNamesList;
-
- // Set up default values when we are using default position
- QString sigma = "N/A";
- QString adjustedSigma = "N/A";
- double correction = 0.0;
-
- // position parameters
- for (int i = 0; i < nPositionParameters; i++) {
- // If not using the default position, we can correctly access sigmas and corrections
- // members
- if (!useDefaultPosition) {
- correction = m_corrections(i);
- adjustedSigma = QString::number(m_adjustedSigmas[i], 'f', 8);
- sigma = ( IsSpecial(m_aprioriSigmas[i]) ? "FREE" : toString(m_aprioriSigmas[i], 8) );
- }
-
- sprintf(buf,"%s",parameterNamesList.at(i).toStdString().c_str() );
- fpOut << buf;
- sprintf(buf,"%18.8lf ",finalParameterValues[i] - correction);
- fpOut << buf;
- sprintf(buf,"%20.8lf ",correction);
- fpOut << buf;
- sprintf(buf,"%23.8lf ",finalParameterValues[i]);
- fpOut << buf;
- sprintf(buf," ");
- fpOut << buf;
- sprintf(buf,"%6s",sigma.toStdString().c_str());
- fpOut << buf;
- sprintf(buf," ");
- fpOut << buf;
- if (errorPropagation) {
- sprintf(buf,"%s",adjustedSigma.toStdString().c_str());
- }
- else {
- sprintf(buf,"%s","N/A");
- }
- fpOut<= nParameters - nPointingCoefficients) && useDefaultTwist) {
- correction = 0.0;
- adjustedSigma = "N/A";
- sigma = "N/A";
- }
- else {
- correction = m_corrections(i - offset);
- adjustedSigma = QString::number(m_adjustedSigmas(i-offset) * RAD2DEG, 'f', 8);
- sigma = ( IsSpecial(m_aprioriSigmas[i - offset]) ? "FREE" :
- toString(m_aprioriSigmas[i-offset], 8) );
- }
- }
- // We are using default pointing, so provide default correction and sigma values to output
- else {
- correction = 0.0;
- adjustedSigma = "N/A";
- sigma = "N/A";
- }
-
- sprintf(buf,"%s",parameterNamesList.at(i).toStdString().c_str() );
- fpOut << buf;
- sprintf(buf,"%18.8lf ",(finalParameterValues[i]*RAD2DEG - correction*RAD2DEG));
- fpOut << buf;
- sprintf(buf,"%20.8lf ",(correction*RAD2DEG));
- fpOut << buf;
- sprintf(buf,"%23.8lf ",(finalParameterValues[i]*RAD2DEG));
- fpOut << buf;
- sprintf(buf," ");
- fpOut << buf;
- sprintf(buf,"%6s",sigma.toStdString().c_str());
- fpOut << buf;
- sprintf(buf," ");
- fpOut << buf;
- if (errorPropagation) {
- sprintf(buf,"%s",adjustedSigma.toStdString().c_str());
- }
- else {
- sprintf(buf,"%s","N/A");
- }
- fpOut< finalParameterValues;
- int nPositionCoefficients, nPointingCoefficients;
- bool useDefaultPosition, useDefaultPointing,useDefaultTwist;
-
- bundleOutputFetchData(finalParameterValues,
- nPositionCoefficients,nPointingCoefficients,
- useDefaultPosition,useDefaultPointing,useDefaultTwist);
-
- int nPositionParameters = 3 * nPositionCoefficients;
- int nPointingParameters = 3 * nPointingCoefficients;
- int nParameters = nPositionParameters + nPointingParameters;
-
- QString finalqStr = "";
-
- // Set up default values when we are using default position
- QString sigma = "N/A";
- QString adjustedSigma = "N/A";
- double correction = 0.0;
-
- // Position parameters
- for (int i = 0; i < nPositionParameters; i++) {
- if (!useDefaultPosition) {
- correction = m_corrections(i);
- adjustedSigma = QString::number(m_adjustedSigmas[i], 'f', 8);
- sigma = ( IsSpecial(m_aprioriSigmas[i]) ? "FREE" : toString(m_aprioriSigmas[i], 8) );
- }
- // Provide default values for position if not solving position
- else {
- correction = 0.0;
- adjustedSigma = "N/A";
- sigma = "N/A";
- }
-
- finalqStr += toString(finalParameterValues[i] - correction) + ",";
- finalqStr += toString(correction) + ",";
- finalqStr += toString(finalParameterValues[i]) + ",";
- finalqStr += sigma + ",";
- if (errorPropagation) {
- finalqStr += adjustedSigma + ",";
- }
- else {
- finalqStr += "N/A,";
- }
-
- }
-
- // If not solving position, we need to offset access to correction and sigma members by -3
- // (X,Y,Z) since m_corrections and m_*sigmas are populated according to which parameters are
- // solved
- int offset = 0;
- if (useDefaultPosition) {
- offset = 3;
- }
- // pointing parameters
- for (int i = nPositionParameters; i < nParameters; i++) {
- if (!useDefaultPointing) {
- // Use default values if solving camera but not solving for TWIST to prevent bad indexing
- // into m_corrections and m_*sigmas
- if ( (i >= nParameters - nPointingCoefficients) && useDefaultTwist) {
- correction = 0.0;
- adjustedSigma = "N/A";
- sigma = "N/A";
- }
- else {
- correction = m_corrections(i - offset);
- adjustedSigma = QString::number(m_adjustedSigmas(i-offset) * RAD2DEG, 'f', 8);
- sigma = ( IsSpecial(m_aprioriSigmas[i-offset]) ? "FREE" :
- toString(m_aprioriSigmas[i-offset], 8) );
- }
- }
- // Provide default values for pointing if not solving pointing
- else {
- correction = 0.0;
- adjustedSigma = "N/A";
- sigma = "N/A";
- }
-
- finalqStr += toString(finalParameterValues[i]*RAD2DEG - correction * RAD2DEG) + ",";
- finalqStr += toString(correction * RAD2DEG) + ",";
- finalqStr += toString(finalParameterValues[i]*RAD2DEG) + ",";
- finalqStr += sigma + ",";
- if (errorPropagation) {
- finalqStr += adjustedSigma + ",";
- }
- else {
- finalqStr += "N/A,";
- }
-
- }
-
- return finalqStr;
- }
-
-
- /**
- * Access to parameters for CorrelationMatrix to use.
- *
- * @return @b QStringList Returns a QStringList of the names of the parameters
- */
- QStringList BundleObservation::parameterList() {
- return m_parameterNamesList;
- }
-
/**
* Access to image names for CorrelationMatrix to use.
diff --git a/isis/src/control/objs/BundleUtilities/BundleObservation.h b/isis/src/control/objs/BundleUtilities/BundleObservation.h
index 1e0faae6d475ef6c5fcf8e080b1a47bb9c882002..b3206a4c6a05bfaeead8f6e31a07f1bd2b36cfaf 100644
--- a/isis/src/control/objs/BundleUtilities/BundleObservation.h
+++ b/isis/src/control/objs/BundleUtilities/BundleObservation.h
@@ -14,72 +14,23 @@ find files of those names at the top level of this repository. **/
#include "BundleImage.h"
#include "BundleObservationSolveSettings.h"
+#include "BundleSettings.h"
#include "BundleTargetBody.h"
#include "LinearAlgebra.h"
+#include "BundleMeasure.h"
+#include "SurfacePoint.h"
namespace Isis {
- class BundleObservationSolveSettings;
- class SpicePosition;
- class SpiceRotation;
/**
- * @brief Class for bundle observations
- *
- * This class is used for creating a bundle observation. Contained BundleImages are stored as
- * shared pointers, so they will be automatically deleted when all shared pointers are deleted.
- *
- * @ingroup ControlNetworks
- *
- * @author 2014-07-09 Ken Edmundson
- *
- * @internal
- * @history 2014-07-09 Ken Edmundson - Original version.
- * @history 2014-07-16 Jeannie Backer - Replaced QVectors with QLists.
- * @history 2014-07-17 Kimberly Oyama - Added member variables and accessors for the images and
- * parameters in this observation. They will be used for the correlation
- * matrix.
- * @history 2014-07-23 Jeannie Backer - Replaced QVectors with QLists.
- * @history 2015-02-20 Jeannie Backer - Brought closer to Isis coding standards.
- * @history 2016-08-03 Jesse Mapel - Changed contained member type to a QSharedPointer.
- * Also changed m_solveSettings to a QSharedPointer. Fixes #4150.
- * @history 2016-08-03 Ian Humphrey - Updated documentation and coding standards. Fixes #4078.
- * @history 2016-08-10 Jeannie Backer - Replaced boost vector with Isis::LinearAlgebra::Vector.
- * References #4163.
- * @history 2016-08-15 Jesse Mapel - Added a map between cube serial number and contained
- * bundle image. References #4159.
- * @history 2016-08-23 Ian Humphrey - The applyParameterCorrections() method now throws the
- * last exception. Fixes #4153.
- * @history 2016-10-06 Tyler Wilson - Modified the function formatBundleOutputString so
- * that it can be used by BundleSolutionInfo::outputCSVImages()
- * function. Fixes #4314.
- * @history 2016-10-26 Ian Humphrey - Modified formatBundleOutputString() to provided default
- * values for all solve parameters, whether they are being solved for
- * or not. Fixes #4464.
- * @history 2016-10-27 Tyler Wilson - Modified formatBundleOutputString to change N/A to FREE
- * in the output under POINTS DETAIL when no lat/lon sigmas were entered.
- * Fixes #4317.
- * @history 2016-11-14 Ken Edmundson - Modified the following...
- * -changed adjustedSigma from 0.0 to N/A if error propagation is off
- * when writing bundleout.txt OR images.csv.
- * -changed sigma default from -1.0 to N/A for position and pointing
- * parameters when writing images.csv.
- * @history 2019-05-14 Tyler Wilson - Added the bundleOutputString(std::ofstream &fpOut,
- * bool errorPropagation) function which is called by
- * BundleSolutionInfo::outputText(). This function is a refactor of
- * the formatBundleOutputString and uses the traditional C function
- * sprintf instead of QString arg chaining because it's easier to
- * make the output columns align nicely. Also, it maintains
- * consistency with text output in BundleSolutionInfo.
- * @history 2019-06-03 Tyler Wilson - Deleted the formatBundleOutputString and added the
- * functions bundleOutputCSV/bundleOutputFetchData. Combined
- * with bundleOutputString these three functions will fulfill
- * the same functional role formerly occuped by
- * formatBundleOutputString but with reduced code duplication.
- * @history 2019-08-15 Adam Paquette - Readded the formatBundleOutputString function
- * and added deprication warnings to formatBundleOutputString.
- * @history 2019-09-10 Adam Paquette - Changed how bundleOutputString formats the text
- * that is written to the bundleout.txt file.
+ * @brief Abstract base class for an observation in bundle adjustment.
*
+ * This class is the abstract base class that represents an observation in bundle
+ * adjustment. It handles operations related to the images in the observation,
+ * parameter corrections, and parameter uncertainties. It defines the interface
+ * for choosing observation parameters via BundleObservationSolveSettings. The
+ * partial computation apis required by the bundle adjustment are also defined
+ * but must be implemented by sub-classes.
*/
class BundleObservation : public QVector {
@@ -95,89 +46,62 @@ namespace Isis {
BundleObservation(const BundleObservation &src);
// destructor
- ~BundleObservation();
+ virtual ~BundleObservation();
// equals operator
- BundleObservation &operator=(const BundleObservation &src);
+ virtual BundleObservation &operator=(const BundleObservation &src);
// copy method
+
void copy(const BundleObservation &src);
- void append(const BundleImageQsp &value);
+ virtual bool setSolveSettings(BundleObservationSolveSettings solveSettings) = 0;
- BundleImageQsp imageByCubeSerialNumber(QString cubeSerialNumber);
+ virtual void append(const BundleImageQsp &value);
- bool setSolveSettings(BundleObservationSolveSettings solveSettings);
+ BundleImageQsp imageByCubeSerialNumber(QString cubeSerialNumber);
void setIndex(int n);
int index();
- int numberPositionParameters();
- int numberPointingParameters();
- int numberParameters();
-
QString instrumentId();
- SpiceRotation *spiceRotation();
- SpicePosition *spicePosition();
+ virtual LinearAlgebra::Vector ¶meterWeights();
+ virtual LinearAlgebra::Vector ¶meterCorrections();
+ virtual LinearAlgebra::Vector &aprioriSigmas();
+ virtual LinearAlgebra::Vector &adjustedSigmas();
- LinearAlgebra::Vector ¶meterWeights();
- LinearAlgebra::Vector ¶meterCorrections();
- LinearAlgebra::Vector &aprioriSigmas();
- LinearAlgebra::Vector &adjustedSigmas();
- const BundleObservationSolveSettingsQsp solveSettings();
+ virtual const BundleObservationSolveSettingsQsp solveSettings() = 0;
+ virtual int numberParameters() = 0;
+ virtual bool applyParameterCorrections(LinearAlgebra::Vector corrections) = 0;
- bool applyParameterCorrections(LinearAlgebra::Vector corrections);
- bool initializeExteriorOrientation();
- void initializeBodyRotation();
- void updateBodyRotation();
+ virtual void bundleOutputString(std::ostream &fpOut,bool errorPropagation) = 0;
+ virtual QString bundleOutputCSV(bool errorPropagation) = 0;
- void bundleOutputFetchData(QVector &finalParameterValues,
- int &nPositionCoefficients, int &nPointingCoefficients,
- bool &useDefaultPosition, bool &useDefaultPointing,
- bool &useDefaultTwist);
- void bundleOutputString(std::ostream &fpOut,bool errorPropagation);
- QString bundleOutputCSV(bool errorPropagation);
+ virtual QStringList parameterList() = 0;
+ virtual QStringList imageNames();
- QString formatBundleOutputString(bool errorPropagation, bool imageCSV=false);
- QStringList parameterList();
- QStringList imageNames();
-
- private:
- bool initParameterWeights();
-
- private:
- QString m_observationNumber; /**< This is typically equivalent to serial number
- except in the case of "observation mode" (e.g.
- Lunar Orbiter) where for each image in the
- observation, the observation number is the serial number
- augmented with an additional integer. **/
-
- int m_index; //!< Index of this observation.
+ virtual bool computeTargetPartials(LinearAlgebra::Matrix &coeffTarget, BundleMeasure &measure,
+ BundleSettingsQsp &bundleSettings, BundleTargetBodyQsp &bundleTargetBody) = 0;
+ virtual bool computeImagePartials(LinearAlgebra::Matrix &coeffImage, BundleMeasure &measure) = 0;
+ virtual bool computePoint3DPartials(LinearAlgebra::Matrix &coeffPoint3D, BundleMeasure &measure, SurfacePoint::CoordinateType coordType = SurfacePoint::Rectangular) = 0;
+ virtual bool computeRHSPartials(LinearAlgebra::Vector &coeffRHS, BundleMeasure &measure) = 0;
+ virtual double computeObservationValue(BundleMeasure &measure, double deltaVal) = 0;
+ protected:
+ QString m_observationNumber; /**< The shared portion of the serial numbers of
+ all images in the observation. **/
+ int m_index; //!< Index of this observation in the set of observations.
//! Map between cube serial number and BundleImage pointers.
QMap m_cubeSerialNumberToBundleImageMap;
-
QStringList m_serialNumbers; //!< List of all cube serial numbers in observation.
- QStringList m_parameterNamesList; //!< List of all cube parameters.
QStringList m_imageNames; //!< List of all cube names.
+ QString m_instrumentId; //!< Spacecraft instrument id.
- QString m_instrumentId; //!< Spacecraft instrument id.
-
- BundleObservationSolveSettingsQsp m_solveSettings; //!< Solve settings for this observation.
-
- SpiceRotation *m_instrumentRotation; //!< Instrument spice rotation (in primary image).
- SpicePosition *m_instrumentPosition; //!< Instrument spice position (in primary image).
-// SpiceRotation *m_bodyRotation; //!< Instrument body rotation (in primary image).
-
- BundleTargetBodyQsp m_bundleTargetBody; //!< QShared pointer to BundleTargetBody.
-
- // TODO??? change these to LinearAlgebra vectors...
LinearAlgebra::Vector m_weights; //!< Parameter weights.
//! Cumulative parameter correction vector.
LinearAlgebra::Vector m_corrections;
- //LinearAlgebra::Vector m_solution; //!< parameter solution vector.
//! A posteriori (adjusted) parameter sigmas.
LinearAlgebra::Vector m_aprioriSigmas;
//! A posteriori (adjusted) parameter sigmas.
diff --git a/isis/src/control/objs/BundleUtilities/BundleObservationSolveSettings.cpp b/isis/src/control/objs/BundleUtilities/BundleObservationSolveSettings.cpp
index 0d728bc9f7ae86c02e0eea9259d8b637d997c3fb..63dc77cc50fcd1bafeed46d7b20ab699677d0f27 100644
--- a/isis/src/control/objs/BundleUtilities/BundleObservationSolveSettings.cpp
+++ b/isis/src/control/objs/BundleUtilities/BundleObservationSolveSettings.cpp
@@ -58,7 +58,7 @@ namespace Isis {
BundleObservationSolveSettings::BundleObservationSolveSettings(const PvlGroup &scParameterGroup) {
initialize();
- // group name must be instrument id
+ // group name must be instrument id
m_instrumentId = (QString)scParameterGroup.nameKeyword();
// If CKDEGREE is not specified, then a default of 2 is used
@@ -66,7 +66,7 @@ namespace Isis {
m_ckDegree = (int)(scParameterGroup.findKeyword("CKDEGREE"));
}
- // If CKSOLVEDEGREE is not specified, then a default of 2 is used -------jwb----- why ??? why not match camsolve option ???
+ // If CKSOLVEDEGREE is not specified, then a default of 2 is used
if (scParameterGroup.hasKeyword("CKSOLVEDEGREE")) {
m_ckSolveDegree = (int) (scParameterGroup.findKeyword("CKSOLVEDEGREE"));
}
@@ -237,28 +237,25 @@ namespace Isis {
}
}
}
+
+ // CSM settings
+ if (scParameterGroup.hasKeyword("CSMSOLVESET")) {
+ setCSMSolveSet(stringToCSMSolveSet(scParameterGroup.findKeyword("CSMSOLVESET")));
+ }
+ else if (scParameterGroup.hasKeyword("CSMSOLVETYPE")) {
+ setCSMSolveType(stringToCSMSolveType(scParameterGroup.findKeyword("CSMSOLVETYPE")));
+ }
+ else if (scParameterGroup.hasKeyword("CSMSOLVELIST")) {
+ PvlKeyword csmSolveListKey = scParameterGroup.findKeyword("CSMSOLVELIST");
+ QStringList csmSolveList;
+ for (int i = 0; i < csmSolveListKey.size(); i++) {
+ csmSolveList.append(csmSolveListKey[i]);
+ }
+ setCSMSolveParameterList(csmSolveList);
+ }
}
-// BundleObservationSolveSettings::BundleObservationSolveSettings(const BundleObservationSolveSettings &other)
-// : m_id(new QUuid(other.m_id->toString())),
-// m_instrumentId(other.m_instrumentId),
-// m_instrumentPointingSolveOption(other.m_instrumentPointingSolveOption),
-// m_numberCamAngleCoefSolved(other.m_numberCamAngleCoefSolved),
-// m_ckDegree(other.m_ckDegree),
-// m_ckSolveDegree(other.m_ckSolveDegree),
-// m_solveTwist(other.m_solveTwist),
-// m_solvePointingPolynomialOverExisting(other.m_solvePointingPolynomialOverExisting),
-// m_anglesAprioriSigma(other.m_anglesAprioriSigma),
-// m_pointingInterpolationType(other.m_pointingInterpolationType),
-// m_instrumentPositionSolveOption(other.m_instrumentPositionSolveOption),
-// m_numberCamPosCoefSolved(other.m_numberCamPosCoefSolved),
-// m_spkDegree(other.m_spkDegree),
-// m_spkSolveDegree(other.m_spkSolveDegree),
-// m_solvePositionOverHermiteSpline(other.m_solvePositionOverHermiteSpline),
-// m_positionAprioriSigma(other.m_positionAprioriSigma),
-// m_positionInterpolationType(other.m_positionInterpolationType) {
-// }
/**
* Constructs a BundleObservationSolveSettings from another one.
*
@@ -272,6 +269,10 @@ namespace Isis {
// or intit all variables in all constructors
m_instrumentId = other.m_instrumentId;
+ m_csmSolveOption = other.m_csmSolveOption;
+ m_csmSolveSet = other.m_csmSolveSet;
+ m_csmSolveType = other.m_csmSolveType;
+ m_csmSolveList = other.m_csmSolveList;
m_instrumentPointingSolveOption = other.m_instrumentPointingSolveOption;
m_observationNumbers = other.m_observationNumbers;
m_numberCamAngleCoefSolved = other.m_numberCamAngleCoefSolved;
@@ -320,6 +321,12 @@ namespace Isis {
m_instrumentId = other.m_instrumentId;
m_observationNumbers = other.m_observationNumbers;
+ // CSM related
+ m_csmSolveOption = other.m_csmSolveOption;
+ m_csmSolveSet = other.m_csmSolveSet;
+ m_csmSolveType = other.m_csmSolveType;
+ m_csmSolveList = other.m_csmSolveList;
+
// pointing related
m_instrumentPointingSolveOption = other.m_instrumentPointingSolveOption;
m_numberCamAngleCoefSolved = other.m_numberCamAngleCoefSolved;
@@ -355,6 +362,12 @@ namespace Isis {
m_instrumentId = "";
+ // CSM solve options
+ m_csmSolveOption = BundleObservationSolveSettings::NoCSMParameters;
+ m_csmSolveSet = csm::param::ADJUSTABLE;
+ m_csmSolveType = csm::param::REAL;
+ m_csmSolveList = QStringList();
+
// Camera Pointing Options
// Defaults:
// m_instrumentPointingSolveOption = AnglesOnly;
@@ -441,6 +454,249 @@ namespace Isis {
}
+ // =============================================================================================//
+ // ======================== CSM Options ========================================================//
+ // =============================================================================================//
+
+
+ /**
+ * Convert a string to a CSM solve option enumeration value.
+ *
+ * @param option The option as a string
+ *
+ * @return @b CSMSolveOption The option's enumeration value
+ */
+ BundleObservationSolveSettings::CSMSolveOption
+ BundleObservationSolveSettings::stringToCSMSolveOption(QString option) {
+ if (option.compare("NoCSMParameters", Qt::CaseInsensitive) == 0) {
+ return BundleObservationSolveSettings::NoCSMParameters;
+ }
+ else if (option.compare("Set", Qt::CaseInsensitive) == 0) {
+ return BundleObservationSolveSettings::Set;
+ }
+ else if (option.compare("Type", Qt::CaseInsensitive) == 0) {
+ return BundleObservationSolveSettings::Type;
+ }
+ else if (option.compare("List", Qt::CaseInsensitive) == 0) {
+ return BundleObservationSolveSettings::List;
+ }
+ else {
+ throw IException(IException::Unknown,
+ "Unknown bundle CSM solve option " + option + ".",
+ _FILEINFO_);
+ }
+ }
+
+
+ /**
+ * Convert a CSM solve option enumeration value to a string.
+ *
+ * @param option The option's enumeration value
+ *
+ * @return @b QString The option as a string
+ */
+ QString BundleObservationSolveSettings::csmSolveOptionToString(CSMSolveOption option) {
+ if (option == BundleObservationSolveSettings::NoCSMParameters) {
+ return "NoCSMParameters";
+ }
+ else if (option == BundleObservationSolveSettings::Set) {
+ return "Set";
+ }
+ else if (option == BundleObservationSolveSettings::Type) {
+ return "Type";
+ }
+ else if (option == BundleObservationSolveSettings::List) {
+ return "List";
+ }
+ else {
+ throw IException(IException::Programmer,
+ "Unknown CSM solve option enum [" + toString(option) + "].",
+ _FILEINFO_);
+ }
+ }
+
+
+ /**
+ * Convert a string to its CSM parameter set enumeration value.
+ *
+ * @param set The set name
+ *
+ * @return @b csm::param::Set The set's enumeration value
+ */
+ csm::param::Set BundleObservationSolveSettings::stringToCSMSolveSet(QString set) {
+ if (set.compare("VALID", Qt::CaseInsensitive) == 0) {
+ return csm::param::VALID;
+ }
+ else if (set.compare("ADJUSTABLE", Qt::CaseInsensitive) == 0) {
+ return csm::param::ADJUSTABLE;
+ }
+ else if (set.compare("NON_ADJUSTABLE", Qt::CaseInsensitive) == 0) {
+ return csm::param::NON_ADJUSTABLE;
+ }
+ else {
+ throw IException(IException::Unknown,
+ "Unknown bundle CSM parameter set " + set + ".",
+ _FILEINFO_);
+ }
+ }
+
+
+ /**
+ * Convert a CSM parameter set enumeration value to a string.
+ *
+ * @param set The set's enumeration value
+ *
+ * @return @b QString The set's name
+ */
+ QString BundleObservationSolveSettings::csmSolveSetToString(csm::param::Set set) {
+ if (set == csm::param::VALID) {
+ return "VALID";
+ }
+ else if (set == csm::param::ADJUSTABLE) {
+ return "ADJUSTABLE";
+ }
+ else if (set == csm::param::NON_ADJUSTABLE) {
+ return "NON_ADJUSTABLE";
+ }
+ else {
+ throw IException(IException::Programmer,
+ "Unknown CSM parameter set enum [" + toString(set) + "].",
+ _FILEINFO_);
+ }
+ }
+
+
+ /**
+ * Convert a string to its CSM parameter type enumeration value.
+ *
+ * @param type The type name
+ *
+ * @return @b csm::param::Type The types's enumeration value
+ */
+ csm::param::Type BundleObservationSolveSettings::stringToCSMSolveType(QString type) {
+ if (type.compare("NONE", Qt::CaseInsensitive) == 0) {
+ return csm::param::NONE;
+ }
+ else if (type.compare("FICTITIOUS", Qt::CaseInsensitive) == 0) {
+ return csm::param::FICTITIOUS;
+ }
+ else if (type.compare("REAL", Qt::CaseInsensitive) == 0) {
+ return csm::param::REAL;
+ }
+ else if (type.compare("FIXED", Qt::CaseInsensitive) == 0) {
+ return csm::param::FIXED;
+ }
+ else {
+ throw IException(IException::Unknown,
+ "Unknown bundle CSM parameter type " + type + ".",
+ _FILEINFO_);
+ }
+ }
+
+
+ /**
+ * Convert a CSM parameter type enumeration value to a string.
+ *
+ * @param type The type's enumeration value
+ *
+ * @return @b QString The type's name
+ */
+ QString BundleObservationSolveSettings::csmSolveTypeToString(csm::param::Type type) {
+ if (type == csm::param::NONE) {
+ return "NONE";
+ }
+ else if (type == csm::param::FICTITIOUS) {
+ return "FICTITIOUS";
+ }
+ else if (type == csm::param::REAL) {
+ return "REAL";
+ }
+ else if (type == csm::param::FIXED) {
+ return "FIXED";
+ }
+ else {
+ throw IException(IException::Programmer,
+ "Unknown CSM parameter type enum [" + toString(type) + "].",
+ _FILEINFO_);
+ }
+ }
+
+
+ /**
+ * Set the set of CSM parameters to solve for. See the CSM API documentation
+ * for what the different set values mean.
+ *
+ * @param set The set to solve for
+ */
+ void BundleObservationSolveSettings::setCSMSolveSet(csm::param::Set set) {
+ m_csmSolveOption = BundleObservationSolveSettings::Set;
+ m_csmSolveSet = set;
+ }
+
+
+ /**
+ * Set the type of CSM parameters to solve for.
+ *
+ * @param type The parameter type to solve for
+ */
+ void BundleObservationSolveSettings::setCSMSolveType(csm::param::Type type) {
+ m_csmSolveOption = BundleObservationSolveSettings::Type;
+ m_csmSolveType = type;
+ }
+
+
+ /**
+ * Set an explicit list of CSM parameters to solve for.
+ *
+ * @param list The names of the parameters to solve for
+ */
+ void BundleObservationSolveSettings::setCSMSolveParameterList(QStringList list) {
+ m_csmSolveOption = BundleObservationSolveSettings::List;
+ m_csmSolveList = list;
+ }
+
+
+ /**
+ * Get how the CSM parameters to solve for are specified for this observation.
+ *
+ * @return @b CSMSolveOption
+ */
+ BundleObservationSolveSettings::CSMSolveOption
+ BundleObservationSolveSettings::csmSolveOption() const {
+ return m_csmSolveOption;
+ }
+
+
+ /**
+ * Get the set of CSM parameters to solve for
+ *
+ * @return @b csm::param::Set The CSM parameter set to solve for
+ */
+ csm::param::Set BundleObservationSolveSettings::csmParameterSet() const {
+ return m_csmSolveSet;
+ }
+
+
+ /**
+ * Get the type of CSM parameters to solve for
+ *
+ * @return @b csm::param::Type The CSM parameter type to solve for
+ */
+ csm::param::Type BundleObservationSolveSettings::csmParameterType() const {
+ return m_csmSolveType;
+ }
+
+
+ /**
+ * Get the list of CSM parameters to solve for
+ *
+ * @return @b QStringList The names of the CSM parameters to solve for
+ */
+ QStringList BundleObservationSolveSettings::csmParameterList() const {
+ return m_csmSolveList;
+ }
+
+
// =============================================================================================//
// ======================== Camera Pointing Options ============================================//
// =============================================================================================//
diff --git a/isis/src/control/objs/BundleUtilities/BundleObservationSolveSettings.h b/isis/src/control/objs/BundleUtilities/BundleObservationSolveSettings.h
index 54cd5573bc53ac29b82bfec784d0a5d1ba7e0881..3cddd1489a7ad02fe9ebd27e769f6946bb3962f5 100644
--- a/isis/src/control/objs/BundleUtilities/BundleObservationSolveSettings.h
+++ b/isis/src/control/objs/BundleUtilities/BundleObservationSolveSettings.h
@@ -12,6 +12,9 @@ find files of those names at the top level of this repository. **/
#include
#include
#include
+#include
+
+#include
#include "SpicePosition.h"
#include "SpiceRotation.h"
@@ -97,7 +100,27 @@ class BundleObservationSolveSettings {
bool removeObservationNumber(QString observationNumber);
QSet observationNumbers() const;
+ //! Options for how to solve for CSM parameters.
+ enum CSMSolveOption {
+ NoCSMParameters = 0, /**< Do not solve for CSM parameters.*/
+ Set = 1, /**< Solve for all CSM parameters belonging to a specific set.*/
+ Type = 2, /**< Solve for all CSM parameters of a specific type.*/
+ List = 3 /**< Solve for an explicit list of CSM parameters.*/
+ };
+ static CSMSolveOption stringToCSMSolveOption(QString option);
+ static QString csmSolveOptionToString(CSMSolveOption option);
+ static csm::param::Set stringToCSMSolveSet(QString set);
+ static QString csmSolveSetToString(csm::param::Set set);
+ static csm::param::Type stringToCSMSolveType(QString type);
+ static QString csmSolveTypeToString(csm::param::Type type);
+ void setCSMSolveSet(csm::param::Set set);
+ void setCSMSolveType(csm::param::Type type);
+ void setCSMSolveParameterList(QStringList list);
+ CSMSolveOption csmSolveOption() const;
+ csm::param::Set csmParameterSet() const;
+ csm::param::Type csmParameterType() const;
+ QStringList csmParameterList() const;
//! Options for how to solve for instrument pointing.
enum InstrumentPointingSolveOption {
@@ -203,6 +226,15 @@ class BundleObservationSolveSettings {
QString m_instrumentId; //!< The spacecraft instrument id for this observation.
QSet m_observationNumbers; //!< Associated observation numbers for these settings.
+ // CSM related parameters
+ CSMSolveOption m_csmSolveOption; //!< How the CSM solution is specified
+ csm::param::Set m_csmSolveSet; /**< The CSM parameter set to solve for. Only valid
+ if the solve option is Set.*/
+ csm::param::Type m_csmSolveType; /**< The CSM parameter type to solve for. Only valid
+ if the solve option is Type.*/
+ QStringList m_csmSolveList; /**< The names of the CSM parameters to solve for. Only
+ valid if the solve option is List.*/
+
// pointing related parameters
//! Option for how to solve for instrument pointing.
InstrumentPointingSolveOption m_instrumentPointingSolveOption;
diff --git a/isis/src/control/objs/BundleUtilities/BundleObservationVector.cpp b/isis/src/control/objs/BundleUtilities/BundleObservationVector.cpp
index 697d8e2009290f3d1226a7f674f21ad42d96b679..290260f480030bffa0a0beb00c28ad01d5edd097 100644
--- a/isis/src/control/objs/BundleUtilities/BundleObservationVector.cpp
+++ b/isis/src/control/objs/BundleUtilities/BundleObservationVector.cpp
@@ -8,9 +8,14 @@ find files of those names at the top level of this repository. **/
#include "BundleObservationVector.h"
+#include
+
#include
#include "BundleObservation.h"
+#include "IsisBundleObservation.h"
+#include "Camera.h"
+#include "CsmBundleObservation.h"
#include "IException.h"
namespace Isis {
@@ -33,6 +38,7 @@ namespace Isis {
:QVector(src) {
m_observationNumberToObservationMap = src.m_observationNumberToObservationMap;
m_imageSerialToObservationMap = src.m_imageSerialToObservationMap;
+ m_instIdToObservationMap = src.m_instIdToObservationMap;
}
@@ -60,6 +66,7 @@ namespace Isis {
QVector::operator=(src);
m_observationNumberToObservationMap = src.m_observationNumberToObservationMap;
m_imageSerialToObservationMap = src.m_imageSerialToObservationMap;
+ m_instIdToObservationMap = src.m_instIdToObservationMap;
}
return *this;
}
@@ -92,6 +99,7 @@ namespace Isis {
QString observationNumber,
QString instrumentId,
BundleSettingsQsp bundleSettings) {
+
BundleObservationQsp bundleObservation;
bool addToExisting = false;
@@ -110,17 +118,28 @@ namespace Isis {
bundleImage->setParentObservation(bundleObservation);
// update observation number to observation ptr map
- m_observationNumberToObservationMap.insertMulti(observationNumber,bundleObservation);
+ m_observationNumberToObservationMap.insertMulti(observationNumber, bundleObservation);
// update image serial number to observation ptr map
- m_imageSerialToObservationMap.insertMulti(bundleImage->serialNumber(),bundleObservation);
+ m_imageSerialToObservationMap.insertMulti(bundleImage->serialNumber(), bundleObservation);
}
else {
// create new BundleObservation and append to this vector
- bundleObservation = BundleObservationQsp(new BundleObservation(bundleImage,
- observationNumber,
- instrumentId,
- bundleSettings->bundleTargetBody()));
+
+ bool isIsisObservation = bundleImage->camera()->GetCameraType() != Camera::Csm;
+
+ if (isIsisObservation) {
+ bundleObservation.reset(new IsisBundleObservation(bundleImage,
+ observationNumber,
+ instrumentId,
+ bundleSettings->bundleTargetBody()));
+ }
+ else {
+ bundleObservation.reset(new CsmBundleObservation(bundleImage,
+ observationNumber,
+ instrumentId,
+ bundleSettings->bundleTargetBody()));
+ }
if (!bundleObservation) {
QString message = "Unable to allocate new BundleObservation ";
@@ -128,8 +147,6 @@ namespace Isis {
throw IException(IException::Programmer, message, _FILEINFO_);
}
- bundleImage->setParentObservation(bundleObservation);
-
// Find the bundle observation solve settings for this new observation
BundleObservationSolveSettings solveSettings;
// When there is only one bundle observation solve setting, use it for all observations
@@ -146,50 +163,35 @@ namespace Isis {
bundleObservation->setIndex(size());
+ bundleImage->setParentObservation(bundleObservation);
+
append(bundleObservation);
+ if (isIsisObservation) {
+ QSharedPointer isisObs = qSharedPointerDynamicCast(bundleObservation);
+ isisObs->initializeExteriorOrientation();
+ if (bundleSettings->solveTargetBody()) {
+ isisObs->initializeBodyRotation();
+ }
+ }
+
// update observation number to observation ptr map
m_observationNumberToObservationMap.insertMulti(observationNumber, bundleObservation);
// update image serial number to observation ptr map
m_imageSerialToObservationMap.insertMulti(bundleImage->serialNumber(), bundleObservation);
- }
-
- return bundleObservation;
- }
-
-
- /**
- * Accesses the number of position parameters for the contained BundleObservations.
- *
- * @return @b int Returns the total number of position parameters for the BundleObservations
- */
- int BundleObservationVector::numberPositionParameters() {
- int positionParameters = 0;
- for (int i = 0; i < size(); i++) {
- BundleObservationQsp observation = at(i);
- positionParameters += observation->numberPositionParameters();
- }
-
- return positionParameters;
- }
-
-
- /**
- * Accesses the number of pointing parameters for the contained BundleObservations.
- *
- * @return @b int Returns the total number of pointing parameters for the BundleObservations
- */
- int BundleObservationVector::numberPointingParameters() {
- int pointingParameters = 0;
+ // update instrument ID to observation ptr map
+ // separate held observations out into their own entry
+ if (bundleObservation->numberParameters() == 0) {
+ m_instIdToObservationMap.insertMulti("held", bundleObservation);
+ }
+ else {
+ m_instIdToObservationMap.insertMulti(instrumentId, bundleObservation);
+ }
- for (int i = 0; i < size(); i++) {
- BundleObservationQsp observation = at(i);
- pointingParameters += observation->numberPointingParameters();
}
-
- return pointingParameters;
+ return bundleObservation;
}
@@ -200,7 +202,12 @@ namespace Isis {
* @return @b int Returns the total number of parameters for the contained BundleObservations
*/
int BundleObservationVector::numberParameters() {
- return numberPositionParameters() + numberPointingParameters();
+ int numParameters = 0;
+
+ for (int i = 0; i < size(); i++) {
+ numParameters += at(i)->numberParameters();
+ }
+ return numParameters;
}
@@ -226,33 +233,21 @@ namespace Isis {
/**
- * Initializes the exterior orientations for the contained BundleObservations.
- *
- * @return @b bool Returns true upon successful initialization
+ * Get a list of all instrument IDs that there are observations for
*/
- bool BundleObservationVector::initializeExteriorOrientation() {
- int nObservations = size();
- for (int i = 0; i < nObservations; i++) {
- BundleObservationQsp observation = at(i);
- observation->initializeExteriorOrientation();
- }
-
- return true;
+ QList BundleObservationVector::instrumentIds() const {
+ return m_instIdToObservationMap.uniqueKeys();
}
/**
- * Initializes the body rotations for the contained BundleObservations.
- *
- * @return @b bool Returns true upon successful initialization
+ * Get all of the observations with a specific instrument ID
*/
- bool BundleObservationVector::initializeBodyRotation() {
- int nObservations = size();
- for (int i = 0; i < nObservations; i++) {
- BundleObservationQsp observation = at(i);
- observation->initializeBodyRotation();
- }
-
- return true;
+ QList BundleObservationVector::
+ observationsByInstId(QString instrumentId) const {
+ QList list = m_instIdToObservationMap.values(instrumentId);
+ // multimap returns them in reverse order they were put in, so invert them to preserve order
+ std::reverse(std::begin(list), std::end(list));
+ return list;
}
}
diff --git a/isis/src/control/objs/BundleUtilities/BundleObservationVector.h b/isis/src/control/objs/BundleUtilities/BundleObservationVector.h
index b3b6b10a2683af670b5ee69610ae7c30459961c5..2cb60ef332e12c92ccaf8514cdc2ef5a7413f87c 100644
--- a/isis/src/control/objs/BundleUtilities/BundleObservationVector.h
+++ b/isis/src/control/objs/BundleUtilities/BundleObservationVector.h
@@ -9,13 +9,17 @@ find files of those names at the top level of this repository. **/
/* SPDX-License-Identifier: CC0-1.0 */
+#include
#include
+#include
#include
#include
#include
#include "BundleImage.h"
#include "BundleObservation.h"
+#include "IsisBundleObservation.h"
+#include "CsmBundleObservation.h"
#include "BundleSettings.h"
namespace Isis {
@@ -61,20 +65,20 @@ namespace Isis {
QString instrumentId,
BundleSettingsQsp bundleSettings);
- int numberPositionParameters();
- int numberPointingParameters();
int numberParameters();
BundleObservationQsp observationByCubeSerialNumber(QString cubeSerialNumber);
- bool initializeExteriorOrientation();
- bool initializeBodyRotation();
+ QList instrumentIds() const;
+ QList observationsByInstId(QString instrumentId) const;
private:
//! Map between observation number and pointer to observation.
QMap m_observationNumberToObservationMap;
//! Map between image serial number and pointer to observation.
QMap m_imageSerialToObservationMap;
+ //! Map between instrument ID and pointer to observation.
+ QMultiMap m_instIdToObservationMap;
};
}
diff --git a/isis/src/control/objs/BundleUtilities/BundleUtilities.truth b/isis/src/control/objs/BundleUtilities/BundleUtilities.truth
index fd0c4497afa7bfa9db233a17c41548f447bf695d..082692d99d269943924ae8dd44867be221456047 100644
--- a/isis/src/control/objs/BundleUtilities/BundleUtilities.truth
+++ b/isis/src/control/objs/BundleUtilities/BundleUtilities.truth
@@ -333,9 +333,9 @@ file name = "TestImageFileName"
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
-Testing BundleObservation...
-Constructing empty BundleObservation object...
-Constructing BundleObservation object from BundleImage...
+Testing IsisBundleObservation...
+Constructing empty IsisBundleObservation object...
+Constructing IsisBundleObservation object from BundleImage...
Testing assignment operator to set this equal to itself...
Testing assignment operator to create a new object...
Testing copy constructor...
@@ -501,9 +501,7 @@ TWI (dd) 0.00000000 0.00000000 0.00000000
index = "1"
instrument id = "InstrumentId2"
number parameters = "3"
-number position param = "0"
-number pointing param = "3"
-parameter list: ()
+parameter list: ("X", "Y", "Z", "RA", "DEC", "TWIST")
image names: ()
parameter weights : 0.0 0.0 0.0
parameter corrections : 0.0 0.0 0.0
@@ -521,7 +519,7 @@ TWI (dd) 0.00000000 0.00000000 0.00000000
0.0,0.0,0.0,N/A,N/A,0.0,0.0,0.0,N/A,N/A,0.0,0.0,0.0,N/A,N/A,0.0,0.0,0.0,FREE,0.00000000,0.0,0.0,0.0,FREE,0.00000000,0.0,0.0,0.0,FREE,0.00000000,
init exterior orientiation successful? "Yes"
apply param corrections successful?
-**ERROR** Unable to apply parameter corrections to BundleObservation.
+**ERROR** Unable to apply parameter corrections to IsisBundleObservation.
**ERROR** Instrument rotation is NULL, but pointing solve option is AnglesOnly.
add another image...
@@ -530,19 +528,16 @@ TestImageFileName
TestImage2FileName
Testing exceptions...
-**ERROR** Unable to apply parameter corrections to BundleObservation.
+**ERROR** Unable to apply parameter corrections to IsisBundleObservation.
**ERROR** Instrument position is NULL, but position solve option is PositionOnly.
-**ERROR** Unable to apply parameter corrections to BundleObservation.
+**ERROR** Unable to apply parameter corrections to IsisBundleObservation.
**ERROR** Instrument rotation is NULL, but pointing solve option is AnglesOnly.
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
Testing BundleObservationVector...
-number of position parameters: "0"
-number of pointing parameters: "0"
number of parameters: "0"
-init exterior orientiation successful? "Yes"
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
diff --git a/isis/src/control/objs/BundleUtilities/IsisBundleObservation.cpp b/isis/src/control/objs/BundleUtilities/IsisBundleObservation.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..abbb0cfc44e667b8331f615f4f1006a86c4f34c1
--- /dev/null
+++ b/isis/src/control/objs/BundleUtilities/IsisBundleObservation.cpp
@@ -0,0 +1,1375 @@
+/** 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 "IsisBundleObservation.h"
+
+#include
+#include
+#include
+#include
+
+#include "BundleImage.h"
+#include "BundleControlPoint.h"
+#include "BundleObservationSolveSettings.h"
+#include "BundleTargetBody.h"
+#include "Camera.h"
+#include "LinearAlgebra.h"
+#include "SpicePosition.h"
+#include "SpiceRotation.h"
+#include "CameraGroundMap.h"
+
+using namespace std;
+using namespace boost::numeric::ublas;
+
+namespace Isis {
+
+ /**
+ * Constructs a IsisBundleObservation initialized to a default state.
+ */
+ IsisBundleObservation::IsisBundleObservation() {
+ m_instrumentPosition = NULL;
+ m_instrumentRotation = NULL;
+ }
+
+
+ /**
+ * Constructs a IsisBundleObservation from an BundleImage, an instrument id, an observation
+ * number to assign to this IsisBundleObservation, and a target body.
+ *
+ * @param image QSharedPointer to the primary image in the observation
+ * @param observationNumber Observation number of the observation
+ * @param instrumentId Id of the instrument for the observation
+ * @param bundleTargetBody QSharedPointer to the target body of the observation
+ */
+ IsisBundleObservation::IsisBundleObservation(BundleImageQsp image, QString observationNumber,
+ QString instrumentId, BundleTargetBodyQsp bundleTargetBody) :
+ BundleObservation(image, observationNumber, instrumentId, bundleTargetBody) {
+ m_bundleTargetBody = bundleTargetBody;
+ m_instrumentRotation = NULL;
+ m_instrumentPosition = NULL;
+
+ if (image) {
+ // set the observations spice position and rotation objects from the primary image in the
+ // observation (this is, by design at the moment, the first image added to the observation)
+ // if the image, camera, or instrument position/orientation is null, then set to null
+ m_instrumentPosition = (image->camera() ?
+ (image->camera()->instrumentPosition() ?
+ image->camera()->instrumentPosition() : NULL)
+ : NULL);
+ m_instrumentRotation = (image->camera() ?
+ (image->camera()->instrumentRotation() ?
+ image->camera()->instrumentRotation() : NULL)
+ : NULL);
+ }
+ }
+
+
+ /**
+ * Creates a copy of another IsisBundleObservation.
+ *
+ * @param src Reference to the IsisBundleObservation to copy
+ */
+ IsisBundleObservation::IsisBundleObservation(const IsisBundleObservation &src) : BundleObservation(src) {
+ m_instrumentPosition = src.m_instrumentPosition;
+ m_instrumentRotation = src.m_instrumentRotation;
+ m_solveSettings = src.m_solveSettings;
+ m_bundleTargetBody = src.m_bundleTargetBody;
+ }
+
+
+ /**
+ * Destructor.
+ *
+ * Contained BundleImages will remain until all shared pointers are deleted.
+ */
+ IsisBundleObservation::~IsisBundleObservation() {
+ }
+
+
+ /**
+ * Assignment operator
+ *
+ * Assigns the state of the source IsisBundleObservation to this IsisBundleObservation
+ *
+ * @param IsisBundleObservation Reference to the source IsisBundleObservation to assign from
+ *
+ * @return @b IsisBundleObservation& Reference to this IsisBundleObservation
+ */
+ IsisBundleObservation &IsisBundleObservation::operator=(const IsisBundleObservation &src) {
+ if (&src != this) {
+ BundleObservation::operator=(src);
+ m_instrumentPosition = src.m_instrumentPosition;
+ m_instrumentRotation = src.m_instrumentRotation;
+ m_solveSettings = src.m_solveSettings;
+ m_bundleTargetBody = src.m_bundleTargetBody;
+ }
+ return *this;
+ }
+
+
+ /**
+ * Set solve parameters
+ *
+ * @param solveSettings The solve settings to use
+ *
+ * @return @b bool Returns true if settings were successfully set
+ */
+ bool IsisBundleObservation::setSolveSettings(BundleObservationSolveSettings solveSettings) {
+ m_solveSettings = BundleObservationSolveSettingsQsp(
+ new BundleObservationSolveSettings(solveSettings));
+
+ // initialize solution parameters for this observation
+ int nCameraAngleCoefficients = m_solveSettings->numberCameraAngleCoefficientsSolved();
+ int nCameraPositionCoefficients = m_solveSettings->numberCameraPositionCoefficientsSolved();
+
+ int nParameters = 3*nCameraPositionCoefficients + 2*nCameraAngleCoefficients;
+ if (nCameraAngleCoefficients >= 1 && m_solveSettings->solveTwist()) {
+ nParameters += nCameraAngleCoefficients;
+ }
+ // size vectors and set to zero
+ m_weights.resize(nParameters);
+ m_weights.clear();
+ m_corrections.resize(nParameters);
+ m_corrections.clear();
+ m_adjustedSigmas.resize(nParameters);
+ m_adjustedSigmas.clear();
+ m_aprioriSigmas.resize(nParameters);
+ for ( int i = 0; i < nParameters; i++) {
+ m_aprioriSigmas[i] = Isis::Null;
+ }
+
+ if (!initParameterWeights()) {
+ return false;
+ }
+
+ return true;
+ }
+
+
+ /**
+ * Accesses the instrument's spice rotation
+ *
+ * @return @b SpiceRotation* Returns the SpiceRotation for this observation
+ */
+ SpiceRotation *IsisBundleObservation::spiceRotation() {
+ return m_instrumentRotation;
+ }
+
+
+ /**
+ * Accesses the instrument's spice position
+ *
+ * @return @b SpicePosition* Returns the SpicePosition for this observation
+ */
+ SpicePosition *IsisBundleObservation::spicePosition() {
+ return m_instrumentPosition;
+ }
+
+
+ /**
+ * Accesses the solve settings
+ *
+ * @return @b const IsisBundleObservationSolveSettingsQsp Returns a pointer to the solve
+ * settings for this IsisBundleObservation
+ */
+ const BundleObservationSolveSettingsQsp IsisBundleObservation::solveSettings() {
+ return m_solveSettings;
+ }
+
+
+ /**
+ * Initializes the exterior orientation
+ *
+ * @return @b bool Returns true upon successful intialization
+ */
+ bool IsisBundleObservation::initializeExteriorOrientation() {
+ if (m_solveSettings->instrumentPositionSolveOption() !=
+ BundleObservationSolveSettings::NoPositionFactors) {
+
+ double positionBaseTime = 0.0;
+ double positiontimeScale = 0.0;
+ std::vector posPoly1, posPoly2, posPoly3;
+
+ for (int i = 0; i < size(); i++) {
+ BundleImageQsp image = at(i);
+ SpicePosition *spicePosition = image->camera()->instrumentPosition();
+
+ // If this image isn't the first, copy the position from the first
+ if (i > 0) {
+ spicePosition->SetPolynomialDegree(m_solveSettings->spkSolveDegree());
+ spicePosition->SetOverrideBaseTime(positionBaseTime, positiontimeScale);
+ spicePosition->SetPolynomial(posPoly1, posPoly2, posPoly3,
+ m_solveSettings->positionInterpolationType());
+ }
+ // Otherwise we need to fit the initial position
+ else {
+ // first, set the degree of the spk polynomial to be fit for a priori values
+ spicePosition->SetPolynomialDegree(m_solveSettings->spkDegree());
+
+ // now, set what kind of interpolation to use (polynomial function or
+ // polynomial function over hermite spline)
+ spicePosition->SetPolynomial(m_solveSettings->positionInterpolationType());
+
+ // finally, set the degree of the position polynomial actually used in the bundle adjustment
+ spicePosition->SetPolynomialDegree(m_solveSettings->spkSolveDegree());
+
+ if (m_instrumentPosition) {
+ positionBaseTime = m_instrumentPosition->GetBaseTime();
+ positiontimeScale = m_instrumentPosition->GetTimeScale();
+ m_instrumentPosition->GetPolynomial(posPoly1, posPoly2, posPoly3);
+ }
+ }
+ }
+ }
+
+ if (m_solveSettings->instrumentPointingSolveOption() !=
+ BundleObservationSolveSettings::NoPointingFactors) {
+
+ double rotationBaseTime = 0.0;
+ double rotationtimeScale = 0.0;
+ std::vector anglePoly1, anglePoly2, anglePoly3;
+
+ for (int i = 0; i < size(); i++) {
+ BundleImageQsp image = at(i);
+ SpiceRotation *spicerotation = image->camera()->instrumentRotation();
+
+ // If this image isn't the first, copy the pointing from the first
+ if (i > 0) {
+ spicerotation->SetPolynomialDegree(m_solveSettings->ckSolveDegree());
+ spicerotation->SetOverrideBaseTime(rotationBaseTime, rotationtimeScale);
+ spicerotation->SetPolynomial(anglePoly1, anglePoly2, anglePoly3,
+ m_solveSettings->pointingInterpolationType());
+ }
+ // Otherwise we need to fit the initial pointing
+ else {
+ // first, set the degree of the polynomial to be fit for a priori values
+ spicerotation->SetPolynomialDegree(m_solveSettings->ckDegree());
+
+ // now, set what kind of interpolation to use (polynomial function or
+ // polynomial function over a pointing cache)
+ spicerotation->SetPolynomial(m_solveSettings->pointingInterpolationType());
+
+ // finally, set the degree of the pointing polynomial actually used in the bundle adjustment
+ spicerotation->SetPolynomialDegree(m_solveSettings->ckSolveDegree());
+
+ rotationBaseTime = spicerotation->GetBaseTime();
+ rotationtimeScale = spicerotation->GetTimeScale();
+ spicerotation->GetPolynomial(anglePoly1, anglePoly2, anglePoly3);
+ }
+ }
+ }
+ return true;
+ }
+
+
+ /**
+ * Intializes the body rotation
+ */
+ void IsisBundleObservation::initializeBodyRotation() {
+ std::vector raCoefs = m_bundleTargetBody->poleRaCoefs();
+ std::vector decCoefs = m_bundleTargetBody->poleDecCoefs();
+ std::vector pmCoefs = m_bundleTargetBody->pmCoefs();
+
+ for (int i = 0; i < size(); i++) {
+ BundleImageQsp image = at(i);
+ image->camera()->bodyRotation()->setPckPolynomial(raCoefs, decCoefs, pmCoefs);
+ }
+ }
+
+
+ /**
+ * Updates the body rotation
+ */
+ void IsisBundleObservation::updateBodyRotation() {
+ std::vector raCoefs = m_bundleTargetBody->poleRaCoefs();
+ std::vector decCoefs = m_bundleTargetBody->poleDecCoefs();
+ std::vector pmCoefs = m_bundleTargetBody->pmCoefs();
+
+ for (int i = 0; i < size(); i++) {
+ BundleImageQsp image = at(i);
+ image->camera()->bodyRotation()->setPckPolynomial(raCoefs, decCoefs, pmCoefs);
+ }
+ }
+
+
+ /**
+ * Initializes the paramater weights for solving
+ *
+ * @return @b bool Returns true upon successful intialization
+ */
+ bool IsisBundleObservation::initParameterWeights() {
+
+ // weights for
+ double posWeight = 0.0; // position
+ double velWeight = 0.0; // velocity
+ double accWeight = 0.0; // acceleration
+ double angWeight = 0.0; // angles
+ double angVelWeight = 0.0; // angular velocity
+ double angAccWeight = 0.0; // angular acceleration
+
+ QList aprioriPointingSigmas = m_solveSettings->aprioriPointingSigmas();
+ QList aprioriPositionSigmas = m_solveSettings->aprioriPositionSigmas();
+
+ int nCamPosCoeffsSolved = 3 *m_solveSettings->numberCameraPositionCoefficientsSolved();
+
+ int nCamAngleCoeffsSolved;
+ if (m_solveSettings->solveTwist()) {
+ nCamAngleCoeffsSolved = 3 *m_solveSettings->numberCameraAngleCoefficientsSolved();
+ }
+ else {
+ nCamAngleCoeffsSolved = 2 *m_solveSettings->numberCameraAngleCoefficientsSolved();
+ }
+
+ if (aprioriPositionSigmas.size() >= 1 && aprioriPositionSigmas.at(0) > 0.0) {
+ posWeight = aprioriPositionSigmas.at(0);
+ posWeight = 1.0 / (posWeight *posWeight * 1.0e-6);
+ }
+ if (aprioriPositionSigmas.size() >= 2 && aprioriPositionSigmas.at(1) > 0.0) {
+ velWeight = aprioriPositionSigmas.at(1);
+ velWeight = 1.0 / (velWeight *velWeight * 1.0e-6);
+ }
+ if (aprioriPositionSigmas.size() >= 3 && aprioriPositionSigmas.at(2) > 0.0) {
+ accWeight = aprioriPositionSigmas.at(2);
+ accWeight = 1.0 / (accWeight *accWeight * 1.0e-6);
+ }
+
+ if (aprioriPointingSigmas.size() >= 1 && aprioriPointingSigmas.at(0) > 0.0) {
+ angWeight = aprioriPointingSigmas.at(0);
+ angWeight = 1.0 / (angWeight *angWeight * DEG2RAD * DEG2RAD);
+ }
+ if (aprioriPointingSigmas.size() >= 2 && aprioriPointingSigmas.at(1) > 0.0) {
+ angVelWeight = aprioriPointingSigmas.at(1);
+ angVelWeight = 1.0 / (angVelWeight * angVelWeight * DEG2RAD * DEG2RAD);
+ }
+ if (aprioriPointingSigmas.size() >= 3 && aprioriPointingSigmas.at(2) > 0.0) {
+ angAccWeight = aprioriPointingSigmas.at(2);
+ angAccWeight = 1.0 / (angAccWeight * angAccWeight * DEG2RAD * DEG2RAD);
+ }
+
+ int nSpkTerms = m_solveSettings->spkSolveDegree()+1;
+ nSpkTerms = m_solveSettings->numberCameraPositionCoefficientsSolved();
+ for ( int i = 0; i < nCamPosCoeffsSolved; i++) {
+ if (i % nSpkTerms == 0) {
+ m_aprioriSigmas[i] = aprioriPositionSigmas.at(0);
+ m_weights[i] = posWeight;
+ }
+ if (i % nSpkTerms == 1) {
+ m_aprioriSigmas[i] = aprioriPositionSigmas.at(1);
+ m_weights[i] = velWeight;
+ }
+ if (i % nSpkTerms == 2) {
+ m_aprioriSigmas[i] = aprioriPositionSigmas.at(2);
+ m_weights[i] = accWeight;
+ }
+ }
+
+ int nCkTerms = m_solveSettings->ckSolveDegree()+1;
+ nCkTerms = m_solveSettings->numberCameraAngleCoefficientsSolved();
+ for ( int i = 0; i < nCamAngleCoeffsSolved; i++) {
+ if (i % nCkTerms == 0) {
+ m_aprioriSigmas[nCamPosCoeffsSolved + i] = aprioriPointingSigmas.at(0);
+ m_weights[nCamPosCoeffsSolved + i] = angWeight;
+ }
+ if (i % nCkTerms == 1) {
+ m_aprioriSigmas[nCamPosCoeffsSolved + i] = aprioriPointingSigmas.at(1);
+ m_weights[nCamPosCoeffsSolved + i] = angVelWeight;
+ }
+ if (i % nCkTerms == 2) {
+ m_aprioriSigmas[nCamPosCoeffsSolved + i] = aprioriPointingSigmas.at(2);
+ m_weights[nCamPosCoeffsSolved + i] = angAccWeight;
+ }
+ }
+
+ return true;
+ }
+
+
+ /**
+ * Applies the parameter corrections
+ *
+ * @param corrections Vector of corrections to apply
+ *
+ * @throws IException::Unknown "Instrument position is NULL, but position solve option is
+ * [not NoPositionFactors]"
+ * @throws IException::Unknown "Instrument position is NULL, but pointing solve option is
+ * [not NoPointingFactors]"
+ * @throws IException::Unknown "Unable to apply parameter corrections to IsisBundleObservation."
+ *
+ * @return @b bool Returns true upon successful application of corrections
+ */
+ bool IsisBundleObservation::applyParameterCorrections(LinearAlgebra::Vector corrections) {
+
+ int index = 0;
+
+ try {
+ int nCameraAngleCoefficients = m_solveSettings->numberCameraAngleCoefficientsSolved();
+ int nCameraPositionCoefficients = m_solveSettings->numberCameraPositionCoefficientsSolved();
+
+ BundleObservationSolveSettings::InstrumentPositionSolveOption positionOption
+ = m_solveSettings->instrumentPositionSolveOption();
+ if (positionOption != BundleObservationSolveSettings::NoPositionFactors) {
+
+ if (!m_instrumentPosition) {
+ QString msg = "Instrument position is NULL, but position solve option is ";
+ msg.append(BundleObservationSolveSettings::instrumentPositionSolveOptionToString(
+ positionOption));
+ throw IException(IException::Unknown, msg, _FILEINFO_);
+ }
+
+ std::vector coefX(nCameraPositionCoefficients);
+ std::vector coefY(nCameraPositionCoefficients);
+ std::vector coefZ(nCameraPositionCoefficients);
+
+ m_instrumentPosition->GetPolynomial(coefX, coefY, coefZ);
+
+ // update X coordinate coefficient(s) and sum parameter correction
+ for (int i = 0; i < nCameraPositionCoefficients; i++) {
+ coefX[i] += corrections(index);
+ index++;
+ }
+
+ // update Y coordinate coefficient(s) and sum parameter correction
+ for (int i = 0; i < nCameraPositionCoefficients; i++) {
+ coefY[i] += corrections(index);
+ index++;
+ }
+
+ // update Z coordinate coefficient(s) and sum parameter correction
+ for (int i = 0; i < nCameraPositionCoefficients; i++) {
+ coefZ[i] += corrections(index);
+ index++;
+ }
+
+ // apply updates to all images in observation
+ for (int i = 0; i < size(); i++) {
+ BundleImageQsp image = at(i);
+ SpicePosition *spiceposition = image->camera()->instrumentPosition();
+ spiceposition->SetPolynomial(coefX, coefY, coefZ,
+ m_solveSettings->positionInterpolationType());
+ }
+ }
+
+ BundleObservationSolveSettings::InstrumentPointingSolveOption pointingOption
+ = m_solveSettings->instrumentPointingSolveOption();
+ if (pointingOption != BundleObservationSolveSettings::NoPointingFactors) {
+
+ if (!m_instrumentRotation) {
+ QString msg = "Instrument rotation is NULL, but pointing solve option is ";
+ msg.append(BundleObservationSolveSettings::instrumentPointingSolveOptionToString(
+ pointingOption));
+ throw IException(IException::Unknown, msg, _FILEINFO_);
+ }
+
+ std::vector coefRA(nCameraPositionCoefficients);
+ std::vector coefDEC(nCameraPositionCoefficients);
+ std::vector coefTWI(nCameraPositionCoefficients);
+
+ m_instrumentRotation->GetPolynomial(coefRA, coefDEC, coefTWI);
+
+ // update RA coefficient(s)
+ for (int i = 0; i < nCameraAngleCoefficients; i++) {
+ coefRA[i] += corrections(index);
+ index++;
+ }
+
+ // update DEC coefficient(s)
+ for (int i = 0; i < nCameraAngleCoefficients; i++) {
+ coefDEC[i] += corrections(index);
+ index++;
+ }
+
+ if (m_solveSettings->solveTwist()) {
+ // update TWIST coefficient(s)
+ for (int i = 0; i < nCameraAngleCoefficients; i++) {
+ coefTWI[i] += corrections(index);
+ index++;
+ }
+ }
+
+ // apply updates to all images in observation
+ for (int i = 0; i < size(); i++) {
+ BundleImageQsp image = at(i);
+ SpiceRotation *spiceRotation = image->camera()->instrumentRotation();
+ spiceRotation->SetPolynomial(coefRA, coefDEC, coefTWI,
+ m_solveSettings->pointingInterpolationType());
+ }
+ }
+
+ // update corrections
+ m_corrections += corrections;
+
+ }
+ catch (IException &e) {
+ QString msg = "Unable to apply parameter corrections to IsisBundleObservation.";
+ throw IException(e, IException::Unknown, msg, _FILEINFO_);
+ }
+ return true;
+ }
+
+
+ /**
+ * Returns the number of position parameters there are
+ *
+ * @return @b int Returns the number of position parameters
+ */
+ int IsisBundleObservation::numberPositionParameters() {
+ return 3.0 * m_solveSettings->numberCameraPositionCoefficientsSolved();
+ }
+
+
+ /**
+ * Returns the number of pointing parameters being solved for
+ *
+ * @return @b int Returns the number of pointing parameters
+ */
+ int IsisBundleObservation::numberPointingParameters() {
+ int angleCoefficients = m_solveSettings->numberCameraAngleCoefficientsSolved();
+
+ if (m_solveSettings->solveTwist()) {
+ return 3.0 * angleCoefficients;
+ }
+ return 2.0 * angleCoefficients;
+ }
+
+
+ /**
+ * Returns the number of total parameters there are for solving
+ *
+ * The total number of parameters is equal to the number of position parameters and number of
+ * pointing parameters
+ *
+ * @return @b int Returns the number of parameters there are
+ */
+ int IsisBundleObservation::numberParameters() {
+ return numberPositionParameters() + numberPointingParameters();
+ }
+
+
+/**
+ * Returns the list of observation parameter names.
+ *
+ * This will always return at least one set of positions and pointings
+ * because we always output at least the center values even when not solving
+ * for them.
+ *
+ * @return @b QStringList List of observation parameter names
+ */
+QStringList IsisBundleObservation::parameterList() {
+ QStringList paramList;
+
+ // We still want to output the center postion even if not solving for it
+ // so always do at least 1
+ int numberCamPosCoefSolved = std::max(
+ solveSettings()->numberCameraPositionCoefficientsSolved(),
+ 1);
+ for (int i = 0; i < numberCamPosCoefSolved; i++) {
+ if (numberCamPosCoefSolved == 1) {
+ paramList.push_back("X");
+ }
+ else {
+ QString str = "X(t" + toString(i) + ")";
+ paramList.push_back(str);
+ }
+ }
+ for (int i = 0; i < numberCamPosCoefSolved; i++) {
+ if (numberCamPosCoefSolved == 1) {
+ paramList.push_back("Y");
+ }
+ else {
+ QString str = "Y(t" + toString(i) + ")";
+ paramList.push_back(str);
+ }
+ }
+ for (int i = 0; i < numberCamPosCoefSolved; i++) {
+ if (numberCamPosCoefSolved == 1) {
+ paramList.push_back("Z");
+ }
+ else {
+ QString str = "Z(t" + toString(i) + ")";
+ paramList.push_back(str);
+ }
+ }
+
+ // We still want to output the center pointing even if not solving for it
+ // so always do at least 1
+ int numberCamAngleCoefSolved = std::max(
+ solveSettings()->numberCameraAngleCoefficientsSolved(),
+ 1);
+ for (int i = 0; i < numberCamAngleCoefSolved; i++) {
+ if (numberCamAngleCoefSolved == 1) {
+ paramList.push_back("RA");
+ }
+ else {
+ QString str = "RA(t" + toString(i) + ")";
+ paramList.push_back(str);
+ }
+ }
+ for (int i = 0; i < numberCamAngleCoefSolved; i++) {
+ if (numberCamAngleCoefSolved == 1) {
+ paramList.push_back("DEC");
+ }
+ else {
+ QString str = "DEC(t" + toString(i) + ")";
+ paramList.push_back(str);
+ }
+ }
+ for (int i = 0; i < numberCamAngleCoefSolved; i++) {
+ if (numberCamAngleCoefSolved == 1) {
+ paramList.push_back("TWIST");
+ }
+ else {
+ QString str = "TWIST(t" + toString(i) + ")";
+ paramList.push_back(str);
+ }
+ }
+
+ return paramList;
+}
+
+
+ /**
+ * @brief Fetches data for the log file output methods.
+ *
+ * @param finalParameterValues Reference to QVector of calculated
+ * position and pointing
+ * @param nPositionCoefficients Reference to int of the number of position coefficients
+ * @param nPointingCoefficients Reference to int of the number of pointing coefficients
+ * @param useDefaultPosition Reference to boolean of whether to use default position
+ * @param useDefaultPointing Reference to boolean of whether to use default pointing
+ * @param useDefaultTwist Reference to bollean of whether to use defualt twist
+ */
+ void IsisBundleObservation::bundleOutputFetchData(QVector &finalParameterValues,
+ int &nPositionCoefficients, int &nPointingCoefficients,
+ bool &useDefaultPosition,
+ bool &useDefaultPointing, bool &useDefaultTwist) {
+
+ std::vector coefX,coefY,coefZ,coefRA,coefDEC,coefTWI;
+ nPositionCoefficients = m_solveSettings->numberCameraPositionCoefficientsSolved();
+ nPointingCoefficients = m_solveSettings->numberCameraAngleCoefficientsSolved();
+
+ // Indicate if we need to obtain default position or pointing values
+ useDefaultPosition = false;
+ useDefaultPointing = false;
+ // Indicate if we need to use default values when not solving twist
+ useDefaultTwist = !(m_solveSettings->solveTwist());
+
+ // If we aren't solving for position, set the number of coefficients to 1 so we
+ // can output the instrumentPosition's center coordinate values for X, Y, and Z
+ if (nPositionCoefficients == 0) {
+ nPositionCoefficients = 1;
+ useDefaultPosition = true;
+ }
+
+ // If we arent' solving for pointing, set the number of coefficients to 1 so we
+ // can output the instrumentPointing's center angles for RA, DEC, and TWI
+ if (nPointingCoefficients == 0) {
+ nPointingCoefficients = 1;
+ useDefaultPointing = true;
+ }
+
+ coefX.resize(nPositionCoefficients);
+ coefY.resize(nPositionCoefficients);
+ coefZ.resize(nPositionCoefficients);
+ coefRA.resize(nPointingCoefficients);
+ coefDEC.resize(nPointingCoefficients);
+ coefTWI.resize(nPointingCoefficients);
+
+ if (m_instrumentPosition) {
+ if (!useDefaultPosition) {
+ m_instrumentPosition->GetPolynomial(coefX,coefY,coefZ);
+ }
+ // Use the position's center coordinate if not solving for spacecraft position
+ else {
+ const std::vector centerCoord = m_instrumentPosition->GetCenterCoordinate();
+ coefX[0] = centerCoord[0];
+ coefY[0] = centerCoord[1];
+ coefZ[0] = centerCoord[2];
+ }
+ }
+
+ if (m_instrumentRotation) {
+ if (!useDefaultPointing) {
+ m_instrumentRotation->GetPolynomial(coefRA,coefDEC,coefTWI);
+ }
+ // Use the pointing's center angles if not solving for pointing (rotation)
+ else {
+ const std::vector centerAngles = m_instrumentRotation->GetCenterAngles();
+ coefRA[0] = centerAngles[0];
+ coefDEC[0] = centerAngles[1];
+ coefTWI[0] = centerAngles[2];
+ }
+ }
+
+ // Combine all vectors into one
+ if (nPositionCoefficients > 0) {
+ for (int i=0; i < nPositionCoefficients; i++) {
+ finalParameterValues.append(coefX[i]);
+ }
+ for (int i=0; i < nPositionCoefficients; i++) {
+ finalParameterValues.append(coefY[i]);
+ }
+ for (int i=0; i < nPositionCoefficients; i++) {
+ finalParameterValues.append(coefZ[i]);
+ }
+ }
+ if (nPointingCoefficients > 0) {
+ for (int i=0; i < nPointingCoefficients; i++) {
+ finalParameterValues.append(coefRA[i]);
+ }
+ for (int i=0; i < nPointingCoefficients; i++) {
+ finalParameterValues.append(coefDEC[i]);
+ }
+ for (int i=0; i < nPointingCoefficients; i++) {
+ finalParameterValues.append(coefTWI[i]);
+ }
+ }
+
+ }
+
+
+ /**
+ * @brief Takes in an open std::ofstream and writes out information which goes into the
+ * bundleout.txt file.
+ *
+ * @param fpOut The open std::ofstream object which is passed in from
+ * BundleSolutionInfo::outputText()
+ * @param errorPropagation Boolean indicating whether or not to attach more information
+ * (corrections, sigmas, adjusted sigmas...) to the output.
+ */
+ void IsisBundleObservation::bundleOutputString(std::ostream &fpOut, bool errorPropagation) {
+
+ char buf[4096];
+
+ QVector finalParameterValues;
+ int nPositionCoefficients, nPointingCoefficients;
+ bool useDefaultPosition, useDefaultPointing,useDefaultTwist;
+
+ bundleOutputFetchData(finalParameterValues,
+ nPositionCoefficients,nPointingCoefficients,
+ useDefaultPosition,useDefaultPointing,useDefaultTwist);
+
+ int nPositionParameters = 3 * nPositionCoefficients;
+ int nPointingParameters = 3 * nPointingCoefficients;
+ int nParameters = nPositionParameters + nPointingParameters;
+
+ // for convenience, create vectors of parameters names and values in the correct sequence
+ QStringList parameterNamesListX,parameterNamesListY,parameterNamesListZ,
+ parameterNamesListRA,parameterNamesListDEC,parameterNamesListTWI,
+ parameterNamesList;
+ QStringList correctionUnitListX,correctionUnitListY,correctionUnitListZ,
+ correctionUnitListRA,correctionUnitListDEC,correctionUnitListTWI,
+ correctionUnitList;
+
+ QString str("%1(%2) ");
+ QString str2("%1(%2) ");
+ QString strN("%1(%2)");
+
+
+ if (nPositionCoefficients > 0) {
+ for (int j = 0; j < nPositionCoefficients;j++) {
+ if (j == 0) {
+ parameterNamesListX.append(str.arg(" X ").arg("km"));
+ parameterNamesListY.append(str.arg(" Y ").arg("km"));
+ parameterNamesListZ.append(str.arg(" Z ").arg("km"));
+ correctionUnitListX.append("m");
+ correctionUnitListY.append("m");
+ correctionUnitListZ.append("m");
+ } //end inner-if
+
+ else if (j==1) {
+ parameterNamesListX.append( str2.arg(" ").arg("km/s") );
+ parameterNamesListY.append( str2.arg(" ").arg("km/s") );
+ parameterNamesListZ.append( str2.arg(" ").arg("km/s") );
+ correctionUnitListX.append("m/s");
+ correctionUnitListY.append("m/s");
+ correctionUnitListZ.append("m/s");
+ }
+ else {
+ QString str("%1(%2)");
+ parameterNamesListX.append(strN.arg(" ").arg("km/s^"+toString(j) ) );
+ parameterNamesListY.append(strN.arg(" ").arg("km/s^"+toString(j) ) );
+ parameterNamesListZ.append(strN.arg(" ").arg("km/s^"+toString(j) ) );
+ correctionUnitListX.append("m/s^"+toString(j));
+ correctionUnitListY.append("m/s^"+toString(j));
+ correctionUnitListZ.append("m/s^"+toString(j));
+ }
+ }//end for
+ }//end outer-if
+
+ if (nPointingCoefficients > 0) {
+ for (int j = 0; j < nPointingCoefficients;j++) {
+ if (j == 0) {
+ parameterNamesListRA.append(str.arg(" RA ").arg("dd"));
+ parameterNamesListDEC.append(str.arg("DEC ").arg("dd"));
+ parameterNamesListTWI.append(str.arg("TWI ").arg("dd"));
+ correctionUnitListRA.append("dd");
+ correctionUnitListDEC.append("dd");
+ correctionUnitListTWI.append("dd");
+ } //end inner-if
+
+ else if (j==1) {
+ parameterNamesListRA.append( str2.arg(" ").arg("dd/s") );
+ parameterNamesListDEC.append( str2.arg(" ").arg("dd/s") );
+ parameterNamesListTWI.append( str2.arg(" ").arg("dd/s") );
+ correctionUnitListRA.append("dd/s");
+ correctionUnitListDEC.append("dd/s");
+ correctionUnitListTWI.append("dd/s");
+ }
+ else {
+ parameterNamesListRA.append(strN.arg(" ").arg("dd/s^"+toString(j) ) );
+ parameterNamesListDEC.append(strN.arg(" ").arg("dd/s^"+toString(j) ) );
+ parameterNamesListTWI.append(strN.arg(" ").arg("dd/s^"+toString(j) ) );
+ correctionUnitListRA.append("dd/s^"+toString(j));
+ correctionUnitListDEC.append("dd/s^"+toString(j));
+ correctionUnitListTWI.append("dd/s^"+toString(j));
+ }
+ }//end for
+ }// end outer-if
+
+ //Put all of the parameter names together into one QStringList
+ parameterNamesList.append(parameterNamesListX);
+ parameterNamesList.append(parameterNamesListY);
+ parameterNamesList.append(parameterNamesListZ);
+ parameterNamesList.append(parameterNamesListRA);
+ parameterNamesList.append(parameterNamesListDEC);
+ parameterNamesList.append(parameterNamesListTWI);
+
+ //Put all of the correction unit names together into one QStringList
+ correctionUnitList.append(correctionUnitListX);
+ correctionUnitList.append(correctionUnitListY);
+ correctionUnitList.append(correctionUnitListZ);
+ correctionUnitList.append(correctionUnitListDEC);
+ correctionUnitList.append(correctionUnitListRA);
+ correctionUnitList.append(correctionUnitListTWI);
+
+ // Set up default values when we are using default position
+ QString sigma = "N/A";
+ QString adjustedSigma = "N/A";
+ double correction = 0.0;
+
+ // position parameters
+ for (int i = 0; i < nPositionParameters; i++) {
+ // If not using the default position, we can correctly access sigmas and corrections
+ // members
+ if (!useDefaultPosition) {
+ correction = m_corrections(i);
+ adjustedSigma = QString::number(m_adjustedSigmas[i], 'f', 8);
+ sigma = ( IsSpecial(m_aprioriSigmas[i]) ? "FREE" : toString(m_aprioriSigmas[i], 8) );
+ }
+
+ sprintf(buf,"%s", parameterNamesList.at(i).toStdString().c_str() );
+ fpOut << buf;
+ sprintf(buf,"%18.8lf ", finalParameterValues[i] - correction);
+ fpOut << buf;
+ sprintf(buf,"%20.8lf ", correction);
+ fpOut << buf;
+ sprintf(buf,"%23.8lf ", finalParameterValues[i]);
+ fpOut << buf;
+ sprintf(buf," ");
+ fpOut << buf;
+ sprintf(buf,"%6s", sigma.toStdString().c_str());
+ fpOut << buf;
+ sprintf(buf," ");
+ fpOut << buf;
+ if (errorPropagation) {
+ sprintf(buf,"%s", adjustedSigma.toStdString().c_str());
+ }
+ else {
+ sprintf(buf,"%s", "N/A");
+ }
+ fpOut << buf;
+ sprintf(buf," ");
+ fpOut << buf;
+ sprintf(buf,"%s\n", correctionUnitList.at(i).toStdString().c_str() );
+ fpOut << buf;
+
+ }
+
+ // We need to use an offset of -3 (1 coef; X,Y,Z) if we used the default center coordinate
+ // (i.e. we did not solve for position), as m_corrections and m_*sigmas are populated
+ // according to which parameters are solved
+ int offset = 0;
+ if (useDefaultPosition) {
+ offset = 3;
+ }
+
+ // pointing parameters
+ for (int i = nPositionParameters; i < nParameters; i++) {
+ if (!useDefaultPointing) {
+ // If solving camera and not solving for twist, provide default values for twist to
+ // prevent bad indexing into m_corrections and m_*sigmas
+ // TWIST is last parameter, which corresponds to nParameters - nPointingCoefficients
+ if ( (i >= nParameters - nPointingCoefficients) && useDefaultTwist) {
+ correction = 0.0;
+ adjustedSigma = "N/A";
+ sigma = "N/A";
+ }
+ else {
+ correction = m_corrections(i - offset);
+ adjustedSigma = QString::number(m_adjustedSigmas(i-offset) * RAD2DEG, 'f', 8);
+ sigma = ( IsSpecial(m_aprioriSigmas[i - offset]) ? "FREE" :
+ toString(m_aprioriSigmas[i-offset], 8) );
+ }
+ }
+ // We are using default pointing, so provide default correction and sigma values to output
+ else {
+ correction = 0.0;
+ adjustedSigma = "N/A";
+ sigma = "N/A";
+ }
+
+ sprintf(buf,"%s",parameterNamesList.at(i).toStdString().c_str() );
+ fpOut << buf;
+ sprintf(buf,"%18.8lf ",(finalParameterValues[i]*RAD2DEG - correction*RAD2DEG));
+ fpOut << buf;
+ sprintf(buf,"%20.8lf ",(correction*RAD2DEG));
+ fpOut << buf;
+ sprintf(buf,"%23.8lf ",(finalParameterValues[i]*RAD2DEG));
+ fpOut << buf;
+ sprintf(buf," ");
+ fpOut << buf;
+ sprintf(buf,"%6s",sigma.toStdString().c_str());
+ fpOut << buf;
+ sprintf(buf," ");
+ fpOut << buf;
+ if (errorPropagation) {
+ sprintf(buf,"%s",adjustedSigma.toStdString().c_str());
+ }
+ else {
+ sprintf(buf,"%s","N/A");
+ }
+ fpOut< finalParameterValues;
+ int nPositionCoefficients, nPointingCoefficients;
+ bool useDefaultPosition, useDefaultPointing,useDefaultTwist;
+
+ bundleOutputFetchData(finalParameterValues,
+ nPositionCoefficients,nPointingCoefficients,
+ useDefaultPosition,useDefaultPointing,useDefaultTwist);
+
+ int nPositionParameters = 3 * nPositionCoefficients;
+ int nPointingParameters = 3 * nPointingCoefficients;
+ int nParameters = nPositionParameters + nPointingParameters;
+
+ QString finalqStr = "";
+
+ // Set up default values when we are using default position
+ QString sigma = "N/A";
+ QString adjustedSigma = "N/A";
+ double correction = 0.0;
+
+ // Position parameters
+ for (int i = 0; i < nPositionParameters; i++) {
+ if (!useDefaultPosition) {
+ correction = m_corrections(i);
+ adjustedSigma = QString::number(m_adjustedSigmas[i], 'f', 8);
+ sigma = ( IsSpecial(m_aprioriSigmas[i]) ? "FREE" : toString(m_aprioriSigmas[i], 8) );
+ }
+ // Provide default values for position if not solving position
+ else {
+ correction = 0.0;
+ adjustedSigma = "N/A";
+ sigma = "N/A";
+ }
+
+ finalqStr += toString(finalParameterValues[i] - correction) + ",";
+ finalqStr += toString(correction) + ",";
+ finalqStr += toString(finalParameterValues[i]) + ",";
+ finalqStr += sigma + ",";
+ if (errorPropagation) {
+ finalqStr += adjustedSigma + ",";
+ }
+ else {
+ finalqStr += "N/A,";
+ }
+
+ }
+
+ // If not solving position, we need to offset access to correction and sigma members by -3
+ // (X,Y,Z) since m_corrections and m_*sigmas are populated according to which parameters are
+ // solved
+ int offset = 0;
+ if (useDefaultPosition) {
+ offset = 3;
+ }
+ // pointing parameters
+ for (int i = nPositionParameters; i < nParameters; i++) {
+ if (!useDefaultPointing) {
+ // Use default values if solving camera but not solving for TWIST to prevent bad indexing
+ // into m_corrections and m_*sigmas
+ if ( (i >= nParameters - nPointingCoefficients) && useDefaultTwist) {
+ correction = 0.0;
+ adjustedSigma = "N/A";
+ sigma = "N/A";
+ }
+ else {
+ correction = m_corrections(i - offset);
+ adjustedSigma = QString::number(m_adjustedSigmas(i-offset) * RAD2DEG, 'f', 8);
+ sigma = ( IsSpecial(m_aprioriSigmas[i-offset]) ? "FREE" :
+ toString(m_aprioriSigmas[i-offset], 8) );
+ }
+ }
+ // Provide default values for pointing if not solving pointing
+ else {
+ correction = 0.0;
+ adjustedSigma = "N/A";
+ sigma = "N/A";
+ }
+
+ finalqStr += toString(finalParameterValues[i]*RAD2DEG - correction * RAD2DEG) + ",";
+ finalqStr += toString(correction * RAD2DEG) + ",";
+ finalqStr += toString(finalParameterValues[i]*RAD2DEG) + ",";
+ finalqStr += sigma + ",";
+ if (errorPropagation) {
+ finalqStr += adjustedSigma + ",";
+ }
+ else {
+ finalqStr += "N/A,";
+ }
+
+ }
+
+ return finalqStr;
+ }
+
+
+ /**
+ * Computes any needed partials for the target body parameters.
+ *
+ * @param coeffTarget Matrix for target body partial derivatives
+ * @param measure The measure that the partials are being
+ * computed for.
+ * @param bundleSettings The settings for the bundle adjustment
+ * @param bundleTargetBody QSharedPointer to the target body of
+ * the observation
+ *
+ * @return bool
+ */
+ bool IsisBundleObservation::computeTargetPartials(matrix &coeffTarget, BundleMeasure &measure,
+ BundleSettingsQsp &bundleSettings, BundleTargetBodyQsp &bundleTargetBody) {
+ coeffTarget.clear();
+
+ Camera *measureCamera = measure.camera();
+ BundleControlPoint *point = measure.parentControlPoint();
+ SurfacePoint surfacePoint = point->adjustedSurfacePoint();
+
+ int index = 0;
+
+ if (bundleSettings->solvePoleRA()) {
+ measureCamera->GroundMap()->GetdXYdTOrientation(SpiceRotation::WRT_RightAscension, 0,
+ &coeffTarget(0, index),
+ &coeffTarget(1, index));
+ index++;
+ }
+
+ if (bundleSettings->solvePoleRAVelocity()) {
+ measureCamera->GroundMap()->GetdXYdTOrientation(SpiceRotation::WRT_RightAscension, 1,
+ &coeffTarget(0, index),
+ &coeffTarget(1, index));
+ index++;
+ }
+
+ if (bundleSettings->solvePoleDec()) {
+ measureCamera->GroundMap()->GetdXYdTOrientation(SpiceRotation::WRT_Declination, 0,
+ &coeffTarget(0, index),
+ &coeffTarget(1, index));
+ index++;
+ }
+
+ if (bundleSettings->solvePoleDecVelocity()) {
+ measureCamera->GroundMap()->GetdXYdTOrientation(SpiceRotation::WRT_Declination, 1,
+ &coeffTarget(0, index),
+ &coeffTarget(1, index));
+ index++;
+ }
+
+ if (bundleSettings->solvePM()) {
+ measureCamera->GroundMap()->GetdXYdTOrientation(SpiceRotation::WRT_Twist, 0,
+ &coeffTarget(0, index),
+ &coeffTarget(1, index));
+ index++;
+ }
+
+ if (bundleSettings->solvePMVelocity()) {
+ measureCamera->GroundMap()->GetdXYdTOrientation(SpiceRotation::WRT_Twist, 1,
+ &coeffTarget(0, index),
+ &coeffTarget(1, index));
+ index++;
+ }
+
+ if (bundleTargetBody->solveMeanRadius()) {
+ std::vector lookBWRTMeanRadius =
+ measureCamera->GroundMap()->MeanRadiusPartial(surfacePoint,
+ bundleTargetBody->meanRadius());
+
+ measureCamera->GroundMap()->GetdXYdPoint(lookBWRTMeanRadius, &coeffTarget(0, index),
+ &coeffTarget(1, index));
+ index++;
+ }
+
+ if (bundleTargetBody->solveTriaxialRadii()) {
+
+ std::vector lookBWRTRadiusA =
+ measureCamera->GroundMap()->EllipsoidPartial(surfacePoint,
+ CameraGroundMap::WRT_MajorAxis);
+
+ measureCamera->GroundMap()->GetdXYdPoint(lookBWRTRadiusA, &coeffTarget(0, index),
+ &coeffTarget(1, index));
+ index++;
+
+ std::vector lookBWRTRadiusB =
+ measureCamera->GroundMap()->EllipsoidPartial(surfacePoint,
+ CameraGroundMap::WRT_MinorAxis);
+
+ measureCamera->GroundMap()->GetdXYdPoint(lookBWRTRadiusB, &coeffTarget(0, index),
+ &coeffTarget(1, index));
+ index++;
+
+ std::vector lookBWRTRadiusC =
+ measureCamera->GroundMap()->EllipsoidPartial(surfacePoint,
+ CameraGroundMap::WRT_PolarAxis);
+
+ measureCamera->GroundMap()->GetdXYdPoint(lookBWRTRadiusC, &coeffTarget(0, index),
+ &coeffTarget(1, index));
+ index++;
+ }
+
+ double observationSigma = 1.4 * measureCamera->PixelPitch();
+ double observationWeight = 1.0 / observationSigma;
+
+ // Multiply coefficients by observation weight
+ coeffTarget *= observationWeight;
+
+ return true;
+ }
+
+
+ /**
+ * Calculates the sensor partials with respect to the selected
+ * solve parameters and populates the coeffImage matrix.
+ *
+ * @param coeffImage A matrix that will be populated with the
+ * sensor partials with respect to the
+ * specified solve parameters.
+ * @param measure The measure that the partials are being
+ * computed for.
+ *
+ * @return bool
+ */
+ bool IsisBundleObservation::computeImagePartials(matrix &coeffImage, BundleMeasure &measure) {
+ coeffImage.clear();
+
+ Camera *camera = measure.camera();
+
+ int index = 0;
+
+ // Parials for X, Y, Z position coordinates
+ if (solveSettings()->instrumentPositionSolveOption() !=
+ BundleObservationSolveSettings::NoPositionFactors) {
+
+ int numCamPositionCoefficients =
+ solveSettings()->numberCameraPositionCoefficientsSolved();
+
+ // Add the partial for the x coordinate of the position (differentiating
+ // point(x,y,z) - spacecraftPosition(x,y,z) in J2000
+ for (int cameraCoef = 0; cameraCoef < numCamPositionCoefficients; cameraCoef++) {
+ camera->GroundMap()->GetdXYdPosition(SpicePosition::WRT_X, cameraCoef,
+ &coeffImage(0, index),
+ &coeffImage(1, index));
+ index++;
+ }
+
+ // Add the partial for the y coordinate of the position
+ for (int cameraCoef = 0; cameraCoef < numCamPositionCoefficients; cameraCoef++) {
+ camera->GroundMap()->GetdXYdPosition(SpicePosition::WRT_Y, cameraCoef,
+ &coeffImage(0, index),
+ &coeffImage(1, index));
+ index++;
+ }
+
+ // Add the partial for the z coordinate of the position
+ for (int cameraCoef = 0; cameraCoef < numCamPositionCoefficients; cameraCoef++) {
+ camera->GroundMap()->GetdXYdPosition(SpicePosition::WRT_Z, cameraCoef,
+ &coeffImage(0, index),
+ &coeffImage(1, index));
+ index++;
+ }
+ }
+
+ // Partials for RA, DEC, twist
+ if (solveSettings() ->instrumentPointingSolveOption() !=
+ BundleObservationSolveSettings::NoPointingFactors) {
+
+ int numCamAngleCoefficients =
+ solveSettings()->numberCameraAngleCoefficientsSolved();
+
+ // Add the partials for ra
+ for (int cameraCoef = 0; cameraCoef < numCamAngleCoefficients; cameraCoef++) {
+ camera->GroundMap()->GetdXYdOrientation(SpiceRotation::WRT_RightAscension,
+ cameraCoef, &coeffImage(0, index),
+ &coeffImage(1, index));
+ index++;
+ }
+
+ // Add the partials for dec
+ for (int cameraCoef = 0; cameraCoef < numCamAngleCoefficients; cameraCoef++) {
+ camera->GroundMap()->GetdXYdOrientation(SpiceRotation::WRT_Declination,
+ cameraCoef, &coeffImage(0, index),
+ &coeffImage(1, index));
+ index++;
+ }
+
+ // Add the partial for twist if necessary
+ if (solveSettings()->solveTwist()) {
+ for (int cameraCoef = 0; cameraCoef < numCamAngleCoefficients; cameraCoef++) {
+ camera->GroundMap()->GetdXYdOrientation(SpiceRotation::WRT_Twist,
+ cameraCoef, &coeffImage(0, index),
+ &coeffImage(1, index));
+ index++;
+ }
+ }
+ }
+
+ // Multiply coefficients by observation weight
+ double observationSigma = 1.4 * camera->PixelPitch();
+ double observationWeight = 1.0 / observationSigma;
+ coeffImage *= observationWeight;
+
+ return true;
+ }
+
+
+ /**
+ * Calculates the ground partials for the ground point currently
+ * set in the sensor model.
+ *
+ * @param coeffPoint3D A matrix that will be populated with the
+ * (line, sample) partials with respect to
+ * the ground point.
+ * @param measure The measure that the partials are being
+ * computed for.
+ * @param coordType Specifies whether latitudinal or (x, y, z)
+ * coordinates are used.
+ *
+ * @return bool
+ */
+ bool IsisBundleObservation::computePoint3DPartials(matrix &coeffPoint3D, BundleMeasure &measure, SurfacePoint::CoordinateType coordType) {
+ coeffPoint3D.clear();
+ Camera *measureCamera = measure.camera();
+ BundleControlPoint* point = measure.parentControlPoint();
+
+ // These vectors are either body-fixed latitudinal (lat/lon/radius) or rectangular (x/y/z)
+ // depending on the value of coordinate type in SurfacePoint
+ std::vector lookBWRTCoord1 = point->adjustedSurfacePoint().Partial(coordType, SurfacePoint::One);
+ std::vector lookBWRTCoord2 = point->adjustedSurfacePoint().Partial(coordType, SurfacePoint::Two);
+ std::vector lookBWRTCoord3 = point->adjustedSurfacePoint().Partial(coordType, SurfacePoint::Three);
+
+ measureCamera->GroundMap()->GetdXYdPoint(lookBWRTCoord1,
+ &coeffPoint3D(0, 0),
+ &coeffPoint3D(1, 0));
+ measureCamera->GroundMap()->GetdXYdPoint(lookBWRTCoord2,
+ &coeffPoint3D(0, 1),
+ &coeffPoint3D(1, 1));
+ measureCamera->GroundMap()->GetdXYdPoint(lookBWRTCoord3,
+ &coeffPoint3D(0, 2),
+ &coeffPoint3D(1, 2));
+
+ double observationSigma = 1.4 * measureCamera->PixelPitch();
+ double observationWeight = 1.0 / observationSigma;
+
+ // Multiply coefficients by observation weight
+ coeffPoint3D *= observationWeight;
+
+ return true;
+ }
+
+
+ /**
+ * Calculates the sample, line residuals between the measured
+ * focal plane values and the focal plane coordinates calculated
+ * for the ground point by the sensor model.
+ *
+ * @param coeffRHS A vector that will contain the focal plane
+ * x, y residuals.
+ * @param measure The measure that the partials are being
+ * computed for.
+ *
+ * @return bool
+ */
+ bool IsisBundleObservation::computeRHSPartials(boost::numeric::ublas::vector &coeffRHS, BundleMeasure &measure) {
+ coeffRHS.clear();
+ Camera *measureCamera = measure.camera();
+ BundleControlPoint* point = measure.parentControlPoint();
+ // Compute the look vector in instrument coordinates based on time of observation and apriori
+ // lat/lon/radius. As of 05/15/2019, this call no longer does the back-of-planet test. An optional
+ // bool argument was added CameraGroundMap::GetXY to turn off the test.
+ double computedX, computedY;
+ if (!(measureCamera->GroundMap()->GetXY(point->adjustedSurfacePoint(),
+ &computedX, &computedY, false))) {
+ QString msg = "Unable to map apriori surface point for measure ";
+ msg += measure.cubeSerialNumber() + " on point " + point->id() + " into focal plane";
+ throw IException(IException::User, msg, _FILEINFO_);
+ }
+
+ double measuredX = measure.focalPlaneMeasuredX();
+ double measuredY = measure.focalPlaneMeasuredY();
+
+ double deltaX = measuredX - computedX;
+ double deltaY = measuredY - computedY;
+
+ coeffRHS(0) = deltaX;
+ coeffRHS(1) = deltaY;
+
+ // Multiply coefficients by observation weight
+ double observationSigma = 1.4 * measureCamera->PixelPitch();
+ double observationWeight = 1.0 / observationSigma;
+
+ coeffRHS *= observationWeight;
+
+ return true;
+ }
+
+
+ /**
+ * Converts the observed value from a focal plane coordinate to
+ * an image sample or line.
+ *
+ * @param measure measure The measure that the partials are
+ * being computed for.
+ * @param deltaVal The difference between the measured and
+ * calculated focal plane coordinate
+ *
+ * @return double The The difference between the measured and
+ * calculated (line, sample) coordinate
+ */
+ double IsisBundleObservation::computeObservationValue(BundleMeasure &measure, double deltaVal) {
+ Camera *measureCamera = measure.camera();
+ return deltaVal / measureCamera->PixelPitch();
+ }
+}
+
diff --git a/isis/src/control/objs/BundleUtilities/IsisBundleObservation.h b/isis/src/control/objs/BundleUtilities/IsisBundleObservation.h
new file mode 100644
index 0000000000000000000000000000000000000000..b9e58f97012069e81a58b80a04fee4ee667d67a4
--- /dev/null
+++ b/isis/src/control/objs/BundleUtilities/IsisBundleObservation.h
@@ -0,0 +1,101 @@
+#ifndef IsisBundleObservation_h
+#define IsisBundleObservation_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
+#include
+
+#include "BundleImage.h"
+#include "BundleObservationSolveSettings.h"
+#include "BundleSettings.h"
+#include "BundleTargetBody.h"
+#include "LinearAlgebra.h"
+#include "BundleObservation.h"
+#include "BundleMeasure.h"
+#include "SurfacePoint.h"
+
+namespace Isis {
+ class BundleObservationSolveSettings;
+ class SpicePosition;
+ class SpiceRotation;
+
+ /**
+ * Class for observations that use ISIS camera models in bundle adjustment
+ *
+ * @ingroup ControlNetworks
+ */
+ class IsisBundleObservation : public BundleObservation {
+
+ public:
+ // default constructor
+ IsisBundleObservation();
+
+ // constructor
+ IsisBundleObservation(BundleImageQsp image, QString observationNumber, QString instrumentId,
+ BundleTargetBodyQsp bundleTargetBody);
+
+ // copy constructor
+ IsisBundleObservation(const IsisBundleObservation &src);
+
+ // destructor
+ ~IsisBundleObservation();
+
+ // equals operator
+ IsisBundleObservation &operator=(const IsisBundleObservation &src);
+
+ // copy method
+ void copy(const IsisBundleObservation &src);
+
+ virtual bool setSolveSettings(BundleObservationSolveSettings solveSettings);
+
+ int numberPositionParameters();
+ int numberPointingParameters();
+ int numberParameters();
+
+ SpiceRotation *spiceRotation();
+ SpicePosition *spicePosition();
+
+ const BundleObservationSolveSettingsQsp solveSettings();
+
+ bool applyParameterCorrections(LinearAlgebra::Vector corrections);
+ bool initializeExteriorOrientation();
+ void initializeBodyRotation();
+ void updateBodyRotation();
+
+ void bundleOutputFetchData(QVector &finalParameterValues,
+ int &nPositionCoefficients, int &nPointingCoefficients,
+ bool &useDefaultPosition, bool &useDefaultPointing,
+ bool &useDefaultTwist);
+ void bundleOutputString(std::ostream &fpOut,bool errorPropagation);
+ QString bundleOutputCSV(bool errorPropagation);
+
+ virtual QStringList parameterList();
+
+ bool computeTargetPartials(LinearAlgebra::Matrix &coeffTarget, BundleMeasure &measure, BundleSettingsQsp &bundleSettings, BundleTargetBodyQsp &bundleTargetBody);
+ bool computeImagePartials(LinearAlgebra::Matrix &coeffImage, BundleMeasure &measure);
+ bool computePoint3DPartials(LinearAlgebra::Matrix &coeffPoint3D, BundleMeasure &measure, SurfacePoint::CoordinateType coordType);
+ bool computeRHSPartials(LinearAlgebra::Vector &coeffRHS, BundleMeasure &measure);
+ double computeObservationValue(BundleMeasure &measure, double deltaVal);
+
+ private:
+ bool initParameterWeights();
+ BundleObservationSolveSettingsQsp m_solveSettings; //!< Solve settings for this observation.
+
+ SpiceRotation *m_instrumentRotation; //!< Instrument spice rotation (in primary image).
+ SpicePosition *m_instrumentPosition; //!< Instrument spice position (in primary image).
+
+ BundleTargetBodyQsp m_bundleTargetBody; //!< QShared pointer to BundleTargetBody.
+ };
+
+ //! Typdef for IsisBundleObservation QSharedPointer.
+ typedef QSharedPointer IsisBundleObservationQsp;
+}
+
+#endif // IsisBundleObservation_h
diff --git a/isis/src/control/objs/BundleUtilities/unitTest.cpp b/isis/src/control/objs/BundleUtilities/unitTest.cpp
index 3e0d42b98d245df15bd214d21f8e0548b3b6dc9a..875487907778f28c937f9d2829af30d87d9db867 100755
--- a/isis/src/control/objs/BundleUtilities/unitTest.cpp
+++ b/isis/src/control/objs/BundleUtilities/unitTest.cpp
@@ -10,7 +10,7 @@ find files of those names at the top level of this repository. **/
#include "BundleControlPoint.h"
#include "BundleImage.h"
#include "BundleMeasure.h"
-#include "BundleObservation.h"
+#include "IsisBundleObservation.h"
#include "BundleObservationSolveSettings.h"
#include "BundleObservationVector.h"
#include "BundleSettings.h"
@@ -385,7 +385,7 @@ int main(int argc, char *argv[]) {
Camera *camera = NULL;
BundleImage bi(camera, "TestImageSerialNumber", "TestImageFileName");
qDebug() << "setting null parentBundleObservation to BundleImage...";
- BundleObservationQsp parentObservation;
+ IsisBundleObservationQsp parentObservation;
bi.setParentObservation(parentObservation);
qDebug() << "Access camera and parentObservation ...";
// Camera *cam = bi.camera();
@@ -412,8 +412,8 @@ int main(int argc, char *argv[]) {
qDebug() << "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
qDebug() << "";
qDebug() << "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
- qDebug() << "Testing BundleObservation...";
- qDebug() << "Constructing empty BundleObservation object...";
+ qDebug() << "Testing IsisBundleObservation...";
+ qDebug() << "Constructing empty IsisBundleObservation object...";
/**
TEST COVERAGE (SCOPE) FOR THIS SOURCE FILE: ??% (need to re-run SquishCoco)
NEED:
@@ -429,29 +429,29 @@ int main(int argc, char *argv[]) {
pntsigma[1] > 0, pntsigma[2] == 0
6) formatBundleOutputString - with instrumentPosition/instrumentRotation not NULL
*/
- BundleObservation bo;
+ IsisBundleObservation bo;
BundleTargetBodyQsp bundleTargetBody = BundleTargetBodyQsp(new BundleTargetBody);
- qDebug() << "Constructing BundleObservation object from BundleImage...";
- BundleObservation bo2(bi2,
+ qDebug() << "Constructing IsisBundleObservation object from BundleImage...";
+ IsisBundleObservation bo2(bi2,
"ObservationNumber2",
"InstrumentId2",
bundleTargetBody);
BundleImageQsp nullImage;
- BundleObservation nullBO(nullImage,
+ IsisBundleObservation nullBO(nullImage,
"NullObservationNumber",
"NullInstrumentId",
bundleTargetBody);
qDebug() << "Testing assignment operator to set this equal to itself...";
{
- BundleObservation &tbo2 = bo2;
+ IsisBundleObservation &tbo2 = bo2;
bo2 = tbo2;
}
qDebug() << "Testing assignment operator to create a new object...";
bo = bo2;
qDebug() << "Testing copy constructor...";
- BundleObservation bo3(bo);
+ IsisBundleObservation bo3(bo);
qDebug() << "Testing mutators and accessors...";
qDebug() << " Set/get solve settings using with CAMESOLVE=NONE...";
@@ -491,8 +491,6 @@ int main(int argc, char *argv[]) {
qDebug() << "index = " << toString(bo3.index());
qDebug() << "instrument id = " << bo3.instrumentId();
qDebug() << "number parameters = " << toString(bo3.numberParameters());
- qDebug() << "number position param = " << toString(bo3.numberPositionParameters());
- qDebug() << "number pointing param = " << toString(bo3.numberPointingParameters());
qDebug() << "parameter list: " << bo3.parameterList();
qDebug() << "image names: " << bo3.imageNames();
@@ -615,29 +613,11 @@ int main(int argc, char *argv[]) {
*/
BundleObservationVector bov;
BundleSettingsQsp bundleSettings = BundleSettingsQsp(new BundleSettings);
- // BundleObservation *obs1 = bov.addNew(bi2, "obs1", "InstrumentIdBOV", bundleSettings);
- //qDebug() << obs1->formatBundleOutputString(true);
- //obs1 = bov.observationByCubeSerialNumber("obs1");
- //BundleObservation *obs2 = bov.addNew(bundleImage, "obs2", "InstrumentIdBOV", bundleSettings);
- //qDebug() << obs2->formatBundleOutputString(true);
- qDebug() << "number of position parameters: " << toString(bov.numberPositionParameters());
- qDebug() << "number of pointing parameters: " << toString(bov.numberPointingParameters());
qDebug() << "number of parameters: " << toString(bov.numberParameters());
-
-#if 0
- BundleObservation obs1b = *bov.getObservationByCubeSerialNumber("obs1");
- qDebug() << "same observation?" << toString((obs1 == obs1b));
- qDebug() << obs1b.formatBundleOutputString(true);
-#endif
- // Following segfaults (see #4157)
- qDebug() << "init exterior orientiation successful? " << toString(bov.initializeExteriorOrientation());
qDebug() << "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
qDebug() << "";
qDebug() << "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
qDebug() << "Testing BundleControlPoint...";
- #if 0
- TEST COVERAGE (SCOPE) FOR THIS SOURCE FILE: 100%
- #endif
// #1 Test free point with default settings (solveRadius=false), apriori coordinates set, but no
// sigmas (other settings: observation mode = false, update =false, errorProp = false)
qDebug() << "BCP test 1 - Create FreePoint with free point containing 2 measures "
@@ -1098,7 +1078,7 @@ settings->setSolveOptions(false, false, false, false, SurfacePoint::Rectangular,
catch (IException &e) {
e.print();
}
- bundleMeasure.setParentObservation(BundleObservationQsp(new BundleObservation(bo2)));
+ bundleMeasure.setParentObservation(IsisBundleObservationQsp(new IsisBundleObservation(bo2)));
// const BundleObservationSolveSettings *solveSettings =
bundleMeasure.observationSolveSettings();
// Camera *cam =
diff --git a/isis/src/control/objs/ControlPoint/ControlPoint.cpp b/isis/src/control/objs/ControlPoint/ControlPoint.cpp
index 8c934eb2196c048929feeb38dd14fbd2161d2674..c5f08f0d1221cdf92ff93e4dd2a0834601f9f5b9 100644
--- a/isis/src/control/objs/ControlPoint/ControlPoint.cpp
+++ b/isis/src/control/objs/ControlPoint/ControlPoint.cpp
@@ -934,8 +934,15 @@ namespace Isis {
}
bool setImageSuccess = cam->SetImage(m->GetSample(), m->GetLine());
- m->SetFocalPlaneMeasured(cam->DistortionMap()->UndistortedFocalPlaneX(),
- cam->DistortionMap()->UndistortedFocalPlaneY());
+ // CSM cameras do not have focal planes so use sample and line instead
+ if (cam->GetCameraType() == Camera::Csm) {
+ m->SetFocalPlaneMeasured(m->GetSample(),
+ m->GetLine());
+ }
+ else {
+ m->SetFocalPlaneMeasured(cam->DistortionMap()->UndistortedFocalPlaneX(),
+ cam->DistortionMap()->UndistortedFocalPlaneY());
+ }
// TODO: Seems like we should be able to skip this computation if point is fixed or
// constrained in any coordinate. Currently we are always summing coordinates here. We could
@@ -1033,12 +1040,7 @@ namespace Isis {
if (m->IsIgnored()) {
continue;
}
- // The following lines actually check for Candidate measures
- // Commented out on 2011-03-24 by DAC
-// if (!m->IsMeasured()) {
-// continue;
- // TODO: Should we use crater diameter?
Camera *cam = m->Camera();
double cuSamp;
@@ -1051,24 +1053,8 @@ namespace Isis {
// instead of using the measured time.
ComputeResiduals_Millimeters();
- if (cam->GetCameraType() != Isis::Camera::Radar) {
-
- // Now things get tricky. We want to produce errors in pixels not mm
- // but some of the camera maps could fail. One that won't is the
- // FocalPlaneMap which takes x/y to detector s/l. We will bypass the
- // distortion map and have residuals in undistorted pixels.
- if (!fpmap->SetFocalPlane(m->GetFocalPlaneComputedX(), m->GetFocalPlaneComputedY())) {
- QString msg = "Sanity check #1 for ControlPoint [" + GetId() +
- "], ControlMeasure [" + m->GetCubeSerialNumber() + "]";
- throw IException(IException::Programmer, msg, _FILEINFO_);
- // This error shouldn't happen but check anyways
- }
-
- cuSamp = fpmap->DetectorSample();
- cuLine = fpmap->DetectorLine();
- }
-
- else {
+ // Convert the residuals in millimeters to undistorted pixels
+ if (cam->GetCameraType() == Isis::Camera::Radar) {
// For radar line is calculated from time in the camera. Use the
// closest line to scale the focal plane y (doppler shift) to image line
// for computing the line residual. Get a local ratio
@@ -1129,11 +1115,40 @@ namespace Isis {
cuSamp = fpmap->DetectorSample();
cuLine = m->GetLine() + deltaLine;
}
+ else if (cam->GetCameraType() == Isis::Camera::Csm) {
+ //
+ cuSamp = m->GetFocalPlaneComputedX();
+ cuLine = m->GetFocalPlaneComputedY();
+ }
+ else {
+ // Now things get tricky. We want to produce errors in pixels not mm
+ // but some of the camera maps could fail. One that won't is the
+ // FocalPlaneMap which takes x/y to detector s/l. We will bypass the
+ // distortion map and have residuals in undistorted pixels.
+ if (!fpmap->SetFocalPlane(m->GetFocalPlaneComputedX(), m->GetFocalPlaneComputedY())) {
+ QString msg = "Sanity check #1 for ControlPoint [" + GetId() +
+ "], ControlMeasure [" + m->GetCubeSerialNumber() + "]";
+ throw IException(IException::Programmer, msg, _FILEINFO_);
+ // This error shouldn't happen but check anyways
+ }
+
+ cuSamp = fpmap->DetectorSample();
+ cuLine = fpmap->DetectorLine();
+ }
+
+ // Compute the measures sample and line
double muSamp;
double muLine;
- if (cam->GetCameraType() != Isis::Camera::Radar) {
+ if (cam->GetCameraType() == Isis::Camera::Radar ||
+ cam->GetCameraType() == Isis::Camera::Csm) {
+ // For CSM and Radar we use distorted pixels
+ muSamp = m->GetSample();
+ muLine = m->GetLine();
+ }
+ else {
+ // For other sensors conver to undistorted pixels
// Again we will bypass the distortion map and have residuals in undistorted pixels.
if (!fpmap->SetFocalPlane(m->GetFocalPlaneMeasuredX(), m->GetFocalPlaneMeasuredY())) {
QString msg = "Sanity check #2 for ControlPoint [" + GetId() +
@@ -1144,14 +1159,10 @@ namespace Isis {
muSamp = fpmap->DetectorSample();
muLine = fpmap->DetectorLine();
}
- else {
- muSamp = m->GetSample();
- muLine = m->GetLine();
- }
// The units are in detector sample/lines. We will apply the instrument
// summing mode to get close to real pixels. Note however we are in
- // undistorted pixels except for radar instruments.
+ // undistorted pixels except for radar and CSM instruments.
double sampResidual = muSamp - cuSamp;
double lineResidual = muLine - cuLine;
m->SetResidual(sampResidual, lineResidual);
@@ -1193,35 +1204,36 @@ namespace Isis {
if (m->IsIgnored()) {
continue;
}
- // The following lines actually check for Candidate measures
- // Commented out on 2011-03-24 by DAC
-// if (!m->IsMeasured()) {
-// continue;
- // TODO: Should we use crater diameter?
Camera *cam = m->Camera();
double cudx, cudy;
// Map the coordinates of the control point through the Spice of the
// measurement sample/line to get the computed undistorted focal plane
- // coordinates (mm if not radar). This works for radar too because in
- // the undistorted focal plane, y has not been set to 0 (set to 0 when
- // going to distorted focal plane or ground range in this case), so we
- // can hold the Spice to calculate residuals in undistorted focal plane
- // coordinates.
- if (cam->GetCameraType() != 0) { // no need to call setimage for framing camera
+ // coordinates (mm if not radar).
+ // This works for radar too because in the undistorted focal plane,
+ // y has not been set to 0 (set to 0 when going to distorted focal plane
+ // or ground range in this case), so we can hold the Spice to calculate
+ // residuals in undistorted focal plane coordinates.
+ // This does not work with CSM as it does not have a focal plane so
+ // just use the sample and line
+ if (cam->GetCameraType() == Camera::Csm) {
+ cam->SetGround(GetAdjustedSurfacePoint());
+ cudx = cam->Sample();
+ cudy = cam->Line();
+ // Reset to measure
cam->SetImage(m->GetSample(), m->GetLine());
}
-
- // The default bool value is true. Turn back-of-planet test off for bundle adjustment.
- cam->GroundMap()->GetXY(GetAdjustedSurfacePoint(), &cudx, &cudy, false);
- // double mudx = m->GetFocalPlaneMeasuredX();
- // double mudy = m->GetFocalPlaneMeasuredY();
+ else {
+ // no need to call setimage for framing camera
+ if (cam->GetCameraType() != 0) {
+ cam->SetImage(m->GetSample(), m->GetLine());
+ }
+ // The default bool value is true. Turn back-of-planet test off for bundle adjustment.
+ cam->GroundMap()->GetXY(GetAdjustedSurfacePoint(), &cudx, &cudy, false);
+ }
m->SetFocalPlaneComputed(cudx, cudy);
-
- // This is wrong. The stored residual is in pixels (sample,line), not x and y
- // m->SetResidual(mudx - cudx, mudy - cudy);
}
return Success;
diff --git a/isis/src/control/objs/CsmBundleObservation/CsmBundleObservation.cpp b/isis/src/control/objs/CsmBundleObservation/CsmBundleObservation.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8d4fb1e22fecdab94cec8ad4e85f449521f9acfb
--- /dev/null
+++ b/isis/src/control/objs/CsmBundleObservation/CsmBundleObservation.cpp
@@ -0,0 +1,484 @@
+/** 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 "CsmBundleObservation.h"
+
+#include
+#include
+#include
+#include
+
+#include "BundleImage.h"
+#include "BundleControlPoint.h"
+#include "BundleObservationSolveSettings.h"
+#include "BundleTargetBody.h"
+#include "Camera.h"
+#include "CSMCamera.h"
+#include "LinearAlgebra.h"
+#include "SpicePosition.h"
+#include "SpiceRotation.h"
+
+using namespace std;
+
+namespace Isis {
+
+ /**
+ * Constructs a CsmBundleObservation initialized to a default state.
+ */
+ CsmBundleObservation::CsmBundleObservation() {
+ }
+
+
+ /**
+ * Constructs a CsmBundleObservation from a BundleImage, an instrument id, an observation
+ * number to assign to this CsmBundleObservation, and a target body.
+ *
+ * @param image QSharedPointer to the primary image in the observation
+ * @param observationNumber Observation number of the observation
+ * @param instrumentId Id of the instrument for the observation
+ * @param bundleTargetBody QSharedPointer to the target body of the observation
+ */
+ CsmBundleObservation::CsmBundleObservation(BundleImageQsp image, QString observationNumber,
+ QString instrumentId, BundleTargetBodyQsp bundleTargetBody) : BundleObservation(image, observationNumber, instrumentId, bundleTargetBody) {
+ if (bundleTargetBody) {
+ QString msg = "Target body parameters cannot be solved for with CSM observations.";
+ throw IException(IException::User, msg, _FILEINFO_);
+ }
+ }
+
+
+ /**
+ * Creates a copy of another CsmBundleObservation.
+ *
+ * @param src Reference to the CsmBundleObservation to copy
+ */
+ CsmBundleObservation::CsmBundleObservation(const CsmBundleObservation &src) : BundleObservation(src) {
+ m_solveSettings = src.m_solveSettings;
+ m_paramIndices = src.m_paramIndices;
+ }
+
+
+ /**
+ * Destructor.
+ *
+ * Contained BundleImages will remain until all shared pointers are deleted.
+ */
+ CsmBundleObservation::~CsmBundleObservation() {
+ }
+
+
+ /**
+ * Assignment operator
+ *
+ * Assigns the state of the source CsmBundleObservation to this CsmBundleObservation
+ *
+ * @param CsmBundleObservation Reference to the source CsmBundleObservation to assign from
+ *
+ * @return @b CsmBundleObservation& Reference to this CsmBundleObservation
+ */
+ CsmBundleObservation &CsmBundleObservation::operator=(const CsmBundleObservation &src) {
+ if (&src != this) {
+ m_solveSettings = src.m_solveSettings;
+ m_paramIndices = src.m_paramIndices;
+ }
+ return *this;
+ }
+
+
+ /**
+ * Set solve parameters
+ *
+ * @param solveSettings The solve settings to use
+ *
+ * @return @b bool Returns true if settings were successfully set
+ */
+ bool CsmBundleObservation::setSolveSettings(BundleObservationSolveSettings solveSettings) {
+ m_solveSettings = BundleObservationSolveSettingsQsp(
+ new BundleObservationSolveSettings(solveSettings));
+
+ CSMCamera *csmCamera = dynamic_cast(front()->camera());
+
+ m_paramIndices.clear();
+ m_weights.clear();
+ m_corrections.clear();
+ m_adjustedSigmas.clear();
+
+ if (m_solveSettings->csmSolveOption() == BundleObservationSolveSettings::Set) {
+ m_paramIndices = csmCamera->getParameterIndices(m_solveSettings->csmParameterSet());
+ }
+ else if (m_solveSettings->csmSolveOption() == BundleObservationSolveSettings::Type) {
+ m_paramIndices = csmCamera->getParameterIndices(m_solveSettings->csmParameterType());
+ }
+ else if (m_solveSettings->csmSolveOption() == BundleObservationSolveSettings::List) {
+ m_paramIndices = csmCamera->getParameterIndices(m_solveSettings->csmParameterList());
+ }
+ else {
+ return false;
+ }
+
+ int nParams = m_paramIndices.size();
+
+ m_weights.resize(nParams);
+ m_corrections.resize(nParams);
+ m_adjustedSigmas.resize(nParams);
+ m_aprioriSigmas.resize(nParams);
+
+ for (int i = 0; i < nParams; i++) {
+ m_aprioriSigmas[i] = csmCamera->getParameterCovariance(m_paramIndices[i], m_paramIndices[i]);
+ }
+
+ return true;
+ }
+
+
+ /**
+ * Accesses the solve settings
+ *
+ * @return @b const BundleObservationSolveSettingsQsp Returns a pointer to the solve
+ * settings for this CsmBundleObservation
+ */
+ const BundleObservationSolveSettingsQsp CsmBundleObservation::solveSettings() {
+ return BundleObservationSolveSettingsQsp(nullptr);
+ }
+
+
+ /**
+ * Applies the parameter corrections
+ *
+ * @param corrections Vector of corrections to apply
+ *
+ * @throws IException::Unknown "Instrument position is NULL, but position solve option is
+ * [not NoPositionFactors]"
+ * @throws IException::Unknown "Instrument position is NULL, but pointing solve option is
+ * [not NoPointingFactors]"
+ * @throws IException::Unknown "Unable to apply parameter corrections to CsmBundleObservation."
+ *
+ * @return @b bool Returns true upon successful application of corrections
+ */
+ bool CsmBundleObservation::applyParameterCorrections(LinearAlgebra::Vector corrections) {
+ // Check that the correction vector is the correct size
+ if (corrections.size() != m_paramIndices.size()) {
+ QString msg = "Invalid correction vector passed to observation.";
+ IException(IException::Programmer, msg, _FILEINFO_);
+ }
+
+ // Apply the corrections to the CSM camera
+ CSMCamera *csmCamera = dynamic_cast(front()->camera());
+ for (size_t i = 0; i < corrections.size(); i++) {
+ csmCamera->applyParameterCorrection(m_paramIndices[i], corrections[i]);
+ }
+
+ // Accumulate the total corrections
+ m_corrections += corrections;
+
+ return true;
+ }
+
+
+ /**
+ * Returns the number of total parameters there are for solving
+ *
+ * The total number of parameters is equal to the number of position parameters and number of
+ * pointing parameters
+ *
+ * @return @b int Returns the number of parameters there are
+ */
+ int CsmBundleObservation::numberParameters() {
+ return m_paramIndices.size();
+ }
+
+
+ /**
+ * @brief Takes in an open std::ofstream and writes out information which goes into the
+ * bundleout.txt file.
+ *
+ * @param fpOut The open std::ofstream object which is passed in from
+ * BundleSolutionInfo::outputText()
+ * @param errorPropagation Boolean indicating whether or not to attach more information
+ * (corrections, sigmas, adjusted sigmas...) to the output.
+ */
+ void CsmBundleObservation::bundleOutputString(std::ostream &fpOut, bool errorPropagation) {
+
+ char buf[4096];
+
+ QVector finalParameterValues;
+ CSMCamera *csmCamera = dynamic_cast(front()->camera());
+
+ int nParameters = numberParameters();
+
+ QStringList parameterNamesList;
+ QStringList parameterUnitList;
+
+ for (int i = 0; i < nParameters; i++) {
+ parameterNamesList.append(csmCamera->getParameterName(m_paramIndices[i]));
+ parameterUnitList.append(csmCamera->getParameterUnits(m_paramIndices[i]));
+ finalParameterValues.append(csmCamera->getParameterValue(m_paramIndices[i]));
+ }
+
+
+ // Set up default values when we are using default position
+ QString sigma;
+ QString adjustedSigma;
+ double correction;
+
+ for (int i = 0; i < nParameters; i++) {
+
+ correction = m_corrections(i);
+ adjustedSigma = QString::number(m_adjustedSigmas[i], 'f', 8);
+ sigma = (IsSpecial(m_aprioriSigmas[i]) ? "FREE" : toString(m_aprioriSigmas[i], 8));
+
+ sprintf(buf,"%.11s", parameterNamesList.at(i).toStdString().c_str());
+ fpOut << buf;
+ sprintf(buf,"%18.8lf ", finalParameterValues[i] - correction);
+ fpOut << buf;
+ sprintf(buf,"%20.8lf ", correction);
+ fpOut << buf;
+ sprintf(buf,"%23.8lf ", finalParameterValues[i]);
+ fpOut << buf;
+ sprintf(buf," ");
+ fpOut << buf;
+ sprintf(buf,"%6s", sigma.toStdString().c_str());
+ fpOut << buf;
+ sprintf(buf," ");
+ fpOut << buf;
+ if (errorPropagation) {
+ sprintf(buf,"%s", adjustedSigma.toStdString().c_str());
+ }
+ else {
+ sprintf(buf, "%s","N/A");
+ }
+ fpOut << buf;
+ sprintf(buf," ");
+ fpOut << buf;
+ sprintf(buf,"%s\n", parameterUnitList.at(i).toStdString().c_str());
+ fpOut << buf;
+
+ }
+ }
+
+ /**
+ * @brief Creates and returns a formatted QString representing the bundle coefficients and
+ * parameters in csv format.
+ *
+ * @param errorPropagation Boolean indicating whether or not to attach more information
+ * (corrections, sigmas, adjusted sigmas...) to the output QString
+ *
+ * @return @b QString Returns a formatted QString representing the CsmBundleObservation in
+ * csv format
+ */
+ QString CsmBundleObservation::bundleOutputCSV(bool errorPropagation) {
+ QString finalqStr = "";
+ CSMCamera *csmCamera = dynamic_cast(front()->camera());
+
+ for (size_t i = 0; i < m_paramIndices.size(); i++) {
+ double finalValue = csmCamera->getParameterValue(m_paramIndices[i]);
+ finalqStr += toString(finalValue - m_corrections[i]) + ",";
+ finalqStr += toString(m_corrections[i]) + ",";
+ finalqStr += toString(finalValue) + ",";
+ finalqStr += toString(m_aprioriSigmas[i], 8) + ",";
+ if (errorPropagation) {
+ finalqStr += QString::number(m_adjustedSigmas[i], 'f', 8) + ",";
+ }
+ else {
+ finalqStr += "N/A,";
+ }
+ }
+
+ return finalqStr;
+ }
+
+
+ /**
+ * Returns the list of observation parameter names.
+ *
+ * This will always return at least one set of positions and pointings
+ * because we always output at least the center values even when not solving
+ * for them.
+ *
+ * @return @b QStringList List of observation parameter names
+ */
+ QStringList CsmBundleObservation::parameterList() {
+ QStringList paramList;
+ CSMCamera *csmCamera = dynamic_cast(front()->camera());
+
+ for (int paramIndex : m_paramIndices) {
+ paramList.push_back(csmCamera->getParameterName(paramIndex));
+ }
+
+ return paramList;
+ }
+
+ /**
+ * Cannot compute target body parameters for a CSM observation,
+ * so always throws an exception.
+ *
+ * @param coeffTarget Matrix for target body partial derivatives
+ * @param measure The measure that the partials are being
+ * computed for.
+ * @param bundleSettings The settings for the bundle adjustment
+ * @param bundleTargetBody QSharedPointer to the target body of
+ * the observation
+ *
+ * @return bool Always false
+ */
+ bool CsmBundleObservation::computeTargetPartials(LinearAlgebra::Matrix &coeffTarget, BundleMeasure &measure, BundleSettingsQsp &bundleSettings, BundleTargetBodyQsp &bundleTargetBody) {
+ if (bundleTargetBody) {
+ QString msg = "Target body parameters cannot be solved for with CSM observations.";
+ throw IException(IException::User, msg, _FILEINFO_);
+ }
+ return false;
+ }
+
+
+ /**
+ * Calculates the sensor partials with respect to the solve
+ * parameters and populates the coeffImage matrix.
+ *
+ * @param coeffImage A matrix that will be populated with the
+ * sensor partials with respect to the solve
+ * parameters.
+ * @param measure The measure that the partials are being
+ * computed for.
+ *
+ * @return bool
+ */
+ bool CsmBundleObservation::computeImagePartials(LinearAlgebra::Matrix &coeffImage, BundleMeasure &measure) {
+ coeffImage.clear();
+
+ CSMCamera *csmCamera = dynamic_cast(measure.camera());
+ SurfacePoint groundPoint = measure.parentControlPoint()->adjustedSurfacePoint();
+
+ // Loop over parameters and populate matrix
+ for (size_t i = 0; i < m_paramIndices.size(); i++) {
+ vector partials = csmCamera->getSensorPartials(m_paramIndices[i], groundPoint);
+ coeffImage(0, i) = partials[1];
+ coeffImage(1, i) = partials[0];
+ }
+
+ return true;
+ }
+
+
+ /**
+ * Calculates the ground partials for the line, sample currently
+ * set in the sensor model.
+ *
+ * @param coeffPoint3D A matrix that will be populated with the
+ * (line, sample) partials with respect to
+ * the ground point.
+ * @param measure The measure that the partials are being
+ * computed for.
+ * @param coordType Not used in this class. Coordinates are
+ * x,y,z
+ *
+ * @return bool
+ */
+ bool CsmBundleObservation::computePoint3DPartials(LinearAlgebra::Matrix &coeffPoint3D, BundleMeasure &measure, SurfacePoint::CoordinateType coordType) {
+ coeffPoint3D.clear();
+
+ CSMCamera *measureCamera = dynamic_cast(measure.camera());
+
+ // do ground partials
+ SurfacePoint groundPoint = measure.parentControlPoint()->adjustedSurfacePoint();
+ vector groundPartials = measureCamera->GroundPartials(groundPoint);
+
+ if (coordType == SurfacePoint::Rectangular) {
+ // groundPartials is:
+ // line WRT x
+ // line WRT y
+ // line WRT z
+ // sample WRT x
+ // sample WRT y
+ // sample WRT z
+ // Scale from WRT m to WRT Km
+ coeffPoint3D(1,0) = groundPartials[0] * 1000;
+ coeffPoint3D(1,1) = groundPartials[1] * 1000;
+ coeffPoint3D(1,2) = groundPartials[2] * 1000;
+ coeffPoint3D(0,0) = groundPartials[3] * 1000;
+ coeffPoint3D(0,1) = groundPartials[4] * 1000;
+ coeffPoint3D(0,2) = groundPartials[5] * 1000;
+ }
+ else if (coordType == SurfacePoint::Latitudinal) {
+ std::vector latDerivative = groundPoint.LatitudinalDerivative(SurfacePoint::One);
+ std::vector lonDerivative = groundPoint.LatitudinalDerivative(SurfacePoint::Two);
+ std::vector radDerivative = groundPoint.LatitudinalDerivative(SurfacePoint::Three);
+
+ // Line w.r.t (lat, lon, radius)
+ coeffPoint3D(1,0) = 1000 * (groundPartials[0]*latDerivative[0] + groundPartials[1]*latDerivative[1] + groundPartials[2]*latDerivative[2]);
+ coeffPoint3D(1,1) = 1000 * (groundPartials[0]*lonDerivative[0] + groundPartials[1]*lonDerivative[1] + groundPartials[2]*lonDerivative[2]);
+ coeffPoint3D(1,2) = 1000 * (groundPartials[0]*radDerivative[0] + groundPartials[1]*radDerivative[1] + groundPartials[2]*radDerivative[2]);
+
+ // Sample w.r.t (lat, lon, radius)
+ coeffPoint3D(0,0) = 1000 * (groundPartials[3]*latDerivative[0] + groundPartials[4]*latDerivative[1] + groundPartials[5]*latDerivative[2]);
+ coeffPoint3D(0,1) = 1000 * (groundPartials[3]*lonDerivative[0] + groundPartials[4]*lonDerivative[1] + groundPartials[5]*lonDerivative[2]);
+ coeffPoint3D(0,2) = 1000 * (groundPartials[3]*radDerivative[0] + groundPartials[4]*radDerivative[1] + groundPartials[5]*radDerivative[2]);
+ }
+ else {
+ IString msg ="Unknown surface point coordinate type enum [" + toString(coordType) + "]." ;
+ throw IException(IException::Programmer, msg, _FILEINFO_);
+ }
+ return true;
+ }
+
+
+ /**
+ * Calculates the sample, line residuals between the values
+ * measured in the image and the ground-to-image sample, line
+ * calculated by the sensor model.
+ *
+ * @param coeffRHS A vector that will contain the sample, line
+ * residuals.
+ * @param measure The measure that the partials are being
+ * computed for.
+ *
+ * @return bool
+ */
+ bool CsmBundleObservation::computeRHSPartials(LinearAlgebra::Vector &coeffRHS, BundleMeasure &measure) {
+ // Clear old values
+ coeffRHS.clear();
+
+ Camera *measureCamera = measure.camera();
+ BundleControlPoint* point = measure.parentControlPoint();
+
+ // Get ground-to-image computed coordinates for this point.
+ if (!(measureCamera->SetGround(point->adjustedSurfacePoint()))) {
+ QString msg = "Unable to map apriori surface point for measure ";
+ msg += measure.cubeSerialNumber() + " on point " + point->id() + " back into image.";
+ throw IException(IException::User, msg, _FILEINFO_);
+ }
+ double computedSample = measureCamera->Sample();
+ double computedLine = measureCamera->Line();
+
+ // The RHS is the difference between the measured coordinates on the image
+ // and the coordinates calculated by the ground to image call.
+ double deltaSample = measure.sample() - computedSample;
+ double deltaLine = measure.line() - computedLine;
+
+ coeffRHS(0) = deltaSample;
+ coeffRHS(1) = deltaLine;
+
+ return true;
+ }
+
+
+ /**
+ * Returns the observed value in (sample, line) coordinates.
+ * This requires no modification for Csm.
+ *
+ * @param measure measure The measure that the partials are
+ * being computed for.
+ * @param deltaVal The difference between the measured and
+ * calculate sample, line coordinates
+ *
+ * @return double The The difference between the measured and
+ * calculated (line, sample) coordinate
+ */
+ double CsmBundleObservation::computeObservationValue(BundleMeasure &measure, double deltaVal) {
+ return deltaVal;
+ }
+}
diff --git a/isis/src/control/objs/CsmBundleObservation/CsmBundleObservation.h b/isis/src/control/objs/CsmBundleObservation/CsmBundleObservation.h
new file mode 100644
index 0000000000000000000000000000000000000000..6952d0d5aa725ce2b857d8c91cf5efe2dd8a3050
--- /dev/null
+++ b/isis/src/control/objs/CsmBundleObservation/CsmBundleObservation.h
@@ -0,0 +1,78 @@
+#ifndef CsmBundleObservation_h
+#define CsmBundleObservation_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
+#include
+
+#include "BundleImage.h"
+#include "BundleObservationSolveSettings.h"
+#include "BundleTargetBody.h"
+#include "LinearAlgebra.h"
+#include "BundleObservation.h"
+
+namespace Isis {
+
+ /**
+ * Class for observations that use CSM camera models in bundle adjustment
+ *
+ * @ingroup ControlNetworks
+ */
+ class CsmBundleObservation : public BundleObservation {
+
+ public:
+ // default constructor
+ CsmBundleObservation();
+
+ // constructor
+ CsmBundleObservation(BundleImageQsp image, QString observationNumber, QString instrumentId,
+ BundleTargetBodyQsp bundleTargetBody);
+
+ // copy constructor
+ CsmBundleObservation(const CsmBundleObservation &src);
+
+ // destructor
+ ~CsmBundleObservation();
+
+ // equals operator
+ CsmBundleObservation &operator=(const CsmBundleObservation &src);
+
+ // copy method
+ void copy(const CsmBundleObservation &src);
+
+ virtual bool setSolveSettings(BundleObservationSolveSettings solveSettings);
+
+ int numberParameters();
+
+ const BundleObservationSolveSettingsQsp solveSettings();
+
+ bool applyParameterCorrections(LinearAlgebra::Vector corrections);
+
+ void bundleOutputString(std::ostream &fpOut,bool errorPropagation);
+ QString bundleOutputCSV(bool errorPropagation);
+
+ virtual QStringList parameterList();
+
+ bool computeTargetPartials(LinearAlgebra::Matrix &coeffTarget, BundleMeasure &measure, BundleSettingsQsp &bundleSettings, BundleTargetBodyQsp &bundleTargetBody);
+ bool computeImagePartials(LinearAlgebra::Matrix &coeffImage, BundleMeasure &measure);
+ bool computePoint3DPartials(LinearAlgebra::Matrix &coeffPoint3D, BundleMeasure &measure, SurfacePoint::CoordinateType coordType);
+ bool computeRHSPartials(LinearAlgebra::Vector &coeffRHS, BundleMeasure &measure);
+ double computeObservationValue(BundleMeasure &measure, double deltaVal);
+
+ private:
+ bool initParameterWeights();
+
+ private:
+ BundleObservationSolveSettingsQsp m_solveSettings; //!< Solve settings for this observation.
+ std::vector m_paramIndices; //!< The indices of the parameters the observation is solving for
+ };
+}
+
+#endif // CsmBundleObservation_h
diff --git a/isis/tests/BundleObservationSolveSettingsTests.cpp b/isis/tests/BundleObservationSolveSettingsTests.cpp
index 7c0e748fc9b4bfd5d6ac37b23c9eb3c6682983dd..d6e286ac4fcfca50d2762d8f871a95d2c3b886d3 100644
--- a/isis/tests/BundleObservationSolveSettingsTests.cpp
+++ b/isis/tests/BundleObservationSolveSettingsTests.cpp
@@ -24,6 +24,15 @@ QDomDocument saveToQDomDocument(BundleObservationSolveSettings &boss) {
}
+class CSMSolveOptionStrings : public testing::TestWithParam> {
+};
+class CSMSolveSetStrings : public testing::TestWithParam> {
+};
+class CSMSolveTypeStrings : public testing::TestWithParam> {
+};
class PointingSolveOptionStrings : public testing::TestWithParam> {
};
@@ -35,6 +44,10 @@ TEST(BundleObservationSolveSettings, DefaultConstructor) {
BundleObservationSolveSettings boss;
EXPECT_PRED_FORMAT2(AssertQStringsEqual, boss.instrumentId(), "");
+ EXPECT_EQ(boss.csmSolveOption(), BundleObservationSolveSettings::NoCSMParameters);
+ EXPECT_EQ(boss.csmParameterSet(), csm::param::ADJUSTABLE);
+ EXPECT_EQ(boss.csmParameterType(), csm::param::REAL);
+ EXPECT_TRUE(boss.csmParameterList().empty());
EXPECT_EQ(boss.instrumentPointingSolveOption(), BundleObservationSolveSettings::AnglesOnly);
EXPECT_EQ(boss.ckDegree(), 2);
EXPECT_EQ(boss.ckSolveDegree(), 2);
@@ -56,6 +69,10 @@ TEST(BundleObservationSolveSettings, CopyConstructor) {
BundleObservationSolveSettings copied(boss);
EXPECT_PRED_FORMAT2(AssertQStringsEqual, copied.instrumentId(), "");
+ EXPECT_EQ(copied.csmSolveOption(), BundleObservationSolveSettings::NoCSMParameters);
+ EXPECT_EQ(copied.csmParameterSet(), csm::param::ADJUSTABLE);
+ EXPECT_EQ(copied.csmParameterType(), csm::param::REAL);
+ EXPECT_TRUE(copied.csmParameterList().empty());
EXPECT_EQ(copied.instrumentPointingSolveOption(), BundleObservationSolveSettings::AnglesOnly);
EXPECT_EQ(copied.ckDegree(), 2);
EXPECT_EQ(copied.ckSolveDegree(), 2);
@@ -77,12 +94,15 @@ TEST(BundleObservationSolveSettings, PvlGroupConstructor) {
PvlKeyword camsolve("CamSolve");
PvlKeyword twist("Twist");
PvlKeyword spsolve("SPSolve");
+ PvlKeyword csmsolveset("CSMSOLVESET");
camsolve = "Angles";
twist = "yes";
spsolve = "None";
+ csmsolveset = "ADJUSTABLE";
settingsGroup += camsolve;
settingsGroup += twist;
settingsGroup += spsolve;
+ settingsGroup += csmsolveset;
BundleObservationSolveSettings boss(settingsGroup);
@@ -100,6 +120,48 @@ TEST(BundleObservationSolveSettings, PvlGroupConstructor) {
EXPECT_FALSE(boss.solvePositionOverHermite());
EXPECT_EQ(boss.positionInterpolationType(), SpiceRotation::PolyFunction);
EXPECT_TRUE(boss.aprioriPositionSigmas().isEmpty());
+ EXPECT_EQ(boss.csmSolveOption(), BundleObservationSolveSettings::Set);
+ EXPECT_EQ(boss.csmParameterSet(), csm::param::ADJUSTABLE);
+}
+
+TEST(BundleObservationSolveSettings, PvlGroupCSMTypeConstructor) {
+ PvlGroup settingsGroup("VO1/VISA");
+ PvlKeyword camsolve("CamSolve");
+ PvlKeyword spsolve("SPSolve");
+ PvlKeyword csmsolvetype("CSMSOLVETYPE");
+ camsolve = "None";
+ spsolve = "None";
+ csmsolvetype = "REAL";
+ settingsGroup += camsolve;
+ settingsGroup += spsolve;
+ settingsGroup += csmsolvetype;
+
+ BundleObservationSolveSettings boss(settingsGroup);
+
+ EXPECT_EQ(boss.csmSolveOption(), BundleObservationSolveSettings::Type);
+ EXPECT_EQ(boss.csmParameterType(), csm::param::REAL);
+}
+
+TEST(BundleObservationSolveSettings, PvlGroupCSMListConstructor) {
+ PvlGroup settingsGroup("VO1/VISA");
+ PvlKeyword camsolve("CamSolve");
+ PvlKeyword spsolve("SPSolve");
+ PvlKeyword csmsolvelist("CSMSOLVELIST");
+ camsolve = "None";
+ spsolve = "None";
+ csmsolvelist += "Param 1";
+ csmsolvelist += "Param 2";
+ settingsGroup += camsolve;
+ settingsGroup += spsolve;
+ settingsGroup += csmsolvelist;
+
+ BundleObservationSolveSettings boss(settingsGroup);
+
+ EXPECT_EQ(boss.csmSolveOption(), BundleObservationSolveSettings::List);
+ QStringList csmParamList = boss.csmParameterList();
+ ASSERT_EQ(csmParamList.size(), 2);
+ EXPECT_EQ(csmParamList[0].toStdString(), "Param 1");
+ EXPECT_EQ(csmParamList[1].toStdString(), "Param 2");
}
TEST(BundleObservationSolveSettings, AssignmentOperator) {
@@ -259,6 +321,34 @@ TEST(BundleObservationSolveSettings, setInstrumentPositionSettingsPositionVeloci
EXPECT_EQ(boss.aprioriPositionSigmas().at(2), Isis::Null);
}
+TEST(BundleObservationSolveSettings, setCsmSolveType) {
+ BundleObservationSolveSettings boss;
+ boss.setCSMSolveSet(csm::param::VALID);
+
+ EXPECT_EQ(boss.csmSolveOption(), BundleObservationSolveSettings::Set);
+ EXPECT_EQ(boss.csmParameterSet(), csm::param::VALID);
+}
+
+TEST(BundleObservationSolveSettings, setCSMSolveType) {
+ BundleObservationSolveSettings boss;
+ boss.setCSMSolveType(csm::param::FICTITIOUS);
+
+ EXPECT_EQ(boss.csmSolveOption(), BundleObservationSolveSettings::Type);
+ EXPECT_EQ(boss.csmParameterType(), csm::param::FICTITIOUS);
+}
+
+TEST(BundleObservationSolveSettings, setCSMSolveParameterList) {
+ BundleObservationSolveSettings boss;
+ boss.setCSMSolveParameterList({"param1", "param2"});
+
+ QStringList parameterList = boss.csmParameterList();
+
+ EXPECT_EQ(boss.csmSolveOption(), BundleObservationSolveSettings::List);
+ ASSERT_EQ(parameterList.size(), 2);
+ EXPECT_EQ(parameterList[0].toStdString(), "param1");
+ EXPECT_EQ(parameterList[1].toStdString(), "param2");
+}
+
TEST(BundleObservationSolveSettings, SaveSettings){
BundleObservationSolveSettings boss;
QDomDocument settingsDoc = saveToQDomDocument(boss);
@@ -353,6 +443,36 @@ TEST(BundleObservationSolveSettings, SaveSettings){
aprioriPositionSigmas.namedItem("sigma").nodeValue(), "");
}
+TEST_P(CSMSolveOptionStrings, StringToOption) {
+ EXPECT_EQ(GetParam().first,
+ BundleObservationSolveSettings::stringToCSMSolveOption(GetParam().second));
+}
+
+TEST_P(CSMSolveOptionStrings, OptionToString) {
+ EXPECT_PRED_FORMAT2(AssertQStringsEqual, GetParam().second,
+ BundleObservationSolveSettings::csmSolveOptionToString(GetParam().first));
+}
+
+TEST_P(CSMSolveSetStrings, StringToOption) {
+ EXPECT_EQ(GetParam().first,
+ BundleObservationSolveSettings::stringToCSMSolveSet(GetParam().second));
+}
+
+TEST_P(CSMSolveSetStrings, OptionToString) {
+ EXPECT_PRED_FORMAT2(AssertQStringsEqual, GetParam().second,
+ BundleObservationSolveSettings::csmSolveSetToString(GetParam().first));
+}
+
+TEST_P(CSMSolveTypeStrings, StringToOption) {
+ EXPECT_EQ(GetParam().first,
+ BundleObservationSolveSettings::stringToCSMSolveType(GetParam().second));
+}
+
+TEST_P(CSMSolveTypeStrings, OptionToString) {
+ EXPECT_PRED_FORMAT2(AssertQStringsEqual, GetParam().second,
+ BundleObservationSolveSettings::csmSolveTypeToString(GetParam().first));
+}
+
TEST_P(PointingSolveOptionStrings, StringToOption) {
EXPECT_EQ(GetParam().first,
BundleObservationSolveSettings::stringToInstrumentPointingSolveOption(GetParam().second));
@@ -373,6 +493,23 @@ TEST_P(PositionSolveOptionStrings, OptionToString) {
BundleObservationSolveSettings::instrumentPositionSolveOptionToString(GetParam().first));
}
+INSTANTIATE_TEST_SUITE_P(BundleObservationSolveSettings, CSMSolveOptionStrings, ::testing::Values(
+ qMakePair(BundleObservationSolveSettings::NoCSMParameters, QString("NoCSMParameters")),
+ qMakePair(BundleObservationSolveSettings::Set, QString("Set")),
+ qMakePair(BundleObservationSolveSettings::Type, QString("Type")),
+ qMakePair(BundleObservationSolveSettings::List, QString("List"))));
+
+INSTANTIATE_TEST_SUITE_P(BundleObservationSolveSettings, CSMSolveSetStrings, ::testing::Values(
+ qMakePair(csm::param::VALID, QString("VALID")),
+ qMakePair(csm::param::ADJUSTABLE, QString("ADJUSTABLE")),
+ qMakePair(csm::param::NON_ADJUSTABLE, QString("NON_ADJUSTABLE"))));
+
+INSTANTIATE_TEST_SUITE_P(BundleObservationSolveSettings, CSMSolveTypeStrings, ::testing::Values(
+ qMakePair(csm::param::NONE, QString("NONE")),
+ qMakePair(csm::param::FICTITIOUS, QString("FICTITIOUS")),
+ qMakePair(csm::param::REAL, QString("REAL")),
+ qMakePair(csm::param::FIXED, QString("FIXED"))));
+
INSTANTIATE_TEST_SUITE_P(BundleObservationSolveSettings, PointingSolveOptionStrings, ::testing::Values(
qMakePair(BundleObservationSolveSettings::NoPointingFactors, QString("None")),
qMakePair(BundleObservationSolveSettings::AnglesOnly, QString("AnglesOnly")),
diff --git a/isis/tests/CSMCameraTests.cpp b/isis/tests/CSMCameraTests.cpp
index 5c3fedc3c86384087b51fd22cbc13abfe895fda8..1d57ef6025acdf132f5b70ca2c6243fb36ef7e9a 100644
--- a/isis/tests/CSMCameraTests.cpp
+++ b/isis/tests/CSMCameraTests.cpp
@@ -4,6 +4,7 @@
#include "csm/csm.h"
#include "csm/Ellipsoid.h"
+#include "CSMCamera.h"
#include "Fixtures.h"
#include "iTime.h"
#include "Latitude.h"
@@ -13,6 +14,8 @@
#include "TestUtilities.h"
#include "FileName.h"
#include "Fixtures.h"
+#include "SerialNumber.h"
+#include "SerialNumberList.h"
#include
using json = nlohmann::json;
@@ -41,6 +44,18 @@ TEST_F(CSMCameraFixture, SetImage) {
}
+TEST_F(CSMCameraFixture, SetImageNoIntersect) {
+ csm::Ellipsoid wgs84;
+ EXPECT_CALL(mockModel, imageToRemoteImagingLocus(MatchImageCoord(csm::ImageCoord(4.5, 4.5)), ::testing::_, ::testing::_, ::testing::_))
+ .Times(1)
+ // looking straight down X-Axis
+ .WillOnce(::testing::Return(csm::EcefLocus(wgs84.getSemiMajorRadius() + 50000, 0, 0, 0, 1, 0)));
+
+ EXPECT_FALSE(testCam->SetImage(5, 5));
+ EXPECT_THAT(testCam->lookDirectionBodyFixed(), ::testing::ElementsAre(0.0, 1.0, 0.0));
+}
+
+
TEST_F(CSMCameraDemFixture, SetImage) {
EXPECT_CALL(mockModel, imageToRemoteImagingLocus(MatchImageCoord(csm::ImageCoord(4.5, 4.5)), ::testing::_, ::testing::_, ::testing::_))
.Times(1)
@@ -250,6 +265,217 @@ TEST_F(CSMCameraSetFixture, EmissionAngle) {
}
+TEST_F(CSMCameraSetFixture, GroundPartials) {
+ std::vector expectedPartials = {1, 2, 3, 4, 5, 6};
+ EXPECT_CALL(mockModel, computeGroundPartials(MatchEcefCoord(groundPt)))
+ .Times(1)
+ .WillOnce(::testing::Return(expectedPartials));
+
+ std::vector groundPartials = dynamic_cast(testCam)->GroundPartials();
+ ASSERT_EQ(groundPartials.size(), 6);
+ EXPECT_EQ(groundPartials[0], expectedPartials[0]);
+ EXPECT_EQ(groundPartials[1], expectedPartials[1]);
+ EXPECT_EQ(groundPartials[2], expectedPartials[2]);
+ EXPECT_EQ(groundPartials[3], expectedPartials[3]);
+ EXPECT_EQ(groundPartials[4], expectedPartials[4]);
+ EXPECT_EQ(groundPartials[5], expectedPartials[5]);
+}
+
+
+TEST_F(CSMCameraSetFixture, SensorPartials) {
+ std::pair expectedPartials = {1.23, -5.43};
+ EXPECT_CALL(mockModel, computeSensorPartials(1, MatchEcefCoord(groundPt), 0.001, NULL, NULL))
+ .Times(1)
+ .WillOnce(::testing::Return(expectedPartials));
+
+ std::vector groundPartials =
+ dynamic_cast(testCam)->getSensorPartials(1, testCam->GetSurfacePoint());
+ ASSERT_EQ(groundPartials.size(), 2);
+ EXPECT_EQ(groundPartials[0], expectedPartials.first);
+ EXPECT_EQ(groundPartials[1], expectedPartials.second);
+}
+
+
+TEST_F(CSMCameraFixture, getParameterIndicesSet) {
+ std::vector paramIndices = {0, 1, 2};
+ EXPECT_CALL(mockModel, getNumParameters())
+ .WillRepeatedly(::testing::Return(3));
+ EXPECT_CALL(mockModel, getParameterType(0))
+ .WillRepeatedly(::testing::Return(csm::param::REAL));
+ EXPECT_CALL(mockModel, getParameterType(1))
+ .WillRepeatedly(::testing::Return(csm::param::REAL));
+ EXPECT_CALL(mockModel, getParameterType(2))
+ .WillRepeatedly(::testing::Return(csm::param::REAL));
+
+ std::vector indices = dynamic_cast(testCam)->getParameterIndices(csm::param::ADJUSTABLE);
+ ASSERT_EQ(indices.size(), paramIndices.size());
+ for (size_t i = 0; i < paramIndices.size(); i++) {
+ EXPECT_EQ(indices[i], paramIndices[i]) << "Error at index " << i;
+ }
+}
+
+
+TEST_F(CSMCameraFixture, getParameterIndicesType) {
+ std::vector paramIndices = {1, 2};
+ EXPECT_CALL(mockModel, getNumParameters())
+ .WillRepeatedly(::testing::Return(3));
+ EXPECT_CALL(mockModel, getParameterType(0))
+ .WillRepeatedly(::testing::Return(csm::param::FIXED));
+ EXPECT_CALL(mockModel, getParameterType(1))
+ .WillRepeatedly(::testing::Return(csm::param::REAL));
+ EXPECT_CALL(mockModel, getParameterType(2))
+ .WillRepeatedly(::testing::Return(csm::param::REAL));
+
+ std::vector indices = dynamic_cast(testCam)->getParameterIndices(csm::param::REAL);
+ ASSERT_EQ(indices.size(), paramIndices.size());
+ for (size_t i = 0; i < paramIndices.size(); i++) {
+ EXPECT_EQ(indices[i], paramIndices[i]) << "Error at index " << i;
+ }
+}
+
+
+TEST_F(CSMCameraFixture, getParameterIndicesList) {
+ std::vector paramIndices = {2, 0};
+ EXPECT_CALL(mockModel, getNumParameters())
+ .WillRepeatedly(::testing::Return(3));
+ EXPECT_CALL(mockModel, getParameterName(0))
+ .WillRepeatedly(::testing::Return("Parameter 1"));
+ EXPECT_CALL(mockModel, getParameterName(1))
+ .WillRepeatedly(::testing::Return("Parameter 2"));
+ EXPECT_CALL(mockModel, getParameterName(2))
+ .WillRepeatedly(::testing::Return("Parameter 3"));
+
+ QStringList paramList = {"Parameter 3", "Parameter 1"};
+
+ std::vector indices = dynamic_cast(testCam)->getParameterIndices(paramList);
+ ASSERT_EQ(indices.size(), paramIndices.size());
+ for (size_t i = 0; i < paramIndices.size(); i++) {
+ EXPECT_EQ(indices[i], paramIndices[i]) << "Error at index " << i;
+ }
+}
+
+
+TEST_F(CSMCameraFixture, getParameterIndicesListComparison) {
+ std::vector paramIndices = {2, 0, 1};
+ EXPECT_CALL(mockModel, getNumParameters())
+ .WillRepeatedly(::testing::Return(3));
+ EXPECT_CALL(mockModel, getParameterName(0))
+ .WillRepeatedly(::testing::Return("Parameter 1 "));
+ EXPECT_CALL(mockModel, getParameterName(1))
+ .WillRepeatedly(::testing::Return(" Parameter 2"));
+ EXPECT_CALL(mockModel, getParameterName(2))
+ .WillRepeatedly(::testing::Return("Parameter 3"));
+
+ QStringList paramList = {"PARAMETER 3", " Parameter 1", "parameter 2 "};
+
+ std::vector indices = dynamic_cast(testCam)->getParameterIndices(paramList);
+ ASSERT_EQ(indices.size(), paramIndices.size());
+ for (size_t i = 0; i < paramIndices.size(); i++) {
+ EXPECT_EQ(indices[i], paramIndices[i]) << "Error at index " << i;
+ }
+}
+
+
+TEST_F(CSMCameraFixture, getParameterIndicesListError) {
+ std::vector paramIndices = {3, 1};
+ EXPECT_CALL(mockModel, getNumParameters())
+ .WillRepeatedly(::testing::Return(3));
+ EXPECT_CALL(mockModel, getParameterName(0))
+ .WillRepeatedly(::testing::Return("Parameter 1"));
+ EXPECT_CALL(mockModel, getParameterName(1))
+ .WillRepeatedly(::testing::Return("Parameter 2"));
+ EXPECT_CALL(mockModel, getParameterName(2))
+ .WillRepeatedly(::testing::Return("Parameter 3"));
+
+ QStringList paramList = {"Parameter 4", "Parameter 1", "Parameter 0"};
+
+ try
+ {
+ dynamic_cast(testCam)->getParameterIndices(paramList);
+ }
+ catch(Isis::IException &e)
+ {
+ EXPECT_TRUE(e.toString().toLatin1().contains("Failed to find indices for the following parameters ["
+ "Parameter 4,Parameter 0].")) << e.toString().toStdString();
+ }
+ catch(...)
+ {
+ FAIL() << "Expected an IException with message \""
+ "Failed to find indices for the following parameters [Parameter 4,Parameter 0].\"";
+ }
+}
+
+
+TEST_F(CSMCameraFixture, applyParameterCorrection) {
+ EXPECT_CALL(mockModel, getParameterValue(2))
+ .Times(1)
+ .WillOnce(::testing::Return(0.5));
+ EXPECT_CALL(mockModel, setParameterValue(2, 1.5))
+ .Times(1);
+
+ dynamic_cast(testCam)->applyParameterCorrection(2, 1.0);
+}
+
+
+TEST_F(CSMCameraFixture, getParameterCovariance) {
+ EXPECT_CALL(mockModel, getParameterCovariance(2, 3))
+ .Times(1)
+ .WillOnce(::testing::Return(0.5));
+
+ EXPECT_EQ(dynamic_cast(testCam)->getParameterCovariance(2, 3), 0.5);
+}
+
+
+TEST_F(CSMCameraFixture, getParameterName) {
+ EXPECT_CALL(mockModel, getParameterName(2))
+ .Times(1)
+ .WillOnce(::testing::Return("Omega Bias"));
+
+ EXPECT_EQ(dynamic_cast(testCam)->getParameterName(2), "Omega Bias");
+}
+
+
+TEST_F(CSMCameraFixture, getParameterValue) {
+ EXPECT_CALL(mockModel, getParameterValue(2))
+ .Times(1)
+ .WillOnce(::testing::Return(0.5));
+
+ EXPECT_DOUBLE_EQ(dynamic_cast(testCam)->getParameterValue(2), 0.5);
+}
+
+
+TEST_F(CSMCameraFixture, getParameterUnits) {
+ EXPECT_CALL(mockModel, getParameterUnits(2))
+ .Times(1)
+ .WillOnce(::testing::Return("m"));
+
+ EXPECT_EQ(dynamic_cast(testCam)->getParameterUnits(2), "m");
+}
+
+
+TEST_F(CSMCameraSetFixture, SerialNumber) {
+ QString sn = SerialNumber::Compose(*testCube);
+ SerialNumberList snl;
+
+ snl.add(testCube->fileName());
+ QString instId = snl.spacecraftInstrumentId(sn);
+
+ EXPECT_PRED_FORMAT2(AssertQStringsEqual, sn, "TestPlatform/TestInstrument/2000-01-01T11:58:55.816");
+ EXPECT_TRUE(snl.hasSerialNumber(sn));
+ EXPECT_PRED_FORMAT2(AssertQStringsEqual, instId, "TESTPLATFORM/TESTINSTRUMENT");
+}
+
+
+TEST_F(CSMCameraFixture, CameraState) {
+ std::string testString = "MockSensorModel\nTestModelState";
+ EXPECT_CALL(mockModel, getModelState())
+ .Times(1)
+ .WillOnce(::testing::Return(testString));
+
+ EXPECT_EQ(dynamic_cast(testCam)->getModelState().toStdString(), testString);
+}
+
+
TEST_F(CSMCameraFixture, SetTime) {
try
{
@@ -462,4 +688,4 @@ TEST_F(CSMCameraFixture, Declination) {
FAIL() << "Expected an IException with message \""
" Declination is not supported for CSM camera models\"";
}
-}
\ No newline at end of file
+}
diff --git a/isis/tests/CsmBundleObservationTests.cpp b/isis/tests/CsmBundleObservationTests.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..7c4468730b774838e6c9ee39665133a7031cee8d
--- /dev/null
+++ b/isis/tests/CsmBundleObservationTests.cpp
@@ -0,0 +1,341 @@
+#include
+#include
+#include
+
+#include "CsmBundleObservation.h"
+#include "CSMCamera.h"
+#include "Fixtures.h"
+#include "MockCsmPlugin.h"
+#include "Mocks.h"
+#include "TestUtilities.h"
+#include "SerialNumber.h"
+#include "BundleControlPoint.h"
+#include "BundleImage.h"
+#include "BundleTargetBody.h"
+
+
+#include "gmock/gmock.h"
+
+
+using namespace Isis;
+
+TEST_F(CSMCameraFixture, CsmBundleOutputString) {
+ EXPECT_CALL(mockModel, getNumParameters())
+ .WillRepeatedly(::testing::Return(3));
+ EXPECT_CALL(mockModel, getParameterType(0))
+ .WillRepeatedly(::testing::Return(csm::param::REAL));
+ EXPECT_CALL(mockModel, getParameterType(1))
+ .WillRepeatedly(::testing::Return(csm::param::REAL));
+ EXPECT_CALL(mockModel, getParameterType(2))
+ .WillRepeatedly(::testing::Return(csm::param::REAL));
+ EXPECT_CALL(mockModel, getParameterName(0))
+ .WillRepeatedly(::testing::Return("Parameter 1"));
+ EXPECT_CALL(mockModel, getParameterName(1))
+ .WillRepeatedly(::testing::Return("Parameter 2"));
+ EXPECT_CALL(mockModel, getParameterName(2))
+ .WillRepeatedly(::testing::Return("Parameter 3"));
+ EXPECT_CALL(mockModel, getParameterUnits(0))
+ .WillRepeatedly(::testing::Return("m"));
+ EXPECT_CALL(mockModel, getParameterUnits(1))
+ .WillRepeatedly(::testing::Return("sec"));
+ EXPECT_CALL(mockModel, getParameterUnits(2))
+ .WillRepeatedly(::testing::Return("cm"));
+ EXPECT_CALL(mockModel, getParameterValue(0))
+ .WillRepeatedly(::testing::Return(234.2));
+ EXPECT_CALL(mockModel, getParameterValue(1))
+ .WillRepeatedly(::testing::Return(0.0));
+ EXPECT_CALL(mockModel, getParameterValue(2))
+ .WillRepeatedly(::testing::Return(M_PI));
+ EXPECT_CALL(mockModel, getParameterCovariance(0, 0))
+ .WillRepeatedly(::testing::Return(0.112));
+ EXPECT_CALL(mockModel, getParameterCovariance(1, 1))
+ .WillRepeatedly(::testing::Return(0.0123));
+ EXPECT_CALL(mockModel, getParameterCovariance(2, 2))
+ .WillRepeatedly(::testing::Return(0.342));
+
+ std::stringstream fpOut;
+
+ QString sn = SerialNumber::Compose(*testCube);
+
+ BundleImageQsp bi = BundleImageQsp(new BundleImage(testCam, sn, testCube->fileName()));
+ BundleObservationSolveSettings bundleSolSetting;
+
+ bundleSolSetting.setCSMSolveSet(csm::param::ADJUSTABLE);
+
+ CsmBundleObservation observation(bi,
+ "ObservationNumber",
+ "InstrumentId",
+ nullptr);
+
+ EXPECT_TRUE(observation.setSolveSettings(bundleSolSetting));
+ observation.bundleOutputString(fpOut, false);
+
+ QStringList lines = QString::fromStdString(fpOut.str()).split("\n");
+ EXPECT_EQ(lines[0].toStdString(),
+ "Parameter 1 234.20000000 0.00000000 234.20000000 0.112 N/A m");
+ EXPECT_EQ(lines[1].toStdString(),
+ "Parameter 2 0.00000000 0.00000000 0.00000000 0.0123 N/A sec");
+ EXPECT_EQ(lines[2].toStdString(),
+ "Parameter 3 3.14159265 0.00000000 3.14159265 0.342 N/A cm");
+}
+
+
+TEST_F(CSMCameraFixture, CsmBundleOutputCSVString) {
+ EXPECT_CALL(mockModel, getNumParameters())
+ .WillRepeatedly(::testing::Return(3));
+ EXPECT_CALL(mockModel, getParameterType(0))
+ .WillRepeatedly(::testing::Return(csm::param::REAL));
+ EXPECT_CALL(mockModel, getParameterType(1))
+ .WillRepeatedly(::testing::Return(csm::param::REAL));
+ EXPECT_CALL(mockModel, getParameterType(2))
+ .WillRepeatedly(::testing::Return(csm::param::REAL));
+ EXPECT_CALL(mockModel, getParameterName(0))
+ .WillRepeatedly(::testing::Return("Parameter 1"));
+ EXPECT_CALL(mockModel, getParameterName(1))
+ .WillRepeatedly(::testing::Return("Parameter 2"));
+ EXPECT_CALL(mockModel, getParameterName(2))
+ .WillRepeatedly(::testing::Return("Parameter 3"));
+ EXPECT_CALL(mockModel, getParameterUnits(0))
+ .WillRepeatedly(::testing::Return("m"));
+ EXPECT_CALL(mockModel, getParameterUnits(1))
+ .WillRepeatedly(::testing::Return("sec"));
+ EXPECT_CALL(mockModel, getParameterUnits(2))
+ .WillRepeatedly(::testing::Return("cm"));
+ EXPECT_CALL(mockModel, getParameterValue(0))
+ .WillRepeatedly(::testing::Return(234.2));
+ EXPECT_CALL(mockModel, getParameterValue(1))
+ .WillRepeatedly(::testing::Return(0.0));
+ EXPECT_CALL(mockModel, getParameterValue(2))
+ .WillRepeatedly(::testing::Return(100.0));
+ EXPECT_CALL(mockModel, getParameterCovariance(0, 0))
+ .WillRepeatedly(::testing::Return(0.112));
+ EXPECT_CALL(mockModel, getParameterCovariance(1, 1))
+ .WillRepeatedly(::testing::Return(0.0123));
+ EXPECT_CALL(mockModel, getParameterCovariance(2, 2))
+ .WillRepeatedly(::testing::Return(0.342));
+
+ QString sn = SerialNumber::Compose(*testCube);
+
+ BundleImageQsp bi = BundleImageQsp(new BundleImage(testCam, sn, testCube->fileName()));
+ BundleObservationSolveSettings bundleSolSetting;
+
+ bundleSolSetting.setCSMSolveSet(csm::param::ADJUSTABLE);
+
+ CsmBundleObservation observation(bi,
+ "ObservationNumber",
+ "InstrumentId",
+ nullptr);
+
+ EXPECT_TRUE(observation.setSolveSettings(bundleSolSetting));
+ QString csvString = observation.bundleOutputCSV(false);
+ EXPECT_EQ(csvString.toStdString(),
+ "234.2,0.0,234.2,0.112,N/A,"
+ "0.0,0.0,0.0,0.0123,N/A,"
+ "100.0,0.0,100.0,0.342,N/A,");
+
+ csvString = observation.bundleOutputCSV(true);
+ EXPECT_FALSE(csvString.contains("N/A"));
+}
+
+
+TEST_F(CSMCameraFixture, CsmBundleSetSolveSettings) {
+ EXPECT_CALL(mockModel, getNumParameters())
+ .WillRepeatedly(::testing::Return(3));
+ EXPECT_CALL(mockModel, getParameterType(0))
+ .WillRepeatedly(::testing::Return(csm::param::FICTITIOUS));
+ EXPECT_CALL(mockModel, getParameterType(1))
+ .WillRepeatedly(::testing::Return(csm::param::FIXED));
+ EXPECT_CALL(mockModel, getParameterType(2))
+ .WillRepeatedly(::testing::Return(csm::param::REAL));
+ EXPECT_CALL(mockModel, getParameterName(0))
+ .WillRepeatedly(::testing::Return("Parameter 1"));
+ EXPECT_CALL(mockModel, getParameterName(1))
+ .WillRepeatedly(::testing::Return("Parameter 2"));
+ EXPECT_CALL(mockModel, getParameterName(2))
+ .WillRepeatedly(::testing::Return("Parameter 3"));
+ EXPECT_CALL(mockModel, getParameterCovariance(0, 0))
+ .WillRepeatedly(::testing::Return(0.112));
+ EXPECT_CALL(mockModel, getParameterCovariance(1, 1))
+ .WillRepeatedly(::testing::Return(0.0123));
+ EXPECT_CALL(mockModel, getParameterCovariance(2, 2))
+ .WillRepeatedly(::testing::Return(0.342));
+
+
+ QString sn = SerialNumber::Compose(*testCube);
+
+ BundleImageQsp bi = BundleImageQsp(new BundleImage(testCam, sn, testCube->fileName()));
+ BundleObservationSolveSettings bundleSolSetting;
+
+ CsmBundleObservation observation(bi,
+ "ObservationNumber",
+ "InstrumentId",
+ nullptr);
+
+ QStringList paramList;
+
+ bundleSolSetting.setCSMSolveSet(csm::param::ADJUSTABLE);
+
+ ASSERT_TRUE(observation.setSolveSettings(bundleSolSetting));
+ ASSERT_EQ(observation.numberParameters(), 2);
+ paramList = observation.parameterList();
+ ASSERT_EQ(paramList.size(), 2);
+ EXPECT_EQ(paramList[0].toStdString(), "Parameter 1");
+ EXPECT_EQ(paramList[1].toStdString(), "Parameter 3");
+
+ bundleSolSetting.setCSMSolveType(csm::param::FIXED);
+
+ ASSERT_TRUE(observation.setSolveSettings(bundleSolSetting));
+ ASSERT_EQ(observation.numberParameters(), 1);
+ paramList = observation.parameterList();
+ ASSERT_EQ(paramList.size(), 1);
+ EXPECT_EQ(paramList[0].toStdString(), "Parameter 2");
+
+ paramList.clear();
+ paramList.push_back("Parameter 2");
+ paramList.push_back("Parameter 3");
+ bundleSolSetting.setCSMSolveParameterList(paramList);
+
+ ASSERT_TRUE(observation.setSolveSettings(bundleSolSetting));
+ ASSERT_EQ(observation.numberParameters(), 2);
+ paramList = observation.parameterList();
+ ASSERT_EQ(paramList.size(), 2);
+ EXPECT_EQ(paramList[0].toStdString(), "Parameter 2");
+ EXPECT_EQ(paramList[1].toStdString(), "Parameter 3");
+}
+
+
+TEST_F(CSMCameraFixture, CsmBundleApplyParameterCorrections) {
+ EXPECT_CALL(mockModel, getNumParameters())
+ .WillRepeatedly(::testing::Return(3));
+ EXPECT_CALL(mockModel, getParameterType(0))
+ .WillRepeatedly(::testing::Return(csm::param::FICTITIOUS));
+ EXPECT_CALL(mockModel, getParameterType(1))
+ .WillRepeatedly(::testing::Return(csm::param::FIXED));
+ EXPECT_CALL(mockModel, getParameterType(2))
+ .WillRepeatedly(::testing::Return(csm::param::REAL));
+ EXPECT_CALL(mockModel, getParameterName(0))
+ .WillRepeatedly(::testing::Return("Parameter 1"));
+ EXPECT_CALL(mockModel, getParameterName(1))
+ .WillRepeatedly(::testing::Return("Parameter 2"));
+ EXPECT_CALL(mockModel, getParameterName(2))
+ .WillRepeatedly(::testing::Return("Parameter 3"));
+ EXPECT_CALL(mockModel, getParameterCovariance(0, 0))
+ .WillRepeatedly(::testing::Return(0.112));
+ EXPECT_CALL(mockModel, getParameterCovariance(1, 1))
+ .WillRepeatedly(::testing::Return(0.0123));
+ EXPECT_CALL(mockModel, getParameterCovariance(2, 2))
+ .WillRepeatedly(::testing::Return(0.342));
+ EXPECT_CALL(mockModel, getParameterValue(0))
+ .WillRepeatedly(::testing::Return(234.2));
+ EXPECT_CALL(mockModel, getParameterValue(1))
+ .WillRepeatedly(::testing::Return(0.0));
+ EXPECT_CALL(mockModel, getParameterValue(2))
+ .WillRepeatedly(::testing::Return(100.0));
+ EXPECT_CALL(mockModel, setParameterValue(0, 235.2))
+ .Times(1);
+ EXPECT_CALL(mockModel, setParameterValue(2, 110.0))
+ .Times(1);
+
+
+ QString sn = SerialNumber::Compose(*testCube);
+
+ BundleImageQsp bi = BundleImageQsp(new BundleImage(testCam, sn, testCube->fileName()));
+ BundleObservationSolveSettings bundleSolSetting;
+
+ CsmBundleObservation observation(bi,
+ "ObservationNumber",
+ "InstrumentId",
+ nullptr);
+
+ QStringList paramList;
+
+ bundleSolSetting.setCSMSolveSet(csm::param::ADJUSTABLE);
+
+ ASSERT_TRUE(observation.setSolveSettings(bundleSolSetting));
+
+ LinearAlgebra::Vector corrections(2);
+ corrections[0] = 1.0;
+ corrections[1] = 10.0;
+
+ ASSERT_TRUE(observation.applyParameterCorrections(corrections));
+}
+
+
+TEST_F(CSMCameraFixture, CsmBundleComputePoint3DPartials) {
+ EXPECT_CALL(mockModel, getNumParameters())
+ .WillRepeatedly(::testing::Return(3));
+ EXPECT_CALL(mockModel, getParameterType(0))
+ .WillRepeatedly(::testing::Return(csm::param::FICTITIOUS));
+ EXPECT_CALL(mockModel, getParameterType(1))
+ .WillRepeatedly(::testing::Return(csm::param::FIXED));
+ EXPECT_CALL(mockModel, getParameterType(2))
+ .WillRepeatedly(::testing::Return(csm::param::REAL));
+ EXPECT_CALL(mockModel, getParameterName(0))
+ .WillRepeatedly(::testing::Return("Parameter 1"));
+ EXPECT_CALL(mockModel, getParameterName(1))
+ .WillRepeatedly(::testing::Return("Parameter 2"));
+ EXPECT_CALL(mockModel, getParameterName(2))
+ .WillRepeatedly(::testing::Return("Parameter 3"));
+ EXPECT_CALL(mockModel, getParameterCovariance(0, 0))
+ .WillRepeatedly(::testing::Return(0.112));
+ EXPECT_CALL(mockModel, getParameterCovariance(1, 1))
+ .WillRepeatedly(::testing::Return(0.0123));
+ EXPECT_CALL(mockModel, getParameterCovariance(2, 2))
+ .WillRepeatedly(::testing::Return(0.342));
+ EXPECT_CALL(mockModel, computeGroundPartials)
+ .WillRepeatedly(::testing::Return(std::vector{1, 2, 3, 4, 5, 6}));
+
+
+ QString sn = SerialNumber::Compose(*testCube);
+
+ BundleImageQsp bi = BundleImageQsp(new BundleImage(testCam, sn, testCube->fileName()));
+ BundleObservationSolveSettings bundleSolSetting;
+
+ CsmBundleObservation observation(bi,
+ "ObservationNumber",
+ "InstrumentId",
+ nullptr);
+
+ QStringList paramList;
+
+ bundleSolSetting.setCSMSolveSet(csm::param::ADJUSTABLE);
+
+ ASSERT_TRUE(observation.setSolveSettings(bundleSolSetting));
+
+ BundleSettingsQsp testBundleSettings(new BundleSettings());
+
+ SurfacePoint testSurfacePoint(Displacement(1000.0, Displacement::Kilometers),
+ Displacement(0.0, Displacement::Kilometers),
+ Displacement(0.0, Displacement::Kilometers));
+
+ ControlPoint testPoint("testPoint");
+ testPoint.SetAdjustedSurfacePoint(testSurfacePoint);
+
+ ControlMeasure *testMeasure = new ControlMeasure();
+ testMeasure->SetCubeSerialNumber(sn);
+ testMeasure->SetCamera(testCam);
+ testPoint.Add(testMeasure);
+
+ BundleControlPointQsp testBundlePoint(new BundleControlPoint(testBundleSettings, &testPoint));
+ BundleMeasureQsp testBundleMeasure = testBundlePoint->front();
+
+ LinearAlgebra::Matrix coeffPoint3D(2, 3);
+
+ ASSERT_TRUE(observation.computePoint3DPartials(coeffPoint3D, *testBundleMeasure, SurfacePoint::Rectangular));
+
+ EXPECT_EQ(coeffPoint3D(0,0), 4000);
+ EXPECT_EQ(coeffPoint3D(0,1), 5000);
+ EXPECT_EQ(coeffPoint3D(0,2), 6000);
+ EXPECT_EQ(coeffPoint3D(1,0), 1000);
+ EXPECT_EQ(coeffPoint3D(1,1), 2000);
+ EXPECT_EQ(coeffPoint3D(1,2), 3000);
+
+ ASSERT_TRUE(observation.computePoint3DPartials(coeffPoint3D, *testBundleMeasure, SurfacePoint::Latitudinal));
+
+ EXPECT_EQ(coeffPoint3D(0,0), 6000000);
+ EXPECT_EQ(coeffPoint3D(0,1), 5000000);
+ EXPECT_EQ(coeffPoint3D(0,2), 4000);
+ EXPECT_EQ(coeffPoint3D(1,0), 3000000);
+ EXPECT_EQ(coeffPoint3D(1,1), 2000000);
+ EXPECT_EQ(coeffPoint3D(1,2), 1000);
+}
\ No newline at end of file
diff --git a/isis/tests/Fixtures.cpp b/isis/tests/Fixtures.cpp
index 0a8247911d8f616a01f6fe646079f5a63f42e670..6fa52ac81857bd0fe69a3c8582c0397e5d557283 100644
--- a/isis/tests/Fixtures.cpp
+++ b/isis/tests/Fixtures.cpp
@@ -5,6 +5,7 @@
#include "FileName.h"
#include "Blob.h"
+#include "csminit.h"
#include "Fixtures.h"
#include "Portal.h"
#include "LineManager.h"
@@ -185,7 +186,7 @@ namespace Isis {
int v_lineNum = 0;
for(v_line.begin(); !v_line.end(); v_line++) {
for(int i = 0; i < v_line.size(); i++) {
- if(i == 4) {
+ if(i == 4) {
v_line[i] = NULL8;
}
else {
@@ -210,7 +211,7 @@ namespace Isis {
int b_lineNum = 0;
for(b_line.begin(); !b_line.end(); b_line++) {
for(int i = 0; i < b_line.size(); i++) {
- if( b_lineNum == 22 ) {
+ if( b_lineNum == 22 ) {
b_line[i] = NULL8;
}
else {
@@ -1389,6 +1390,7 @@ namespace Isis {
testCube.reset();
}
+
void NullPixelCube::SetUp() {
TempTestingFiles::SetUp();
@@ -1406,6 +1408,7 @@ namespace Isis {
}
}
+
void NullPixelCube::TearDown() {
if (testCube->isOpen()) {
testCube->close();
@@ -1416,4 +1419,135 @@ namespace Isis {
}
}
+
+ void MiniRFNetwork::SetUp() {
+ TempTestingFiles::SetUp();
+
+ testCube1 = new Cube("data/miniRFImage/LSZ_00455_1CD_XKU_87S324_V1_S1_Null.crop.cub");
+ testCube2 = new Cube("data/miniRFImage/LSZ_00457_1CD_XKU_87S321_V1_S1_Null.crop.cub");
+ testCube3 = new Cube("data/miniRFImage/LSZ_00459_1CD_XKU_88S327_V1_S1_Null.crop.cub");
+
+ cubeList = new FileList();
+
+ cubeList->append(testCube1->fileName());
+ cubeList->append(testCube2->fileName());
+ cubeList->append(testCube3->fileName());
+
+
+ cubeListFile = tempDir.path() + "/cubes.lis";
+ cubeList->write(cubeListFile);
+
+ network = new ControlNet("data/miniRFImage/Cabeus_Orbit400_withSS_AprioriPts.net");
+ controlNetPath = tempDir.path() + "/miniRFNet.net";
+ network->Write(controlNetPath);
+ }
+
+ void MiniRFNetwork::TearDown() {
+ if (testCube1->isOpen()) {
+ testCube1->close();
+ }
+ delete testCube1;
+ if (testCube2->isOpen()) {
+ testCube2->close();
+ }
+ delete testCube2;
+ if (testCube3->isOpen()) {
+ testCube3->close();
+ }
+ delete testCube3;
+
+ if (cubeList) {
+ delete cubeList;
+ }
+ }
+
+ void VikThmNetwork::SetUp() {
+ TempTestingFiles::SetUp();
+
+ testCube1 = new Cube("data/vikingThemisNetwork/F704b51.lev1_slo_crop.cub");
+ testCube2 = new Cube("data/vikingThemisNetwork/F857a32.lev1_slo_crop.cub");
+ testCube3 = new Cube("data/vikingThemisNetwork/I28234014RDR_crop.cub");
+ testCube4 = new Cube("data/vikingThemisNetwork/I52634011RDR_crop.cub");
+
+ cubeList = new FileList();
+
+ cubeList->append(testCube1->fileName());
+ cubeList->append(testCube2->fileName());
+ cubeList->append(testCube3->fileName());
+ cubeList->append(testCube4->fileName());
+
+
+ cubeListFile = tempDir.path() + "/cubes.lis";
+ cubeList->write(cubeListFile);
+
+ network = new ControlNet("data/vikingThemisNetwork/themis_dayir_VO_arcadia_extract_hand.net");
+ controlNetPath = tempDir.path() + "/vikThmNet.net";
+ network->Write(controlNetPath);
+ }
+
+ void VikThmNetwork::TearDown() {
+ if (testCube1->isOpen()) {
+ testCube1->close();
+ }
+ delete testCube1;
+ if (testCube2->isOpen()) {
+ testCube2->close();
+ }
+ delete testCube2;
+ if (testCube3->isOpen()) {
+ testCube3->close();
+ }
+ delete testCube3;
+ if (testCube4->isOpen()) {
+ testCube4->close();
+ }
+ delete testCube4;
+
+ if (cubeList) {
+ delete cubeList;
+ }
+ }
+
+ void CSMNetwork::SetUp(){
+ QString APP_XML = FileName("$ISISROOT/bin/xml/csminit.xml").expanded();
+ QVector fNames = {"/Test_A", "/Test_B",
+ "/Test_C", "/Test_D",
+ "/Test_E", "/Test_F",
+ "/Test_G", "/Test_H",
+ "/Test_I", "/Test_J"
+ };
+
+ cubes.fill(nullptr, 10);
+
+ cubeList = new FileList();
+ cubeListFile = tempDir.path() + "/cubes.lis";
+ // Create CSMInit-ed cubes
+ for (int i = 0; i < cubes.size() ; i++){
+ cubes[i] = new Cube();
+ cubes[i]->setDimensions(1024,1024,1);
+ FileName cubName = FileName(tempDir.path()+fNames[i]+".cub");
+ cubes[i]->create(cubName.expanded());
+ cubeList->append(cubes[i]->fileName());
+ QVector args = {"from="+cubName.expanded(),
+ "state=data/CSMNetwork/"+fNames[i]+".json",
+ "modelname=TestCsmModel",
+ "pluginname=TestCsmPlugin"
+ };
+ UserInterface ui(APP_XML, args);
+ csminit(ui);
+ }
+ cubeList->write(cubeListFile);
+ }
+
+ void CSMNetwork::TearDown() {
+ for(int i = 0; i < cubes.size(); i++) {
+ if(cubes[i] && cubes[i]->isOpen()) {
+ delete cubes[i];
+ }
+ }
+
+ if (cubeList) {
+ delete cubeList;
+ }
+ }
}
diff --git a/isis/tests/Fixtures.h b/isis/tests/Fixtures.h
index 4f4cff40c21b46e8263ee8bfae1bcc724c6f4977..c73bc04581d35fc14cf536cb887d205965f6bc52 100644
--- a/isis/tests/Fixtures.h
+++ b/isis/tests/Fixtures.h
@@ -85,7 +85,6 @@ namespace Isis {
void TearDown() override;
};
-
class DefaultCube : public TempTestingFiles {
protected:
Cube *testCube;
@@ -316,9 +315,57 @@ class HistoryBlob : public TempTestingFiles {
void SetUp() override;
};
+
class NullPixelCube : public TempTestingFiles {
protected:
Cube *testCube;
+ void SetUp() override;
+ void TearDown() override;
+};
+
+
+class MiniRFNetwork : public TempTestingFiles {
+ protected:
+ Cube *testCube1;
+ Cube *testCube2;
+ Cube *testCube3;
+
+ FileList *cubeList;
+ QString cubeListFile;
+
+ ControlNet *network;
+ QString controlNetPath;
+
+ void SetUp() override;
+ void TearDown() override;
+};
+
+class VikThmNetwork : public TempTestingFiles {
+ protected:
+ Cube *testCube1;
+ Cube *testCube2;
+ Cube *testCube3;
+ Cube *testCube4;
+
+ FileList *cubeList;
+ QString cubeListFile;
+
+ ControlNet *network;
+ QString controlNetPath;
+
+ void SetUp() override;
+ void TearDown() override;
+};
+
+class CSMNetwork : public TempTestingFiles {
+ protected:
+
+ QVector stateStringFiles;
+ QVector labelFiles;
+ QVector cubes;
+
+ FileList *cubeList;
+ QString cubeListFile;
void SetUp() override;
void TearDown() override;
diff --git a/isis/tests/FunctionalTestsCsminit.cpp b/isis/tests/FunctionalTestsCsminit.cpp
index 9d64f3b17052bc3296b45720ccf64aeb1d72b997..c0caa763febd91d381065d39973cefe38bb6e314 100644
--- a/isis/tests/FunctionalTestsCsminit.cpp
+++ b/isis/tests/FunctionalTestsCsminit.cpp
@@ -36,9 +36,13 @@ class CSMPluginFixture : public TempTestingFiles {
// Create and populate test ISDs
json isd;
- isd["test_param_one"] = 1.0;
- isd["test_param_two"] = 2.0;
-
+ isd["reference_time"] = 0;
+ isd["center_latitude"] = 3.03125;
+ isd["center_longitude"] = -2.9375;
+ isd["scale"] = 240;
+ isd["center_longitude_sigma"] = 0.0645181963189456;
+ isd["center_latitude_sigma"] = 0.0645181963189456;
+ isd["scale_sigma"] = 8.25832912882503;
isdPath = tempDir.path() + "/default.json";
std::ofstream file(isdPath.toStdString());
file << isd;
@@ -118,16 +122,16 @@ TEST_F(CSMPluginFixture, CSMInitDefault) {
ASSERT_TRUE(infoGroup.hasKeyword("ReferenceTime"));
EXPECT_EQ(infoGroup["ReferenceTime"][0].toStdString(), model.getReferenceDateAndTime());
ASSERT_TRUE(infoGroup.hasKeyword("ModelParameterNames"));
- ASSERT_EQ(infoGroup["ModelParameterNames"].size(), 2);
+ ASSERT_EQ(infoGroup["ModelParameterNames"].size(), 3);
EXPECT_EQ(infoGroup["ModelParameterNames"][0].toStdString(), TestCsmModel::PARAM_NAMES[0]);
EXPECT_EQ(infoGroup["ModelParameterNames"][1].toStdString(), TestCsmModel::PARAM_NAMES[1]);
ASSERT_TRUE(infoGroup.hasKeyword("ModelParameterUnits"));
- ASSERT_EQ(infoGroup["ModelParameterUnits"].size(), 2);
+ ASSERT_EQ(infoGroup["ModelParameterUnits"].size(), 3);
EXPECT_EQ(infoGroup["ModelParameterUnits"][0].toStdString(), TestCsmModel::PARAM_UNITS[0]);
EXPECT_EQ(infoGroup["ModelParameterUnits"][1].toStdString(), TestCsmModel::PARAM_UNITS[1]);
ASSERT_TRUE(infoGroup.hasKeyword("ModelParameterTypes"));
- ASSERT_EQ(infoGroup["ModelParameterTypes"].size(), 2);
- EXPECT_EQ(infoGroup["ModelParameterTypes"][0].toStdString(), "FICTITIOUS");
+ ASSERT_EQ(infoGroup["ModelParameterTypes"].size(), 3);
+ EXPECT_EQ(infoGroup["ModelParameterTypes"][0].toStdString(), "REAL");
EXPECT_EQ(infoGroup["ModelParameterTypes"][1].toStdString(), "REAL");
// Check the Kernels group
@@ -291,9 +295,13 @@ TEST_F(CSMPluginFixture, CSMInitFails) {
TEST_F(DefaultCube, CSMInitSpiceCleanup) {
// Create an ISD
json isd;
- isd["test_param_one"] = 1.0;
- isd["test_param_two"] = 2.0;
-
+ isd["reference_time"] = 0;
+ isd["center_latitude"] = 3.03125;
+ isd["center_longitude"] = -2.9375;
+ isd["scale"] = 240;
+ isd["center_longitude_sigma"] = 0.0645181963189456;
+ isd["center_latitude_sigma"] = 0.0645181963189456;
+ isd["scale_sigma"] = 8.25832912882503;
QString isdPath = tempDir.path() + "/default.json";
std::ofstream file(isdPath.toStdString());
file << isd;
diff --git a/isis/tests/FunctionalTestsJigsaw.cpp b/isis/tests/FunctionalTestsJigsaw.cpp
index 2d9d9a9d74ada145b9c3667db98fcbb00fe4c50d..2e94d3ab73cdc46bea1e9523321dcb575c4c5b7a 100644
--- a/isis/tests/FunctionalTestsJigsaw.cpp
+++ b/isis/tests/FunctionalTestsJigsaw.cpp
@@ -9,6 +9,7 @@
#include "Latitude.h"
#include "Longitude.h"
#include "ControlPoint.h"
+#include "CSMCamera.h"
#include "jigsaw.h"
@@ -17,7 +18,7 @@
#include "gmock/gmock.h"
using namespace Isis;
-using namespace testing;
+using namespace testing;
static QString APP_XML = FileName("$ISISROOT/bin/xml/jigsaw.xml").expanded();
@@ -41,7 +42,7 @@ TEST_F(ApolloNetwork, FunctionalTestJigsawApollo) {
jigsaw(ui);
- // Test points.csv, images.csv, residuals.csv
+ // Test points.csv, images.csv, residuals.csv
QString pointsOutput = tempDir.path() + "/bundleout_points.csv";
QString imagesOutput = tempDir.path() + "/bundleout_images.csv";
@@ -69,7 +70,7 @@ TEST_F(ApolloNetwork, FunctionalTestJigsawApollo) {
csvLine = line.getRow(2);
compareCsvLine(csvLine, "Label,Status,Measures,Measures,RMS,(dd),(dd),(km),(m),(m),(m),(m),(m),(m),(km),(km),(km)");
- // Compare all of the values from the network against the values in the CSV
+ // Compare all of the values from the network against the values in the CSV
QList points = outputNet.GetPoints();
EXPECT_EQ(numRows-3, points.length());
@@ -78,7 +79,7 @@ TEST_F(ApolloNetwork, FunctionalTestJigsawApollo) {
for (int i=3; i < numRows; i++) {
csvLine = line.getRow(i);
EXPECT_NO_THROW({
- outputPoint = outputNet.GetPoint(csvLine[0]);
+ outputPoint = outputNet.GetPoint(csvLine[0]);
}) << "Point in points.csv file is not present in the output network.";
EXPECT_EQ(outputPoint->GetPointTypeString().toUpper().toStdString(), QString(csvLine[1]).toStdString());
EXPECT_EQ(outputPoint->GetNumMeasures() - outputPoint->GetNumberOfRejectedMeasures(), csvLine[2].toInt());
@@ -161,13 +162,13 @@ TEST_F(ApolloNetwork, FunctionalTestJigsawApollo) {
csvLine = line.getRow(2);
compareCsvLine(csvLine, "Label,Filename,Serial Number,(mm),(mm),(pixels),(pixels),(pixels),(pixels),(pixels),Rejected");
- // Check line/sample and residuals
+ // Check line/sample and residuals
// Check all measures
ControlMeasure* measure;
for (int i=3; i < numRows; i++) {
csvLine = line.getRow(i);
EXPECT_NO_THROW({
- outputPoint = outputNet.GetPoint(csvLine[0]);
+ outputPoint = outputNet.GetPoint(csvLine[0]);
}) << "Point in residuals.csv is not present in output network.";
EXPECT_NO_THROW({
measure = outputPoint->GetMeasure(csvLine[2]);
@@ -181,7 +182,7 @@ TEST_F(ApolloNetwork, FunctionalTestJigsawApollo) {
}
// Spot check a few measures for hard-coded values:
- compareCsvLine(line.getRow(14), "AS15_000031448,/tmp/qt_temp-l7wTTZ/cube1.cub,APOLLO15/METRIC/1971-07-31T14:00:53.547, -24.91466687, -8.24555718, 4109.77150653, 2450.19288272,-0.00343036, 0.70304341, 0.70305178", 2);
+ compareCsvLine(line.getRow(14), "AS15_000031448,/tmp/qt_temp-l7wTTZ/cube1.cub,APOLLO15/METRIC/1971-07-31T14:00:53.547, -24.91466687, -8.24555718, 4109.77150653, 2450.19288272,-0.00343036, 0.70304341, 0.70305178", 2);
compareCsvLine(line.getRow(142), "AS15_000032200,/tmp/qt_temp-l7wTTZ/cube2.cub,APOLLO15/METRIC/1971-07-31T14:01:16.947, -25.59176645, -10.57595225, 4143.71597937, 2333.56318790, -0.00372340, 0.48459237, 0.48460667", 2);
compareCsvLine(line.getRow(424), "AS15_000055094,/tmp/qt_temp-l7wTTZ/cube1.cub,APOLLO15/METRIC/1971-07-31T14:00:53.547, 20.35945982, 34.23830188, 1844.18431849, 4576.36730130, 0.00691810, -0.57578795, 0.57582951", 2);
@@ -235,17 +236,17 @@ TEST_F(ApolloNetwork, FunctionalTestJigsawBundleXYZ) {
QFile bundleFile(bundleoutPath);
- QString bundleOut;
+ QString bundleOut;
if (bundleFile.open(QIODevice::ReadOnly)) {
- bundleOut = bundleFile.read(bundleFile.size());
+ bundleOut = bundleFile.read(bundleFile.size());
}
- else {
+ else {
FAIL() << "Failed to open latlat_bundleout.txt" << std::endl;
}
bundleFile.close();
QStringList lines = bundleOut.split("\n");
- EXPECT_THAT(lines[24].toStdString(), HasSubstr("LATITUDINAL"));
+ EXPECT_THAT(lines[24].toStdString(), HasSubstr("LATITUDINAL"));
EXPECT_THAT(lines[57].toStdString(), HasSubstr("LATITUDE"));
EXPECT_THAT(lines[58].toStdString(), HasSubstr("LONGITUDE"));
EXPECT_THAT(lines[59].toStdString(), HasSubstr("RADIUS"));
@@ -336,9 +337,9 @@ TEST_F(ApolloNetwork, FunctionalTestJigsawBundleXYZ) {
QFile bundleFile2(bundleoutPath2);
QString bundleOut2;
if (bundleFile2.open(QIODevice::ReadOnly)) {
- bundleOut2 = bundleFile2.read(bundleFile2.size());
+ bundleOut2 = bundleFile2.read(bundleFile2.size());
}
- else {
+ else {
FAIL() << "Failed to open rectrect_bundleout.txt" << std::endl;
}
bundleFile2.close();
@@ -414,9 +415,9 @@ TEST_F(ApolloNetwork, FunctionalTestJigsawBundleXYZ) {
QFile bundleFile4(bundleoutPath4);
QString bundleOut4;
if (bundleFile4.open(QIODevice::ReadOnly)) {
- bundleOut4 = bundleFile4.read(bundleFile2.size());
+ bundleOut4 = bundleFile4.read(bundleFile2.size());
}
- else {
+ else {
FAIL() << "Failed to open rectrect_bundleout.txt" << std::endl;
}
bundleFile4.close();
@@ -434,7 +435,7 @@ TEST_F(ApolloNetwork, FunctionalTestJigsawBundleXYZ) {
EXPECT_THAT(lines[667].toStdString(), HasSubstr("BODY-FIXED-X"));
EXPECT_THAT(lines[668].toStdString(), HasSubstr("BODY-FIXED-Y"));
EXPECT_THAT(lines[669].toStdString(), HasSubstr("BODY-FIXED-Z"));
-
+
bundleFile4.close();
// Compare newtwork and images.csv against the latitude, latitude bundle
@@ -471,48 +472,48 @@ TEST_F(ApolloNetwork, FunctionalTestJigsawBundleXYZ) {
TEST_F(ObservationPair, FunctionalTestJigsawCamSolveAll) {
// delete to remove old camera for when cam is updated
delete cubeL;
- delete cubeR;
-
+ delete cubeR;
+
QTemporaryDir prefix;
QString outCnetFileName = prefix.path() + "/outTemp.net";
- QVector args = {"fromlist="+cubeListFile, "cnet="+cnetPath, "onet="+outCnetFileName,
- "observations=yes", "update=yes", "Cksolvedegree=3",
+ QVector args = {"fromlist="+cubeListFile, "cnet="+cnetPath, "onet="+outCnetFileName,
+ "observations=yes", "update=yes", "Cksolvedegree=3",
"Camsolve=all", "twist=no", "Spsolve=none", "Radius=no", "imagescsv=on", "file_prefix="+prefix.path()+"/"};
UserInterface options(APP_XML, args);
-
- Pvl log;
+
+ Pvl log;
try {
jigsaw(options, &log);
}
catch (IException &e) {
FAIL() << "Unable to bundle: " << e.what() << std::endl;
}
-
- // images were updated
+
+ // images were updated
cubeL = new Cube(cubeLPath, "r");
cubeR = new Cube(cubeRPath, "r");
-
+
ControlNet oNet;
oNet.ReadControl(outCnetFileName);
- EXPECT_NEAR(oNet.AverageResidual(), 0.123132, 0.00001);
+ EXPECT_NEAR(oNet.AverageResidual(), 0.123132, 0.00001);
EXPECT_NEAR(oNet.GetMaximumResidual(), 0.379967, 0.00001);
ASSERT_EQ(oNet.GetNumIgnoredMeasures(), 0);
ASSERT_EQ(oNet.GetNumValidPoints(), 46);
-
- QList points = oNet.GetPoints();
-
+
+ QList points = oNet.GetPoints();
+
Statistics xstats;
Statistics ystats;
Statistics zstats;
- for (int i = 0; i < points.size(); i++) {
+ for (int i = 0; i < points.size(); i++) {
xstats.AddData(points.at(i)->GetAdjustedSurfacePoint().GetX().kilometers());
ystats.AddData(points.at(i)->GetAdjustedSurfacePoint().GetY().kilometers());
zstats.AddData(points.at(i)->GetAdjustedSurfacePoint().GetZ().kilometers());
}
-
+
EXPECT_NEAR(xstats.Average(), 1556.64806314499741, 0.00001);
EXPECT_NEAR(xstats.StandardDeviation(), 10.663072757957551, 0.00001);
EXPECT_NEAR(xstats.Minimum(), 1540.43360835455860, 0.00001);
@@ -526,98 +527,107 @@ TEST_F(ObservationPair, FunctionalTestJigsawCamSolveAll) {
EXPECT_NEAR(zstats.Average(), 763.0309515939565, 0.00001);
EXPECT_NEAR(zstats.StandardDeviation(), 19.783664466904419, 0.00001);
EXPECT_NEAR(zstats.Minimum(), 728.82827218510067, 0.00001);
- EXPECT_NEAR(zstats.Maximum(), 793.9672179283682, 0.00001);
+ EXPECT_NEAR(zstats.Maximum(), 793.9672179283682, 0.00001);
- Camera *cam = cubeL->camera();
+ Camera *cam = cubeL->camera();
SpiceRotation *rot = cam->instrumentRotation();
- std::vector a1;
- std::vector a2;
+ std::vector a1;
+ std::vector a2;
std::vector a3;
- rot->GetPolynomial(a1, a2, a3);
-
+ rot->GetPolynomial(a1, a2, a3);
+
EXPECT_NEAR(a1.at(0), 2.16338, 0.0001);
EXPECT_NEAR(a1.at(1), -0.0264475, 0.0001);
EXPECT_NEAR(a1.at(2), 0.00469675, 0.0001);
EXPECT_NEAR(a1.at(3), 0.0210955, 0.0001);
-
+
EXPECT_NEAR(a2.at(0), 1.83011, 0.0001);
EXPECT_NEAR(a2.at(1), -0.0244244, 0.0001);
EXPECT_NEAR(a2.at(2), -0.00456569, 0.0001);
EXPECT_NEAR(a2.at(3), 0.00637157, 0.0001);
- QFile file(prefix.path() + "/bundleout_images.csv");
- if (!file.open(QIODevice::ReadOnly)) {
- FAIL() << file.errorString().toStdString();
+ QFile leftFile(prefix.path() + "/bundleout_images_LUNARRECONNAISSANCEORBITER_NACL.csv");
+ if (!leftFile.open(QIODevice::ReadOnly)) {
+ FAIL() << leftFile.errorString().toStdString();
}
-
- // skip the first two lines, we don't want to compare the header.
- file.readLine();
- file.readLine();
-
- QString line = file.readLine();
- QStringList elems = line.split(",");
-
+
+ // skip the first two lines, we don't want to compare the header.
+ leftFile.readLine();
+ leftFile.readLine();
+
+ QString line = leftFile.readLine();
+ QStringList elems = line.split(",");
+
// RA(t0) final
- EXPECT_NEAR(elems.at(21).toDouble(), 123.9524918, 0.00001);
+ EXPECT_NEAR(elems.at(21).toDouble(), 123.9524918, 0.00001);
// RA(t1) final
- EXPECT_NEAR(elems.at(26).toDouble(), -1.51532975, 0.00001);
+ EXPECT_NEAR(elems.at(26).toDouble(), -1.51532975, 0.00001);
// RA(t2) final
- EXPECT_NEAR(elems.at(31).toDouble(), 0.2691039, 0.00001);
+ EXPECT_NEAR(elems.at(31).toDouble(), 0.2691039, 0.00001);
// RA(t3) final
- EXPECT_NEAR(elems.at(36).toDouble(), 1.208684781, 0.00001);
+ EXPECT_NEAR(elems.at(36).toDouble(), 1.208684781, 0.00001);
// DEC(t0) final
- EXPECT_NEAR(elems.at(41).toDouble(), 104.8575294, 0.00001);
+ EXPECT_NEAR(elems.at(41).toDouble(), 104.8575294, 0.00001);
// DEC(t1) final
- EXPECT_NEAR(elems.at(46).toDouble(), -1.399416621, 0.00001);
+ EXPECT_NEAR(elems.at(46).toDouble(), -1.399416621, 0.00001);
// DEC(t2) final
- EXPECT_NEAR(elems.at(51).toDouble(), -0.26159502200533, 0.00001);
+ EXPECT_NEAR(elems.at(51).toDouble(), -0.26159502200533, 0.00001);
// DEC(t3) final
- EXPECT_NEAR(elems.at(56).toDouble(), 0.365064224, 0.00001);
-
-
- line = file.readLine();
- elems = line.split(",");
-
+ EXPECT_NEAR(elems.at(56).toDouble(), 0.365064224, 0.00001);
+
+
+ QFile rightFile(prefix.path() + "/bundleout_images_LUNARRECONNAISSANCEORBITER_NACR.csv");
+ if (!rightFile.open(QIODevice::ReadOnly)) {
+ FAIL() << rightFile.errorString().toStdString();
+ }
+
+ // skip the first two lines, we don't want to compare the header.
+ rightFile.readLine();
+ rightFile.readLine();
+
+ line = rightFile.readLine();
+ elems = line.split(",");
+
// RA(t0) final
- EXPECT_NEAR(elems.at(21).toDouble(), 121.4164029, 0.00001);
+ EXPECT_NEAR(elems.at(21).toDouble(), 121.4164029, 0.00001);
// RA(t1) final
- EXPECT_NEAR(elems.at(26).toDouble(), -1.510464718, 0.00001);
+ EXPECT_NEAR(elems.at(26).toDouble(), -1.510464718, 0.00001);
// RA(t2) final
- EXPECT_NEAR(elems.at(31).toDouble(), 0.253046705, 0.00001);
+ EXPECT_NEAR(elems.at(31).toDouble(), 0.253046705, 0.00001);
// RA(t3) final
- EXPECT_NEAR(elems.at(36).toDouble(), 1.203832854, 0.00001);
+ EXPECT_NEAR(elems.at(36).toDouble(), 1.203832854, 0.00001);
// DEC(t0) final
- EXPECT_NEAR(elems.at(41).toDouble(), 106.11241033284, 0.00001);
+ EXPECT_NEAR(elems.at(41).toDouble(), 106.11241033284, 0.00001);
// DEC(t1) final
- EXPECT_NEAR(elems.at(46).toDouble(), -1.4160602752902001, 0.00001);
+ EXPECT_NEAR(elems.at(46).toDouble(), -1.4160602752902001, 0.00001);
// DEC(t2) final
- EXPECT_NEAR(elems.at(51).toDouble(), -0.26704142, 0.00001);
+ EXPECT_NEAR(elems.at(51).toDouble(), -0.26704142, 0.00001);
// DEC(t3) final
- EXPECT_NEAR(elems.at(56).toDouble(), 0.365717165, 0.00001);
+ EXPECT_NEAR(elems.at(56).toDouble(), 0.365717165, 0.00001);
}
TEST_F(ApolloNetwork, FunctionalTestJigsawHeldList) {
QTemporaryDir prefix;
-
- QString heldlistpath = prefix.path() + "/heldlist.lis";
- FileList heldList;
+
+ QString heldlistpath = prefix.path() + "/heldlist.lis";
+ FileList heldList;
heldList.append(cubes[5]->fileName());
- heldList.write(heldlistpath);
+ heldList.write(heldlistpath);
QString outCnetFileName = prefix.path() + "/outTemp.net";
- QVector args = {"fromlist="+cubeListFile, "cnet="+controlNetPath, "onet="+outCnetFileName, "heldlist="+heldlistpath,
- "radius=yes", "errorpropagation=yes", "spsolve=position", "Spacecraft_position_sigma=1000",
- "Residuals_csv=off", "Camsolve=angles", "Twist=yes", "Camera_angles_sigma=2",
+ QVector args = {"fromlist="+cubeListFile, "cnet="+controlNetPath, "onet="+outCnetFileName, "heldlist="+heldlistpath,
+ "radius=yes", "errorpropagation=yes", "spsolve=position", "Spacecraft_position_sigma=1000",
+ "Residuals_csv=off", "Camsolve=angles", "Twist=yes", "Camera_angles_sigma=2",
"Output_csv=off", "imagescsv=on", "file_prefix="+prefix.path()+"/"};
UserInterface options(APP_XML, args);
-
- Pvl log;
-
+
+ Pvl log;
+
try {
jigsaw(options, &log);
}
@@ -631,35 +641,35 @@ TEST_F(ApolloNetwork, FunctionalTestJigsawHeldList) {
csvLine = header.getRow(7);
- // assert corrections are very small
+ // assert corrections are very small
// X Correction
- EXPECT_LE(std::abs(csvLine[5].toDouble()), 1e-10);
+ EXPECT_LE(std::abs(csvLine[5].toDouble()), 1e-10);
// Y Correction
- EXPECT_LE(std::abs(csvLine[10].toDouble()), 1e-10);
+ EXPECT_LE(std::abs(csvLine[10].toDouble()), 1e-10);
// Z Correction
- EXPECT_LE(std::abs(csvLine[15].toDouble()), 1e-10);
+ EXPECT_LE(std::abs(csvLine[15].toDouble()), 1e-10);
// RA Correction
- EXPECT_LE(std::abs(csvLine[20].toDouble()), 1e-10);
+ EXPECT_LE(std::abs(csvLine[20].toDouble()), 1e-10);
// DEC Correction
- EXPECT_LE(std::abs(csvLine[25].toDouble()), 1e-10);
+ EXPECT_LE(std::abs(csvLine[25].toDouble()), 1e-10);
// TWIST Correction
- EXPECT_LE(std::abs(csvLine[30].toDouble()), 1e-10);
+ EXPECT_LE(std::abs(csvLine[30].toDouble()), 1e-10);
}
TEST_F(ApolloNetwork, FunctionalTestJigsawOutlierRejection) {
QTemporaryDir prefix;
-
+
QString outCnetFileName = prefix.path() + "/outTemp.net";
- QVector args = {"fromlist="+cubeListFile, "cnet="+controlNetPath, "onet="+outCnetFileName,
- "radius=yes", "errorpropagation=yes", "outlier_rejection=True", "spsolve=position", "Spacecraft_position_sigma=1000",
- "Residuals_csv=on", "Camsolve=angles", "Twist=yes", "Camera_angles_sigma=2",
+ QVector args = {"fromlist="+cubeListFile, "cnet="+controlNetPath, "onet="+outCnetFileName,
+ "radius=yes", "errorpropagation=yes", "outlier_rejection=True", "spsolve=position", "Spacecraft_position_sigma=1000",
+ "Residuals_csv=on", "Camsolve=angles", "Twist=yes", "Camera_angles_sigma=2",
"Output_csv=off", "imagescsv=on", "file_prefix="+prefix.path() + "/"};
UserInterface options(APP_XML, args);
-
- Pvl log;
-
+
+ Pvl log;
+
try {
jigsaw(options, &log);
}
@@ -670,22 +680,22 @@ TEST_F(ApolloNetwork, FunctionalTestJigsawOutlierRejection) {
QString residualsCsv = prefix.path() + "/residuals.csv";
QFile bo(residualsCsv);
- QString contents;
+ QString contents;
if (bo.open(QIODevice::ReadOnly)) {
- contents = bo.read(bo.size());
+ contents = bo.read(bo.size());
}
- else {
+ else {
FAIL() << "Failed to open bundleout.txt" << std::endl;
}
-
- int nRejectedCsv = 0;
+
+ int nRejectedCsv = 0;
QStringList lines = contents.split("\n");
for (int i = 0; i < lines.size(); i++) {
- if (lines[i].right(1).trimmed() == "*") {
- nRejectedCsv++;
+ if (lines[i].right(1).trimmed() == "*") {
+ nRejectedCsv++;
}
}
-
+
ASSERT_EQ(nRejectedCsv, 51);
}
@@ -694,36 +704,36 @@ TEST_F(ApolloNetwork, FunctionalTestJigsawOutlierRejection) {
TEST_F(ApolloNetwork, FunctionalTestJigsawMEstimator) {
QTemporaryDir prefix;
QString newNetworkPath = prefix.path()+"/badMeasures.net";
-
- QVector pid = {"AS15_000031985",
- "AS15_000033079",
- "AS15_SocetPAN_03",
+
+ QVector pid = {"AS15_000031985",
+ "AS15_000033079",
+ "AS15_SocetPAN_03",
"AS15_Tie03"};
-
- QVector mid = {"APOLLO15/METRIC/1971-07-31T14:01:40.346",
- "APOLLO15/METRIC/1971-07-31T14:02:27.179",
- "APOLLO15/METRIC/1971-07-31T14:02:03.751",
+
+ QVector mid = {"APOLLO15/METRIC/1971-07-31T14:01:40.346",
+ "APOLLO15/METRIC/1971-07-31T14:02:27.179",
+ "APOLLO15/METRIC/1971-07-31T14:02:03.751",
"APOLLO15/METRIC/1971-07-31T14:00:53.547"};
-
+
for (int i = 0; i < pid.size(); i++) {
- // grab random points and add error to a single measure
+ // grab random points and add error to a single measure
ControlPoint *point = network->GetPoint(pid[i]);
ControlMeasure *measure = point->GetMeasure(mid[i]);
- measure->SetCoordinate(measure->GetLine()+50, measure->GetLine()+50);
+ measure->SetCoordinate(measure->GetLine()+50, measure->GetLine()+50);
}
- network->Write(newNetworkPath);
-
+ network->Write(newNetworkPath);
+
QString outCnetFileName = prefix.path() + "/outTemp.net";
QVector args = {"fromlist="+cubeListFile, "cnet="+newNetworkPath, "onet="+outCnetFileName,
"Radius=yes", "Errorpropagation=yes", "Spsolve=position","Spacecraft_position_sigma=1000.0",
- "Camsolve=angles", "twist=yes", "Camera_angles_sigma=2",
- "Model1=huber", "Max_model1_c_quantile=0.6", "Model2=chen", "Max_model2_c_quantile=0.98", "Sigma0=1e-3",
+ "Camsolve=angles", "twist=yes", "Camera_angles_sigma=2",
+ "Model1=huber", "Max_model1_c_quantile=0.6", "Model2=chen", "Max_model2_c_quantile=0.98", "Sigma0=1e-3",
"bundleout_txt=yes", "Output_csv=on", "imagescsv=on", "file_prefix="+prefix.path()+"/"};
UserInterface options(APP_XML, args);
- Pvl log;
+ Pvl log;
try {
jigsaw(options, &log);
}
@@ -735,29 +745,29 @@ TEST_F(ApolloNetwork, FunctionalTestJigsawMEstimator) {
CSVReader header = CSVReader(prefix.path()+"/bundleout_images.csv",
false, 0, ',', false, true);
- ControlNet onet;
+ ControlNet onet;
onet.ReadControl(outCnetFileName);
-
+
QVector presiduals = {};
- QVector> mresiduals = {{1.27975, 1.54281, 1.8778, 1.30159},
- {2.25115, 2.33559, 0.547574, 3.16777},
- {1.15396, 0.69243, 1.03005, 0.848934},
- {2.24641, 4.39168, 0.560941, 2.844}};
+ QVector> mresiduals = {{1.27975, 1.54281, 1.8778, 1.30159},
+ {2.25115, 2.33559, 0.547574, 3.16777},
+ {1.15396, 0.69243, 1.03005, 0.848934},
+ {2.24641, 4.39168, 0.560941, 2.844}};
for (int i = 0; i < pid.size(); i++) {
ControlPoint *point = network->GetPoint(pid[i]);
QList measures = point->getMeasures();
for (int j = 0; j < measures.size(); j++ ) {
- EXPECT_NEAR(measures.at(j)->GetResidualMagnitude(), mresiduals[i][j], 0.0001);
+ EXPECT_NEAR(measures.at(j)->GetResidualMagnitude(), mresiduals[i][j], 0.0001);
}
}
QFile bo(prefix.path()+"/bundleout.txt");
- QString contents;
+ QString contents;
if (bo.open(QIODevice::ReadOnly)) {
- contents = bo.read(bo.size());
+ contents = bo.read(bo.size());
}
- else {
+ else {
FAIL() << "Failed to open bundleout.txt" << std::endl;
}
@@ -782,11 +792,11 @@ TEST_F(ApolloNetwork, FunctionalTestJigsawMEstimator) {
TEST_F(ObservationPair, FunctionalTestJigsawErrorNoSolve) {
QTemporaryDir prefix;
QString outCnetFileName = prefix.path() + "/outTemp.net";
- QVector args = {"fromlist="+cubeListFile, "cnet="+cnetPath, "onet="+outCnetFileName,
- "camsolve=None", "spsolve=None"};
-
- UserInterface options(APP_XML, args);
- Pvl log;
+ QVector