From 93bc3c7441f29e47989b66feaa6270037a5afe1b Mon Sep 17 00:00:00 2001 From: Kristin <kberry@usgs.gov> Date: Wed, 3 Oct 2018 09:59:54 -0700 Subject: [PATCH] UsgsAstroFramePlugin refactor, part one (#117) * Initial updates for refactoring the UsgsAstroFramePlugin * Jacobian1 test now passing * All coefficients test now passing * More testing passing * Down to 6 failing tests * Fixed failing position-offset tests * Update to strip out full-paths and also we're down to one failing test * Fixed last failing test by updating canModelBeConstructedFromIsd to load the json ISD into a csm::Isd object if it has not already been loaded * Updated based on review comments --- include/usgscsm/UsgsAstroFramePlugin.h | 2 + src/UsgsAstroFramePlugin.cpp | 70 ++- tests/FrameCameraTests.cpp | 754 +++++++++---------------- tests/TestyMcTestFace.cpp | 23 +- 4 files changed, 336 insertions(+), 513 deletions(-) diff --git a/include/usgscsm/UsgsAstroFramePlugin.h b/include/usgscsm/UsgsAstroFramePlugin.h index e15ee68..8b6f57e 100644 --- a/include/usgscsm/UsgsAstroFramePlugin.h +++ b/include/usgscsm/UsgsAstroFramePlugin.h @@ -45,6 +45,8 @@ class UsgsAstroFramePlugin : public csm::Plugin { // TODO when implementing, add any other necessary members. private: + csm::Isd loadImageSupportData(const csm::Isd &imageSupportData) const; + static const UsgsAstroFramePlugin m_registeredPlugin; static const std::string _PLUGIN_NAME; static const std::string _MANUFACTURER_NAME; diff --git a/src/UsgsAstroFramePlugin.cpp b/src/UsgsAstroFramePlugin.cpp index 4641cd2..74cf266 100644 --- a/src/UsgsAstroFramePlugin.cpp +++ b/src/UsgsAstroFramePlugin.cpp @@ -3,6 +3,10 @@ #include <cstdlib> #include <string> +#include <iostream> +#include <sstream> +#include <fstream> +#include <map> #include <csm.h> #include <Error.h> @@ -181,7 +185,8 @@ bool UsgsAstroFramePlugin::canModelBeConstructedFromState(const std::string &mod modelName != UsgsAstroFrameSensorModel::_SENSOR_MODEL_NAME){ constructible = false; } - // Check that the necessary keys are there (this does not chek values at all.) + + // 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()){ @@ -273,18 +278,65 @@ return sensor_model; } -csm::Model *UsgsAstroFramePlugin::constructModelFromISD(const csm::Isd &imageSupportData, +// 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, + throw csm::Error(csm::Error::ISD_NOT_SUPPORTED, "Sensor model support data provided is not supported by this plugin", - "UsgsAstroFramePlugin::constructModelFromISD"); + "UsgsAstroFramePlugin::constructModelFromISD"); } - UsgsAstroFrameSensorModel *sensorModel = new UsgsAstroFrameSensorModel(); + // Create the empty sensorModel + UsgsAstroFrameSensorModel *sensorModel = new UsgsAstroFrameSensorModel(); + // Keep track of necessary keywords that are missing from the ISD. std::vector<std::string> missingKeywords; @@ -375,7 +427,6 @@ csm::Model *UsgsAstroFramePlugin::constructModelFromISD(const csm::Isd &imageSup 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()); @@ -537,9 +588,14 @@ bool UsgsAstroFramePlugin::canISDBeConvertedToModelState(const csm::Isd &imageSu convertible = false; } + csm::Isd localImageSupportData = imageSupportData; + if (imageSupportData.parameters().empty()) { + localImageSupportData = loadImageSupportData(imageSupportData); + } + std::string value; for(auto &key : _ISD_KEYWORD){ - value = imageSupportData.param(key); + value = localImageSupportData.param(key); if (value.empty()){ convertible = false; } diff --git a/tests/FrameCameraTests.cpp b/tests/FrameCameraTests.cpp index 454d663..27bdb6e 100644 --- a/tests/FrameCameraTests.cpp +++ b/tests/FrameCameraTests.cpp @@ -19,14 +19,13 @@ 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; @@ -39,118 +38,56 @@ protected: return sensorModel; else return nullptr; - - } - virtual void SetUp() { - - - std::ifstream isdFile("data/simpleFramerISD.json"); - json jsonIsd = json::parse(isdFile); - for (json::iterator it = jsonIsd.begin(); it != jsonIsd.end(); ++it) { - json jsonValue = it.value(); - if (jsonValue.size() > 1) { - for (int i = 0; i < jsonValue.size(); i++) { - isd.addParam(it.key(), jsonValue[i].dump()); - } - } - else { - isd.addParam(it.key(), jsonValue.dump()); - } - } - isdFile.close(); - } + 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( + 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; - + UsgsAstroFrameSensorModel* sensorModel = dynamic_cast<UsgsAstroFrameSensorModel *>(model); + if (sensorModel) + return sensorModel; + else + return nullptr; } - - virtual void SetUp() { - std::ifstream isdFile("data/simpleFramerISD.json"); - json jsonIsd = json::parse(isdFile); - for (json::iterator it = jsonIsd.begin(); it != jsonIsd.end(); ++it) { - json jsonValue = it.value(); - if (jsonValue.size() > 1) { - for (int i = 0; i < jsonValue.size(); i++) { - isd.addParam(it.key(), jsonValue[i].dump()); - } - } - else { - isd.addParam(it.key(), jsonValue.dump()); - } - } - isdFile.close(); + 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; - std::ifstream isdFile("data/simpleFramerISD.json"); - json jsonIsd = json::parse(isdFile); - csm::Isd isd; - for (json::iterator it = jsonIsd.begin(); it != jsonIsd.end(); ++it) { - json jsonValue = it.value(); - if (jsonValue.size() > 1) { - for (int i = 0; i < jsonValue.size(); i++){ - isd.addParam(it.key(), jsonValue[i].dump()); - } - } - else { - isd.addParam(it.key(), jsonValue.dump()); - } - } - - isdFile.close(); + 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); } @@ -159,64 +96,39 @@ class FrameSensorModel : public ::testing::Test { delete sensorModel; sensorModel = NULL; } - } }; - - INSTANTIATE_TEST_CASE_P(JacobianTest,FramerParameterizedTest, ::testing::Values(csm::ImageCoord(2.5,2.5),csm::ImageCoord(7.5,7.5))); TEST_P(FramerParameterizedTest,JacobianTest) { - int precision = 20; - std:string odtx_key= "odt_x"; - std::string odty_key="odt_y"; - - isd.clearParams(odty_key); - isd.clearParams(odtx_key); - - - vector<double> odtx{1.0,0.0,1.0,0.0,1.0,0.0,1.0,0.0,1.0,0.0}; - vector<double> odty{0.0,1.0,0.0,1.0,0.0,1.0,0.0,1.0,0.0,1.0}; - - - for (auto & val: odtx){ - ostringstream strval; - strval << setprecision(precision) << val; - isd.addParam("odt_x", strval.str()); - } - for (auto & val: odty){ - ostringstream strval; - strval << setprecision(precision) << val; - isd.addParam("odt_y", strval.str()); - } - UsgsAstroFrameSensorModel* sensorModel = createModel(isd); + 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()); + double Jxx,Jxy,Jyx,Jyy; - ASSERT_NE(sensorModel, nullptr); csm::ImageCoord imagePt1 = GetParam(); cout << "[" << imagePt1.samp << "," << imagePt1.line << "]"<< endl; sensorModel->distortionJacobian(imagePt1.samp, imagePt1.line, Jxx, Jxy,Jyx,Jyy); - double determinant = fabs(Jxx*Jyy - Jxy*Jyx); - EXPECT_GT(determinant,1e-3); delete sensorModel; sensorModel=NULL; - - } -//NOTE: The imagePt format is (Lines,Samples) +// NOTE: The imagePt format is (Lines,Samples) -//centered and slightly off-center: +// centered and slightly off-center: TEST_F(FrameSensorModel, Center) { csm::ImageCoord imagePt(7.5, 7.5); csm::EcefCoord groundPt = sensorModel->imageToGround(imagePt, 0.0); @@ -232,7 +144,7 @@ TEST_F(FrameSensorModel, SlightlyOffCenter) { EXPECT_NEAR(groundPt.z, 1.98039612, 1e-8); } -//Test all four corners: +// Test all four corners: TEST_F(FrameSensorModel, OffBody1) { csm::ImageCoord imagePt(15.0, 0.0); csm::EcefCoord groundPt = sensorModel->imageToGround(imagePt, 0.0); @@ -265,343 +177,236 @@ TEST_F(FrameSensorModel, OffBody4) { TEST_F(FrameIsdTest, setFocalPlane1) { - int precision = 20; - std:string odtx_key= "odt_x"; - std::string odty_key="odt_y"; - - isd.clearParams(odty_key); - isd.clearParams(odtx_key); - csm::ImageCoord imagePt(7.5, 7.5); double ux,uy; - vector<double> odtx{0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0}; - vector<double> odty{0.0,1.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0}; + UsgsAstroFrameSensorModel* sensorModel = createModel(isd); + std::string modelState = sensorModel->getModelState(); + auto state = json::parse(modelState); - for (auto & val: odtx){ - ostringstream strval; - strval << setprecision(precision) << val; - isd.addParam("odt_x", strval.str()); - } - for (auto & val: odty){ - ostringstream strval; - strval << setprecision(precision) << val; - isd.addParam("odt_y", strval.str()); - } - - UsgsAstroFrameSensorModel* sensorModel =createModel(isd); - 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); - delete sensorModel; - sensorModel = NULL; - + 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()); + 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); + delete sensorModel; + sensorModel = NULL; } - TEST_F(FrameIsdTest, Jacobian1) { + csm::ImageCoord imagePt(7.5, 7.5); - int precision = 20; - std:string odtx_key= "odt_x"; - std::string odty_key="odt_y"; - - isd.clearParams(odty_key); - isd.clearParams(odtx_key); - - csm::ImageCoord imagePt(7.5, 7.5); - - vector<double> odtx{0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,0.0}; - vector<double> odty{0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,1.0,1.0}; - - for (auto & val: odtx){ - ostringstream strval; - strval << setprecision(precision) << val; - isd.addParam("odt_x", strval.str()); - } - for (auto & val: odty){ - ostringstream strval; - strval << setprecision(precision) << val; - isd.addParam("odt_y", strval.str()); - } - - UsgsAstroFrameSensorModel* sensorModel = createModel(isd); - - - double Jxx,Jxy,Jyx,Jyy; - - ASSERT_NE(sensorModel, nullptr); - sensorModel->distortionJacobian(imagePt.samp, imagePt.line, Jxx, Jxy,Jyx,Jyy); - - EXPECT_NEAR(Jxx,56.25,1e-8 ); - 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; - + UsgsAstroFrameSensorModel* sensorModel = createModel(isd); + 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()); + + double Jxx,Jxy,Jyx,Jyy; + + ASSERT_NE(sensorModel, nullptr); + sensorModel->distortionJacobian(imagePt.samp, imagePt.line, Jxx, Jxy,Jyx,Jyy); + + EXPECT_NEAR(Jxx,56.25,1e-8 ); + 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) { + csm::ImageCoord imagePt(7.5, 7.5); - int precision = 20; - - std:string odtx_key= "odt_x"; - std::string odty_key="odt_y"; - - isd.clearParams(odty_key); - isd.clearParams(odtx_key); - - csm::ImageCoord imagePt(7.5, 7.5); - - vector<double> odtx{1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0}; - vector<double> odty{1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0}; - - for (auto & val: odtx){ - ostringstream strval; - strval << setprecision(precision) << val; - isd.addParam("odt_x", strval.str()); - } - for (auto & val: odty){ - ostringstream strval; - strval << setprecision(precision) << val; - isd.addParam("odt_y", strval.str()); - } - - - UsgsAstroFrameSensorModel* sensorModel = createModel(isd); - - 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; - + UsgsAstroFrameSensorModel* sensorModel = createModel(isd); + 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()); + + 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) { + csm::ImageCoord imagePt(1872.25, 1872.25); - int precision = 20; - std:string odtx_key= "odt_x"; - std::string odty_key="odt_y"; - - isd.clearParams(odty_key); - isd.clearParams(odtx_key); - - csm::ImageCoord imagePt(1872.25, 1872.25); - - vector<double> odtx{1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0}; - vector<double> odty{1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0}; - - for (auto & val: odtx){ - ostringstream strval; - strval << setprecision(precision) << val; - isd.addParam("odt_x", strval.str()); - } - for (auto & val: odty){ - ostringstream strval; - strval << setprecision(precision) << val; - isd.addParam("odt_y", strval.str()); - } - - - - UsgsAstroFrameSensorModel* sensorModel = createModel(isd); - - - double ux,uy; - ASSERT_NE(sensorModel, nullptr); - sensorModel->setFocalPlane(imagePt.samp, imagePt.line,ux,uy ); - + UsgsAstroFrameSensorModel* sensorModel = createModel(isd); + 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()); - //The Jacobian is singular, so the setFocalPlane should break out of it's iteration and - //returns the same distorted coordinates that were passed in. - EXPECT_NEAR(ux,imagePt.samp,1e-8 ); - EXPECT_NEAR(uy,imagePt.line,1e-8); + double ux,uy; + ASSERT_NE(sensorModel, nullptr); + sensorModel->setFocalPlane(imagePt.samp, imagePt.line,ux,uy ); - delete sensorModel; - sensorModel = NULL; + // The Jacobian is singular, so the setFocalPlane should break out of it's iteration and + // returns the same distorted coordinates that were passed in. + EXPECT_NEAR(ux,imagePt.samp,1e-8 ); + EXPECT_NEAR(uy,imagePt.line,1e-8); + delete sensorModel; + sensorModel = NULL; } TEST_F(FrameIsdTest, distortMe_AlternatingOnes) { + csm::ImageCoord imagePt(7.5, 7.5); - int precision = 20; - std:string odtx_key= "odt_x"; - std::string odty_key="odt_y"; - - isd.clearParams(odty_key); - isd.clearParams(odtx_key); - - csm::ImageCoord imagePt(7.5, 7.5); - - vector<double> odtx{1.0,0.0,1.0,0.0,1.0,0.0,1.0,0.0,1.0,0.0}; - vector<double> odty{0.0,1.0,0.0,1.0,0.0,1.0,0.0,1.0,0.0,1.0}; - - for (auto & val: odtx){ - ostringstream strval; - strval << setprecision(precision) << val; - isd.addParam("odt_x", strval.str()); - } - for (auto & val: odty){ - ostringstream strval; - strval << setprecision(precision) << val; - isd.addParam("odt_y", strval.str()); - } - - UsgsAstroFrameSensorModel* sensorModel = createModel(isd); - - 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; - + UsgsAstroFrameSensorModel* sensorModel = createModel(isd); + 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()); + + 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) { + csm::ImageCoord imagePt(963.75, 908.5); - int precision = 20; - std:string odtx_key= "odt_x"; - std::string odty_key="odt_y"; - - isd.clearParams(odty_key); - isd.clearParams(odtx_key); + UsgsAstroFrameSensorModel* sensorModel = createModel(isd); + 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()); - csm::ImageCoord imagePt(963.75, 908.5); - - vector<double> odtx{1.0,0.0,1.0,0.0,1.0,0.0,1.0,0.0,1.0,0.0}; - vector<double> odty{0.0,1.0,0.0,1.0,0.0,1.0,0.0,1.0,0.0,1.0}; - - for (auto & val: odtx){ - ostringstream strval; - strval << setprecision(precision) << val; - isd.addParam("odt_x", strval.str()); - } - for (auto & val: odty){ - ostringstream strval; - strval << setprecision(precision) << val; - isd.addParam("odt_y", strval.str()); - } - - UsgsAstroFrameSensorModel* sensorModel = createModel(isd); - - double ux,uy; - ASSERT_NE(sensorModel, nullptr); - - sensorModel->setFocalPlane(imagePt.samp, imagePt.line,ux,uy ); + double ux,uy; + ASSERT_NE(sensorModel, nullptr); - EXPECT_NEAR(ux,7.5,1e-8 ); - EXPECT_NEAR(uy,7.5,1e-8); + sensorModel->setFocalPlane(imagePt.samp, imagePt.line,ux,uy ); - delete sensorModel; - sensorModel = NULL; + EXPECT_NEAR(ux,7.5,1e-8 ); + EXPECT_NEAR(uy,7.5,1e-8); + delete sensorModel; + sensorModel = NULL; } // Focal Length Tests: TEST_F(FrameIsdTest, FL500_OffBody4) { - std::string key = "focal_length"; - std::string newValue = "500.0"; - isd.clearParams(key); - isd.addParam(key,newValue); - - - UsgsAstroFrameSensorModel* sensorModel = createModel(isd); + 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()); + + 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; +} - 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) { - std::string key = "focal_length"; - std::string newValue = "500.0"; - isd.clearParams(key); - isd.addParam(key,newValue); - - UsgsAstroFrameSensorModel* sensorModel = createModel(isd); + 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()); + + 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; +} - 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) { - std::string key = "focal_length"; - std::string newValue = "500.0"; - isd.clearParams(key); - isd.addParam(key,newValue); - - UsgsAstroFrameSensorModel* sensorModel = createModel(isd); + std::string key = "m_focalLength"; + double newValue = 500.0; - ASSERT_NE(sensorModel, nullptr); - csm::ImageCoord imagePt(7.5, 7.5); - csm::EcefCoord groundPt = sensorModel->imageToGround(imagePt, 0.0); - EXPECT_NEAR(groundPt.x, 10.0, 1e-8); - EXPECT_NEAR(groundPt.y, 0.0, 1e-8); - EXPECT_NEAR(groundPt.z, 0.0, 1e-8); + UsgsAstroFrameSensorModel* sensorModel = createModel(isd); + std::string modelState = sensorModel->getModelState(); + auto state = json::parse(modelState); + state[key] = newValue; + sensorModel->replaceModelState(state.dump()); - delete sensorModel; - sensorModel = NULL; + ASSERT_NE(sensorModel, nullptr); + csm::ImageCoord imagePt(7.5, 7.5); + csm::EcefCoord groundPt = sensorModel->imageToGround(imagePt, 0.0); + 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) { - std::string key = "focal_length"; - std::string newValue = "500.0"; - isd.clearParams(key); - isd.addParam(key,newValue); - UsgsAstroFrameSensorModel* sensorModel = createModel(isd); - - 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.98000392e-01, 1e-8); - - delete sensorModel; - sensorModel = NULL; +TEST_F(FrameIsdTest, 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()); + + 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.98000392e-01, 1e-8); + + delete sensorModel; + sensorModel = NULL; } -//Observer x position: +// Observer x position: TEST_F(FrameIsdTest, X10_SlightlyOffCenter) { - std::string key = "x_sensor_origin"; - std::string newValue = "10.0"; - isd.clearParams(key); - isd.addParam(key,newValue); - + double newValue = 10.0; UsgsAstroFrameSensorModel* sensorModel = createModel(isd); + sensorModel->setParameterValue(0, newValue); // X ASSERT_NE(sensorModel, nullptr); csm::ImageCoord imagePt(7.5, 6.5); @@ -612,38 +417,32 @@ TEST_F(FrameIsdTest, X10_SlightlyOffCenter) { delete sensorModel; sensorModel = NULL; - } + + TEST_F(FrameIsdTest, X1e9_SlightlyOffCenter) { - std::string key = "x_sensor_origin"; - std::string newValue = "1000000000.0"; - isd.clearParams(key); - isd.addParam(key,newValue); + double newValue = 1000000000.0; UsgsAstroFrameSensorModel* sensorModel = createModel(isd); + sensorModel->setParameterValue(0, newValue); // X ASSERT_NE(sensorModel, nullptr); csm::ImageCoord imagePt(7.5, 6.5); csm::EcefCoord groundPt = sensorModel->imageToGround(imagePt, 0.0); - //Note: In the following, the tolerance was increased due to the very large distance being tested (~6.68 AU). + // Note: In the following, the tolerance was increased due to the very large distance being tested (~6.68 AU). EXPECT_NEAR(groundPt.x, 3.99998400e+03, 1e-4); EXPECT_NEAR(groundPt.y, 0.0, 1e-4); EXPECT_NEAR(groundPt.z, 1.99999200e+06, 1e-4); delete sensorModel; sensorModel = NULL; - } -//Angle rotations: -TEST_F(FrameIsdTest, Rotation_omegaPi_Center) { - std::string key = "omega"; - std::ostringstream strval; - strval << std::setprecision(20) << M_PI; - isd.clearParams(key); - isd.addParam(key,strval.str()); +// Angle rotations: +TEST_F(FrameIsdTest, Rotation_omegaPi_Center) { UsgsAstroFrameSensorModel* sensorModel = createModel(isd); + sensorModel->setParameterValue(3, M_PI); // omega ASSERT_NE(sensorModel, nullptr); csm::ImageCoord imagePt(7.5, 7.5); @@ -654,28 +453,15 @@ TEST_F(FrameIsdTest, Rotation_omegaPi_Center) { delete sensorModel; sensorModel = NULL; - } -TEST_F(FrameIsdTest, Rotation_NPole_Center) { - std::string key = "phi"; - std::ostringstream strval; - strval << std::setprecision(20) << -M_PI; - isd.clearParams(key); - isd.addParam(key,strval.str()); - key = "x_sensor_origin"; - std::string newValue = "0.0"; - isd.clearParams(key); - isd.addParam(key,newValue); - key = "y_sensor_origin"; - newValue = "0.0"; - isd.clearParams(key); - isd.addParam(key,newValue); - key = "z_sensor_origin"; - newValue = "1000.0"; - isd.clearParams(key); - isd.addParam(key,newValue); + +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 ASSERT_NE(sensorModel, nullptr); csm::ImageCoord imagePt(7.5, 7.5); @@ -686,27 +472,15 @@ TEST_F(FrameIsdTest, Rotation_NPole_Center) { delete sensorModel; sensorModel = NULL; - } -TEST_F(FrameIsdTest, Rotation_SPole_Center) { - std::string key = "phi"; - std::string newValue = "0.0"; - isd.clearParams(key); - isd.addParam(key,newValue); - key = "x_sensor_origin"; - newValue = "0.0"; - isd.clearParams(key); - isd.addParam(key,newValue); - key = "y_sensor_origin"; - newValue = "0.0"; - isd.clearParams(key); - isd.addParam(key,newValue); - key = "z_sensor_origin"; - newValue = "-1000.0"; - isd.clearParams(key); - isd.addParam(key,newValue); + +TEST_F(FrameIsdTest, Rotation_SPole_Center) { UsgsAstroFrameSensorModel* sensorModel = createModel(isd); + sensorModel->setParameterValue(4, 0.0); // phi + 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); @@ -717,60 +491,67 @@ TEST_F(FrameIsdTest, Rotation_SPole_Center) { delete sensorModel; sensorModel = NULL; - } // Ellipsoid axis tests: TEST_F(FrameIsdTest, SemiMajorAxis100x_Center) { - std::string key = "semi_major_axis"; - std::string newValue = "1.0"; - isd.clearParams(key); - isd.addParam(key,newValue); + 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 = createModel(isd); + ASSERT_NE(sensorModel, nullptr); + csm::ImageCoord imagePt(7.5, 7.5); + csm::EcefCoord groundPt = sensorModel->imageToGround(imagePt, 0.0); + EXPECT_NEAR(groundPt.x, 1000.0, 1e-8); + EXPECT_NEAR(groundPt.y, 0.0, 1e-8); + EXPECT_NEAR(groundPt.z, 0.0, 1e-8); - ASSERT_NE(sensorModel, nullptr); - csm::ImageCoord imagePt(7.5, 7.5); - csm::EcefCoord groundPt = sensorModel->imageToGround(imagePt, 0.0); - EXPECT_NEAR(groundPt.x, 1000.0, 1e-8); - EXPECT_NEAR(groundPt.y, 0.0, 1e-8); - EXPECT_NEAR(groundPt.z, 0.0, 1e-8); + delete sensorModel; + sensorModel = NULL; +} - delete sensorModel; - sensorModel = NULL; -} TEST_F(FrameIsdTest, SemiMajorAxis10x_SlightlyOffCenter) { - std::string key = "semi_major_axis"; - std::string newValue = "0.10"; - isd.clearParams(key); - isd.addParam(key,newValue); - - UsgsAstroFrameSensorModel* sensorModel = createModel(isd); - ASSERT_NE(sensorModel, nullptr); - csm::ImageCoord imagePt(7.5, 6.5); - csm::EcefCoord groundPt = sensorModel->imageToGround(imagePt, 0.0); - //Note: In the following, the tolerance was increased due to the combination of an offset image point and - // a very large deviation from sphericity. - 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); + 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()); + + ASSERT_NE(sensorModel, nullptr); + csm::ImageCoord imagePt(7.5, 6.5); + csm::EcefCoord groundPt = sensorModel->imageToGround(imagePt, 0.0); + // Note: In the following, the tolerance was increased due to the combination of an offset image point and + // a very large deviation from sphericity. + 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; +} - delete sensorModel; - sensorModel = NULL; -} // 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 = "semi_minor_axis"; - std::string newValue = "0.10"; - isd.clearParams(key); - isd.addParam(key,newValue); + 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()); ASSERT_NE(sensorModel, nullptr); csm::ImageCoord imagePt(7.5, 6.5); @@ -781,5 +562,4 @@ TEST_F(FrameIsdTest, SemiMinorAxis10x_SlightlyOffCenter) { delete sensorModel; sensorModel = NULL; - } diff --git a/tests/TestyMcTestFace.cpp b/tests/TestyMcTestFace.cpp index 20c569e..7b0696c 100644 --- a/tests/TestyMcTestFace.cpp +++ b/tests/TestyMcTestFace.cpp @@ -12,25 +12,10 @@ using json = nlohmann::json; class FrameIsdTest : public ::testing::Test { protected: - - csm::Isd isd; - - virtual void SetUp() { - std::ifstream isdFile("data/simpleFramerISD.json"); - json jsonIsd = json::parse(isdFile); - for (json::iterator it = jsonIsd.begin(); it != jsonIsd.end(); ++it) { - json jsonValue = it.value(); - if (jsonValue.size() > 1) { - for (int i = 0; i < jsonValue.size(); i++) { - isd.addParam(it.key(), jsonValue[i].dump()); - } - } - else { - isd.addParam(it.key(), jsonValue.dump()); - } - } - isdFile.close(); - } + csm::Isd isd; + virtual void SetUp() { + isd.setFilename("data/simpleFramerISD.img"); + }; }; TEST(FramePluginTests, PluginName) { -- GitLab