diff --git a/include/usgscsm/Distortion.h b/include/usgscsm/Distortion.h index 149e374c4dcf5ea83a6765227023a540ddfbd801..b324d4cc0c1445c0649a325669fb1e5b057ffc5b 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 150320bad31d0f549b8829456c83ba6ee39834a3..36ba65ef1384aa66c9c92e7637017615924c6cee 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 26c01df07b7112aec503bcd1e6b7dcc7e0f79152..67f80c084394f972dba2cb219aa9faf25726e872 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 44986ffe0f2735d4d13be77730feb0adc579d357..6177b347abef538ec8c1ba298f4f3601656cf3b2 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 fe4665585c6f0962c099d0ec20585e65dbe937a1..c59103828d75c377218d650d897deba501031795 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 26715ef0193b85232bfaa6cd13f7a852307bae9e..d39275b727ba291776d10d83ffe542e20bdae5da 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); +}