Skip to content

Commit 9598004

Browse files
rad-eng-59GitHub Enterprise
authored andcommitted
Ant geom (#726)
* Add a new module "antenna::geometryfunc" and update "geometry::geometry" module - Add pybind11 module for "geometryfunc" - Add a python test suite for "geometryfunc" - Modify "srPosFromLookVecDem" in "geometry" with new initial value - Fix typo in doc of pybind "ltpcoordinates.cpp" of "geometry" - Replace all instances of scalar input argument DEM height "dem_hgt" with "isce3::geometry::DEMInterpolator" object - Update all respective C++ and pybind11 scripts as well as their test suites. - Update doxygen and numpy docstrings accordingly - Run clang-format and autopep8
1 parent 5282ba5 commit 9598004

File tree

16 files changed

+875
-61
lines changed

16 files changed

+875
-61
lines changed

cxx/isce3/Headers.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
set(HEADERS
22
antenna/forward.h
3+
antenna/geometryfunc.h
34
antenna/Frame.h
45
antenna/Frame.icc
56
antenna/SphGridType.h

cxx/isce3/Sources.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
set(SRCS
2+
antenna/geometryfunc.cpp
23
core/Attitude.cpp
34
core/Baseline.cpp
45
core/Basis.cpp

cxx/isce3/antenna/geometryfunc.cpp

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
// Definition of the antenna-related geometry functions
2+
#include "geometryfunc.h"
3+
4+
#include <isce3/core/Quaternion.h>
5+
#include <isce3/core/Vector.h>
6+
#include <isce3/except/Error.h>
7+
#include <isce3/geometry/geometry.h>
8+
9+
// Aliases
10+
using namespace isce3::core;
11+
namespace geom = isce3::geometry;
12+
namespace ant = isce3::antenna;
13+
using VecXd = Eigen::VectorXd;
14+
15+
// Helper local functions
16+
17+
/**
18+
* @internal
19+
* Helper function to get slant range and LLH and convergence flag
20+
* @param[in] el_theta : either elevation or theta angle in radians
21+
* depending on the "frame" object.
22+
* @param[in] az_phi : either azimuth or phi angle in radians depending
23+
* on the "frame" object.
24+
* @param[in] pos_ecef : antenna/spacecraft position in ECEF (m,m,m)
25+
* @param[in] vel_ecef : spacecraft velocity scaled by -2/wavalength in
26+
* ECEF (m/s,m/s,m/s)
27+
* @param[in] quat : isce3 quaternion object for transformation from antenna
28+
* body-fixed to ECEF
29+
* @param[in] dem_interp (optional): isce3 DEMInterpolator object
30+
* w.r.t ellipsoid. Default is zero height.
31+
* @param[in] abs_tol (optional): Abs error/tolerance in height estimation (m)
32+
* between desired input height and final output height. Default is 0.5.
33+
* @param[in] max_iter (optional): Max number of iterations in height
34+
* estimation. Default is 10.
35+
* @param[in] frame (optional): isce3 Frame object to define antenna spherical
36+
* coordinate system. Default is based on "EL_AND_AZ" spherical grid.
37+
* @param[in] ellips (optional): isce3 Ellipsoid object defining the
38+
* ellipsoidal planet. Default is WGS84 ellipsoid.
39+
* @return a tuple of three values : slantrange (m), Doppler (Hz), a bool
40+
* which is true if height tolerance is met, false otherwise.
41+
* @exception InvalidArgument, RuntimeError
42+
*/
43+
static std::tuple<double, double, bool> _get_sr_dop_conv(double el_theta,
44+
double az_phi, const Vec3& pos_ecef, const Vec3& vel_ecef,
45+
const Quaternion& quat, const geom::DEMInterpolator& dem_interp,
46+
double abs_tol, int max_iter, const ant::Frame& frame,
47+
const Ellipsoid& ellips)
48+
{
49+
// pointing sphercial to cartesian in Antenna frame
50+
auto pnt_xyz = frame.sphToCart(el_theta, az_phi);
51+
// pointing from Ant XYZ to global ECEF
52+
auto pnt_ecef = quat.rotate(pnt_xyz);
53+
// get slant range and target position on/above the ellipsoid
54+
Vec3 tg_ecef, tg_llh;
55+
double sr;
56+
auto iter_info = geom::srPosFromLookVecDem(sr, tg_ecef, tg_llh, pos_ecef,
57+
pnt_ecef, dem_interp, abs_tol, max_iter, ellips);
58+
bool convergence {true};
59+
if (iter_info.second > abs_tol)
60+
convergence = false;
61+
62+
double doppler = vel_ecef.dot(pnt_ecef);
63+
64+
return {sr, doppler, convergence};
65+
}
66+
67+
// Antenna to Radar functions
68+
std::tuple<double, double, bool> ant::ant2rgdop(double el_theta, double az_phi,
69+
const Vec3& pos_ecef, const Vec3& vel_ecef, const Quaternion& quat,
70+
double wavelength, const geom::DEMInterpolator& dem_interp,
71+
double abs_tol, int max_iter, const ant::Frame& frame,
72+
const Ellipsoid& ellips)
73+
{
74+
if (!(wavelength > 0.0))
75+
throw isce3::except::InvalidArgument(
76+
ISCE_SRCINFO(), "Bad value for wavelength!");
77+
78+
const auto vel_ecef_cst = (-2. / wavelength) * vel_ecef;
79+
80+
return _get_sr_dop_conv(el_theta, az_phi, pos_ecef, vel_ecef_cst, quat,
81+
dem_interp, abs_tol, max_iter, frame, ellips);
82+
}
83+
84+
std::tuple<VecXd, VecXd, bool> ant::ant2rgdop(
85+
const Eigen::Ref<const VecXd>& el_theta, double az_phi,
86+
const Vec3& pos_ecef, const Vec3& vel_ecef, const Quaternion& quat,
87+
double wavelength, const geom::DEMInterpolator& dem_interp,
88+
double abs_tol, int max_iter, const ant::Frame& frame,
89+
const Ellipsoid& ellips)
90+
{
91+
if (wavelength <= 0.0)
92+
throw isce3::except::InvalidArgument(
93+
ISCE_SRCINFO(), "Bad value for wavelength!");
94+
95+
// initialization and vector allocations
96+
const auto vel_ecef_cst = (-2. / wavelength) * vel_ecef;
97+
auto ang_size = el_theta.size();
98+
VecXd slantrange(ang_size);
99+
VecXd doppler(ang_size);
100+
bool converge {true};
101+
102+
#pragma omp parallel for
103+
for (decltype(ang_size) idx = 0; idx < ang_size; ++idx) {
104+
auto [sr, dop, flag] =
105+
_get_sr_dop_conv(el_theta[idx], az_phi, pos_ecef, vel_ecef_cst,
106+
quat, dem_interp, abs_tol, max_iter, frame, ellips);
107+
slantrange(idx) = sr;
108+
doppler(idx) = dop;
109+
if (!flag)
110+
converge = false;
111+
}
112+
return {slantrange, doppler, converge};
113+
}
114+
115+
// Antenna to Geometry
116+
std::tuple<Vec3, bool> ant::ant2geo(double el_theta, double az_phi,
117+
const Vec3& pos_ecef, const Quaternion& quat,
118+
const geom::DEMInterpolator& dem_interp, double abs_tol, int max_iter,
119+
const ant::Frame& frame, const Ellipsoid& ellips)
120+
{
121+
// pointing sphercial to cartesian in Antenna frame
122+
auto pnt_xyz = frame.sphToCart(el_theta, az_phi);
123+
// pointing from Ant XYZ to global ECEF
124+
auto pnt_ecef = quat.rotate(pnt_xyz);
125+
// get slant range and target position on/above the ellipsoid
126+
Vec3 tg_ecef, tg_llh;
127+
double sr;
128+
auto iter_info = geom::srPosFromLookVecDem(sr, tg_ecef, tg_llh, pos_ecef,
129+
pnt_ecef, dem_interp, abs_tol, max_iter, ellips);
130+
bool convergence {true};
131+
if (iter_info.second > abs_tol)
132+
convergence = false;
133+
134+
return {tg_llh, convergence};
135+
}
136+
137+
std::tuple<std::vector<Vec3>, bool> ant::ant2geo(
138+
const Eigen::Ref<const VecXd>& el_theta, double az_phi,
139+
const Vec3& pos_ecef, const Quaternion& quat,
140+
const geom::DEMInterpolator& dem_interp, double abs_tol, int max_iter,
141+
const ant::Frame& frame, const Ellipsoid& ellips)
142+
{
143+
// initialize and allocate vectors
144+
auto ang_size {el_theta.size()};
145+
std::vector<Vec3> tg_llh_vec(ang_size);
146+
bool converge {true};
147+
148+
#pragma omp parallel for
149+
for (decltype(ang_size) idx = 0; idx < ang_size; ++idx) {
150+
auto [tg_llh, flag] = ant::ant2geo(el_theta(idx), az_phi, pos_ecef,
151+
quat, dem_interp, abs_tol, max_iter, frame, ellips);
152+
153+
if (!flag)
154+
converge = false;
155+
tg_llh_vec[idx] = tg_llh;
156+
}
157+
return {tg_llh_vec, converge};
158+
}

cxx/isce3/antenna/geometryfunc.h

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
/** @file geometryfunc.h
2+
* A collection of antenna-related geometry functions.
3+
*/
4+
#pragma once
5+
6+
#include <isce3/core/forward.h>
7+
8+
#include <tuple>
9+
#include <vector>
10+
11+
#include <Eigen/Dense>
12+
13+
#include <isce3/antenna/Frame.h>
14+
#include <isce3/core/Ellipsoid.h>
15+
#include <isce3/geometry/DEMInterpolator.h>
16+
17+
/** @namespace isce3::antenna */
18+
namespace isce3 { namespace antenna {
19+
20+
// Antenna to Radar
21+
22+
/**
23+
* Estimate Radar products, Slant range and Doppler centroid, from
24+
* spherical angles in antenna body-fixed domain for a certain spacecraft
25+
* position, velocity,and attitude at a certain height w.r.t. an ellipsoid.
26+
* @param[in] el_theta : either elevation or theta angle in radians
27+
* depending on the "frame" object.
28+
* @param[in] az_phi : either azimuth or phi angle in radians depending
29+
* on the "frame" object.
30+
* @param[in] pos_ecef : antenna/spacecraft position in ECEF (m,m,m)
31+
* @param[in] vel_ecef : spacecraft velocity in ECEF (m/s,m/s,m/s)
32+
* @param[in] quat : isce3 quaternion object for transformation from antenna
33+
* body-fixed to ECEF
34+
* @param[in] wavelength : Radar wavelength in (m).
35+
* @param[in] dem_interp (optional): isce3 DEMInterpolator object
36+
* w.r.t ellipsoid. Default is zero height.
37+
* @param[in] abs_tol (optional): Abs error/tolerance in height estimation (m)
38+
* between desired input height and final output height. Default is 0.5.
39+
* @param[in] max_iter (optional): Max number of iterations in height
40+
* estimation. Default is 10.
41+
* @param[in] frame (optional): isce3 Frame object to define antenna spherical
42+
* coordinate system. Default is based on "EL_AND_AZ" spherical grid.
43+
* @param[in] ellips (optional): isce3 Ellipsoid object defining the
44+
* ellipsoidal planet. Default is WGS84 ellipsoid.
45+
* @return slantrange (m)
46+
* @return Doppler (Hz)
47+
* @return a bool which is true if height tolerance is met, false otherwise.
48+
* @exception InvalidArgument, RuntimeError
49+
* @cite ReeTechDesDoc
50+
*/
51+
52+
std::tuple<double, double, bool> ant2rgdop(double el_theta, double az_phi,
53+
const isce3::core::Vec3& pos_ecef, const isce3::core::Vec3& vel_ecef,
54+
const isce3::core::Quaternion& quat, double wavelength,
55+
const isce3::geometry::DEMInterpolator& dem_interp = {},
56+
double abs_tol = 0.5, int max_iter = 10,
57+
const isce3::antenna::Frame& frame = {},
58+
const isce3::core::Ellipsoid& ellips = {});
59+
60+
/**
61+
* Overloaded function to estimate Radar products, Slant ranges and Doppler
62+
* centroids, from spherical angles in antenna body-fixed domain for a
63+
* certain spacecraft position, velocity,and attitude at a certain height
64+
* w.r.t. an ellipsoid.
65+
* @param[in] el_theta : a vector of either elevation or theta angle in
66+
* radians depending on the "frame" object.
67+
* @param[in] az_phi : either azimuth or phi angle in radians depending
68+
* on the "frame" object.
69+
* @param[in] pos_ecef : antenna/spacecraft position in ECEF (m,m,m)
70+
* @param[in] vel_ecef : spacecraft velocity in ECEF (m/s,m/s,m/s)
71+
* @param[in] quat : isce3 quaternion object for transformation from antenna
72+
* body-fixed to ECEF
73+
* @param[in] wavelength : Radar wavelength in (m).
74+
* @param[in] dem_interp (optional): isce3 DEMInterpolator object
75+
* w.r.t ellipsoid. Default is zero height.
76+
* @param[in] abs_tol (optional): Abs error/tolerance in height estimation (m)
77+
* between desired input height and final output height. Default is 0.5.
78+
* @param[in] max_iter (optional): Max number of iterations in height
79+
* estimation. Default is 10.
80+
* @param[in] frame (optional): isce3 Frame object to define antenna spherical
81+
* coordinate system. Default is based on "EL_AND_AZ" spherical grid.
82+
* @param[in] ellips (optional): isce3 Ellipsoid object defining the
83+
* ellipsoidal planet. Default is WGS84 ellipsoid.
84+
* @return an Eigen::VectorXd of slant ranges (m)
85+
* @return an Eigen::VectorXd of Doppler values (Hz)
86+
* @return a bool which is true if height tolerance is met, false otherwise.
87+
* @exception InvalidArgument, RuntimeError
88+
* @cite ReeTechDesDoc
89+
*/
90+
std::tuple<Eigen::VectorXd, Eigen::VectorXd, bool> ant2rgdop(
91+
const Eigen::Ref<const Eigen::VectorXd>& el_theta, double az_phi,
92+
const isce3::core::Vec3& pos_ecef, const isce3::core::Vec3& vel_ecef,
93+
const isce3::core::Quaternion& quat, double wavelength,
94+
const isce3::geometry::DEMInterpolator& dem_interp = {},
95+
double abs_tol = 0.5, int max_iter = 10,
96+
const isce3::antenna::Frame& frame = {},
97+
const isce3::core::Ellipsoid& ellips = {});
98+
99+
// Antenna to Geometry
100+
101+
/**
102+
* Estimate geodetic geolocation (longitude, latitude, height) from
103+
* spherical angles in antenna body-fixed domain for a certain spacecraft
104+
* position and attitude at a certain height w.r.t. an ellipsoid.
105+
* @param[in] el_theta : either elevation or theta angle in radians
106+
* depending on the "frame" object.
107+
* @param[in] az_phi : either azimuth or phi angle in radians depending
108+
* on the "frame" object.
109+
* @param[in] pos_ecef : antenna/spacecraft position in ECEF (m,m,m)
110+
* @param[in] quat : isce3 quaternion object for transformation from antenna
111+
* body-fixed to ECEF
112+
* @param[in] dem_interp (optional): isce3 DEMInterpolator object
113+
* w.r.t ellipsoid. Default is zero height.
114+
* @param[in] abs_tol (optional): Abs error/tolerance in height estimation (m)
115+
* between desired input height and final output height. Default is 0.5.
116+
* @param[in] max_iter (optional): Max number of iterations in height
117+
* estimation. Default is 10.
118+
* @param[in] frame (optional): isce3 Frame object to define antenna spherical
119+
* coordinate system. Default is based on "EL_AND_AZ" spherical grid.
120+
* @param[in] ellips (optional): isce3 Ellipsoid object defining the
121+
* ellipsoidal planet. Default is WGS84 ellipsoid.
122+
* @return an isce3::core::Vec3 of geodetic LLH(longitude,latitude,height)
123+
* in (rad,rad,m)
124+
* @return a bool which is true if height tolerance is met, false otherwise.
125+
* @exception InvalidArgument, RuntimeError
126+
* @cite ReeTechDesDoc
127+
*/
128+
std::tuple<isce3::core::Vec3, bool> ant2geo(double el_theta, double az_phi,
129+
const isce3::core::Vec3& pos_ecef, const isce3::core::Quaternion& quat,
130+
const isce3::geometry::DEMInterpolator& dem_interp = {},
131+
double abs_tol = 0.5, int max_iter = 10,
132+
const isce3::antenna::Frame& frame = {},
133+
const isce3::core::Ellipsoid& ellips = {});
134+
135+
/**
136+
* Overloaded function to estimate geodetic geolocation
137+
* (longitude, latitude, height) from spherical angles in antenna
138+
* body-fixed domain for a certain spacecraft position and attitude
139+
* at a certain height w.r.t. an ellipsoid.
140+
* @param[in] el_theta : a vector of either elevation or theta angle
141+
* in radians depending on the "frame" object.
142+
* @param[in] az_phi : either azimuth or phi angle in radians depending
143+
* on the "frame" object.
144+
* @param[in] pos_ecef : antenna/spacecraft position in ECEF (m,m,m)
145+
* @param[in] quat : isce3 quaternion object for transformation from antenna
146+
* body-fixed to ECEF
147+
* @param[in] dem_interp (optional): isce3 DEMInterpolator object
148+
* w.r.t ellipsoid. Default is zero height.
149+
* @param[in] abs_tol (optional): Abs error/tolerance in height estimation (m)
150+
* between desired input height and final output height. Default is 0.5.
151+
* @param[in] max_iter (optional): Max number of iterations in height
152+
* estimation. Default is 10.
153+
* @param[in] frame (optional): isce3 Frame object to define antenna spherical
154+
* coordinate system. Default is based on "EL_AND_AZ" spherical grid.
155+
* @param[in] ellips (optional): isce3 Ellipsoid object defining the
156+
* ellipsoidal planet. Default is WGS84 ellipsoid.
157+
* @return a vector of isce3::core::Vec3 of geodetic
158+
* LLH(longitude,latitude,height) in (rad,rad,m)
159+
* @return a bool which is true if height tolerance is met, false otherwise.
160+
* @exception InvalidArgument, RuntimeError
161+
* @cite ReeTechDesDoc
162+
*/
163+
std::tuple<std::vector<isce3::core::Vec3>, bool> ant2geo(
164+
const Eigen::Ref<const Eigen::VectorXd>& el_theta, double az_phi,
165+
const isce3::core::Vec3& pos_ecef, const isce3::core::Quaternion& quat,
166+
const isce3::geometry::DEMInterpolator& dem_interp = {},
167+
double abs_tol = 0.5, int max_iter = 10,
168+
const isce3::antenna::Frame& frame = {},
169+
const isce3::core::Ellipsoid& ellips = {});
170+
171+
}} // namespace isce3::antenna

cxx/isce3/geometry/geometry.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -452,19 +452,28 @@ double isce3::geometry::slantRangeFromLookVec(
452452

453453
std::pair<int, double> isce3::geometry::srPosFromLookVecDem(double& sr,
454454
Vec3& tg_pos, Vec3& llh, const Vec3& sc_pos, const Vec3& lkvec,
455-
double dem_hgt, double hgt_err, int num_iter, const Ellipsoid& ellips)
455+
const DEMInterpolator& dem_interp, double hgt_err, int num_iter,
456+
const Ellipsoid& ellips)
456457
{
457458
if (hgt_err <= 0.0 || num_iter <= 0)
458459
throw isce3::except::InvalidArgument(ISCE_SRCINFO(),
459460
"Height Error and number of iteration "
460461
"must be non-zero positive values!");
461-
sr = slantRangeFromLookVec(sc_pos, lkvec, ellips);
462+
463+
// form a new ellipsoid whose radii adjusted by mean height
464+
const auto mean_hgt = dem_interp.meanHeight();
465+
const auto a_new = ellips.a() + mean_hgt;
466+
const auto b_new = ellips.b() + mean_hgt;
467+
const auto e2_new = 1.0 - (b_new * b_new) / (a_new * a_new);
468+
// initial guess of slant range per new ellipsoid
469+
sr = slantRangeFromLookVec(sc_pos, lkvec, Ellipsoid(a_new, e2_new));
462470
int cnt {0};
463471
double abs_hgt_dif;
464472
do {
465473
tg_pos = sr * lkvec + sc_pos;
466474
llh = ellips.xyzToLonLat(tg_pos);
467-
auto hgt_dif {dem_hgt - llh(2)};
475+
auto dem_hgt = dem_interp.interpolateLonLat(llh(0), llh(1));
476+
auto hgt_dif = dem_hgt - llh(2);
468477
sr += hgt_dif / _downVal(llh(0), llh(1), tg_pos);
469478
abs_hgt_dif = std::abs(hgt_dif);
470479
++cnt;

0 commit comments

Comments
 (0)