Skip to content
Snippets Groups Projects
Unverified Commit 56bbb366 authored by Oleg Alexandrov's avatar Oleg Alexandrov Committed by GitHub
Browse files

Add fix for ground to image calculation for LRO NAC cameras (#341)


* Add fix for ground to image calculation for LRO NAC cameras

* Make the choice of the sign of m_iTransL only once at model loading

* Reword a comment

* Robustness fix, must always ensure fractional part is 0.5

* Remove the abs, cannot assume those values are positive

* Added opposite flight and detector test

Co-authored-by: default avatarJesse Mapel <jmapel@usgs.gov>
parent 9414c80a
No related branches found
No related tags found
No related merge requests found
...@@ -648,6 +648,36 @@ void UsgsAstroLsSensorModel::updateState() { ...@@ -648,6 +648,36 @@ void UsgsAstroLsSensorModel::updateState() {
// Set focal length variance // Set focal length variance
m_covariance[15 * num_params + 15] = positionVariance; m_covariance[15 * num_params + 15] = positionVariance;
// Test if a pixel projected to the ground and projected back
// returns to the original location. If not, flip the sign of
// m_iTransL. It is very important here to pick a pixel which is not
// an integer, as this test may succeed for integer pixels and fail
// for non-integer ones. Also, need to pick the answer with the
// smallest achieved precision, even when neither of them is smaller
// than the desired precision.
lineCtr = round(m_nLines / 2.0) + 0.5;
sampCtr = round(m_nSamples / 2.0) + 0.5;
double desiredPrecision = 0.001;
ip = csm::ImageCoord(lineCtr, sampCtr);
csm::EcefCoord xyz = imageToGround(ip, refHeight);
double achievedPrecision1 = 1.0;
// Will use m_iTransL on the next line
ip = groundToImage(xyz, desiredPrecision, &achievedPrecision1);
double achievedPrecision2 = 1.0;
for (int it = 0; it < sizeof(m_iTransL)/sizeof(double); it++)
m_iTransL[it] = -m_iTransL[it]; // use a flipped m_iTransL
ip = groundToImage(xyz, desiredPrecision, &achievedPrecision2);
if (std::abs(achievedPrecision1) <= std::abs(achievedPrecision2)) {
// Flip back m_iTransL as the original was better
for (int it = 0; it < sizeof(m_iTransL)/sizeof(double); it++)
m_iTransL[it] = -m_iTransL[it];
}
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
...@@ -2045,7 +2075,7 @@ std::vector<double> UsgsAstroLsSensorModel::computeDetectorView( ...@@ -2045,7 +2075,7 @@ std::vector<double> UsgsAstroLsSensorModel::computeDetectorView(
bodyToCamera[5] * bodyLookY + bodyToCamera[5] * bodyLookY +
bodyToCamera[8] * bodyLookZ; bodyToCamera[8] * bodyLookZ;
MESSAGE_LOG( MESSAGE_LOG(
"computeDetectorView: look vector (camrea ref frame)" "computeDetectorView: look vector (camera ref frame)"
"{} {} {}", "{} {} {}",
cameraLookX, cameraLookY, cameraLookZ) cameraLookX, cameraLookY, cameraLookZ)
......
...@@ -261,6 +261,32 @@ class OrbitalLineScanSensorModel : public ::testing::Test { ...@@ -261,6 +261,32 @@ class OrbitalLineScanSensorModel : public ::testing::Test {
} }
}; };
class FlippedOrbitalLineScanSensorModel : public ::testing::Test {
protected:
csm::Isd isd;
UsgsAstroLsSensorModel *sensorModel;
void SetUp() override {
sensorModel = NULL;
isd.setFilename("data/flippedOrbitalLineScan.img");
UsgsAstroPlugin cameraPlugin;
csm::Model *model = cameraPlugin.constructModelFromISD(
isd, "USGS_ASTRO_LINE_SCANNER_SENSOR_MODEL");
sensorModel = dynamic_cast<UsgsAstroLsSensorModel *>(model);
ASSERT_NE(sensorModel, nullptr);
}
void TearDown() override {
if (sensorModel) {
delete sensorModel;
sensorModel = NULL;
}
}
};
class TwoLineScanSensorModels : public ::testing::Test { class TwoLineScanSensorModels : public ::testing::Test {
protected: protected:
csm::Isd isd; csm::Isd isd;
......
...@@ -276,6 +276,14 @@ TEST_F(OrbitalLineScanSensorModel, ReferenceDateTime) { ...@@ -276,6 +276,14 @@ TEST_F(OrbitalLineScanSensorModel, ReferenceDateTime) {
EXPECT_EQ(date, "2000-01-01T00:16:39Z"); EXPECT_EQ(date, "2000-01-01T00:16:39Z");
} }
TEST_F(FlippedOrbitalLineScanSensorModel, OppositeFlightDetector) {
csm::ImageCoord imagePt(8.7, 8.0);
csm::EcefCoord groundPt = sensorModel->imageToGround(imagePt, 0.0);
csm::ImageCoord backProjImagePt = sensorModel->groundToImage(groundPt);
EXPECT_NEAR(imagePt.line, backProjImagePt.line, 0.001);
EXPECT_NEAR(imagePt.samp, backProjImagePt.samp, 0.001);
}
TEST_F(TwoLineScanSensorModels, CrossCovariance) { TEST_F(TwoLineScanSensorModels, CrossCovariance) {
std::vector<double> crossCovars = std::vector<double> crossCovars =
sensorModel1->getCrossCovarianceMatrix(*sensorModel2); sensorModel1->getCrossCovarianceMatrix(*sensorModel2);
......
{
"name_model" : "USGS_ASTRO_LINE_SCANNER_SENSOR_MODEL",
"name_platform" : "TEST_PLATFORM",
"name_sensor" : "TEST_SENSOR",
"center_ephemeris_time": 1000.0,
"starting_ephemeris_time": 999.2,
"line_scan_rate": [
[0.5, -0.85, 0.1]
],
"detector_sample_summing": 1,
"detector_line_summing": 1,
"t0_ephemeris": -0.8,
"dt_ephemeris": 0.1,
"t0_quaternion": -0.8,
"dt_quaternion": 0.1,
"focal2pixel_lines": [0.0, 10.0, 0.0],
"focal2pixel_samples": [0.0, 0.0, 10.0],
"focal_length_model": {
"focal_length": 50
},
"image_lines": 16,
"image_samples": 16,
"detector_center" : {
"line" : 0.5,
"sample" : 8.0
},
"interpolation_method": "lagrange",
"optical_distortion": {
"radial": {
"coefficients": [0.0, 0.0, 0.0]
}
},
"radii": {
"semimajor": 1000,
"semiminor": 1000,
"unit":"km"
},
"reference_height": {
"maxheight": 1000,
"minheight": -1000,
"unit": "m"
},
"instrument_position": {
"unit": "km",
"positions": [
[1050.0, 0.0, -0.0],
[1049.99999524, 0.0, -0.1],
[1049.99998095, 0.0, -0.2],
[1049.99995714, 0.0, -0.3],
[1049.99992381, 0.0, -0.39999999],
[1049.99988095, 0.0, -0.49999998],
[1049.99982857, 0.0, -0.59999997],
[1049.99976667, 0.0, -0.69999995],
[1049.99969524, 0.0, -0.79999992],
[1049.99961429, 0.0, -0.89999989],
[1049.99952381, 0.0, -0.99999985],
[1049.99942381, 0.0, -1.0999998],
[1049.99931429, 0.0, -1.19999974],
[1049.99919524, 0.0, -1.29999967],
[1049.99906667, 0.0, -1.39999959],
[1049.99892857, 0.0, -1.49999949]
],
"velocities": [
[-0.0, 0.0, -1.0500],
[-0.1, 0.0, -1.04999999524],
[-0.2, 0.0, -1.04999998095],
[-0.3, 0.0, -1.04999995714],
[-0.39999999, 0.0 ,-1.04999992381],
[-0.49999998, 0.0 ,-1.04999988095],
[-0.59999997, 0.0 ,-1.04999982857],
[-0.69999995, 0.0 ,-1.04999976667],
[-0.79999992, 0.0 ,-1.04999969524],
[-0.89999989, 0.0 ,-1.04999961429],
[-0.99999985, 0.0 ,-1.04999952381],
[-1.0999998, 0.0 ,-1.04999942381],
[-1.19999974, 0.0 ,-1.04999931429],
[-1.29999967, 0.0 ,-1.04999919524],
[-1.39999959, 0.0 ,-1.04999906667],
[-1.49999949, 0.0, -1.04999892857]
],
"ephemeris_times": [
999.2,
999.3,
999.4,
999.5,
999.6,
999.7,
999.8,
999.9,
1000.0,
1000.1,
1000.2,
1000.3,
1000.4,
1000.5,
1000.6,
1000.7
],
"reference_frame": 1
},
"instrument_pointing": {
"quaternions": [
[0.70710678, 0.0, -0.70710678, 0.0],
[0.70707311, 0.0, -0.70714045, 0.0],
[0.70703943, 0.0, -0.70717412, 0.0],
[0.70700576, 0.0, -0.70720779, 0.0],
[0.70697208, 0.0, -0.70724146, 0.0],
[0.7069384, 0.0, -0.70727512, 0.0],
[0.70690472, 0.0, -0.70730878, 0.0],
[0.70687104, 0.0, -0.70734244, 0.0],
[0.70683736, 0.0, -0.7073761 , 0.0],
[0.70680367, 0.0, -0.70740976, 0.0],
[0.70676998, 0.0, -0.70744342, 0.0],
[0.70673629, 0.0, -0.70747707, 0.0],
[0.7067026, 0.0, -0.70751073, 0.0],
[0.70666891, 0.0, -0.70754438, 0.0],
[0.70663522, 0.0, -0.70757803, 0.0],
[0.70660152, 0.0, -0.70761168, 0.0]
],
"ephemeris_times": [
999.2,
999.3,
999.4,
999.5,
999.6,
999.7,
999.8,
999.9,
1000.0,
1000.1,
1000.2,
1000.3,
1000.4,
1000.5,
1000.6,
1000.7
],
"angular_velocities": [
[0.0, 0.0, 0.0],
[0.0, 0.0, 0.0],
[0.0, 0.0, 0.0],
[0.0, 0.0, 0.0],
[0.0, 0.0, 0.0],
[0.0, 0.0, 0.0],
[0.0, 0.0, 0.0],
[0.0, 0.0, 0.0],
[0.0, 0.0, 0.0],
[0.0, 0.0, 0.0],
[0.0, 0.0, 0.0],
[0.0, 0.0, 0.0],
[0.0, 0.0, 0.0],
[0.0, 0.0, 0.0],
[0.0, 0.0, 0.0],
[0.0, 0.0, 0.0]
],
"reference_frame": 1
},
"body_rotation": {
"quaternions": [
[1.0, 0.0, 0.0, 0.0],
[1.0, 0.0, 0.0, 0.0],
[1.0, 0.0, 0.0, 0.0],
[1.0, 0.0, 0.0, 0.0],
[1.0, 0.0, 0.0, 0.0],
[1.0, 0.0, 0.0, 0.0],
[1.0, 0.0, 0.0, 0.0],
[1.0, 0.0, 0.0, 0.0],
[1.0, 0.0, 0.0, 0.0],
[1.0, 0.0, 0.0, 0.0],
[1.0, 0.0, 0.0, 0.0],
[1.0, 0.0, 0.0, 0.0],
[1.0, 0.0, 0.0, 0.0],
[1.0, 0.0, 0.0, 0.0],
[1.0, 0.0, 0.0, 0.0],
[1.0, 0.0, 0.0, 0.0]
],
"ephemeris_times": [
999.2,
999.3,
999.4,
999.5,
999.6,
999.7,
999.8,
999.9,
1000.0,
1000.1,
1000.2,
1000.3,
1000.4,
1000.5,
1000.6,
1000.7
],
"angular_velocities": [
[0.0, 0.0, 0.0],
[0.0, 0.0, 0.0],
[0.0, 0.0, 0.0],
[0.0, 0.0, 0.0],
[0.0, 0.0, 0.0],
[0.0, 0.0, 0.0],
[0.0, 0.0, 0.0],
[0.0, 0.0, 0.0],
[0.0, 0.0, 0.0],
[0.0, 0.0, 0.0],
[0.0, 0.0, 0.0],
[0.0, 0.0, 0.0],
[0.0, 0.0, 0.0],
[0.0, 0.0, 0.0],
[0.0, 0.0, 0.0],
[0.0, 0.0, 0.0]
],
"reference_frame": 1,
"constant_frames": [1, 2, 3],
"time_dependent_frames": [4, 5, 6]
},
"starting_detector_line": 1,
"starting_detector_sample": 0,
"sun_position": {
"positions": [
[0.100, 0.100, 0.100],
[0.150, 0.150, 0.150],
[0.200, 0.200, 0.200],
[0.250, 0.250, 0.250]
],
"velocities": [
[0.125, 0.125, 0.125],
[0.125, 0.125, 0.125],
[0.125, 0.125, 0.125],
[0.125, 0.125, 0.125]
],
"ephemeris_times": [
999.2,
999.6,
1000.0,
1000.4
],
"reference_frame": 1,
"unit": "km"
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment