USGS

Isis 3.0 Object Programmers' Reference

Home

RadarSlantRangeMap.cpp
Go to the documentation of this file.
1 
23 #include "RadarSlantRangeMap.h"
24 
25 #include "IString.h"
26 #include "iTime.h"
27 #include "PvlSequence.h"
28 
29 namespace Isis {
38  RadarSlantRangeMap::RadarSlantRangeMap(Camera *parent, double groundRangeResolution) :
39  CameraDistortionMap(parent, 1.0) {
40 
41  p_camera = parent;
42  p_et = DBL_MAX;
43  p_a[0] = p_a[1] = p_a[2] = p_a[3] = 0.0;
44 
45  // Need to come up with an initial guess when solving for ground
46  // range given slantrange. We will compute the ground range at the
47  // near and far edges of the image by evaluating the sample-to-
48  // ground-range equation: r_gnd=(S-1)*groundRangeResolution
49  // at the edges of the image. We also need to add some padding to
50  // allow for solving for coordinates that are slightly outside of
51  // the actual image area. Use S=-0.25*p_camera->Samples() and
52  // S=1.25*p_camera->Samples().
53  p_initialMinGroundRangeGuess = (-0.25 * p_camera->Samples() - 1.0)
54  * groundRangeResolution;
55  p_initialMaxGroundRangeGuess = (1.25 * p_camera->Samples() - 1.0)
56  * groundRangeResolution;
57  p_tolerance = 0.1; // Default tolerance is a tenth of a meter
58  p_maxIterations = 30;
59  }
60 
64  bool RadarSlantRangeMap::SetFocalPlane(const double dx, const double dy) {
65  p_focalPlaneX = dx; // dx is a ground range distance in meters
66  p_focalPlaneY = dy; // dy is Doppler shift in htz and should always be 0
67 
68  if(p_et != p_camera->time().Et()) ComputeA();
69  double slantRange = p_a[0] + p_a[1] * dx + p_a[2] * dx * dx + p_a[3] * dx * dx * dx; // meters
70 
71  p_camera->SetFocalLength(slantRange);
72  p_undistortedFocalPlaneX = slantRange / p_rangeSigma;
73  p_undistortedFocalPlaneY = 0;
74 
75  return true;
76  }
77 
82  const double uy) {
83  p_undistortedFocalPlaneX = ux * p_rangeSigma; // ux converts to slant range in meters
84  p_undistortedFocalPlaneY = uy * p_dopplerSigma; // uy converts to Doppler shift in htz and should always be 0
85 
86  if(p_et != p_camera->time().Et()) ComputeA();
87 
88  // Evaluate the ground range at the 2 extremes of the image
89  double slant = p_undistortedFocalPlaneX;
90  double minGroundRangeGuess = slant - (p_a[0] + p_initialMinGroundRangeGuess *
91  (p_a[1] + p_initialMinGroundRangeGuess * (p_a[2] +
92  p_initialMinGroundRangeGuess * p_a[3])));
93  double maxGroundRangeGuess = slant - (p_a[0] + p_initialMaxGroundRangeGuess *
94  (p_a[1] + p_initialMaxGroundRangeGuess * (p_a[2] +
95  p_initialMaxGroundRangeGuess * p_a[3])));
96 
97  // If the ground range guesses at the 2 extremes of the image are equal
98  // or they have the same sign, then the ground range cannot be solved for.
99  if((minGroundRangeGuess == maxGroundRangeGuess) ||
100  (minGroundRangeGuess < 0.0 && maxGroundRangeGuess < 0.0) ||
101  (minGroundRangeGuess > 0.0 && maxGroundRangeGuess > 0.0)) return false;
102 
103  // Use Wijngaarden/Dekker/Brent algorithm to find a root of the function:
104  // g(groundRange) = slantRange - (p_a[0] + groundRange * (p_a[1] +
105  // groundRange * (p_a[2] + groundRange * p_a[3])))
106  // The algorithm used is a combination of the bisection method with the
107  // secant method.
108  int iter = 0;
109  double eps = 3.E-8;
110  double ax = p_initialMinGroundRangeGuess;
111  double bx = p_initialMaxGroundRangeGuess;
112  double fax = minGroundRangeGuess;
113  double fbx = maxGroundRangeGuess;
114  double fcx = fbx;
115  double cx = 0.0;
116  double d = 0.0;
117  double e = 0.0;
118  double tol1;
119  double xm;
120  double p, q, r, s, t;
121 
122  do {
123  iter++;
124  if(fbx * fcx > 0.0) {
125  cx = ax;
126  fcx = fax;
127  d = bx - ax;
128  e = d;
129  }
130  if(fabs(fcx) < fabs(fbx)) {
131  ax = bx;
132  bx = cx;
133  cx = ax;
134  fax = fbx;
135  fbx = fcx;
136  fcx = fax;
137  }
138  tol1 = 2.0 * eps * fabs(bx) + 0.5 * p_tolerance;
139  xm = 0.5 * (cx - bx);
140  if(fabs(xm) <= tol1 || fbx == 0.0) {
141  p_focalPlaneX = bx;
142  p_focalPlaneY = 0.0;
143  return true;
144  }
145  if(fabs(e) >= tol1 && fabs(fax) > fabs(fbx)) {
146  s = fbx / fax;
147  if(ax == cx) {
148  p = 2.0 * xm * s;
149  q = 1.0 - s;
150  }
151  else {
152  q = fax / fcx;
153  r = fbx / fcx;
154  p = s * (2.0 * xm * q * (q - r) - (bx - ax) * (r - 1.0));
155  q = (q - 1.0) * (r - 1.0) * (s - 1.0);
156  }
157  if(p > 0.0) q = -q;
158  p = fabs(p);
159  t = 3.0 * xm * q - fabs(tol1 * q);
160  if(t > fabs(e * q)) t = fabs(e * q);
161  if(2.0 * p < t) {
162  e = d;
163  d = p / q;
164  }
165  else {
166  d = xm;
167  e = d;
168  }
169  }
170  else {
171  d = xm;
172  e = d;
173  }
174  ax = bx;
175  fax = fbx;
176  if(fabs(d) > tol1) {
177  bx = bx + d;
178  }
179  else {
180  if(xm >= 0.0) {
181  t = fabs(tol1);
182  }
183  else {
184  t = -fabs(tol1);
185  }
186  bx = bx + t;
187  }
188  fbx = slant - (p_a[0] + bx * (p_a[1] + bx * (p_a[2] + bx * p_a[3])));
189  }
190  while(iter <= p_maxIterations);
191 
192  return false;
193  }
194 
200  PvlSequence seq;
201  seq = keyword;
202  for(int i = 0; i < seq.Size(); i++) {
203  // TODO: Test array size to be 4 if not throw error
204  std::vector<QString> array = seq[i];
205  double et;
206  utc2et_c(array[0].toAscii().data(), &et);
207  p_time.push_back(et);
208  p_a0.push_back(toDouble(array[1]));
209  p_a1.push_back(toDouble(array[2]));
210  p_a2.push_back(toDouble(array[3]));
211  p_a3.push_back(toDouble(array[4]));
212  // TODO: Test that times are ordered if not throw error
213  // Make the mrf2isis program sort them if necessary
214  }
215  }
216 
222  double currentEt = p_camera->time().Et();
223 
224  std::vector<double>::iterator pos = lower_bound(p_time.begin(), p_time.end(), currentEt);
225 
226  int index = p_time.size() - 1;
227  if (currentEt <= p_time[0]) {
228  p_a[0] = p_a0[0];
229  p_a[1] = p_a1[0];
230  p_a[2] = p_a2[0];
231  p_a[3] = p_a3[0];
232  }
233  else if (currentEt >= p_time.at(index)) {
234  p_a[0] = p_a0[index];
235  p_a[1] = p_a1[index];
236  p_a[2] = p_a2[index];
237  p_a[3] = p_a3[index];
238  } else {
239  index = pos - p_time.begin();
240  double weight = (currentEt - p_time.at(index-1)) /
241  (p_time.at(index) - p_time.at(index-1));
242  p_a[0] = p_a0[index-1] * (1.0 - weight) + p_a0[index] * weight;
243  p_a[1] = p_a1[index-1] * (1.0 - weight) + p_a1[index] * weight;
244  p_a[2] = p_a2[index-1] * (1.0 - weight) + p_a2[index] * weight;
245  p_a[3] = p_a3[index-1] * (1.0 - weight) + p_a3[index] * weight;
246  }
247  }
248 
252  void RadarSlantRangeMap::SetWeightFactors(double range_sigma, double doppler_sigma) {
253  p_rangeSigma = range_sigma; // meters scaling factor
254  p_dopplerSigma = doppler_sigma; // htz scaling factor
255  }
256 }