Skip to content

Commit 2863c44

Browse files
bhawkinsGitHub Enterprise
authored andcommitted
Use time instead of range to test geo2rdr convergence (#886)
* Control geo2rdr convergence with time. * Clarify cuda Geo2rdr test (still meets old metric). * Fix up pybind cuda Geo2rdr test * Test using max rather than RMS error. * Update documentation of geo2rdr threshold. * Use consistent geo2rdr thresholds in bindings. * Apply time step after convergence check so returned range and time are consistent. * Make CPU, GPU, and Python geo2rdr tests consistent and allow for error slightly larger than tolerance. * Update comment to better describe new test metric. * Ensure (time, range) are consistent even when geo2rdr fails to converge. * Repeat (t,r) consistency fix in other two geo2rdr implementations.
1 parent 919ed1d commit 2863c44

File tree

17 files changed

+114
-85
lines changed

17 files changed

+114
-85
lines changed

cxx/isce3/cuda/geometry/gpuGeometry.cu

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,14 @@ int geo2rdr(const Vec3& inputLLH, const isce3::core::Ellipsoid& ellipsoid,
7474
// Use mid-orbit epoch as initial guess
7575
aztime = orbit.midTime();
7676

77+
// Newton step, init to zero.
78+
double dt = 0.0;
79+
7780
// Begin iterations
7881
int converged = 0;
79-
double slantRange_old = 0.0;
8082
for (int i = 0; i < maxIter; ++i) {
83+
// Apply Newton step from previous iteration.
84+
aztime -= dt;
8185

8286
// Interpolate the orbit to current estimate of azimuth time
8387
Vec3 pos, vel;
@@ -95,16 +99,6 @@ int geo2rdr(const Vec3& inputLLH, const isce3::core::Ellipsoid& ellipsoid,
9599
return converged;
96100
}
97101

98-
// Check convergence
99-
if (std::abs(slantRange - slantRange_old) < threshold) {
100-
converged = 1;
101-
*slantRange_result = slantRange;
102-
*aztime_result = aztime;
103-
return converged;
104-
} else {
105-
slantRange_old = slantRange;
106-
}
107-
108102
// Compute doppler
109103
const double dopfact = dr.dot(vel);
110104
const double fdop = doppler.eval(slantRange) * dopscale;
@@ -119,8 +113,17 @@ int geo2rdr(const Vec3& inputLLH, const isce3::core::Ellipsoid& ellipsoid,
119113
const double c2 = (fdop / slantRange) + fdopder;
120114
const double fnprime = c1 + c2 * dopfact;
121115

122-
// Update guess for azimuth time
123-
aztime -= fn / fnprime;
116+
// Compute Newton step. Don't apply until start of next iteration so
117+
// that returned (slantRange, aztime) are always consistent.
118+
dt = fn / fnprime;
119+
120+
// Check convergence
121+
if (std::abs(dt) < threshold) {
122+
converged = 1;
123+
*slantRange_result = slantRange;
124+
*aztime_result = aztime;
125+
return converged;
126+
}
124127
}
125128

126129
// If we reach this point, no convergence for specified threshold

cxx/isce3/geocode/GeocodePolygon.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ class GeocodePolygon {
3333
* @param[in] orbit Orbit
3434
* @param[in] input_dop Doppler LUT associated with the radar grid
3535
* @param[in] dem_raster Input DEM raster
36-
* @param[in] threshold Distance threshold for convergence
36+
* @param[in] threshold Azimuth time threshold for convergence (s)
3737
* @param[in] num_iter Maximum number of Newton-Raphson iterations
3838
* @param[in] delta_range Step size used for computing Doppler derivative
3939
*/

cxx/isce3/geometry/RTC.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ void computeRtc(isce3::product::Product& product, isce3::io::Raster& dem_raster,
155155
* looks associated with the geogrid will be saved
156156
* @param[in] rtc_memory_mode Select memory mode
157157
* @param[in] interp_method Interpolation Method
158-
* @param[in] threshold Distance threshold for convergence
158+
* @param[in] threshold Azimuth time threshold for convergence (s)
159159
* @param[in] num_iter Maximum number of Newton-Raphson iterations
160160
* @param[in] delta_range Step size used for computing derivative of
161161
* doppler
@@ -214,7 +214,7 @@ void computeRtc(const isce3::product::RadarGridParameters& radarGrid,
214214
* looks associated with the geogrid will be saved
215215
* @param[in] rtc_memory_mode Select memory mode
216216
* @param[in] interp_method Interpolation Method
217-
* @param[in] threshold Distance threshold for convergence
217+
* @param[in] threshold Azimuth time threshold for convergence (s)
218218
* @param[in] num_iter Maximum number of Newton-Raphson iterations
219219
* @param[in] delta_range Step size used for computing derivative of
220220
* doppler
@@ -301,7 +301,7 @@ void computeRtcBilinearDistribution(isce3::io::Raster& dem_raster,
301301
* looks associated with the geogrid will be saved
302302
* @param[in] rtc_memory_mode Select memory mode
303303
* @param[in] interp_method Interpolation Method
304-
* @param[in] threshold Distance threshold for convergence
304+
* @param[in] threshold Azimuth time threshold for convergence (s)
305305
* @param[in] num_iter Maximum number of Newton-Raphson iterations
306306
* @param[in] delta_range Step size used for computing derivative of
307307
* doppler

cxx/isce3/geometry/detail/Geo2Rdr.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ namespace isce3 { namespace geometry { namespace detail {
1010

1111
/** \internal Root-finding configuration parameters for geo2rdr */
1212
struct Geo2RdrParams {
13-
/** \internal Absolute slant range convergence tolerance (m) */
13+
/** \internal Absolute azimuth time convergence tolerance (s) */
1414
double threshold = 1e-8;
1515

1616
/** \internal Maximum number of Newton-Raphson iterations */

cxx/isce3/geometry/detail/Geo2Rdr.icc

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,13 @@ geo2rdr(double* t, double* r, const isce3::core::Vec3& llh,
136136
}
137137
}
138138

139+
// Newton step, initialized to zero.
140+
double dt = 0.0;
141+
139142
// begin iterations
140-
double r_old = 0.;
141143
for (int i = 0; i < params.maxiter; ++i) {
144+
// apply Newton step here so that (r,t) are always consistent on return.
145+
*t -= dt;
142146

143147
// interpolate orbit
144148
Vec3 pos, vel;
@@ -156,21 +160,17 @@ geo2rdr(double* t, double* r, const isce3::core::Vec3& llh,
156160
}
157161
}
158162

159-
// check for convergence
160-
if (std::abs(*r - r_old) < params.threshold) {
161-
return ErrorCode::Success;
162-
}
163-
164163
// update guess for azimuth time
165-
double dt;
166164
const auto status = computeDopplerAztimeDiff(&dt, *t, *r, rvec, vel,
167165
doppler, wvl, params.delta_range);
168166
if (status != ErrorCode::Success) {
169167
return status;
170168
}
171169

172-
*t -= dt;
173-
r_old = *r;
170+
// check for convergence
171+
if (std::abs(dt) < params.threshold) {
172+
return ErrorCode::Success;
173+
}
174174
}
175175

176176
// if we reach this point, no convergence for specified threshold

cxx/isce3/geometry/geometry.cpp

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -198,9 +198,14 @@ int isce3::geometry::geo2rdr(const Vec3& inputLLH, const Ellipsoid& ellipsoid,
198198
if (error)
199199
return !converged;
200200

201-
double slantRange_old = slantRange;
201+
// Newton step, initialized to zero.
202+
double aztime_diff = 0.0;
203+
202204
// Begin iterations
203205
for (int i = 0; i < maxIter; ++i) {
206+
// Apply Newton step computed in previous iteration here so that
207+
// (aztime, slantRange) are always consistent on return.
208+
aztime -= aztime_diff;
204209

205210
// Interpolate the orbit to current estimate of azimuth time
206211
orbit.interpolate(
@@ -219,17 +224,15 @@ int isce3::geometry::geo2rdr(const Vec3& inputLLH, const Ellipsoid& ellipsoid,
219224
}
220225

221226
slantRange = dr.norm();
222-
// Check convergence
223-
if (std::abs(slantRange - slantRange_old) < threshold)
224-
return converged;
225-
else
226-
slantRange_old = slantRange;
227227

228228
// Update guess for azimuth time
229-
double aztime_diff = _compute_doppler_aztime_diff(dr, satvel, doppler,
229+
aztime_diff = _compute_doppler_aztime_diff(dr, satvel, doppler,
230230
wavelength, aztime, slantRange, deltaRange);
231231

232-
aztime -= aztime_diff;
232+
// Check convergence
233+
if (std::abs(aztime_diff) < threshold) {
234+
return converged;
235+
}
233236
}
234237
// If we reach this point, no convergence for specified threshold
235238
return !converged;

cxx/isce3/geometry/metadataCubes.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ inline void writeVectorDerivedCubes(const int array_pos_i,
112112
* @param[out] elevation_angle_raster Elevation angle (in degrees wrt
113113
* geodedic nadir) cube raster
114114
* @param[out] ground_track_velocity_raster Ground-track velocity raster
115-
* @param[in] threshold_geo2rdr Range threshold for geo2rdr
115+
* @param[in] threshold_geo2rdr Azimuth time threshold for geo2rdr
116116
* @param[in] numiter_geo2rdr Geo2rdr maximum number of iterations
117117
* @param[in] delta_range Step size used for computing
118118
* derivative of doppler
@@ -183,7 +183,7 @@ void makeRadarGridCubes(const isce3::product::RadarGridParameters& radar_grid,
183183
* @param[out] elevation_angle_raster Elevation angle (in degrees wrt
184184
* geodedic nadir) cube raster
185185
* @param[out] ground_track_velocity_raster Ground-track velocity raster
186-
* @param[in] threshold_geo2rdr Range threshold for geo2rdr
186+
* @param[in] threshold_geo2rdr Azimuth time threshold for geo2rdr
187187
* @param[in] numiter_geo2rdr Geo2rdr maximum number of iterations
188188
* @param[in] delta_range Step size used for computing
189189
* derivative of doppler

python/extensions/pybind_isce3/cuda/geocode/cuGeocode.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
#include <isce3/container/RadarGeometry.h>
77
#include <isce3/core/Constants.h>
8+
#include <isce3/geometry/detail/Geo2Rdr.h>
89
#include <isce3/io/Raster.h>
910
#include <isce3/product/GeoGridParameters.h>
1011

@@ -14,6 +15,7 @@ using isce3::cuda::geocode::Geocode;
1415

1516
void addbinding(pybind11::class_<Geocode>& pyGeocode)
1617
{
18+
const isce3::geometry::detail::Geo2RdrParams defaults;
1719
pyGeocode
1820
.def(py::init<const isce3::product::GeoGridParameters&,
1921
const isce3::container::RadarGeometry&,
@@ -28,8 +30,10 @@ void addbinding(pybind11::class_<Geocode>& pyGeocode)
2830
isce3::core::BILINEAR_METHOD,
2931
py::arg("dem_interp_method") =
3032
isce3::core::BIQUINTIC_METHOD,
31-
py::arg("threshold") = 1e-8, py::arg("maxiter") = 50,
32-
py::arg("delta_range") = 10, py::arg("invalid_value") = 0.0,
33+
py::arg("threshold") = defaults.threshold,
34+
py::arg("maxiter") = defaults.maxiter,
35+
py::arg("delta_range") = defaults.delta_range,
36+
py::arg("invalid_value") = 0.0,
3337
R"(
3438
Create CUDA geocode object.
3539

python/extensions/pybind_isce3/cuda/geometry/geo2rdr.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <isce3/core/Ellipsoid.h>
77
#include <isce3/core/LUT2d.h>
88
#include <isce3/core/Orbit.h>
9+
#include <isce3/geometry/detail/Geo2Rdr.h>
910
#include <isce3/geometry/geometry.h>
1011
#include <isce3/io/Raster.h>
1112
#include <isce3/product/RadarGridParameters.h>
@@ -16,6 +17,7 @@ namespace py = pybind11;
1617

1718
void addbinding(py::class_<Geo2rdr> & pyGeo2Rdr)
1819
{
20+
const isce3::geometry::detail::Geo2RdrParams defaults;
1921
pyGeo2Rdr
2022
.def(py::init([](const isce3::product::RadarGridParameters & radar_grid,
2123
const isce3::core::Orbit & orbit,
@@ -35,8 +37,8 @@ void addbinding(py::class_<Geo2rdr> & pyGeo2Rdr)
3537
py::arg("orbit"),
3638
py::arg("ellipsoid"),
3739
py::arg("doppler") = isce3::core::LUT2d<double>(),
38-
py::arg("threshold") = 1e-8,
39-
py::arg("numiter") = 25,
40+
py::arg("threshold") = defaults.threshold,
41+
py::arg("numiter") = defaults.maxiter,
4042
py::arg("lines_per_block") = 1000)
4143
.def("geo2rdr", py::overload_cast<isce3::io::Raster &, const std::string &,
4244
double, double>

python/extensions/pybind_isce3/geocode/GeocodePolygon.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ void addbinding(py::class_<GeocodePolygon<T>> &pyGeocodePolygon)
4747
orbit Orbit
4848
input_dop Doppler LUT associated with the radar grid
4949
dem_raster Input DEM raster
50-
threshold Distance threshold for convergence
50+
threshold Azimuth time threshold for convergence (s)
5151
num_iter Maximum number of Newton-Raphson iterations
5252
delta_range Step size used for computing Doppler derivative
5353
)")

0 commit comments

Comments
 (0)