Isis 3 Programmer Reference
CameraGroundMap.cpp
Go to the documentation of this file.
1 
23 #include "CameraGroundMap.h"
24 
25 #include <iostream>
26 
27 #include <QDebug>
28 
29 #include <SpiceUsr.h>
30 
31 #include "IException.h"
32 #include "Latitude.h"
33 #include "Longitude.h"
34 #include "NaifStatus.h"
35 #include "SurfacePoint.h"
36 #include "Target.h"
37 
38 using namespace std;
39 
40 namespace Isis {
41 
47  CameraGroundMap::CameraGroundMap(Camera *parent) {
48  p_camera = parent;
49  p_camera->SetGroundMap(this);
50  }
51 
52 
66  bool CameraGroundMap::SetFocalPlane(const double ux, const double uy, const double uz) {
67  NaifStatus::CheckErrors();
68 
69  SpiceDouble lookC[3];
70  lookC[0] = ux;
71  lookC[1] = uy;
72  lookC[2] = uz;
73 
74  SpiceDouble unitLookC[3];
75  vhat_c(lookC, unitLookC);
76 
77  NaifStatus::CheckErrors();
78 
79  bool result = p_camera->SetLookDirection(unitLookC);
80  return result;
81  }
82 
83 
92  bool CameraGroundMap::SetGround(const Latitude &lat, const Longitude &lon) {
93  if (p_camera->target()->shape()->name() == "Plane") {
94  double radius = lat.degrees();
95  // double azimuth = lon.degrees();
96  Latitude lat(0., Angle::Degrees);
97  if (radius < 0.0) radius = 0.0; // TODO: massive, temporary kluge to get around testing
98  // latitude at -90 in caminfo app (are there
99  // more issues like this? Probably)KE
100  if (p_camera->Sensor::SetGround(SurfacePoint(lat, lon, Distance(radius, Distance::Meters)))) {
101  LookCtoFocalPlaneXY();
102  return true;
103  }
104  }
105  else {
106  Distance radius(p_camera->LocalRadius(lat, lon));
107  if (radius.isValid()) {
108  if (p_camera->Sensor::SetGround(SurfacePoint(lat, lon, radius))) {
109  LookCtoFocalPlaneXY();
110  return true;
111  }
112  }
113  }
114 
115  return false;
116  }
117 
118 
122  void CameraGroundMap::LookCtoFocalPlaneXY() {
123  double lookC[3];
124  p_camera->Sensor::LookDirection(lookC);
125 
126  //Get the fl as the z coordinate to handle instruments looking down the -z axis 2013-02-22.
127  double focalLength = p_camera->DistortionMap()->UndistortedFocalPlaneZ();
128  double scale = focalLength / lookC[2];
129 
130  p_focalPlaneX = lookC[0] * scale;
131  p_focalPlaneY = lookC[1] * scale;
132  }
133 
134 
142  bool CameraGroundMap::SetGround(const SurfacePoint &surfacePoint) {
143  if (p_camera->Sensor::SetGround(surfacePoint)) {
144  LookCtoFocalPlaneXY();
145  return true;
146  }
147 
148  return false;
149  }
150 
151 
168  bool CameraGroundMap::GetXY(const SurfacePoint &point, double *cudx,
169  double *cudy, bool test) {
170 
171  vector<double> pB(3);
172  pB[0] = point.GetX().kilometers();
173  pB[1] = point.GetY().kilometers();
174  pB[2] = point.GetZ().kilometers();
175 
176  // Check for Sky images
177  if (p_camera->target()->isSky()) {
178  return false;
179  }
180 
181  // Should a check be added to make sure SetImage has been called???
182 
183  // Get spacecraft vector in j2000 coordinates
184  SpiceRotation *bodyRot = p_camera->bodyRotation();
185  SpiceRotation *instRot = p_camera->instrumentRotation();
186  vector<double> pJ = bodyRot->J2000Vector(pB);
187  vector<double> sJ = p_camera->instrumentPosition()->Coordinate();
188 
189  // Calculate lookJ
190  vector<double> lookJ(3);
191  for (int ic = 0; ic < 3; ic++) {
192  lookJ[ic] = pJ[ic] - sJ[ic];
193  }
194 
195  // Save pB for target body partial derivative calculations NEW *** DAC 8-14-2015
196  m_pB = pB;
197 
198  // During iterations in the bundle adjustment do not do the back-of-planet test.
199  // Failures are expected to happen during the bundle adjustment due to bad camera
200  // pointing or position, poor a priori points, or inaccurate target body information. For
201  // instance, control points near the limb of an image often fail the test. The hope is
202  // that during the bundle adjustment, any variables causing points to fail the test will
203  // be corrected. If not, the point residuals will likely be large on a point that fails the
204  // test. The back-of-planet test is still a valid check for a control net diagnostic
205  // program, but not for the bundle adjustment.
206  //
207  // TODO It might be useful to have a separate diagnostic program test all points in a
208  // control net to see if any of the control points fail the back-of-planet test on
209  // any of the images.
210 
211  // Check for point on back of planet by checking to see if surface point is viewable
212  // (test emission angle)
213  if (test) {
214  vector<double> lookB = bodyRot->ReferenceVector(lookJ);
215  double upsB[3], upB[3], dist;
216  vminus_c((SpiceDouble *) &lookB[0], upsB);
217  unorm_c(upsB, upsB, &dist);
218  unorm_c((SpiceDouble *) &pB[0], upB, &dist);
219  double cosangle = vdot_c(upB, upsB);
220  double emission;
221  if (cosangle > 1) {
222  emission = 0;
223  }
224  else if (cosangle < -1) {
225  emission = 180.;
226  }
227  else {
228  emission = acos(cosangle) * 180.0 / Isis::PI;
229  }
230 
231  if (fabs(emission) > 90.) {
232  return false;
233  }
234  }
235 
236  // Get the look vector in the camera frame and the instrument rotation
237  m_lookJ.resize(3);
238  m_lookJ = lookJ;
239  vector<double> lookC(3);
240  lookC = instRot->ReferenceVector(m_lookJ);
241 
242  // Get focal length with direction for scaling coordinates
243  double fl = p_camera->DistortionMap()->UndistortedFocalPlaneZ();
244 
245  *cudx = lookC[0] * fl / lookC[2];
246  *cudy = lookC[1] * fl / lookC[2];
247  return true;
248  }
249 
250 
270  bool CameraGroundMap::GetXY(const double lat, const double lon,
271  const double radius, double *cudx, double *cudy) {
272  SurfacePoint spoint(Latitude(lat, Angle::Degrees),
273  Longitude(lon, Angle::Degrees),
274  Distance(radius, Distance::Meters));
275  return GetXY(spoint, cudx, cudy);
276  }
277 
278 
295  bool CameraGroundMap::GetdXYdPosition(const SpicePosition::PartialType varType, int coefIndex,
296  double *dx, double *dy) {
297 
298  //TODO add a check to make sure m_lookJ has been set
299 
300  // Get directional fl for scaling coordinates
301  double fl = p_camera->DistortionMap()->UndistortedFocalPlaneZ();
302 
303  // Rotate look vector into camera frame
304  SpiceRotation *instRot = p_camera->instrumentRotation();
305  vector<double> lookC(3);
306  lookC = instRot->ReferenceVector(m_lookJ);
307 
308  SpicePosition *instPos = p_camera->instrumentPosition();
309 
310  vector<double> d_lookJ = instPos->CoordinatePartial(varType, coefIndex);
311  for (int j = 0; j < 3; j++) d_lookJ[j] *= -1.0;
312  vector<double> d_lookC = instRot->ReferenceVector(d_lookJ);
313  *dx = fl * DQuotient(lookC, d_lookC, 0);
314  *dy = fl * DQuotient(lookC, d_lookC, 1);
315  return true;
316  }
317 
318 
334  bool CameraGroundMap::GetdXYdOrientation(const SpiceRotation::PartialType varType, int coefIndex,
335  double *dx, double *dy) {
336 
337  //TODO add a check to make sure m_lookJ has been set
338 
339  // Get directional fl for scaling coordinates
340  double fl = p_camera->DistortionMap()->UndistortedFocalPlaneZ();
341 
342  // Rotate J2000 look vector into camera frame
343  SpiceRotation *instRot = p_camera->instrumentRotation();
344  vector<double> lookC(3);
345  lookC = instRot->ReferenceVector(m_lookJ);
346 
347  // Rotate J2000 look vector into camera frame through the derivative rotation
348  vector<double> d_lookC = instRot->ToReferencePartial(m_lookJ, varType, coefIndex);
349 
350  *dx = fl * DQuotient(lookC, d_lookC, 0);
351  *dy = fl * DQuotient(lookC, d_lookC, 1);
352  return true;
353  }
354 
355 
370  bool CameraGroundMap::GetdXYdTOrientation(const SpiceRotation::PartialType varType, int coefIndex,
371  double *dx, double *dy) {
372 
373  //TODO add a check to make sure m_pB and m_lookJ have been set.
374  // 0. calculate or save from previous GetXY call lookB. We need toJ2000Partial that is
375  // like a derivative form of J2000Vector
376  // 1. we will call d_lookJ = bodyrot->toJ2000Partial (Make sure the partials are correct for
377  // the target body orientation matrix.
378  // 2. we will then call d_lookC = instRot->ReferenceVector(d_lookJ)
379  // 3. the rest should be the same.
380 
381  // Get directional fl for scaling coordinates
382  double fl = p_camera->DistortionMap()->UndistortedFocalPlaneZ();
383 
384  // Rotate body-fixed look vector into J2000 through the derivative rotation
385  SpiceRotation *bodyRot = p_camera->bodyRotation();
386  SpiceRotation *instRot = p_camera->instrumentRotation();
387  vector<double> dlookJ = bodyRot->toJ2000Partial(m_pB, varType, coefIndex);
388  vector<double> lookC(3);
389  vector<double> dlookC(3);
390 
391  // Rotate both the J2000 look vector and the derivative J2000 look vector into the camera
392  lookC = instRot->ReferenceVector(m_lookJ);
393  dlookC = instRot->ReferenceVector(dlookJ);
394 
395  *dx = fl * DQuotient(lookC, dlookC, 0);
396  *dy = fl * DQuotient(lookC, dlookC, 1);
397  return true;
398  }
399 
400 
414  bool CameraGroundMap::GetdXYdPoint(vector<double> d_pB, double *dx, double *dy) {
415 
416  // TODO add a check to make sure m_lookJ has been set
417 
418  // Get directional fl for scaling coordinates
419  double fl = p_camera->DistortionMap()->UndistortedFocalPlaneZ();
420 
421  // Rotate look vector into camera frame
422  SpiceRotation *instRot = p_camera->instrumentRotation();
423  vector<double> lookC(3);
424  lookC = instRot->ReferenceVector(m_lookJ);
425 
426  SpiceRotation *bodyRot = p_camera->bodyRotation();
427  vector<double> d_lookJ = bodyRot->J2000Vector(d_pB);
428  vector<double> d_lookC = instRot->ReferenceVector(d_lookJ);
429 
430  *dx = fl * DQuotient(lookC, d_lookC, 0);
431  *dy = fl * DQuotient(lookC, d_lookC, 1);
432  return true;
433  }
434 
435 
452  vector<double> CameraGroundMap::EllipsoidPartial(SurfacePoint spoint, PartialType raxis) {
453  double rlat = spoint.GetLatitude().radians();
454  double rlon = spoint.GetLongitude().radians();
455  double sinLon = sin(rlon);
456  double cosLon = cos(rlon);
457  double sinLat = sin(rlat);
458  double cosLat = cos(rlat);
459 
460  vector<double> v(3);
461 
462  switch (raxis) {
463  case WRT_MajorAxis:
464  v[0] = cosLat * cosLon;
465  v[1] = 0.0;
466  v[2] = 0.0;
467  break;
468  case WRT_MinorAxis:
469  v[0] = 0.0;
470  v[1] = cosLat * sinLon;
471  v[2] = 0.0;
472  break;
473  case WRT_PolarAxis:
474  v[0] = 0.0;
475  v[1] = 0.0;
476  v[2] = sinLat;
477  break;
478  default:
479  QString msg = "Invalid partial type for this method";
480  throw IException(IException::Programmer, msg, _FILEINFO_);
481  }
482 
483  return v;
484  }
485 
486 
502  vector<double> CameraGroundMap::MeanRadiusPartial(SurfacePoint spoint, Distance meanRadius) {
503  double radkm = meanRadius.kilometers();
504 
505  vector<double> v(3);
506 
507  v[0] = spoint.GetX().kilometers() / radkm;
508  v[1] = spoint.GetY().kilometers() / radkm;
509  v[2] = spoint.GetZ().kilometers() / radkm;
510 
511  return v;
512  }
513 
514 
524  vector<double> CameraGroundMap::PointPartial(SurfacePoint spoint, PartialType wrt) {
525  double rlat = spoint.GetLatitude().radians();
526  double rlon = spoint.GetLongitude().radians();
527  double sinLon = sin(rlon);
528  double cosLon = cos(rlon);
529  double sinLat = sin(rlat);
530  double cosLat = cos(rlat);
531  double radkm = spoint.GetLocalRadius().kilometers();
532 
533  vector<double> v(3);
534  if (wrt == WRT_Latitude) {
535  v[0] = -radkm * sinLat * cosLon;
536  v[1] = -radkm * sinLon * sinLat;
537  v[2] = radkm * cosLat;
538  }
539  else if (wrt == WRT_Longitude) {
540  v[0] = -radkm * cosLat * sinLon;
541  v[1] = radkm * cosLat * cosLon;
542  v[2] = 0.0;
543  }
544  else {
545  v[0] = cosLon * cosLat;
546  v[1] = sinLon * cosLat;
547  v[2] = sinLat;
548  }
549 
550  return v;
551  }
552 
553 
566  double CameraGroundMap::DQuotient(vector<double> &look,
567  vector<double> &dlook,
568  int index) {
569  return (look[2] * dlook[index] - look[index] * dlook[2]) /
570  (look[2] * look[2]);
571  }
572 }
This class defines a body-fixed surface point.
Definition: SurfacePoint.h:148
const double PI
The mathematical constant PI.
Definition: Constants.h:56
void SetGroundMap(CameraGroundMap *map)
Sets the Ground Map.
Definition: Camera.cpp:2399
double radians() const
Convert an angle to a double.
Definition: Angle.h:243
Namespace for the standard library.
This class is designed to encapsulate the concept of a Latitude.
Definition: Latitude.h:63
std::vector< double > CoordinatePartial(SpicePosition::PartialType partialVar, int coeffIndex)
Set the coefficients of a polynomial fit to each of the three coordinates of the position vector for ...
double kilometers() const
Get the distance in kilometers.
Definition: Distance.cpp:118
Distance measurement, usually in meters.
Definition: Distance.h:47
Latitude GetLatitude() const
Return the body-fixed latitude for the surface point.
double degrees() const
Get the angle in units of Degrees.
Definition: Angle.h:249
This class is designed to encapsulate the concept of a Longitude.
Definition: Longitude.h:52
PartialType
Radius axes types to use when computing partials.
std::vector< double > ReferenceVector(const std::vector< double > &jVec)
Given a direction vector in J2000, return a reference frame direction.
#define _FILEINFO_
Macro for the filename and line number.
Definition: IException.h:40
Obtain SPICE rotation information for a body.
PartialType
This enumeration indicates whether the partial derivative is taken with respect to Right Ascension...
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
std::vector< double > toJ2000Partial(const std::vector< double > &lookT, PartialType partialVar, int coeffIndex)
Given a direction vector in the reference frame, compute the derivative with respect to one of the co...
Longitude GetLongitude() const
Return the body-fixed longitude for the surface point.
std::vector< double > J2000Vector(const std::vector< double > &rVec)
Given a direction vector in the reference frame, return a J2000 direction.
Isis exception class.
Definition: IException.h:107
Obtain SPICE position information for a body.
Namespace for ISIS/Bullet specific routines.
Definition: Apollo.h:31
double kilometers() const
Get the displacement in kilometers.
Distance GetLocalRadius() const
Return the radius of the surface point.
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
std::vector< double > ToReferencePartial(std::vector< double > &lookJ, PartialType partialVar, int coeffIndex)
Compute the derivative with respect to one of the coefficients in the angle polynomial fit equation o...