Unverified Commit 356a1dac authored by Kristin's avatar Kristin Committed by GitHub
Browse files

Adds ground to image and support functions. (#280)



* Non-compiling rough-draft of groundToImage and helper functions

* Merge with upstream changesa and add compiling version of groundtoimage

* Incremental improvements. Moved secant function back into previous function because two return values

* Compiles and some cleanup

* I might regret this, but pushed dopplerShiftFrequency calculation to a lambda fn and made secantRoot a function

* Clean up and move secantRoot to utilities. Add test. Update brentsMethod to take a lambda and update other code accordingly

* remove ooo

* Move bounds checking into secantRoot function and move exceptions around

* Replace placeholders with member variables.

* Add getRangeCoefficients function

* Update to include wavelength, add tests for functions, and fix broken functions based on tests

* Update g->i test with real line, samp image values and fix accidental copy-paste errors

* Tweaked ground to image

* Updated format and associated parsing of range coefficients and times

* Oops, missed some files last commit

* Add 0.5 offset to line calculation needed and update tests to add an Isis comparison test

* Updated Test SAR ISD

* Removed ISIS test and fixed ISD parsing test failure

Co-authored-by: default avatarJesse Mapel <jmapel@usgs.gov>
parent 1a792565
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -191,6 +191,16 @@ class UsgsAstroSarSensorModel : public csm::RasterGM, virtual public csm::Settab

    virtual void setEllipsoid(const csm::Ellipsoid &ellipsoid);

    double dopplerShift(csm::EcefCoord groundPt, double tolerance) const;

    double slantRange(csm::EcefCoord surfPt, double time) const;

    double slantRangeToGroundRange(const csm::EcefCoord& groundPt, double time, double slantRange, double tolerance) const;

    csm::EcefVector getSpacecraftPosition(double time) const;
    csm::EcefVector getSpacecraftVelocity(double time) const;
    std::vector<double> getRangeCoefficients(double time) const;

    ////////////////////////////
    // Model static variables //
    ////////////////////////////
@@ -216,6 +226,7 @@ class UsgsAstroSarSensorModel : public csm::RasterGM, virtual public csm::Settab
    double       m_scaledPixelWidth;
    double       m_startingEphemerisTime;
    double       m_centerEphemerisTime;
    double       m_endingEphemerisTime;
    double       m_majorAxis;
    double       m_minorAxis;
    std::string  m_platformIdentifier;
@@ -228,6 +239,7 @@ class UsgsAstroSarSensorModel : public csm::RasterGM, virtual public csm::Settab
    double       m_dtEphem;
    double       m_t0Ephem;
    std::vector<double> m_scaleConversionCoefficients;
    std::vector<double> m_scaleConversionTimes;
    std::vector<double> m_positions;
    std::vector<double> m_velocities;
    std::vector<double> m_currentParameterValue;
@@ -236,6 +248,7 @@ class UsgsAstroSarSensorModel : public csm::RasterGM, virtual public csm::Settab
    std::vector<double> m_covariance;
    std::vector<double> m_sunPosition;
    std::vector<double> m_sunVelocity;
    double m_wavelength;
};

#endif
+11 −2
Original line number Diff line number Diff line
@@ -74,9 +74,16 @@ void lagrangeInterp (
double brentRoot(
  double lowerBound,
  double upperBound,
  double (*func)(double),
  std::function<double(double)> func,
  double epsilon = 1e-10);

double secantRoot(
    double lowerBound,
    double upperBound,
    std::function<double(double)> func,
    double epsilon = 1e-10,
    int maxIterations = 30);

// Methods for checking/accessing the ISD

double metric_conversion(double val, std::string from, std::string to="m");
@@ -89,12 +96,14 @@ int getTotalLines(nlohmann::json isd, csm::WarningList *list=nullptr);
int getTotalSamples(nlohmann::json isd, csm::WarningList *list=nullptr);
double getStartingTime(nlohmann::json isd, csm::WarningList *list=nullptr);
double getCenterTime(nlohmann::json isd, csm::WarningList *list=nullptr);
double getEndingTime(nlohmann::json isd, csm::WarningList *list=nullptr);
std::vector<double> getIntegrationStartLines(nlohmann::json isd, csm::WarningList *list=nullptr);
std::vector<double> getIntegrationStartTimes(nlohmann::json isd, csm::WarningList *list=nullptr);
std::vector<double> getIntegrationTimes(nlohmann::json isd, csm::WarningList *list=nullptr);
double getExposureDuration(nlohmann::json isd, csm::WarningList *list=nullptr);
double getScaledPixelWidth(nlohmann::json isd, csm::WarningList *list=nullptr);
std::vector<double> getScaleConversionCoefficients(nlohmann::json isd, csm::WarningList *list=nullptr);
std::vector<double> getScaleConversionTimes(nlohmann::json isd, csm::WarningList *list=nullptr);
int getSampleSumming(nlohmann::json isd, csm::WarningList *list=nullptr);
int getLineSumming(nlohmann::json isd, csm::WarningList *list=nullptr);
double getFocalLength(nlohmann::json isd, csm::WarningList *list=nullptr);
@@ -117,5 +126,5 @@ std::vector<double> getSunVelocities(nlohmann::json isd, csm::WarningList *list=
std::vector<double> getSensorPositions(nlohmann::json isd, csm::WarningList *list=nullptr);
std::vector<double> getSensorVelocities(nlohmann::json isd, csm::WarningList *list=nullptr);
std::vector<double> getSensorOrientations(nlohmann::json isd, csm::WarningList *list=nullptr);

double getWavelength(nlohmann::json isd, csm::WarningList *list=nullptr);
#endif
+186 −5
Original line number Diff line number Diff line
#include "UsgsAstroSarSensorModel.h"
#include "Utilities.h"

#include <functional>
#include <iomanip>
#include <string.h>
#include <cmath>

#include <json/json.hpp>

using json = nlohmann::json;
using namespace std;

#define MESSAGE_LOG(logger, ...) if (logger) { logger->info(__VA_ARGS__); }

const string UsgsAstroSarSensorModel::_SENSOR_MODEL_NAME = "USGS_ASTRO_SAR_SENSOR_MODEL";
const int UsgsAstroSarSensorModel::NUM_PARAMETERS = 6;
const string UsgsAstroSarSensorModel::PARAMETER_NAME[] =
@@ -63,6 +68,7 @@ string UsgsAstroSarSensorModel::constructStateFromIsd(

  state["m_centerEphemerisTime"] = getCenterTime(isd, parsingWarnings);
  state["m_startingEphemerisTime"] = getStartingTime(isd, parsingWarnings);
  state["m_endingEphemerisTime"] = getEndingTime(isd, parsingWarnings);

  state["m_exposureDuration"] = getExposureDuration(isd, parsingWarnings);

@@ -108,6 +114,8 @@ string UsgsAstroSarSensorModel::constructStateFromIsd(
  // SAR specific values
  state["m_scaledPixelWidth"] = getScaledPixelWidth(isd, parsingWarnings);
  state["m_scaleConversionCoefficients"] = getScaleConversionCoefficients(isd, parsingWarnings);
  state["m_scaleConversionTimes"] = getScaleConversionTimes(isd, parsingWarnings);
  state["m_wavelength"] = getWavelength(isd, parsingWarnings);

  // Default to identity covariance
  state["m_covariance"] =
@@ -120,10 +128,14 @@ string UsgsAstroSarSensorModel::constructStateFromIsd(
    if (warnings) {
      warnings->insert(warnings->end(), parsingWarnings->begin(), parsingWarnings->end());
    }
    delete parsingWarnings;
    std::string message = "ISD is invalid for creating the sensor model with error [";
    csm::Warning warn = parsingWarnings->front();
    message += warn.getMessage();
    message += "]";
    parsingWarnings = nullptr;
    delete parsingWarnings;
    throw csm::Error(csm::Error::SENSOR_MODEL_NOT_CONSTRUCTIBLE,
                     "ISD is invalid for creating the sensor model.",
                     message,
                     "UsgsAstroSarSensorModel::constructStateFromIsd");
  }

@@ -178,6 +190,7 @@ void UsgsAstroSarSensorModel::reset()
  m_scaledPixelWidth = 0;
  m_startingEphemerisTime = 0;
  m_centerEphemerisTime = 0;
  m_endingEphemerisTime = 0;
  m_majorAxis = 0;
  m_minorAxis = 0;
  m_platformIdentifier = "Unknown";
@@ -189,6 +202,7 @@ void UsgsAstroSarSensorModel::reset()
  m_dtEphem = 0;
  m_t0Ephem = 0;
  m_scaleConversionCoefficients.clear();
  m_scaleConversionTimes.clear();
  m_positions.clear();
  m_velocities.clear();
  m_currentParameterValue = vector<double>(NUM_PARAMETERS, 0.0);
@@ -199,6 +213,7 @@ void UsgsAstroSarSensorModel::reset()
  m_covariance = vector<double>(NUM_PARAMETERS * NUM_PARAMETERS,0.0);
  m_sunPosition.clear();
  m_sunVelocity.clear();
  m_wavelength = 0;
}

void UsgsAstroSarSensorModel::replaceModelState(const string& argState)
@@ -214,8 +229,10 @@ void UsgsAstroSarSensorModel::replaceModelState(const string& argState)
  m_nSamples = stateJson["m_nSamples"];
  m_exposureDuration = stateJson["m_exposureDuration"];
  m_scaledPixelWidth = stateJson["m_scaledPixelWidth"];
  m_wavelength = stateJson["m_wavelength"];
  m_startingEphemerisTime = stateJson["m_startingEphemerisTime"];
  m_centerEphemerisTime = stateJson["m_centerEphemerisTime"];
  m_endingEphemerisTime = stateJson["m_endingEphemerisTime"];
  m_majorAxis = stateJson["m_majorAxis"];
  m_minorAxis = stateJson["m_minorAxis"];
  m_platformIdentifier = stateJson["m_platformIdentifier"].get<string>();
@@ -225,6 +242,7 @@ void UsgsAstroSarSensorModel::replaceModelState(const string& argState)
  m_dtEphem = stateJson["m_dtEphem"];
  m_t0Ephem = stateJson["m_t0Ephem"];
  m_scaleConversionCoefficients = stateJson["m_scaleConversionCoefficients"].get<vector<double>>();
  m_scaleConversionTimes = stateJson["m_scaleConversionTimes"].get<vector<double>>();
  m_positions = stateJson["m_positions"].get<vector<double>>();
  m_velocities = stateJson["m_velocities"].get<vector<double>>();
  m_currentParameterValue = stateJson["m_currentParameterValue"].get<vector<double>>();
@@ -255,6 +273,7 @@ string UsgsAstroSarSensorModel::getModelState() const
  state["m_sunVelocity"] = m_sunVelocity;
  state["m_centerEphemerisTime"] = m_centerEphemerisTime;
  state["m_startingEphemerisTime"] = m_startingEphemerisTime;
  state["m_endingEphemerisTime"] = m_endingEphemerisTime;
  state["m_exposureDuration"] = m_exposureDuration;
  state["m_dtEphem"] = m_dtEphem;
  state["m_t0Ephem"] = m_t0Ephem;
@@ -268,23 +287,117 @@ string UsgsAstroSarSensorModel::getModelState() const
  state["m_minElevation"] = m_minElevation;
  state["m_maxElevation"] = m_maxElevation;
  state["m_scaledPixelWidth"] = m_scaledPixelWidth;
  state["m_wavelength"] = m_wavelength;
  state["m_scaleConversionCoefficients"] = m_scaleConversionCoefficients;
  state["m_scaleConversionTimes"] = m_scaleConversionTimes;
  state["m_covariance"] = m_covariance;

  return state.dump();
}



csm::ImageCoord UsgsAstroSarSensorModel::groundToImage(
    const csm::EcefCoord& groundPt,
    double desiredPrecision,
    double* achievedPrecision,
    csm::WarningList* warnings) const
    csm::WarningList* warnings) const {

  //MESSAGE_LOG(this->m_logger, "Computing groundToImage(ImageCoord) for {}, {}, {}, with desired precision {}",
  //          groundPt.x, groundPt.y, groundPt.z, desiredPrecision);

  // Find time of closest approach to groundPt and the corresponding slant range by finding
  // the root of the doppler shift frequency
  try {
    double timeTolerance = m_exposureDuration * desiredPrecision / 2.0;
    double time = dopplerShift(groundPt, timeTolerance);
    double slantRangeValue = slantRange(groundPt, time);

    // Find the ground range, based on the ground-range-to-slant-range polynomial defined by the
    // range coefficient set, with a time closest to the calculated time of closest approach
    double groundTolerance = m_scaledPixelWidth * desiredPrecision / 2.0;
    double groundRange = slantRangeToGroundRange(groundPt, time, slantRangeValue, groundTolerance);

    double line = (time - m_startingEphemerisTime) / m_exposureDuration + 0.5;
    double sample = groundRange / m_scaledPixelWidth;
    return csm::ImageCoord(line, sample);
  } catch (std::exception& error) {
    std::string message = "Could not calculate groundToImage, with error [";
    message += error.what();
    message += "]";
    throw csm::Error(csm::Error::UNKNOWN_ERROR, message, "groundToImage");
  }
}

// Calculate the root
double UsgsAstroSarSensorModel::dopplerShift(
    csm::EcefCoord groundPt,
    double tolerance) const
{
  return csm::ImageCoord(0.0, 0.0);
   std::function<double(double)> dopplerShiftFunction = [this, groundPt](double time) {
     csm::EcefVector spacecraftPosition = getSpacecraftPosition(time);
     csm::EcefVector spacecraftVelocity = getSpacecraftVelocity(time);
     double lookVector[3];

     lookVector[0] = spacecraftPosition.x - groundPt.x;
     lookVector[1] = spacecraftPosition.y - groundPt.y;
     lookVector[2] = spacecraftPosition.z - groundPt.z;

     double slantRange = sqrt(pow(lookVector[0], 2) +  pow(lookVector[1], 2) + pow(lookVector[2], 2));


     double dopplerShift = -2.0 * (lookVector[0]*spacecraftVelocity.x + lookVector[1]*spacecraftVelocity.y
                            + lookVector[2]*spacecraftVelocity.z)/(slantRange * m_wavelength);

     return dopplerShift;
   };

  // Do root-finding for "dopplerShift"
  return brentRoot(m_startingEphemerisTime, m_endingEphemerisTime, dopplerShiftFunction, tolerance);
}


double UsgsAstroSarSensorModel::slantRange(csm::EcefCoord surfPt,
    double time) const
{
  csm::EcefVector spacecraftPosition = getSpacecraftPosition(time);
  double lookVector[3];

  lookVector[0] = spacecraftPosition.x - surfPt.x;
  lookVector[1] = spacecraftPosition.y - surfPt.y;
  lookVector[2] = spacecraftPosition.z - surfPt.z;
  return sqrt(pow(lookVector[0], 2) +  pow(lookVector[1], 2) + pow(lookVector[2], 2));
}

double UsgsAstroSarSensorModel::slantRangeToGroundRange(
    const csm::EcefCoord& groundPt,
    double time,
    double slantRange,
    double tolerance) const
{
  std::vector<double> coeffs = getRangeCoefficients(time);

  // Calculates the ground range from the slant range.
  std::function<double(double)> slantRangeToGroundRangeFunction =
    [coeffs, slantRange](double groundRange){
   return slantRange - (coeffs[0] + groundRange * (coeffs[1] + groundRange * (coeffs[2] + groundRange * coeffs[3])));
  };

  // Need to come up with an initial guess when solving for ground
  // range given slant range. Compute the ground range at the
  // near and far edges of the image by evaluating the sample-to-
  // ground-range equation: groundRange=(sample-1)*scaled_pixel_width
  // at the edges of the image. We also need to add some padding to
  // allow for solving for coordinates that are slightly outside of
  // the actual image area. Use sample=-0.25*image_samples and
  // sample=1.25*image_samples.
  double minGroundRangeGuess = (-0.25 * m_nSamples - 1.0) * m_scaledPixelWidth;
  double maxGroundRangeGuess = (1.25 * m_nSamples - 1.0) * m_scaledPixelWidth;

  // Tolerance to 1/20th of a pixel for now.
  return brentRoot(minGroundRangeGuess, maxGroundRangeGuess, slantRangeToGroundRangeFunction, tolerance);
}


csm::ImageCoordCovar UsgsAstroSarSensorModel::groundToImage(
    const csm::EcefCoordCovar& groundPt,
    double desiredPrecision,
@@ -657,3 +770,71 @@ void UsgsAstroSarSensorModel::setEllipsoid(const csm::Ellipsoid &ellipsoid)
   m_majorAxis = ellipsoid.getSemiMajorRadius();
   m_minorAxis = ellipsoid.getSemiMinorRadius();
}

csm::EcefVector UsgsAstroSarSensorModel::getSpacecraftPosition(double time) const{
  int numPositions = m_positions.size();
  csm::EcefVector spacecraftPosition = csm::EcefVector();

  // If there are multiple positions, use Lagrange interpolation
  if ((numPositions/3) > 1) {
    double position[3];
    lagrangeInterp(numPositions/3, &m_positions[0], m_t0Ephem, m_dtEphem,
                   time, 3, 8, position);
    spacecraftPosition.x = position[0];
    spacecraftPosition.y = position[1];
    spacecraftPosition.z = position[2];
  }
  else {
    spacecraftPosition.x = m_positions[0];
    spacecraftPosition.y = m_positions[1];
    spacecraftPosition.z = m_positions[2];
  }
  // Can add third case if need be, but seems unlikely to come up for SAR
  return spacecraftPosition;
}

csm::EcefVector UsgsAstroSarSensorModel::getSpacecraftVelocity(double time) const {
  int numVelocities = m_velocities.size();
  csm::EcefVector spacecraftVelocity = csm::EcefVector();

  // If there are multiple positions, use Lagrange interpolation
  if ((numVelocities/3) > 1) {
    double velocity[3];
    lagrangeInterp(numVelocities/3, &m_velocities[0], m_t0Ephem, m_dtEphem,
                   time, 3, 8, velocity);
    spacecraftVelocity.x = velocity[0];
    spacecraftVelocity.y = velocity[1];
    spacecraftVelocity.z = velocity[2];
  }
  else {
    spacecraftVelocity.x = m_velocities[0];
    spacecraftVelocity.y = m_velocities[1];
    spacecraftVelocity.z = m_velocities[2];
  }
  return spacecraftVelocity;
}


std::vector<double> UsgsAstroSarSensorModel::getRangeCoefficients(double time) const {
  int numCoeffs = m_scaleConversionCoefficients.size();
  std::vector<double> interpCoeffs;

  double endTime = m_scaleConversionTimes.back();
  if ((numCoeffs/4) > 1) {
    double coefficients[4];
    double dtEphem = (endTime - m_scaleConversionTimes[0]) / (m_scaleConversionCoefficients.size()/4);
    lagrangeInterp(m_scaleConversionCoefficients.size()/4, &m_scaleConversionCoefficients[0], m_scaleConversionTimes[0], dtEphem,
                   time, 4, 8, coefficients);
    interpCoeffs.push_back(coefficients[0]);
    interpCoeffs.push_back(coefficients[1]);
    interpCoeffs.push_back(coefficients[2]);
    interpCoeffs.push_back(coefficients[3]);
  }
  else {
    interpCoeffs.push_back(m_scaleConversionCoefficients[0]);
    interpCoeffs.push_back(m_scaleConversionCoefficients[1]);
    interpCoeffs.push_back(m_scaleConversionCoefficients[2]);
    interpCoeffs.push_back(m_scaleConversionCoefficients[3]);
  }
  return interpCoeffs;
}
+121 −5
Original line number Diff line number Diff line
@@ -280,14 +280,14 @@ void lagrangeInterp(
double brentRoot(
  double lowerBound,
  double upperBound,
  double (*func)(double),
  std::function<double(double)> func,
  double epsilon) {
    double counterPoint = lowerBound;
    double currentPoint = upperBound;
    double counterFunc = func(counterPoint);
    double currentFunc = func(currentPoint);
    if (counterFunc * currentFunc > 0.0) {
      throw std::invalid_argument("Function values at the boundaries have the same sign.");
      throw std::invalid_argument("Function values at the boundaries have the same sign [brentRoot].");
    }
    if (fabs(counterFunc) < fabs(currentFunc)) {
      std::swap(counterPoint, currentPoint);
@@ -304,7 +304,7 @@ double brentRoot(

    do {
      // Inverse quadratic interpolation
      if (counterFunc != previousFunc && counterFunc != currentFunc) {
      if (counterFunc != previousFunc && counterFunc != currentFunc && currentFunc != previousFunc) {
        nextPoint = (counterPoint * currentFunc * previousFunc) / ((counterFunc - currentFunc) * (counterFunc - previousFunc));
        nextPoint += (currentPoint * counterFunc * previousFunc) / ((currentFunc - counterFunc) * (currentFunc - previousFunc));
        nextPoint += (previousPoint * currentFunc * counterFunc) / ((previousFunc - counterFunc) * (previousFunc - currentFunc));
@@ -345,6 +345,66 @@ double brentRoot(
    return nextPoint;
  }

double secantRoot(double lowerBound, double upperBound, std::function<double(double)> func,
                  double epsilon, int maxIters) {
  bool found = false;

  double x0 = lowerBound;
  double x1 = upperBound;
  double f0 = func(x0);
  double f1 = func(x1);
  double diff = 0;
  double x2 = 0;
  double f2 = 0;

  std::cout << "f0, f1: " << f0 << ", " << f1 << std::endl;

  // Make sure we bound the root (f = 0.0)
  if (f0 * f1 > 0.0) {
    throw std::invalid_argument("Function values at the boundaries have the same sign [secantRoot].");
  }

  // Order the bounds
  if (f1 < f0) {
    std::swap(x0, x1);
    std::swap(f0, f1);
  }

  for (int iteration=0; iteration < maxIters; iteration++) {
    x2 = x1 - f1 * (x1 - x0)/(f1 - f0);
    f2 = func(x2);

    // Update the bounds for the next iteration
    if (f2 < 0.0) {
      diff = x1 - x2;
      x1 = x2;
      f1 = f2;
    }
    else {
      diff = x0 - x2;
      x0 = x2;
      f0 = f2;
    }

    // Check to see if we're done
    if ((fabs(diff) <= epsilon) || (f2 == 0.0) ) {
      found = true;
      break;
    }
  }

  if (found) {
   return x2;
  }
  else {
    throw csm::Error(
    csm::Error::UNKNOWN_ERROR,
    "Could not find a root of the function using the secant method",
    "secantRoot");
  }
}


// convert a measurement
double metric_conversion(double val, std::string from, std::string to) {
    json typemap = {
@@ -512,6 +572,23 @@ double getCenterTime(json isd, csm::WarningList *list) {
  return time;
}

double getEndingTime(json isd, csm::WarningList *list) {
  double time = 0.0;
  try {
    time = isd.at("ending_ephemeris_time");
  }
  catch (...) {
    if (list) {
      list->push_back(
        csm::Warning(
          csm::Warning::DATA_NOT_AVAILABLE,
          "Could not parse the ending image time.",
          "Utilities::getEndingTime()"));
    }
  }
  return time;
}

std::vector<double> getIntegrationStartLines(json isd, csm::WarningList *list) {
  std::vector<double> lines;
  try {
@@ -1138,19 +1215,58 @@ double getScaledPixelWidth(nlohmann::json isd, csm::WarningList *list) {
  return width;
}

std::vector<double> getScaleConversionTimes(nlohmann::json isd, csm::WarningList *list) {
  std::vector<double> time;
  try {
    time = isd.at("range_conversion_times").get<std::vector<double>>();
  }
  catch (...) {
    if (list) {
      list->push_back(
        csm::Warning(
          csm::Warning::DATA_NOT_AVAILABLE,
          "Could not parse the range conversion times.",
          "Utilities::getScaleConversionTimes()"));
    }
  }
  return time;
}

std::vector<double> getScaleConversionCoefficients(nlohmann::json isd, csm::WarningList *list) {
  std::vector<double> coefficients;
  try {
    coefficients = isd.at("range_conversion_coefficients").get<std::vector<double>>();
   for (auto& location : isd.at("range_conversion_coefficients")){
     coefficients.push_back(location[0]);
     coefficients.push_back(location[1]);
     coefficients.push_back(location[2]);
     coefficients.push_back(location[3]);
    }
  }
  catch (...) {
    if (list) {
      list->push_back(
        csm::Warning(
          csm::Warning::DATA_NOT_AVAILABLE,
          "Could not parse the range conversion coefficients and times.",
          "Could not parse the range conversion coefficients.",
          "Utilities::getScaleConversionCoefficients()"));
    }
  }
  return coefficients;
}

double getWavelength(json isd, csm::WarningList *list) {
  double wavelength = 0.0;
  try {
    wavelength = isd.at("wavelength");
  }
  catch (...) {
    if (list) {
      list->push_back(
        csm::Warning(
          csm::Warning::DATA_NOT_AVAILABLE,
          "Could not parse the wavelength.",
          "Utilities::getWavelength()"));
    }
  }
  return wavelength;
}
+26 −0
Original line number Diff line number Diff line
@@ -319,4 +319,30 @@ class SarIsdTest : public ::testing::Test {
   }
};

class SarSensorModel : public ::testing::Test {
   protected:
      csm::Isd isd;
      UsgsAstroSarSensorModel *sensorModel;

      void SetUp() override {
         sensorModel = NULL;

         isd.setFilename("data/orbitalSar.img");
         UsgsAstroPlugin sarCameraPlugin;

         csm::Model *model = sarCameraPlugin.constructModelFromISD(
               isd,
               "USGS_ASTRO_SAR_SENSOR_MODEL");
         sensorModel = dynamic_cast<UsgsAstroSarSensorModel *>(model);
         ASSERT_NE(sensorModel, nullptr);
      }

      void TearDown() override {
         if (sensorModel) {
            delete sensorModel;
            sensorModel = NULL;
         }
      }
};

#endif
Loading