From 6448168536ac98f781dd0c9618694e836bd9c3e9 Mon Sep 17 00:00:00 2001 From: acpaquette <acpaquette@usgs.gov> Date: Thu, 25 Apr 2019 12:22:18 -0700 Subject: [PATCH] Dawn Distortion (#231) * Added more logging to various functions * Updated distortion and warning parseing * Removed duplicate distortion models for kaguya * Adds the dawn radial distortion model * Updated comments in distortion and the line scanner * Updated dawn distortion logic * Removed duplicate logging statement in the frame sensor * Updated dawn distortion model and added tests --- include/usgscsm/Distortion.h | 3 +- src/Distortion.cpp | 64 +++++++++++++++++++++++++++++++ src/UsgsAstroFrameSensorModel.cpp | 4 +- src/UsgsAstroLsSensorModel.cpp | 22 +++++++++-- src/Utilities.cpp | 21 ++++++++++ tests/DistortionTests.cpp | 28 ++++++++++++++ 6 files changed, 135 insertions(+), 7 deletions(-) diff --git a/include/usgscsm/Distortion.h b/include/usgscsm/Distortion.h index 149e374..b324d4c 100644 --- a/include/usgscsm/Distortion.h +++ b/include/usgscsm/Distortion.h @@ -9,7 +9,8 @@ enum DistortionType { RADIAL, TRANSVERSE, - KAGUYATC + KAGUYATC, + DAWNFC }; // Transverse Distortion diff --git a/src/Distortion.cpp b/src/Distortion.cpp index 150320b..36ba65e 100644 --- a/src/Distortion.cpp +++ b/src/Distortion.cpp @@ -200,6 +200,58 @@ void removeDistortion(double dx, double dy, double &ux, double &uy, ux = dx + dr_x; uy = dy + dr_y; } + break; + // The dawn distortion model is "reversed" from other distortion models so + // the remove function iteratively computes undistorted coordinates based on + // the distorted coordinates, rather than iteratively computing distorted coordinates + // to undistorted coordinates. + case DAWNFC: { + double r2; + int numAttempts = 1; + bool done; + + /**************************************************************************** + * Pre-loop intializations + ****************************************************************************/ + + r2 = dy * dy + dx * dx; + double guess_dx, guess_dy; + double guess_ux, guess_uy; + + /**************************************************************************** + * Loop ... + ****************************************************************************/ + do { + guess_ux = dx / (1.0 + opticalDistCoeffs[0] * r2); + guess_uy = dy / (1.0 + opticalDistCoeffs[0] * r2); + + r2 = guess_uy * guess_uy + guess_ux * guess_ux; + + guess_dx = guess_ux * (1.0 + opticalDistCoeffs[0] * r2); + guess_dy = guess_uy * (1.0 + opticalDistCoeffs[0] * r2); + + done = false; + + if (abs(guess_dx - dx) < tolerance && abs(guess_dy - dy) < tolerance) { + done = true; + } + + /* Not converging so bomb */ + numAttempts++; + if(numAttempts > 20) { + std::cout << "Didn't converge" << std::endl; + return; + } + } + while(!done); + + /**************************************************************************** + * Sucess ... + ****************************************************************************/ + + ux = guess_ux; + uy = guess_uy; + } } } @@ -324,5 +376,17 @@ void applyDistortion(double ux, double uy, double &dx, double &dy, dy = ydistorted; } } + break; + // The dawn distortion model is "reversed" from other distortion models so + // the apply function computes distorted coordinates as a + // fn(undistorted coordinates) + case DAWNFC: { + double r2; + + r2 = ux * ux + uy * uy; + + dx = ux * (1.0 + opticalDistCoeffs[0] * r2); + dy = uy * (1.0 + opticalDistCoeffs[0] * r2); + } } } diff --git a/src/UsgsAstroFrameSensorModel.cpp b/src/UsgsAstroFrameSensorModel.cpp index 26c01df..67f80c0 100644 --- a/src/UsgsAstroFrameSensorModel.cpp +++ b/src/UsgsAstroFrameSensorModel.cpp @@ -941,8 +941,8 @@ std::string UsgsAstroFrameSensorModel::constructStateFromIsd(const std::string& } // get optical_distortion - state["m_distortionType"] = getDistortionModel(isd); - state["m_opticalDistCoeffs"] = getDistortionCoeffs(isd); + state["m_distortionType"] = getDistortionModel(isd, warnings); + state["m_opticalDistCoeffs"] = getDistortionCoeffs(isd, warnings); // get detector_center state["m_ccdCenter"][0] = getDetectorCenterLine(isd, parsingWarnings); diff --git a/src/UsgsAstroLsSensorModel.cpp b/src/UsgsAstroLsSensorModel.cpp index 44986ff..6177b34 100644 --- a/src/UsgsAstroLsSensorModel.cpp +++ b/src/UsgsAstroLsSensorModel.cpp @@ -2865,11 +2865,25 @@ std::string UsgsAstroLsSensorModel::constructStateFromIsd(const std::string imag } // Get the optional logging file - state["m_logFile"] = getLogFile(isd); + state["m_logFile"] = getLogFile(isd, warnings); - // 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(); + if (!parsingWarnings->empty()) { + if (warnings) { + warnings->insert(warnings->end(), parsingWarnings->begin(), parsingWarnings->end()); + } + delete parsingWarnings; + parsingWarnings = nullptr; + throw csm::Error(csm::Error::SENSOR_MODEL_NOT_CONSTRUCTIBLE, + "ISD is invalid for creating the sensor model.", + "UsgsAstroFrameSensorModel::constructStateFromIsd"); + } + + delete parsingWarnings; + parsingWarnings = nullptr; + + // The state data will still be updated when a sensor model is created since + // some state data is not in the ISD and requires a SM to compute them. + return state.dump(); } diff --git a/src/Utilities.cpp b/src/Utilities.cpp index fe46655..c591038 100644 --- a/src/Utilities.cpp +++ b/src/Utilities.cpp @@ -766,6 +766,9 @@ DistortionType getDistortionModel(json isd, csm::WarningList *list) { else if (distortion.compare("kaguyatc") == 0) { return DistortionType::KAGUYATC; } + else if (distortion.compare("dawnfc") == 0) { + return DistortionType::DAWNFC; + } } catch (...) { if (list) { @@ -855,7 +858,25 @@ std::vector<double> getDistortionCoeffs(json isd, csm::WarningList *list) { coefficients = std::vector<double>(8, 0.0); } } + break; + case DistortionType::DAWNFC: { + try { + coefficients = isd.at("optical_distortion").at("dawnfc").at("coefficients").get<std::vector<double>>(); + return coefficients; + } + catch (...) { + if (list) { + list->push_back( + csm::Warning( + csm::Warning::DATA_NOT_AVAILABLE, + "Could not parse the dawn radial distortion model coefficients.", + "Utilities::getDistortion()")); + } + coefficients = std::vector<double>(1, 0.0); + } + } + break; } if (list) { list->push_back( diff --git a/tests/DistortionTests.cpp b/tests/DistortionTests.cpp index 26715ef..d39275b 100644 --- a/tests/DistortionTests.cpp +++ b/tests/DistortionTests.cpp @@ -149,3 +149,31 @@ TEST(Radial, testInverseOnesCoeffs){ EXPECT_NEAR(dx,4,1e-8); EXPECT_NEAR(dy,0,1e-8); } + +TEST(DawnFc, testApply) { + csm::ImageCoord imagePt(10.0, 10.0); + + double dx, dy; + double desiredPrecision = 0.0000001; + std::vector<double> coeffs = {8.4e-06}; + + applyDistortion(imagePt.samp, imagePt.line, dx, dy, coeffs, + DistortionType::DAWNFC, desiredPrecision); + + EXPECT_NEAR(dx, 10.0168, 1e-8); + EXPECT_NEAR(dy, 10.0168, 1e-8); +} + +TEST(DawnFc, testRemove) { + csm::ImageCoord imagePt(10.0168, 10.0168); + + double ux, uy; + double desiredPrecision = 0.0000001; + std::vector<double> coeffs = {8.4e-06}; + + removeDistortion(imagePt.samp, imagePt.line, ux, uy, coeffs, + DistortionType::DAWNFC, desiredPrecision); + + EXPECT_NEAR(ux,10.0,1e-8); + EXPECT_NEAR(uy,10.0,1e-8); +} -- GitLab