diff --git a/CMakeLists.txt b/CMakeLists.txt index 58f2ab12c649f8202f2486524f7760c19f90681c..e656f5074213b944181f4d80df70cabef538c856 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -67,10 +67,11 @@ set(PROJ_TARGET PROJ::proj) add_library(usgscsm SHARED src/UsgsAstroPlugin.cpp + src/UsgsAstroPluginSupport.cpp src/UsgsAstroFrameSensorModel.cpp src/UsgsAstroPushFrameSensorModel.cpp src/UsgsAstroLsSensorModel.cpp - src/UsgsAstroProjectedLsSensorModel.cpp + src/UsgsAstroProjectedSensorModel.cpp src/UsgsAstroSarSensorModel.cpp src/Distortion.cpp src/Utilities.cpp diff --git a/include/usgscsm/UsgsAstroPluginSupport.h b/include/usgscsm/UsgsAstroPluginSupport.h new file mode 100644 index 0000000000000000000000000000000000000000..ee17d313d8d1e681179544c413b225937a9bb0fe --- /dev/null +++ b/include/usgscsm/UsgsAstroPluginSupport.h @@ -0,0 +1,9 @@ +#ifndef INCLUDE_USGSCSM_USGSASTROPLUGINSUPPORT_H_ +#define INCLUDE_USGSCSM_USGSASTROPLUGINSUPPORT_H_ + +#include <RasterGM.h> +#include <csm/Plugin.h> + +csm::RasterGM *getUsgsCsmModel(const std::string &stringIsd, const std::string &modelName, csm::WarningList *warnings); + +#endif // INCLUDE_USGSCSM_USGSASTROPLUGINSUPPORT_H_ diff --git a/include/usgscsm/UsgsAstroProjectedLsSensorModel.h b/include/usgscsm/UsgsAstroProjectedLsSensorModel.h deleted file mode 100644 index 56b6fbb0df050c7400cada2f2c160e3554f81200..0000000000000000000000000000000000000000 --- a/include/usgscsm/UsgsAstroProjectedLsSensorModel.h +++ /dev/null @@ -1,266 +0,0 @@ -/** Copyright © 2017-2022 BAE Systems Information and Electronic Systems Integration Inc. - -Redistribution and use in source and binary forms, with or without modification, are permitted -provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this list of conditions -and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, this list of -conditions and the following disclaimer in the documentation and/or other materials provided -with the distribution. - -3. Neither the name of the copyright holder nor the names of its contributors may be used to -endorse or promote products derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT -OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. **/ - -#ifndef INCLUDE_USGSCSM_USGSASTROPROJECTEDLSSENSORMODEL_H_ -#define INCLUDE_USGSCSM_USGSASTROPROJECTEDLSSENSORMODEL_H_ - -#include <RasterGM.h> -#include <SettableEllipsoid.h> - -#include<utility> -#include<memory> -#include<string> -#include<vector> - -#include "ale/Orientations.h" -#include "ale/States.h" - -#include "spdlog/spdlog.h" - -#include "UsgsAstroLsSensorModel.h" - -class UsgsAstroProjectedLsSensorModel : public UsgsAstroLsSensorModel { - public: - // Initializes the class from state data as formatted - // in a string by the toString() method - void setState(const std::string& state); - - virtual void replaceModelState(const std::string& stateString); - //> This method attempts to initialize the current model with the state - // given by argState. The argState argument can be a string previously - // retrieved from the getModelState method. - // - // If argState contains a valid state for the current model, - // the internal state of the model is updated. - // - // If the model cannot be updated to the given state, a csm::Error is - // thrown and the internal state of the model is undefined. - // - // If the argument state string is empty, the model remains unchanged. - //< - - // This method checks to see if the model name is recognized - // in the input state string. - static std::string getModelNameFromModelState(const std::string& model_state); - - std::string constructStateFromIsd(const std::string imageSupportData, - csm::WarningList* list); - - // State data elements; - std::vector<double> m_geoTransform; - std::string m_projString; - - // Define logging pointer and file content - std::shared_ptr<spdlog::logger> m_logger = spdlog::get("usgscsm_logger"); - - // Hardcoded - static const std::string _SENSOR_MODEL_NAME; // state date element 0 - - static const std::string _STATE_KEYWORD[]; - - // Set to default values - void reset(); - - //-------------------------------------------------------------- - // Constructors/Destructor - //-------------------------------------------------------------- - - UsgsAstroProjectedLsSensorModel(); - ~UsgsAstroProjectedLsSensorModel(); - - virtual std::string getModelState() const; - - // Set the sensor model based on the input state data - void set(const std::string& state_data); - - //---------------------------------------------------------------- - // The following public methods are implementations of - // the methods inherited from RasterGM and SettableEllipsoid. - // These are defined in the CSM API. - //---------------------------------------------------------------- - - //--- - // Core Photogrammetry - //--- - virtual csm::ImageCoord groundToImage( - const csm::EcefCoord& groundPt, double desiredPrecision = 0.001, - double* achievedPrecision = NULL, - csm::WarningList* warnings = NULL) const; - - //> This method converts the given groundPt (x,y,z in ECEF meters) to a - // returned image coordinate (line, sample in full image space pixels). - // - // Iterative algorithms will use desiredPrecision, in meters, as the - // convergence criterion, otherwise it will be ignored. - // - // If a non-NULL achievedPrecision argument is received, it will be - // populated with the actual precision, in meters, achieved by iterative - // algorithms and 0.0 for deterministic algorithms. - // - // If a non-NULL warnings argument is received, it will be populated - // as applicable. - //< - - virtual csm::ImageCoordCovar groundToImage( - const csm::EcefCoordCovar& groundPt, double desiredPrecision = 0.001, - double* achievedPrecision = NULL, - csm::WarningList* warnings = NULL) const; - //> This method converts the given groundPt (x,y,z in ECEF meters and - // corresponding 3x3 covariance in ECEF meters squared) to a returned - // image coordinate with covariance (line, sample in full image space - // pixels and corresponding 2x2 covariance in pixels squared). - // - // Iterative algorithms will use desiredPrecision, in meters, as the - // convergence criterion, otherwise it will be ignored. - // - // If a non-NULL achievedPrecision argument is received, it will be - // populated with the actual precision, in meters, achieved by iterative - // algorithms and 0.0 for deterministic algorithms. - // - // If a non-NULL warnings argument is received, it will be populated - // as applicable. - //< - - virtual csm::EcefCoord imageToGround(const csm::ImageCoord& imagePt, - double height, - double desiredPrecision = 0.001, - double* achievedPrecision = NULL, - csm::WarningList* warnings = NULL) const; - //> This method converts the given imagePt (line,sample in full image - // space pixels) and given height (in meters relative to the WGS-84 - // ellipsoid) to a returned ground coordinate (x,y,z in ECEF meters). - // - // Iterative algorithms will use desiredPrecision, in meters, as the - // convergence criterion, otherwise it will be ignored. - // - // If a non-NULL achievedPrecision argument is received, it will be - // populated with the actual precision, in meters, achieved by iterative - // algorithms and 0.0 for deterministic algorithms. - // - // If a non-NULL warnings argument is received, it will be populated - // as applicable. - //< - - virtual csm::EcefCoordCovar imageToGround( - const csm::ImageCoordCovar& imagePt, double height, double heightVariance, - double desiredPrecision = 0.001, double* achievedPrecision = NULL, - csm::WarningList* warnings = NULL) const; - //> This method converts the given imagePt (line, sample in full image - // space pixels and corresponding 2x2 covariance in pixels squared) - // and given height (in meters relative to the WGS-84 ellipsoid) and - // corresponding heightVariance (in meters) to a returned ground - // coordinate with covariance (x,y,z in ECEF meters and corresponding - // 3x3 covariance in ECEF meters squared). - // - // Iterative algorithms will use desiredPrecision, in meters, as the - // convergence criterion, otherwise it will be ignored. - // - // If a non-NULL achievedPrecision argument is received, it will be - // populated with the actual precision, in meters, achieved by iterative - // algorithms and 0.0 for deterministic algorithms. - // - // If a non-NULL warnings argument is received, it will be populated - // as applicable. - //< - - virtual csm::EcefLocus imageToProximateImagingLocus( - const csm::ImageCoord& imagePt, const csm::EcefCoord& groundPt, - double desiredPrecision = 0.001, double* achievedPrecision = NULL, - csm::WarningList* warnings = NULL) const; - //> This method, for the given imagePt (line, sample in full image space - // pixels), returns the position and direction of the imaging locus - // nearest the given groundPt (x,y,z in ECEF meters). - // - // Note that there are two opposite directions possible. Both are - // valid, so either can be returned; the calling application can convert - // to the other as necessary. - // - // Iterative algorithms will use desiredPrecision, in meters, as the - // convergence criterion for the locus position, otherwise it will be - // ignored. - // - // If a non-NULL achievedPrecision argument is received, it will be - // populated with the actual precision, in meters, achieved by iterative - // algorithms and 0.0 for deterministic algorithms. - // - // If a non-NULL warnings argument is received, it will be populated - // as applicable. - //< - - virtual csm::EcefLocus imageToRemoteImagingLocus( - const csm::ImageCoord& imagePt, double desiredPrecision = 0.001, - double* achievedPrecision = NULL, - csm::WarningList* warnings = NULL) const; - //> This method, for the given imagePt (line, sample in full image space - // pixels), returns the position and direction of the imaging locus - // at the sensor. - // - // Note that there are two opposite directions possible. Both are - // valid, so either can be returned; the calling application can convert - // to the other as necessary. - // - // Iterative algorithms will use desiredPrecision, in meters, as the - // convergence criterion for the locus position, otherwise it will be - // ignored. - // - // If a non-NULL achievedPrecision argument is received, it will be - // populated with the actual precision, in meters, achieved by iterative - // algorithms and 0.0 for deterministic algorithms. - // - // If a non-NULL warnings argument is received, it will be populated - // as applicable. - // - // Notes: - // - // The remote imaging locus is only well-defined for optical sensors. - // It is undefined for SAR sensors and might not be available for - // polynomial and other non-physical models. The - // imageToProximateImagingLocus method should be used instead where - // possible. - //< - - //--- - // Error Correction - //--- - - virtual csm::Version getVersion() const; - //> This method returns the version of the model code. The Version - // object can be compared to other Version objects with its comparison - // operators. Not to be confused with the CSM API version. - //< - - virtual std::string getModelName() const; - //> This method returns a string identifying the name of the model. - //< - - virtual std::string getPedigree() const; - //> This method returns a string that identifies the sensor, - // the model type, its mode of acquisition and processing path. - // For example, an optical sensor model or a cubic rational polynomial - // model created from the same sensor's support data would produce - // different pedigrees for each case. - //< -}; - -#endif // INCLUDE_USGSCSM_USGSASTROPROJECTEDLSSENSORMODEL_H_ diff --git a/include/usgscsm/UsgsAstroProjectedSensorModel.h b/include/usgscsm/UsgsAstroProjectedSensorModel.h new file mode 100644 index 0000000000000000000000000000000000000000..4763d3902dabfe62aa4872f3a3d9d673dcd8cc5e --- /dev/null +++ b/include/usgscsm/UsgsAstroProjectedSensorModel.h @@ -0,0 +1,828 @@ +/** Copyright © 2017-2022 BAE Systems Information and Electronic Systems Integration Inc. + +Redistribution and use in source and binary forms, with or without modification, are permitted +provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions +and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this list of +conditions and the following disclaimer in the documentation and/or other materials provided +with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors may be used to +endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. **/ + +#ifndef INCLUDE_USGSCSM_USGSASTROPROJECTEDSENSORMODEL_H_ +#define INCLUDE_USGSCSM_USGSASTROPROJECTEDSENSORMODEL_H_ + +#include <RasterGM.h> +#include <SettableEllipsoid.h> + +#include<utility> +#include<memory> +#include<string> +#include<vector> + +#include "ale/Orientations.h" +#include "ale/States.h" + +#include "spdlog/spdlog.h" + +#include "UsgsAstroLsSensorModel.h" + +class UsgsAstroProjectedSensorModel : public csm::RasterGM, + virtual public csm::SettableEllipsoid { + +public: + // Initializes the class from state data as formatted + // in a string by the toString() method + void setState(const std::string &state); + + virtual void replaceModelState(const std::string &stateString); + //> This method attempts to initialize the current model with the state + // given by argState. The argState argument can be a string previously + // retrieved from the getModelState method. + // + // If argState contains a valid state for the current model, + // the internal state of the model is updated. + // + // If the model cannot be updated to the given state, a csm::Error is + // thrown and the internal state of the model is undefined. + // + // If the argument state string is empty, the model remains unchanged. + //< + + // This method checks to see if the model name is recognized + // in the input state string. + static std::string getModelNameFromModelState(const std::string &model_state); + + std::string constructStateFromIsd(const std::string imageSupportData, + csm::WarningList *list); + + // State data elements; + double m_majorAxis; + double m_minorAxis; + std::vector<double> m_geoTransform; + std::string m_projString; + + // Define logging pointer and file content + std::shared_ptr<spdlog::logger> m_logger = spdlog::get("usgscsm_logger"); + + // Hardcoded + static const std::string _SENSOR_MODEL_NAME; // state date element 0 + + static const std::string _STATE_KEYWORD[]; + + // Set to default values + void reset(); + + //-------------------------------------------------------------- + // Constructors/Destructor + //-------------------------------------------------------------- + + UsgsAstroProjectedSensorModel(); + ~UsgsAstroProjectedSensorModel(); + + virtual std::string getModelState() const; + + // Set the sensor model based on the input state data + void set(const std::string &state_data); + + //---------------------------------------------------------------- + // The following public methods are implementations of + // the methods inherited from RasterGM and SettableEllipsoid. + // These are defined in the CSM API. + //---------------------------------------------------------------- + + //--- + // Core Photogrammetry + //--- + virtual csm::ImageCoord groundToImage( + const csm::EcefCoord &groundPt, double desiredPrecision = 0.001, + double *achievedPrecision = NULL, + csm::WarningList *warnings = NULL) const; + + //> This method converts the given groundPt (x,y,z in ECEF meters) to a + // returned image coordinate (line, sample in full image space pixels). + // + // Iterative algorithms will use desiredPrecision, in meters, as the + // convergence criterion, otherwise it will be ignored. + // + // If a non-NULL achievedPrecision argument is received, it will be + // populated with the actual precision, in meters, achieved by iterative + // algorithms and 0.0 for deterministic algorithms. + // + // If a non-NULL warnings argument is received, it will be populated + // as applicable. + //< + + virtual csm::ImageCoordCovar groundToImage( + const csm::EcefCoordCovar &groundPt, double desiredPrecision = 0.001, + double *achievedPrecision = NULL, + csm::WarningList *warnings = NULL) const; + //> This method converts the given groundPt (x,y,z in ECEF meters and + // corresponding 3x3 covariance in ECEF meters squared) to a returned + // image coordinate with covariance (line, sample in full image space + // pixels and corresponding 2x2 covariance in pixels squared). + // + // Iterative algorithms will use desiredPrecision, in meters, as the + // convergence criterion, otherwise it will be ignored. + // + // If a non-NULL achievedPrecision argument is received, it will be + // populated with the actual precision, in meters, achieved by iterative + // algorithms and 0.0 for deterministic algorithms. + // + // If a non-NULL warnings argument is received, it will be populated + // as applicable. + //< + + virtual csm::EcefCoord imageToGround(const csm::ImageCoord &imagePt, + double height, + double desiredPrecision = 0.001, + double *achievedPrecision = NULL, + csm::WarningList *warnings = NULL) const; + //> This method converts the given imagePt (line,sample in full image + // space pixels) and given height (in meters relative to the WGS-84 + // ellipsoid) to a returned ground coordinate (x,y,z in ECEF meters). + // + // Iterative algorithms will use desiredPrecision, in meters, as the + // convergence criterion, otherwise it will be ignored. + // + // If a non-NULL achievedPrecision argument is received, it will be + // populated with the actual precision, in meters, achieved by iterative + // algorithms and 0.0 for deterministic algorithms. + // + // If a non-NULL warnings argument is received, it will be populated + // as applicable. + //< + + virtual csm::EcefCoordCovar imageToGround( + const csm::ImageCoordCovar &imagePt, double height, double heightVariance, + double desiredPrecision = 0.001, double *achievedPrecision = NULL, + csm::WarningList *warnings = NULL) const; + //> This method converts the given imagePt (line, sample in full image + // space pixels and corresponding 2x2 covariance in pixels squared) + // and given height (in meters relative to the WGS-84 ellipsoid) and + // corresponding heightVariance (in meters) to a returned ground + // coordinate with covariance (x,y,z in ECEF meters and corresponding + // 3x3 covariance in ECEF meters squared). + // + // Iterative algorithms will use desiredPrecision, in meters, as the + // convergence criterion, otherwise it will be ignored. + // + // If a non-NULL achievedPrecision argument is received, it will be + // populated with the actual precision, in meters, achieved by iterative + // algorithms and 0.0 for deterministic algorithms. + // + // If a non-NULL warnings argument is received, it will be populated + // as applicable. + //< + + virtual csm::EcefLocus imageToProximateImagingLocus( + const csm::ImageCoord &imagePt, const csm::EcefCoord &groundPt, + double desiredPrecision = 0.001, double *achievedPrecision = NULL, + csm::WarningList *warnings = NULL) const; + //> This method, for the given imagePt (line, sample in full image space + // pixels), returns the position and direction of the imaging locus + // nearest the given groundPt (x,y,z in ECEF meters). + // + // Note that there are two opposite directions possible. Both are + // valid, so either can be returned; the calling application can convert + // to the other as necessary. + // + // Iterative algorithms will use desiredPrecision, in meters, as the + // convergence criterion for the locus position, otherwise it will be + // ignored. + // + // If a non-NULL achievedPrecision argument is received, it will be + // populated with the actual precision, in meters, achieved by iterative + // algorithms and 0.0 for deterministic algorithms. + // + // If a non-NULL warnings argument is received, it will be populated + // as applicable. + //< + + virtual csm::EcefLocus imageToRemoteImagingLocus( + const csm::ImageCoord &imagePt, double desiredPrecision = 0.001, + double *achievedPrecision = NULL, + csm::WarningList *warnings = NULL) const; + //> This method, for the given imagePt (line, sample in full image space + // pixels), returns the position and direction of the imaging locus + // at the sensor. + // + // Note that there are two opposite directions possible. Both are + // valid, so either can be returned; the calling application can convert + // to the other as necessary. + // + // Iterative algorithms will use desiredPrecision, in meters, as the + // convergence criterion for the locus position, otherwise it will be + // ignored. + // + // If a non-NULL achievedPrecision argument is received, it will be + // populated with the actual precision, in meters, achieved by iterative + // algorithms and 0.0 for deterministic algorithms. + // + // If a non-NULL warnings argument is received, it will be populated + // as applicable. + // + // Notes: + // + // The remote imaging locus is only well-defined for optical sensors. + // It is undefined for SAR sensors and might not be available for + // polynomial and other non-physical models. The + // imageToProximateImagingLocus method should be used instead where + // possible. + //< + + //--- + // Monoscopic Mensuration + //--- + virtual csm::ImageCoord getImageStart() const; + //> This method returns the starting coordinate (line, sample in full + // image space pixels) for the imaging operation. Typically (0,0). + //< + + virtual csm::ImageVector getImageSize() const; + //> This method returns the number of lines and samples in full image + // space pixels for the imaging operation. + // + // Note that the model might not be valid over the entire imaging + // operation. Use getValidImageRange() to get the valid range of image + // coordinates. + //< + + virtual std::pair<csm::ImageCoord, csm::ImageCoord> getValidImageRange() + const; + //> This method returns the minimum and maximum image coordinates + // (line, sample in full image space pixels), respectively, over which + // the current model is valid. The image coordinates define opposite + // corners of a rectangle whose sides are parallel to the line and + // sample axes. + // + // The valid image range does not always match the full image + // coverage as returned by the getImageStart and getImageSize methods. + // + // Used in conjunction with the getValidHeightRange method, it is + // possible to determine the full range of ground coordinates over which + // the model is valid. + //< + + virtual std::pair<double, double> getValidHeightRange() const; + //> This method returns the minimum and maximum heights (in meters + // relative to WGS-84 ellipsoid), respectively, over which the model is + // valid. For example, a model for an airborne platform might not be + // designed to return valid coordinates for heights above the aircraft. + // + // If there are no limits defined for the model, (-99999.0,99999.0) + // will be returned. + //< + + virtual csm::EcefVector getIlluminationDirection( + const csm::EcefCoord &groundPt) const; + //> This method returns a vector defining the direction of + // illumination at the given groundPt (x,y,z in ECEF meters). + // Note that there are two opposite directions possible. Both are + // valid, so either can be returned; the calling application can convert + // to the other as necessary. + //< + + //--- + // Time and Trajectory + //--- + virtual double getImageTime(const csm::ImageCoord &imagePt) const; + //> This method returns the time in seconds at which the pixel at the + // given imagePt (line, sample in full image space pixels) was captured + // + // The time provided is relative to the reference date and time given + // by the Model::getReferenceDateAndTime method. + //< + + virtual csm::EcefCoord getSensorPosition( + const csm::ImageCoord &imagePt) const; + //> This method returns the position of the physical sensor + // (x,y,z in ECEF meters) when the pixel at the given imagePt + // (line, sample in full image space pixels) was captured. + // + // A csm::Error will be thrown if the sensor position is not available. + //< + + virtual csm::EcefCoord getSensorPosition(double time) const; + //> This method returns the position of the physical sensor + // (x,y,z meters ECEF) at the given time relative to the reference date + // and time given by the Model::getReferenceDateAndTime method. + //< + + virtual csm::EcefVector getSensorVelocity( + const csm::ImageCoord &imagePt) const; + //> This method returns the velocity of the physical sensor + // (x,y,z in ECEF meters per second) when the pixel at the given imagePt + // (line, sample in full image space pixels) was captured. + //< + + virtual csm::EcefVector getSensorVelocity(double time) const; + //> This method returns the velocity of the physical sensor + // (x,y,z in ECEF meters per second ) at the given time relative to the + // reference date and time given by the Model::getReferenceDateAndTime + // method. + //< + + virtual csm::RasterGM::SensorPartials computeSensorPartials( + int index, const csm::EcefCoord &groundPt, + double desiredPrecision = 0.001, double *achievedPrecision = NULL, + csm::WarningList *warnings = NULL) const; + //> This is one of two overloaded methods. This method takes only + // the necessary inputs. Some effieciency can be obtained by using the + // other method. Even more efficiency can be obtained by using the + // computeAllSensorPartials method. + // + // This method returns the partial derivatives of line and sample + // (in pixels per the applicable model parameter units), respectively, + // with respect to the model parameter given by index at the given + // groundPt (x,y,z in ECEF meters). + // + // Derived model implementations may wish to implement this method by + // calling the groundToImage method and passing the resulting image + // coordinate to the other computeSensorPartials method. + // + // If a non-NULL achievedPrecision argument is received, it will be + // populated with the highest actual precision, in meters, achieved by + // iterative algorithms and 0.0 for deterministic algorithms. + // + // If a non-NULL achievedPrecision argument is received, it will be + // populated with the actual precision, in meters, achieved by iterative + // algorithms and 0.0 for deterministic algorithms. + // + // If a non-NULL warnings argument is received, it will be populated + // as applicable. + //< + + virtual csm::RasterGM::SensorPartials computeSensorPartials( + int index, const csm::ImageCoord &imagePt, const csm::EcefCoord &groundPt, + double desiredPrecision = 0.001, double *achievedPrecision = NULL, + csm::WarningList *warnings = NULL) const; + //> This is one of two overloaded methods. This method takes + // an input image coordinate for efficiency. Even more efficiency can + // be obtained by using the computeAllSensorPartials method. + // + // This method returns the partial derivatives of line and sample + // (in pixels per the applicable model parameter units), respectively, + // with respect to the model parameter given by index at the given + // groundPt (x,y,z in ECEF meters). + // + // The imagePt, corresponding to the groundPt, is given so that it does + // not need to be computed by the method. Results are unpredictable if + // the imagePt provided does not correspond to the result of calling the + // groundToImage method with the given groundPt. + // + // Implementations with iterative algorithms (typically ground-to-image + // calls) will use desiredPrecision, in meters, as the convergence + // criterion, otherwise it will be ignored. + // + // If a non-NULL achievedPrecision argument is received, it will be + // populated with the highest actual precision, in meters, achieved by + // iterative algorithms and 0.0 for deterministic algorithms. + // + // If a non-NULL warnings argument is received, it will be populated + // as applicable. + //< + + virtual std::vector<csm::RasterGM::SensorPartials> computeAllSensorPartials( + const csm::EcefCoord &groundPt, csm::param::Set pSet = csm::param::VALID, + double desiredPrecision = 0.001, double *achievedPrecision = NULL, + csm::WarningList *warnings = NULL) const; + //> This is one of two overloaded methods. This method takes only + // the necessary inputs. Some effieciency can be obtained by using the + // other method. + // + // This method returns the partial derivatives of line and sample + // (in pixels per the applicable model parameter units), respectively, + // with respect to to each of the desired model parameters at the given + // groundPt (x,y,z in ECEF meters). Desired model parameters are + // indicated by the given pSet. + // + // Implementations with iterative algorithms (typically ground-to-image + // calls) will use desiredPrecision, in meters, as the convergence + // criterion, otherwise it will be ignored. + // + // If a non-NULL achievedPrecision argument is received, it will be + // populated with the highest actual precision, in meters, achieved by + // iterative algorithms and 0.0 for deterministic algorithms. + // + // If a non-NULL warnings argument is received, it will be populated + // as applicable. + // + // The value returned is a vector of pairs with line and sample partials + // for one model parameter in each pair. The indices of the + // corresponding model parameters can be found by calling the + // getParameterSetIndices method for the given pSet. + // + // Derived models may wish to implement this directly for efficiency, + // but an implementation is provided here that calls the + // computeSensorPartials method for each desired parameter index. + //< + + virtual std::vector<csm::RasterGM::SensorPartials> computeAllSensorPartials( + const csm::ImageCoord &imagePt, const csm::EcefCoord &groundPt, + csm::param::Set pSet = csm::param::VALID, double desiredPrecision = 0.001, + double *achievedPrecision = NULL, + csm::WarningList *warnings = NULL) const; + //> This is one of two overloaded methods. This method takes + // an input image coordinate for efficiency. + // + // This method returns the partial derivatives of line and sample + // (in pixels per the applicable model parameter units), respectively, + // with respect to to each of the desired model parameters at the given + // groundPt (x,y,z in ECEF meters). Desired model parameters are + // indicated by the given pSet. + // + // The imagePt, corresponding to the groundPt, is given so that it does + // not need to be computed by the method. Results are unpredictable if + // the imagePt provided does not correspond to the result of calling the + // groundToImage method with the given groundPt. + // + // Implementations with iterative algorithms (typically ground-to-image + // calls) will use desiredPrecision, in meters, as the convergence + // criterion, otherwise it will be ignored. + // + // If a non-NULL achievedPrecision argument is received, it will be + // populated with the highest actual precision, in meters, achieved by + // iterative algorithms and 0.0 for deterministic algorithms. + // + // If a non-NULL warnings argument is received, it will be populated + // as applicable. + // + // The value returned is a vector of pairs with line and sample partials + // for one model parameter in each pair. The indices of the + // corresponding model parameters can be found by calling the + // getParameterSetIndices method for the given pSet. + // + // Derived models may wish to implement this directly for efficiency, + // but an implementation is provided here that calls the + // computeSensorPartials method for each desired parameter index. + //< + + virtual std::vector<double> computeGroundPartials( + const csm::EcefCoord &groundPt) const; + //> This method returns the partial derivatives of line and sample + // (in pixels per meter) with respect to the given groundPt + // (x,y,z in ECEF meters). + // + // The value returned is a vector with six elements as follows: + // + //- [0] = line wrt x + //- [1] = line wrt y + //- [2] = line wrt z + //- [3] = sample wrt x + //- [4] = sample wrt y + //- [5] = sample wrt z + //< + + virtual const csm::CorrelationModel &getCorrelationModel() const; + //> This method returns a reference to a CorrelationModel. + // The CorrelationModel is used to determine the correlation between + // the model parameters of different models of the same type. + // These correlations are used to establish the "a priori" cross-covariance + // between images. While some applications (such as generation of a + // replacement sensor model) may wish to call this method directly, + // it is reccommended that the inherited method + // GeometricModel::getCrossCovarianceMatrix() be called instead. + //< + + virtual std::vector<double> getUnmodeledCrossCovariance( + const csm::ImageCoord &pt1, const csm::ImageCoord &pt2) const; + //> This method returns the 2x2 line and sample cross covariance + // (in pixels squared) between the given imagePt1 and imagePt2 for any + // model error not accounted for by the model parameters. The error is + // reported as the four terms of a 2x2 matrix, returned as a 4 element + // vector. + //< + + virtual csm::EcefCoord getReferencePoint() const; + //> This method returns the ground point indicating the general + // location of the image. + //< + + virtual void setReferencePoint(const csm::EcefCoord &groundPt); + //> This method sets the ground point indicating the general location + // of the image. + //< + + //--- + // Sensor Model Parameters + //--- + virtual int getNumParameters() const; + //> This method returns the number of adjustable parameters. + //< + + virtual std::string getParameterName(int index) const; + //> This method returns the name for the adjustable parameter + // indicated by the given index. + // + // If the index is out of range, a csm::Error may be thrown. + //< + + virtual std::string getParameterUnits(int index) const; + //> This method returns the units for the adjustable parameter + // indicated by the given index. This string is intended for human + // consumption, not automated analysis. Preferred unit names are: + // + //- meters "m" + //- centimeters "cm" + //- millimeters "mm" + //- micrometers "um" + //- nanometers "nm" + //- kilometers "km" + //- inches-US "inch" + //- feet-US "ft" + //- statute miles "mi" + //- nautical miles "nmi" + //- + //- radians "rad" + //- microradians "urad" + //- decimal degrees "deg" + //- arc seconds "arcsec" + //- arc minutes "arcmin" + //- + //- seconds "sec" + //- minutes "min" + //- hours "hr" + //- + //- steradian "sterad" + //- + //- none "unitless" + //- + //- lines per second "lines/sec" + //- samples per second "samples/sec" + //- frames per second "frames/sec" + //- + //- watts "watt" + //- + //- degrees Kelvin "K" + //- + //- gram "g" + //- kilogram "kg" + //- pound - US "lb" + //- + //- hertz "hz" + //- megahertz "mhz" + //- gigahertz "ghz" + // + // Units may be combined with "/" or "." to indicate division or + // multiplication. The caret symbol "^" can be used to indicate + // exponentiation. Thus "m.m" and "m^2" are the same and indicate + // square meters. The return "m/sec^2" indicates an acceleration in + // meters per second per second. + // + // Derived classes may choose to return additional unit names, as + // required. + //< + + virtual bool hasShareableParameters() const; + //> This method returns true if there exists at least one adjustable + // parameter on the model that is shareable. See the + // isParameterShareable() method. This method should return false if + // all calls to isParameterShareable() return false. + //< + + virtual bool isParameterShareable(int index) const; + //> This method returns a flag to indicate whether or not the adjustable + // parameter referenced by index is shareable across models. + //< + + virtual csm::SharingCriteria getParameterSharingCriteria(int index) const; + //> This method returns characteristics to indicate how the adjustable + // parameter referenced by index is shareable across models. + //< + + virtual double getParameterValue(int index) const; + //> This method returns the value of the adjustable parameter + // referenced by the given index. + //< + + virtual void setParameterValue(int index, double value); + //> This method sets the value for the adjustable parameter referenced by + // the given index. + //< + + virtual csm::param::Type getParameterType(int index) const; + //> This method returns the type of the adjustable parameter + // referenced by the given index. + //< + + virtual void setParameterType(int index, csm::param::Type pType); + //> This method sets the type of the adjustable parameter + // reference by the given index. + //< + + //--- + // Uncertainty Propagation + //--- + virtual double getParameterCovariance(int index1, int index2) const; + //> This method returns the covariance between the parameters + // referenced by index1 and index2. Variance of a single parameter + // is indicated by specifying the samve value for index1 and index2. + //< + + virtual void setParameterCovariance(int index1, int index2, + double covariance); + //> This method is used to set the covariance between the parameters + // referenced by index1 and index2. Variance of a single parameter + // is indicated by specifying the samve value for index1 and index2. + //< + + //--- + // Error Correction + //--- + virtual int getNumGeometricCorrectionSwitches() const; + //> This method returns the number of geometric correction switches + // implemented for the current model. + //< + + virtual std::string getGeometricCorrectionName(int index) const; + //> This method returns the name for the geometric correction switch + // referenced by the given index. + //< + + virtual void setGeometricCorrectionSwitch(int index, bool value, + csm::param::Type pType); + //> This method is used to enable/disable the geometric correction switch + // referenced by the given index. + //< + + virtual bool getGeometricCorrectionSwitch(int index) const; + //> This method returns the value of the geometric correction switch + // referenced by the given index. + //< + + virtual std::vector<double> getCrossCovarianceMatrix( + const csm::GeometricModel &comparisonModel, + csm::param::Set pSet = csm::param::VALID, + const csm::GeometricModel::GeometricModelList &otherModels = + csm::GeometricModel::GeometricModelList()) const; + //> This method returns a matrix containing the elements of the error + // cross covariance between this model and a given second model + // (comparisonModel). The set of cross covariance elements returned is + // indicated by pSet, which, by default, is all VALID parameters. + // + // If comparisonModel is the same as this model, the covariance for + // this model will be returned. It is equivalent to calling + // getParameterCovariance() for the same set of elements. Note that + // even if the cross covariance for a particular model type is always + // zero, the covariance for this model must still be supported. + // + // The otherModels list contains all of the models in the current + // photogrammetric process; some cross-covariance implementations are + // influenced by other models. It can be omitted if it is not needed + // by any models being used. + // + // The returned vector will logically be a two-dimensional matrix of + // covariances, though for simplicity it is stored in a one-dimensional + // vector (STL has no two-dimensional structure). The height (number of + // rows) of this matrix is the number of parameters on the current model, + // and the width (number of columns) is the number of parameters on + // the comparison model. Thus, the covariance between p1 on this model + // and p2 on the comparison model is found in index (N*p1 + p2) + // in the returned vector. N is the size of the vector returned by + // getParameterSetIndices() on the comparison model for the given pSet). + // + // Note that cross covariance is often zero. Non-zero cross covariance + // can occur for models created from the same sensor (or different + // sensors on the same platform). While cross covariances can result + // from a bundle adjustment involving multiple models, no mechanism + // currently exists within csm to "set" the cross covariance between + // models. It should thus be assumed that the returned cross covariance + // reflects the "un-adjusted" state of the models. + //< + + virtual csm::Version getVersion() const; + //> This method returns the version of the model code. The Version + // object can be compared to other Version objects with its comparison + // operators. Not to be confused with the CSM API version. + //< + + virtual std::string getModelName() const; + //> This method returns a string identifying the name of the model. + //< + + virtual std::string getPedigree() const; + //> This method returns a string that identifies the sensor, + // the model type, its mode of acquisition and processing path. + // For example, an optical sensor model or a cubic rational polynomial + // model created from the same sensor's support data would produce + // different pedigrees for each case. + //< + + //--- + // Basic collection information + //--- + virtual std::string getImageIdentifier() const; + //> This method returns an identifier to uniquely indicate the imaging + // operation associated with this model. + // This is the primary identifier of the model. + // + // This method may return an empty string if the ID is unknown. + //< + + virtual void setImageIdentifier(const std::string &imageId, + csm::WarningList *warnings = NULL); + //> This method sets an identifier to uniquely indicate the imaging + // operation associated with this model. Typically used for models + // whose initialization does not produce an adequate identifier. + // + // If a non-NULL warnings argument is received, it will be populated + // as applicable. + //< + + virtual std::string getSensorIdentifier() const; + //> This method returns an identifier to indicate the specific sensor + // that was used to acquire the image. This ID must be unique among + // sensors for a given model name. It is used to determine parameter + // correlation and sharing. Equivalent to camera or mission ID. + // + // This method may return an empty string if the sensor ID is unknown. + //< + + virtual std::string getPlatformIdentifier() const; + //> This method returns an identifier to indicate the specific platform + // that was used to acquire the image. This ID must unique among + // platforms for a given model name. It is used to determine parameter + // correlation sharing. Equivalent to vehicle or aircraft tail number. + // + // This method may return an empty string if the platform ID is unknown. + //< + + virtual std::string getCollectionIdentifier() const; + //> This method returns an identifer to indicate a collection activity + // common to a set of images. This ID must be unique among collection + // activities for a given model name. It is used to determine parameter + // correlation and sharing. + //< + + virtual std::string getTrajectoryIdentifier() const; + //> This method returns an identifier to indicate a trajectory common + // to a set of images. This ID must be unique among trajectories + // for a given model name. It is used to determine parameter + // correlation and sharing. + //< + + virtual std::string getSensorType() const; + //> This method returns a description of the sensor type (EO, IR, SAR, + // etc). See csm.h for a list of common types. Should return + // CSM_SENSOR_TYPE_UNKNOWN if the sensor type is unknown. + //< + + virtual std::string getSensorMode() const; + //> This method returns a description of the sensor mode (FRAME, + // PUSHBROOM, SPOT, SCAN, etc). See csm.h for a list of common modes. + // Should return CSM_SENSOR_MODE_UNKNOWN if the sensor mode is unknown. + //< + + virtual std::string getReferenceDateAndTime() const; + //> This method returns an approximate date and time at which the + // image was taken. The returned string follows the ISO 8601 standard. + // + //- Precision Format Example + //- year yyyy "1961" + //- month yyyymm "196104" + //- day yyyymmdd "19610420" + //- hour yyyymmddThh "19610420T20" + //- minute yyyymmddThhmm "19610420T2000" + //- second yyyymmddThhmmss "19610420T200000" + //< + + //--- + // Sensor Model State + //--- + // virtual std::string setModelState(std::string stateString) const; + //> This method returns a string containing the data to exactly recreate + // the current model. It can be used to restore this model to a + // previous state with the replaceModelState method or create a new + // model object that is identical to this model. + // The string could potentially be saved to a file for later use. + // An empty string is returned if it is not possible to save the + // current state. + //< + + virtual csm::Ellipsoid getEllipsoid() const; + //> This method returns the planetary ellipsoid. + //< + + virtual void setEllipsoid(const csm::Ellipsoid &ellipsoid); + //> This method sets the planetary ellipsoid. + //< + + protected: + csm::RasterGM *m_camera; +}; + +#endif // INCLUDE_USGSCSM_USGSASTROPROJECTEDSENSORMODEL_H_ diff --git a/src/UsgsAstroPlugin.cpp b/src/UsgsAstroPlugin.cpp index ba24543c7b35b086583b0b4d0de821a464b7e43c..81f26c5b6a23d0173289e37f03eb99077a987f8d 100644 --- a/src/UsgsAstroPlugin.cpp +++ b/src/UsgsAstroPlugin.cpp @@ -23,16 +23,18 @@ IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISI OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. **/ #include "UsgsAstroPlugin.h" +#include "UsgsAstroPluginSupport.h" #include "UsgsAstroFrameSensorModel.h" #include "UsgsAstroLsSensorModel.h" -#include "UsgsAstroProjectedLsSensorModel.h" +#include "UsgsAstroProjectedSensorModel.h" #include "UsgsAstroPushFrameSensorModel.h" #include "UsgsAstroSarSensorModel.h" #include <algorithm> #include <cstdlib> #include <fstream> +#include <stdexcept> #include <string> #include <csm/Error.h> @@ -64,7 +66,7 @@ using json = nlohmann::json; const std::string UsgsAstroPlugin::_PLUGIN_NAME = "UsgsAstroPluginCSM"; const std::string UsgsAstroPlugin::_MANUFACTURER_NAME = "UsgsAstrogeology"; const std::string UsgsAstroPlugin::_RELEASE_DATE = "20190222"; -const int UsgsAstroPlugin::_N_SENSOR_MODELS = 4; +const int UsgsAstroPlugin::_N_SENSOR_MODELS = 5; // Static Instance of itself const UsgsAstroPlugin UsgsAstroPlugin::m_registeredPlugin; @@ -134,7 +136,7 @@ std::string UsgsAstroPlugin::getModelName(size_t modelIndex) const { std::vector<std::string> supportedModelNames = { UsgsAstroFrameSensorModel::_SENSOR_MODEL_NAME, UsgsAstroLsSensorModel::_SENSOR_MODEL_NAME, - UsgsAstroProjectedLsSensorModel::_SENSOR_MODEL_NAME, + UsgsAstroProjectedSensorModel::_SENSOR_MODEL_NAME, UsgsAstroSarSensorModel::_SENSOR_MODEL_NAME, UsgsAstroPushFrameSensorModel::_SENSOR_MODEL_NAME}; MESSAGE_LOG(spdlog::level::debug, "Get Model Name: {}. Used index: {}", @@ -327,76 +329,19 @@ csm::Model *UsgsAstroPlugin::constructModelFromISD( MESSAGE_LOG(spdlog::level::info, "Running constructModelFromISD"); std::string stringIsd = loadImageSupportData(imageSupportDataOriginal); - MESSAGE_LOG(spdlog::level::trace, "ISD String: {}", stringIsd); - if (modelName == UsgsAstroFrameSensorModel::_SENSOR_MODEL_NAME) { - UsgsAstroFrameSensorModel *model = new UsgsAstroFrameSensorModel(); + csm::Model *model = getUsgsCsmModel(stringIsd, modelName, warnings); + + // Try to get the projected model, if not return the the unprojected model + try { + UsgsAstroProjectedSensorModel *projModel = new UsgsAstroProjectedSensorModel(); try { - MESSAGE_LOG(spdlog::level::debug, "Trying to construct a UsgsAstroFrameSensorModel"); - model->replaceModelState( - model->constructStateFromIsd(stringIsd, warnings)); + MESSAGE_LOG(spdlog::level::debug, "Trying to construct a UsgsAstroProjectedSensorModel"); + projModel->replaceModelState( + projModel->constructStateFromIsd(stringIsd, warnings)); MESSAGE_LOG(spdlog::level::debug, "Constructed model: {}", modelName); + return projModel; } catch (std::exception &e) { - delete model; - csm::Error::ErrorType aErrorType = - csm::Error::SENSOR_MODEL_NOT_CONSTRUCTIBLE; - std::string aMessage = "Could not construct model ["; - aMessage += modelName; - aMessage += "] with error ["; - aMessage += e.what(); - aMessage += "]"; - MESSAGE_LOG(spdlog::level::err, aMessage); - std::string aFunction = "UsgsAstroPlugin::constructModelFromISD()"; - throw csm::Error(aErrorType, aMessage, aFunction); - } - return model; - } else if (modelName == UsgsAstroLsSensorModel::_SENSOR_MODEL_NAME) { - UsgsAstroLsSensorModel *model = new UsgsAstroLsSensorModel(); - try { - MESSAGE_LOG(spdlog::level::debug, "Trying to construct a UsgsAstroLsSensorModel"); - model->replaceModelState( - model->constructStateFromIsd(stringIsd, warnings)); - } catch (std::exception &e) { - delete model; - csm::Error::ErrorType aErrorType = - csm::Error::SENSOR_MODEL_NOT_CONSTRUCTIBLE; - std::string aMessage = "Could not construct model ["; - aMessage += modelName; - aMessage += "] with error ["; - aMessage += e.what(); - aMessage += "]"; - std::string aFunction = "UsgsAstroPlugin::constructModelFromISD()"; - MESSAGE_LOG(spdlog::level::err, aMessage); - throw csm::Error(aErrorType, aMessage, aFunction); - } - return model; - } else if (modelName == UsgsAstroProjectedLsSensorModel::_SENSOR_MODEL_NAME) { - UsgsAstroProjectedLsSensorModel *model = new UsgsAstroProjectedLsSensorModel(); - try { - MESSAGE_LOG(spdlog::level::debug, "Trying to construct a UsgsAstroProjectedLsSensorModel"); - model->replaceModelState( - model->constructStateFromIsd(stringIsd, warnings)); - } catch (std::exception &e) { - delete model; - csm::Error::ErrorType aErrorType = - csm::Error::SENSOR_MODEL_NOT_CONSTRUCTIBLE; - std::string aMessage = "Could not construct model ["; - aMessage += modelName; - aMessage += "] with error ["; - aMessage += e.what(); - aMessage += "]"; - std::string aFunction = "UsgsAstroPlugin::constructModelFromISD()"; - MESSAGE_LOG(spdlog::level::err, aMessage); - throw csm::Error(aErrorType, aMessage, aFunction); - } - return model; - } else if (modelName == UsgsAstroSarSensorModel::_SENSOR_MODEL_NAME) { - UsgsAstroSarSensorModel *model = new UsgsAstroSarSensorModel(); - MESSAGE_LOG(spdlog::level::debug, "Trying to construct a UsgsAstroSarSensorModel"); - try { - model->replaceModelState( - model->constructStateFromIsd(stringIsd, warnings)); - } catch (std::exception &e) { - delete model; + delete projModel; csm::Error::ErrorType aErrorType = csm::Error::SENSOR_MODEL_NOT_CONSTRUCTIBLE; std::string aMessage = "Could not construct model ["; @@ -404,37 +349,13 @@ csm::Model *UsgsAstroPlugin::constructModelFromISD( aMessage += "] with error ["; aMessage += e.what(); aMessage += "]"; - std::string aFunction = "UsgsAstroPlugin::constructModelFromISD()"; MESSAGE_LOG(spdlog::level::err, aMessage); + std::string aFunction = "UsgsAstroPlugin::getUsgsCsmModel()"; throw csm::Error(aErrorType, aMessage, aFunction); } + } catch(std::exception &e) { + MESSAGE_LOG(spdlog::level::info, "Failed to make projected model with error: \n{}", e.what()); return model; - } else if (modelName == UsgsAstroPushFrameSensorModel::_SENSOR_MODEL_NAME) { - UsgsAstroPushFrameSensorModel *model = new UsgsAstroPushFrameSensorModel(); - MESSAGE_LOG(spdlog::level::debug, "Trying to construct a UsgsAstroPushFrameSensorModel"); - try { - model->replaceModelState( - model->constructStateFromIsd(stringIsd, warnings)); - } catch (std::exception &e) { - delete model; - csm::Error::ErrorType aErrorType = - csm::Error::SENSOR_MODEL_NOT_CONSTRUCTIBLE; - std::string aMessage = "Could not construct model ["; - aMessage += modelName; - aMessage += "] with error ["; - aMessage += e.what(); - aMessage += "]"; - std::string aFunction = "UsgsAstroPlugin::constructModelFromISD()"; - MESSAGE_LOG(spdlog::level::err, aMessage); - throw csm::Error(aErrorType, aMessage, aFunction); - } - return model; - } else { - csm::Error::ErrorType aErrorType = csm::Error::SENSOR_MODEL_NOT_SUPPORTED; - std::string aMessage = "Model [" + modelName + "] not supported: "; - std::string aFunction = "UsgsAstroPlugin::constructModelFromISD()"; - MESSAGE_LOG(spdlog::level::err, aMessage); - throw csm::Error(aErrorType, aMessage, aFunction); } } @@ -455,9 +376,9 @@ csm::Model *UsgsAstroPlugin::constructModelFromState( UsgsAstroLsSensorModel *model = new UsgsAstroLsSensorModel(); model->replaceModelState(modelState); return model; - } else if (modelName == UsgsAstroProjectedLsSensorModel::_SENSOR_MODEL_NAME) { - MESSAGE_LOG(spdlog::level::debug, "Constructing a UsgsAstroProjectedLsSensorModel"); - UsgsAstroProjectedLsSensorModel *model = new UsgsAstroProjectedLsSensorModel(); + } else if (modelName == UsgsAstroProjectedSensorModel::_SENSOR_MODEL_NAME) { + MESSAGE_LOG(spdlog::level::debug, "Constructing a UsgsAstroProjectedSensorModel"); + UsgsAstroProjectedSensorModel *model = new UsgsAstroProjectedSensorModel(); model->replaceModelState(modelState); return model; }else if (modelName == UsgsAstroSarSensorModel::_SENSOR_MODEL_NAME) { diff --git a/src/UsgsAstroPluginSupport.cpp b/src/UsgsAstroPluginSupport.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e4d25859fd8b2b300da6928f63bec02239996e7e --- /dev/null +++ b/src/UsgsAstroPluginSupport.cpp @@ -0,0 +1,97 @@ +#include "UsgsAstroPluginSupport.h" + +#include "UsgsAstroFrameSensorModel.h" +#include "UsgsAstroLsSensorModel.h" +#include "UsgsAstroPushFrameSensorModel.h" +#include "UsgsAstroSarSensorModel.h" + +#include <fstream> + +#include "spdlog/spdlog.h" + +#include <nlohmann/json.hpp> +using json = nlohmann::json; + +csm::RasterGM *getUsgsCsmModel( + const std::string &stringIsd, const std::string &modelName, + csm::WarningList *warnings) { + if (modelName == UsgsAstroFrameSensorModel::_SENSOR_MODEL_NAME) { + UsgsAstroFrameSensorModel *model = new UsgsAstroFrameSensorModel(); + try { + model->replaceModelState( + model->constructStateFromIsd(stringIsd, warnings)); + } catch (std::exception &e) { + delete model; + csm::Error::ErrorType aErrorType = + csm::Error::SENSOR_MODEL_NOT_CONSTRUCTIBLE; + std::string aMessage = "Could not construct model ["; + aMessage += modelName; + aMessage += "] with error ["; + aMessage += e.what(); + aMessage += "]"; + std::string aFunction = "UsgsAstroPluginSupport::getUsgsCsmModel()"; + throw csm::Error(aErrorType, aMessage, aFunction); + } + return model; + } else if (modelName == UsgsAstroLsSensorModel::_SENSOR_MODEL_NAME) { + UsgsAstroLsSensorModel *model = new UsgsAstroLsSensorModel(); + try { + model->replaceModelState( + model->constructStateFromIsd(stringIsd, warnings)); + } catch (std::exception &e) { + delete model; + csm::Error::ErrorType aErrorType = + csm::Error::SENSOR_MODEL_NOT_CONSTRUCTIBLE; + std::string aMessage = "Could not construct model ["; + aMessage += modelName; + aMessage += "] with error ["; + aMessage += e.what(); + aMessage += "]"; + std::string aFunction = "UsgsAstroPluginSupport::getUsgsCsmModel()"; + throw csm::Error(aErrorType, aMessage, aFunction); + } + return model; + } else if (modelName == UsgsAstroSarSensorModel::_SENSOR_MODEL_NAME) { + UsgsAstroSarSensorModel *model = new UsgsAstroSarSensorModel(); + try { + model->replaceModelState( + model->constructStateFromIsd(stringIsd, warnings)); + } catch (std::exception &e) { + delete model; + csm::Error::ErrorType aErrorType = + csm::Error::SENSOR_MODEL_NOT_CONSTRUCTIBLE; + std::string aMessage = "Could not construct model ["; + aMessage += modelName; + aMessage += "] with error ["; + aMessage += e.what(); + aMessage += "]"; + std::string aFunction = "UsgsAstroPluginSupport::getUsgsCsmModel()"; + throw csm::Error(aErrorType, aMessage, aFunction); + } + return model; + } else if (modelName == UsgsAstroPushFrameSensorModel::_SENSOR_MODEL_NAME) { + UsgsAstroPushFrameSensorModel *model = new UsgsAstroPushFrameSensorModel(); + try { + model->replaceModelState( + model->constructStateFromIsd(stringIsd, warnings)); + } catch (std::exception &e) { + delete model; + csm::Error::ErrorType aErrorType = + csm::Error::SENSOR_MODEL_NOT_CONSTRUCTIBLE; + std::string aMessage = "Could not construct model ["; + aMessage += modelName; + aMessage += "] with error ["; + aMessage += e.what(); + aMessage += "]"; + std::string aFunction = "UsgsAstroPluginSupport::getUsgsCsmModel()"; + throw csm::Error(aErrorType, aMessage, aFunction); + } + return model; + } else { + csm::Error::ErrorType aErrorType = csm::Error::SENSOR_MODEL_NOT_SUPPORTED; + std::string aMessage = "Model [" + modelName + "] not supported: "; + std::string aFunction = "UsgsAstroPluginSupport::getUsgsCsmModel()"; + throw csm::Error(aErrorType, aMessage, aFunction); + } + +} \ No newline at end of file diff --git a/src/UsgsAstroProjectedLsSensorModel.cpp b/src/UsgsAstroProjectedLsSensorModel.cpp deleted file mode 100644 index d2eb6395dbacb0a42c7354834852adea82fb6d8c..0000000000000000000000000000000000000000 --- a/src/UsgsAstroProjectedLsSensorModel.cpp +++ /dev/null @@ -1,398 +0,0 @@ -/** Copyright © 2017-2022 BAE Systems Information and Electronic Systems Integration Inc. - -Redistribution and use in source and binary forms, with or without modification, are permitted -provided that the following conditions are met: - -1. Redistributions of source code must retain the above copyright notice, this list of conditions -and the following disclaimer. - -2. Redistributions in binary form must reproduce the above copyright notice, this list of -conditions and the following disclaimer in the documentation and/or other materials provided -with the distribution. - -3. Neither the name of the copyright holder nor the names of its contributors may be used to -endorse or promote products derived from this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR -IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR -CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER -IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT -OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. **/ - -#include "UsgsAstroProjectedLsSensorModel.h" -#include "Utilities.h" - -#include <proj.h> - -#include <Error.h> -#include <nlohmann/json.hpp> - -#include "ale/Util.h" - -#define MESSAGE_LOG(...) \ - if (m_logger) { \ - m_logger->log(__VA_ARGS__); \ - } - -using json = nlohmann::json; - -const std::string UsgsAstroProjectedLsSensorModel::_SENSOR_MODEL_NAME = - "USGS_ASTRO_PROJECTED_LINE_SCANNER_SENSOR_MODEL"; - -const std::string UsgsAstroProjectedLsSensorModel::_STATE_KEYWORD[] = { - "m_modelName", - "m_imageIdentifier", - "m_sensorName", - "m_nLines", - "m_nSamples", - "m_platformFlag", - "m_intTimeLines", - "m_intTimeStartTimes", - "m_intTimes", - "m_startingEphemerisTime", - "m_centerEphemerisTime", - "m_detectorSampleSumming", - "m_detectorSampleSumming", - "m_startingDetectorSample", - "m_startingDetectorLine", - "m_ikCode", - "m_focalLength", - "m_zDirection", - "m_distortionType", - "m_opticalDistCoeffs", - "m_iTransS", - "m_iTransL", - "m_detectorSampleOrigin", - "m_detectorLineOrigin", - "m_majorAxis", - "m_minorAxis", - "m_platformIdentifier", - "m_sensorIdentifier", - "m_minElevation", - "m_maxElevation", - "m_dtEphem", - "m_t0Ephem", - "m_dtQuat", - "m_t0Quat", - "m_numPositions", - "m_numQuaternions", - "m_positions", - "m_velocities", - "m_quaternions", - "m_currentParameterValue", - "m_parameterType", - "m_referencePointXyz", - "m_sunPosition", - "m_sunVelocity", - "m_gsd", - "m_flyingHeight", - "m_halfSwath", - "m_halfTime", - "m_covariance", - "m_geoTransform", - "m_projString", -}; - -//*************************************************************************** -// UsgsAstroLineScannerSensorModel::replaceModelState -//*************************************************************************** -void UsgsAstroProjectedLsSensorModel::replaceModelState(const std::string& stateString) { - reset(); - - auto j = stateAsJson(stateString); - m_geoTransform = j["m_geoTransform"].get<std::vector<double>>(); - m_projString = j["m_projString"]; - MESSAGE_LOG( - spdlog::level::trace, - "m_geoTransform: {} " - "m_projString: {} ", - j["m_geoTransform"].dump(), j["m_projString"].dump()); - UsgsAstroLsSensorModel::replaceModelState(stateString); -} - -//*************************************************************************** -// UsgsAstroLineScannerSensorModel::getModelNameFromModelState -//*************************************************************************** -std::string UsgsAstroProjectedLsSensorModel::getModelNameFromModelState( - const std::string& model_state) { - // Parse the string to JSON - auto j = stateAsJson(model_state); - // If model name cannot be determined, return a blank string - std::string model_name; - - if (j.find("m_modelName") != j.end()) { - model_name = j["m_modelName"]; - } else { - csm::Error::ErrorType aErrorType = csm::Error::INVALID_SENSOR_MODEL_STATE; - std::string aMessage = "No 'm_modelName' key in the model state object."; - std::string aFunction = "UsgsAstroProjectedLsPlugin::getModelNameFromModelState"; - csm::Error csmErr(aErrorType, aMessage, aFunction); - throw(csmErr); - } - if (model_name != _SENSOR_MODEL_NAME) { - csm::Error::ErrorType aErrorType = csm::Error::SENSOR_MODEL_NOT_SUPPORTED; - std::string aMessage = "Sensor model not supported."; - std::string aFunction = "UsgsAstroProjectedLsPlugin::getModelNameFromModelState()"; - csm::Error csmErr(aErrorType, aMessage, aFunction); - throw(csmErr); - } - return model_name; -} - -//*************************************************************************** -// UsgsAstroLineScannerSensorModel::getModelState -//*************************************************************************** -std::string UsgsAstroProjectedLsSensorModel::getModelState() const { - auto state = stateAsJson(UsgsAstroLsSensorModel::getModelState()); - state["m_geoTransform"] = m_geoTransform; - state["m_projString"] = m_projString; - MESSAGE_LOG( - spdlog::level::trace, - "m_geoTransform: {}, {}, {}, {}, {}, {} " - "m_projString: {} ", - m_geoTransform[0], - m_geoTransform[1], - m_geoTransform[2], - m_geoTransform[3], - m_geoTransform[4], - m_geoTransform[5], - m_projString); - // Use dump(2) to avoid creating the model string as a single long line - std::string stateString = getModelName() + "\n" + state.dump(2); - return stateString; -} - -//*************************************************************************** -// UsgsAstroLineScannerSensorModel::reset -//*************************************************************************** -void UsgsAstroProjectedLsSensorModel::reset() { - MESSAGE_LOG(spdlog::level::debug, "Running reset()"); - - m_geoTransform = std::vector<double>(6, 0.0); - m_projString = ""; -} - -//***************************************************************************** -// UsgsAstroProjectedLsSensorModel Constructor -//***************************************************************************** -UsgsAstroProjectedLsSensorModel::UsgsAstroProjectedLsSensorModel() : UsgsAstroLsSensorModel() {} - -//***************************************************************************** -// UsgsAstroProjectedLsSensorModel Destructor -//***************************************************************************** -UsgsAstroProjectedLsSensorModel::~UsgsAstroProjectedLsSensorModel() {} - -//--------------------------------------------------------------------------- -// Core Photogrammetry -//--------------------------------------------------------------------------- - -//*************************************************************************** -// UsgsAstroLsSensorModel::groundToImage -//*************************************************************************** -csm::ImageCoord UsgsAstroProjectedLsSensorModel::groundToImage( - const csm::EcefCoord &ground_pt, double desired_precision, - double *achieved_precision, csm::WarningList *warnings) const { - - PJ_CONTEXT *C = proj_context_create(); - - /* Create a projection. */ - PJ *isdProj = proj_create(C, (m_projString + " +type=crs").c_str()); - if (0 == isdProj) { - MESSAGE_LOG( - spdlog::level::debug, - "Failed to create isd transformation object"); - return csm::ImageCoord(0, 0); - } - - /* Create the geocentric projection for our target */ - std::string radius_a = "+a=" + std::to_string(m_majorAxis); - std::string radius_b = "+b=" + std::to_string(m_minorAxis); - std::string projString = "+proj=geocent " + radius_a + " " + radius_b + " +type=crs"; - PJ *ecefProj = proj_create(C, projString.c_str()); - if (0 == ecefProj) { - MESSAGE_LOG( - spdlog::level::debug, - "Failed to create geocent transformation object"); - return csm::ImageCoord(0, 0); - } - - // Compute the transformation from our ISIS projection to ecef - PJ *isdProj2ecefProj = proj_create_crs_to_crs_from_pj(C, isdProj, ecefProj, 0, 0); - PJ_COORD c_in; - c_in.xyz.x = ground_pt.x; - c_in.xyz.y = ground_pt.y; - c_in.xyz.z = ground_pt.z; - MESSAGE_LOG( - spdlog::level::info, - "Ground point {}, {}, {}", - c_in.xyz.x, c_in.xyz.y, c_in.xyz.z); - PJ_COORD c_out = proj_trans(isdProj2ecefProj, PJ_INV, c_in); - MESSAGE_LOG( - spdlog::level::info, - "Meters {}, {}", - c_out.xyz.x, c_out.xyz.y); - std::vector<double> lineSampleCoord = meterToPixel(c_out.xyz.x, c_out.xyz.y, m_geoTransform); - csm::ImageCoord imagePt(lineSampleCoord[0], lineSampleCoord[1]); - MESSAGE_LOG( - spdlog::level::info, - "groundToImage result of ({}, {})", - imagePt.line, imagePt.samp); - return imagePt; -} - -//*************************************************************************** -// UsgsAstroLsSensorModel::groundToImage -//*************************************************************************** -csm::ImageCoordCovar UsgsAstroProjectedLsSensorModel::groundToImage( - const csm::EcefCoordCovar &groundPt, double desired_precision, - double *achieved_precision, csm::WarningList *warnings) const { - csm::ImageCoordCovar imageCoordCovar = UsgsAstroLsSensorModel::groundToImage(groundPt, desired_precision, achieved_precision, warnings); - csm::ImageCoord projImagePt = groundToImage(groundPt); - - imageCoordCovar.line = projImagePt.line; - imageCoordCovar.samp = projImagePt.samp; - return imageCoordCovar; -} - -//*************************************************************************** -// UsgsAstroProjectedLsSensorModel::imageToGround -//*************************************************************************** -csm::EcefCoord UsgsAstroProjectedLsSensorModel::imageToGround( - const csm::ImageCoord& image_pt, double height, double desired_precision, - double* achieved_precision, csm::WarningList* warnings) const { - MESSAGE_LOG( - spdlog::level::info, - "Computing imageToGround for {}, {}, {}, with desired precision {}", - image_pt.line, image_pt.samp, height, desired_precision); - - double x = 0, y = 0, z = 0; - double meterLine, meterSamp; - std::vector<double> meterCoord = pixelToMeter(image_pt.line, image_pt.samp, m_geoTransform); - meterLine = meterCoord[0]; - meterSamp = meterCoord[1]; - PJ_CONTEXT *C = proj_context_create(); - - /* Create a projection. */ - PJ *isdProj = proj_create(C, (m_projString + " +type=crs").c_str()); - if (0 == isdProj) { - MESSAGE_LOG( - spdlog::level::debug, - "Failed to create isd transformation object"); - return csm::EcefCoord(x, y, z); - } - - /* Create the geocentric projection for our target */ - std::string radius_a = "+a=" + std::to_string(m_majorAxis); - std::string radius_b = "+b=" + std::to_string(m_minorAxis); - std::string projString = "+proj=geocent " + radius_a + " " + radius_b + " +type=crs"; - PJ *ecefProj = proj_create(C, projString.c_str()); - if (0 == ecefProj) { - MESSAGE_LOG( - spdlog::level::debug, - "Failed to create geocent transformation object"); - return csm::EcefCoord(x, y, z); - } - - // Compute the transformation from our ISIS projection to ecef - PJ *isdProj2ecefProj = proj_create_crs_to_crs_from_pj(C, isdProj, ecefProj, 0, 0); - PJ_COORD c_in; - c_in.xy.x = meterSamp; - c_in.xy.y = meterLine; - PJ_COORD c_out = proj_trans(isdProj2ecefProj, PJ_FWD, c_in); - x = c_out.xyz.x, y = c_out.xyz.y, z = c_out.xyz.z; - MESSAGE_LOG( - spdlog::level::info, - "imageToGround result {} {} {}", - x, y, z); - return csm::EcefCoord(x, y, z); -} - -//*************************************************************************** -// UsgsAstroProjectedLsSensorModel::imageToGround -//*************************************************************************** -csm::EcefCoordCovar UsgsAstroProjectedLsSensorModel::imageToGround( - const csm::ImageCoordCovar& image_pt, double height, double heightVariance, - double desired_precision, double* achieved_precision, - csm::WarningList* warnings) const { - csm::EcefCoord groundCoord = imageToGround(image_pt, height); - csm::ImageCoord cameraImagePt = UsgsAstroLsSensorModel::groundToImage(groundCoord); - csm::ImageCoordCovar cameraImagePtCovar(cameraImagePt.line, cameraImagePt.samp); - - return UsgsAstroLsSensorModel::imageToGround(cameraImagePtCovar, height, heightVariance, desired_precision, achieved_precision, warnings); -} - -//*************************************************************************** -// UsgsAstroProjectedLsSensorModel::imageToProximateImagingLocus -//*************************************************************************** -csm::EcefLocus UsgsAstroProjectedLsSensorModel::imageToProximateImagingLocus( - const csm::ImageCoord& image_pt, const csm::EcefCoord& ground_pt, - double desired_precision, double* achieved_precision, - csm::WarningList* warnings) const { - csm::EcefCoord projGround = imageToGround(image_pt, 0); - csm::ImageCoord cameraImagePt = UsgsAstroLsSensorModel::groundToImage(projGround); - - return UsgsAstroLsSensorModel::imageToProximateImagingLocus(cameraImagePt, ground_pt, desired_precision, achieved_precision, warnings); -} - -//*************************************************************************** -// UsgsAstroProjectedLsSensorModel::imageToRemoteImagingLocus -//*************************************************************************** -csm::EcefLocus UsgsAstroProjectedLsSensorModel::imageToRemoteImagingLocus( - const csm::ImageCoord& image_pt, double desired_precision, - double* achieved_precision, csm::WarningList* warnings) const { - // Go from proj x, y to latlon then ground to image - // Convert imagept to camera imagept - csm::EcefCoord groundCoord = imageToGround(image_pt, 0); - csm::ImageCoord cameraImagePt = UsgsAstroLsSensorModel::groundToImage(groundCoord); - - return UsgsAstroLsSensorModel::imageToRemoteImagingLocus(cameraImagePt, desired_precision, achieved_precision, warnings); -} - -//--------------------------------------------------------------------------- -// Sensor Model Information -//--------------------------------------------------------------------------- - -//*************************************************************************** -// UsgsAstroProjectedLsSensorModel::getPedigree -//*************************************************************************** -std::string UsgsAstroProjectedLsSensorModel::getPedigree() const { - return "USGS_PROJECTED_LINE_SCANNER"; -} - -//*************************************************************************** -// UsgsAstroProjectedLsSensorModel::getSensorModelName -//*************************************************************************** -std::string UsgsAstroProjectedLsSensorModel::getModelName() const { - return UsgsAstroProjectedLsSensorModel::_SENSOR_MODEL_NAME; -} - -//*************************************************************************** -// UsgsAstroProjectedLsSensorModel::getVersion -//*************************************************************************** -csm::Version UsgsAstroProjectedLsSensorModel::getVersion() const { - return csm::Version(1, 0, 0); -} - -//*************************************************************************** -// UsgsAstroLineScannerSensorModel::constructStateFromIsd -//*************************************************************************** -std::string UsgsAstroProjectedLsSensorModel::constructStateFromIsd( - const std::string imageSupportData, csm::WarningList* warnings) { - // return UsgsAstroLsSensorModel::constructStateFromIsd(imageSupportData, warnings); - json lsState = json::parse(UsgsAstroLsSensorModel::constructStateFromIsd(imageSupportData, warnings)); - json state = json::parse(imageSupportData); - - lsState["m_geoTransform"] = ale::getGeoTransform(state); - lsState["m_projString"] = ale::getProjection(state); - MESSAGE_LOG( - spdlog::level::trace, - "m_geoTransform: {} " - "m_projString: {} ", - lsState["m_geoTransform"].dump(), lsState["m_projString"].dump()); - // The state data will still be updated when a sensor model is created since - // some state data is not in the ISD and requires a SM to compute them. - return lsState.dump(); -} diff --git a/src/UsgsAstroProjectedSensorModel.cpp b/src/UsgsAstroProjectedSensorModel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..6ee91166e5eebfe6d0c9e384622bd181132f6536 --- /dev/null +++ b/src/UsgsAstroProjectedSensorModel.cpp @@ -0,0 +1,824 @@ +/** Copyright © 2017-2022 BAE Systems Information and Electronic Systems Integration Inc. + +Redistribution and use in source and binary forms, with or without modification, are permitted +provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions +and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this list of +conditions and the following disclaimer in the documentation and/or other materials provided +with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors may be used to +endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR +CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER +IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. **/ + +#include "UsgsAstroProjectedSensorModel.h" +#include "UsgsAstroPluginSupport.h" +#include "Utilities.h" + +#include <proj.h> + +#include <Error.h> +#include <nlohmann/json.hpp> + +#include "ale/Util.h" + +#define MESSAGE_LOG(...) \ + if (m_logger) { \ + m_logger->log(__VA_ARGS__); \ + } + +using json = nlohmann::json; + +const std::string UsgsAstroProjectedSensorModel::_SENSOR_MODEL_NAME = + "USGS_ASTRO_PROJECTED_SENSOR_MODEL"; + +const std::string UsgsAstroProjectedSensorModel::_STATE_KEYWORD[] = { + "m_modelName", + "m_imageIdentifier", + "m_sensorName", + "m_nLines", + "m_nSamples", + "m_platformFlag", + "m_intTimeLines", + "m_intTimeStartTimes", + "m_intTimes", + "m_startingEphemerisTime", + "m_centerEphemerisTime", + "m_detectorSampleSumming", + "m_detectorSampleSumming", + "m_startingDetectorSample", + "m_startingDetectorLine", + "m_ikCode", + "m_focalLength", + "m_zDirection", + "m_distortionType", + "m_opticalDistCoeffs", + "m_iTransS", + "m_iTransL", + "m_detectorSampleOrigin", + "m_detectorLineOrigin", + "m_majorAxis", + "m_minorAxis", + "m_platformIdentifier", + "m_sensorIdentifier", + "m_minElevation", + "m_maxElevation", + "m_dtEphem", + "m_t0Ephem", + "m_dtQuat", + "m_t0Quat", + "m_numPositions", + "m_numQuaternions", + "m_positions", + "m_velocities", + "m_quaternions", + "m_currentParameterValue", + "m_parameterType", + "m_referencePointXyz", + "m_sunPosition", + "m_sunVelocity", + "m_gsd", + "m_flyingHeight", + "m_halfSwath", + "m_halfTime", + "m_covariance", + "m_geoTransform", + "m_projString", +}; + +//*************************************************************************** +// UsgsAstroLineScannerSensorModel::replaceModelState +//*************************************************************************** +void UsgsAstroProjectedSensorModel::replaceModelState(const std::string& stateString) { + reset(); + + auto j = stateAsJson(stateString); + m_majorAxis = j["m_majorAxis"]; + m_minorAxis = j["m_minorAxis"]; + m_geoTransform = j["m_geoTransform"].get<std::vector<double>>(); + m_projString = j["m_projString"]; + MESSAGE_LOG( + spdlog::level::trace, + "m_majorAxis: {} " + "m_minorAxis: {} " + "m_geoTransform: {} " + "m_projString: {} ", + j["m_majorAxis"].dump(), j["m_minorAxis"].dump(), j["m_geoTransform"].dump(), j["m_projString"].dump()); + m_camera->replaceModelState(stateString); +} + +//*************************************************************************** +// UsgsAstroLineScannerSensorModel::getModelNameFromModelState +//*************************************************************************** +std::string UsgsAstroProjectedSensorModel::getModelNameFromModelState( + const std::string& model_state) { + // Parse the string to JSON + auto j = stateAsJson(model_state); + // If model name cannot be determined, return a blank string + std::string model_name; + + if (j.find("m_modelName") != j.end()) { + model_name = j["m_modelName"]; + } else { + csm::Error::ErrorType aErrorType = csm::Error::INVALID_SENSOR_MODEL_STATE; + std::string aMessage = "No 'm_modelName' key in the model state object."; + std::string aFunction = "UsgsAstroProjectedPlugin::getModelNameFromModelState"; + csm::Error csmErr(aErrorType, aMessage, aFunction); + throw(csmErr); + } + if (model_name != _SENSOR_MODEL_NAME) { + csm::Error::ErrorType aErrorType = csm::Error::SENSOR_MODEL_NOT_SUPPORTED; + std::string aMessage = "Sensor model not supported."; + std::string aFunction = "UsgsAstroProjectedPlugin::getModelNameFromModelState()"; + csm::Error csmErr(aErrorType, aMessage, aFunction); + throw(csmErr); + } + return model_name; +} + +//*************************************************************************** +// UsgsAstroLineScannerSensorModel::getModelState +//*************************************************************************** +std::string UsgsAstroProjectedSensorModel::getModelState() const { + auto state = stateAsJson(m_camera->getModelState()); + state["m_modelName"] = _SENSOR_MODEL_NAME; + state["m_majorAxis"] = m_majorAxis; + state["m_minorAxis"] = m_minorAxis; + state["m_geoTransform"] = m_geoTransform; + state["m_projString"] = m_projString; + MESSAGE_LOG( + spdlog::level::trace, + "m_majorAxis: {} " + "m_minorAxis: {} " + "m_geoTransform: {}, {}, {}, {}, {}, {} " + "m_projString: {} ", + m_majorAxis, + m_minorAxis, + m_geoTransform[0], + m_geoTransform[1], + m_geoTransform[2], + m_geoTransform[3], + m_geoTransform[4], + m_geoTransform[5], + m_projString); + // Use dump(2) to avoid creating the model string as a single long line + std::string stateString = getModelName() + "\n" + state.dump(2); + return stateString; +} + +//*************************************************************************** +// UsgsAstroLineScannerSensorModel::reset +//*************************************************************************** +void UsgsAstroProjectedSensorModel::reset() { + MESSAGE_LOG(spdlog::level::debug, "Running reset()"); + + m_majorAxis = 3400000.0; + m_minorAxis = 3350000.0; + m_geoTransform = std::vector<double>(6, 0.0); + m_projString = ""; +} + +//***************************************************************************** +// UsgsAstroProjectedSensorModel Constructor +//***************************************************************************** +UsgsAstroProjectedSensorModel::UsgsAstroProjectedSensorModel() {} + +//***************************************************************************** +// UsgsAstroProjectedSensorModel Destructor +//***************************************************************************** +UsgsAstroProjectedSensorModel::~UsgsAstroProjectedSensorModel() {} + +//--------------------------------------------------------------------------- +// Core Photogrammetry +//--------------------------------------------------------------------------- + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::groundToImage +//*************************************************************************** +csm::ImageCoord UsgsAstroProjectedSensorModel::groundToImage( + const csm::EcefCoord &ground_pt, double desired_precision, + double *achieved_precision, csm::WarningList *warnings) const { + + PJ_CONTEXT *C = proj_context_create(); + + /* Create a projection. */ + PJ *isdProj = proj_create(C, (m_projString + " +type=crs").c_str()); + if (0 == isdProj) { + MESSAGE_LOG( + spdlog::level::debug, + "Failed to create isd transformation object"); + return csm::ImageCoord(0, 0); + } + + /* Create the geocentric projection for our target */ + std::string radius_a = "+a=" + std::to_string(m_majorAxis); + std::string radius_b = "+b=" + std::to_string(m_minorAxis); + std::string projString = "+proj=geocent " + radius_a + " " + radius_b + " +type=crs"; + PJ *ecefProj = proj_create(C, projString.c_str()); + if (0 == ecefProj) { + MESSAGE_LOG( + spdlog::level::debug, + "Failed to create geocent transformation object"); + return csm::ImageCoord(0, 0); + } + + // Compute the transformation from our ISIS projection to ecef + PJ *isdProj2ecefProj = proj_create_crs_to_crs_from_pj(C, isdProj, ecefProj, 0, 0); + PJ_COORD c_in; + c_in.xyz.x = ground_pt.x; + c_in.xyz.y = ground_pt.y; + c_in.xyz.z = ground_pt.z; + MESSAGE_LOG( + spdlog::level::info, + "Ground point {}, {}, {}", + c_in.xyz.x, c_in.xyz.y, c_in.xyz.z); + PJ_COORD c_out = proj_trans(isdProj2ecefProj, PJ_INV, c_in); + MESSAGE_LOG( + spdlog::level::info, + "Meters {}, {}", + c_out.xyz.x, c_out.xyz.y); + std::vector<double> lineSampleCoord = meterToPixel(c_out.xyz.x, c_out.xyz.y, m_geoTransform); + csm::ImageCoord imagePt(lineSampleCoord[0], lineSampleCoord[1]); + MESSAGE_LOG( + spdlog::level::info, + "groundToImage result of ({}, {})", + imagePt.line, imagePt.samp); + return imagePt; +} + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::groundToImage +//*************************************************************************** +csm::ImageCoordCovar UsgsAstroProjectedSensorModel::groundToImage( + const csm::EcefCoordCovar &groundPt, double desired_precision, + double *achieved_precision, csm::WarningList *warnings) const { + csm::ImageCoordCovar imageCoordCovar = m_camera->groundToImage(groundPt, desired_precision, achieved_precision, warnings); + csm::ImageCoord projImagePt = groundToImage(groundPt); + + imageCoordCovar.line = projImagePt.line; + imageCoordCovar.samp = projImagePt.samp; + return imageCoordCovar; +} + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::imageToGround +//*************************************************************************** +csm::EcefCoord UsgsAstroProjectedSensorModel::imageToGround( + const csm::ImageCoord& image_pt, double height, double desired_precision, + double* achieved_precision, csm::WarningList* warnings) const { + MESSAGE_LOG( + spdlog::level::info, + "Computing imageToGround for {}, {}, {}, with desired precision {}", + image_pt.line, image_pt.samp, height, desired_precision); + + double x = 0, y = 0, z = 0; + double meterLine, meterSamp; + std::vector<double> meterCoord = pixelToMeter(image_pt.line, image_pt.samp, m_geoTransform); + meterLine = meterCoord[0]; + meterSamp = meterCoord[1]; + PJ_CONTEXT *C = proj_context_create(); + + /* Create a projection. */ + PJ *isdProj = proj_create(C, (m_projString + " +type=crs").c_str()); + if (0 == isdProj) { + MESSAGE_LOG( + spdlog::level::debug, + "Failed to create isd transformation object"); + return csm::EcefCoord(x, y, z); + } + + /* Create the geocentric projection for our target */ + std::string radius_a = "+a=" + std::to_string(m_majorAxis); + std::string radius_b = "+b=" + std::to_string(m_minorAxis); + std::string projString = "+proj=geocent " + radius_a + " " + radius_b + " +type=crs"; + PJ *ecefProj = proj_create(C, projString.c_str()); + if (0 == ecefProj) { + MESSAGE_LOG( + spdlog::level::debug, + "Failed to create geocent transformation object"); + return csm::EcefCoord(x, y, z); + } + + // Compute the transformation from our ISIS projection to ecef + PJ *isdProj2ecefProj = proj_create_crs_to_crs_from_pj(C, isdProj, ecefProj, 0, 0); + PJ_COORD c_in; + c_in.xy.x = meterSamp; + c_in.xy.y = meterLine; + PJ_COORD c_out = proj_trans(isdProj2ecefProj, PJ_FWD, c_in); + x = c_out.xyz.x, y = c_out.xyz.y, z = c_out.xyz.z; + MESSAGE_LOG( + spdlog::level::info, + "imageToGround result {} {} {}", + x, y, z); + return csm::EcefCoord(x, y, z); +} + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::imageToGround +//*************************************************************************** +csm::EcefCoordCovar UsgsAstroProjectedSensorModel::imageToGround( + const csm::ImageCoordCovar& image_pt, double height, double heightVariance, + double desired_precision, double* achieved_precision, + csm::WarningList* warnings) const { + csm::EcefCoord groundCoord = imageToGround(image_pt, height); + csm::ImageCoord cameraImagePt = m_camera->groundToImage(groundCoord); + csm::ImageCoordCovar cameraImagePtCovar(cameraImagePt.line, cameraImagePt.samp); + + return m_camera->imageToGround(cameraImagePtCovar, height, heightVariance, desired_precision, achieved_precision, warnings); +} + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::imageToProximateImagingLocus +//*************************************************************************** +csm::EcefLocus UsgsAstroProjectedSensorModel::imageToProximateImagingLocus( + const csm::ImageCoord& image_pt, const csm::EcefCoord& ground_pt, + double desired_precision, double* achieved_precision, + csm::WarningList* warnings) const { + csm::EcefCoord projGround = imageToGround(image_pt, 0); + csm::ImageCoord cameraImagePt = m_camera->groundToImage(projGround); + + return m_camera->imageToProximateImagingLocus(cameraImagePt, ground_pt, desired_precision, achieved_precision, warnings); +} + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::imageToRemoteImagingLocus +//*************************************************************************** +csm::EcefLocus UsgsAstroProjectedSensorModel::imageToRemoteImagingLocus( + const csm::ImageCoord& image_pt, double desired_precision, + double* achieved_precision, csm::WarningList* warnings) const { + // Go from proj x, y to latlon then ground to image + // Convert imagept to camera imagept + csm::EcefCoord groundCoord = imageToGround(image_pt, 0); + csm::ImageCoord cameraImagePt = m_camera->groundToImage(groundCoord); + + return m_camera->imageToRemoteImagingLocus(cameraImagePt, desired_precision, achieved_precision, warnings); +} + +//--------------------------------------------------------------------------- +// Uncertainty Propagation +//--------------------------------------------------------------------------- + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::computeGroundPartials +//*************************************************************************** +std::vector<double> UsgsAstroProjectedSensorModel::computeGroundPartials( + const csm::EcefCoord& ground_pt) const { + return m_camera->computeGroundPartials(ground_pt); +} + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::computeSensorPartials +//*************************************************************************** +csm::RasterGM::SensorPartials UsgsAstroProjectedSensorModel::computeSensorPartials( + int index, const csm::EcefCoord &groundPt, double desiredPrecision, + double *achievedPrecision, csm::WarningList *warnings) const { + MESSAGE_LOG( + spdlog::level::debug, + "Calculating computeSensorPartials for ground point {}, {}, {} with " + "desired precision {}", + groundPt.x, groundPt.y, groundPt.z, desiredPrecision) + + csm::ImageCoord imagePt = m_camera->groundToImage(groundPt, desiredPrecision, achievedPrecision); + + return m_camera->computeSensorPartials(index, imagePt, groundPt, desiredPrecision, + achievedPrecision, warnings); +} + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::computeSensorPartials +//*************************************************************************** +csm::RasterGM::SensorPartials UsgsAstroProjectedSensorModel::computeSensorPartials( + int index, const csm::ImageCoord &imagePt, const csm::EcefCoord &groundPt, + double desiredPrecision, double *achievedPrecision, + csm::WarningList *warnings) const { + return m_camera->computeSensorPartials(index, imagePt, groundPt, desiredPrecision, + achievedPrecision, warnings); +} + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::computeAllSensorPartials +//*************************************************************************** +std::vector<csm::RasterGM::SensorPartials> +UsgsAstroProjectedSensorModel::computeAllSensorPartials( + const csm::EcefCoord& ground_pt, csm::param::Set pSet, + double desired_precision, double* achieved_precision, + csm::WarningList* warnings) const { + + MESSAGE_LOG( + spdlog::level::info, + "Computing computeAllSensorPartials for ground point {}, {}, {} with " + "desired precision {}", + ground_pt.x, ground_pt.y, ground_pt.z, desired_precision) + csm::ImageCoord image_pt = + m_camera->groundToImage(ground_pt, desired_precision, achieved_precision, warnings); + + return computeAllSensorPartials(image_pt, ground_pt, pSet, desired_precision, + achieved_precision, warnings); +} + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::computeAllSensorPartials +//*************************************************************************** +std::vector<csm::RasterGM::SensorPartials> +UsgsAstroProjectedSensorModel::computeAllSensorPartials( + const csm::ImageCoord& image_pt, const csm::EcefCoord& ground_pt, + csm::param::Set pSet, double desired_precision, double* achieved_precision, + csm::WarningList* warnings) const { + + return m_camera->computeAllSensorPartials(image_pt, ground_pt, pSet, desired_precision, + achieved_precision, warnings); +} + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::getParameterCovariance +//*************************************************************************** +double UsgsAstroProjectedSensorModel::getParameterCovariance(int index1, + int index2) const { + return m_camera->getParameterCovariance(index1, index2); +} + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::setParameterCovariance +//*************************************************************************** +void UsgsAstroProjectedSensorModel::setParameterCovariance(int index1, int index2, + double covariance) { + m_camera->setParameterCovariance(index1, index2, covariance); +} + +//--------------------------------------------------------------------------- +// Time and Trajectory +//--------------------------------------------------------------------------- + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::getTrajectoryIdentifier +//*************************************************************************** +std::string UsgsAstroProjectedSensorModel::getTrajectoryIdentifier() const { + return m_camera->getTrajectoryIdentifier(); +} + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::getReferenceDateAndTime +//*************************************************************************** +std::string UsgsAstroProjectedSensorModel::getReferenceDateAndTime() const { + return m_camera->getReferenceDateAndTime(); +} + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::getImageTime +//*************************************************************************** +double UsgsAstroProjectedSensorModel::getImageTime( + const csm::ImageCoord& image_pt) const { + return m_camera->getImageTime(image_pt); +} + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::getSensorPosition +//*************************************************************************** +csm::EcefCoord UsgsAstroProjectedSensorModel::getSensorPosition( + const csm::ImageCoord& imagePt) const { + csm::EcefCoord ground = imageToGround(imagePt, 0); + csm::ImageCoord cameraImagePt = m_camera->groundToImage(ground); + + return getSensorPosition(m_camera->getImageTime(cameraImagePt)); +} + +//*************************************************************************** +// UsgsAstroLsSensorModel::getSensorPosition +//*************************************************************************** +csm::EcefCoord UsgsAstroProjectedSensorModel::getSensorPosition(double time) const { + return m_camera->getSensorPosition(time); +} + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::getSensorVelocity +//*************************************************************************** +csm::EcefVector UsgsAstroProjectedSensorModel::getSensorVelocity( + const csm::ImageCoord& imagePt) const { + csm::EcefCoord ground = imageToGround(imagePt, 0); + csm::ImageCoord cameraImagePt = m_camera->groundToImage(ground); + + return getSensorVelocity(m_camera->getImageTime(cameraImagePt)); +} + +//*************************************************************************** +// UsgsAstroLsSensorModel::getSensorPosition +//*************************************************************************** +csm::EcefVector UsgsAstroProjectedSensorModel::getSensorVelocity(double time) const { + return m_camera->getSensorVelocity(time); +} + +//--------------------------------------------------------------------------- +// Sensor Model Parameters +//--------------------------------------------------------------------------- + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::setParameterValue +//*************************************************************************** +void UsgsAstroProjectedSensorModel::setParameterValue(int index, double value) { + m_camera->setParameterValue(index, value); +} + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::getParameterValue +//*************************************************************************** +double UsgsAstroProjectedSensorModel::getParameterValue(int index) const { + return m_camera->getParameterValue(index); +} + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::getParameterName +//*************************************************************************** +std::string UsgsAstroProjectedSensorModel::getParameterName(int index) const { + return m_camera->getParameterName(index); +} + +std::string UsgsAstroProjectedSensorModel::getParameterUnits(int index) const { + // All parameters are meters or scaled to meters + return m_camera->getParameterUnits(index); +} + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::getNumParameters +//*************************************************************************** +int UsgsAstroProjectedSensorModel::getNumParameters() const { + return m_camera->getNumParameters(); +} + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::getParameterType +//*************************************************************************** +csm::param::Type UsgsAstroProjectedSensorModel::getParameterType(int index) const { + return m_camera->getParameterType(index); +} + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::setParameterType +//*************************************************************************** +void UsgsAstroProjectedSensorModel::setParameterType(int index, + csm::param::Type pType) { + m_camera->setParameterType(index, pType); +} + +//--------------------------------------------------------------------------- +// Sensor Model Information +//--------------------------------------------------------------------------- + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::getPedigree +//*************************************************************************** +std::string UsgsAstroProjectedSensorModel::getPedigree() const { + return "USGS_PROJECTED"; +} + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::getImageIdentifier +//*************************************************************************** +std::string UsgsAstroProjectedSensorModel::getImageIdentifier() const { + return m_camera->getImageIdentifier(); +} + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::setImageIdentifier +//*************************************************************************** +void UsgsAstroProjectedSensorModel::setImageIdentifier(const std::string& imageId, + csm::WarningList* warnings) { + m_camera->setImageIdentifier(imageId, warnings); +} + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::getSensorIdentifier +//*************************************************************************** +std::string UsgsAstroProjectedSensorModel::getSensorIdentifier() const { + return m_camera->getSensorIdentifier(); +} + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::getPlatformIdentifier +//*************************************************************************** +std::string UsgsAstroProjectedSensorModel::getPlatformIdentifier() const { + return m_camera->getPlatformIdentifier(); +} + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::setReferencePoint +//*************************************************************************** +void UsgsAstroProjectedSensorModel::setReferencePoint( + const csm::EcefCoord& ground_pt) { + m_camera->setReferencePoint(ground_pt); +} + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::getReferencePoint +//*************************************************************************** +csm::EcefCoord UsgsAstroProjectedSensorModel::getReferencePoint() const { + // Return ground point at image center + return m_camera->getReferencePoint(); +} + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::getSensorModelName +//*************************************************************************** +std::string UsgsAstroProjectedSensorModel::getModelName() const { + return UsgsAstroProjectedSensorModel::_SENSOR_MODEL_NAME; +} + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::getImageStart +//*************************************************************************** +csm::ImageCoord UsgsAstroProjectedSensorModel::getImageStart() const { + return m_camera->getImageStart(); +} + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::getImageSize +//*************************************************************************** +csm::ImageVector UsgsAstroProjectedSensorModel::getImageSize() const { + return m_camera->getImageSize(); +} + +//--------------------------------------------------------------------------- +// Monoscopic Mensuration +//--------------------------------------------------------------------------- + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::getValidHeightRange +//*************************************************************************** +std::pair<double, double> UsgsAstroProjectedSensorModel::getValidHeightRange() const { + return m_camera->getValidHeightRange(); +} + + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::getValidImageRange +//*************************************************************************** +std::pair<csm::ImageCoord, csm::ImageCoord> +UsgsAstroProjectedSensorModel::getValidImageRange() const { + return m_camera->getValidImageRange(); +} + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::getIlluminationDirection +//*************************************************************************** +csm::EcefVector UsgsAstroProjectedSensorModel::getIlluminationDirection( + const csm::EcefCoord& groundPt) const { + return m_camera->getIlluminationDirection(groundPt); +} + +//--------------------------------------------------------------------------- +// Error Correction +//--------------------------------------------------------------------------- + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::getNumGeometricCorrectionSwitches +//*************************************************************************** +int UsgsAstroProjectedSensorModel::getNumGeometricCorrectionSwitches() const { + return m_camera->getNumGeometricCorrectionSwitches(); +} + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::getGeometricCorrectionName +//*************************************************************************** +std::string UsgsAstroProjectedSensorModel::getGeometricCorrectionName( + int index) const { + return m_camera->getGeometricCorrectionName(index); +} + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::setGeometricCorrectionSwitch +//*************************************************************************** +void UsgsAstroProjectedSensorModel::setGeometricCorrectionSwitch( + int index, bool value, csm::param::Type pType) { + m_camera->setGeometricCorrectionSwitch(index, value, pType); +} + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::getGeometricCorrectionSwitch +//*************************************************************************** +bool UsgsAstroProjectedSensorModel::getGeometricCorrectionSwitch(int index) const { + return m_camera->getGeometricCorrectionSwitch(index); +} + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::getCrossCovarianceMatrix +//*************************************************************************** +std::vector<double> UsgsAstroProjectedSensorModel::getCrossCovarianceMatrix( + const csm::GeometricModel& comparisonModel, csm::param::Set pSet, + const csm::GeometricModel::GeometricModelList& otherModels) const { + return m_camera->getCrossCovarianceMatrix(comparisonModel, pSet, otherModels); +} + +//*************************************************************************** +// UsgsAstroLineScannerSensorModel::getCorrelationModel +//*************************************************************************** +const csm::CorrelationModel& UsgsAstroProjectedSensorModel::getCorrelationModel() + const { + return m_camera->getCorrelationModel(); +} + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::getUnmodeledCrossCovariance +//*************************************************************************** +std::vector<double> UsgsAstroProjectedSensorModel::getUnmodeledCrossCovariance( + const csm::ImageCoord& pt1, const csm::ImageCoord& pt2) const { + return m_camera->getUnmodeledCrossCovariance(pt1, pt2); +} + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::getCollectionIdentifier +//*************************************************************************** +std::string UsgsAstroProjectedSensorModel::getCollectionIdentifier() const { + return m_camera->getCollectionIdentifier(); +} + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::hasShareableParameters +//*************************************************************************** +bool UsgsAstroProjectedSensorModel::hasShareableParameters() const { + return m_camera->hasShareableParameters(); +} + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::isParameterShareable +//*************************************************************************** +bool UsgsAstroProjectedSensorModel::isParameterShareable(int index) const { + // Parameter sharing is not supported for this sensor + return m_camera->isParameterShareable(index); +} + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::getParameterSharingCriteria +//*************************************************************************** +csm::SharingCriteria UsgsAstroProjectedSensorModel::getParameterSharingCriteria( + int index) const { + return m_camera->getParameterSharingCriteria(index); +} + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::getSensorType +//*************************************************************************** +std::string UsgsAstroProjectedSensorModel::getSensorType() const { + return m_camera->getSensorType(); +} + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::getSensorMode +//*************************************************************************** +std::string UsgsAstroProjectedSensorModel::getSensorMode() const { + return m_camera->getSensorMode(); +} + +//*************************************************************************** +// UsgsAstroProjectedSensorModel::getVersion +//*************************************************************************** +csm::Version UsgsAstroProjectedSensorModel::getVersion() const { + return csm::Version(1, 0, 0); +} + +//*************************************************************************** +// UsgsAstroLineScannerSensorModel::getEllipsoid +//*************************************************************************** +csm::Ellipsoid UsgsAstroProjectedSensorModel::getEllipsoid() const { + return csm::Ellipsoid(m_majorAxis, m_minorAxis); +} + +void UsgsAstroProjectedSensorModel::setEllipsoid(const csm::Ellipsoid& ellipsoid) { + m_majorAxis = ellipsoid.getSemiMajorRadius(); + m_minorAxis = ellipsoid.getSemiMinorRadius(); + // Needs to set cameras ellipsoid but RasterGM is not a SettableEllipsoid +} + +//*************************************************************************** +// UsgsAstroLineScannerSensorModel::constructStateFromIsd +//*************************************************************************** +std::string UsgsAstroProjectedSensorModel::constructStateFromIsd( + const std::string imageSupportData, csm::WarningList* warnings) { + json state = json::parse(imageSupportData); + std::string modelName = ale::getSensorModelName(state); + + m_camera = getUsgsCsmModel(imageSupportData, modelName, warnings); + json projState = stateAsJson(m_camera->getModelState()); + + // Force update the modelName + projState["m_modelName"] = _SENSOR_MODEL_NAME; + projState["m_geoTransform"] = ale::getGeoTransform(state); + projState["m_projString"] = ale::getProjection(state); + MESSAGE_LOG( + spdlog::level::trace, + "m_geoTransform: {} " + "m_projString: {} ", + projState["m_geoTransform"].dump(), projState["m_projString"].dump()); + // The state data will still be updated when a sensor model is created since + // some state data is not in the ISD and requires a SM to compute them. + return projState.dump(); +} \ No newline at end of file diff --git a/src/Utilities.cpp b/src/Utilities.cpp index 5599c252995bd5b394eb387afc4f130a3d2ec690..dfcfae3b042c867b84c465664ad11b4176d316d4 100644 --- a/src/Utilities.cpp +++ b/src/Utilities.cpp @@ -1,6 +1,5 @@ #include "Utilities.h" - #include <Error.h> #include <cmath> #include <stack>