Skip to content

Commit aa5b16a

Browse files
jungkyoJungGitHub Enterprise
authored andcommitted
Merge pull request #2 from isce-3/develop
Update from original
2 parents c07e937 + f9037d7 commit aa5b16a

File tree

88 files changed

+2910
-1598
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

88 files changed

+2910
-1598
lines changed

cxx/isce3/Headers.cmake

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
set(HEADERS
22
antenna/detail/WinChirpRgCompPow.h
33
antenna/detail/WinChirpRgCompPow.icc
4+
antenna/edge_method_cost_func.h
45
antenna/forward.h
56
antenna/ElPatternEst.h
67
antenna/geometryfunc.h
@@ -18,8 +19,6 @@ core/Baseline.h
1819
core/Basis.h
1920
core/Common.h
2021
core/Constants.h
21-
core/Cube.h
22-
core/Cube.icc
2322
core/DateTime.h
2423
core/DenseMatrix.h
2524
core/detail/BuildOrbit.h
@@ -41,7 +40,6 @@ core/LUT1d.h
4140
core/LUT1d.icc
4241
core/LUT2d.h
4342
core/Matrix.h
44-
core/Matrix.icc
4543
core/Metadata.h
4644
core/Orbit.h
4745
core/Peg.h
@@ -125,18 +123,12 @@ io/IH5.icc
125123
io/Raster.h
126124
io/Raster.icc
127125
io/Serialization.h
128-
matchtemplate/ampcor/correlators/correlators.h
129-
matchtemplate/ampcor/correlators/kernels.h
130-
matchtemplate/ampcor/correlators/Sequential.h
131-
matchtemplate/ampcor/correlators/Sequential.icc
132-
matchtemplate/ampcor/dom/dom.h
133-
matchtemplate/ampcor/dom/Raster.h
134-
matchtemplate/ampcor/dom/Raster.icc
135-
matchtemplate/ampcor/dom/SLC.h
136-
matchtemplate/ampcor/dom/SLC.icc
137126
math/Bessel.h
138127
math/ComplexMultiply.h
128+
math/detail/RootFind1dBase.h
139129
math/polyfunc.h
130+
math/RootFind1dNewton.h
131+
math/RootFind1dSecant.h
140132
math/Sinc.h
141133
math/Sinc.icc
142134
polsar/symmetrize.h

cxx/isce3/Sources.cmake

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
set(SRCS
2+
antenna/edge_method_cost_func.cpp
23
antenna/ElPatternEst.cpp
34
antenna/geometryfunc.cpp
45
core/Attitude.cpp
@@ -58,21 +59,10 @@ io/gdal/SpatialReference.cpp
5859
io/IH5.cpp
5960
io/IH5Dataset.cpp
6061
io/Raster.cpp
61-
matchtemplate/ampcor/correlators/c2r.cpp
62-
matchtemplate/ampcor/correlators/correlate.cpp
63-
matchtemplate/ampcor/correlators/detect.cpp
64-
matchtemplate/ampcor/correlators/maxcor.cpp
65-
matchtemplate/ampcor/correlators/migrate.cpp
66-
matchtemplate/ampcor/correlators/nudge.cpp
67-
matchtemplate/ampcor/correlators/offsets.cpp
68-
matchtemplate/ampcor/correlators/r2c.cpp
69-
matchtemplate/ampcor/correlators/refStats.cpp
70-
matchtemplate/ampcor/correlators/sat.cpp
71-
matchtemplate/ampcor/correlators/tgtStats.cpp
72-
matchtemplate/ampcor/dom/Raster.cc
73-
matchtemplate/ampcor/dom/SLC.cc
7462
math/Bessel.cpp
7563
math/polyfunc.cpp
64+
math/RootFind1dNewton.cpp
65+
math/RootFind1dSecant.cpp
7666
polsar/symmetrize.cpp
7767
product/GeoGridParameters.cpp
7868
product/Product.cpp

cxx/isce3/antenna/detail/WinChirpRgCompPow.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
namespace isce3 { namespace antenna { namespace detail {
1313

1414
// Aliases, typedef:
15-
// fuzzy naming convention by isce3::core::EMtarix module!!!
1615
using RowMatrixXcf = isce3::core::EMatrix2D<std::complex<float>>;
1716

1817
// Functions:
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
#include <algorithm>
2+
#include <cmath>
3+
#include <vector>
4+
5+
#include <Eigen/Dense>
6+
7+
#include <isce3/antenna/edge_method_cost_func.h>
8+
#include <isce3/except/Error.h>
9+
#include <isce3/math/RootFind1dNewton.h>
10+
#include <isce3/math/polyfunc.h>
11+
12+
namespace isce3 { namespace antenna {
13+
14+
std::tuple<double, double, bool, int> rollAngleOffsetFromEdge(
15+
const poly1d_t& polyfit_echo, const poly1d_t& polyfit_ant,
16+
const isce3::core::Linspace<double>& look_ang,
17+
std::optional<poly1d_t> polyfit_weight)
18+
{
19+
// check the input arguments
20+
if (polyfit_echo.order != 3 || polyfit_ant.order != 3)
21+
throw isce3::except::InvalidArgument(ISCE_SRCINFO(),
22+
"Requires 3rd-order poly-fit object for both "
23+
"Echo and Antenna!");
24+
constexpr double a_tol {1e-5};
25+
if (std::abs(polyfit_echo.mean - polyfit_ant.mean) > a_tol ||
26+
std::abs(polyfit_echo.norm - polyfit_ant.norm) > a_tol)
27+
throw isce3::except::InvalidArgument(ISCE_SRCINFO(),
28+
"Requires same (mean, std) for Echo and Antenna Poly1d obj!");
29+
30+
if (!(polyfit_echo.norm > 0.0))
31+
throw isce3::except::InvalidArgument(ISCE_SRCINFO(),
32+
"Requires positive std of Echo and Antenna Poly1d obj!");
33+
34+
if (polyfit_weight) {
35+
if (polyfit_weight->order < 0)
36+
throw isce3::except::InvalidArgument(ISCE_SRCINFO(),
37+
"The order of polyfit for weights must be "
38+
"at least 0 (constant weights)!");
39+
if (!(polyfit_weight->norm > 0.0))
40+
throw isce3::except::InvalidArgument(ISCE_SRCINFO(),
41+
"Requires positive std of weight Poly1d obj!");
42+
}
43+
44+
// create a copy polyfit objects "echo" and "ant" with zero mean and unit
45+
// std
46+
auto pf_echo_cp = polyfit_echo;
47+
pf_echo_cp.mean = 0.0;
48+
pf_echo_cp.norm = 1.0;
49+
auto pf_ant_cp = polyfit_ant;
50+
pf_ant_cp.mean = 0.0;
51+
pf_ant_cp.norm = 1.0;
52+
53+
// declare and initialize a look angle vector
54+
Eigen::ArrayXd lka_vec(look_ang.size());
55+
for (int idx = 0; idx < look_ang.size(); ++idx)
56+
lka_vec(idx) = look_ang[idx];
57+
58+
// create a weighting vector from look vector and weighting Poly1d
59+
Eigen::ArrayXd wgt_vec;
60+
if (polyfit_weight) {
61+
Eigen::Map<Eigen::ArrayXd> wgt_coef(
62+
polyfit_weight->coeffs.data(), polyfit_weight->coeffs.size());
63+
wgt_vec = isce3::math::polyval(
64+
wgt_coef, lka_vec, polyfit_weight->mean, polyfit_weight->norm);
65+
// normalize power in dB
66+
wgt_vec -= wgt_vec.maxCoeff();
67+
// convert from dB to linear power scale
68+
wgt_vec = Eigen::pow(10, 0.1 * wgt_vec);
69+
}
70+
// centralized and scaled the look vector based on mean/std of the echo
71+
// Poly1d to be used for both antenna and echo in the cost function.
72+
lka_vec -= polyfit_echo.mean;
73+
const auto std_inv = 1.0 / polyfit_echo.norm;
74+
lka_vec *= std_inv;
75+
76+
// form some derivatives used in the cost function
77+
auto pf_echo_der = pf_echo_cp.derivative();
78+
auto pf_ant_der = pf_ant_cp.derivative();
79+
auto pf_ant_der2 = pf_ant_der.derivative();
80+
// create a memmap of the coeff for the first and second derivatives
81+
Eigen::Map<Eigen::ArrayXd> coef_ant_der(
82+
pf_ant_der.coeffs.data(), pf_ant_der.coeffs.size());
83+
Eigen::Map<Eigen::ArrayXd> coef_ant_der2(
84+
pf_ant_der2.coeffs.data(), pf_ant_der2.coeffs.size());
85+
Eigen::Map<Eigen::ArrayXd> coef_echo_der(
86+
pf_echo_der.coeffs.data(), pf_echo_der.coeffs.size());
87+
// form some arrays over scaled look angles for diff of first derivatives
88+
// and for second derivative
89+
auto ant_echo_der_dif_vec =
90+
isce3::math::polyval(coef_ant_der - coef_echo_der, lka_vec);
91+
auto ant_der2_vec = isce3::math::polyval(coef_ant_der2, lka_vec);
92+
93+
// build cost function in the form of Poly1d object (3th order polynimal!)
94+
auto cf_pf = isce3::core::Poly1d(3, 0.0, 1.0);
95+
// fill up the coeff for the derivative of the WMSE cost function:
96+
// cost(ofs) = pf_wgt*(pf_echo_der(el) - pf_ant_der(el + ofs))**2
97+
// See section 1.1 of the cited reference.
98+
if (polyfit_weight) {
99+
auto tmp1 = wgt_vec * ant_echo_der_dif_vec;
100+
auto tmp2 = wgt_vec * ant_der2_vec;
101+
cf_pf.coeffs[0] = (tmp1 * ant_der2_vec).sum();
102+
cf_pf.coeffs[1] = (tmp2 * ant_der2_vec).sum() +
103+
6 * pf_ant_cp.coeffs[3] * tmp1.sum();
104+
cf_pf.coeffs[2] = 9 * pf_ant_cp.coeffs[3] * tmp2.sum();
105+
cf_pf.coeffs[3] =
106+
18 * pf_ant_cp.coeffs[3] * pf_ant_cp.coeffs[3] * wgt_vec.sum();
107+
} else // no weighting
108+
{
109+
cf_pf.coeffs[0] = (ant_echo_der_dif_vec * ant_der2_vec).sum();
110+
cf_pf.coeffs[1] = ant_der2_vec.square().sum() +
111+
6 * pf_ant_cp.coeffs[3] * ant_echo_der_dif_vec.sum();
112+
cf_pf.coeffs[2] = 9 * pf_ant_cp.coeffs[3] * ant_der2_vec.sum();
113+
cf_pf.coeffs[3] = 18 * pf_ant_cp.coeffs[3] * pf_ant_cp.coeffs[3] *
114+
look_ang.size();
115+
}
116+
// form Root finding object
117+
auto rf_obj =
118+
isce3::math::RootFind1dNewton(1e-4, 20, look_ang.spacing() / 10.);
119+
// solve for the root/roll offset via Newton
120+
auto [roll, f_val, flag, n_iter] = rf_obj.root(cf_pf);
121+
// scale back the roll angle by std of original poly1d object
122+
roll *= polyfit_echo.norm;
123+
124+
return {roll, f_val, flag, n_iter};
125+
}
126+
127+
std::tuple<double, double, bool, int> rollAngleOffsetFromEdge(
128+
const poly1d_t& polyfit_echo, const poly1d_t& polyfit_ant,
129+
double look_ang_near, double look_ang_far, double look_ang_prec,
130+
std::optional<poly1d_t> polyfit_weight)
131+
{
132+
if (!(look_ang_near > 0.0 && look_ang_far > 0.0 && look_ang_prec > 0.0))
133+
throw isce3::except::InvalidArgument(ISCE_SRCINFO(),
134+
"All look angles values must be positive numbers!");
135+
if (look_ang_near >= (look_ang_far - look_ang_prec))
136+
throw isce3::except::InvalidArgument(ISCE_SRCINFO(),
137+
"Near-range look angle shall be smaller than "
138+
"far one by at least one prec!");
139+
140+
const auto ang_size =
141+
static_cast<int>((look_ang_far - look_ang_near) / look_ang_prec) +
142+
1;
143+
auto look_ang = isce3::core::Linspace<double>::from_interval(
144+
look_ang_near, look_ang_far, ang_size);
145+
146+
return rollAngleOffsetFromEdge(
147+
polyfit_echo, polyfit_ant, look_ang, polyfit_weight);
148+
}
149+
150+
}} // namespace isce3::antenna
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
/** @file edge_method_cost_func.h
2+
* Cost functions used in EL antenna pointing estimation via edge method
3+
*/
4+
#pragma once
5+
6+
#include <optional>
7+
#include <tuple>
8+
9+
#include <isce3/core/Linspace.h>
10+
#include <isce3/core/Poly1d.h>
11+
12+
/** @namespace isce3::antenna */
13+
namespace isce3 { namespace antenna {
14+
15+
// Aliases
16+
using poly1d_t = isce3::core::Poly1d;
17+
18+
/**
19+
* Estimate roll angle offset via edge method from poly-fitted
20+
* power patterns obtained from echo raw data and antenna pattern.
21+
* The cost function is solved via Newton method and final solution
22+
* is the weighted average of individual solution within look
23+
* (off-nadir) angles [near, far] with desired angle precision all
24+
* defined by isce3 Linspace.
25+
* See equations for cost function in section 1.1 of the reference
26+
* @cite EdgeMethodElPointDoc
27+
* The only difference is that the look angles are in (rad) rather than in
28+
* (deg). Note that the respective magnitudes for both echo and antenna can be
29+
* either 2-way or 1-way power patterns.
30+
* @param[in] polyfit_echo isce3 Poly1d object for polyfitted magnitude
31+
* of either range compressed (preferred) or raw echo data.
32+
* It must be third-order polynomial of relative magnitude/power in (dB)
33+
* as a function of look angle in (rad)
34+
* @param[in] polyfit_ant isce3 Poly1d object for antenna EL power pattern.
35+
* It must be third-order polynomial of relative magnitude/power in (dB)
36+
* as a function of look angle in (rad).
37+
* It must have the same mean and std as that of "polyfit_echo"!
38+
* @param[in] look_ang isce3 Linspace object to cover desired range of
39+
* look angles (rad) with desired precision/spacing.
40+
* @param[in] polyfit_weight (optional) isce3 Poly1d object for weightings used
41+
* in final weighted averaged of individual solutions over desired look angle
42+
* coverage. It shall represent relative magnitude/power in (dB) as a function
43+
* of look angle in (rad).
44+
* The order of the polynomial must be at least 0 (constant weights).
45+
* @return roll angle offset (rad)
46+
* Note that the roll offset shall be added to EL angles in antenna frame
47+
* to align EL power pattern from antenna to the one extracted from echo given
48+
* the cost function optimized for offset applied to polyfitted antenna data.
49+
* @return max cost function value among all iterations
50+
* @return overall convergence flag (true or false)
51+
* @return max number of iterations among all iterations
52+
* @exception InvalidArgument
53+
*/
54+
std::tuple<double, double, bool, int> rollAngleOffsetFromEdge(
55+
const poly1d_t& polyfit_echo, const poly1d_t& polyfit_ant,
56+
const isce3::core::Linspace<double>& look_ang,
57+
std::optional<poly1d_t> polyfit_weight = {});
58+
59+
/**
60+
* Estimate roll angle offset via edge method from poly-fitted
61+
* power patterns obtained from echo raw data and antenna pattern.
62+
* The cost function is solved via Newton method and final solution
63+
* is the weighted average of individual solution within look
64+
* (off-nadir) angles [near, far] with desired angle precision "look_ang_prec".
65+
* See equations for cost function in section 1.1 of the reference
66+
* @cite EdgeMethodElPointDoc
67+
* The only difference is that the look angles are in (rad) rather than in
68+
* (deg). Note that the respective magnitudes for both echo and antenna can be
69+
* either 2-way or 1-way power patterns.
70+
* @param[in] polyfit_echo isce3 Poly1d object for polyfitted magnitude
71+
* of either range compressed (preferred) or raw echo data.
72+
* It must be third-order polynomial of relative magnitude/power in (dB)
73+
* as a function of look angle in (rad)
74+
* @param[in] polyfit_ant isce3 Poly1d object for antenna EL power pattern.
75+
* It must be third-order polynomial of relative magnitude/power in (dB)
76+
* as a function of look angle in (rad).
77+
* It must have the same mean and std as that of "polyfit_echo"!
78+
* @param[in] look_ang_near look angle for near range in (rad)
79+
* @param[in] look_ang_far look angle for far range in (rad)
80+
* @param[in] look_ang_prec look angle precision/resolution in (rad)
81+
* @param[in] polyfit_weight (optional) isce3 Poly1d object for weightings used
82+
* in final weighted averaged of individual solutions over desired look angle
83+
* coverage. It shall represent relative magnitude/power in (dB) as a function
84+
* of look angle in (rad).
85+
* The order of the polynomial must be at least 0 (constant weights).
86+
* @return roll angle offset (rad)
87+
* Note that the roll offset shall be added to EL angles in antenna frame
88+
* to align EL power pattern from antenna to the one extracted from echo given
89+
* the cost function optimized for offset applied to polyfitted antenna data.
90+
* @return max cost function value among all iterations
91+
* @return overall convergence flag (true or false)
92+
* @return max number of iterations among all iterations
93+
* @exception InvalidArgument
94+
*/
95+
std::tuple<double, double, bool, int> rollAngleOffsetFromEdge(
96+
const poly1d_t& polyfit_echo, const poly1d_t& polyfit_ant,
97+
double look_ang_near, double look_ang_far, double look_ang_prec,
98+
std::optional<poly1d_t> polyfit_weight = {});
99+
100+
}} // namespace isce3::antenna

cxx/isce3/antenna/geometryfunc.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,6 @@ namespace isce3 { namespace antenna {
4848
* @exception InvalidArgument, RuntimeError
4949
* @cite ReeTechDesDoc
5050
*/
51-
5251
std::tuple<double, double, bool> ant2rgdop(double el_theta, double az_phi,
5352
const isce3::core::Vec3& pos_ecef, const isce3::core::Vec3& vel_ecef,
5453
const isce3::core::Quaternion& quat, double wavelength,

0 commit comments

Comments
 (0)