From 1e981d2c7a29e5e913968db86c49b5730c2ace9a Mon Sep 17 00:00:00 2001 From: jlaura <jlaura@usgs.gov> Date: Wed, 19 Dec 2018 11:33:23 -0700 Subject: [PATCH] Merging dev into master for release (#158) * Updated ISD and tests (#87) * updated tests + RIP TestyMcTestFace * keys updated * Probably should not hard code .cpps in the CMakeLists.txt for GTest * updated specs to mimic synthetic json * appveyor assumed broken from standup, disabling until fixed * eulers are now quats * merge from jay's changes * merge markers * renamed quats as per Jessie's reccomendation * only appends sensor_orientation to missing params * stupid markers * updated test ISD * changes as per some comments * updated as per comments * defaults are all 0 * #pragma once to C style header guard * stragler change * missed some params * missed another * moving things around * patched segfault error + added detector center as defined in json schema (#94) * patched segfault error + added detector center as defined in the swagger schema * verbose travi * Fixed optical distortion and pixel to focal transforms. (#115) * Update to use quaternions in test to match new ISD * Fixes #121 * Fix 1 remaining failing omega rotation test * Updates token to be in quotes * Still trying to get the builds working. * Updates to force upload * Adds newline * Update for formatting * Trying to force travis to deploy with labels I am editing this on the repo in order to get Travis to do its thing - I can not do this via a PR. * Update .travis.yml * Update meta.yaml to try and force a dev tag on the builds to get labels to work. * Update meta.yaml * Update .travis.yml * test x scaling for reset model state * test FL500 conversion * test FL500 conversion * Add tests to include * commit to force run of tests on mac with debug output * switch to using tolerances from dev * 0.5 pixel offset * try moving set of filename into setup * initialize differently test * more debug output * Add matrix to debug output * Even more debug output from matrix calculation * Add missing quaternion component to state string * cleanup debug output now that problem is fixed * fix added spacing * Adds in check for PR for upload * echo to check travis env * fixes equality check for PR * Clean up some spacing (non-functional) in UsgsAstroFrameModel * Fixed canModelBeConstructedFromISD throwing an exception when the metadata file doesn't exist. (#134) * fixed can be converted error * Added not constructible test for frame plugin * Removed old LS ISD header (#137) * Update some of the tests that set a new state value to use a function in the fixture, rather than repeating code * Windows Build (#139) * adds win build * Windows build * Updates submodules * Refactoring to move to one plugin and removed unused classes. (#138) * merge * changed varrs * reset test * First iteration * it compiles, although renaming this is still neccessary * added source * cleaned up, tests still need to pass * post merge clean up * validation updated, validation tests are now passing * Addressed comments from Jesse * last Jesse comment, convertISDToModelState doesn't check if pointer is invalid anymore as the sensor model should except * model_name -> m_modelName for frame getState * copy paste error in FrameSensorModel * Resolve merge conflicts with FrameIsdTest vs. SimpleFrameIsdTest names * Fix hopefully last merge problem * Conda build on win (#143) * Conda build on win * Trying a straight build first * Unneeded csmapi * Now trying to upload build * Trying a build and upload * Trying syntax change * trying ps * Update .appveyor.yml * Update .appveyor.yml * Update .appveyor.yml * Update .appveyor.yml * Update .appveyor.yml * Update .appveyor.yml * Update .appveyor.yml * Update .appveyor.yml * Update .appveyor.yml * Update .appveyor.yml * Update .appveyor.yml * Update meta.yaml * Update bld.bat This is a test to see where appveyor is failing. * Update bld.bat * Update bld.bat * Update meta.yaml * Update .appveyor.yml * Update .appveyor.yml * Update .appveyor.yml * Update .appveyor.yml * Adds if/else into appveyor (#146) * Adds if/else into appveyor * Update .appveyor.yml * Updates to use gcc7 * Update .travis.yml * Update .appveyor.yml * Fixed Line Scan construction and condensed plugin tests (#145) * First pass at test LS ISD * Initial LS plugin test base * fixed a test in frame plugin tests * Initial LS plugin test suite * Moved to single plugin test file * Added some new plugin tests * Fixed LS construction * Re-updated submodules * Reverted gtest * removed debuf prints left in and made getModelName functional (#148) * Changed line scan sensor model to new ISD spec (#149) * Changed line scan sensor model to new ISD spec * Updated LS to the proper spec * Changed model_name to name_model * Updated tests to use new name_ format in ISD * Updated LS test data to new spec * Fixed typo in ls test ISD * Moved framer to new ISD format. Added bad debug statements. * Updated LS to new spec * Fixed focal length epsilon name * Added model state test for framer (#152) * fixed nan issue (#153) * fixed nan issue * left in for loop * Removed switch statement for ls distortion: (#150) --- .appveyor.yml | 44 +- .travis.yml | 11 +- CMakeLists.txt | 23 +- csm | 2 +- gtest | 2 +- include/usgscsm/UsgsAstroFrameSensorModel.h | 57 +- include/usgscsm/UsgsAstroLsISD.h | 154 --- include/usgscsm/UsgsAstroLsPlugin.h | 219 ---- include/usgscsm/UsgsAstroLsSensorModel.h | 119 +- include/usgscsm/UsgsAstroLsStateData.h | 208 ---- ...gsAstroFramePlugin.h => UsgsAstroPlugin.h} | 23 +- recipe/bld.bat | 7 + recipe/meta.yaml | 12 +- src/UsgsAstroFramePlugin.cpp | 620 ---------- src/UsgsAstroFrameSensorModel.cpp | 778 +++++++----- src/UsgsAstroLsPlugin.cpp | 534 --------- src/UsgsAstroLsSensorModel.cpp | 1039 ++++++++++++----- src/UsgsAstroLsStateData.cpp | 538 --------- src/UsgsAstroPlugin.cpp | 284 +++++ tests/CMakeLists.txt | 12 +- tests/Fixtures.h | 144 +++ tests/FrameCameraTests.cpp | 324 ++--- tests/PluginTests.cpp | 190 +++ tests/TestyMcTestFace.cpp | 124 -- tests/data/constVelocityLineScan.json | 93 ++ tests/data/simpleFramerISD.json | 143 +-- 26 files changed, 2341 insertions(+), 3363 deletions(-) delete mode 100644 include/usgscsm/UsgsAstroLsISD.h delete mode 100644 include/usgscsm/UsgsAstroLsPlugin.h delete mode 100644 include/usgscsm/UsgsAstroLsStateData.h rename include/usgscsm/{UsgsAstroFramePlugin.h => UsgsAstroPlugin.h} (82%) create mode 100644 recipe/bld.bat delete mode 100644 src/UsgsAstroFramePlugin.cpp delete mode 100644 src/UsgsAstroLsPlugin.cpp delete mode 100644 src/UsgsAstroLsStateData.cpp create mode 100644 src/UsgsAstroPlugin.cpp create mode 100644 tests/Fixtures.h create mode 100644 tests/PluginTests.cpp delete mode 100644 tests/TestyMcTestFace.cpp create mode 100644 tests/data/constVelocityLineScan.json diff --git a/.appveyor.yml b/.appveyor.yml index 43ad8f2..cfdf80e 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -7,17 +7,41 @@ platform: configuration: - Release - - Debug - -environment: - CSM_LIBRARY_PATH: C:\\Miniconda36-x64\lib - CSM_INCLUDE_PATH: C:\\Miniconda36-x64\include install: - git submodule update --init --recursive - # This pulls csm from conda - - cmd: call C:\\Miniconda36-x64\Scripts\activate.bat - - cmd: conda install -y -c usgs-astrogeology libcsm - - cmake . + - call C:\\Miniconda36-x64\Scripts\activate.bat + - conda config --set always_yes yes --set changeps1 no + - conda update -q conda + - conda install conda-build anaconda-client + - conda config --add channels usgs-astrogeology + +before_build: + - mkdir build + - cd build + build_script: - - cmake --build . -- %MSBUILD_ARGS% + - cmake -G "Visual Studio 15 2017 Win64" -DBUILD_TESTS=OFF .. + - cmake --build . --target ALL_BUILD --config Release + +artifacts: + - path: build\Release\usgscsm.dll + name: usgscsm.dll + +on_success: +- cd ../ +- conda build -q recipe/ +- ps: + if ($env:APPVEYOR_PULL_REQUEST_NUMBER -eq "") { + $tar_glob = conda build recipe --output; + Write-Host "tar_glob $tar_glob"; + if ($env:APPVEYOR_REPO_BRANCH -eq "dev") { + $anaconda_label = "dev" + } else { + $anaconda_label = "main" + }; + Write-Host "anaconda_label $anaconda_label"; + $parameters = '-t', "$env:CONDA_UPLOAD_TOKEN", 'upload', "$tar_glob", '-l', + "$anaconda_label", '--force', '--no-progress'; + & cmd /c 'anaconda 2>&1' $parameters; + }; diff --git a/.travis.yml b/.travis.yml index 52c16c3..c0a3508 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,15 +14,16 @@ matrix: sources: - ubuntu-toolchain-r-test packages: - - g++-6 + - g++-7 env: - - MATRIX_EVAL="CXX=g++-6 && CC=gcc-6" + - MATRIX_EVAL="CXX=g++-7 && CC=gcc-7" - os: osx osx_image: xcode9.4 env: - MATRIX_EVAL="CXX=clang++ && CC=clang" before_install: + - echo "$TRAVIS_PULL_REQUEST" - eval "${MATRIX_EVAL}" - | if [ "$TRAVIS_OS_NAME" == "linux" ]; then @@ -58,8 +59,8 @@ after_success: - builddir=(`conda build recipe --output`) # Label based on the branch and upload to anaconda.org - | - if [ "$TRAVIS_BRANCH" == "master" ]; then + if [ "$TRAVIS_BRANCH" == "master" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ]; then anaconda -t="$CONDA_UPLOAD_TOKEN" upload $builddir; - elif [ "$TRAVIS_BRANCH" == "dev" ]; then - anaconda -t="$CONDA_UPLOAD_TOKEN" upload $builddir --label dev; + elif [ "$TRAVIS_BRANCH" == "dev" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ]; then + anaconda -t="$CONDA_UPLOAD_TOKEN" upload $builddir --label dev --force; fi diff --git a/CMakeLists.txt b/CMakeLists.txt index cee474e..76ab4a6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,17 +15,18 @@ if(BUILD_CSM) set(CSM_LIBRARY csmapi) else() find_path(CSM_INCLUDE_DIR NAMES "csm.h" - PATH_SUFFIXES "csm" + PATH_SUFFIXES "csm" PATHS $ENV{CONDA_PREFIX}/include/) find_library(CSM_LIBRARY csmapi PATHS $ENV{CONDA_PREFIX}/lib) + + message("--Found CSM Library: ${CSM_LIBRARY}") + message("--Found CSM Include Directory: ${CSM_INCLUDE_DIR}") endif(BUILD_CSM) add_library(usgscsm SHARED - src/UsgsAstroFramePlugin.cpp + src/UsgsAstroPlugin.cpp src/UsgsAstroFrameSensorModel.cpp - src/UsgsAstroLsPlugin.cpp - src/UsgsAstroLsSensorModel.cpp - src/UsgsAstroLsStateData.cpp) + src/UsgsAstroLsSensorModel.cpp) set_target_properties(usgscsm PROPERTIES VERSION ${PROJECT_VERSION} @@ -42,7 +43,6 @@ target_include_directories(usgscsm ) # Setup for GoogleTest - find_package (Threads) target_link_libraries(usgscsm @@ -50,16 +50,11 @@ target_link_libraries(usgscsm gtest ${CMAKE_THREAD_LIBS_INIT}) if(WIN32) - option(CMAKE_USE_WIN32_THREADS_INIT "using WIN32 threads" ON) - option(gtest_disable_pthreads "Disable uses of pthreads in gtest." ON) - install(TARGETS usgscsm - RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR}) - install(DIRECTORY ${USGSCSM_INCLUDE_DIRS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + install(TARGETS usgscsm RUNTIME DESTINATION ${CMAKE_INSTALL_LIBDIR}) else() - install(TARGETS usgscsm - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) - install(DIRECTORY ${USGSCSM_INCLUDE_DIRS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + install(TARGETS usgscsm LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) endif() +install(DIRECTORY ${USGSCSM_INCLUDE_DIRS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) # Optional build or link against CSM diff --git a/csm b/csm index ea22180..c78dbba 160000 --- a/csm +++ b/csm @@ -1 +1 @@ -Subproject commit ea22180f46f86f4c95ade84ab81eb4477bdd8dd6 +Subproject commit c78dbba3731432249a75db9fdd7415b292d46715 diff --git a/gtest b/gtest index e5e2ef7..2fe3bd9 160000 --- a/gtest +++ b/gtest @@ -1 +1 @@ -Subproject commit e5e2ef7cd27cc089c1d8302a11970ef870554294 +Subproject commit 2fe3bd994b3189899d93f1d5a881e725e046fdc2 diff --git a/include/usgscsm/UsgsAstroFrameSensorModel.h b/include/usgscsm/UsgsAstroFrameSensorModel.h index c82d1d8..7da5473 100644 --- a/include/usgscsm/UsgsAstroFrameSensorModel.h +++ b/include/usgscsm/UsgsAstroFrameSensorModel.h @@ -9,6 +9,10 @@ #include "RasterGM.h" #include "CorrelationModel.h" +#include <json.hpp> +using json = nlohmann::json; + + class UsgsAstroFrameSensorModel : public csm::RasterGM { // UsgsAstroFramePlugin needs to access private members friend class UsgsAstroFramePlugin; @@ -17,11 +21,19 @@ class UsgsAstroFrameSensorModel : public csm::RasterGM { UsgsAstroFrameSensorModel(); ~UsgsAstroFrameSensorModel(); + + bool isValidModelState(const std::string& stringState, csm::WarningList *warnings); + bool isValidIsd(const std::string& stringIsd, csm::WarningList *warnings); + virtual csm::ImageCoord groundToImage(const csm::EcefCoord &groundPt, double desiredPrecision=0.001, double *achievedPrecision=NULL, csm::WarningList *warnings=NULL) const; + + std::string constructStateFromIsd(const std::string& jsonIsd, csm::WarningList *warnings); + void reset(); + virtual csm::ImageCoordCovar groundToImage(const csm::EcefCoordCovar &groundPt, double desiredPrecision=0.001, double *achievedPrecision=NULL, @@ -301,12 +313,12 @@ class UsgsAstroFrameSensorModel : public csm::RasterGM { protected: FRIEND_TEST(FramerParameterizedTest,JacobianTest); - FRIEND_TEST(FrameIsdTest, setFocalPlane1); - FRIEND_TEST(FrameIsdTest, Jacobian1); - FRIEND_TEST(FrameIsdTest, setFocalPlane_AllCoefficientsOne); - FRIEND_TEST(FrameIsdTest, distortMe_AllCoefficientsOne); - FRIEND_TEST(FrameIsdTest, setFocalPlane_AlternatingOnes); - FRIEND_TEST(FrameIsdTest, distortMe_AlternatingOnes); + FRIEND_TEST(FrameSensorModel, setFocalPlane1); + FRIEND_TEST(FrameSensorModel, Jacobian1); + FRIEND_TEST(FrameSensorModel, setFocalPlane_AllCoefficientsOne); + FRIEND_TEST(FrameSensorModel, distortMe_AllCoefficientsOne); + FRIEND_TEST(FrameSensorModel, setFocalPlane_AlternatingOnes); + FRIEND_TEST(FrameSensorModel, distortMe_AlternatingOnes); virtual bool setFocalPlane(double dx,double dy,double &undistortedX,double &undistortedY) const; virtual void distortionFunction(double ux, double uy, double &dx, double &dy) const; @@ -316,7 +328,6 @@ protected: private: - // Input parameters static const int m_numParameters; static const std::string m_parameterName[]; @@ -326,40 +337,43 @@ protected: std::vector<double> m_noAdjustments; std::vector<double> m_odtX; std::vector<double> m_odtY; - - static const int _NUM_STATE_KEYWORDS; - static const std::string _STATE_KEYWORD[]; - - double m_transX[3]; - double m_transY[3]; + std::vector<double> m_transX; + std::vector<double> m_transY; + std::vector<double> m_spacecraftVelocity; + std::vector<double> m_sunPosition; + std::vector<double> m_ccdCenter; + std::vector<double> m_iTransS; + std::vector<double> m_iTransL; + std::vector<double> m_boresight; double m_majorAxis; double m_minorAxis; double m_focalLength; - double m_spacecraftVelocity[3]; - double m_sunPosition[3]; - double m_ccdCenter[2]; double m_minElevation; double m_maxElevation; - double m_line_pp; - double m_sample_pp; + double m_linePp; + double m_samplePp; double m_startingDetectorSample; double m_startingDetectorLine; std::string m_targetName; + std::string m_modelName; double m_ifov; std::string m_instrumentID; double m_focalLengthEpsilon; double m_originalHalfLines; std::string m_spacecraftName; double m_pixelPitch; - double m_iTransS[3]; - double m_iTransL[3]; + double m_ephemerisTime; double m_originalHalfSamples; - double m_boresight[3]; int m_nLines; int m_nSamples; int m_nParameters; + json _state; + static const int _NUM_STATE_KEYWORDS; + static const int NUM_PARAMETERS; + static const std::string _STATE_KEYWORD[]; + csm::NoCorrelationModel _no_corr_model; double getValue(int index,const std::vector<double> &adjustments) const; @@ -371,6 +385,7 @@ protected: double xl, double yl, double zl, double& x,double& y, double& z) const; + }; #endif diff --git a/include/usgscsm/UsgsAstroLsISD.h b/include/usgscsm/UsgsAstroLsISD.h deleted file mode 100644 index 2b0d683..0000000 --- a/include/usgscsm/UsgsAstroLsISD.h +++ /dev/null @@ -1,154 +0,0 @@ -//---------------------------------------------------------------------------- -// -// UNCLASSIFIED -// -// Copyright © 1989-2017 BAE Systems Information and Electronic Systems Integration Inc. -// ALL RIGHTS RESERVED -// Use of this software product is governed by the terms of a license -// agreement. The license agreement is found in the installation directory. -// -// For support, please visit http://www.baesystems.com/gxp -// -// FILENAME: UsgsAstroLsISD.h -// -// DESCRIPTION: -// -// Image Support Data (ISD) to build the Astro Line Scanner sensor model. -// The ISD format is defined by the imagery provider. A few common formats -// include name/value pairs, XML, NITF TREs, and GeoTiff tags. -// -// This ISD is formatted as a list of name/value pairs. The order of the -// list generally does not matter, except that the length of a vector needs -// to be read in before the vector itself. Extra data in the support data -// file will be ignored. -// -// There is data describing the ellipsoid that can optionally be in a -// seperate file. This is to support legacy data, but is not encouraged. -// -// For the Astro LS sensor model there is a close relationship between the -// ISD and the State data. This is not always the case. So, it is best to -// seperate the ISD parsing (done here), the translation of ISD to state -// data (done in the plugin), and the instantiation of the sensor model -// from state data (done in the sensor model). -// -// SOFTWARE HISTORY: -// -// Date Author Comment -// ----------- ---------- ------- -// 16-Oct-2017 BAE Systems Initial Release -// -//############################################################################# -#ifndef __USGS_ASTRO_LINE_SCANNER_ISD_H -#define __USGS_ASTRO_LINE_SCANNER_ISD_H - -#include <vector> -#include <string> - -#include <csm.h> -#include <Isd.h> -#include <SettableEllipsoid.h> - -class UsgsAstroLsISD -{ - public: - - - UsgsAstroLsISD() - { - reset(); - } - - UsgsAstroLsISD( - const std::string& lis_file_name, - const std::string& ell_file_name) - { - reset(); - setISD(lis_file_name, ell_file_name); - } - - virtual ~UsgsAstroLsISD() {} - - // Formats the support data as a string - // This is mainly used to check that the - // support data is read in correctly. - std::string toString() const; - - // Initializes the class from ISD as formatted by the image provider. - // - // Note that if the ellipsoid data is found in the main ISD file, - // the ellipsoid data file is not needed. - void setISD( - const std::string& lis_file_name, - const std::string& ell_file_name); - - - //-------------------------------------------------------------------------- - // Helper Routines - //-------------------------------------------------------------------------- - // Initial check that support data file exists and looks like Astro LS ISD. - static bool checkFileValidity( - const csm::Isd& image_support_data, - std::string& lis_file_name, - std::string& ell_file_name, - std::string& img_rel_name); - - - // ISD elements; - // The support data is defined by USGS. See the documentation at - // http://htmlpreview.github.io/?https://github.com/USGS-Astrogeology/socet_set/blob/master/SS4HiRISE/Tutorials/ISD_keyword_examples/AstroLineScanner_ISD_Keywords.ls.htm - // Even for fields that do not change, it is best to include them in - // the support data rather than hard code values in the sensor model. - // Since this is not always done, some fields are optional. - std::string m_sensor_type; - int m_total_lines; - int m_total_samples; - int m_platform; - int m_aberr; - int m_atmref; - double m_int_time; - double m_starting_ephemeris_time; - double m_center_ephemeris_time; - double m_detector_sample_summing; - double m_starting_sample; - int m_ikcode; - double m_focal; - double m_isis_z_direction; - double m_optical_dist_coef[3]; - double m_itranss[3]; - double m_itransl[3]; - double m_detector_sample_origin; - double m_detector_line_origin; - double m_detector_line_offset; - double m_mounting_angles[3]; - double m_dt_ephem; - double m_t0_ephem; - double m_dt_quat; - double m_t0_quat; - int m_number_of_ephem; - int m_number_of_quaternions; - std::vector<double> m_ephem_pts; - std::vector<double> m_ephem_rates; - std::vector<double> m_quaternions; - std::vector<double> m_tri_parameters; - double m_semi_major_axis; - double m_eccentricity; - - // Optional fields - double m_ref_height; - double m_min_valid_ht; - double m_max_valid_ht; - std::string m_image_id; - std::string m_sensor_id; - std::string m_platform_id; - std::string m_traj_id; - std::string m_coll_id; - std::string m_ref_date_time; - - static const std::string mISD_KEYWORDS[]; - - protected: - // Set to default values - void reset(); -}; - -#endif diff --git a/include/usgscsm/UsgsAstroLsPlugin.h b/include/usgscsm/UsgsAstroLsPlugin.h deleted file mode 100644 index fd41ce4..0000000 --- a/include/usgscsm/UsgsAstroLsPlugin.h +++ /dev/null @@ -1,219 +0,0 @@ -//---------------------------------------------------------------------------- -// -// UNCLASSIFIED -// -// Copyright © 1989-2017 BAE Systems Information and Electronic Systems Integration Inc. -// ALL RIGHTS RESERVED -// Use of this software product is governed by the terms of a license -// agreement. The license agreement is found in the installation directory. -// -// For support, please visit http://www.baesystems.com/gxp -// -// Description: -// This class creates instances of the Astro Line Scanner sensor model. The -// sensor model can be created from either image support data or sensor model -// state data. This plugin is an implementation of the CSM 3.0.3 CSM plugin -// class. It supports ISD specified by image file name. It is expected that -// a support data file exist in the same directory with the images file name -// with "_keywords.lis" appended instead of the original extension. An optional -// file containing ellipsoid data (ellipsoid.ell) can also be placed in this -// directory. Otherwise, the ellipsoid data is found in the .lis file. -// -// Revision History: -// Date Name Description -// ----------- --------- ----------------------------------------------- -// 30-APR-2017 BAE Systems Initial Implementation based on CSM 2.0 code -// 16-OCT-2017 BAE Systems Update for CSM 3.0.3 -//----------------------------------------------------------------------------- - -#ifndef __USGS_ASTRO_LINE_SCANNER_PLUGIN_H -#define __USGS_ASTRO_LINE_SCANNER_PLUGIN_H - -#include <string> -#include <Plugin.h> - - -class UsgsAstroLsPlugin : public csm::Plugin -{ -public: - - //--- - // The public interface is inherited from the csm::Plugin class. - //--- - - //-------------------------------------------------------------------------- - // Plugin Interface - //-------------------------------------------------------------------------- - virtual std::string getPluginName() const; - //> This method returns the character std::string that identifies the - // plugin. - //< - - //--- - // CSM Plugin Descriptors - //--- - virtual std::string getManufacturer() const; - //> This method returns name of the organization that created the plugin. - //< - - virtual std::string getReleaseDate() const; - //> This method returns release date of the plugin. - // The returned string follows the ISO 8601 standard. - // - //- Precision Format Example - //- year yyyy "1961" - //- month yyyymm "196104" - //- day yyyymmdd "19610420" - //< - - virtual csm::Version getCsmVersion() const; - //> This method returns the CSM API version that the plugin conforms to. - //< - - //--- - // Model Availability - //--- - virtual size_t getNumModels() const; - //> This method returns the number of types of models that this plugin - // can create. - //< - - virtual std::string getModelName(size_t modelIndex) const; - //> This method returns the name of the model for the given modelIndex. - // The order does not matter - the index is only used to cycle through - // all of the model names. - // - // The model index must be less than getNumModels(), or an exception - // will be thrown. - //< - - virtual std::string getModelFamily(size_t modelIndex) const; - //> This method returns the model "family" for the model for the given - // modelIndex. This should be the same as what is returned from - // csm::Model::getFamily() for the model. - // - // SETs can use this information to exclude models when searching for a - // model to create. - // - // The model index must be less than getNumModels(), or an exception - // will be thrown. - //< - - //--- - // Model Descriptors - //--- - virtual csm::Version getModelVersion(const std::string& modelName) const; - //> This method returns the version of the code for the model given - // by modelIndex. The Version object can be compared to other Version - // objects with its comparison operators. Not to be confused with the - // CSM API version. - //< - - //--- - // Model Construction - //--- - virtual bool canModelBeConstructedFromState( - const std::string& modelName, - const std::string& modelState, - csm::WarningList* warnings = NULL) const; - //> This method returns a boolean indicating whether or not a model of the - // given modelName can be constructed from the given modelState. - // - // If a non-NULL warnings argument is received, it will be populated - // as applicable. - //< - - virtual bool canModelBeConstructedFromISD( - const csm::Isd& imageSupportData, - const std::string& modelName, - csm::WarningList* warnings = NULL) const; - //> This method returns a boolean indicating whether or not a model of the - // given modelName can be constructed from the given imageSupportData. - // - // If a non-NULL warnings argument is received, it will be populated - // as applicable. - //< - - virtual csm::Model* constructModelFromState( - const std::string& modelState, - csm::WarningList* warnings = NULL) const; - //> This method allocates and initializes an object of the appropriate - // derived Model class with the given modelState and returns a pointer to - // the Model base class. The object is allocated by this method using - // new; it is the responsibility of the calling application to delete it. - // - // If a non-NULL warnings argument is received, it will be populated - // as applicable. - //< - - virtual csm::Model* constructModelFromISD( - const csm::Isd& imageSupportData, - const std::string& modelName, - csm::WarningList* warnings = NULL) const; - //> This method allocates and initializes an object of the appropriate - // derived Model class with the given imageSupportData and returns a - // pointer to the Model base class. The object is allocated by this - // method using new; it is the responsibility of the calling - // application to delete it. - // - // If a non-NULL warnings argument is received, it will be populated - // as applicable. - //< - - virtual std::string getModelNameFromModelState( - const std::string& modelState, - csm::WarningList* warnings = NULL) const; - // This method returns the model name for which the given modelState - // is applicable. - // - // If a non-NULL warnings argument is received, it will be populated - // as applicable. - //< - - //--- - // Image Support Data Conversions - //--- - virtual bool canISDBeConvertedToModelState( - const csm::Isd& imageSupportData, - const std::string& modelName, - csm::WarningList* warnings = NULL) const; - //> This method returns a boolean indicating whether or not a model state - // of the given modelName can be constructed from the given - // imageSupportData. - // - // If a non-NULL warnings argument is received, it will be populated - // as applicable. - //< - - virtual std::string convertISDToModelState( - const csm::Isd& imageSupportData, - const std::string& modelName, - csm::WarningList* warnings = NULL) const; - //> This method returns a model state string for the given modelName, - // constructed from the given imageSupportData. - // - // If a non-NULL warnings argument is received, it will be populated - // as applicable. - //< - -//private: - - //-------------------------------------------------------------------------- - // Constructors/Destructor - //-------------------------------------------------------------------------- - - UsgsAstroLsPlugin(); - ~UsgsAstroLsPlugin(); - -private: - //-------------------------------------------------------------------------- - // Data Members - //-------------------------------------------------------------------------- - - // This is needed to allow the plugin to be registered. - static const UsgsAstroLsPlugin _theRegisteringObject; - static const std::string mISD_KEYWORDS[]; - static const std::string mSTATE_KEYWORDS[]; -}; // UsgsAstroLsPlugin - -#endif // __USGS_ASTRO_LINE_SCANNER_PLUGIN_H diff --git a/include/usgscsm/UsgsAstroLsSensorModel.h b/include/usgscsm/UsgsAstroLsSensorModel.h index 5306a0b..2fc6d7e 100644 --- a/include/usgscsm/UsgsAstroLsSensorModel.h +++ b/include/usgscsm/UsgsAstroLsSensorModel.h @@ -27,7 +27,6 @@ #ifndef __USGS_ASTRO_LINE_SCANNER_SENSORMODEL_H #define __USGS_ASTRO_LINE_SCANNER_SENSORMODEL_H -#include "UsgsAstroLsStateData.h" #include <RasterGM.h> #include <SettableEllipsoid.h> #include <CorrelationModel.h> @@ -37,6 +36,102 @@ class UsgsAstroLsSensorModel : public csm::RasterGM, virtual public csm::Settabl { 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& argState); + //> 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) const; + + // State data elements; + std::string m_imageIdentifier; // 1 + std::string m_sensorType; // 2 + int m_totalLines; // 3 + int m_totalSamples; // 4 + double m_offsetLines; // 5 + double m_offsetSamples; // 6 + int m_platformFlag; // 7 + int m_aberrFlag; // 8 + int m_atmRefFlag; // 9 + std::vector<double> m_intTimeLines; + std::vector<double> m_intTimeStartTimes; + std::vector<double> m_intTimes; + double m_startingEphemerisTime; // 11 + double m_centerEphemerisTime; // 12 + double m_detectorSampleSumming; // 13 + double m_startingSample; // 14 + int m_ikCode; // 15 + double m_focal; // 16 + double m_isisZDirection; // 17 + double m_opticalDistCoef[3]; // 18 + double m_iTransS[3]; // 19 + double m_iTransL[3]; // 20 + double m_detectorSampleOrigin; // 21 + double m_detectorLineOrigin; // 22 + double m_detectorLineOffset; // 23 + double m_mountingMatrix[9]; // 24 + double m_semiMajorAxis; // 25 + double m_semiMinorAxis; // 26 + std::string m_referenceDateAndTime; // 27 + std::string m_platformIdentifier; // 28 + std::string m_sensorIdentifier; // 29 + std::string m_trajectoryIdentifier; // 30 + std::string m_collectionIdentifier; // 31 + double m_refElevation; // 32 + double m_minElevation; // 33 + double m_maxElevation; // 34 + double m_dtEphem; // 35 + double m_t0Ephem; // 36 + double m_dtQuat; // 37 + double m_t0Quat; // 38 + int m_numEphem; // 39 + int m_numQuaternions; // 40 + std::vector<double> m_ephemPts; // 41 + std::vector<double> m_ephemRates; // 42 + std::vector<double> m_quaternions; // 43 + std::vector<double> m_parameterVals; // 44 + std::vector<csm::param::Type> m_parameterType; // 45 + csm::EcefCoord m_referencePointXyz; // 46 + double m_gsd; // 47 + double m_flyingHeight; // 48 + double m_halfSwath; // 49 + double m_halfTime; // 50 + std::vector<double> m_covariance; // 51 + int m_imageFlipFlag; // 52 + + // Hardcoded + static const std::string _SENSOR_MODEL_NAME; // state date element 0 + + static const std::string _STATE_KEYWORD[]; + static const int NUM_PARAM_TYPES; + static const std::string PARAM_STRING_ALL[]; + static const csm::param::Type PARAM_CHAR_ALL[]; + static const int NUM_PARAMETERS; + static const std::string PARAMETER_NAME[]; + + // Set to default values + void reset(); + //-------------------------------------------------------------- // Constructors/Destructor //-------------------------------------------------------------- @@ -44,8 +139,11 @@ public: UsgsAstroLsSensorModel(); ~UsgsAstroLsSensorModel(); + virtual std::string getModelState() const; + + // Set the sensor model based on the input state data - void set( const UsgsAstroLsStateData &state_data ); + void set( const std::string &state_data ); //---------------------------------------------------------------- @@ -775,7 +873,7 @@ public: //--- // Sensor Model State //--- - virtual std::string getModelState() const; + // 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 @@ -785,20 +883,6 @@ public: // current state. //< - virtual void replaceModelState(const std::string& argState); - //> 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. - //< - virtual csm::Ellipsoid getEllipsoid() const; //> This method returns the planetary ellipsoid. //< @@ -951,7 +1035,6 @@ private: double determinant3x3(double mat[9]) const; - UsgsAstroLsStateData _data; // Holds the state data csm::NoCorrelationModel _no_corr_model; // A way to report no correlation between images is supported std::vector<double> _no_adjustment; // A vector of zeros indicating no internal adjustment diff --git a/include/usgscsm/UsgsAstroLsStateData.h b/include/usgscsm/UsgsAstroLsStateData.h deleted file mode 100644 index 1527194..0000000 --- a/include/usgscsm/UsgsAstroLsStateData.h +++ /dev/null @@ -1,208 +0,0 @@ -//---------------------------------------------------------------------------- -// -// UNCLASSIFIED -// -// Copyright © 1989-2017 BAE Systems Information and Electronic Systems Integration Inc. -// ALL RIGHTS RESERVED -// Use of this software product is governed by the terms of a license -// agreement. The license agreement is found in the installation directory. -// -// For support, please visit http://www.baesystems.com/gxp -// -// DESCRIPTION: -// -// Holds State data that runs the Astro Line Scanner Sensor Model. -// The format of the state data is determined by the sensor model -// developer. The CSM plugin converts ISD to state data and the -// CSM sensor model is instantiated based on the state data. -// -// By CSM convention, the sensor model name is the first element in -// the state data. The rest of the state data is order independent -// with the exception that the length of vectors must come before -// the vector data. -// -// For the Astro Line Scanner sensor model, the state data closely -// follows the support data. This is not always the case. For this -// model, the state data is a list name/value pairs. -// -// -// SOFTWARE HISTORY: -// -// Date Author Comment -// ----------- ---------- ------- -// 13-OCT-2017 BAE Systems Initial Release -// -//############################################################################# -#ifndef __USGS_ASTRO_LINE_SCANNER_STATE_DATA_H -#define __USGS_ASTRO_LINE_SCANNER_STATE_DATA_H - -#include <vector> -#include <string> - -#include <csm.h> -#include <SettableEllipsoid.h> - -class UsgsAstroLsStateData -{ - public: - - UsgsAstroLsStateData() - { - reset(); - } - - UsgsAstroLsStateData(const std::string &state) - { - reset(); - setState(state); - } - - ~UsgsAstroLsStateData() {} - - // Formats the state data as a string. - // This is the format that is used to instantiate a sensor model. - std::string toString() const; - - // Formats the sate data as a JSON string. - std::string toJson() const; - - // Initializes the class from state data as formatted - // in a string by the toString() method - void setState(const std::string &state); - - // 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); - - // State data elements; - std::string m_ImageIdentifier; // 1 - std::string m_SensorType; // 2 - int m_TotalLines; // 3 - int m_TotalSamples; // 4 - double m_OffsetLines; // 5 - double m_OffsetSamples; // 6 - int m_PlatformFlag; // 7 - int m_AberrFlag; // 8 - int m_AtmRefFlag; // 9 - std::vector<double> m_IntTimeLines; - std::vector<double> m_IntTimeStartTimes; - std::vector<double> m_IntTimes; - double m_StartingEphemerisTime; // 11 - double m_CenterEphemerisTime; // 12 - double m_DetectorSampleSumming; // 13 - double m_StartingSample; // 14 - int m_IkCode; // 15 - double m_Focal; // 16 - double m_IsisZDirection; // 17 - double m_OpticalDistCoef[3]; // 18 - double m_ITransS[3]; // 19 - double m_ITransL[3]; // 20 - double m_DetectorSampleOrigin; // 21 - double m_DetectorLineOrigin; // 22 - double m_DetectorLineOffset; // 23 - double m_MountingMatrix[9]; // 24 - double m_SemiMajorAxis; // 25 - double m_SemiMinorAxis; // 26 - std::string m_ReferenceDateAndTime; // 27 - std::string m_PlatformIdentifier; // 28 - std::string m_SensorIdentifier; // 29 - std::string m_TrajectoryIdentifier; // 30 - std::string m_CollectionIdentifier; // 31 - double m_RefElevation; // 32 - double m_MinElevation; // 33 - double m_MaxElevation; // 34 - double m_DtEphem; // 35 - double m_T0Ephem; // 36 - double m_DtQuat; // 37 - double m_T0Quat; // 38 - int m_NumEphem; // 39 - int m_NumQuaternions; // 40 - std::vector<double> m_EphemPts; // 41 - std::vector<double> m_EphemRates; // 42 - std::vector<double> m_Quaternions; // 43 - std::vector<double> m_ParameterVals; // 44 - std::vector<csm::param::Type> m_ParameterType; // 45 - csm::EcefCoord m_ReferencePointXyz; // 46 - double m_Gsd; // 47 - double m_FlyingHeight; // 48 - double m_HalfSwath; // 49 - double m_HalfTime; // 50 - std::vector<double> m_Covariance; // 51 - int m_ImageFlipFlag; // 52 - - // Hardcoded - static const std::string SENSOR_MODEL_NAME; // state date element 0 - - static const std::string STATE_KEYWORD[]; - static const int NUM_PARAM_TYPES; - static const std::string PARAM_STRING_ALL[]; - static const csm::param::Type PARAM_CHAR_ALL[]; - static const int NUM_PARAMETERS; - static const std::string PARAMETER_NAME[]; - - enum - { - STA_SENSOR_MODEL_NAME, - STA_IMAGE_IDENTIFIER, - STA_SENSOR_TYPE, - STA_TOTAL_LINES, - STA_TOTAL_SAMPLES, - STA_OFFSET_LINES, - STA_OFFSET_SAMPLES, - STA_PLATFORM_FLAG, - STA_ABERR_FLAG, - STA_ATMREF_FLAG, - STA_INT_TIME_LINES, - STA_INT_TIME_START_TIMES, - STA_INT_TIMES, - STA_STARTING_EPHEMERIS_TIME, - STA_CENTER_EPHEMERIS_TIME, - STA_DETECTOR_SAMPLE_SUMMING, - STA_STARTING_SAMPLE, - STA_IK_CODE, - STA_FOCAL, - STA_ISIS_Z_DIRECTION, - STA_OPTICAL_DIST_COEF, - STA_I_TRANS_S, - STA_I_TRANS_L, - STA_DETECTOR_SAMPLE_ORIGIN, - STA_DETECTOR_LINE_ORIGIN, - STA_DETECTOR_LINE_OFFSET, - STA_MOUNTING_MATRIX, - STA_SEMI_MAJOR_AXIS, - STA_SEMI_MINOR_AXIS, - STA_REFERENCE_DATE_AND_TIME, - STA_PLATFORM_IDENTIFIER, - STA_SENSOR_IDENTIFIER, - STA_TRAJECTORY_IDENTIFIER, - STA_COLLECTION_IDENTIFIER, - STA_REF_ELEVATION, - STA_MIN_ELEVATION, - STA_MAX_ELEVATION, - STA_DT_EPHEM, - STA_T0_EPHEM, - STA_DT_QUAT, - STA_T0_QUAT, - STA_NUM_EPHEM, - STA_NUM_QUATERNIONS, - STA_EPHEM_PTS, - STA_EPHEM_RATES, - STA_QUATERNIONS, - STA_PARAMETER_VALS, - STA_PARAMETER_TYPE, - STA_REFERENCE_POINT_XYZ, - STA_GSD, - STA_FLYING_HEIGHT, - STA_HALF_SWATH, - STA_HALF_TIME, - STA_COVARIANCE, - STA_IMAGE_FLIP_FLAG, - _NUM_STATE_KEYWORDS - }; - - // Set to default values - void reset(); -}; - -#endif diff --git a/include/usgscsm/UsgsAstroFramePlugin.h b/include/usgscsm/UsgsAstroPlugin.h similarity index 82% rename from include/usgscsm/UsgsAstroFramePlugin.h rename to include/usgscsm/UsgsAstroPlugin.h index 8b6f57e..a3a3c76 100644 --- a/include/usgscsm/UsgsAstroFramePlugin.h +++ b/include/usgscsm/UsgsAstroPlugin.h @@ -1,5 +1,5 @@ -#ifndef UsgsAstroFramePlugin_h -#define UsgsAstroFramePlugin_h +#ifndef UsgsAstroPlugin_h +#define UsgsAstroPlugin_h #include <string> @@ -7,13 +7,16 @@ #include <Plugin.h> #include <Version.h> +#include <json.hpp> +using json = nlohmann::json; -class UsgsAstroFramePlugin : public csm::Plugin { +class UsgsAstroPlugin : public csm::Plugin { public: - UsgsAstroFramePlugin(); - ~UsgsAstroFramePlugin(); + UsgsAstroPlugin(); + ~UsgsAstroPlugin(); + virtual std::string getStateFromISD(csm::Isd imageSupportData) const; virtual std::string getPluginName() const; virtual std::string getManufacturer() const; virtual std::string getReleaseDate() const; @@ -42,12 +45,12 @@ class UsgsAstroFramePlugin : public csm::Plugin { const std::string &modelName, csm::WarningList *warnings = NULL) const; + std::string loadImageSupportData(const csm::Isd &imageSupportDataOriginal) const; + // TODO when implementing, add any other necessary members. private: - csm::Isd loadImageSupportData(const csm::Isd &imageSupportData) const; - - static const UsgsAstroFramePlugin m_registeredPlugin; + static const UsgsAstroPlugin m_registeredPlugin; static const std::string _PLUGIN_NAME; static const std::string _MANUFACTURER_NAME; static const std::string _RELEASE_DATE; @@ -56,6 +59,10 @@ private: static const std::string _ISD_KEYWORD[]; static const int _NUM_STATE_KEYWORDS; static const std::string _STATE_KEYWORD[]; + static const json MODEL_KEYWORDS; + + typedef csm::Model* (*sensorConstructor)(void); + static std::map<std::string, sensorConstructor> MODELS; }; #endif diff --git a/recipe/bld.bat b/recipe/bld.bat new file mode 100644 index 0000000..04c8729 --- /dev/null +++ b/recipe/bld.bat @@ -0,0 +1,7 @@ +mkdir build +cd build +cmake -G "Visual Studio 15 2017 Win64" -DBUILD_TESTS=OFF .. +cmake --build . --target ALL_BUILD --config Release +copy Release\usgscsm.dll %LIBRARY_BIN% + +if errorlevel 1 exit 1 diff --git a/recipe/meta.yaml b/recipe/meta.yaml index f9eee4d..fc8a832 100644 --- a/recipe/meta.yaml +++ b/recipe/meta.yaml @@ -1,22 +1,30 @@ + package: - name: usgscam + name: usgscsm version: "0.1.0" source: git_url: https://github.com/USGS-Astrogeology/CSM-CameraModel.git +build: + string: dev requirements: build: - {{ compiler('cxx') }} # [linux] + - vc 14 # [win] - cmake >=3.10 - libcsm + - vc 14 # [win] + run: + - vc # [win] test: commands: - test -e $PREFIX/lib/libusgscsm.so # [linux] - test -e $PREFIX/lib/libusgscsm.dylib # [osx] + - if not exist %LIBRARY_BIN%\usgscsm.dll exit 1 # [win] about: home: https://github.com/USGS-Astrogeology/CSM-CameraModels license: None - summary: "USGS Astrogeology Community Sensor Model compliant sensor models." +summary: "USGS Astrogeology Community Sensor Model compliant sensor models." diff --git a/src/UsgsAstroFramePlugin.cpp b/src/UsgsAstroFramePlugin.cpp deleted file mode 100644 index 74cf266..0000000 --- a/src/UsgsAstroFramePlugin.cpp +++ /dev/null @@ -1,620 +0,0 @@ -#include "UsgsAstroFramePlugin.h" -#include "UsgsAstroFrameSensorModel.h" - -#include <cstdlib> -#include <string> -#include <iostream> -#include <sstream> -#include <fstream> -#include <map> - -#include <csm.h> -#include <Error.h> -#include <Plugin.h> -#include <Warning.h> -#include <Version.h> - -#include <json.hpp> - - -using json = nlohmann::json; - -#ifdef _WIN32 -# define DIR_DELIMITER_STR "\\" -#else -# define DIR_DELIMITER_STR "/" -#endif - - -// Declaration of static variables -const std::string UsgsAstroFramePlugin::_PLUGIN_NAME = "UsgsAstroFramePluginCSM"; -const std::string UsgsAstroFramePlugin::_MANUFACTURER_NAME = "UsgsAstrogeology"; -const std::string UsgsAstroFramePlugin::_RELEASE_DATE = "20170425"; -const int UsgsAstroFramePlugin::_N_SENSOR_MODELS = 1; - -const int UsgsAstroFramePlugin::_NUM_ISD_KEYWORDS = 36; -const std::string UsgsAstroFramePlugin::_ISD_KEYWORD[] = -{ - "boresight", - "ccd_center", - "ephemeris_time", - "focal_length", - "focal_length_epsilon", - "ifov", - "instrument_id", - "itrans_line", - "itrans_sample", - "kappa", - "min_elevation", - "max_elevation", - "model_name", - "nlines", - "nsamples", - "odt_x", - "odt_y", - "omega", - "original_half_lines", - "original_half_samples", - "phi", - "pixel_pitch", - "semi_major_axis", - "semi_minor_axis", - "spacecraft_name", - "starting_detector_line", - "starting_detector_sample", - "target_name", - "transx", - "transy", - "x_sensor_origin", - "y_sensor_origin", - "z_sensor_origin", - "x_sensor_velocity", - "y_sensor_velocity", - "z_sensor_velocity", - "x_sun_position", - "y_sun_position", - "z_sun_position" -}; - -const int UsgsAstroFramePlugin::_NUM_STATE_KEYWORDS = 32; -const std::string UsgsAstroFramePlugin::_STATE_KEYWORD[] = -{ - "m_focalLength", - "m_iTransS", - "m_iTransL", - "m_boresight", - "m_transX", - "m_transY", - "m_majorAxis", - "m_minorAxis", - "m_spacecraftVelocity", - "m_sunPosition", - "m_startingDetectorSample", - "m_startingDetectorLine", - "m_targetName", - "m_ifov", - "m_instrumentID", - "m_focalLengthEpsilon", - "m_ccdCenter", - "m_line_pp", - "m_sample_pp", - "m_minElevation", - "m_maxElevation", - "m_odtX", - "m_odtY", - "m_originalHalfLines", - "m_originalHalfSamples", - "m_spacecraftName", - "m_pixelPitch", - "m_ephemerisTime", - "m_nLines", - "m_nSamples", - "m_currentParameterValue", - "m_currentParameterCovariance" -}; - - -// Static Instance of itself -const UsgsAstroFramePlugin UsgsAstroFramePlugin::m_registeredPlugin; - -UsgsAstroFramePlugin::UsgsAstroFramePlugin() { -} - - -UsgsAstroFramePlugin::~UsgsAstroFramePlugin() { -} - - -std::string UsgsAstroFramePlugin::getPluginName() const { - return _PLUGIN_NAME; -} - - -std::string UsgsAstroFramePlugin::getManufacturer() const { - return _MANUFACTURER_NAME; -} - - -std::string UsgsAstroFramePlugin::getReleaseDate() const { - return _RELEASE_DATE; -} - - -csm::Version UsgsAstroFramePlugin::getCsmVersion() const { - return CURRENT_CSM_VERSION; -} - - -size_t UsgsAstroFramePlugin::getNumModels() const { - return _N_SENSOR_MODELS; -} - - -std::string UsgsAstroFramePlugin::getModelName(size_t modelIndex) const { - - return UsgsAstroFrameSensorModel::_SENSOR_MODEL_NAME; -} - - -std::string UsgsAstroFramePlugin::getModelFamily(size_t modelIndex) const { - return CSM_RASTER_FAMILY; -} - - -csm::Version UsgsAstroFramePlugin::getModelVersion(const std::string &modelName) const { - return csm::Version(1, 0, 0); -} - - -bool UsgsAstroFramePlugin::canModelBeConstructedFromState(const std::string &modelName, - const std::string &modelState, - csm::WarningList *warnings) const { - bool constructible = true; - - // Get the model name from the model state - std::string model_name_from_state; - try { - model_name_from_state = getModelNameFromModelState(modelState, warnings); - } - catch(...) { - return false; - } - - // Check that the plugin supports the model - if (modelName != model_name_from_state || - modelName != UsgsAstroFrameSensorModel::_SENSOR_MODEL_NAME){ - constructible = false; - } - - // Check that the necessary keys are there (this does not check values at all.) - auto state = json::parse(modelState); - for(auto &key : _STATE_KEYWORD){ - if (state.find(key) == state.end()){ - constructible = false; - break; - } - } - return constructible; -} - - -bool UsgsAstroFramePlugin::canModelBeConstructedFromISD(const csm::Isd &imageSupportData, - const std::string &modelName, - csm::WarningList *warnings) const { - return canISDBeConvertedToModelState(imageSupportData, modelName, warnings); -} - - -csm::Model *UsgsAstroFramePlugin::constructModelFromState(const std::string& modelState, - csm::WarningList *warnings) const { - csm::Model *sensor_model = 0; - - // Get the sensor model name from the sensor model state - std::string model_name_from_state = getModelNameFromModelState(modelState); - - if (model_name_from_state != UsgsAstroFrameSensorModel::_SENSOR_MODEL_NAME){ - csm::Error::ErrorType aErrorType = csm::Error::INVALID_SENSOR_MODEL_STATE; - std::string aMessage = "Model name from state is not recognized."; - std::string aFunction = "UsgsAstroFramePlugin::constructModelFromState()"; - throw csm::Error(aErrorType, aMessage, aFunction); - } - - if (!canModelBeConstructedFromState(model_name_from_state, modelState)){ - csm::Error::ErrorType aErrorType = csm::Error::INVALID_SENSOR_MODEL_STATE; - std::string aMessage = "Model state is not valid."; - std::string aFunction = "UsgsAstroFramePlugin::constructModelFromState()"; - throw csm::Error(aErrorType, aMessage, aFunction); - } - - // Create the model from the state - UsgsAstroFrameSensorModel* mdsensor_model = new UsgsAstroFrameSensorModel(); - - auto state = json::parse(modelState); - - mdsensor_model->m_ccdCenter[0] = state["m_ccdCenter"][0]; - mdsensor_model->m_ccdCenter[1] = state["m_ccdCenter"][1]; - mdsensor_model->m_ephemerisTime = state["m_ephemerisTime"]; - mdsensor_model->m_focalLength = state["m_focalLength"]; - mdsensor_model->m_focalLengthEpsilon = state["m_focalLengthEpsilon"]; - mdsensor_model->m_ifov = state["m_ifov"]; - mdsensor_model->m_instrumentID = state["m_instrumentID"]; - - mdsensor_model->m_majorAxis = state["m_majorAxis"]; - mdsensor_model->m_minorAxis = state["m_minorAxis"]; - mdsensor_model->m_startingDetectorLine = state["m_startingDetectorLine"]; - mdsensor_model->m_startingDetectorSample = state["m_startingDetectorSample"]; - mdsensor_model->m_line_pp = state["m_line_pp"]; - mdsensor_model->m_sample_pp = state["m_sample_pp"]; - mdsensor_model->m_originalHalfLines = state["m_originalHalfLines"]; - mdsensor_model->m_originalHalfSamples = state["m_originalHalfSamples"]; - mdsensor_model->m_spacecraftName = state["m_spacecraftName"]; - mdsensor_model->m_pixelPitch = state["m_pixelPitch"]; - mdsensor_model->m_nLines = state["m_nLines"]; - mdsensor_model->m_nSamples = state["m_nSamples"]; - mdsensor_model->m_minElevation = state["m_minElevation"]; - mdsensor_model->m_maxElevation = state["m_maxElevation"]; - - for (int i=0;i<3;i++){ - mdsensor_model->m_boresight[i] = state["m_boresight"][i]; - mdsensor_model->m_iTransL[i] = state["m_iTransL"][i]; - mdsensor_model->m_iTransS[i] = state["m_iTransS"][i]; - - mdsensor_model->m_transX[i] = state["m_transX"][i]; - mdsensor_model->m_transY[i] = state["m_transY"][i]; - mdsensor_model->m_spacecraftVelocity[i] = state["m_spacecraftVelocity"][i]; - mdsensor_model->m_sunPosition[i] = state["m_sunPosition"][i]; - } - - // Having types as vectors, instead of arrays makes interoperability with - // the JSON library very easy. - mdsensor_model->m_currentParameterValue = state["m_currentParameterValue"].get<std::vector<double>>(); - mdsensor_model->m_odtX = state["m_odtX"].get<std::vector<double>>(); - mdsensor_model->m_odtY = state["m_odtY"].get<std::vector<double>>(); - - mdsensor_model->m_currentParameterCovariance = state["m_currentParameterCovariance"].get<std::vector<double>>(); - -sensor_model = mdsensor_model; -return sensor_model; -} - - -// This function takes a csm::Isd which only has the image filename set. It uses this filename to -// find a metadata json file loacated alongside the image file. It creates and returns new csm::Isd -// with its parameters populated by the metadata file. -csm::Isd UsgsAstroFramePlugin::loadImageSupportData(const csm::Isd &imageSupportDataOriginal) const{ - // Get image location from the input csm::Isd: - std::string imageFilename = imageSupportDataOriginal.filename(); - - // Load 'sidecar' ISD file - size_t lastIndex = imageFilename.find_last_of("."); - std::string baseName = imageFilename.substr(0, lastIndex); - std::string isdFilename = baseName.append(".json"); - - csm::Isd imageSupportData(isdFilename); - imageSupportData.clearAllParams(); - - try { - std::ifstream isdFile(isdFilename); - json jsonIsd = json::parse(isdFile); - for (json::iterator it = jsonIsd.begin(); it != jsonIsd.end(); ++it) { - if (it.value().size() >1 ) { - std::vector<double> v = it.value(); - for (int j=0;j < v.size(); j++) { - std::ostringstream val; - val << std::setprecision(15) << v[j]; - imageSupportData.addParam(it.key(),val.str()); - } - } - else { - imageSupportData.addParam(it.key(), it.value().dump()); - } - } - isdFile.close(); - } catch (...) { - std::string errorMessage = "Could not read metadata file associated with image: "; - errorMessage.append(isdFilename); - throw csm::Error(csm::Error::FILE_READ, errorMessage, - "UsgsAstroFramePlugin::loadImageSupportData"); - } - - return imageSupportData; -} - -csm::Model *UsgsAstroFramePlugin::constructModelFromISD(const csm::Isd &imageSupportDataOriginal, - const std::string &modelName, - csm::WarningList *warnings) const { - - csm::Isd imageSupportData = loadImageSupportData(imageSupportDataOriginal); - - // FIXME: Check needs to be updated to use new JSON isd spec - // Check if the sensor model can be constructed from ISD given the model name - if (!canModelBeConstructedFromISD(imageSupportData, modelName)) { - throw csm::Error(csm::Error::ISD_NOT_SUPPORTED, - "Sensor model support data provided is not supported by this plugin", - "UsgsAstroFramePlugin::constructModelFromISD"); - } - - // Create the empty sensorModel - UsgsAstroFrameSensorModel *sensorModel = new UsgsAstroFrameSensorModel(); - - // Keep track of necessary keywords that are missing from the ISD. - std::vector<std::string> missingKeywords; - - sensorModel->m_startingDetectorSample = - atof(imageSupportData.param("starting_detector_sample").c_str()); - sensorModel->m_startingDetectorLine = - atof(imageSupportData.param("starting_detector_line").c_str()); - - sensorModel->m_targetName = imageSupportData.param("target_name"); - - sensorModel->m_ifov = atof(imageSupportData.param("ifov").c_str()); - - sensorModel->m_instrumentID = imageSupportData.param("instrument_id"); - if (imageSupportData.param("instrument_id") == "") { - missingKeywords.push_back("instrument_id"); - } - sensorModel->m_focalLength = atof(imageSupportData.param("focal_length").c_str()); - if (imageSupportData.param("focal_length") == "") { - missingKeywords.push_back("focal_length"); - } - sensorModel->m_focalLengthEpsilon = - atof(imageSupportData.param("focal_length_epsilon").c_str()); - - sensorModel->m_currentParameterValue[0] = - atof(imageSupportData.param("x_sensor_origin").c_str()); - sensorModel->m_currentParameterValue[1] = - atof(imageSupportData.param("y_sensor_origin").c_str()); - sensorModel->m_currentParameterValue[2] = - atof(imageSupportData.param("z_sensor_origin").c_str()); - if (imageSupportData.param("x_sensor_origin") == "") { - missingKeywords.push_back("x_sensor_origin"); - } - if (imageSupportData.param("y_sensor_origin") == "") { - missingKeywords.push_back("y_sensor_origin"); - } - if (imageSupportData.param("z_sensor_origin") == "") { - missingKeywords.push_back("z_sensor_origin"); - } - - sensorModel->m_spacecraftVelocity[0] = - atof(imageSupportData.param("x_sensor_velocity").c_str()); - sensorModel->m_spacecraftVelocity[1] = - atof(imageSupportData.param("y_sensor_velocity").c_str()); - sensorModel->m_spacecraftVelocity[2] = - atof(imageSupportData.param("z_sensor_velocity").c_str()); - // sensor velocity not strictly necessary? - - sensorModel->m_sunPosition[0] = - atof(imageSupportData.param("x_sun_position").c_str()); - sensorModel->m_sunPosition[1] = - atof(imageSupportData.param("y_sun_position").c_str()); - sensorModel->m_sunPosition[2] = - atof(imageSupportData.param("z_sun_position").c_str()); - // sun position is not strictly necessary, but is required for getIlluminationDirection. - - sensorModel->m_currentParameterValue[3] = atof(imageSupportData.param("omega").c_str()); - sensorModel->m_currentParameterValue[4] = atof(imageSupportData.param("phi").c_str()); - sensorModel->m_currentParameterValue[5] = atof(imageSupportData.param("kappa").c_str()); - if (imageSupportData.param("omega") == "") { - missingKeywords.push_back("omega"); - } - if (imageSupportData.param("phi") == "") { - missingKeywords.push_back("phi"); - } - if (imageSupportData.param("kappa") == "") { - missingKeywords.push_back("kappa"); - } - - sensorModel->m_odtX[0] = atof(imageSupportData.param("odt_x", 0).c_str()); - sensorModel->m_odtX[1] = atof(imageSupportData.param("odt_x", 1).c_str()); - sensorModel->m_odtX[2] = atof(imageSupportData.param("odt_x", 2).c_str()); - sensorModel->m_odtX[3] = atof(imageSupportData.param("odt_x", 3).c_str()); - sensorModel->m_odtX[4] = atof(imageSupportData.param("odt_x", 4).c_str()); - sensorModel->m_odtX[5] = atof(imageSupportData.param("odt_x", 5).c_str()); - sensorModel->m_odtX[6] = atof(imageSupportData.param("odt_x", 6).c_str()); - sensorModel->m_odtX[7] = atof(imageSupportData.param("odt_x", 7).c_str()); - sensorModel->m_odtX[8] = atof(imageSupportData.param("odt_x", 8).c_str()); - sensorModel->m_odtX[9] = atof(imageSupportData.param("odt_x", 9).c_str()); - - sensorModel->m_odtY[0] = atof(imageSupportData.param("odt_y", 0).c_str()); - sensorModel->m_odtY[1] = atof(imageSupportData.param("odt_y", 1).c_str()); - sensorModel->m_odtY[2] = atof(imageSupportData.param("odt_y", 2).c_str()); - sensorModel->m_odtY[3] = atof(imageSupportData.param("odt_y", 3).c_str()); - sensorModel->m_odtY[4] = atof(imageSupportData.param("odt_y", 4).c_str()); - sensorModel->m_odtY[5] = atof(imageSupportData.param("odt_y", 5).c_str()); - sensorModel->m_odtY[6] = atof(imageSupportData.param("odt_y", 6).c_str()); - sensorModel->m_odtY[7] = atof(imageSupportData.param("odt_y", 7).c_str()); - sensorModel->m_odtY[8] = atof(imageSupportData.param("odt_y", 8).c_str()); - sensorModel->m_odtY[9] = atof(imageSupportData.param("odt_y", 9).c_str()); - - sensorModel->m_ccdCenter[0] = atof(imageSupportData.param("ccd_center", 0).c_str()); - sensorModel->m_ccdCenter[1] = atof(imageSupportData.param("ccd_center", 1).c_str()); - - sensorModel->m_originalHalfLines = atof(imageSupportData.param("original_half_lines").c_str()); - sensorModel->m_spacecraftName = imageSupportData.param("spacecraft_name"); - - sensorModel->m_pixelPitch = atof(imageSupportData.param("pixel_pitch").c_str()); - - sensorModel->m_iTransS[0] = atof(imageSupportData.param("itrans_sample", 0).c_str()); - sensorModel->m_iTransS[1] = atof(imageSupportData.param("itrans_sample", 1).c_str()); - sensorModel->m_iTransS[2] = atof(imageSupportData.param("itrans_sample", 2).c_str()); - - if (imageSupportData.param("itrans_sample", 0) == "") { - missingKeywords.push_back("itrans_sample missing first element"); - } - else if (imageSupportData.param("itrans_sample", 1) == "") { - missingKeywords.push_back("itrans_sample missing second element"); - } - else if (imageSupportData.param("itrans_sample", 2) == "") { - missingKeywords.push_back("itrans_sample missing third element"); - } - - sensorModel->m_ephemerisTime = atof(imageSupportData.param("ephemeris_time").c_str()); - if (imageSupportData.param("ephemeris_time") == "") { - missingKeywords.push_back("ephemeris_time"); - } - - sensorModel->m_originalHalfSamples = - atof(imageSupportData.param("original_half_samples").c_str()); - - sensorModel->m_boresight[0] = atof(imageSupportData.param("boresight", 0).c_str()); - sensorModel->m_boresight[1] = atof(imageSupportData.param("boresight", 1).c_str()); - sensorModel->m_boresight[2] = atof(imageSupportData.param("boresight", 2).c_str()); - - sensorModel->m_iTransL[0] = atof(imageSupportData.param("itrans_line", 0).c_str()); - sensorModel->m_iTransL[1] = atof(imageSupportData.param("itrans_line", 1).c_str()); - sensorModel->m_iTransL[2] = atof(imageSupportData.param("itrans_line", 2).c_str()); - if (imageSupportData.param("itrans_line", 0) == "") { - missingKeywords.push_back("itrans_line needs 3 elements"); - } - else if (imageSupportData.param("itrans_line", 1) == "") { - missingKeywords.push_back("itrans_line needs 3 elements"); - } - else if (imageSupportData.param("itrans_line", 2) == "") { - missingKeywords.push_back("itrans_line needs 3 elements"); - } - - sensorModel->m_nLines = atoi(imageSupportData.param("nlines").c_str()); - sensorModel->m_nSamples = atoi(imageSupportData.param("nsamples").c_str()); - if (imageSupportData.param("nlines") == "") { - missingKeywords.push_back("nlines"); - } - if (imageSupportData.param("nsamples") == "") { - missingKeywords.push_back("nsamples"); - } - - sensorModel->m_transY[0] = atof(imageSupportData.param("transy", 0).c_str()); - sensorModel->m_transY[1] = atof(imageSupportData.param("transy", 1).c_str()); - sensorModel->m_transY[2] = atof(imageSupportData.param("transy", 2).c_str()); - if (imageSupportData.param("transy", 0) == "") { - missingKeywords.push_back("transy 0"); - } - else if (imageSupportData.param("transy", 1) == "") { - missingKeywords.push_back("transy 1"); - } - else if (imageSupportData.param("transy", 2) == "") { - missingKeywords.push_back("transy 2"); - } - - sensorModel->m_transX[0] = atof(imageSupportData.param("transx", 0).c_str()); - sensorModel->m_transX[1] = atof(imageSupportData.param("transx", 1).c_str()); - sensorModel->m_transX[2] = atof(imageSupportData.param("transx", 2).c_str()); - if (imageSupportData.param("transx", 0) == "") { - missingKeywords.push_back("transx 0"); - } - else if (imageSupportData.param("transx", 1) == "") { - missingKeywords.push_back("transx 1"); - } - else if (imageSupportData.param("transx", 2) == "") { - missingKeywords.push_back("transx"); - } - - sensorModel->m_majorAxis = 1000 * atof(imageSupportData.param("semi_major_axis").c_str()); - if (imageSupportData.param("semi_major_axis") == "") { - missingKeywords.push_back("semi_major_axis"); - } - // Do we assume that if we do not have a semi-minor axis, then the body is a sphere? - if (imageSupportData.param("semi_minor_axis") == "") { - sensorModel->m_minorAxis = sensorModel->m_majorAxis; - } - else { - sensorModel->m_minorAxis = 1000 * atof(imageSupportData.param("semi_minor_axis").c_str()); - } - - sensorModel->m_minElevation = atof(imageSupportData.param("min_elevation").c_str()); - sensorModel->m_maxElevation = atof(imageSupportData.param("max_elevation").c_str()); - if (imageSupportData.param("min_elevation") == ""){ - missingKeywords.push_back("min_elevation"); - } - if (imageSupportData.param("max_elevation") == ""){ - missingKeywords.push_back("max_elevation"); - } - // If we are missing necessary keywords from ISD, we cannot create a valid sensor model. - if (missingKeywords.size() != 0) { - - std::string errorMessage = "ISD is missing the necessary keywords: ["; - - for (int i = 0; i < (int)missingKeywords.size(); i++) { - if (i == (int)missingKeywords.size() - 1) { - errorMessage += missingKeywords[i] + "]"; - } - else { - errorMessage += missingKeywords[i] + ", "; - } - } - - throw csm::Error(csm::Error::SENSOR_MODEL_NOT_CONSTRUCTIBLE, - errorMessage, - "UsgsAstroFramePlugin::constructModelFromISD"); - } - - return sensorModel; -} - - -std::string UsgsAstroFramePlugin::getModelNameFromModelState(const std::string &modelState, - csm::WarningList *warnings) const { - std::string name; - auto state = json::parse(modelState); - if(state.find("model_name") != state.end()){ - name = state["model_name"]; - } - else{ - csm::Error::ErrorType aErrorType = csm::Error::INVALID_SENSOR_MODEL_STATE; - std::string aMessage = "No 'model_name' key in the model state object."; - std::string aFunction = "UsgsAstroFramePlugin::getModelNameFromModelState"; - csm::Error csmErr(aErrorType, aMessage, aFunction); - throw(csmErr); - } - - if (name != UsgsAstroFrameSensorModel::_SENSOR_MODEL_NAME){ - csm::Error::ErrorType aErrorType = csm::Error::SENSOR_MODEL_NOT_SUPPORTED; - std::string aMessage = "Sensor model not supported."; - std::string aFunction = "UsgsAstroFramePlugin::getModelNameFromModelState()"; - csm::Error csmErr(aErrorType, aMessage, aFunction); - throw(csmErr); - } - - - return UsgsAstroFrameSensorModel::_SENSOR_MODEL_NAME; -} - - -bool UsgsAstroFramePlugin::canISDBeConvertedToModelState(const csm::Isd &imageSupportData, - const std::string &modelName, - csm::WarningList *warnings) const { - bool convertible = true; - if (modelName !=UsgsAstroFrameSensorModel::_SENSOR_MODEL_NAME){ - convertible = false; - } - - csm::Isd localImageSupportData = imageSupportData; - if (imageSupportData.parameters().empty()) { - localImageSupportData = loadImageSupportData(imageSupportData); - } - - std::string value; - for(auto &key : _ISD_KEYWORD){ - value = localImageSupportData.param(key); - if (value.empty()){ - convertible = false; - } - } - return convertible; -} - - -std::string UsgsAstroFramePlugin::convertISDToModelState(const csm::Isd &imageSupportData, - const std::string &modelName, - csm::WarningList *warnings) const { - csm::Model* sensor_model = constructModelFromISD( - imageSupportData, modelName); - - if (sensor_model == 0){ - csm::Error::ErrorType aErrorType = csm::Error::ISD_NOT_SUPPORTED; - std::string aMessage = "ISD not supported: "; - std::string aFunction = "UsgsAstroFramePlugin::convertISDToModelState()"; - throw csm::Error(aErrorType, aMessage, aFunction); - } - return sensor_model->getModelState(); -} diff --git a/src/UsgsAstroFrameSensorModel.cpp b/src/UsgsAstroFrameSensorModel.cpp index f3050b4..2ef4aea 100644 --- a/src/UsgsAstroFrameSensorModel.cpp +++ b/src/UsgsAstroFrameSensorModel.cpp @@ -15,134 +15,63 @@ using namespace std; // Declaration of static variables const std::string UsgsAstroFrameSensorModel::_SENSOR_MODEL_NAME = "USGS_ASTRO_FRAME_SENSOR_MODEL"; -const int UsgsAstroFrameSensorModel::m_numParameters = 6; +const int UsgsAstroFrameSensorModel::NUM_PARAMETERS = 7; const std::string UsgsAstroFrameSensorModel::m_parameterName[] = { "X Sensor Position (m)", // 0 "Y Sensor Position (m)", // 1 "Z Sensor Position (m)", // 2 - "Omega (radians)", // 3 - "Phi (radians)", // 4 - "Kappa (radians)" // 5 + "w", // 3 + "v1", // 4 + "v2", // 5 + "v3" // 6 }; const int UsgsAstroFrameSensorModel::_NUM_STATE_KEYWORDS = 32; -const std::string UsgsAstroFrameSensorModel::_STATE_KEYWORD[] = -{ - "m_focalLength", - "m_iTransS", - "m_iTransL", - "m_boresight", - "m_transX", - "m_transY", - "m_majorAxis", - "m_minorAxis", - "m_spacecraftVelocity", - "m_sunPosition", - "m_startingDetectorSample", - "m_startingDetectorLine", - "m_targetName", - "m_ifov", - "m_instrumentID", - "m_focalLengthEpsilon", - "m_ccdCenter", - "m_line_pp", - "m_sample_pp", - "m_minElevation", - "m_maxElevation", - "m_odtX", - "m_odtY", - "m_originalHalfLines", - "m_originalHalfSamples", - "m_spacecraftName", - "m_pixelPitch", - "m_ephemerisTime", - "m_nLines", - "m_nSamples", - "m_minElevation", - "m_maxElevation", - "m_currentParameterValue", - "m_currentParameterCovariance" -}; UsgsAstroFrameSensorModel::UsgsAstroFrameSensorModel() { + reset(); +} - m_transX[0] = 0.0; - m_transX[1] = 0.0; - m_transX[2] = 0.0; - - m_transY[0] = 0.0; - m_transY[1] = 0.0; - m_transY[2] = 0.0; - - m_iTransS[0] = 0.0; - m_iTransS[1] = 0.0; - m_iTransS[2] = 0.0; - - m_iTransL[0] = 0.0; - m_iTransL[0] = 0.0; - m_iTransL[0] = 0.0; - - m_majorAxis = 0.0; - m_minorAxis = 0.0; - m_focalLength = 0.0; - - m_spacecraftVelocity[0] = 0.0; - m_spacecraftVelocity[1] = 0.0; - m_spacecraftVelocity[2] = 0.0; - - m_sunPosition[0] = 0.0; - m_sunPosition[1] = 0.0; - m_sunPosition[2] = 0.0; - - m_startingDetectorSample = 0.0; - m_startingDetectorLine = 0.0; - m_targetName = ""; - m_ifov = 0.0; - m_instrumentID = ""; - m_focalLengthEpsilon = 0.0; - - m_ccdCenter[0] = 0.0; - m_ccdCenter[1] = 0.0; - - m_line_pp = 0.0; - m_sample_pp = 0.0; - - m_odtX.assign(10, 0.0); - m_odtY.assign(10, 0.0); - - m_originalHalfLines = 0.0; - m_spacecraftName = ""; - m_pixelPitch = 0.0; - - m_iTransS[0] = 0.0; - m_iTransS[1] = 0.0; - m_iTransS[2] = 0.0; - - m_iTransL[0] = 0.0; - m_iTransL[1] = 0.0; - m_iTransL[2] = 0.0; - - m_ephemerisTime = 0.0; - m_originalHalfSamples = 0.0; - m_boresight[0] = 0.0; - m_boresight[1] = 0.0; - m_boresight[2] = 0.0; - - m_nLines = 0; - m_nSamples = 0; - - m_currentParameterValue.assign(m_numParameters, 0.0); - m_currentParameterCovariance.assign(m_numParameters*m_numParameters,0.0); - m_noAdjustments.assign(m_numParameters,0.0); - - m_parameterType.assign(m_numParameters, csm::param::REAL); - +void UsgsAstroFrameSensorModel::reset() { + m_modelName = _SENSOR_MODEL_NAME; + m_majorAxis = 0.0; + m_minorAxis = 0.0; + m_focalLength = 0.0; + m_startingDetectorSample = 0.0; + m_startingDetectorLine = 0.0; + m_targetName = ""; + m_ifov = 0; + m_instrumentID = ""; + m_focalLengthEpsilon = 0.0; + m_linePp = 0.0; + m_samplePp = 0.0; + m_originalHalfLines = 0.0; + m_spacecraftName = ""; + m_pixelPitch = 0.0; + m_ephemerisTime = 0.0; + m_originalHalfSamples = 0.0; + m_nLines = 0; + m_nSamples = 0; + + m_currentParameterValue = std::vector<double>(NUM_PARAMETERS, 0.0); + m_currentParameterCovariance = std::vector<double>(NUM_PARAMETERS*NUM_PARAMETERS,0.0); + m_noAdjustments = std::vector<double>(NUM_PARAMETERS,0.0); + m_ccdCenter = std::vector<double>(2, 0.0); + m_spacecraftVelocity = std::vector<double>(3, 0.0); + m_sunPosition = std::vector<double>(3, 0.0); + m_odtX = std::vector<double>(10, 0.0); + m_odtY = std::vector<double>(10, 0.0); + m_transX = std::vector<double>(3, 0.0); + m_transY = std::vector<double>(3, 0.0); + m_iTransS = std::vector<double>(3, 0.0); + m_iTransL = std::vector<double>(3, 0.0); + m_boresight = std::vector<double>(3, 0.0); + m_parameterType = std::vector<csm::param::Type>(NUM_PARAMETERS, csm::param::REAL); } UsgsAstroFrameSensorModel::~UsgsAstroFrameSensorModel() {} - /** * @brief UsgsAstroFrameSensorModel::groundToImage * @param groundPt @@ -157,7 +86,7 @@ csm::ImageCoord UsgsAstroFrameSensorModel::groundToImage(const csm::EcefCoord &g double *achievedPrecision, csm::WarningList *warnings) const { - return groundToImage(groundPt,m_noAdjustments,desiredPrecision,achievedPrecision,warnings); + return groundToImage(groundPt, m_noAdjustments, desiredPrecision, achievedPrecision, warnings); } @@ -196,18 +125,18 @@ csm::ImageCoord UsgsAstroFrameSensorModel::groundToImage( // Sensor position double undistortedx, undistortedy, denom; denom = m[0][2] * xo + m[1][2] * yo + m[2][2] * zo; - undistortedx = (f * (m[0][0] * xo + m[1][0] * yo + m[2][0] * zo)/denom) + m_sample_pp; //m_sample_pp like this assumes mm - undistortedy = (f * (m[0][1] * xo + m[1][1] * yo + m[2][1] * zo)/denom) + m_line_pp; + undistortedx = (f * (m[0][0] * xo + m[1][0] * yo + m[2][0] * zo)/denom) + m_samplePp; //m_samplePp like this assumes mm + undistortedy = (f * (m[0][1] * xo + m[1][1] * yo + m[2][1] * zo)/denom) + m_linePp; // Apply the distortion to the line/sample location and then convert back to line/sample double distortedx, distortedy; distortionFunction(undistortedx, undistortedy, distortedx, distortedy); - //Convert distorted mm into line/sample + // Convert distorted mm into line/sample double sample, line; - sample = m_iTransS[0] + m_iTransS[1] * distortedx + m_iTransS[2] * distortedx + m_ccdCenter[0]; - line = m_iTransL[0] + m_iTransL[1] * distortedy + m_iTransL[2] * distortedy + m_ccdCenter[0]; + sample = m_iTransS[0] + m_iTransS[1] * distortedx + m_iTransS[2] * distortedy + m_ccdCenter[1]; + line = m_iTransL[0] + m_iTransL[1] * distortedx + m_iTransL[2] * distortedy + m_ccdCenter[0]; return csm::ImageCoord(line, sample); } @@ -233,27 +162,28 @@ csm::EcefCoord UsgsAstroFrameSensorModel::imageToGround(const csm::ImageCoord &i double sample = imagePt.samp; double line = imagePt.line; - //Here is where we should be able to apply an adjustment to opk + // Here is where we should be able to apply an adjustment to opk double m[3][3]; calcRotationMatrix(m); - //Apply the principal point offset, assuming the pp is given in pixels + // Apply the principal point offset, assuming the pp is given in pixels double xl, yl, zl, lo, so; - lo = line - m_line_pp; - so = sample - m_sample_pp; + lo = line - m_linePp; + so = sample - m_samplePp; - //Convert from the pixel space into the metric space - double optical_center_x, optical_center_y, x_camera, y_camera; - optical_center_x = m_ccdCenter[0]; - optical_center_y = m_ccdCenter[1]; - y_camera = m_transY[0] + m_transY[1] * (lo - optical_center_y) + m_transY[2] * (lo - optical_center_y); - x_camera = m_transX[0] + m_transX[1] * (so - optical_center_x) + m_transX[2] * (so - optical_center_x); + // Convert from the pixel space into the metric space + double line_center, sample_center, x_camera, y_camera; + line_center = m_ccdCenter[0]; + sample_center = m_ccdCenter[1]; + y_camera = m_transY[0] + m_transY[1] * (lo - line_center) + m_transY[2] * (so - sample_center); + x_camera = m_transX[0] + m_transX[1] * (lo - line_center) + m_transX[2] * (so - sample_center); // Apply the distortion model (remove distortion) double undistorted_cameraX, undistorted_cameraY = 0.0; + setFocalPlane(x_camera, y_camera, undistorted_cameraX, undistorted_cameraY); - //Now back from distorted mm to pixels + // Now back from distorted mm to pixels double udx, udy; //distorted line and sample udx = undistorted_cameraX; udy = undistorted_cameraY; @@ -269,6 +199,7 @@ csm::EcefCoord UsgsAstroFrameSensorModel::imageToGround(const csm::ImageCoord &i zc = m_currentParameterValue[2]; // Intersect with some height about the ellipsoid. + losEllipsoidIntersect(height, xc, yc, zc, xl, yl, zl, x, y, z); return csm::EcefCoord(x, y, z); @@ -301,10 +232,10 @@ csm::EcefLocus UsgsAstroFrameSensorModel::imageToRemoteImagingLocus(const csm::I csm::WarningList *warnings) const { // Find the line,sample on the focal plane (mm) // CSM center = 0.5, MDIS IK center = 1.0 - double col = imagePt.samp - (m_ccdCenter[0]); - double row = imagePt.line - (m_ccdCenter[1]); - double focalPlaneX = m_transX[0] + m_transX[1] * col + m_transX[2] * col; - double focalPlaneY = m_transY[0] + m_transY[1] * row + m_transY[2] * row; + double row = imagePt.line - m_ccdCenter[0]; + double col = imagePt.samp - m_ccdCenter[1]; + double focalPlaneX = m_transX[0] + m_transX[1] * row + m_transX[2] * col; + double focalPlaneY = m_transY[0] + m_transY[1] * row + m_transY[2] * col; // Distort double undistortedFocalPlaneX = focalPlaneX; @@ -500,7 +431,7 @@ csm::RasterGM::SensorPartials UsgsAstroFrameSensorModel::computeSensorPartials(i const double delta = 1.0; // Update the parameter - std::vector<double>adj(m_numParameters, 0.0); + std::vector<double>adj(NUM_PARAMETERS, 0.0); adj[index] = delta; csm::ImageCoord imagePt1 = groundToImage(groundPt,adj,desiredPrecision,achievedPrecision); @@ -520,103 +451,101 @@ std::vector<csm::RasterGM::SensorPartials> UsgsAstroFrameSensorModel::computeAll csm::param::Set pset, double desiredPrecision, double *achievedPrecision, - csm::WarningList *warnings) const - { - std::vector<int> indices = getParameterSetIndices(pset); - size_t num = indices.size(); - std::vector<csm::RasterGM::SensorPartials> partials; - for (int index = 0;index < num;index++){ - partials.push_back(computeSensorPartials( - indices[index], - imagePt, groundPt, - desiredPrecision, achievedPrecision, warnings)); - } - return partials; - } + csm::WarningList *warnings) const { + std::vector<int> indices = getParameterSetIndices(pset); + size_t num = indices.size(); + std::vector<csm::RasterGM::SensorPartials> partials; + for (int index = 0;index < num;index++){ + partials.push_back(computeSensorPartials( + indices[index], + imagePt, groundPt, + desiredPrecision, achievedPrecision, warnings)); + } + return partials; +} std::vector<csm::RasterGM::SensorPartials> UsgsAstroFrameSensorModel::computeAllSensorPartials( const csm::EcefCoord& groundPt, csm::param::Set pset, double desiredPrecision, double *achievedPrecision, - csm::WarningList *warnings) const - { - csm::ImageCoord imagePt = groundToImage(groundPt, - desiredPrecision, achievedPrecision, warnings); - return computeAllSensorPartials(imagePt, groundPt, - pset, desiredPrecision, achievedPrecision, warnings); + csm::WarningList *warnings) const { + csm::ImageCoord imagePt = groundToImage(groundPt, + desiredPrecision, achievedPrecision, warnings); + return computeAllSensorPartials(imagePt, groundPt, + pset, desiredPrecision, achievedPrecision, warnings); } -std::vector<double> UsgsAstroFrameSensorModel::computeGroundPartials(const csm::EcefCoord &groundPt) const { - - // Partials of line, sample wrt X, Y, Z - // Uses collinearity equations - std::vector<double> partials(6, 0.0); - - double m[3][3]; - calcRotationMatrix(m, m_noAdjustments); - - double xo, yo, zo; - xo = groundPt.x - m_currentParameterValue[0]; - yo = groundPt.y - m_currentParameterValue[1]; - zo = groundPt.z - m_currentParameterValue[2]; - - double u, v, w; - u = m[0][0] * xo + m[0][1] * yo + m[0][2] * zo; - v = m[1][0] * xo + m[1][1] * yo + m[1][2] * zo; - w = m[2][0] * xo + m[2][1] * yo + m[2][2] * zo; +std::vector<double> UsgsAstroFrameSensorModel::computeGroundPartials(const csm::EcefCoord + &groundPt) const { + // Partials of line, sample wrt X, Y, Z + // Uses collinearity equations + std::vector<double> partials(6, 0.0); - double fdw, udw, vdw; - fdw = m_focalLength / w; - udw = u / w; - vdw = v / w; - - double upx, vpx, wpx; - upx = m[0][0]; - vpx = m[1][0]; - wpx = m[2][0]; - partials[0] = -fdw * ( upx - udw * wpx ); - partials[3] = -fdw * ( vpx - vdw * wpx ); - - double upy, vpy, wpy; - upy = m[0][1]; - vpy = m[1][1]; - wpy = m[2][1]; - partials[1] = -fdw * ( upy - udw * wpy ); - partials[4] = -fdw * ( vpy - vdw * wpy ); - - double upz, vpz, wpz; - upz = m[0][2]; - vpz = m[1][2]; - wpz = m[2][2]; - partials[2] = -fdw * ( upz - udw * wpz ); - partials[5] = -fdw * ( vpz - vdw * wpz ); + double m[3][3]; + calcRotationMatrix(m, m_noAdjustments); + + double xo, yo, zo; + xo = groundPt.x - m_currentParameterValue[0]; + yo = groundPt.y - m_currentParameterValue[1]; + zo = groundPt.z - m_currentParameterValue[2]; + + double u, v, w; + u = m[0][0] * xo + m[0][1] * yo + m[0][2] * zo; + v = m[1][0] * xo + m[1][1] * yo + m[1][2] * zo; + w = m[2][0] * xo + m[2][1] * yo + m[2][2] * zo; + + double fdw, udw, vdw; + fdw = m_focalLength / w; + udw = u / w; + vdw = v / w; + + double upx, vpx, wpx; + upx = m[0][0]; + vpx = m[1][0]; + wpx = m[2][0]; + partials[0] = -fdw * ( upx - udw * wpx ); + partials[3] = -fdw * ( vpx - vdw * wpx ); + + double upy, vpy, wpy; + upy = m[0][1]; + vpy = m[1][1]; + wpy = m[2][1]; + partials[1] = -fdw * ( upy - udw * wpy ); + partials[4] = -fdw * ( vpy - vdw * wpy ); + + double upz, vpz, wpz; + upz = m[0][2]; + vpz = m[1][2]; + wpz = m[2][2]; + partials[2] = -fdw * ( upz - udw * wpz ); + partials[5] = -fdw * ( vpz - vdw * wpz ); - return partials; + return partials; } const csm::CorrelationModel& UsgsAstroFrameSensorModel::getCorrelationModel() const { - return _no_corr_model; + return _no_corr_model; } std::vector<double> UsgsAstroFrameSensorModel::getUnmodeledCrossCovariance(const csm::ImageCoord &pt1, const csm::ImageCoord &pt2) const { - throw csm::Error(csm::Error::UNSUPPORTED_FUNCTION, - "Unsupported function", - "UsgsAstroFrameSensorModel::getUnmodeledCrossCovariance"); + throw csm::Error(csm::Error::UNSUPPORTED_FUNCTION, + "Unsupported function", + "UsgsAstroFrameSensorModel::getUnmodeledCrossCovariance"); } csm::Version UsgsAstroFrameSensorModel::getVersion() const { - return csm::Version(0,1,0); + return csm::Version(0,1,0); } std::string UsgsAstroFrameSensorModel::getModelName() const { - return _SENSOR_MODEL_NAME; + return _SENSOR_MODEL_NAME; } @@ -689,7 +618,7 @@ std::string UsgsAstroFrameSensorModel::getReferenceDateAndTime() const { std::string UsgsAstroFrameSensorModel::getModelState() const { json state = { - {"model_name", _SENSOR_MODEL_NAME}, + {"m_modelName", _SENSOR_MODEL_NAME}, {"m_focalLength" , m_focalLength}, {"m_iTransS", {m_iTransS[0], m_iTransS[1], m_iTransS[2]}}, {"m_iTransL", {m_iTransL[0], m_iTransL[1], m_iTransL[2]}}, @@ -709,8 +638,8 @@ std::string UsgsAstroFrameSensorModel::getModelState() const { {"m_instrumentID", m_instrumentID}, {"m_focalLengthEpsilon", m_focalLengthEpsilon}, {"m_ccdCenter", {m_ccdCenter[0], m_ccdCenter[1]}}, - {"m_line_pp", m_line_pp}, - {"m_sample_pp", m_sample_pp}, + {"m_linePp", m_linePp}, + {"m_samplePp", m_samplePp}, {"m_minElevation", m_minElevation}, {"m_maxElevation", m_maxElevation}, {"m_odtX", {m_odtX[0], m_odtX[1], m_odtX[2], m_odtX[3], m_odtX[4], @@ -726,69 +655,321 @@ std::string UsgsAstroFrameSensorModel::getModelState() const { {"m_nSamples", m_nSamples}, {"m_currentParameterValue", {m_currentParameterValue[0], m_currentParameterValue[1], m_currentParameterValue[2], m_currentParameterValue[3], - m_currentParameterValue[4], m_currentParameterValue[5]}}, + m_currentParameterValue[4], m_currentParameterValue[5], + m_currentParameterValue[6]}}, {"m_currentParameterCovariance", m_currentParameterCovariance} }; + return state.dump(); } +bool UsgsAstroFrameSensorModel::isValidModelState(const std::string& stringState, csm::WarningList *warnings) { + std::vector<std::string> requiredKeywords = { + "m_modelName", + "m_majorAxis", + "m_minorAxis", + "m_focalLength", + "m_startingDetectorSample", + "m_startingDetectorLine", + "m_focalLengthEpsilon", + "m_nLines", + "m_nSamples", + "m_currentParameterValue", + "m_ccdCenter", + "m_spacecraftVelocity", + "m_sunPosition", + "m_odtX", + "m_odtY", + "m_transX", + "m_transY", + "m_iTransS", + "m_iTransL" + }; + + json jsonState = json::parse(stringState); + std::vector<std::string> missingKeywords; + + for (auto &key : requiredKeywords) { + if (jsonState.find(key) == jsonState.end()) { + missingKeywords.push_back(key); + } + } + + if (!missingKeywords.empty()) { + std::ostringstream oss; + std::copy(missingKeywords.begin(), missingKeywords.end(), std::ostream_iterator<std::string>(oss, " ")); + warnings->push_back(csm::Warning( + csm::Warning::DATA_NOT_AVAILABLE, + "State has missing keywrods: " + oss.str(), + "UsgsAstroFrameSensorModel::isValidModelState" + )); + } + + std::string modelName = jsonState.value<std::string>("m_modelName", ""); + + if (modelName != _SENSOR_MODEL_NAME) { + warnings->push_back(csm::Warning( + csm::Warning::DATA_NOT_AVAILABLE, + "Incorrect model name in state, expected " + _SENSOR_MODEL_NAME + " but got " + modelName, + "UsgsAstroFrameSensorModel::isValidModelState" + )); + } + + return modelName == _SENSOR_MODEL_NAME && missingKeywords.empty(); +} + + +bool UsgsAstroFrameSensorModel::isValidIsd(const std::string& Isd, csm::WarningList *warnings) { + // no obvious clean way to truely validate ISD with it's nested structure, + // or rather, it would be a pain to maintain, so just check if + // we can get a valid state from ISD. Once ISD schema is 100% clear + // we can change this. + try { + std::string state = constructStateFromIsd(Isd, warnings); + return isValidModelState(state, warnings); + } + catch(...) { + return false; + } +} + -void UsgsAstroFrameSensorModel::replaceModelState(const std::string& modelState) { - auto state = json::parse(modelState); - for(auto &key : _STATE_KEYWORD){ - if (state.find(key) == state.end()){ - csm::Error::ErrorType aErrorType = csm::Error::INVALID_SENSOR_MODEL_STATE; - std::string aMessage = "State key %s mission", key; - std::string aFunction = "UsgsAstroFramePlugin::replaceModelState()"; - throw csm::Error(aErrorType, aMessage, aFunction); - } - // TODO: This is pulled right out of the plugin - good reason to have the state be a - // distinct class a la the generic line scan model. - m_ccdCenter[0] = state["m_ccdCenter"][0]; - m_ccdCenter[1] = state["m_ccdCenter"][1]; - m_ephemerisTime = state["m_ephemerisTime"]; - m_focalLength = state["m_focalLength"]; - m_focalLengthEpsilon = state["m_focalLengthEpsilon"]; - m_ifov = state["m_ifov"]; - m_instrumentID = state["m_instrumentID"]; - - m_majorAxis = state["m_majorAxis"]; - m_minorAxis = state["m_minorAxis"]; - m_startingDetectorLine = state["m_startingDetectorLine"]; - m_startingDetectorSample = state["m_startingDetectorSample"]; - m_line_pp = state["m_line_pp"]; - m_sample_pp = state["m_sample_pp"]; - m_originalHalfLines = state["m_originalHalfLines"]; - m_originalHalfSamples = state["m_originalHalfSamples"]; - m_spacecraftName = state["m_spacecraftName"]; - m_pixelPitch = state["m_pixelPitch"]; - m_nLines = state["m_nLines"]; - m_nSamples = state["m_nSamples"]; - m_minElevation = state["m_minElevation"]; - m_maxElevation = state["m_maxElevation"]; - - for (int i=0;i<3;i++){ - m_boresight[i] = state["m_boresight"][i]; - m_iTransL[i] = state["m_iTransL"][i]; - m_iTransS[i] = state["m_iTransS"][i]; - - m_transX[i] = state["m_transX"][i]; - m_transY[i] = state["m_transY"][i]; - m_spacecraftVelocity[i] = state["m_spacecraftVelocity"][i]; - m_sunPosition[i] = state["m_sunPosition"][i]; - } - - // Having types as vectors, instead of arrays makes interoperability with - // the JSON library very easy. - m_currentParameterValue = state["m_currentParameterValue"].get<std::vector<double>>(); - m_odtX = state["m_odtX"].get<std::vector<double>>(); - m_odtY = state["m_odtY"].get<std::vector<double>>(); - - m_currentParameterCovariance = state["m_currentParameterCovariance"].get<std::vector<double>>(); +void UsgsAstroFrameSensorModel::replaceModelState(const std::string& stringState) { + + json state = json::parse(stringState); + + // The json library's .at() will except if key is missing + try { + m_modelName = state.at("m_modelName").get<std::string>(); + m_majorAxis = state.at("m_majorAxis").get<double>(); + m_minorAxis = state.at("m_minorAxis").get<double>(); + m_focalLength = state.at("m_focalLength").get<double>(); + m_startingDetectorSample = state.at("m_startingDetectorSample").get<double>(); + m_startingDetectorLine = state.at("m_startingDetectorLine").get<double>(); + m_focalLengthEpsilon = state.at("m_focalLengthEpsilon").get<double>(); + m_nLines = state.at("m_nLines").get<int>(); + m_nSamples = state.at("m_nSamples").get<int>(); + m_currentParameterValue = state.at("m_currentParameterValue").get<std::vector<double>>(); + m_ccdCenter = state.at("m_ccdCenter").get<std::vector<double>>(); + m_spacecraftVelocity = state.at("m_spacecraftVelocity").get<std::vector<double>>(); + m_sunPosition = state.at("m_sunPosition").get<std::vector<double>>(); + m_odtX = state.at("m_odtX").get<std::vector<double>>(); + m_odtY = state.at("m_odtY").get<std::vector<double>>(); + m_transX = state.at("m_transX").get<std::vector<double>>(); + m_transY = state.at("m_transY").get<std::vector<double>>(); + m_iTransS = state.at("m_iTransS").get<std::vector<double>>(); + m_iTransL = state.at("m_iTransL").get<std::vector<double>>(); + + // Leaving unused params commented out + // m_targetName = state.at("m_targetName").get<std::string>(); + // m_ifov = state.at("m_ifov").get<double>(); + // m_instrumentID = state.at("m_instrumentID").get<std::string>(); + // m_currentParameterCovariance = state.at("m_currentParameterCovariance").get<std::vector<double>>(); + // m_noAdjustments = state.at("m_noAdjustments").get<std::vector<double>>(); + // m_linePp = state.at("m_linePp").get<double>(); + // m_samplePp = state.at("m_samplePp").get<double>(); + // m_originalHalfLines = state.at("m_originalHalfLines").get<double>(); + // m_spacecraftName = state.at("m_spacecraftName").get<std::string>(); + // m_pixelPitch = state.at("m_pixelPitch").get<double>(); + // m_ephemerisTime = state.at("m_ephemerisTime").get<double>(); + // m_originalHalfSamples = state.at("m_originalHalfSamples").get<double>(); + // m_boresight = state.at("m_boresight").get<std::vector<double>>(); + + // Cast int vector to csm::param::Type vector by simply copying it + // std::vector<int> paramType = state.at("m_parameterType").get<std::vector<int>>(); + // m_parameterType = std::vector<csm::param::Type>(); + // for(auto &t : paramType){ + // paramType.push_back(static_cast<csm::param::Type>(t)); + // } + } + catch(std::out_of_range& e) { + throw csm::Error(csm::Error::SENSOR_MODEL_NOT_CONSTRUCTIBLE, + "State keywords required to generate sensor model missing: " + std::string(e.what()) + "\nUsing model string: " + stringState, + "UsgsAstroFrameSensorModel::replaceModelState"); } } +std::string UsgsAstroFrameSensorModel::constructStateFromIsd(const std::string& jsonIsd, csm::WarningList* warnings) { + auto metric_conversion = [](double val, std::string from, std::string to="m") { + json typemap = { + {"m", 0}, + {"km", 3} + }; + + // everything to lowercase + std::transform(from.begin(), from.end(), from.begin(), ::tolower); + std::transform(to.begin(), to.end(), to.begin(), ::tolower); + return val*pow(10, typemap[from].get<int>() - typemap[to].get<int>()); + }; + + json isd = json::parse(jsonIsd); + json state = {}; + + + try { + state["m_modelName"] = isd.at("name_model"); + std::cerr << "Model Name Parsed!" << std::endl; + + state["m_startingDetectorSample"] = isd.at("starting_detector_sample"); + state["m_startingDetectorLine"] = isd.at("starting_detector_line"); + + std::cerr << "Detector Starting Pixel Parsed!" << std::endl; + + // get focal length + { + json jayson = isd.at("focal_length_model"); + json focal_length = jayson.at("focal_length"); + json epsilon = jayson.at("focal_epsilon"); + + state["m_focalLength"] = focal_length; + state["m_focalLengthEpsilon"] = epsilon; + + std::cerr << "Focal Length Parsed!" << std::endl; + } + + // get sensor_position + { + json jayson = isd.at("sensor_position"); + json positions = jayson.at("positions")[0]; + json velocities = jayson.at("velocities")[0]; + json unit = jayson.at("unit"); + + unit = unit.get<std::string>(); + state["m_currentParameterValue"] = json(); + state["m_currentParameterValue"][0] = metric_conversion(positions[0].get<double>(), unit); + state["m_currentParameterValue"][1] = metric_conversion(positions[1].get<double>(), unit); + state["m_currentParameterValue"][2] = metric_conversion(positions[2].get<double>(), unit); + state["m_spacecraftVelocity"] = velocities; + + std::cerr << "Sensor Location Parsed!" << std::endl; + } + + // get sun_position + // sun position is not strictly necessary, but is required for getIlluminationDirection. + { + json jayson = isd.at("sun_position"); + json positions = jayson.at("positions")[0]; + json unit = jayson.at("unit"); + + unit = unit.get<std::string>(); + state["m_sunPosition"] = json(); + state["m_sunPosition"][0] = metric_conversion(positions[0].get<double>(), unit); + state["m_sunPosition"][1] = metric_conversion(positions[1].get<double>(), unit); + state["m_sunPosition"][2] = metric_conversion(positions[2].get<double>(), unit); + + std::cerr << "Sun Position Parsed!" << std::endl; + } + + // get sensor_orientation quaternion + { + json jayson = isd.at("sensor_orientation"); + json quaternion = jayson.at("quaternions")[0]; + + state["m_currentParameterValue"][3] = quaternion[0]; + state["m_currentParameterValue"][4] = quaternion[1]; + state["m_currentParameterValue"][5] = quaternion[2]; + state["m_currentParameterValue"][6] = quaternion[3]; + + std::cerr << "Sensor Orientation Parsed!" << std::endl; + } + + // get optical_distortion + { + json jayson = isd.at("optical_distortion"); + std::vector<double> xDistortion = jayson.at("transverse").at("x"); + std::vector<double> yDistortion = jayson.at("transverse").at("y"); + xDistortion.resize(10, 0.0); + yDistortion.resize(10, 0.0); + + state["m_odtX"] = xDistortion; + state["m_odtY"] = yDistortion; + + std::cerr << "Distortion Parsed!" << std::endl; + } + + // get detector_center + { + json jayson = isd.at("detector_center"); + json sample = jayson.at("sample"); + json line = jayson.at("line"); + + state["m_ccdCenter"][0] = line; + state["m_ccdCenter"][1] = sample; + + std::cerr << "Detector Center Parsed!" << std::endl; + } + + // get radii + { + json jayson = isd.at("radii"); + json semiminor = jayson.at("semiminor"); + json semimajor = jayson.at("semimajor"); + json unit = jayson.at("unit"); + + unit = unit.get<std::string>(); + state["m_minorAxis"] = metric_conversion(semiminor.get<double>(), unit); + state["m_majorAxis"] = metric_conversion(semimajor.get<double>(), unit); + + std::cerr << "Target Radii Parsed!" << std::endl; + } + + // get reference_height + { + json reference_height = isd.at("reference_height"); + json maxheight = reference_height.at("maxheight"); + json minheight = reference_height.at("minheight"); + json unit = reference_height.at("unit"); + + unit = unit.get<std::string>(); + state["m_minElevation"] = metric_conversion(minheight.get<double>(), unit); + state["m_maxElevation"] = metric_conversion(maxheight.get<double>(), unit); + + std::cerr << "Reference Height Parsed!" << std::endl; + } + + state["m_ephemerisTime"] = isd.at("center_ephemeris_time"); + state["m_nLines"] = isd.at("image_lines"); + state["m_nSamples"] = isd.at("image_samples"); + + state["m_iTransL"] = isd.at("focal2pixel_lines"); + + state["m_iTransS"] = isd.at("focal2pixel_samples"); + + // We don't pass the pixel to focal plane transformation so invert the + // focal plane to pixel transformation + double determinant = state["m_iTransL"][1].get<double>() * state["m_iTransS"][2].get<double>() - + state["m_iTransL"][2].get<double>() * state["m_iTransS"][1].get<double>(); + + state["m_transX"][1] = state["m_iTransL"][1].get<double>() / determinant; + state["m_transX"][2] = -state["m_iTransS"][1].get<double>() / determinant; + state["m_transX"][0] = -(state["m_transX"][1].get<double>() * state["m_iTransL"][0].get<double>() + + state["m_transX"][2].get<double>() * state["m_iTransS"][0].get<double>()); + + state["m_transY"][1] = -state["m_iTransL"][2].get<double>() / determinant; + state["m_transY"][2] = state["m_iTransS"][2].get<double>() / determinant; + state["m_transY"][0] = -(state["m_transY"][1].get<double>() * state["m_iTransL"][0].get<double>() + + state["m_transY"][2].get<double>() * state["m_iTransS"][0].get<double>()); + + std::cerr << "Focal To Pixel Transformation Parsed!" << std::endl; + + } + catch(std::out_of_range& e) { + throw csm::Error(csm::Error::SENSOR_MODEL_NOT_CONSTRUCTIBLE, + "ISD missing necessary keywords to create sensor model: " + std::string(e.what()), + "UsgsAstroFrameSensorModel::constructStateFromIsd"); + } + catch(...) { + throw csm::Error(csm::Error::SENSOR_MODEL_NOT_CONSTRUCTIBLE, + "ISD is invalid for creating the sensor model.", + "UsgsAstroFrameSensorModel::constructStateFromIsd"); + } + + return state.dump(); + +} + + csm::EcefCoord UsgsAstroFrameSensorModel::getReferencePoint() const { throw csm::Error(csm::Error::UNSUPPORTED_FUNCTION, "Unsupported function", @@ -804,13 +985,11 @@ void UsgsAstroFrameSensorModel::setReferencePoint(const csm::EcefCoord &groundPt int UsgsAstroFrameSensorModel::getNumParameters() const { - - return m_numParameters; + return NUM_PARAMETERS; } std::string UsgsAstroFrameSensorModel::getParameterName(int index) const { - return m_parameterName[index]; } @@ -925,49 +1104,41 @@ std::vector<double> UsgsAstroFrameSensorModel::getCrossCovarianceMatrix( void UsgsAstroFrameSensorModel::calcRotationMatrix( double m[3][3]) const { - // Trigonometric functions for rotation matrix - double sinw = std::sin(m_currentParameterValue[3]); - double cosw = std::cos(m_currentParameterValue[3]); - double sinp = std::sin(m_currentParameterValue[4]); - double cosp = std::cos(m_currentParameterValue[4]); - double sink = std::sin(m_currentParameterValue[5]); - double cosk = std::cos(m_currentParameterValue[5]); - - // Rotation matrix taken from Introduction to Mordern Photogrammetry by - // Edward M. Mikhail, et al., p. 373 - m[0][0] = cosp * cosk; - m[0][1] = cosw * sink + sinw * sinp * cosk; - m[0][2] = sinw * sink - cosw * sinp * cosk; - m[1][0] = -1 * cosp * sink; - m[1][1] = cosw * cosk - sinw * sinp * sink; - m[1][2] = sinw * cosk + cosw * sinp * sink; - m[2][0] = sinp; - m[2][1] = -1 * sinw * cosp; - m[2][2] = cosw * cosp; + double w = m_currentParameterValue[3]; + double x = m_currentParameterValue[4]; + double y = m_currentParameterValue[5]; + double z = m_currentParameterValue[6]; + + m[0][0] = w*w + x*x - y*y - z*z; + m[0][1] = 2 * (x*y - w*z); + m[0][2] = 2 * (w*y + x*z); + m[1][0] = 2 * (x*y + w*z); + m[1][1] = w*w - x*x + y*y - z*z; + m[1][2] = 2 * (y*z - w*x); + m[2][0] = 2 * (x*z - w*y); + m[2][1] = 2 * (w*x + y*z); + m[2][2] = w*w - x*x - y*y + z*z; } void UsgsAstroFrameSensorModel::calcRotationMatrix( double m[3][3], const std::vector<double> &adjustments) const { - // Trigonometric functions for rotation matrix - double sinw = std::sin(getValue(3,adjustments)); - double cosw = std::cos(getValue(3,adjustments)); - double sinp = std::sin(getValue(4,adjustments)); - double cosp = std::cos(getValue(4,adjustments)); - double sink = std::sin(getValue(5,adjustments)); - double cosk = std::cos(getValue(5,adjustments)); - - m[0][0] = cosp * cosk; - m[0][1] = cosw * sink + sinw * sinp * cosk; - m[0][2] = sinw * sink - cosw * sinp * cosk; - m[1][0] = -1 * cosp * sink; - m[1][1] = cosw * cosk - sinw * sinp * sink; - m[1][2] = sinw * cosk + cosw * sinp * sink; - m[2][0] = sinp; - m[2][1] = -1 * sinw * cosp; - m[2][2] = cosw * cosp; + double w = getValue(3, adjustments); + double x = getValue(4, adjustments); + double y = getValue(5, adjustments); + double z = getValue(6, adjustments); + + m[0][0] = w*w + x*x - y*y - z*z; + m[0][1] = 2 * (x*y - w*z); + m[0][2] = 2 * (w*y + x*z); + m[1][0] = 2 * (x*y + w*z); + m[1][1] = w*w - x*x + y*y - z*z; + m[1][2] = 2 * (y*z - w*x); + m[2][0] = 2 * (x*z - w*y); + m[2][1] = 2 * (w*x + y*z); + m[2][2] = w*w - x*x - y*y + z*z; } @@ -1045,7 +1216,7 @@ bool UsgsAstroFrameSensorModel::setFocalPlane(double dx,double dy, // Solve the distortion equation using the Newton-Raphson method. // Set the error tolerance to about one millionth of a NAC pixel. - const double tol = 1.4E-7; + const double tol = 1.4E-5; // The maximum number of iterations of the Newton-Raphson method. const int maxTries = 60; @@ -1076,9 +1247,8 @@ bool UsgsAstroFrameSensorModel::setFocalPlane(double dx,double dy, distortionJacobian(x, y, Jxx, Jxy, Jyx, Jyy); double determinant = Jxx * Jyy - Jxy * Jyx; - if (fabs(determinant) < 1E-7) { + if (fabs(determinant) < 1E-6) { - cout << "Singular determinant." << endl; undistortedX = x; undistortedY = y; // @@ -1106,9 +1276,7 @@ bool UsgsAstroFrameSensorModel::setFocalPlane(double dx,double dy, undistortedY = dy; return false; } - return true; - } @@ -1161,8 +1329,6 @@ void UsgsAstroFrameSensorModel::distortionJacobian(double x, double y, double &J Jyx = Jyx + d_dx[i] * m_odtY[i]; Jyy = Jyy + d_dy[i] * m_odtY[i]; } - - } diff --git a/src/UsgsAstroLsPlugin.cpp b/src/UsgsAstroLsPlugin.cpp deleted file mode 100644 index f275a0c..0000000 --- a/src/UsgsAstroLsPlugin.cpp +++ /dev/null @@ -1,534 +0,0 @@ -//---------------------------------------------------------------------------- -// -// UNCLASSIFIED -// -// Copyright © 1989-2017 BAE Systems Information and Electronic Systems Integration Inc. -// ALL RIGHTS RESERVED -// Use of this software product is governed by the terms of a license -// agreement. The license agreement is found in the installation directory. -// -// For support, please visit http://www.baesystems.com/gxp -// -// Revision History: -// Date Name Description -// ----------- --------- ----------------------------------------------- -// 30-APR-2017 BAE Systems Initial Implementation based on CSM 2.0 code -// 16-OCT-2017 BAE Systems Update for CSM 3.0.3 -// -//----------------------------------------------------------------------------- - -#define USGSASTROLINESCANNER_LIBRARY - -#include "UsgsAstroLsPlugin.h" -#include "UsgsAstroLsISD.h" -#include "UsgsAstroLsSensorModel.h" -#include "UsgsAstroLsStateData.h" - -#ifdef _WIN32 -# define DIR_DELIMITER_STR "\\" -#else -# define DIR_DELIMITER_STR "/" -#endif - -//#ifdef WIN32 -//#pragma comment(linker, SENCSM_MANIFESTDEPENDENCY_GXP_CSMAPI) -//#endif // WIN32 - -#include <iostream> -#include <sstream> -#include <fstream> -#include <stdlib.h> -#include <math.h> -#include <json.hpp> - - -using json = nlohmann::json; - -// Declaration of static variables -static const std::string PLUGIN_NAME = "USGS_ASTRO_LINE_SCANNER_PLUGIN"; -static const std::string MANUFACTURER_NAME = "BAE_SYSTEMS_GXP"; -static const std::string RELEASE_DATE = "20171230"; -static const int N_SENSOR_MODELS = 1; -const std::string UsgsAstroLsPlugin::mISD_KEYWORDS[] = -{ - "SENSOR_TYPE", - "TOTAL_LINES", - "TOTAL_SAMPLES", - "PLATFORM", - "ABERR", - "ATMREF", - "INT_TIME", - "STARTING_EPHEMERIS_TIME", - "CENTER_EPHEMERIS_TIME", - "DETECTOR_SAMPLE_SUMMING", - "STARTING_SAMPLE", - "IKCODE", - "FOCAL", - "ISIS_Z_DIRECTION", - "OPTICAL_DIST_COEF", - "ITRANSS", - "ITRANSL", - "DETECTOR_SAMPLE_ORIGIN", - "DETECTOR_LINE_ORIGIN", - "DETECTOR_LINE_OFFSET", - "MOUNTING_ANGLES", - "DT_EPHEM", - "T0_EPHEM", - "DT_QUAT", - "T0_QUAT", - "NUMBER_OF_EPHEM", - "NUMBER_OF_QUATERNIONS", - "EPHEM_PTS", - "EPHEM_RATES", - "QUATERNIONS", - "TRI_PARAMETERS", - "SEMI_MAJOR_AXIS", - "ECCENTRICITY", - // Everything below here is optional - "REFERENCE_HEIGHT", - "MIN_VALID_HT", - "MAX_VALID_HT", - "IMAGE_ID", - "SENSOR_ID", - "PLATFORM_ID", - "TRAJ_ID", - "COLL_ID", - "REF_DATE_TIME" -}; - -const std::string UsgsAstroLsPlugin::mSTATE_KEYWORDS[] = -{ - "STA_SENSOR_MODEL_NAME", - "STA_IMAGE_IDENTIFIER", - "STA_SENSOR_TYPE", - "STA_TOTAL_LINES", - "STA_TOTAL_SAMPLES", - "STA_OFFSET_LINES", - "STA_OFFSET_SAMPLES", - "STA_PLATFORM_FLAG", - "STA_ABERR_FLAG", - "STA_ATMREF_FLAG", - "STA_INT_TIME_LINES", - "STA_INT_TIME_START_TIMES", - "STA_INT_TIMES", - "STA_STARTING_EPHEMERIS_TIME", - "STA_CENTER_EPHEMERIS_TIME", - "STA_DETECTOR_SAMPLE_SUMMING", - "STA_STARTING_SAMPLE", - "STA_IK_CODE", - "STA_FOCAL", - "STA_ISIS_Z_DIRECTION", - "STA_OPTICAL_DIST_COEF", - "STA_I_TRANS_S", - "STA_I_TRANS_L", - "STA_DETECTOR_SAMPLE_ORIGIN", - "STA_DETECTOR_LINE_ORIGIN", - "STA_DETECTOR_LINE_OFFSET", - "STA_MOUNTING_MATRIX", - "STA_SEMI_MAJOR_AXIS", - "STA_SEMI_MINOR_AXIS", - "STA_REFERENCE_DATE_AND_TIME", - "STA_PLATFORM_IDENTIFIER", - "STA_SENSOR_IDENTIFIER", - "STA_TRAJECTORY_IDENTIFIER", - "STA_COLLECTION_IDENTIFIER", - "STA_REF_ELEVATION", - "STA_MIN_ELEVATION", - "STA_MAX_ELEVATION", - "STA_DT_EPHEM", - "STA_T0_EPHEM", - "STA_DT_QUAT", - "STA_T0_QUAT", - "STA_NUM_EPHEM", - "STA_NUM_QUATERNIONS", - "STA_EPHEM_PTS", - "STA_EPHEM_RATES", - "STA_QUATERNIONS", - "STA_PARAMETER_VALS", - "STA_PARAMETER_TYPE", - "STA_REFERENCE_POINT_XYZ", - "STA_GSD", - "STA_FLYING_HEIGHT", - "STA_HALF_SWATH", - "STA_HALF_TIME", - "STA_COVARIANCE", - "STA_IMAGE_FLIP_FLAG" -}; - -//*************************************************************************** -// Static instance of itself -//*************************************************************************** -const UsgsAstroLsPlugin UsgsAstroLsPlugin::_theRegisteringObject; - - -//*************************************************************************** -// UsgsAstroLsPlugin::UsgsAstroLsPlugin -//*************************************************************************** -UsgsAstroLsPlugin::UsgsAstroLsPlugin() -{ -} - -//***************************************************************************** -// UsgsAstroLsPlugin::~UsgsAstroLsPlugin -//***************************************************************************** -UsgsAstroLsPlugin::~UsgsAstroLsPlugin() -{ -} - -//*************************************************************************** -// UsgsAstroLsPlugin::getPluginName -//*************************************************************************** -std::string UsgsAstroLsPlugin::getPluginName() const -{ - return PLUGIN_NAME; -} - -//*************************************************************************** -// UsgsAstroLsPlugin::getManufacturer -//*************************************************************************** -std::string UsgsAstroLsPlugin::getManufacturer() const -{ - return MANUFACTURER_NAME; -} - -//*************************************************************************** -// UsgsAstroLsPlugin::getReleaseDate -//*************************************************************************** -std::string UsgsAstroLsPlugin::getReleaseDate() const -{ - return RELEASE_DATE; -} - -//*************************************************************************** -// UsgsAstroLsPlugin::getCSMVersion -//*************************************************************************** -csm::Version UsgsAstroLsPlugin::getCsmVersion() const -{ - return CURRENT_CSM_VERSION; -} - -//*************************************************************************** -// UsgsAstroLsPlugin::getNSensorModels -//*************************************************************************** -size_t UsgsAstroLsPlugin::getNumModels() const -{ - return N_SENSOR_MODELS; -} - -//*************************************************************************** -// UsgsAstroLsPlugin::getSensorModelName -//*************************************************************************** -std::string UsgsAstroLsPlugin::getModelName(size_t modelIndex) const -{ - // Always return the only sensor model name defined regardless of index - return UsgsAstroLsStateData::SENSOR_MODEL_NAME; -} - - -//*************************************************************************** -// UsgsAstroLsPlugin::getModelFamily -//*************************************************************************** -std::string UsgsAstroLsPlugin::getModelFamily(size_t modelIndex) const -{ - return CSM_RASTER_FAMILY; -} - -//*************************************************************************** -// UsgsAstroLsPlugin::getSensorModelVersion -//*************************************************************************** -csm::Version UsgsAstroLsPlugin::getModelVersion( - const std::string &model_name) const -{ - if (model_name != UsgsAstroLsStateData::SENSOR_MODEL_NAME) - { - csm::Error::ErrorType aErrorType = csm::Error::SENSOR_MODEL_NOT_SUPPORTED; - std::string aMessage = " Sensor model not supported: "; - std::string aFunction = "UsgsAstroLsPlugin::getSensorModelVersion()"; - csm::Error csmErr(aErrorType, aMessage, aFunction); - throw (csmErr); - } - - return csm::Version(1, 0, 0); -} - - -//*************************************************************************** -// UsgsAstroLsPlugin::canSensorModelBeConstructedFromState -//*************************************************************************** -bool UsgsAstroLsPlugin::canModelBeConstructedFromState( - const std::string& model_name, - const std::string& model_state, - csm::WarningList* warnings) const -{ - // Initialize constructible flag - bool constructible = true; - - // Get sensor model from sensor model state - std::string name_from_state; - - try - { - name_from_state = getModelNameFromModelState(model_state); - } - catch (...) - { - } - - // Check if plugin supports sensor model name - if (model_name != name_from_state) - { - constructible = false; - } - - // Check that all of the necessary state keys are in place - auto j = json::parse(model_state); - for (auto &key : mSTATE_KEYWORDS){ - if (j.find(key) == j.end()){ - constructible = false; - } - } - - return constructible; -} - -//*************************************************************************** -// UsgsAstroLsPlugin::canSensorModelBeConstructedFromISD -//*************************************************************************** -bool UsgsAstroLsPlugin::canModelBeConstructedFromISD( - const csm::Isd &image_support_data, - const std::string& model_name, - csm::WarningList* warnings) const -{ - // Check file validity - bool constructible = true; - - std::string value; - for(auto &key : mISD_KEYWORDS){ - value = image_support_data.param(key); - if (value.empty()){ - std::cout<<key<<"\n"<<std::endl; - constructible = false; - } - } - - return constructible; -} - - -//*************************************************************************** -// UsgsAstroLsPlugin::constructSensorModelFromState -//*************************************************************************** -csm::Model* UsgsAstroLsPlugin::constructModelFromState( - const std::string& model_state, - csm::WarningList* warnings ) const -{ - - // Get the sensor model name from the sensor model state - std::string model_name_from_state = getModelNameFromModelState(model_state); - - if (!canModelBeConstructedFromState(model_name_from_state, model_state)){ - csm::Error::ErrorType aErrorType = csm::Error::INVALID_SENSOR_MODEL_STATE; - std::string aMessage = "Model state is not valid."; - std::string aFunction = "UsgsAstroLsPlugin::constructModelFromState()"; - throw csm::Error(aErrorType, aMessage, aFunction); - } - UsgsAstroLsStateData data; - data.setState( model_state ); - - UsgsAstroLsSensorModel* sensor_model = new UsgsAstroLsSensorModel(); - // I do not think that exposing a set method is necessarily CSM compliant? - sensor_model->set( data ); - - return sensor_model; -} - -//*************************************************************************** -// UsgsAstroLsPlugin::constructSensorModelFromISD -//*************************************************************************** -csm::Model* UsgsAstroLsPlugin::constructModelFromISD( - const csm::Isd& image_support_data, - const std::string& model_name, - csm::WarningList* warnings) const -{ - std::string stateStr = convertISDToModelState(image_support_data, model_name, warnings); - UsgsAstroLsStateData state(stateStr); - - UsgsAstroLsSensorModel* sm = new UsgsAstroLsSensorModel(); - // I do not see things like flying height getting set properly, are things overflowing? - sm->set(state); - - csm::Model* sensor_model = sm; - return sensor_model; -} - -//*************************************************************************** -// UsgsAstroLsPlugin::getSensorModelNameFromSensorModelState -//*************************************************************************** -std::string UsgsAstroLsPlugin::getModelNameFromModelState( - const std::string& model_state, - csm::WarningList* warnings) const -{ - return UsgsAstroLsStateData::getModelNameFromModelState( model_state ); -} - -//*************************************************************************** -// UsgsAstroLsPlugin::canISDBeConvertedToSensorModelState -//*************************************************************************** -bool UsgsAstroLsPlugin::canISDBeConvertedToModelState( - const csm::Isd& image_support_data, - const std::string& model_name, - csm::WarningList* warnings) const -{ - // Check if ISD is supported - return canModelBeConstructedFromISD(image_support_data, model_name); -} - -//*************************************************************************** -// UsgsAstroLsPlugin::convertISDToSensorModelState -//*************************************************************************** -std::string UsgsAstroLsPlugin::convertISDToModelState( - const csm::Isd& image_support_data, - const std::string& model_name, - csm::WarningList* warnings) const -{ - - if (!canModelBeConstructedFromISD(image_support_data, model_name)){ - throw csm::Error(csm::Error::ISD_NOT_SUPPORTED, - "Sensor model support data provided is not supported by this plugin", - "GenericLsPlugin::constructModelFromISD"); - } - - // Instantiate UsgsAstroLineScanner sensor model - UsgsAstroLsStateData state; - int num_params = state.NUM_PARAMETERS; - //int num_params_square = num_params * num_params; - - // Translate the ISD to state data - // if( .m_image_id.size() > 1 && image_support_data.m_image_id != "UNKNOWN") - //{ - // state.m_ImageIdentifier = image_support_data.m_image_id; - //} - - //else - //{ - // state.m_ImageIdentifier = img_rel_name; - //} - - state.m_ImageIdentifier = image_support_data.param("IMAGE_ID"); - state.m_SensorType = image_support_data.param("SENSOR_TYPE"); - state.m_TotalLines = atoi(image_support_data.param("TOTAL_LINES").c_str()); - state.m_TotalSamples = atoi(image_support_data.param("TOTAL_SAMPLES").c_str()); - state.m_OffsetLines = 0.0; - state.m_OffsetSamples = 0.0; - state.m_PlatformFlag = atoi(image_support_data.param("PLATFORM").c_str()); - state.m_AberrFlag = atoi(image_support_data.param("ABERR").c_str()); - state.m_AtmRefFlag = atoi(image_support_data.param("ATMREF").c_str()); - state.m_StartingEphemerisTime = atof(image_support_data.param("STARTING_EPHEMERIS_TIME").c_str()); - state.m_CenterEphemerisTime = atof(image_support_data.param("CENTER_EPHEMERIS_TIME").c_str()); - if (image_support_data.param("NUMBER_OF_INT_TIMES").empty()) { - state.m_IntTimeLines = {0.5}; - state.m_IntTimeStartTimes = {state.m_StartingEphemerisTime - state.m_CenterEphemerisTime}; - state.m_IntTimes = {atof(image_support_data.param("INT_TIME").c_str())}; - } - else { - int numIntTimes = atoi(image_support_data.param("NUMBER_OF_INT_TIMES").c_str()); - for (int i = 0; i < numIntTimes; i++) { - state.m_IntTimeLines.push_back(atof(image_support_data.param("INT_TIME", i*3).c_str())); - state.m_IntTimeStartTimes.push_back(atof(image_support_data.param("INT_TIME", i*3 + 1).c_str())); - state.m_IntTimes.push_back(atof(image_support_data.param("INT_TIME", i*3 + 2).c_str())); - } - } - state.m_CenterEphemerisTime = atof(image_support_data.param("CENTER_EPHEMERIS_TIME").c_str()); - state.m_DetectorSampleSumming = atoi(image_support_data.param("DETECTOR_SAMPLE_SUMMING").c_str()); - state.m_StartingSample = atoi(image_support_data.param("STARTING_SAMPLE").c_str()); - state.m_IkCode = atoi(image_support_data.param("IKCODE").c_str()); - state.m_Focal = atof(image_support_data.param("FOCAL").c_str()); - state.m_IsisZDirection = atof(image_support_data.param("ISIS_Z_DIRECTION").c_str()); - - for (int i = 0; i < 3; i++) - { - state.m_OpticalDistCoef[i] = atof(image_support_data.param("OPTICAL_DIST_COEF", i).c_str()); - state.m_ITransS[i] = atof(image_support_data.param("ITRANSS", i).c_str()); - state.m_ITransL[i] = atof(image_support_data.param("ITRANSL", i).c_str()); - } - - state.m_DetectorSampleOrigin = atof(image_support_data.param("DETECTOR_SAMPLE_ORIGIN").c_str()); - state.m_DetectorLineOrigin = atof(image_support_data.param("DETECTOR_LINE_ORIGIN").c_str()); - state.m_DetectorLineOffset = atof(image_support_data.param("DETECTOR_LINE_OFFSET").c_str()); - - double cos_a = cos(atof(image_support_data.param("MOUNTING_ANGLES", 0).c_str())); - double sin_a = sin(atof(image_support_data.param("MOUNTING_ANGLES", 0).c_str())); - double cos_b = cos(atof(image_support_data.param("MOUNTING_ANGLES", 1).c_str())); - double sin_b = sin(atof(image_support_data.param("MOUNTING_ANGLES", 1).c_str())); - double cos_c = cos(atof(image_support_data.param("MOUNTING_ANGLES", 2).c_str())); - double sin_c = sin(atof(image_support_data.param("MOUNTING_ANGLES", 2).c_str())); - state.m_MountingMatrix[0] = cos_b * cos_c; - state.m_MountingMatrix[1] = -cos_a * sin_c + sin_a * sin_b * cos_c; - state.m_MountingMatrix[2] = sin_a * sin_c + cos_a * sin_b * cos_c; - state.m_MountingMatrix[3] = cos_b * sin_c; - state.m_MountingMatrix[4] = cos_a * cos_c + sin_a * sin_b * sin_c; - state.m_MountingMatrix[5] = -sin_a * cos_c + cos_a * sin_b * sin_c; - state.m_MountingMatrix[6] = -sin_b; - state.m_MountingMatrix[7] = sin_a * cos_b; - state.m_MountingMatrix[8] = cos_a * cos_b; - - state.m_DtEphem = atof(image_support_data.param("DT_EPHEM").c_str()); - state.m_T0Ephem = atof(image_support_data.param("T0_EPHEM").c_str()); - state.m_DtQuat = atof(image_support_data.param("DT_QUAT").c_str()); - state.m_T0Quat = atof(image_support_data.param("T0_QUAT").c_str()); - state.m_NumEphem = atoi(image_support_data.param("NUMBER_OF_EPHEM").c_str()); - state.m_NumQuaternions = atoi(image_support_data.param("NUMBER_OF_QUATERNIONS").c_str()); - - int numEphem = atoi(image_support_data.param("NUMBER_OF_EPHEM").c_str()); - for (int i=0;i < numEphem * 3; i++){ - state.m_EphemPts.push_back(atof(image_support_data.param("EPHEM_PTS", i).c_str())); - state.m_EphemRates.push_back(atof(image_support_data.param("EPHEM_RATES", i).c_str())); - } - - int numQuat = atoi(image_support_data.param("NUMBER_OF_QUATERNIONS").c_str()); - for (int i=0; i < numQuat * 4; i++){ - state.m_Quaternions.push_back(atof(image_support_data.param("QUATERNIONS", i).c_str())); - } - - //state.m_EphemPts = image_support_data.m_ephem_pts; - //state.m_EphemRates = image_support_data.m_ephem_rates; - //state.m_Quaternions = image_support_data.m_quaternions; - - for (int i=0; i < 18;i++){ - state.m_ParameterVals.push_back(atof(image_support_data.param("TRI_PARAMETERS", i).c_str())); - } - //state.m_ParameterVals = image_support_data.m_tri_parameters; - double deltaF = state.m_ParameterVals[num_params - 1] - state.m_Focal; - if (fabs(deltaF) < 0.4 * state.m_Focal) - state.m_ParameterVals[num_params - 1] = deltaF; - - // Set the ellipsoid - state.m_SemiMajorAxis = atof(image_support_data.param("SEMI_MAJOR_AXIS").c_str()); - state.m_SemiMinorAxis = - state.m_SemiMajorAxis * sqrt(1.0 - atof(image_support_data.param("ECCENTRICITY").c_str()) * atof(image_support_data.param("ECCENTRICITY").c_str())); - - // Now finish setting the state data from the ISD read in - - // set identifiers - state.m_ReferenceDateAndTime = image_support_data.param("REF_DATE_TIME"); - state.m_PlatformIdentifier = image_support_data.param("PLATFORM_ID"); - state.m_SensorIdentifier = image_support_data.param("SENSOR_ID"); - state.m_TrajectoryIdentifier = image_support_data.param("TRAJ_ID"); - state.m_CollectionIdentifier = image_support_data.param("COLL_ID"); - - // Ground elevations - state.m_RefElevation = atof(image_support_data.param("REFERNCE_HEIGHT").c_str()); - state.m_MinElevation = atof(image_support_data.param("MIN_VALID_HT").c_str()); - state.m_MaxElevation = atof(image_support_data.param("MAX_VALID_HT").c_str()); - - // Zero parameter values - for (int i = 0; i < num_params; i++) - { - state.m_ParameterVals[i] = 0.0; - state.m_ParameterType[i] = csm::param::REAL; - } - - // The state data will still be updated when a sensor model is created since - // some state data is notin the ISD and requires a SM to compute them. - return state.toJson(); -} diff --git a/src/UsgsAstroLsSensorModel.cpp b/src/UsgsAstroLsSensorModel.cpp index de6ea12..c3b0be4 100644 --- a/src/UsgsAstroLsSensorModel.cpp +++ b/src/UsgsAstroLsSensorModel.cpp @@ -16,7 +16,7 @@ // 24-Apr-2017 BAE Systems Update for CSM 3.0.2 // 24-OCT-2017 BAE Systems Update for CSM 3.0.3 //----------------------------------------------------------------------------- -#define USGSASTROLINESCANNER_LIBRARY +#define USGS_SENSOR_LIBRARY #include "UsgsAstroLsSensorModel.h" @@ -25,14 +25,396 @@ #include <sstream> #include <math.h> +#define USGSASTROLINESCANNER_LIBRARY + +#include <sstream> +#include <Error.h> +#include <json.hpp> +using json = nlohmann::json; + +const std::string UsgsAstroLsSensorModel::_SENSOR_MODEL_NAME + = "USGS_ASTRO_LINE_SCANNER_SENSOR_MODEL"; +const int UsgsAstroLsSensorModel::NUM_PARAMETERS = 16; +const std::string UsgsAstroLsSensorModel::PARAMETER_NAME[] = +{ + "IT Pos. Bias ", // 0 + "CT Pos. Bias ", // 1 + "Rad Pos. Bias ", // 2 + "IT Vel. Bias ", // 3 + "CT Vel. Bias ", // 4 + "Rad Vel. Bias ", // 5 + "Omega Bias ", // 6 + "Phi Bias ", // 7 + "Kappa Bias ", // 8 + "Omega Rate ", // 9 + "Phi Rate ", // 10 + "Kappa Rate ", // 11 + "Omega Accl ", // 12 + "Phi Accl ", // 13 + "Kappa Accl ", // 14 + "Focal Bias " // 15 +}; + + +const std::string UsgsAstroLsSensorModel::_STATE_KEYWORD[] = +{ + "m_sensorModelName", + "m_imageIdentifier", + "m_sensorType", + "m_totalLines", + "m_totalSamples", + "m_offsetLines", + "m_offsetSamples", + "m_platformFlag", + "m_aberrFlag", + "m_atmrefFlag", + "m_intTimeLines", + "m_intTimeStartTimes", + "m_intTimes", + "m_startingEphemerisTime", + "m_centerEphemerisTime", + "m_detectorSampleSumming", + "m_startingSample", + "m_ikCode", + "m_focal", + "m_isisZDirection", + "m_opticalDistCoef", + "m_iTransS", + "m_iTransL", + "m_detectorSampleOrigin", + "m_detectorLineOrigin", + "m_detectorLineOffset", + "m_mountingMatrix", + "m_semiMajorAxis", + "m_semiMinorAxis", + "m_referenceDateAndTime", + "m_platformIdentifier", + "m_sensorIdentifier", + "m_trajectoryIdentifier", + "m_collectionIdentifier", + "m_refElevation", + "m_minElevation", + "m_maxElevation", + "m_dtEphem", + "m_t0Ephem", + "m_dtQuat", + "m_t0Quat", + "m_numEphem", + "m_numQuaternions", + "m_ephemPts", + "m_ephemRates", + "m_quaternions", + "m_parameterVals", + "m_parameterType", + "m_referencePointXyz", + "m_gsd", + "m_flyingHeight", + "m_halfSwath", + "m_halfTime", + "m_covariance", + "m_imageFlipFlag" +}; + +const int UsgsAstroLsSensorModel::NUM_PARAM_TYPES = 4; +const std::string UsgsAstroLsSensorModel::PARAM_STRING_ALL[] = +{ + "NONE", + "FICTITIOUS", + "REAL", + "FIXED" +}; +const csm::param::Type + UsgsAstroLsSensorModel::PARAM_CHAR_ALL[] = +{ + csm::param::NONE, + csm::param::FICTITIOUS, + csm::param::REAL, + csm::param::FIXED +}; + + +void UsgsAstroLsSensorModel::replaceModelState(const std::string &stateString ) +{ + reset(); + auto j = json::parse(stateString); + int num_params = NUM_PARAMETERS; + int num_paramsSq = num_params * num_params; + + m_imageIdentifier = j["m_imageIdentifier"].get<std::string>(); + m_sensorType = j["m_sensorType"]; + m_totalLines = j["m_totalLines"]; + m_totalSamples = j["m_totalSamples"]; + m_offsetLines = j["m_offsetLines"]; + m_offsetSamples = j["m_offsetSamples"]; + m_platformFlag = j["m_platformFlag"]; + m_aberrFlag = j["m_aberrFlag"]; + m_atmRefFlag = j["m_atmRefFlag"]; + m_intTimeLines = j["m_intTimeLines"].get<std::vector<double>>(); + m_intTimeStartTimes = j["m_intTimeStartTimes"].get<std::vector<double>>(); + m_intTimes = j["m_intTimes"].get<std::vector<double>>(); + m_startingEphemerisTime = j["m_startingEphemerisTime"]; + m_centerEphemerisTime = j["m_centerEphemerisTime"]; + m_detectorSampleSumming = j["m_detectorSampleSumming"]; + m_startingSample = j["m_startingSample"]; + m_ikCode = j["m_ikCode"]; + m_focal = j["m_focal"]; + m_isisZDirection = j["m_isisZDirection"]; + for (int i = 0; i < 3; i++) { + m_opticalDistCoef[i] = j["m_opticalDistCoef"][i]; + m_iTransS[i] = j["m_iTransS"][i]; + m_iTransL[i] = j["m_iTransL"][i]; + } + m_detectorSampleOrigin = j["m_detectorSampleOrigin"]; + m_detectorLineOrigin = j["m_detectorLineOrigin"]; + m_detectorLineOffset = j["m_detectorLineOffset"]; + for (int i = 0; i < 9; i++) { + m_mountingMatrix[i] = j["m_mountingMatrix"][i]; + } + m_semiMajorAxis = j["m_semiMajorAxis"]; + m_semiMinorAxis = j["m_semiMinorAxis"]; + m_referenceDateAndTime = j["m_referenceDateAndTime"]; + m_platformIdentifier = j["m_platformIdentifier"]; + m_sensorIdentifier = j["m_sensorIdentifier"]; + m_trajectoryIdentifier = j["m_trajectoryIdentifier"]; + m_collectionIdentifier = j["m_collectionIdentifier"]; + m_refElevation = j["m_refElevation"]; + m_minElevation = j["m_minElevation"]; + m_maxElevation = j["m_maxElevation"]; + m_dtEphem = j["m_dtEphem"]; + m_t0Ephem = j["m_t0Ephem"]; + m_dtQuat = j["m_dtQuat"]; + m_t0Quat = j["m_t0Quat"]; + m_numEphem = j["m_numEphem"]; + m_numQuaternions = j["m_numQuaternions"]; + m_referencePointXyz.x = j["m_referencePointXyz"][0]; + m_referencePointXyz.y = j["m_referencePointXyz"][1]; + m_referencePointXyz.z = j["m_referencePointXyz"][2]; + m_gsd = j["m_gsd"]; + m_flyingHeight = j["m_flyingHeight"]; + m_halfSwath = j["m_halfSwath"]; + m_halfTime = j["m_halfTime"]; + m_imageFlipFlag = j["m_imageFlipFlag"]; + // Vector = is overloaded so explicit get with type required. + m_ephemPts = j["m_ephemPts"].get<std::vector<double>>(); + m_ephemRates = j["m_ephemRates"].get<std::vector<double>>(); + m_quaternions = j["m_quaternions"].get<std::vector<double>>(); + m_parameterVals = j["m_parameterVals"].get<std::vector<double>>(); + m_covariance = j["m_covariance"].get<std::vector<double>>(); + for (int i = 0; i < num_params; i++) { + for (int k = 0; k < NUM_PARAM_TYPES; k++) { + if (j["m_parameterType"][i] == PARAM_STRING_ALL[k]) { + m_parameterType[i] = PARAM_CHAR_ALL[k]; + break; + } + } + } + + // If computed state values are still default, then compute them + if (m_gsd == 1.0 && m_flyingHeight == 1000.0) + { + updateState(); + } + + try + { + setLinearApproximation(); + } + catch (...) + { + _linear = false; + } +} + +std::string UsgsAstroLsSensorModel::getModelNameFromModelState( + const std::string& model_state) +{ + // Parse the string to JSON + auto j = json::parse(model_state); + // If model name cannot be determined, return a blank string + std::string model_name; + + if (j.find("m_sensorModelName") != j.end()) { + model_name = j["m_sensorModelName"]; + } else { + csm::Error::ErrorType aErrorType = csm::Error::INVALID_SENSOR_MODEL_STATE; + std::string aMessage = "No 'm_sensorModelName' key in the model state object."; + std::string aFunction = "UsgsAstroLsPlugin::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 = "UsgsAstroLsPlugin::getModelNameFromModelState()"; + csm::Error csmErr(aErrorType, aMessage, aFunction); + throw(csmErr); + } + return model_name; +} + +std::string UsgsAstroLsSensorModel::getModelState() const { + json state; + state["m_imageIdentifier"] = m_imageIdentifier; + state["m_sensorType"] = m_sensorType; + state["m_totalLines"] = m_totalLines; + state["m_totalSamples"] = m_totalSamples; + state["m_offsetLines"] = m_offsetLines; + state["m_offsetSamples"] = m_offsetSamples; + state["m_platformFlag"] = m_platformFlag; + state["m_aberrFlag"] = m_aberrFlag; + state["m_atmRefFlag"] = m_atmRefFlag; + state["m_intTimeLines"] = m_intTimeLines; + state["m_intTimeStartTimes"] = m_intTimeStartTimes; + state["m_intTimes"] = m_intTimes; + state["m_startingEphemerisTime"] = m_startingEphemerisTime; + state["m_centerEphemerisTime"] = m_centerEphemerisTime; + state["m_detectorSampleSumming"] = m_detectorSampleSumming; + state["m_startingSample"] = m_startingSample; + state["m_ikCode"] = m_ikCode; + state["m_focal"] = m_focal; + state["m_isisZDirection"] = m_isisZDirection; + state["m_opticalDistCoef"] = std::vector<double>(m_opticalDistCoef, m_opticalDistCoef+3); + state["m_iTransS"] = std::vector<double>(m_iTransS, m_iTransS+3); + state["m_iTransL"] = std::vector<double>(m_iTransL, m_iTransL+3); + state["m_detectorSampleOrigin"] = m_detectorSampleOrigin; + state["m_detectorLineOrigin"] = m_detectorLineOrigin; + state["m_detectorLineOffset"] = m_detectorLineOffset; + state["m_mountingMatrix"] = std::vector<double>(m_mountingMatrix, m_mountingMatrix+9); + state["m_semiMajorAxis"] = m_semiMajorAxis; + state["m_semiMinorAxis"] = m_semiMinorAxis; + state["m_referenceDateAndTime"] = m_referenceDateAndTime; + state["m_platformIdentifier"] = m_platformIdentifier; + state["m_sensorIdentifier"] = m_sensorIdentifier; + state["m_trajectoryIdentifier"] = m_trajectoryIdentifier; + state["m_collectionIdentifier"] = m_collectionIdentifier; + state["m_refElevation"] = m_refElevation; + state["m_minElevation"] = m_minElevation; + state["m_maxElevation"] = m_maxElevation; + state["m_dtEphem"] = m_dtEphem; + state["m_t0Ephem"] = m_t0Ephem; + state["m_dtQuat"] = m_dtQuat; + state["m_t0Quat"] = m_t0Quat; + state["m_numEphem"] = m_numEphem; + state["m_numQuaternions"] = m_numQuaternions; + state["m_ephemPts"] = m_ephemPts; + state["m_ephemRates"] = m_ephemRates; + state["m_quaternions"] = m_quaternions; + state["m_parameterVals"] = m_parameterVals; + state["m_parameterType"] = m_parameterType; + state["m_gsd"] = m_gsd; + state["m_flyingHeight"] = m_flyingHeight; + state["m_halfSwath"] = m_halfSwath; + state["m_halfTime"] = m_halfTime; + state["m_covariance"] = m_covariance; + state["m_imageFlipFlag"] = m_imageFlipFlag; + + state["m_referencePointXyz"] = json(); + state["m_referencePointXyz"]["x"] = m_referencePointXyz.x; + state["m_referencePointXyz"]["y"] = m_referencePointXyz.y; + state["m_referencePointXyz"]["z"] = m_referencePointXyz.z; + + return state.dump(); + } + +void UsgsAstroLsSensorModel::reset() +{ + _linear = false; // default until a linear model is made + _u0 = 0.0; + _du_dx = 0.0; + _du_dy = 0.0; + _du_dz = 0.0; + _v0 = 0.0; + _dv_dx = 0.0; + _dv_dy = 0.0; + _dv_dz = 0.0; + + _no_adjustment.assign(UsgsAstroLsSensorModel::NUM_PARAMETERS, 0.0); + + m_imageIdentifier = ""; // 1 + m_sensorType = "USGSAstroLineScanner"; // 2 + m_totalLines = 0; // 3 + m_totalSamples = 0; // 4 + m_offsetLines = 0.0; // 7 + m_offsetSamples = 0.0; // 8 + m_platformFlag = 1; // 9 + m_aberrFlag = 0; // 10 + m_atmRefFlag = 0; // 11 + m_intTimeLines.clear(); + m_intTimeStartTimes.clear(); + m_intTimes.clear(); + m_startingEphemerisTime = 0.0; // 13 + m_centerEphemerisTime = 0.0; // 14 + m_detectorSampleSumming = 1.0; // 15 + m_startingSample = 1.0; // 16 + m_ikCode = -85600; // 17 + m_focal = 350.0; // 18 + m_isisZDirection = 1.0; // 19 + m_opticalDistCoef[0] = 0.0; // 20 + m_opticalDistCoef[1] = 0.0; // 20 + m_opticalDistCoef[2] = 0.0; // 20 + m_iTransS[0] = 0.0; // 21 + m_iTransS[1] = 0.0; // 21 + m_iTransS[2] = 150.0; // 21 + m_iTransL[0] = 0.0; // 22 + m_iTransL[1] = 150.0; // 22 + m_iTransL[2] = 0.0; // 22 + m_detectorSampleOrigin = 2500.0; // 23 + m_detectorLineOrigin = 0.0; // 24 + m_detectorLineOffset = 0.0; // 25 + m_mountingMatrix[0] = 1.0; // 26 + m_mountingMatrix[1] = 0.0; // 26 + m_mountingMatrix[2] = 0.0; // 26 + m_mountingMatrix[3] = 0.0; // 26 + m_mountingMatrix[4] = 1.0; // 26 + m_mountingMatrix[5] = 0.0; // 26 + m_mountingMatrix[6] = 0.0; // 26 + m_mountingMatrix[7] = 0.0; // 26 + m_mountingMatrix[8] = 1.0; // 26 + m_semiMajorAxis = 3400000.0; // 27 + m_semiMinorAxis = 3350000.0; // 28 + m_referenceDateAndTime = ""; // 30 + m_platformIdentifier = ""; // 31 + m_sensorIdentifier = ""; // 32 + m_trajectoryIdentifier = ""; // 33 + m_collectionIdentifier = ""; // 33 + m_refElevation = 30; // 34 + m_minElevation = -8000.0; // 34 + m_maxElevation = 8000.0; // 35 + m_dtEphem = 2.0; // 36 + m_t0Ephem = -70.0; // 37 + m_dtQuat = 0.1; // 38 + m_t0Quat = -40.0; // 39 + m_numEphem = 0; // 40 + m_numQuaternions = 0; // 41 + m_ephemPts.clear(); // 42 + m_ephemRates.clear(); // 43 + m_quaternions.clear(); // 44 + + m_parameterVals.assign(NUM_PARAMETERS,0.0); + m_parameterType.assign(NUM_PARAMETERS,csm::param::REAL); + + m_referencePointXyz.x = 0.0; // 47 + m_referencePointXyz.y = 0.0; // 47 + m_referencePointXyz.z = 0.0; // 47 + m_gsd = 1.0; // 48 + m_flyingHeight = 1000.0; // 49 + m_halfSwath = 1000.0; // 50 + m_halfTime = 10.0; // 51 + + m_covariance = std::vector<double>(NUM_PARAMETERS * NUM_PARAMETERS,0.0); // 52 + m_imageFlipFlag = 0; // 53 +} + + //***************************************************************************** // UsgsAstroLsSensorModel Constructor //***************************************************************************** UsgsAstroLsSensorModel::UsgsAstroLsSensorModel() { - _no_adjustment.assign(UsgsAstroLsStateData::NUM_PARAMETERS, 0.0); + _no_adjustment.assign(UsgsAstroLsSensorModel::NUM_PARAMETERS, 0.0); } + //***************************************************************************** // UsgsAstroLsSensorModel Destructor //***************************************************************************** @@ -40,41 +422,6 @@ UsgsAstroLsSensorModel::~UsgsAstroLsSensorModel() { } -//***************************************************************************** -// UsgsAstroLsSensorModel set -//***************************************************************************** -void UsgsAstroLsSensorModel::set(const UsgsAstroLsStateData &state_data) -{ - _linear = false; // default until a linear model is made - _u0 = 0.0; - _du_dx = 0.0; - _du_dy = 0.0; - _du_dz = 0.0; - _v0 = 0.0; - _dv_dx = 0.0; - _dv_dy = 0.0; - _dv_dz = 0.0; - - _no_adjustment.assign(UsgsAstroLsStateData::NUM_PARAMETERS, 0.0); - _data = state_data; - - // If needed set state data elements that need a sensor model to compute - // Update if still using default settings - if (_data.m_Gsd == 1.0 && _data.m_FlyingHeight == 1000.0) - { - updateState(); - } - - try - { - setLinearApproximation(); - } - catch (...) - { - _linear = false; - } -} - //***************************************************************************** // UsgsAstroLsSensorModel updateState //***************************************************************************** @@ -84,90 +431,47 @@ void UsgsAstroLsSensorModel::updateState() // This routine will set some parameters not found in the ISD. // Reference point (image center) - double lineCtr = _data.m_TotalLines / 2.0; - double sampCtr = _data.m_TotalSamples / 2.0; + double lineCtr = m_totalLines / 2.0; + double sampCtr = m_totalSamples / 2.0; csm::ImageCoord ip(lineCtr, sampCtr); - double refHeight = _data.m_RefElevation; - _data.m_ReferencePointXyz = imageToGround(ip, refHeight); + double refHeight = m_refElevation; + m_referencePointXyz = imageToGround(ip, refHeight); // Compute ground sample distance ip.line += 1; ip.samp += 1; csm::EcefCoord delta = imageToGround(ip, refHeight); - double dx = delta.x - _data.m_ReferencePointXyz.x; - double dy = delta.y - _data.m_ReferencePointXyz.y; - double dz = delta.z - _data.m_ReferencePointXyz.z; - _data.m_Gsd = sqrt((dx*dx + dy*dy + dz*dz) / 2.0); + double dx = delta.x - m_referencePointXyz.x; + double dy = delta.y - m_referencePointXyz.y; + double dz = delta.z - m_referencePointXyz.z; + m_gsd = sqrt((dx*dx + dy*dy + dz*dz) / 2.0); // Compute flying height csm::EcefCoord sensorPos = getSensorPosition(0.0); - dx = sensorPos.x - _data.m_ReferencePointXyz.x; - dy = sensorPos.y - _data.m_ReferencePointXyz.y; - dz = sensorPos.z - _data.m_ReferencePointXyz.z; - _data.m_FlyingHeight = sqrt(dx*dx + dy*dy + dz*dz); + dx = sensorPos.x - m_referencePointXyz.x; + dy = sensorPos.y - m_referencePointXyz.y; + dz = sensorPos.z - m_referencePointXyz.z; + m_flyingHeight = sqrt(dx*dx + dy*dy + dz*dz); // Compute half swath - _data.m_HalfSwath = _data.m_Gsd * _data.m_TotalSamples / 2.0; + m_halfSwath = m_gsd * m_totalSamples / 2.0; // Compute half time duration - double fullImageTime = _data.m_IntTimeStartTimes.back() - _data.m_IntTimeStartTimes.front() - + _data.m_IntTimes.back() * (_data.m_TotalLines - _data.m_IntTimeLines.back()); - _data.m_HalfTime = fullImageTime / 2.0; + double fullImageTime = m_intTimeStartTimes.back() - m_intTimeStartTimes.front() + + m_intTimes.back() * (m_totalLines - m_intTimeLines.back()); + m_halfTime = fullImageTime / 2.0; // Parameter covariance, hardcoded accuracy values - int num_params = _data.NUM_PARAMETERS; - int num_params_square = num_params * num_params; - double variance = _data.m_Gsd * _data.m_Gsd; - for (int i = 0; i < num_params_square; i++) + int num_params = NUM_PARAMETERS; + int num_paramsSquare = num_params * num_params; + double variance = m_gsd * m_gsd; + for (int i = 0; i < num_paramsSquare; i++) { - _data.m_Covariance[i] = 0.0; + m_covariance[i] = 0.0; } for (int i = 0; i < num_params; i++) { - _data.m_Covariance[i * num_params + i] = variance; + m_covariance[i * num_params + i] = variance; } - - // Set flag for flipping image along horizontal axis - int index = int((_data.m_NumEphem - 1) / 2.0) * 3; - double xs, ys, zs; // mid sensor position - xs = _data.m_EphemPts[index]; - ys = _data.m_EphemPts[index + 1]; - zs = _data.m_EphemPts[index + 2]; - double xv, yv, zv; // mid sensor velocity - xv = _data.m_EphemRates[index]; - yv = _data.m_EphemRates[index + 1]; - zv = _data.m_EphemRates[index + 2]; - double xm, ym, zm; // mid line position (mid sample) - xm = _data.m_ReferencePointXyz.x; - ym = _data.m_ReferencePointXyz.y; - zm = _data.m_ReferencePointXyz.z; - // mid line position (first sample) - csm::EcefCoord posf = imageToGround(csm::ImageCoord(lineCtr, 0.0), refHeight); - // mid line position (last sample) - csm::EcefCoord posl = imageToGround(csm::ImageCoord(lineCtr, _data.m_TotalSamples - 1), refHeight); - double xd, yd, zd; // unit vector normal to image footprint - xd = posl.x - posf.x; - yd = posl.y - posf.y; - zd = posl.z - posf.z; - double xn, yn, zn; - xn = yv*zd - zv*yd; - yn = zv*xd - xv*zd; - zn = xv*yd - yv*xd; - double nmag = sqrt(xn*xn + yn*yn + zn*zn); - xn /= nmag; - yn /= nmag; - zn /= nmag; - double xo, yo, zo; // unit vector ground-to_satellite - xo = xs - xm; - yo = ys - ym; - zo = zs - zm; - double omag = sqrt(xo*xo + yo*yo + zo*zo); - xo /= omag; - yo /= omag; - zo /= omag; - double triple_product = xn*xo + yn*yo + zn*zo; - _data.m_ImageFlipFlag = 0; - if (triple_product > 0.0) - _data.m_ImageFlipFlag = 1; } @@ -222,9 +526,9 @@ csm::ImageCoord UsgsAstroLsSensorModel::groundToImage( // in some situations. // Start bisection search on the image lines - double sampCtr = _data.m_TotalSamples / 2.0; + double sampCtr = m_totalSamples / 2.0; double firstTime = getImageTime(csm::ImageCoord(0.0, sampCtr)); - double lastTime = getImageTime(csm::ImageCoord(_data.m_TotalLines, sampCtr)); + double lastTime = getImageTime(csm::ImageCoord(m_totalLines, sampCtr)); double firstOffset = computeViewingPixel(firstTime, ground_pt, adj).line - 0.5; double lastOffset = computeViewingPixel(lastTime, ground_pt, adj).line - 0.5; @@ -242,14 +546,14 @@ csm::ImageCoord UsgsAstroLsSensorModel::groundToImage( csm::ImageCoord approxPoint; computeLinearApproximation(ground_pt, approxPoint); csm::ImageCoord approxNextPoint = approxPoint; - if (approxNextPoint.line + 1 < _data.m_TotalLines) { + if (approxNextPoint.line + 1 < m_totalLines) { ++approxNextPoint.line; } else { --approxNextPoint.line; } - csm::EcefCoord approxIntersect = imageToGround(approxPoint, _data.m_RefElevation); - csm::EcefCoord approxNextIntersect = imageToGround(approxNextPoint, _data.m_RefElevation); + csm::EcefCoord approxIntersect = imageToGround(approxPoint, m_refElevation); + csm::EcefCoord approxNextIntersect = imageToGround(approxNextPoint, m_refElevation); double lineDX = approxNextIntersect.x - approxIntersect.x; double lineDY = approxNextIntersect.y - approxIntersect.y; double lineDZ = approxNextIntersect.z - approxIntersect.z; @@ -283,17 +587,17 @@ csm::ImageCoord UsgsAstroLsSensorModel::groundToImage( / (lastOffset - firstOffset); csm::ImageCoord calculatedPixel = computeViewingPixel(computedTime, ground_pt, adj); // The computed viewing line is the detector line, so we need to convert that to image lines - auto referenceTimeIt = std::upper_bound(_data.m_IntTimeStartTimes.begin(), - _data.m_IntTimeStartTimes.end(), + auto referenceTimeIt = std::upper_bound(m_intTimeStartTimes.begin(), + m_intTimeStartTimes.end(), computedTime); - if (referenceTimeIt != _data.m_IntTimeStartTimes.begin()) { + if (referenceTimeIt != m_intTimeStartTimes.begin()) { --referenceTimeIt; } - size_t referenceIndex = std::distance(_data.m_IntTimeStartTimes.begin(), referenceTimeIt); - calculatedPixel.line += _data.m_IntTimeLines[referenceIndex] - 1 - + (computedTime - _data.m_IntTimeStartTimes[referenceIndex]) - / _data.m_IntTimes[referenceIndex]; - csm::EcefCoord calculatedPoint = imageToGround(calculatedPixel, _data.m_RefElevation); + size_t referenceIndex = std::distance(m_intTimeStartTimes.begin(), referenceTimeIt); + calculatedPixel.line += m_intTimeLines[referenceIndex] - 1 + + (computedTime - m_intTimeStartTimes[referenceIndex]) + / m_intTimes[referenceIndex]; + csm::EcefCoord calculatedPoint = imageToGround(calculatedPixel, m_refElevation); double dx = ground_pt.x - calculatedPoint.x; double dy = ground_pt.y - calculatedPoint.y; double dz = ground_pt.z - calculatedPoint.z; @@ -301,7 +605,7 @@ csm::ImageCoord UsgsAstroLsSensorModel::groundToImage( // Check that the pixel is actually in the image if ((calculatedPixel.samp < 0) || - (calculatedPixel.samp > _data.m_TotalSamples)) { + (calculatedPixel.samp > m_totalSamples)) { throw csm::Warning( csm::Warning::IMAGE_COORD_OUT_OF_BOUNDS, "The image coordinate is out of bounds of the image size.", @@ -422,7 +726,7 @@ csm::EcefCoord UsgsAstroLsSensorModel::imageToGround( losToEcf( image_pt.line, image_pt.samp, _no_adjustment, xc, yc, zc, vx, vy, vz, xl, yl, zl); - if (_data.m_AberrFlag == 1) + if (m_aberrFlag == 1) { lightAberrationCorr(vx, vy, vz, xl, yl, zl, dxl, dyl, dzl); xl += dxl; @@ -446,6 +750,7 @@ csm::EcefCoord UsgsAstroLsSensorModel::imageToGround( "Desired precision not achieved.", "UsgsAstroLsSensorModel::imageToGround()")); } + return csm::EcefCoord(x, y, z); } @@ -492,7 +797,7 @@ csm::EcefCoordCovar UsgsAstroLsSensorModel::imageToGround( // Use numerical partials const double DELTA_IMAGE = 1.0; - const double DELTA_GROUND = _data.m_Gsd; + const double DELTA_GROUND = m_gsd; csm::ImageCoord ip(image_pt.line, image_pt.samp); csm::EcefCoord gp = imageToGround( @@ -574,7 +879,7 @@ csm::EcefLocus UsgsAstroLsSensorModel::imageToProximateImagingLocus( csm::WarningList* warnings) const { // Object ray unit direction near given ground location - const double DELTA_GROUND = _data.m_Gsd; + const double DELTA_GROUND = m_gsd; double x = ground_pt.x; double y = ground_pt.y; @@ -639,7 +944,7 @@ csm::EcefLocus UsgsAstroLsSensorModel::imageToRemoteImagingLocus( // Set esposure station elevation to zero double height = 0.0; - double GND_DELTA = _data.m_Gsd; + double GND_DELTA = m_gsd; // Point on object ray at zero elevation csm::EcefCoord gp1 = imageToGround( image_pt, height, desired_precision, achieved_precision, warnings); @@ -677,7 +982,7 @@ csm::EcefLocus UsgsAstroLsSensorModel::imageToRemoteImagingLocus( std::vector<double> UsgsAstroLsSensorModel::computeGroundPartials( const csm::EcefCoord& ground_pt) const { - double GND_DELTA = _data.m_Gsd; + double GND_DELTA = m_gsd; // Partial of line, sample wrt X, Y, Z double x = ground_pt.x; double y = ground_pt.y; @@ -732,8 +1037,8 @@ csm::RasterGM::SensorPartials UsgsAstroLsSensorModel::computeSensorPartials( { // Compute numerical partials ls wrt specific parameter - const double DELTA = _data.m_Gsd; - std::vector<double> adj(UsgsAstroLsStateData::NUM_PARAMETERS, 0.0); + const double DELTA = m_gsd; + std::vector<double> adj(UsgsAstroLsSensorModel::NUM_PARAMETERS, 0.0); adj[index] = DELTA; csm::ImageCoord img1 = groundToImage( @@ -795,8 +1100,8 @@ double UsgsAstroLsSensorModel::getParameterCovariance( int index1, int index2) const { - int index = UsgsAstroLsStateData::NUM_PARAMETERS * index1 + index2; - return _data.m_Covariance[index]; + int index = UsgsAstroLsSensorModel::NUM_PARAMETERS * index1 + index2; + return m_covariance[index]; } //*************************************************************************** @@ -807,8 +1112,8 @@ void UsgsAstroLsSensorModel::setParameterCovariance( int index2, double covariance) { - int index = UsgsAstroLsStateData::NUM_PARAMETERS * index1 + index2; - _data.m_Covariance[index] = covariance; + int index = UsgsAstroLsSensorModel::NUM_PARAMETERS * index1 + index2; + m_covariance[index] = covariance; } //--------------------------------------------------------------------------- @@ -820,7 +1125,7 @@ void UsgsAstroLsSensorModel::setParameterCovariance( //*************************************************************************** std::string UsgsAstroLsSensorModel::getTrajectoryIdentifier() const { - return _data.m_TrajectoryIdentifier; + return m_trajectoryIdentifier; } //*************************************************************************** @@ -828,14 +1133,14 @@ std::string UsgsAstroLsSensorModel::getTrajectoryIdentifier() const //*************************************************************************** std::string UsgsAstroLsSensorModel::getReferenceDateAndTime() const { - if (_data.m_ReferenceDateAndTime == "UNKNOWN") + if (m_referenceDateAndTime == "UNKNOWN") { throw csm::Error( csm::Error::UNSUPPORTED_FUNCTION, "Unsupported function", "UsgsAstroLsSensorModel::getReferenceDateAndTime"); } - return _data.m_ReferenceDateAndTime; + return m_referenceDateAndTime; } //*************************************************************************** @@ -850,21 +1155,21 @@ double UsgsAstroLsSensorModel::getImageTime( // CSM image convention: UL pixel center == (0.5, 0.5) // USGS image convention: UL pixel center == (1.0, 1.0) - double lineCSMFull = line1 + _data.m_OffsetLines; + double lineCSMFull = line1 + m_offsetLines; double lineUSGSFull = lineCSMFull + 0.5; // These calculation assumes that the values in the integration time // vectors are in terms of ISIS' pixels - auto referenceLineIt = std::upper_bound(_data.m_IntTimeLines.begin(), - _data.m_IntTimeLines.end(), + auto referenceLineIt = std::upper_bound(m_intTimeLines.begin(), + m_intTimeLines.end(), lineUSGSFull); - if (referenceLineIt != _data.m_IntTimeLines.begin()) { + if (referenceLineIt != m_intTimeLines.begin()) { --referenceLineIt; } - size_t referenceIndex = std::distance(_data.m_IntTimeLines.begin(), referenceLineIt); + size_t referenceIndex = std::distance(m_intTimeLines.begin(), referenceLineIt); - double time = _data.m_IntTimeStartTimes[referenceIndex] - + _data.m_IntTimes[referenceIndex] * (lineUSGSFull - _data.m_IntTimeLines[referenceIndex]); + double time = m_intTimeStartTimes[referenceIndex] + + m_intTimes[referenceIndex] * (lineUSGSFull - m_intTimeLines[referenceIndex]); return time; @@ -920,7 +1225,7 @@ csm::EcefVector UsgsAstroLsSensorModel::getSensorVelocity(double time) const //*************************************************************************** void UsgsAstroLsSensorModel::setParameterValue(int index, double value) { - _data.m_ParameterVals[index] = value; + m_parameterVals[index] = value; } //*************************************************************************** @@ -928,7 +1233,7 @@ void UsgsAstroLsSensorModel::setParameterValue(int index, double value) //*************************************************************************** double UsgsAstroLsSensorModel::getParameterValue(int index) const { - return _data.m_ParameterVals[index]; + return m_parameterVals[index]; } //*************************************************************************** @@ -936,7 +1241,7 @@ double UsgsAstroLsSensorModel::getParameterValue(int index) const //*************************************************************************** std::string UsgsAstroLsSensorModel::getParameterName(int index) const { - return _data.PARAMETER_NAME[index]; + return PARAMETER_NAME[index]; } std::string UsgsAstroLsSensorModel::getParameterUnits(int index) const @@ -951,7 +1256,7 @@ std::string UsgsAstroLsSensorModel::getParameterUnits(int index) const //*************************************************************************** int UsgsAstroLsSensorModel::getNumParameters() const { - return UsgsAstroLsStateData::NUM_PARAMETERS; + return UsgsAstroLsSensorModel::NUM_PARAMETERS; } @@ -960,7 +1265,7 @@ int UsgsAstroLsSensorModel::getNumParameters() const //*************************************************************************** csm::param::Type UsgsAstroLsSensorModel::getParameterType(int index) const { - return _data.m_ParameterType[index]; + return m_parameterType[index]; } @@ -970,7 +1275,7 @@ csm::param::Type UsgsAstroLsSensorModel::getParameterType(int index) const void UsgsAstroLsSensorModel::setParameterType( int index, csm::param::Type pType) { - _data.m_ParameterType[index] = pType; + m_parameterType[index] = pType; } //--------------------------------------------------------------------------- @@ -990,7 +1295,7 @@ std::string UsgsAstroLsSensorModel::getPedigree() const //*************************************************************************** std::string UsgsAstroLsSensorModel::getImageIdentifier() const { - return _data.m_ImageIdentifier; + return m_imageIdentifier; } //*************************************************************************** @@ -1001,7 +1306,7 @@ void UsgsAstroLsSensorModel::setImageIdentifier( csm::WarningList* warnings) { // Image id should include the suffix without the path name - _data.m_ImageIdentifier = imageId; + m_imageIdentifier = imageId; } //*************************************************************************** @@ -1009,7 +1314,7 @@ void UsgsAstroLsSensorModel::setImageIdentifier( //*************************************************************************** std::string UsgsAstroLsSensorModel::getSensorIdentifier() const { - return _data.m_SensorIdentifier; + return m_sensorIdentifier; } //*************************************************************************** @@ -1017,7 +1322,7 @@ std::string UsgsAstroLsSensorModel::getSensorIdentifier() const //*************************************************************************** std::string UsgsAstroLsSensorModel::getPlatformIdentifier() const { - return _data.m_PlatformIdentifier; + return m_platformIdentifier; } //*************************************************************************** @@ -1025,7 +1330,7 @@ std::string UsgsAstroLsSensorModel::getPlatformIdentifier() const //*************************************************************************** void UsgsAstroLsSensorModel::setReferencePoint(const csm::EcefCoord& ground_pt) { - _data.m_ReferencePointXyz = ground_pt; + m_referencePointXyz = ground_pt; } //*************************************************************************** @@ -1034,7 +1339,7 @@ void UsgsAstroLsSensorModel::setReferencePoint(const csm::EcefCoord& ground_pt) csm::EcefCoord UsgsAstroLsSensorModel::getReferencePoint() const { // Return ground point at image center - return _data.m_ReferencePointXyz; + return m_referencePointXyz; } //*************************************************************************** @@ -1042,7 +1347,7 @@ csm::EcefCoord UsgsAstroLsSensorModel::getReferencePoint() const //*************************************************************************** std::string UsgsAstroLsSensorModel::getModelName() const { - return UsgsAstroLsStateData::SENSOR_MODEL_NAME; + return UsgsAstroLsSensorModel::_SENSOR_MODEL_NAME; } //*************************************************************************** @@ -1058,20 +1363,93 @@ csm::ImageCoord UsgsAstroLsSensorModel::getImageStart() const //*************************************************************************** csm::ImageVector UsgsAstroLsSensorModel::getImageSize() const { - return csm::ImageVector(_data.m_TotalLines, _data.m_TotalSamples); + return csm::ImageVector(m_totalLines, m_totalSamples); } //--------------------------------------------------------------------------- // Sensor Model State //--------------------------------------------------------------------------- - -//*************************************************************************** -// UsgsAstroLsSensorModel::getSensorModelState -//*************************************************************************** -std::string UsgsAstroLsSensorModel::getModelState() const -{ - return _data.toJson(); -} +// +// //*************************************************************************** +// // UsgsAstroLsSensorModel::getSensorModelState +// //*************************************************************************** +// std::string UsgsAstroLsSensorModel::setModelState(std::string stateString) const +// { +// auto j = json::parse(stateString); +// int num_params = NUM_PARAMETERS; +// int num_paramsSq = num_params * num_params; +// +// m_imageIdentifier = j["m_imageIdentifier"]; +// m_sensorType = j["m_sensorType"]; +// m_totalLines = j["m_totalLines"]; +// m_totalSamples = j["m_totalSamples"]; +// m_offsetLines = j["m_offsetLines"]; +// m_offsetSamples = j["m_offsetSamples"]; +// m_platformFlag = j["m_platformFlag"]; +// m_aberrFlag = j["m_aberrFlag"]; +// m_atmRefFlag = j["m_atmrefFlag"]; +// m_intTimeLines = j["m_intTimeLines"].get<std::vector<double>>(); +// m_intTimeStartTimes = j["m_intTimeStartTimes"].get<std::vector<double>>(); +// m_intTimes = j["m_intTimes"].get<std::vector<double>>(); +// m_startingEphemerisTime = j["m_startingEphemerisTime"]; +// m_centerEphemerisTime = j["m_centerEphemerisTime"]; +// m_detectorSampleSumming = j["m_detectorSampleSumming"]; +// m_startingSample = j["m_startingSample"]; +// m_ikCode = j["m_ikCode"]; +// m_focal = j["m_focal"]; +// m_isisZDirection = j["m_isisZDirection"]; +// for (int i = 0; i < 3; i++) { +// m_opticalDistCoef[i] = j["m_opticalDistCoef"][i]; +// m_iTransS[i] = j["m_iTransS"][i]; +// m_iTransL[i] = j["m_iTransL"][i]; +// } +// m_detectorSampleOrigin = j["m_detectorSampleOrigin"]; +// m_detectorLineOrigin = j["m_detectorLineOrigin"]; +// m_detectorLineOffset = j["m_detectorLineOffset"]; +// for (int i = 0; i < 9; i++) { +// m_mountingMatrix[i] = j["m_mountingMatrix"][i]; +// } +// m_semiMajorAxis = j["m_semiMajorAxis"]; +// m_semiMinorAxis = j["m_semiMinorAxis"]; +// m_referenceDateAndTime = j["m_referenceDateAndTime"]; +// m_platformIdentifier = j["m_platformIdentifier"]; +// m_sensorIdentifier = j["m_sensorIdentifier"]; +// m_trajectoryIdentifier = j["m_trajectoryIdentifier"]; +// m_collectionIdentifier = j["m_collectionIdentifier"]; +// m_refElevation = j["m_refElevation"]; +// m_minElevation = j["m_minElevation"]; +// m_maxElevation = j["m_maxElevation"]; +// m_dtEphem = j["m_dtEphem"]; +// m_t0Ephem = j["m_t0Ephem"]; +// m_dtQuat = j["m_dtQuat"]; +// m_t0Quat = j["m_t0Quat"]; +// m_numEphem = j["m_numEphem"]; +// m_numQuaternions = j["m_numQuaternions"]; +// m_referencePointXyz.x = j["m_referencePointXyz"][0]; +// m_referencePointXyz.y = j["m_referencePointXyz"][1]; +// m_referencePointXyz.z = j["m_referencePointXyz"][2]; +// m_gsd = j["m_gsd"]; +// m_flyingHeight = j["m_flyingHeight"]; +// m_halfSwath = j["m_halfSwath"]; +// m_halfTime = j["m_halfTime"]; +// m_imageFlipFlag = j["m_imageFlipFlag"]; +// // Vector = is overloaded so explicit get with type required. +// m_ephemPts = j["m_ephemPts"].get<std::vector<double>>(); +// m_ephemRates = j["m_ephemRates"].get<std::vector<double>>(); +// m_quaternions = j["m_quaternions"].get<std::vector<double>>(); +// m_parameterVals = j["m_parameterVals"].get<std::vector<double>>(); +// m_covariance = j["m_covariance"].get<std::vector<double>>(); +// +// for (int i = 0; i < num_params; i++) { +// for (int k = 0; k < NUM_PARAM_TYPES; k++) { +// if (j["m_parameterType"][i] == PARAM_STRING_ALL[k]) { +// m_parameterType[i] = PARAM_CHAR_ALL[k]; +// break; +// } +// } +// } +// +// } //--------------------------------------------------------------------------- // Monoscopic Mensuration @@ -1082,7 +1460,7 @@ std::string UsgsAstroLsSensorModel::getModelState() const //*************************************************************************** std::pair<double, double> UsgsAstroLsSensorModel::getValidHeightRange() const { - return std::pair<double, double>(_data.m_MinElevation, _data.m_MaxElevation); + return std::pair<double, double>(m_minElevation, m_maxElevation); } //*************************************************************************** @@ -1093,7 +1471,7 @@ UsgsAstroLsSensorModel::getValidImageRange() const { return std::pair<csm::ImageCoord, csm::ImageCoord>( csm::ImageCoord(0.0, 0.0), - csm::ImageCoord(_data.m_TotalLines, _data.m_TotalSamples)); + csm::ImageCoord(m_totalLines, m_totalSamples)); } //*************************************************************************** @@ -1202,7 +1580,7 @@ std::vector<double> UsgsAstroLsSensorModel::getUnmodeledCrossCovariance( //*************************************************************************** std::string UsgsAstroLsSensorModel::getCollectionIdentifier() const { - return _data.m_CollectionIdentifier; + return m_collectionIdentifier; } //*************************************************************************** @@ -1261,25 +1639,17 @@ csm::Version UsgsAstroLsSensorModel::getVersion() const return csm::Version(1, 0, 0); } -//*************************************************************************** -// UsgsAstroLsSensorModel::replaceModelState -//*************************************************************************** -void UsgsAstroLsSensorModel::replaceModelState(const std::string& argState) -{ - set(argState); -} - csm::Ellipsoid UsgsAstroLsSensorModel::getEllipsoid() const { - return csm::Ellipsoid(_data.m_SemiMajorAxis, _data.m_SemiMinorAxis); + return csm::Ellipsoid(m_semiMajorAxis, m_semiMinorAxis); } void UsgsAstroLsSensorModel::setEllipsoid( const csm::Ellipsoid &ellipsoid) { - _data.m_SemiMajorAxis = ellipsoid.getSemiMajorRadius(); - _data.m_SemiMinorAxis = ellipsoid.getSemiMinorRadius(); + m_semiMajorAxis = ellipsoid.getSemiMajorRadius(); + m_semiMinorAxis = ellipsoid.getSemiMinorRadius(); } @@ -1288,7 +1658,7 @@ double UsgsAstroLsSensorModel::getValue( int index, const std::vector<double> &adjustments) const { - return _data.m_ParameterVals[index] + adjustments[index]; + return m_parameterVals[index] + adjustments[index]; } //*************************************************************************** @@ -1317,22 +1687,21 @@ void UsgsAstroLsSensorModel::losToEcf( getAdjSensorPosVel(time, adj, xc, yc, zc, vx, vy, vz); // CSM image image convention: UL pixel center == (0.5, 0.5) // USGS image convention: UL pixel center == (1.0, 1.0) - - double sampleCSMFull = sample + _data.m_OffsetSamples; + double sampleCSMFull = sample + m_offsetSamples; double sampleUSGSFull = sampleCSMFull + 0.5; double fractionalLine = line - floor(line) - 0.5; // Compute distorted image coordinates in mm double isisDetSample = (sampleUSGSFull - 1.0) - * _data.m_DetectorSampleSumming + _data.m_StartingSample; - double m11 = _data.m_ITransL[1]; - double m12 = _data.m_ITransL[2]; - double m21 = _data.m_ITransS[1]; - double m22 = _data.m_ITransS[2]; - double t1 = fractionalLine + _data.m_DetectorLineOffset - - _data.m_DetectorLineOrigin - _data.m_ITransL[0]; - double t2 = isisDetSample - _data.m_DetectorSampleOrigin - _data.m_ITransS[0]; + * m_detectorSampleSumming + m_startingSample; + double m11 = m_iTransL[1]; + double m12 = m_iTransL[2]; + double m21 = m_iTransS[1]; + double m22 = m_iTransS[2]; + double t1 = fractionalLine + m_detectorLineOffset + - m_detectorLineOrigin - m_iTransL[0]; + double t2 = isisDetSample - m_detectorSampleOrigin - m_iTransS[0]; double determinant = m11 * m22 - m12 * m21; double p11 = m11 / determinant; double p12 = -m12 / determinant; @@ -1344,38 +1713,27 @@ void UsgsAstroLsSensorModel::losToEcf( // Remove lens distortion double isisFocalPlaneX = isisNatFocalPlaneX; double isisFocalPlaneY = isisNatFocalPlaneY; - switch (_data.m_IkCode) + if (m_opticalDistCoef[0] != 0.0 || + m_opticalDistCoef[1] != 0.0 || + m_opticalDistCoef[2] != 0.0) { - case -85610: - case -85600: - isisFocalPlaneY = isisNatFocalPlaneY / (1.0 + _data.m_OpticalDistCoef[0] - * isisNatFocalPlaneY * isisNatFocalPlaneY); - break; - - default: - if (_data.m_OpticalDistCoef[0] != 0.0 || - _data.m_OpticalDistCoef[1] != 0.0 || - _data.m_OpticalDistCoef[2] != 0.0) + double rr = isisNatFocalPlaneX * isisNatFocalPlaneX + + isisNatFocalPlaneY * isisNatFocalPlaneY; + if (rr > 1.0E-6) { - double rr = isisNatFocalPlaneX * isisNatFocalPlaneX - + isisNatFocalPlaneY * isisNatFocalPlaneY; - if (rr > 1.0E-6) - { - double dr = _data.m_OpticalDistCoef[0] + (rr * (_data.m_OpticalDistCoef[1] - + rr * _data.m_OpticalDistCoef[2])); - isisFocalPlaneX = isisNatFocalPlaneX * (1.0 - dr); - isisFocalPlaneY = isisNatFocalPlaneY * (1.0 - dr); - } + double dr = m_opticalDistCoef[0] + (rr * (m_opticalDistCoef[1] + + rr * m_opticalDistCoef[2])); + isisFocalPlaneX = isisNatFocalPlaneX * (1.0 - dr); + isisFocalPlaneY = isisNatFocalPlaneY * (1.0 - dr); } - break; } // Define imaging ray in image space double losIsis[3]; - losIsis[0] = -isisFocalPlaneX * _data.m_IsisZDirection; - losIsis[1] = -isisFocalPlaneY * _data.m_IsisZDirection; - losIsis[2] = -_data.m_Focal * (1.0 - getValue(15, adj) / _data.m_HalfSwath); + losIsis[0] = -isisFocalPlaneX * m_isisZDirection; + losIsis[1] = -isisFocalPlaneY * m_isisZDirection; + losIsis[2] = -m_focal * (1.0 - getValue(15, adj) / m_halfSwath); double isisMag = sqrt(losIsis[0] * losIsis[0] + losIsis[1] * losIsis[1] + losIsis[2] * losIsis[2]); @@ -1387,30 +1745,30 @@ void UsgsAstroLsSensorModel::losToEcf( double losApl[3]; losApl[0] = - _data.m_MountingMatrix[0] * losIsis[0] - + _data.m_MountingMatrix[1] * losIsis[1] - + _data.m_MountingMatrix[2] * losIsis[2]; + m_mountingMatrix[0] * losIsis[0] + + m_mountingMatrix[1] * losIsis[1] + + m_mountingMatrix[2] * losIsis[2]; losApl[1] = - _data.m_MountingMatrix[3] * losIsis[0] - + _data.m_MountingMatrix[4] * losIsis[1] - + _data.m_MountingMatrix[5] * losIsis[2]; + m_mountingMatrix[3] * losIsis[0] + + m_mountingMatrix[4] * losIsis[1] + + m_mountingMatrix[5] * losIsis[2]; losApl[2] = - _data.m_MountingMatrix[6] * losIsis[0] - + _data.m_MountingMatrix[7] * losIsis[1] - + _data.m_MountingMatrix[8] * losIsis[2]; + m_mountingMatrix[6] * losIsis[0] + + m_mountingMatrix[7] * losIsis[1] + + m_mountingMatrix[8] * losIsis[2]; // Apply attitude correction - double aTime = time - _data.m_T0Quat; + double aTime = time - m_t0Quat; double euler[3]; - double nTime = aTime / _data.m_HalfTime; + double nTime = aTime / m_halfTime; double nTime2 = nTime * nTime; euler[0] = - (getValue(6, adj) + getValue(9, adj)* nTime + getValue(12, adj)* nTime2) / _data.m_FlyingHeight; + (getValue(6, adj) + getValue(9, adj)* nTime + getValue(12, adj)* nTime2) / m_flyingHeight; euler[1] = - (getValue(7, adj) + getValue(10, adj)* nTime + getValue(13, adj)* nTime2) / _data.m_FlyingHeight; + (getValue(7, adj) + getValue(10, adj)* nTime + getValue(13, adj)* nTime2) / m_flyingHeight; euler[2] = - (getValue(8, adj) + getValue(11, adj)* nTime + getValue(14, adj)* nTime2) / _data.m_HalfSwath; + (getValue(8, adj) + getValue(11, adj)* nTime + getValue(14, adj)* nTime2) / m_halfSwath; double cos_a = cos(euler[0]); double sin_a = sin(euler[0]); double cos_b = cos(euler[1]); @@ -1427,6 +1785,7 @@ void UsgsAstroLsSensorModel::losToEcf( plFromApl[6] = -sin_b; plFromApl[7] = sin_a * cos_b; plFromApl[8] = cos_a * cos_b; + double losPl[3]; losPl[0] = plFromApl[0] * losApl[0] + plFromApl[1] * losApl[1] + plFromApl[2] * losApl[2]; @@ -1438,14 +1797,14 @@ void UsgsAstroLsSensorModel::losToEcf( // Apply rotation matrix from sensor quaternions int nOrder = 8; - if (_data.m_PlatformFlag == 0) + if (m_platformFlag == 0) nOrder = 4; int nOrderQuat = nOrder; - if (_data.m_NumQuaternions < 6 && nOrder == 8) + if (m_numQuaternions < 6 && nOrder == 8) nOrderQuat = 4; double q[4]; lagrangeInterp( - _data.m_NumQuaternions, &_data.m_Quaternions[0], _data.m_T0Quat, _data.m_DtQuat, + m_numQuaternions, &m_quaternions[0], m_t0Quat, m_dtQuat, time, 4, nOrderQuat, q); double norm = sqrt(q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]); q[0] /= norm; @@ -1462,6 +1821,8 @@ void UsgsAstroLsSensorModel::losToEcf( ecfFromPl[6] = 2 * (q[0] * q[2] - q[1] * q[3]); ecfFromPl[7] = 2 * (q[1] * q[2] + q[0] * q[3]); ecfFromPl[8] = -q[0] * q[0] - q[1] * q[1] + q[2] * q[2] + q[3] * q[3]; + + xl = ecfFromPl[0] * losPl[0] + ecfFromPl[1] * losPl[1] + ecfFromPl[2] * losPl[2]; yl = ecfFromPl[3] * losPl[0] + ecfFromPl[4] * losPl[1] @@ -1667,7 +2028,7 @@ void UsgsAstroLsSensorModel::computeElevation( // Compute elevation given xyz // Requires semi-major-axis and eccentricity-square const int MKTR = 10; - double ecc_sqr = 1.0 - _data.m_SemiMinorAxis * _data.m_SemiMinorAxis / _data.m_SemiMajorAxis / _data.m_SemiMajorAxis; + double ecc_sqr = 1.0 - m_semiMinorAxis * m_semiMinorAxis / m_semiMajorAxis / m_semiMajorAxis; double ep2 = 1.0 - ecc_sqr; double d2 = x * x + y * y; double d = sqrt(d2); @@ -1684,7 +2045,7 @@ void UsgsAstroLsSensorModel::computeElevation( { hPrev = h; tt = tanPhi * tanPhi; - r = _data.m_SemiMajorAxis / sqrt(1.0 + ep2 * tt); + r = m_semiMajorAxis / sqrt(1.0 + ep2 * tt); zz = z + r * ecc_sqr * tanPhi; n = r * sqrt(1.0 + tt); h = sqrt(d2 + zz * zz) - n; @@ -1702,7 +2063,7 @@ void UsgsAstroLsSensorModel::computeElevation( { hPrev = h; cc = cotPhi * cotPhi; - r = _data.m_SemiMajorAxis / sqrt(ep2 + cc); + r = m_semiMajorAxis / sqrt(ep2 + cc); dd = d - r * ecc_sqr * cotPhi; nn = r * sqrt(1.0 + cc) * ep2; h = sqrt(dd * dd + z * z) - nn; @@ -1739,8 +2100,8 @@ void UsgsAstroLsSensorModel::losEllipsoidIntersect( const int MKTR = 10; double ap, bp, k; - ap = _data.m_SemiMajorAxis + height; - bp = _data.m_SemiMinorAxis + height; + ap = m_semiMajorAxis + height; + bp = m_semiMinorAxis + height; k = ap * ap / (bp * bp); // Solve quadratic equation for scale factor @@ -1889,7 +2250,7 @@ void UsgsAstroLsSensorModel::imageToPlane( losToEcf(line, sample, adj, xc, yc, zc, vx, vy, vz, xl, yl, zl); - if (_data.m_AberrFlag == 1) + if (m_aberrFlag == 1) { lightAberrationCorr(vx, vy, vz, xl, yl, zl, dxl, dyl, dzl); xl += dxl; @@ -1915,13 +2276,13 @@ void UsgsAstroLsSensorModel::getAdjSensorPosVel( { // Sensor position and velocity (4th or 8th order Lagrange). int nOrder = 8; - if (_data.m_PlatformFlag == 0) + if (m_platformFlag == 0) nOrder = 4; double sensPosNom[3]; - lagrangeInterp(_data.m_NumEphem, &_data.m_EphemPts[0], _data.m_T0Ephem, _data.m_DtEphem, + lagrangeInterp(m_numEphem, &m_ephemPts[0], m_t0Ephem, m_dtEphem, time, 3, nOrder, sensPosNom); double sensVelNom[3]; - lagrangeInterp(_data.m_NumEphem, &_data.m_EphemRates[0], _data.m_T0Ephem, _data.m_DtEphem, + lagrangeInterp(m_numEphem, &m_ephemRates[0], m_t0Ephem, m_dtEphem, time, 3, nOrder, sensVelNom); // Compute rotation matrix from ICR to ECF @@ -1960,13 +2321,12 @@ void UsgsAstroLsSensorModel::getAdjSensorPosVel( ecfFromIcr[6] = inTrackUnitVec[2]; ecfFromIcr[7] = crossTrackUnitVec[2]; ecfFromIcr[8] = radialUnitVec[2]; - // Apply position and velocity corrections - double aTime = time - _data.m_T0Ephem; - double dvi = getValue(3, adj) / _data.m_HalfTime; - double dvc = getValue(4, adj) / _data.m_HalfTime; - double dvr = getValue(5, adj) / _data.m_HalfTime; + double aTime = time - m_t0Ephem; + double dvi = getValue(3, adj) / m_halfTime; + double dvc = getValue(4, adj) / m_halfTime; + double dvr = getValue(5, adj) / m_halfTime; vx = sensVelNom[0] + ecfFromIcr[0] * dvi + ecfFromIcr[1] * dvc + ecfFromIcr[2] * dvr; vy = sensVelNom[1] @@ -2004,14 +2364,14 @@ csm::ImageCoord UsgsAstroLsSensorModel::computeViewingPixel( // Rotate the look vector into the camera reference frame int nOrder = 8; - if (_data.m_PlatformFlag == 0) + if (m_platformFlag == 0) nOrder = 4; int nOrderQuat = nOrder; - if (_data.m_NumQuaternions < 6 && nOrder == 8) + if (m_numQuaternions < 6 && nOrder == 8) nOrderQuat = 4; double q[4]; lagrangeInterp( - _data.m_NumQuaternions, &_data.m_Quaternions[0], _data.m_T0Quat, _data.m_DtQuat, + m_numQuaternions, &m_quaternions[0], m_t0Quat, m_dtQuat, time, 4, nOrderQuat, q); double norm = sqrt(q[0] * q[0] + q[1] * q[1] + q[2] * q[2] + q[3] * q[3]); // Divide by the negative norm for 0 through 2 to invert the quaternion @@ -2040,16 +2400,16 @@ csm::ImageCoord UsgsAstroLsSensorModel::computeViewingPixel( + bodyToCamera[8] * bodyLookZ; // Invert the attitude correction - double aTime = time - _data.m_T0Quat; + double aTime = time - m_t0Quat; double euler[3]; - double nTime = aTime / _data.m_HalfTime; + double nTime = aTime / m_halfTime; double nTime2 = nTime * nTime; euler[0] = - (getValue(6, adj) + getValue(9, adj)* nTime + getValue(12, adj)* nTime2) / _data.m_FlyingHeight; + (getValue(6, adj) + getValue(9, adj)* nTime + getValue(12, adj)* nTime2) / m_flyingHeight; euler[1] = - (getValue(7, adj) + getValue(10, adj)* nTime + getValue(13, adj)* nTime2) / _data.m_FlyingHeight; + (getValue(7, adj) + getValue(10, adj)* nTime + getValue(13, adj)* nTime2) / m_flyingHeight; euler[2] = - (getValue(8, adj) + getValue(11, adj)* nTime + getValue(14, adj)* nTime2) / _data.m_HalfSwath; + (getValue(8, adj) + getValue(11, adj)* nTime + getValue(14, adj)* nTime2) / m_halfSwath; double cos_a = cos(euler[0]); double sin_a = sin(euler[0]); double cos_b = cos(euler[1]); @@ -2077,18 +2437,18 @@ csm::ImageCoord UsgsAstroLsSensorModel::computeViewingPixel( + attCorr[8] * cameraLookZ; // Invert the boresight correction - double correctedLookX = _data.m_MountingMatrix[0] * adjustedLookX - + _data.m_MountingMatrix[3] * adjustedLookY - + _data.m_MountingMatrix[6] * adjustedLookZ; - double correctedLookY = _data.m_MountingMatrix[1] * adjustedLookX - + _data.m_MountingMatrix[4] * adjustedLookY - + _data.m_MountingMatrix[7] * adjustedLookZ; - double correctedLookZ = _data.m_MountingMatrix[2] * adjustedLookX - + _data.m_MountingMatrix[5] * adjustedLookY - + _data.m_MountingMatrix[8] * adjustedLookZ; + double correctedLookX = m_mountingMatrix[0] * adjustedLookX + + m_mountingMatrix[3] * adjustedLookY + + m_mountingMatrix[6] * adjustedLookZ; + double correctedLookY = m_mountingMatrix[1] * adjustedLookX + + m_mountingMatrix[4] * adjustedLookY + + m_mountingMatrix[7] * adjustedLookZ; + double correctedLookZ = m_mountingMatrix[2] * adjustedLookX + + m_mountingMatrix[5] * adjustedLookY + + m_mountingMatrix[8] * adjustedLookZ; // Convert to focal plane coordinate - double lookScale = _data.m_Focal / correctedLookZ; + double lookScale = m_focal / correctedLookZ; double focalX = correctedLookX * lookScale; double focalY = correctedLookY * lookScale; @@ -2098,18 +2458,18 @@ csm::ImageCoord UsgsAstroLsSensorModel::computeViewingPixel( // sometimes only well behaved close to the CCD. // Convert to detector line and sample - double detectorLine = _data.m_ITransL[0] - + _data.m_ITransL[1] * focalX - + _data.m_ITransL[2] * focalY; - double detectorSample = _data.m_ITransS[0] - + _data.m_ITransS[1] * focalX - + _data.m_ITransS[2] * focalY; + double detectorLine = m_iTransL[0] + + m_iTransL[1] * focalX + + m_iTransL[2] * focalY; + double detectorSample = m_iTransS[0] + + m_iTransS[1] * focalX + + m_iTransS[2] * focalY; // Convert to image sample line - double line = detectorLine + _data.m_DetectorLineOrigin - _data.m_DetectorLineOffset - - _data.m_OffsetLines + 0.5; - double sample = (detectorSample + _data.m_DetectorSampleOrigin - _data.m_StartingSample) - / _data.m_DetectorSampleSumming - _data.m_OffsetSamples + 0.5; + double line = detectorLine + m_detectorLineOrigin - m_detectorLineOffset + - m_offsetLines + 0.5; + double sample = (detectorSample + m_detectorSampleOrigin - m_startingSample) + / m_detectorSampleSumming - m_offsetSamples + 0.5; return csm::ImageCoord(line, sample); } @@ -2128,8 +2488,8 @@ void UsgsAstroLsSensorModel::computeLinearApproximation( // Since this is valid only over image, // don't let result go beyond the image border. - double numRows = _data.m_TotalLines; - double numCols = _data.m_TotalSamples; + double numRows = m_totalLines; + double numCols = m_totalSamples; if (ip.line < 0.0) ip.line = 0.0; if (ip.line > numRows) ip.line = numRows; @@ -2138,8 +2498,8 @@ void UsgsAstroLsSensorModel::computeLinearApproximation( } else { - ip.line = _data.m_TotalLines / 2.0; - ip.samp = _data.m_TotalSamples / 2.0; + ip.line = m_totalLines / 2.0; + ip.samp = m_totalSamples / 2.0; } } @@ -2164,8 +2524,8 @@ void UsgsAstroLsSensorModel::setLinearApproximation() } - double numRows = _data.m_TotalLines; - double numCols = _data.m_TotalSamples; + double numRows = m_totalLines; + double numCols = m_totalSamples; csm::ImageCoord imagePt; csm::EcefCoord gp[8]; @@ -2279,3 +2639,136 @@ double UsgsAstroLsSensorModel::determinant3x3(double mat[9]) const mat[1] * (mat[3] * mat[8] - mat[6] * mat[5]) + mat[2] * (mat[3] * mat[7] - mat[6] * mat[4]); } + + + + +std::string UsgsAstroLsSensorModel::constructStateFromIsd(const std::string imageSupportData, csm::WarningList *warnings) const +{ + // Instantiate UsgsAstroLineScanner sensor model + json isd = json::parse(imageSupportData); + json state; + + int num_params = NUM_PARAMETERS; + + state["m_imageIdentifier"] = "UNKNOWN"; + state["m_sensorType"] = "LINE_SCAN"; + state["m_totalLines"] = isd.at("image_lines"); + state["m_totalSamples"] = isd.at("image_samples"); + state["m_offsetLines"] = 0.0; + state["m_offsetSamples"] = 0.0; + state["m_platformFlag"] = 1; + state["m_aberrFlag"] = 0; + state["m_atmRefFlag"] = 0; + state["m_centerEphemerisTime"] = isd.at("center_ephemeris_time"); + state["m_startingEphemerisTime"] = isd.at("starting_ephemeris_time"); + + for (auto& scanRate : isd.at("line_scan_rate")) { + state["m_intTimeLines"].push_back(scanRate[0]); + state["m_intTimeStartTimes"].push_back(scanRate[1]); + state["m_intTimes"].push_back(scanRate[2]); + } + + state["m_detectorSampleSumming"] = isd.at("detector_sample_summing"); + state["m_startingSample"] = isd.at("detector_line_summing"); + state["m_ikCode"] = 0; + state["m_focal"] = isd.at("focal_length_model").at("focal_length"); + state["m_isisZDirection"] = 1; + state["m_opticalDistCoef"] = isd.at("optical_distortion").at("radial").at("coefficients"); + state["m_iTransS"] = isd.at("focal2pixel_samples"); + state["m_iTransL"] = isd.at("focal2pixel_lines"); + + state["m_detectorSampleOrigin"] = isd.at("detector_center").at("sample"); + state["m_detectorLineOrigin"] = isd.at("detector_center").at("line"); + state["m_detectorLineOffset"] = 0; + + double cos_a = cos(0); + double sin_a = sin(0); + double cos_b = cos(0); + double sin_b = sin(0); + double cos_c = cos(0); + double sin_c = sin(0); + + state["m_mountingMatrix"] = json::array(); + state["m_mountingMatrix"][0] = cos_b * cos_c; + state["m_mountingMatrix"][1] = -cos_a * sin_c + sin_a * sin_b * cos_c; + state["m_mountingMatrix"][2] = sin_a * sin_c + cos_a * sin_b * cos_c; + state["m_mountingMatrix"][3] = cos_b * sin_c; + state["m_mountingMatrix"][4] = cos_a * cos_c + sin_a * sin_b * sin_c; + state["m_mountingMatrix"][5] = -sin_a * cos_c + cos_a * sin_b * sin_c; + state["m_mountingMatrix"][6] = -sin_b; + state["m_mountingMatrix"][7] = sin_a * cos_b; + state["m_mountingMatrix"][8] = cos_a * cos_b; + + state["m_dtEphem"] = isd.at("dt_ephemeris"); + state["m_t0Ephem"] = isd.at("t0_ephemeris"); + state["m_dtQuat"] = isd.at("dt_quaternion"); + state["m_t0Quat"] = isd.at("t0_quaternion"); + + state["m_numEphem"] = isd.at("sensor_position").at("positions").size(); + state["m_numQuaternions"] = isd.at("sensor_orientation").at("quaternions").size(); + + for (auto& location : isd.at("sensor_position").at("positions")) { + state["m_ephemPts"].push_back(location[0]); + state["m_ephemPts"].push_back(location[1]); + state["m_ephemPts"].push_back(location[2]); + } + + for (auto& velocity : isd.at("sensor_position").at("velocities")) { + state["m_ephemRates"].push_back(velocity[0]); + state["m_ephemRates"].push_back(velocity[1]); + state["m_ephemRates"].push_back(velocity[2]); + } + + for (auto& quaternion : isd.at("sensor_orientation").at("quaternions")) { + state["m_quaternions"].push_back(quaternion[0]); + state["m_quaternions"].push_back(quaternion[1]); + state["m_quaternions"].push_back(quaternion[2]); + state["m_quaternions"].push_back(quaternion[3]); + } + + + state["m_parameterVals"] = std::vector<double>(NUM_PARAMETERS, 0.0); + state["m_parameterVals"][15] = state["m_focal"].get<double>(); + + // Set the ellipsoid + state["m_semiMajorAxis"] = isd.at("radii").at("semimajor"); + state["m_semiMinorAxis"] = isd.at("radii").at("semiminor"); + + // Now finish setting the state data from the ISD read in + + // set identifiers + state["m_referenceDateAndTime"] = "UNKNOWN"; + state["m_platformIdentifier"] = isd.at("name_platform"); + state["m_sensorIdentifier"] = isd.at("name_sensor"); + state["m_trajectoryIdentifier"] = "UNKNOWN"; + state["m_collectionIdentifier"] = "UNKNOWN"; + + // Ground elevations + state["m_refElevation"] = 0.0; + state["m_minElevation"] = isd.at("reference_height").at("minheight"); + state["m_maxElevation"] = isd.at("reference_height").at("maxheight"); + + // Zero ateter values + for (int i = 0; i < NUM_PARAMETERS; i++) { + state["m_ateterType"][i] = csm::param::REAL; + } + + // Default to identity covariance + state["m_covariance"] = + std::vector<double>(NUM_PARAMETERS * NUM_PARAMETERS, 0.0); + for (int i = 0; i < NUM_PARAMETERS; i++) { + state["m_covariance"][i * NUM_PARAMETERS + i] = 1.0; + } + + // Zero computed state values + state["m_referencePointXyz"] = std::vector<double>(3, 0.0); + state["m_gsd"] = 1.0; + state["m_flyingHeight"] = 1000.0; + state["m_halfSwath"] = 1000.0; + state["m_halfTime"] = 10.0; + state["m_imageFlipFlag"] = 0; + // The state data will still be updated when a sensor model is created since + // some state data is notin the ISD and requires a SM to compute them. + return state.dump(); +} diff --git a/src/UsgsAstroLsStateData.cpp b/src/UsgsAstroLsStateData.cpp deleted file mode 100644 index 9b1fba8..0000000 --- a/src/UsgsAstroLsStateData.cpp +++ /dev/null @@ -1,538 +0,0 @@ -//---------------------------------------------------------------------------- -// -// UNCLASSIFIED -// -// Copyright © 1989-2017 BAE Systems Information and Electronic Systems Integration Inc. -// ALL RIGHTS RESERVED -// Use of this software product is governed by the terms of a license -// agreement. The license agreement is found in the installation directory. -// -// For support, please visit http://www.baesystems.com/gxp -// -// FILENAME: UsgsAstroLsStateData.h -// -// DESCRIPTION: -// -// Holds state data used to build the Astro Line Scanner sensor model. -// -// LIMITATIONS: None -// -// SOFTWARE HISTORY: -// -// Date Author Comment -// ----------- ---------- ------- -// 13-OCT-2017 BAE Systems Initial Release -// -// -//############################################################################# - -#define USGSASTROLINESCANNER_LIBRARY - - -#include <UsgsAstroLsStateData.h> -#include <UsgsAstroLsPlugin.h> -#include <sstream> -#include <Error.h> -#include <json.hpp> -using json = nlohmann::json; - -const std::string UsgsAstroLsStateData::SENSOR_MODEL_NAME - = "USGS_ASTRO_LINE_SCANNER_SENSOR_MODEL"; -const int UsgsAstroLsStateData::NUM_PARAMETERS = 16; -const std::string UsgsAstroLsStateData::PARAMETER_NAME[] = -{ - "IT Pos. Bias ", // 0 - "CT Pos. Bias ", // 1 - "Rad Pos. Bias ", // 2 - "IT Vel. Bias ", // 3 - "CT Vel. Bias ", // 4 - "Rad Vel. Bias ", // 5 - "Omega Bias ", // 6 - "Phi Bias ", // 7 - "Kappa Bias ", // 8 - "Omega Rate ", // 9 - "Phi Rate ", // 10 - "Kappa Rate ", // 11 - "Omega Accl ", // 12 - "Phi Accl ", // 13 - "Kappa Accl ", // 14 - "Focal Bias " // 15 -}; - - -const std::string UsgsAstroLsStateData::STATE_KEYWORD[] = -{ - "STA_SENSOR_MODEL_NAME", - "STA_IMAGE_IDENTIFIER", - "STA_SENSOR_TYPE", - "STA_TOTAL_LINES", - "STA_TOTAL_SAMPLES", - "STA_OFFSET_LINES", - "STA_OFFSET_SAMPLES", - "STA_PLATFORM_FLAG", - "STA_ABERR_FLAG", - "STA_ATMREF_FLAG", - "STA_INT_TIME_LINES", - "STA_INT_TIME_START_TIMES", - "STA_INT_TIMES", - "STA_STARTING_EPHEMERIS_TIME", - "STA_CENTER_EPHEMERIS_TIME", - "STA_DETECTOR_SAMPLE_SUMMING", - "STA_STARTING_SAMPLE", - "STA_IK_CODE", - "STA_FOCAL", - "STA_ISIS_Z_DIRECTION", - "STA_OPTICAL_DIST_COEF", - "STA_I_TRANS_S", - "STA_I_TRANS_L", - "STA_DETECTOR_SAMPLE_ORIGIN", - "STA_DETECTOR_LINE_ORIGIN", - "STA_DETECTOR_LINE_OFFSET", - "STA_MOUNTING_MATRIX", - "STA_SEMI_MAJOR_AXIS", - "STA_SEMI_MINOR_AXIS", - "STA_REFERENCE_DATE_AND_TIME", - "STA_PLATFORM_IDENTIFIER", - "STA_SENSOR_IDENTIFIER", - "STA_TRAJECTORY_IDENTIFIER", - "STA_COLLECTION_IDENTIFIER", - "STA_REF_ELEVATION", - "STA_MIN_ELEVATION", - "STA_MAX_ELEVATION", - "STA_DT_EPHEM", - "STA_T0_EPHEM", - "STA_DT_QUAT", - "STA_T0_QUAT", - "STA_NUM_EPHEM", - "STA_NUM_QUATERNIONS", - "STA_EPHEM_PTS", - "STA_EPHEM_RATES", - "STA_QUATERNIONS", - "STA_PARAMETER_VALS", - "STA_PARAMETER_TYPE", - "STA_REFERENCE_POINT_XYZ", - "STA_GSD", - "STA_FLYING_HEIGHT", - "STA_HALF_SWATH", - "STA_HALF_TIME", - "STA_COVARIANCE", - "STA_IMAGE_FLIP_FLAG" -}; - -const int UsgsAstroLsStateData::NUM_PARAM_TYPES = 4; -const std::string UsgsAstroLsStateData::PARAM_STRING_ALL[] = -{ - "NONE", - "FICTITIOUS", - "REAL", - "FIXED" -}; -const csm::param::Type - UsgsAstroLsStateData::PARAM_CHAR_ALL[] = -{ - csm::param::NONE, - csm::param::FICTITIOUS, - csm::param::REAL, - csm::param::FIXED -}; - - -std::string UsgsAstroLsStateData::toJson() const { - json state = { - {STATE_KEYWORD[STA_SENSOR_MODEL_NAME], SENSOR_MODEL_NAME}, - {STATE_KEYWORD[STA_IMAGE_IDENTIFIER], m_ImageIdentifier}, - {STATE_KEYWORD[STA_SENSOR_TYPE], m_SensorType}, - {STATE_KEYWORD[STA_TOTAL_LINES], m_TotalLines}, - {STATE_KEYWORD[STA_TOTAL_SAMPLES], m_TotalSamples}, - {STATE_KEYWORD[STA_OFFSET_LINES], m_OffsetLines}, - {STATE_KEYWORD[STA_OFFSET_SAMPLES], m_OffsetSamples}, - {STATE_KEYWORD[STA_PLATFORM_FLAG], m_PlatformFlag}, - {STATE_KEYWORD[STA_ABERR_FLAG], m_AberrFlag}, - {STATE_KEYWORD[STA_ATMREF_FLAG], m_AtmRefFlag}, - {STATE_KEYWORD[STA_INT_TIME_LINES], m_IntTimeLines}, - {STATE_KEYWORD[STA_INT_TIME_START_TIMES], m_IntTimeStartTimes}, - {STATE_KEYWORD[STA_INT_TIMES], m_IntTimes}, - {STATE_KEYWORD[STA_STARTING_EPHEMERIS_TIME], m_StartingEphemerisTime}, - {STATE_KEYWORD[STA_CENTER_EPHEMERIS_TIME], m_CenterEphemerisTime}, - {STATE_KEYWORD[STA_DETECTOR_SAMPLE_SUMMING], m_DetectorSampleSumming}, - {STATE_KEYWORD[STA_STARTING_SAMPLE], m_StartingSample}, - {STATE_KEYWORD[STA_IK_CODE], m_IkCode}, - {STATE_KEYWORD[STA_FOCAL], m_Focal}, - {STATE_KEYWORD[STA_ISIS_Z_DIRECTION], m_IsisZDirection}, - {STATE_KEYWORD[STA_IMAGE_FLIP_FLAG] , m_ImageFlipFlag}, - {STATE_KEYWORD[STA_REFERENCE_POINT_XYZ], - {m_ReferencePointXyz.x,m_ReferencePointXyz.y, m_ReferencePointXyz.z}}, - {STATE_KEYWORD[STA_GSD], m_Gsd}, - {STATE_KEYWORD[STA_FLYING_HEIGHT], m_FlyingHeight}, - {STATE_KEYWORD[STA_HALF_SWATH], m_HalfSwath}, - {STATE_KEYWORD[STA_HALF_TIME], m_HalfTime}, - {STATE_KEYWORD[STA_SEMI_MAJOR_AXIS], m_SemiMajorAxis}, - {STATE_KEYWORD[STA_SEMI_MINOR_AXIS], m_SemiMinorAxis}, - {STATE_KEYWORD[STA_REFERENCE_DATE_AND_TIME], m_ReferenceDateAndTime}, - {STATE_KEYWORD[STA_PLATFORM_IDENTIFIER], m_PlatformIdentifier}, - {STATE_KEYWORD[STA_SENSOR_IDENTIFIER], m_SensorIdentifier}, - {STATE_KEYWORD[STA_TRAJECTORY_IDENTIFIER], m_TrajectoryIdentifier}, - {STATE_KEYWORD[STA_COLLECTION_IDENTIFIER], m_CollectionIdentifier}, - {STATE_KEYWORD[STA_REF_ELEVATION], m_RefElevation}, - {STATE_KEYWORD[STA_MIN_ELEVATION], m_MinElevation}, - {STATE_KEYWORD[STA_MAX_ELEVATION], m_MaxElevation}, - {STATE_KEYWORD[STA_DT_EPHEM], m_DtEphem}, - {STATE_KEYWORD[STA_T0_EPHEM], m_T0Ephem}, - {STATE_KEYWORD[STA_DT_QUAT], m_DtQuat}, - {STATE_KEYWORD[STA_T0_QUAT], m_T0Quat}, - {STATE_KEYWORD[STA_NUM_EPHEM], m_NumEphem}, - {STATE_KEYWORD[STA_NUM_QUATERNIONS], m_NumQuaternions}, - {STATE_KEYWORD[STA_DETECTOR_SAMPLE_ORIGIN], m_DetectorSampleOrigin}, - {STATE_KEYWORD[STA_DETECTOR_LINE_ORIGIN], m_DetectorLineOrigin}, - {STATE_KEYWORD[STA_DETECTOR_LINE_OFFSET], m_DetectorLineOffset}, - {STATE_KEYWORD[STA_OPTICAL_DIST_COEF], - {m_OpticalDistCoef[0], m_OpticalDistCoef[1], m_OpticalDistCoef[2]}}, - {STATE_KEYWORD[STA_COVARIANCE], m_Covariance}, - {STATE_KEYWORD[STA_I_TRANS_S], {m_ITransS[0], m_ITransS[1], m_ITransS[2]}}, - {STATE_KEYWORD[STA_I_TRANS_L],{m_ITransL[0], m_ITransL[1], m_ITransL[2]}}, - {STATE_KEYWORD[STA_MOUNTING_MATRIX], - {m_MountingMatrix[0], m_MountingMatrix[1], m_MountingMatrix[2], - m_MountingMatrix[3], m_MountingMatrix[4], m_MountingMatrix[5], - m_MountingMatrix[6], m_MountingMatrix[7], m_MountingMatrix[8]}}, - {STATE_KEYWORD[STA_EPHEM_PTS], m_EphemPts}, - {STATE_KEYWORD[STA_EPHEM_RATES], m_EphemRates}, - {STATE_KEYWORD[STA_QUATERNIONS], m_Quaternions}, - {STATE_KEYWORD[STA_PARAMETER_VALS], m_ParameterVals}, - {STATE_KEYWORD[STA_PARAMETER_TYPE], m_ParameterType} - }; - return state.dump(); -} - -std::string UsgsAstroLsStateData::toString() const -{ - std::stringstream state_stream(std::ios_base::out); - state_stream.unsetf (std::ios::floatfield); - state_stream.precision(14); - state_stream << STATE_KEYWORD[STA_SENSOR_MODEL_NAME] << " " << SENSOR_MODEL_NAME << "\n"; // 0 - state_stream << STATE_KEYWORD[STA_IMAGE_IDENTIFIER] << " " << m_ImageIdentifier << "\n"; // 1 - state_stream << STATE_KEYWORD[STA_SENSOR_TYPE] << " " << m_SensorType << "\n"; // 2 - state_stream << STATE_KEYWORD[STA_TOTAL_LINES] << " " << m_TotalLines << "\n"; // 3 - state_stream << STATE_KEYWORD[STA_TOTAL_SAMPLES] << " " << m_TotalSamples << "\n"; // 4 - state_stream << STATE_KEYWORD[STA_OFFSET_LINES] << " " << m_OffsetLines << "\n"; // 7 - state_stream << STATE_KEYWORD[STA_OFFSET_SAMPLES] << " " << m_OffsetSamples << "\n"; // 8 - state_stream << STATE_KEYWORD[STA_PLATFORM_FLAG] << " " << m_PlatformFlag << "\n"; // 9 - state_stream << STATE_KEYWORD[STA_ABERR_FLAG] << " " << m_AberrFlag << "\n"; // 10 - state_stream << STATE_KEYWORD[STA_ATMREF_FLAG]<< " " << m_AtmRefFlag << "\n"; // 11 - state_stream << STATE_KEYWORD[STA_INT_TIME_LINES] << " " ; - for (size_t i = 0; i < m_IntTimeLines.size(); i++) - { - state_stream << m_IntTimeLines[i] << " "; - } - state_stream << "\n"; - state_stream << STATE_KEYWORD[STA_INT_TIME_START_TIMES] << " " ; - for (size_t i = 0; i < m_IntTimeStartTimes.size(); i++) - { - state_stream << m_IntTimeStartTimes[i] << " "; - } - state_stream << "\n"; - state_stream << STATE_KEYWORD[STA_INT_TIMES] << " " ; - for (size_t i = 0; i < m_IntTimes.size(); i++) - { - state_stream << m_IntTimes[i] << " "; - } - state_stream << "\n"; - state_stream << STATE_KEYWORD[STA_STARTING_EPHEMERIS_TIME] << " " - << m_StartingEphemerisTime << "\n"; // 13 - state_stream << STATE_KEYWORD[STA_CENTER_EPHEMERIS_TIME] << " " - << m_CenterEphemerisTime << "\n"; // 14 - state_stream << STATE_KEYWORD[STA_DETECTOR_SAMPLE_SUMMING] << " " - << m_DetectorSampleSumming << "\n"; // 15 - state_stream << STATE_KEYWORD[STA_STARTING_SAMPLE] << " " << m_StartingSample << "\n"; // 16 - state_stream << STATE_KEYWORD[STA_IK_CODE] << " " << m_IkCode << "\n"; // 17 - state_stream << STATE_KEYWORD[STA_FOCAL] << " " << m_Focal << "\n"; // 18 - state_stream << STATE_KEYWORD[STA_ISIS_Z_DIRECTION] << " " << m_IsisZDirection << "\n"; // 19 - state_stream << STATE_KEYWORD[STA_OPTICAL_DIST_COEF] << " "; - for (int i = 0; i < 3; i++) { - state_stream << m_OpticalDistCoef[i] << " " ; // 20 - } - state_stream << "\n"; - state_stream << STATE_KEYWORD[STA_I_TRANS_S] << " "; - for (int i = 0; i < 3; i++) { - state_stream << m_ITransS[i] << " " ; // 21 - } - state_stream << "\n"; - state_stream << STATE_KEYWORD[STA_I_TRANS_L]<< " "; - for (int i = 0; i < 3; i++) { - state_stream << m_ITransL[i] << " "; // 22 - } - state_stream << "\n"; - state_stream << STATE_KEYWORD[STA_DETECTOR_SAMPLE_ORIGIN] << " " - << m_DetectorSampleOrigin << "\n"; // 23 - state_stream << STATE_KEYWORD[STA_DETECTOR_LINE_ORIGIN] << " " - << m_DetectorLineOrigin << "\n"; // 24 - state_stream << STATE_KEYWORD[STA_DETECTOR_LINE_OFFSET] << " " - << m_DetectorLineOffset << "\n"; // 25 - state_stream << STATE_KEYWORD[STA_MOUNTING_MATRIX] << " "; - for (int i =0; i < 9; i++) { - state_stream << m_MountingMatrix[i] << " "; // 26 - } - state_stream << "\n"; - state_stream << STATE_KEYWORD[STA_SEMI_MAJOR_AXIS] << " " << m_SemiMajorAxis << "\n"; // 27 - state_stream << STATE_KEYWORD[STA_SEMI_MINOR_AXIS] << " " << m_SemiMinorAxis << "\n"; // 28 - state_stream << STATE_KEYWORD[STA_REFERENCE_DATE_AND_TIME] << " " - << m_ReferenceDateAndTime << "\n"; // 30 - state_stream << STATE_KEYWORD[STA_PLATFORM_IDENTIFIER] << " " - << m_PlatformIdentifier << "\n"; // 31 - state_stream << STATE_KEYWORD[STA_SENSOR_IDENTIFIER] << " " - << m_SensorIdentifier << "\n"; // 32 - state_stream << STATE_KEYWORD[STA_TRAJECTORY_IDENTIFIER] << " " - << m_TrajectoryIdentifier << "\n"; // 33 - state_stream << STATE_KEYWORD[STA_COLLECTION_IDENTIFIER] << " " - << m_CollectionIdentifier << "\n"; // 33 - state_stream << STATE_KEYWORD[STA_REF_ELEVATION] << " " << m_RefElevation << "\n"; // 34 - state_stream << STATE_KEYWORD[STA_MIN_ELEVATION] << " " << m_MinElevation << "\n"; // 34 - state_stream << STATE_KEYWORD[STA_MAX_ELEVATION] << " " << m_MaxElevation << "\n"; // 35 - state_stream << STATE_KEYWORD[STA_DT_EPHEM] << " " <<m_DtEphem << "\n"; // 36 - state_stream << STATE_KEYWORD[STA_T0_EPHEM] << " " <<m_T0Ephem << "\n"; // 37 - state_stream << STATE_KEYWORD[STA_DT_QUAT] << " " << m_DtQuat << "\n"; // 38 - state_stream << STATE_KEYWORD[STA_T0_QUAT] << " " <<m_T0Quat << "\n"; // 39 - state_stream << STATE_KEYWORD[STA_NUM_EPHEM]<< " " <<m_NumEphem << "\n"; // 40 - state_stream << STATE_KEYWORD[STA_NUM_QUATERNIONS] << " " << m_NumQuaternions << "\n"; // 41 - state_stream << STATE_KEYWORD[STA_EPHEM_PTS] << " " ; - for (int i = 0; i < 3*m_NumEphem; i++) - { - state_stream << m_EphemPts[i] << " "; // 42 - } - state_stream << "\n"; - state_stream << STATE_KEYWORD[STA_EPHEM_RATES] << " "; - for (int i = 0; i < 3*m_NumEphem; i++) - { - state_stream << m_EphemRates[i] << " "; // 43 - } - state_stream << "\n"; - state_stream << STATE_KEYWORD[STA_QUATERNIONS] << " "; - for (int i = 0; i < 4*m_NumQuaternions; i++) - { - state_stream << m_Quaternions[i] << " "; // 44 - } - state_stream << "\n"; - state_stream << STATE_KEYWORD[STA_PARAMETER_VALS] << " "; - for (int i = 0; i < NUM_PARAMETERS; i++) - { - state_stream << m_ParameterVals[i] << " "; // 45 - } - state_stream << "\n"; - state_stream << STATE_KEYWORD[STA_PARAMETER_TYPE] << " "; - for (int i = 0; i < NUM_PARAMETERS; i++) - { - for (int j = 0; j < NUM_PARAM_TYPES; j++) - { - if (m_ParameterType[i] == PARAM_CHAR_ALL[j]) - { - state_stream << PARAM_STRING_ALL[j] << " "; // 46 - break; - } - } - } - state_stream << "\n"; - state_stream << STATE_KEYWORD[STA_REFERENCE_POINT_XYZ] << " "; - state_stream << m_ReferencePointXyz.x << " " ; // 47 - state_stream << m_ReferencePointXyz.y << " " ; // 47 - state_stream << m_ReferencePointXyz.z << "\n" ; // 47 - state_stream << STATE_KEYWORD[STA_GSD] << " " <<m_Gsd << "\n"; // 48 - state_stream << STATE_KEYWORD[STA_FLYING_HEIGHT] << " " << m_FlyingHeight << "\n"; // 49 - state_stream << STATE_KEYWORD[STA_HALF_SWATH] << " " << m_HalfSwath << "\n"; // 50 - state_stream << STATE_KEYWORD[STA_HALF_TIME] << " " << m_HalfTime << "\n"; // 51 - state_stream << STATE_KEYWORD[STA_COVARIANCE] << " "; - for (int i = 0; i < NUM_PARAMETERS*NUM_PARAMETERS; i++) - { - state_stream << m_Covariance[i] << " "; // 52 - } - state_stream << "\n"; - state_stream << STATE_KEYWORD[STA_IMAGE_FLIP_FLAG] << " " << m_ImageFlipFlag << "\n"; // 53 -// state_stream << std::ends; - return state_stream.str(); -} - - -void UsgsAstroLsStateData::setState(const std::string &stateString ) -{ - reset(); - auto j = json::parse(stateString); - int num_params = NUM_PARAMETERS; - int num_params_sq = num_params * num_params; - - m_ImageIdentifier = j["STA_IMAGE_IDENTIFIER"]; - m_SensorType = j["STA_SENSOR_TYPE"]; - m_TotalLines = j["STA_TOTAL_LINES"]; - m_TotalSamples = j["STA_TOTAL_SAMPLES"]; - m_OffsetLines = j["STA_OFFSET_LINES"]; - m_OffsetSamples = j["STA_OFFSET_SAMPLES"]; - m_PlatformFlag = j["STA_PLATFORM_FLAG"]; - m_AberrFlag = j["STA_ABERR_FLAG"]; - m_AtmRefFlag = j["STA_ATMREF_FLAG"]; - m_IntTimeLines = j["STA_INT_TIME_LINES"].get<std::vector<double>>(); - m_IntTimeStartTimes = j["STA_INT_TIME_START_TIMES"].get<std::vector<double>>(); - m_IntTimes = j["STA_INT_TIMES"].get<std::vector<double>>(); - m_StartingEphemerisTime = j["STA_STARTING_EPHEMERIS_TIME"]; - m_CenterEphemerisTime = j["STA_CENTER_EPHEMERIS_TIME"]; - m_DetectorSampleSumming = j["STA_DETECTOR_SAMPLE_SUMMING"]; - m_StartingSample = j["STA_STARTING_SAMPLE"]; - m_IkCode = j["STA_IK_CODE"]; - m_Focal = j["STA_FOCAL"]; - m_IsisZDirection = j["STA_ISIS_Z_DIRECTION"]; - for (int i = 0; i < 3; i++) { - m_OpticalDistCoef[i] = j["STA_OPTICAL_DIST_COEF"][i]; - m_ITransS[i] = j["STA_I_TRANS_S"][i]; - m_ITransL[i] = j["STA_I_TRANS_L"][i]; - } - m_DetectorSampleOrigin = j["STA_DETECTOR_SAMPLE_ORIGIN"]; - m_DetectorLineOrigin = j["STA_DETECTOR_LINE_ORIGIN"]; - m_DetectorLineOffset = j["STA_DETECTOR_LINE_OFFSET"]; - for (int i = 0; i < 9; i++) { - m_MountingMatrix[i] = j["STA_MOUNTING_MATRIX"][i]; - } - m_SemiMajorAxis = j["STA_SEMI_MAJOR_AXIS"]; - m_SemiMinorAxis = j["STA_SEMI_MINOR_AXIS"]; - m_ReferenceDateAndTime = j["STA_REFERENCE_DATE_AND_TIME"]; - m_PlatformIdentifier = j["STA_PLATFORM_IDENTIFIER"]; - m_SensorIdentifier = j["STA_SENSOR_IDENTIFIER"]; - m_TrajectoryIdentifier = j["STA_TRAJECTORY_IDENTIFIER"]; - m_CollectionIdentifier = j["STA_COLLECTION_IDENTIFIER"]; - m_RefElevation = j["STA_REF_ELEVATION"]; - m_MinElevation = j["STA_MIN_ELEVATION"]; - m_MaxElevation = j["STA_MAX_ELEVATION"]; - m_DtEphem = j["STA_DT_EPHEM"]; - m_T0Ephem = j["STA_T0_EPHEM"]; - m_DtQuat = j["STA_DT_QUAT"]; - m_T0Quat = j["STA_T0_QUAT"]; - m_NumEphem = j["STA_NUM_EPHEM"]; - m_NumQuaternions = j["STA_NUM_QUATERNIONS"]; - m_ReferencePointXyz.x = j["STA_REFERENCE_POINT_XYZ"][0]; - m_ReferencePointXyz.y = j["STA_REFERENCE_POINT_XYZ"][1]; - m_ReferencePointXyz.z = j["STA_REFERENCE_POINT_XYZ"][2]; - m_Gsd = j["STA_GSD"]; - m_FlyingHeight = j["STA_FLYING_HEIGHT"]; - m_HalfSwath = j["STA_HALF_SWATH"]; - m_HalfTime = j["STA_HALF_TIME"]; - m_ImageFlipFlag = j["STA_IMAGE_FLIP_FLAG"]; - // Vector = is overloaded so explicit get with type required. - m_EphemPts = j["STA_EPHEM_PTS"].get<std::vector<double>>(); - m_EphemRates = j["STA_EPHEM_RATES"].get<std::vector<double>>(); - m_Quaternions = j["STA_QUATERNIONS"].get<std::vector<double>>(); - m_ParameterVals = j["STA_PARAMETER_VALS"].get<std::vector<double>>(); - m_Covariance = j["STA_COVARIANCE"].get<std::vector<double>>(); - for (int i = 0; i < num_params; i++) { - for (int k = 0; k < NUM_PARAM_TYPES; k++) { - if (j["STA_PARAMETER_TYPE"][i] == PARAM_STRING_ALL[k]) { - m_ParameterType[i] = PARAM_CHAR_ALL[k]; - break; - } - } - } -} - -std::string UsgsAstroLsStateData::getModelNameFromModelState( - const std::string& model_state) -{ - // Parse the string to JSON - auto j = json::parse(model_state); - // If model name cannot be determined, return a blank string - std::string model_name; - - if (j.find("STA_SENSOR_MODEL_NAME") != j.end()) { - model_name = j["STA_SENSOR_MODEL_NAME"]; - } else { - csm::Error::ErrorType aErrorType = csm::Error::INVALID_SENSOR_MODEL_STATE; - std::string aMessage = "No 'STA_SENSOR_MODEL_NAME' key in the model state object."; - std::string aFunction = "UsgsAstroLsPlugin::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 = "UsgsAstroLsPlugin::getModelNameFromModelState()"; - csm::Error csmErr(aErrorType, aMessage, aFunction); - throw(csmErr); - } - return model_name; -} - - -void UsgsAstroLsStateData::reset() -{ - m_ImageIdentifier = ""; // 1 - m_SensorType = "USGSAstroLineScanner"; // 2 - m_TotalLines = 0; // 3 - m_TotalSamples = 0; // 4 - m_OffsetLines = 0.0; // 7 - m_OffsetSamples = 0.0; // 8 - m_PlatformFlag = 1; // 9 - m_AberrFlag = 0; // 10 - m_AtmRefFlag = 0; // 11 - m_IntTimeLines.clear(); - m_IntTimeStartTimes.clear(); - m_IntTimes.clear(); - m_StartingEphemerisTime = 0.0; // 13 - m_CenterEphemerisTime = 0.0; // 14 - m_DetectorSampleSumming = 1.0; // 15 - m_StartingSample = 1.0; // 16 - m_IkCode = -85600; // 17 - m_Focal = 350.0; // 18 - m_IsisZDirection = 1.0; // 19 - m_OpticalDistCoef[0] = 0.0; // 20 - m_OpticalDistCoef[1] = 0.0; // 20 - m_OpticalDistCoef[2] = 0.0; // 20 - m_ITransS[0] = 0.0; // 21 - m_ITransS[1] = 0.0; // 21 - m_ITransS[2] = 150.0; // 21 - m_ITransL[0] = 0.0; // 22 - m_ITransL[1] = 150.0; // 22 - m_ITransL[2] = 0.0; // 22 - m_DetectorSampleOrigin = 2500.0; // 23 - m_DetectorLineOrigin = 0.0; // 24 - m_DetectorLineOffset = 0.0; // 25 - m_MountingMatrix[0] = 1.0; // 26 - m_MountingMatrix[1] = 0.0; // 26 - m_MountingMatrix[2] = 0.0; // 26 - m_MountingMatrix[3] = 0.0; // 26 - m_MountingMatrix[4] = 1.0; // 26 - m_MountingMatrix[5] = 0.0; // 26 - m_MountingMatrix[6] = 0.0; // 26 - m_MountingMatrix[7] = 0.0; // 26 - m_MountingMatrix[8] = 1.0; // 26 - m_SemiMajorAxis = 3400000.0; // 27 - m_SemiMinorAxis = 3350000.0; // 28 - m_ReferenceDateAndTime = ""; // 30 - m_PlatformIdentifier = ""; // 31 - m_SensorIdentifier = ""; // 32 - m_TrajectoryIdentifier = ""; // 33 - m_CollectionIdentifier = ""; // 33 - m_RefElevation = 30; // 34 - m_MinElevation = -8000.0; // 34 - m_MaxElevation = 8000.0; // 35 - m_DtEphem = 2.0; // 36 - m_T0Ephem = -70.0; // 37 - m_DtQuat = 0.1; // 38 - m_T0Quat = -40.0; // 39 - m_NumEphem = 0; // 40 - m_NumQuaternions = 0; // 41 - m_EphemPts.clear(); // 42 - m_EphemRates.clear(); // 43 - m_Quaternions.clear(); // 44 - - m_ParameterVals.assign(NUM_PARAMETERS,0.0); - m_ParameterType.assign(NUM_PARAMETERS,csm::param::REAL); - - m_ReferencePointXyz.x = 0.0; // 47 - m_ReferencePointXyz.y = 0.0; // 47 - m_ReferencePointXyz.z = 0.0; // 47 - m_Gsd = 1.0; // 48 - m_FlyingHeight = 1000.0; // 49 - m_HalfSwath = 1000.0; // 50 - m_HalfTime = 10.0; // 51 - - m_Covariance.assign(NUM_PARAMETERS * NUM_PARAMETERS,0.0); // 52 - for (int i = 0; i < NUM_PARAMETERS; i++) - { - m_Covariance[i * NUM_PARAMETERS + i] = 1.0; - } - m_ImageFlipFlag = 0; // 53 - -} diff --git a/src/UsgsAstroPlugin.cpp b/src/UsgsAstroPlugin.cpp new file mode 100644 index 0000000..fc67553 --- /dev/null +++ b/src/UsgsAstroPlugin.cpp @@ -0,0 +1,284 @@ +#include "UsgsAstroPlugin.h" + +#include "UsgsAstroFrameSensorModel.h" +#include "UsgsAstroLsSensorModel.h" + +#include <algorithm> +#include <cstdlib> +#include <string> +#include <fstream> + +#include <math.h> +#include <csm.h> +#include <Error.h> +#include <Plugin.h> +#include <Warning.h> +#include <Version.h> + +#include <json.hpp> +using json = nlohmann::json; + +#ifdef _WIN32 +# define DIR_DELIMITER_STR "\\" +#else +# define DIR_DELIMITER_STR "/" +#endif + + +// Declaration of static variables +const std::string UsgsAstroPlugin::_PLUGIN_NAME = "UsgsAstroPluginCSM"; +const std::string UsgsAstroPlugin::_MANUFACTURER_NAME = "UsgsAstrogeology"; +const std::string UsgsAstroPlugin::_RELEASE_DATE = "20170425"; +const int UsgsAstroPlugin::_N_SENSOR_MODELS = 2; +const int UsgsAstroPlugin::_NUM_ISD_KEYWORDS = 21; + +const std::string UsgsAstroPlugin::_ISD_KEYWORD[] = +{ + "name_model", + "center_ephemeris_time", + "dt_ephemeris", + "focal2pixel_lines", + "focal2pixel_samples", + "focal_length_model", + "image_lines", + "image_samples", + "interpolation_method", + "number_of_ephemerides", + "optical_distortion", + "radii", + "reference_height", + "sensor_location_unit", + "sensor_location", + "sensor_orientation", + "sensor_velocity", + "detector_center", + "starting_detector_line", + "starting_detector_sample", + "starting_ephemeris_time", + "sun_position" +}; + +// const json UsgsAstroPlugin::MODEL_KEYWORDS = { +// {UsgsAstroFrameSensorModel::_SENSOR_MODEL_NAME, UsgsAstroFrameSensorModel::_STATE_KEYWORD}, +// {UsgsAstroLsSensorModel::_SENSOR_MODEL_NAME, UsgsAstroLsSensorModel::_STATE_KEYWORD} +// }; + + +// Static Instance of itself +const UsgsAstroPlugin UsgsAstroPlugin::m_registeredPlugin; + +UsgsAstroPlugin::UsgsAstroPlugin() { +} + + +UsgsAstroPlugin::~UsgsAstroPlugin() { +} + + +std::string UsgsAstroPlugin::getPluginName() const { + return _PLUGIN_NAME; +} + + +std::string UsgsAstroPlugin::getManufacturer() const { + return _MANUFACTURER_NAME; +} + + +std::string UsgsAstroPlugin::getReleaseDate() const { + return _RELEASE_DATE; +} + + +csm::Version UsgsAstroPlugin::getCsmVersion() const { + return CURRENT_CSM_VERSION; +} + + +size_t UsgsAstroPlugin::getNumModels() const { + return _N_SENSOR_MODELS; +} + + +std::string UsgsAstroPlugin::getModelName(size_t modelIndex) const { + std::vector<std::string> supportedModelNames = { + UsgsAstroFrameSensorModel::_SENSOR_MODEL_NAME, + UsgsAstroLsSensorModel::_SENSOR_MODEL_NAME + }; + return supportedModelNames[modelIndex]; +} + + +std::string UsgsAstroPlugin::getModelFamily(size_t modelIndex) const { + return CSM_RASTER_FAMILY; +} + + +csm::Version UsgsAstroPlugin::getModelVersion(const std::string &modelName) const { + return csm::Version(1, 0, 0); +} + + +bool UsgsAstroPlugin::canModelBeConstructedFromState(const std::string &modelName, + const std::string &modelState, + csm::WarningList *warnings) const { + try { + csm::Model* model = constructModelFromState(modelState, warnings); + return (bool)model; + } + catch(...) { + return false; + } +} + + +bool UsgsAstroPlugin::canModelBeConstructedFromISD(const csm::Isd &imageSupportData, + const std::string &modelName, + csm::WarningList *warnings) const { + try { + csm::Model* model = constructModelFromISD(imageSupportData, modelName, warnings); + return (bool)model; + } + catch(...) { + return false; + } +} + + +// This function takes a csm::Isd which only has the image filename set. It uses this filename to +// find a metadata json file located alongside the image file and returns a json +// encoded string. +std::string UsgsAstroPlugin::loadImageSupportData(const csm::Isd &imageSupportDataOriginal) const { + + // Get image location from the input csm::Isd: + std::string imageFilename = imageSupportDataOriginal.filename(); + size_t lastIndex = imageFilename.find_last_of("."); + std::string baseName = imageFilename.substr(0, lastIndex); + std::string isdFilename = baseName.append(".json"); + + try { + std::ifstream isd_sidecar(isdFilename); + json jsonisd; + isd_sidecar >> jsonisd; + return jsonisd.dump(); + + } catch (...) { + std::string errorMessage = "Could not read metadata file associated with image: "; + errorMessage.append(isdFilename); + throw csm::Error(csm::Error::FILE_READ, errorMessage, + "UsgsAstroPlugin::loadImageSupportData"); + } +} + + +std::string UsgsAstroPlugin::getModelNameFromModelState(const std::string &modelState, + csm::WarningList *warnings) const { + auto state = json::parse(modelState); + + std::string name = state.value<std::string>("name_model", ""); + + if (name == "") { + csm::Error::ErrorType aErrorType = csm::Error::INVALID_SENSOR_MODEL_STATE; + std::string aMessage = "No 'name_model' key in the model state object."; + std::string aFunction = "UsgsAstroPlugin::getModelNameFromModelState"; + csm::Error csmErr(aErrorType, aMessage, aFunction); + throw(csmErr); + } + + return name; +} + + +bool UsgsAstroPlugin::canISDBeConvertedToModelState(const csm::Isd &imageSupportData, + const std::string &modelName, + csm::WarningList *warnings) const { + try { + convertISDToModelState(imageSupportData, modelName, warnings); + } + catch(...) { + return false; + } + return true; +} + + +std::string UsgsAstroPlugin::getStateFromISD(csm::Isd imageSupportData) const { + std::string stringIsd = loadImageSupportData(imageSupportData); + json jsonIsd = json::parse(stringIsd); + return convertISDToModelState(imageSupportData, jsonIsd.at("modelName")); +} + + +std::string UsgsAstroPlugin::convertISDToModelState(const csm::Isd &imageSupportData, + const std::string &modelName, + csm::WarningList *warnings) const { + + csm::Model* sensor_model = constructModelFromISD(imageSupportData, modelName, warnings); + return sensor_model->getModelState(); +} + + +csm::Model *UsgsAstroPlugin::constructModelFromISD(const csm::Isd &imageSupportDataOriginal, + const std::string &modelName, + csm::WarningList *warnings) const { + + std::string stringIsd = loadImageSupportData(imageSupportDataOriginal); + + if (modelName == UsgsAstroFrameSensorModel::_SENSOR_MODEL_NAME) { + UsgsAstroFrameSensorModel *model = new UsgsAstroFrameSensorModel(); + try { + model->replaceModelState(model->constructStateFromIsd(stringIsd, warnings)); + } + catch (...) { + csm::Error::ErrorType aErrorType = csm::Error::SENSOR_MODEL_NOT_CONSTRUCTIBLE; + std::string aMessage = "Invalid ISD for Model " + modelName + ": "; + 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 { + model->replaceModelState(model->constructStateFromIsd(stringIsd, warnings)); + } + catch (...) { + csm::Error::ErrorType aErrorType = csm::Error::SENSOR_MODEL_NOT_CONSTRUCTIBLE; + std::string aMessage = "Invalid ISD for Model " + modelName + ": "; + std::string aFunction = "UsgsAstroPlugin::constructModelFromISD()"; + 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()"; + throw csm::Error(aErrorType, aMessage, aFunction); + } +} + + +csm::Model *UsgsAstroPlugin::constructModelFromState(const std::string& modelState, + csm::WarningList *warnings) const { + + json state = json::parse(modelState); + std::string modelName = state["modelName"]; + + if (modelName == UsgsAstroFrameSensorModel::_SENSOR_MODEL_NAME) { + UsgsAstroFrameSensorModel* model = new UsgsAstroFrameSensorModel(); + model->replaceModelState(modelState); + return model; + } + else if (modelName == UsgsAstroLsSensorModel::_SENSOR_MODEL_NAME) { + UsgsAstroLsSensorModel* model = new UsgsAstroLsSensorModel(); + model->replaceModelState(modelState); + return model; + } + else { + csm::Error::ErrorType aErrorType = csm::Error::ISD_NOT_SUPPORTED; + std::string aMessage = "Model" + modelName + " not supported: "; + std::string aFunction = "UsgsAstroPlugin::constructModelFromState()"; + throw csm::Error(aErrorType, aMessage, aFunction); + } +} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 749de24..3388d81 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,7 +1,15 @@ cmake_minimum_required(VERSION 3.10) # Link runCSMCameraModelTests with what we want to test and the GTest and pthread library -add_executable(runCSMCameraModelTests TestyMcTestFace.cpp FrameCameraTests.cpp) -target_link_libraries(runCSMCameraModelTests usgscsm ${GTEST_LIBRARIES} ${GTEST_MAIN_LIBRARIES} pthread) +add_executable(runCSMCameraModelTests + PluginTests.cpp + FrameCameraTests.cpp) +if(WIN32) + option(CMAKE_USE_WIN32_THREADS_INIT "using WIN32 threads" ON) + option(gtest_disable_pthreads "Disable uses of pthreads in gtest." ON) + target_link_libraries(runCSMCameraModelTests usgscsm ${GTEST_LIBRARIES} ${GTEST_MAIN_LIBRARIES}) +else() + target_link_libraries(runCSMCameraModelTests usgscsm ${GTEST_LIBRARIES} ${GTEST_MAIN_LIBRARIES} pthread) +endif() gtest_discover_tests(runCSMCameraModelTests WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/tests) diff --git a/tests/Fixtures.h b/tests/Fixtures.h new file mode 100644 index 0000000..be28df3 --- /dev/null +++ b/tests/Fixtures.h @@ -0,0 +1,144 @@ +#ifndef Fixtures_h +#define Fixtures_h + +#include "UsgsAstroPlugin.h" +#include "UsgsAstroFrameSensorModel.h" + +#include <json.hpp> + +#include <map> +#include <sstream> +#include <fstream> + +#include <gtest/gtest.h> + +using json = nlohmann::json; + +// Should this be positioned somewhere in the public API? +inline void jsonToIsd(json &object, csm::Isd &isd, std::string prefix="") { + for (json::iterator it = object.begin(); it != object.end(); ++it) { + json jsonValue = it.value(); + if (jsonValue.is_array()) { + for (int i = 0; i < jsonValue.size(); i++) { + isd.addParam(prefix+it.key(), jsonValue[i].dump()); + } + } + else if (jsonValue.is_string()) { + isd.addParam(prefix+it.key(), jsonValue.get<std::string>()); + } + else { + isd.addParam(prefix+it.key(), jsonValue.dump()); + } + } +} + +class FrameSensorModel : public ::testing::Test { + protected: + csm::Isd isd; + UsgsAstroFrameSensorModel *sensorModel; + + void SetUp() override { + sensorModel = NULL; + + isd.setFilename("data/simpleFramerISD.img"); + UsgsAstroPlugin frameCameraPlugin; + + csm::Model *model = frameCameraPlugin.constructModelFromISD( + isd, + "USGS_ASTRO_FRAME_SENSOR_MODEL"); + sensorModel = dynamic_cast<UsgsAstroFrameSensorModel *>(model); + + ASSERT_NE(sensorModel, nullptr); + } + + void TearDown() override { + if (sensorModel) { + delete sensorModel; + sensorModel = NULL; + } + } +}; + +class FrameIsdTest : public ::testing::Test { + protected: + csm::Isd isd; + + virtual void SetUp() { + isd.setFilename("data/simpleFramerISD.img"); + } +}; + +class ConstVelLineScanIsdTest : public ::testing::Test { + protected: + csm::Isd isd; + + virtual void SetUp() { + isd.setFilename("data/constVelocityLineScan.img"); + } +}; + +class FramerParameterizedTest : public ::testing::TestWithParam<csm::ImageCoord> { + +protected: + csm::Isd isd; + + std::string printIsd(csm::Isd &localIsd) { + std::string str; + std::multimap<std::string,std::string> isdmap= localIsd.parameters(); + for (auto it = isdmap.begin(); it != isdmap.end();++it){ + str.append(it->first); + str.append(":"); + str.append(it->second); + } + return str; + } + UsgsAstroFrameSensorModel* createModel(csm::Isd &modifiedIsd) { + + UsgsAstroPlugin frameCameraPlugin; + csm::Model *model = frameCameraPlugin.constructModelFromISD( + modifiedIsd,"USGS_ASTRO_FRAME_SENSOR_MODEL"); + + UsgsAstroFrameSensorModel* sensorModel = dynamic_cast<UsgsAstroFrameSensorModel *>(model); + + if (sensorModel) + return sensorModel; + else + return nullptr; + } + + + virtual void SetUp() { + isd.setFilename("data/simpleFramerISD.img"); + }; +}; + +class FrameStateTest : public ::testing::Test { + protected: + csm::Isd isd; + UsgsAstroFrameSensorModel* createModifiedStateSensorModel(std::string key, double newValue) { + UsgsAstroPlugin cameraPlugin; + csm::Model *model = cameraPlugin.constructModelFromISD(isd,"USGS_ASTRO_FRAME_SENSOR_MODEL"); + + UsgsAstroFrameSensorModel* sensorModel = dynamic_cast<UsgsAstroFrameSensorModel *>(model); + if (sensorModel) { + sensorModel->getModelState(); + std::string modelState = sensorModel->getModelState(); + auto state = json::parse(modelState); + state[key] = newValue; + sensorModel->replaceModelState(state.dump()); + + return sensorModel; + } + else { + return nullptr; + } + } + + void SetUp() override { + isd.setFilename("data/simpleFramerISD.img"); + } +}; + + + +#endif diff --git a/tests/FrameCameraTests.cpp b/tests/FrameCameraTests.cpp index 27bdb6e..cab179e 100644 --- a/tests/FrameCameraTests.cpp +++ b/tests/FrameCameraTests.cpp @@ -1,122 +1,31 @@ -#include "UsgsAstroFramePlugin.h" +#include "UsgsAstroPlugin.h" #include "UsgsAstroFrameSensorModel.h" #include <json.hpp> -#include <iostream> -#include <iomanip> -#include <sstream> -#include <fstream> -#include <map> -#include <vector> #include <gtest/gtest.h> -using namespace std; -using json = nlohmann::json; - +#include "Fixtures.h" -class FramerParameterizedTest : public ::testing::TestWithParam<csm::ImageCoord> { - -protected: - csm::Isd isd; - - void printIsd(csm::Isd &localIsd) { - multimap<string,string> isdmap= localIsd.parameters(); - for (auto it = isdmap.begin(); it != isdmap.end();++it){ - - cout << it->first << " : " << it->second << endl; - } - } - UsgsAstroFrameSensorModel* createModel(csm::Isd &modifiedIsd) { - - UsgsAstroFramePlugin frameCameraPlugin; - csm::Model *model = frameCameraPlugin.constructModelFromISD( - modifiedIsd,"USGS_ASTRO_FRAME_SENSOR_MODEL"); - - UsgsAstroFrameSensorModel* sensorModel = dynamic_cast<UsgsAstroFrameSensorModel *>(model); - - if (sensorModel) - return sensorModel; - else - return nullptr; - } - - - virtual void SetUp() { - isd.setFilename("data/simpleFramerISD.img"); - }; -}; - - -class FrameIsdTest : public ::testing::Test { - protected: - csm::Isd isd; - void printIsd(csm::Isd &localIsd) { - multimap<string,string> isdmap= localIsd.parameters(); - for (auto it = isdmap.begin(); it != isdmap.end();++it){ - cout << it->first << " : " << it->second << endl; - } - } - UsgsAstroFrameSensorModel* createModel(csm::Isd &modifiedIsd) { - UsgsAstroFramePlugin frameCameraPlugin; - csm::Model *model = frameCameraPlugin.constructModelFromISD( - modifiedIsd,"USGS_ASTRO_FRAME_SENSOR_MODEL"); - UsgsAstroFrameSensorModel* sensorModel = dynamic_cast<UsgsAstroFrameSensorModel *>(model); - if (sensorModel) - return sensorModel; - else - return nullptr; - } - - - virtual void SetUp() { - isd.setFilename("data/simpleFramerISD.img"); - } -}; - -class FrameSensorModel : public ::testing::Test { - protected: - protected : - csm::Isd isd; - UsgsAstroFrameSensorModel *sensorModel; - - void SetUp() override { - sensorModel = NULL; - - isd.setFilename("data/simpleFramerISD.img"); - UsgsAstroFramePlugin frameCameraPlugin; - csm::Model *model = frameCameraPlugin.constructModelFromISD( - isd, - "USGS_ASTRO_FRAME_SENSOR_MODEL"); - sensorModel = dynamic_cast<UsgsAstroFrameSensorModel *>(model); - ASSERT_NE(sensorModel, nullptr); - } - - void TearDown() override { - if (sensorModel) { - delete sensorModel; - sensorModel = NULL; - } - } -}; +using json = nlohmann::json; INSTANTIATE_TEST_CASE_P(JacobianTest,FramerParameterizedTest, ::testing::Values(csm::ImageCoord(2.5,2.5),csm::ImageCoord(7.5,7.5))); -TEST_P(FramerParameterizedTest,JacobianTest) { +TEST_P(FramerParameterizedTest, JacobianTest) { UsgsAstroFrameSensorModel* sensorModel = createModel(isd); - std::string modelState = sensorModel->getModelState(); + std::string modelState = sensorModel->getModelState(); auto state = json::parse(modelState); state["m_odtX"] = {1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0}; state["m_odtY"] = {0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0}; - sensorModel->replaceModelState(state.dump()); - + sensorModel->replaceModelState(state.dump()); + double Jxx,Jxy,Jyx,Jyy; ASSERT_NE(sensorModel, nullptr); csm::ImageCoord imagePt1 = GetParam(); - cout << "[" << imagePt1.samp << "," << imagePt1.line << "]"<< endl; +// cout << "[" << imagePt1.samp << "," << imagePt1.line << "]"<< endl; sensorModel->distortionJacobian(imagePt1.samp, imagePt1.line, Jxx, Jxy,Jyx,Jyy); double determinant = fabs(Jxx*Jyy - Jxy*Jyx); @@ -128,6 +37,14 @@ TEST_P(FramerParameterizedTest,JacobianTest) { // NOTE: The imagePt format is (Lines,Samples) +TEST_F(FrameSensorModel, State) { + std::string modelState = sensorModel->getModelState(); + EXPECT_NO_THROW( + sensorModel->replaceModelState(modelState) + ); + EXPECT_EQ(sensorModel->getModelState(), modelState); +} + // centered and slightly off-center: TEST_F(FrameSensorModel, Center) { csm::ImageCoord imagePt(7.5, 7.5); @@ -136,6 +53,7 @@ TEST_F(FrameSensorModel, Center) { EXPECT_NEAR(groundPt.y, 0, 1e-8); EXPECT_NEAR(groundPt.z, 0, 1e-8); } + TEST_F(FrameSensorModel, SlightlyOffCenter) { csm::ImageCoord imagePt(7.5, 6.5); csm::EcefCoord groundPt = sensorModel->imageToGround(imagePt, 0.0); @@ -159,6 +77,7 @@ TEST_F(FrameSensorModel, OffBody2) { EXPECT_NEAR(groundPt.y, 14.99325304, 1e-8); EXPECT_NEAR(groundPt.z, -14.99325304, 1e-8); } + TEST_F(FrameSensorModel, OffBody3) { csm::ImageCoord imagePt(0.0, 0.0); csm::EcefCoord groundPt = sensorModel->imageToGround(imagePt, 0.0); @@ -166,6 +85,7 @@ TEST_F(FrameSensorModel, OffBody3) { EXPECT_NEAR(groundPt.y, 14.99325304, 1e-8); EXPECT_NEAR(groundPt.z, 14.99325304, 1e-8); } + TEST_F(FrameSensorModel, OffBody4) { csm::ImageCoord imagePt(15.0, 15.0); csm::EcefCoord groundPt = sensorModel->imageToGround(imagePt, 0.0); @@ -174,39 +94,34 @@ TEST_F(FrameSensorModel, OffBody4) { EXPECT_NEAR(groundPt.z, -14.99325304, 1e-8); } - - -TEST_F(FrameIsdTest, setFocalPlane1) { +TEST_F(FrameSensorModel, setFocalPlane1) { csm::ImageCoord imagePt(7.5, 7.5); double ux,uy; - UsgsAstroFrameSensorModel* sensorModel = createModel(isd); - - std::string modelState = sensorModel->getModelState(); + std::string modelState = sensorModel->getModelState(); auto state = json::parse(modelState); state["m_odtX"] = {0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0}; state["m_odtY"] = {0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0}; - sensorModel->replaceModelState(state.dump()); + sensorModel->replaceModelState(state.dump()); ASSERT_NE(sensorModel, nullptr); sensorModel->setFocalPlane(imagePt.samp, imagePt.line, ux, uy); EXPECT_NEAR(imagePt.samp,7.5,1e-8 ); - EXPECT_NEAR(imagePt.line,7.5,1e-8); + EXPECT_NEAR(imagePt.line,7.5,1e-8); delete sensorModel; sensorModel = NULL; } -TEST_F(FrameIsdTest, Jacobian1) { +TEST_F(FrameSensorModel, Jacobian1) { csm::ImageCoord imagePt(7.5, 7.5); - UsgsAstroFrameSensorModel* sensorModel = createModel(isd); - std::string modelState = sensorModel->getModelState(); + std::string modelState = sensorModel->getModelState(); auto state = json::parse(modelState); state["m_odtX"] = {0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0}; state["m_odtY"] = {0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,1.0}; - sensorModel->replaceModelState(state.dump()); + sensorModel->replaceModelState(state.dump()); double Jxx,Jxy,Jyx,Jyy; @@ -217,42 +132,40 @@ TEST_F(FrameIsdTest, Jacobian1) { EXPECT_NEAR(Jxy,112.5,1e-8); EXPECT_NEAR(Jyx,56.25,1e-8); EXPECT_NEAR(Jyy,281.25,1e-8); - + delete sensorModel; sensorModel = NULL; } -TEST_F(FrameIsdTest, distortMe_AllCoefficientsOne) { +TEST_F(FrameSensorModel, distortMe_AllCoefficientsOne) { csm::ImageCoord imagePt(7.5, 7.5); - UsgsAstroFrameSensorModel* sensorModel = createModel(isd); - std::string modelState = sensorModel->getModelState(); + std::string modelState = sensorModel->getModelState(); auto state = json::parse(modelState); state["m_odtX"] = {1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0}; state["m_odtY"] = {1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0}; - sensorModel->replaceModelState(state.dump()); + sensorModel->replaceModelState(state.dump()); double dx,dy; ASSERT_NE(sensorModel, nullptr); sensorModel->distortionFunction(imagePt.samp, imagePt.line,dx,dy ); - + EXPECT_NEAR(dx,1872.25,1e-8 ); EXPECT_NEAR(dy,1872.25,1e-8); - + delete sensorModel; sensorModel = NULL; } -TEST_F(FrameIsdTest, setFocalPlane_AllCoefficientsOne) { +TEST_F(FrameSensorModel, setFocalPlane_AllCoefficientsOne) { csm::ImageCoord imagePt(1872.25, 1872.25); - UsgsAstroFrameSensorModel* sensorModel = createModel(isd); - std::string modelState = sensorModel->getModelState(); + std::string modelState = sensorModel->getModelState(); auto state = json::parse(modelState); state["m_odtX"] = {1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0}; state["m_odtY"] = {1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0}; - sensorModel->replaceModelState(state.dump()); + sensorModel->replaceModelState(state.dump()); double ux,uy; ASSERT_NE(sensorModel, nullptr); @@ -268,37 +181,35 @@ TEST_F(FrameIsdTest, setFocalPlane_AllCoefficientsOne) { } -TEST_F(FrameIsdTest, distortMe_AlternatingOnes) { +TEST_F(FrameSensorModel, distortMe_AlternatingOnes) { csm::ImageCoord imagePt(7.5, 7.5); - UsgsAstroFrameSensorModel* sensorModel = createModel(isd); - std::string modelState = sensorModel->getModelState(); + std::string modelState = sensorModel->getModelState(); auto state = json::parse(modelState); state["m_odtX"] = {1.0,0.0,1.0,0.0,1.0,0.0,1.0,0.0,1.0,0.0}; state["m_odtY"] = {0.0,1.0,0.0,1.0,0.0,1.0,0.0,1.0,0.0,1.0}; - sensorModel->replaceModelState(state.dump()); + sensorModel->replaceModelState(state.dump()); double dx,dy; ASSERT_NE(sensorModel, nullptr); sensorModel->distortionFunction(imagePt.samp, imagePt.line,dx,dy ); - + EXPECT_NEAR(dx,908.5,1e-8 ); EXPECT_NEAR(dy,963.75,1e-8); - + delete sensorModel; sensorModel = NULL; } -TEST_F(FrameIsdTest, setFocalPlane_AlternatingOnes) { +TEST_F(FrameSensorModel, setFocalPlane_AlternatingOnes) { csm::ImageCoord imagePt(963.75, 908.5); - UsgsAstroFrameSensorModel* sensorModel = createModel(isd); - std::string modelState = sensorModel->getModelState(); + std::string modelState = sensorModel->getModelState(); auto state = json::parse(modelState); state["m_odtX"] = {1.0,0.0,1.0,0.0,1.0,0.0,1.0,0.0,1.0,0.0}; state["m_odtY"] = {0.0,1.0,0.0,1.0,0.0,1.0,0.0,1.0,0.0,1.0}; - sensorModel->replaceModelState(state.dump()); + sensorModel->replaceModelState(state.dump()); double ux,uy; ASSERT_NE(sensorModel, nullptr); @@ -313,61 +224,45 @@ TEST_F(FrameIsdTest, setFocalPlane_AlternatingOnes) { } - // Focal Length Tests: -TEST_F(FrameIsdTest, FL500_OffBody4) { +TEST_F(FrameStateTest, FL500_OffBody4) { std::string key = "m_focalLength"; double newValue = 500.0; + UsgsAstroFrameSensorModel* sensorModel = createModifiedStateSensorModel(key, newValue); - UsgsAstroFrameSensorModel* sensorModel = createModel(isd); - std::string modelState = sensorModel->getModelState(); - auto state = json::parse(modelState); - state[key] = newValue; - sensorModel->replaceModelState(state.dump()); - ASSERT_NE(sensorModel, nullptr); csm::ImageCoord imagePt(15.0, 15.0); csm::EcefCoord groundPt = sensorModel->imageToGround(imagePt, 0.0); EXPECT_NEAR(groundPt.x, 9.77688917, 1e-8); EXPECT_NEAR(groundPt.y, -1.48533467, 1e-8); EXPECT_NEAR(groundPt.z, -1.48533467, 1e-8); - + delete sensorModel; sensorModel = NULL; } -TEST_F(FrameIsdTest, FL500_OffBody3) { +TEST_F(FrameStateTest, FL500_OffBody3) { std::string key = "m_focalLength"; double newValue = 500.0; + UsgsAstroFrameSensorModel* sensorModel = createModifiedStateSensorModel(key, newValue); - UsgsAstroFrameSensorModel* sensorModel = createModel(isd); - std::string modelState = sensorModel->getModelState(); - auto state = json::parse(modelState); - state[key] = newValue; - sensorModel->replaceModelState(state.dump()); - ASSERT_NE(sensorModel, nullptr); csm::ImageCoord imagePt(0.0, 0.0); csm::EcefCoord groundPt = sensorModel->imageToGround(imagePt, 0.0); EXPECT_NEAR(groundPt.x, 9.77688917, 1e-8); EXPECT_NEAR(groundPt.y, 1.48533467, 1e-8); EXPECT_NEAR(groundPt.z, 1.48533467, 1e-8); - + delete sensorModel; sensorModel = NULL; } -TEST_F(FrameIsdTest, FL500_Center) { +TEST_F(FrameStateTest, FL500_Center) { std::string key = "m_focalLength"; double newValue = 500.0; - - UsgsAstroFrameSensorModel* sensorModel = createModel(isd); - std::string modelState = sensorModel->getModelState(); - auto state = json::parse(modelState); - state[key] = newValue; - sensorModel->replaceModelState(state.dump()); + UsgsAstroFrameSensorModel* sensorModel = createModifiedStateSensorModel(key, newValue); ASSERT_NE(sensorModel, nullptr); csm::ImageCoord imagePt(7.5, 7.5); @@ -375,21 +270,16 @@ TEST_F(FrameIsdTest, FL500_Center) { EXPECT_NEAR(groundPt.x, 10.0, 1e-8); EXPECT_NEAR(groundPt.y, 0.0, 1e-8); EXPECT_NEAR(groundPt.z, 0.0, 1e-8); - + delete sensorModel; sensorModel = NULL; } -TEST_F(FrameIsdTest, FL500_SlightlyOffCenter) { +TEST_F(FrameStateTest, FL500_SlightlyOffCenter) { std::string key = "m_focalLength"; double newValue = 500.0; - - UsgsAstroFrameSensorModel* sensorModel = createModel(isd); - std::string modelState = sensorModel->getModelState(); - auto state = json::parse(modelState); - state[key] = newValue; - sensorModel->replaceModelState(state.dump()); + UsgsAstroFrameSensorModel* sensorModel = createModifiedStateSensorModel(key, newValue); ASSERT_NE(sensorModel, nullptr); csm::ImageCoord imagePt(7.5, 6.5); @@ -403,9 +293,8 @@ TEST_F(FrameIsdTest, FL500_SlightlyOffCenter) { } // Observer x position: -TEST_F(FrameIsdTest, X10_SlightlyOffCenter) { +TEST_F(FrameSensorModel, X10_SlightlyOffCenter) { double newValue = 10.0; - UsgsAstroFrameSensorModel* sensorModel = createModel(isd); sensorModel->setParameterValue(0, newValue); // X ASSERT_NE(sensorModel, nullptr); @@ -419,11 +308,8 @@ TEST_F(FrameIsdTest, X10_SlightlyOffCenter) { sensorModel = NULL; } - -TEST_F(FrameIsdTest, X1e9_SlightlyOffCenter) { +TEST_F(FrameSensorModel, X1e9_SlightlyOffCenter) { double newValue = 1000000000.0; - - UsgsAstroFrameSensorModel* sensorModel = createModel(isd); sensorModel->setParameterValue(0, newValue); // X ASSERT_NE(sensorModel, nullptr); @@ -440,9 +326,16 @@ TEST_F(FrameIsdTest, X1e9_SlightlyOffCenter) { // Angle rotations: -TEST_F(FrameIsdTest, Rotation_omegaPi_Center) { - UsgsAstroFrameSensorModel* sensorModel = createModel(isd); - sensorModel->setParameterValue(3, M_PI); // omega +TEST_F(FrameSensorModel, Rotation_omegaPi_Center) { + sensorModel->setParameterValue(3, 1.0); + sensorModel->setParameterValue(4, 1.0); + sensorModel->setParameterValue(5, 1.0); + + sensorModel->setParameterValue(6, 1.0); + + sensorModel->setParameterValue(0, 1000.0); // X + sensorModel->setParameterValue(1, 0.0); // Y + sensorModel->setParameterValue(2, 0.0); // Z ASSERT_NE(sensorModel, nullptr); csm::ImageCoord imagePt(7.5, 7.5); @@ -456,30 +349,33 @@ TEST_F(FrameIsdTest, Rotation_omegaPi_Center) { } -TEST_F(FrameIsdTest, Rotation_NPole_Center) { - UsgsAstroFrameSensorModel* sensorModel = createModel(isd); - sensorModel->setParameterValue(4, -M_PI); // phi - sensorModel->setParameterValue(0, 0.0); // X - sensorModel->setParameterValue(1, 0.0); // Y - sensorModel->setParameterValue(2, 1000.0); // Z +TEST_F(FrameSensorModel, Rotation_NPole_Center) { + sensorModel->setParameterValue(3, 0.0); + sensorModel->setParameterValue(4, -1.0); + sensorModel->setParameterValue(5, 0.0); - ASSERT_NE(sensorModel, nullptr); - csm::ImageCoord imagePt(7.5, 7.5); - csm::EcefCoord groundPt = sensorModel->imageToGround(imagePt, 0.0); - EXPECT_NEAR(groundPt.x, 0.0, 1e-8); - EXPECT_NEAR(groundPt.y, 0.0, 1e-8); - EXPECT_NEAR(groundPt.z, 10.0, 1e-8); + sensorModel->setParameterValue(6, 0.0); - delete sensorModel; - sensorModel = NULL; + sensorModel->setParameterValue(0, 0.0); // X + sensorModel->setParameterValue(1, 0.0); // Y + sensorModel->setParameterValue(2, 1000.0); // Z + + ASSERT_NE(sensorModel, nullptr); + csm::ImageCoord imagePt(7.5, 7.5); + csm::EcefCoord groundPt = sensorModel->imageToGround(imagePt, 0.0); + EXPECT_NEAR(groundPt.x, 0.0, 1e-8); + EXPECT_NEAR(groundPt.y, 0.0, 1e-8); + EXPECT_NEAR(groundPt.z, 10.0, 1e-8); + + delete sensorModel; + sensorModel = NULL; } -TEST_F(FrameIsdTest, Rotation_SPole_Center) { - UsgsAstroFrameSensorModel* sensorModel = createModel(isd); +TEST_F(FrameSensorModel, Rotation_SPole_Center) { sensorModel->setParameterValue(4, 0.0); // phi sensorModel->setParameterValue(0, 0.0); // X - sensorModel->setParameterValue(1, 0.0); // Y + sensorModel->setParameterValue(1, 0.0); // Y sensorModel->setParameterValue(2, -1000.0); // Z ASSERT_NE(sensorModel, nullptr); @@ -495,15 +391,11 @@ TEST_F(FrameIsdTest, Rotation_SPole_Center) { // Ellipsoid axis tests: -TEST_F(FrameIsdTest, SemiMajorAxis100x_Center) { +TEST_F(FrameStateTest, SemiMajorAxis100x_Center) { std::string key = "m_majorAxis"; double newValue = 1000.0; - UsgsAstroFrameSensorModel* sensorModel = createModel(isd); - std::string modelState = sensorModel->getModelState(); - auto state = json::parse(modelState); - state[key] = newValue; - sensorModel->replaceModelState(state.dump()); + UsgsAstroFrameSensorModel* sensorModel = createModifiedStateSensorModel(key, newValue); ASSERT_NE(sensorModel, nullptr); csm::ImageCoord imagePt(7.5, 7.5); @@ -517,15 +409,10 @@ TEST_F(FrameIsdTest, SemiMajorAxis100x_Center) { } -TEST_F(FrameIsdTest, SemiMajorAxis10x_SlightlyOffCenter) { +TEST_F(FrameStateTest, SemiMajorAxis10x_SlightlyOffCenter) { std::string key = "m_majorAxis"; double newValue = 100.0; - - UsgsAstroFrameSensorModel* sensorModel = createModel(isd); - std::string modelState = sensorModel->getModelState(); - auto state = json::parse(modelState); - state[key] = newValue; - sensorModel->replaceModelState(state.dump()); + UsgsAstroFrameSensorModel* sensorModel = createModifiedStateSensorModel(key, newValue); ASSERT_NE(sensorModel, nullptr); csm::ImageCoord imagePt(7.5, 6.5); @@ -535,7 +422,7 @@ TEST_F(FrameIsdTest, SemiMajorAxis10x_SlightlyOffCenter) { EXPECT_NEAR(groundPt.x, 9.83606557e+01, 1e-7); EXPECT_NEAR(groundPt.y, 0.0, 1e-7); EXPECT_NEAR(groundPt.z, 1.80327869, 1e-7); - + delete sensorModel; sensorModel = NULL; } @@ -543,23 +430,18 @@ TEST_F(FrameIsdTest, SemiMajorAxis10x_SlightlyOffCenter) { // The following test is for the scenario where the semi_minor_axis is actually larger // than the semi_major_axis: -TEST_F(FrameIsdTest, SemiMinorAxis10x_SlightlyOffCenter) { - std::string key = "m_minorAxis"; - double newValue = 100.0; - - UsgsAstroFrameSensorModel* sensorModel = createModel(isd); - std::string modelState = sensorModel->getModelState(); - auto state = json::parse(modelState); - state[key] = newValue; - sensorModel->replaceModelState(state.dump()); +TEST_F(FrameStateTest, SemiMinorAxis10x_SlightlyOffCenter) { + std::string key = "m_minorAxis"; + double newValue = 100.0; + UsgsAstroFrameSensorModel* sensorModel = createModifiedStateSensorModel(key, newValue); - ASSERT_NE(sensorModel, nullptr); - csm::ImageCoord imagePt(7.5, 6.5); - csm::EcefCoord groundPt = sensorModel->imageToGround(imagePt, 0.0); - EXPECT_NEAR(groundPt.x, 9.99803960, 1e-8); - EXPECT_NEAR(groundPt.y, 0.0, 1e-8); - EXPECT_NEAR(groundPt.z, 1.98000392, 1e-8); + ASSERT_NE(sensorModel, nullptr); + csm::ImageCoord imagePt(7.5, 6.5); + csm::EcefCoord groundPt = sensorModel->imageToGround(imagePt, 0.0); + EXPECT_NEAR(groundPt.x, 9.99803960, 1e-8); + EXPECT_NEAR(groundPt.y, 0.0, 1e-8); + EXPECT_NEAR(groundPt.z, 1.98000392, 1e-8); - delete sensorModel; - sensorModel = NULL; + delete sensorModel; + sensorModel = NULL; } diff --git a/tests/PluginTests.cpp b/tests/PluginTests.cpp new file mode 100644 index 0000000..2252e88 --- /dev/null +++ b/tests/PluginTests.cpp @@ -0,0 +1,190 @@ +#include "UsgsAstroPlugin.h" +#include "UsgsAstroFrameSensorModel.h" +#include "UsgsAstroLsSensorModel.h" + +#include <sstream> +#include <fstream> + +#include <gtest/gtest.h> + +#include "Fixtures.h" + +TEST(PluginTests, PluginName) { + UsgsAstroPlugin testPlugin; + EXPECT_EQ("UsgsAstroPluginCSM", testPlugin.getPluginName()); +} + +TEST(PluginTests, ManufacturerName) { + UsgsAstroPlugin testPlugin; + EXPECT_EQ("UsgsAstrogeology", testPlugin.getManufacturer()); +} + +TEST(PluginTests, ReleaseDate) { + UsgsAstroPlugin testPlugin; + EXPECT_EQ("20170425", testPlugin.getReleaseDate()); +} + +TEST(PluginTests, NumModels) { + UsgsAstroPlugin testPlugin; + EXPECT_EQ(2, testPlugin.getNumModels()); +} + +TEST(PluginTests, BadISDFile) { + UsgsAstroPlugin testPlugin; + csm::Isd badIsd("Not a file"); + EXPECT_FALSE(testPlugin.canModelBeConstructedFromISD( + badIsd, + "USGS_ASTRO_FRAME_SENSOR_MODEL")); + EXPECT_FALSE(testPlugin.canModelBeConstructedFromISD( + badIsd, + "USGS_ASTRO_LINE_SCANNER_SENSOR_MODEL")); +} + +TEST(FrameStateTests, NoStateName) { + UsgsAstroPlugin testPlugin; + std::string badState = "{\"not_a_name\":\"bad_name\"}"; + EXPECT_FALSE(testPlugin.canModelBeConstructedFromState( + "USGS_ASTRO_FRAME_SENSOR_MODEL", + badState)); +} + +TEST(FrameStateTests, BadStateName) { + UsgsAstroPlugin testPlugin; + std::string badState = "{\"m_model_name\":\"bad_name\"}"; + EXPECT_FALSE(testPlugin.canModelBeConstructedFromState( + "USGS_ASTRO_FRAME_SENSOR_MODEL", + badState)); +} + +TEST(FrameStateTests, BadStateValue) { + UsgsAstroPlugin testPlugin; + std::string badState = "{" + "\"m_model_name\":\"USGS_ASTRO_FRAME_SENSOR_MODEL\"," + "\"bad_param\":\"bad_value\"}"; + EXPECT_FALSE(testPlugin.canModelBeConstructedFromState( + "USGS_ASTRO_FRAME_SENSOR_MODEL", + badState)); +} + +TEST(FrameStateTests, MissingStateValue) { + UsgsAstroPlugin testPlugin; + std::string badState = "{" + "\"m_model_name\":\"USGS_ASTRO_FRAME_SENSOR_MODEL\"}"; + EXPECT_FALSE(testPlugin.canModelBeConstructedFromState( + "USGS_ASTRO_FRAME_SENSOR_MODEL", + badState)); +} + +TEST_F(FrameIsdTest, Constructible) { + UsgsAstroPlugin testPlugin; + EXPECT_TRUE(testPlugin.canModelBeConstructedFromISD( + isd, + "USGS_ASTRO_FRAME_SENSOR_MODEL")); +} + +TEST_F(FrameIsdTest, NotConstructible) { + UsgsAstroPlugin testPlugin; + isd.setFilename("data/constVelocityLineScan.img"); + EXPECT_FALSE(testPlugin.canModelBeConstructedFromISD( + isd, + "USGS_ASTRO_FRAME_SENSOR_MODEL")); +} + + +TEST_F(FrameIsdTest, ConstructValidCamera) { + UsgsAstroPlugin testPlugin; + csm::Model *cameraModel = NULL; + EXPECT_NO_THROW( + cameraModel = testPlugin.constructModelFromISD( + isd, + "USGS_ASTRO_FRAME_SENSOR_MODEL", + NULL) + ); + UsgsAstroFrameSensorModel *frameModel = dynamic_cast<UsgsAstroFrameSensorModel *>(cameraModel); + EXPECT_NE(frameModel, nullptr); + if (cameraModel) { + delete cameraModel; + } +} + + +TEST_F(FrameIsdTest, ConstructInValidCamera) { + UsgsAstroPlugin testPlugin; + isd.setFilename("data/constVelocityLineScan.img"); + csm::Model *cameraModel = NULL; + try { + testPlugin.constructModelFromISD( + isd, + "USGS_ASTRO_FRAME_SENSOR_MODEL", + NULL); + FAIL() << "Expected an error"; + } + catch(csm::Error &e) { + EXPECT_EQ(e.getError(), csm::Error::SENSOR_MODEL_NOT_CONSTRUCTIBLE); + } + catch(...) { + FAIL() << "Expected csm SENSOR_MODEL_NOT_CONSTRUCTIBLE error"; + } + if (cameraModel) { + delete cameraModel; + } +} + +TEST_F(ConstVelLineScanIsdTest, Constructible) { + UsgsAstroPlugin testPlugin; + EXPECT_TRUE(testPlugin.canModelBeConstructedFromISD( + isd, + "USGS_ASTRO_LINE_SCANNER_SENSOR_MODEL")); +} + +TEST_F(ConstVelLineScanIsdTest, NotConstructible) { + UsgsAstroPlugin testPlugin; + isd.setFilename("data/simpleFramerISD.img"); + EXPECT_FALSE(testPlugin.canModelBeConstructedFromISD( + isd, + "USGS_ASTRO_LINE_SCANNER_SENSOR_MODEL")); +} + +TEST_F(ConstVelLineScanIsdTest, ConstructValidCamera) { + UsgsAstroPlugin testPlugin; + csm::Model *cameraModel = NULL; + EXPECT_NO_THROW( + cameraModel = testPlugin.constructModelFromISD( + isd, + "USGS_ASTRO_LINE_SCANNER_SENSOR_MODEL", + NULL) + ); + UsgsAstroLsSensorModel *frameModel = dynamic_cast<UsgsAstroLsSensorModel *>(cameraModel); + EXPECT_NE(frameModel, nullptr); + if (cameraModel) { + delete cameraModel; + } +} + +TEST_F(ConstVelLineScanIsdTest, ConstructInValidCamera) { + UsgsAstroPlugin testPlugin; + isd.setFilename("data/simpleFramerISD.img"); + csm::Model *cameraModel = NULL; + try { + testPlugin.constructModelFromISD( + isd, + "USGS_ASTRO_LINE_SCANNER_SENSOR_MODEL", + NULL); + FAIL() << "Expected an error"; + + } + catch(csm::Error &e) { + EXPECT_EQ(e.getError(), csm::Error::SENSOR_MODEL_NOT_CONSTRUCTIBLE); + } + catch(...) { + FAIL() << "Expected csm SENSOR_MODEL_NOT_CONSTRUCTIBLE error"; + } + if (cameraModel) { + delete cameraModel; + } +} + +int main(int argc, char **argv) { + ::testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/tests/TestyMcTestFace.cpp b/tests/TestyMcTestFace.cpp deleted file mode 100644 index 7b0696c..0000000 --- a/tests/TestyMcTestFace.cpp +++ /dev/null @@ -1,124 +0,0 @@ -#include "UsgsAstroFramePlugin.h" -#include "UsgsAstroFrameSensorModel.h" - -#include <json.hpp> - -#include <sstream> -#include <fstream> - -#include <gtest/gtest.h> - -using json = nlohmann::json; - -class FrameIsdTest : public ::testing::Test { - protected: - csm::Isd isd; - virtual void SetUp() { - isd.setFilename("data/simpleFramerISD.img"); - }; -}; - -TEST(FramePluginTests, PluginName) { - UsgsAstroFramePlugin testPlugin; - EXPECT_EQ("UsgsAstroFramePluginCSM", testPlugin.getPluginName());; -} - -TEST(FramePluginTests, ManufacturerName) { - UsgsAstroFramePlugin testPlugin; - EXPECT_EQ("UsgsAstrogeology", testPlugin.getManufacturer());; -} - -TEST(FramePluginTests, ReleaseDate) { - UsgsAstroFramePlugin testPlugin; - EXPECT_EQ("20170425", testPlugin.getReleaseDate());; -} - -TEST(FramePluginTests, NumModels) { - UsgsAstroFramePlugin testPlugin; - EXPECT_EQ(1, testPlugin.getNumModels());; -} - -TEST(FramePluginTests, NoStateName) { - UsgsAstroFramePlugin testPlugin; - std::string badState = "{\"not_a_name\":\"bad_name\"}"; - EXPECT_FALSE(testPlugin.canModelBeConstructedFromState( - "USGS_ASTRO_FRAME_SENSOR_MODEL", - badState));; -} - -TEST(FramePluginTests, BadStateName) { - UsgsAstroFramePlugin testPlugin; - std::string badState = "{\"model_name\":\"bad_name\"}"; - EXPECT_FALSE(testPlugin.canModelBeConstructedFromState( - "USGS_ASTRO_FRAME_SENSOR_MODEL", - badState));; -} - -TEST(FramePluginTests, BadStateValue) { - UsgsAstroFramePlugin testPlugin; - std::string badState = "{" - "\"model_name\":\"USGS_ASTRO_FRAME_SENSOR_MODEL\"," - "\"bad_param\":\"bad_value\"}"; - EXPECT_FALSE(testPlugin.canModelBeConstructedFromState( - "USGS_ASTRO_FRAME_SENSOR_MODEL", - badState));; -} - -TEST(FramePluginTests, MissingStateValue) { - UsgsAstroFramePlugin testPlugin; - std::string badState = "{" - "\"model_name\":\"USGS_ASTRO_FRAME_SENSOR_MODEL\"}"; - EXPECT_FALSE(testPlugin.canModelBeConstructedFromState( - "USGS_ASTRO_FRAME_SENSOR_MODEL", - badState));; -} - -TEST_F(FrameIsdTest, Constructible) { - UsgsAstroFramePlugin testPlugin; - EXPECT_TRUE(testPlugin.canModelBeConstructedFromISD( - isd, - "USGS_ASTRO_FRAME_SENSOR_MODEL")); -} - -TEST_F(FrameIsdTest, ConstructValidCamera) { - UsgsAstroFramePlugin testPlugin; - csm::Model *cameraModel = NULL; - EXPECT_NO_THROW( - cameraModel = testPlugin.constructModelFromISD( - isd, - "USGS_ASTRO_FRAME_SENSOR_MODEL", - NULL) - ); - UsgsAstroFrameSensorModel *frameModel = dynamic_cast<UsgsAstroFrameSensorModel *>(cameraModel); - EXPECT_NE(frameModel, nullptr); - if (cameraModel) { - delete cameraModel; - } -} - -TEST_F(FrameIsdTest, ConstructInValidCamera) { - UsgsAstroFramePlugin testPlugin; - // Remove the model_name keyword from the ISD to make it invalid - isd.clearParams("model_name"); - csm::Model *cameraModel = NULL; - try { - testPlugin.constructModelFromISD( - isd, - "USGS_ASTRO_FRAME_SENSOR_MODEL", - NULL); - } - catch(csm::Error &e) { - EXPECT_EQ(e.getError(), csm::Error::ISD_NOT_SUPPORTED); - } - catch(...) { - FAIL() << "Expected csm ISD_NOT_SUPPORTED error"; - } - if (cameraModel) { - delete cameraModel; - } -} - -int main(int argc, char **argv) { - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/tests/data/constVelocityLineScan.json b/tests/data/constVelocityLineScan.json new file mode 100644 index 0000000..7f910ef --- /dev/null +++ b/tests/data/constVelocityLineScan.json @@ -0,0 +1,93 @@ +{ + "name_model" : "USGS_ASTRO_LINE_SCANNER_SENSOR_MODEL", + "name_platform" : "TEST_PLATFORM", + "name_sensor" : "TEST_SENSOR", + "center_ephemeris_time": 1000.0, + "starting_ephemeris_time": 992.0, + "line_scan_rate": [ + [0.5, 992.0, 0.1] + ], + "detector_sample_summing": 1, + "detector_line_summing": 1, + "t0_ephemeris": -8.0, + "dt_ephemeris": 0.2, + "t0_quaternion": -8.0, + "dt_quaternion": 0.2, + "focal2pixel_lines": [0.0, 10.0, 0.0], + "focal2pixel_samples": [0.0, 0.0, 10.0], + "focal_length_model": { + "focal_length": 50, + "focal_epsilon": 1.0 + }, + "image_lines": 16, + "image_samples": 16, + "detector_center" : { + "line" : 0.5, + "sample" : 7.5 + }, + "interpolation_method": "lagrange", + "optical_distortion": { + "radial": { + "coefficients": [0.0, 0.0, 0.0] + } + }, + "radii": { + "semimajor": 10, + "semiminor": 10, + "unit":"m" + }, + "reference_height": { + "maxheight": 1, + "minheight": -1, + "unit": "m" + }, + "sensor_position": { + "unit": "m", + "positions": [ + [1000.0, 0.0, 16.0], + [1000.0, 0.0, 12.0], + [1000.0, 0.0, 8.0], + [1000.0, 0.0, 4.0], + [1000.0, 0.0, 0.0], + [1000.0, 0.0, -4.0], + [1000.0, 0.0, -8.0], + [1000.0, 0.0, -12.0], + [1000.0, 0.0, -16.0] + ], + "velocities": [ + [0.0, 0.0, -20.0], + [0.0, 0.0, -20.0], + [0.0, 0.0, -20.0], + [0.0, 0.0, -20.0], + [0.0, 0.0, -20.0], + [0.0, 0.0, -20.0], + [0.0, 0.0, -20.0], + [0.0, 0.0, -20.0], + [0.0, 0.0, -20.0] + ] + }, + "sensor_orientation": { + "quaternions": [ + [0.0, -0.707106781186547, 0.0, 0.707106781186547], + [0.0, -0.707106781186547, 0.0, 0.707106781186547], + [0.0, -0.707106781186547, 0.0, 0.707106781186547], + [0.0, -0.707106781186547, 0.0, 0.707106781186547], + [0.0, -0.707106781186547, 0.0, 0.707106781186547], + [0.0, -0.707106781186547, 0.0, 0.707106781186547], + [0.0, -0.707106781186547, 0.0, 0.707106781186547], + [0.0, -0.707106781186547, 0.0, 0.707106781186547], + [0.0, -0.707106781186547, 0.0, 0.707106781186547] + ] + }, + "starting_detector_line": 0, + "starting_detector_sample": 0, + "sun_position": { + "positions": [ + [100.0, 100.0, 0.0] + ], + "velocities": [ + [0.0, 0.0, 0.0] + ], + "unit": "m" + } +} diff --git a/tests/data/simpleFramerISD.json b/tests/data/simpleFramerISD.json index f1c3733..63fb799 100644 --- a/tests/data/simpleFramerISD.json +++ b/tests/data/simpleFramerISD.json @@ -1,86 +1,61 @@ { - "boresight": [ - 0.0, - 0.0, - 1.0 - ], - "ccd_center": [ - 7.5, - 7.5 - ], - "ephemeris_time": 100.0, - "focal_length": 50, - "focal_length_epsilon": 1.0, - "ifov": 6.0, - "model_name": "USGS_ASTRO_FRAME_SENSOR_MODEL", - "spacecraft_name": "TEST_CRAFT", - "instrument_id": "TEST_SENSOR", - "target_name": "TEST_BALL", - "pixel_pitch": 0.1, - "itrans_line": [ - 0.0, - 0.0, - 10 - ], - "itrans_sample": [ - 0.0, - 10, - 0.0 - ], - "transx": [ - 0.0, - 0.1, - 0.0 - ], - "transy": [ - 0.0, - 0.0, - 0.1 - ], - "min_elevation": -1, - "max_elevation": 1, - "nlines": 16, - "nsamples": 16, - "original_half_lines": 8.0, - "original_half_samples": 8.0, - "omega": 0, - "phi": -1.5707963267948966, - "kappa": 3.141592653589793, - "semi_major_axis":0.01, - "semi_minor_axis":0.01, - "x_sensor_origin": 1000, - "y_sensor_origin": 0, - "z_sensor_origin": 0, - "x_sensor_velocity": 1, - "y_sensor_velocity": 0, - "z_sensor_velocity": 0, - "x_sun_position": 100, - "y_sun_position": 100, - "z_sun_position": 0, - "odt_x": [ - 0.0, - 1.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0 - ], - "odt_y": [ - 0.0, - 1.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0, - 0.0 - ], - "starting_detector_line": 0.0, - "starting_detector_sample": 0.0 + "name_model" : "USGS_ASTRO_FRAME_SENSOR_MODEL", + "center_ephemeris_time": 50, + "dt_ephemeris": 100, + "focal2pixel_lines": [0.0, 0.0, 10.0], + "focal2pixel_samples": [0.0, 10.0, 0.0], + "focal_length_model": { + "focal_length": 50, + "focal_epsilon": 1.0 + }, + "image_lines": 15, + "image_samples": 15, + "detector_center" : { + "line" : 7.5, + "sample" : 7.5 + }, + "interpolation_method": "lagrange", + "number_of_ephemerides": 1, + "optical_distortion": { + "transverse": { + "x": [0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], + "y": [0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] + } + }, + "radii": { + "semimajor": 0.01, + "semiminor": 0.01, + "unit":"km" + }, + "reference_height": { + "maxheight": 1, + "minheight": -1, + "unit": "m" + }, + "sensor_position": { + "unit": "m", + "positions": [ + [1000.0, 0.0, 0.0] + ], + "velocities": [ + [0.0, 0.0, 0.0] + ] + }, + "sensor_orientation": { + "quaternions": [ + [0.0, -0.707106781186547, 0.0, 0.707106781186547] + ] + }, + "starting_detector_line": 0, + "starting_detector_sample": 0, + "starting_ephemeris_time": 0, + "sun_position": { + "unit": "m", + "positions": [ + [100.0, 100.0, 0.0] + ], + "velocities": [ + [0.0, 0.0, 0.0] + ] + } } -- GitLab