Isis 3 Programmer Reference
CameraGroundMap.cpp
1 
6 /* SPDX-License-Identifier: CC0-1.0 */
7 #include "CameraGroundMap.h"
8 
9 #include <iostream>
10 
11 #include <QDebug>
12 
13 #include <SpiceUsr.h>
14 
15 #include "IException.h"
16 #include "Latitude.h"
17 #include "Longitude.h"
18 #include "NaifStatus.h"
19 #include "SurfacePoint.h"
20 #include "Target.h"
21 
22 using namespace std;
23 
24 namespace Isis {
25 
31  CameraGroundMap::CameraGroundMap(Camera *parent) {
32  p_camera = parent;
33  p_camera->SetGroundMap(this);
34  }
35 
36 
50  bool CameraGroundMap::SetFocalPlane(const double ux, const double uy, const double uz) {
51  NaifStatus::CheckErrors();
52 
53  SpiceDouble lookC[3];
54  lookC[0] = ux;
55  lookC[1] = uy;
56  lookC[2] = uz;
57 
58  SpiceDouble unitLookC[3];
59  vhat_c(lookC, unitLookC);
60 
61  NaifStatus::CheckErrors();
62 
63  bool result = p_camera->SetLookDirection(unitLookC);
64  return result;
65  }
66 
67 
76  bool CameraGroundMap::SetGround(const Latitude &lat, const Longitude &lon) {
77  if (p_camera->target()->shape()->name() == "Plane") {
78  double radius = lat.degrees();
79  // double azimuth = lon.degrees();
80  Latitude lat(0., Angle::Degrees);
81  if (radius < 0.0) radius = 0.0; // TODO: massive, temporary kluge to get around testing
82  // latitude at -90 in caminfo app (are there
83  // more issues like this? Probably)KE
84  if (p_camera->Sensor::SetGround(SurfacePoint(lat, lon, Distance(radius, Distance::Meters)))) {
85  LookCtoFocalPlaneXY();
86  return true;
87  }
88  }
89  else {
90  Distance radius(p_camera->LocalRadius(lat, lon));
91  if (radius.isValid()) {
92  if (p_camera->Sensor::SetGround(SurfacePoint(lat, lon, radius))) {
93  LookCtoFocalPlaneXY();
94  return true;
95  }
96  }
97  }
98 
99  return false;
100  }
101 
102 
106  void CameraGroundMap::LookCtoFocalPlaneXY() {
107  double lookC[3];
108  p_camera->Sensor::LookDirection(lookC);
109 
110  //Get the fl as the z coordinate to handle instruments looking down the -z axis 2013-02-22.
111  double focalLength = p_camera->DistortionMap()->UndistortedFocalPlaneZ();
112  double scale = focalLength / lookC[2];
113 
114  p_focalPlaneX = lookC[0] * scale;
115  p_focalPlaneY = lookC[1] * scale;
116  }
117 
118 
126  bool CameraGroundMap::SetGround(const SurfacePoint &surfacePoint) {
127  if (p_camera->Sensor::SetGround(surfacePoint)) {
128  LookCtoFocalPlaneXY();
129  return true;
130  }
131 
132  return false;
133  }
134 
135 
152  bool CameraGroundMap::GetXY(const SurfacePoint &point, double *cudx,
153  double *cudy, bool test) {
154 
155  vector<double> pB(3);
156  pB[0] = point.GetX().kilometers();
157  pB[1] = point.GetY().kilometers();
158  pB[2] = point.GetZ().kilometers();
159 
160  // Check for Sky images
161  if (p_camera->target()->isSky()) {
162  return false;
163  }
164 
165  // Should a check be added to make sure SetImage has been called???
166 
167  // Get spacecraft vector in j2000 coordinates
168  SpiceRotation *bodyRot = p_camera->bodyRotation();
169  SpiceRotation *instRot = p_camera->instrumentRotation();
170  vector<double> pJ = bodyRot->J2000Vector(pB);
171  vector<double> sJ = p_camera->instrumentPosition()->Coordinate();
172 
173  // Calculate lookJ
174  vector<double> lookJ(3);
175  for (int ic = 0; ic < 3; ic++) {
176  lookJ[ic] = pJ[ic] - sJ[ic];
177  }
178 
179  // Save pB for target body partial derivative calculations NEW *** DAC 8-14-2015
180  m_pB = pB;
181 
182  // During iterations in the bundle adjustment do not do the back-of-planet test.
183  // Failures are expected to happen during the bundle adjustment due to bad camera
184  // pointing or position, poor a priori points, or inaccurate target body information. For
185  // instance, control points near the limb of an image often fail the test. The hope is
186  // that during the bundle adjustment, any variables causing points to fail the test will
187  // be corrected. If not, the point residuals will likely be large on a point that fails the
188  // test. The back-of-planet test is still a valid check for a control net diagnostic
189  // program, but not for the bundle adjustment.
190  //
191  // TODO It might be useful to have a separate diagnostic program test all points in a
192  // control net to see if any of the control points fail the back-of-planet test on
193  // any of the images.
194 
195  // Check for point on back of planet by checking to see if surface point is viewable
196  // (test emission angle)
197  if (test) {
198  vector<double> lookB = bodyRot->ReferenceVector(lookJ);
199  double upsB[3], upB[3], dist;
200  vminus_c((SpiceDouble *) &lookB[0], upsB);
201  unorm_c(upsB, upsB, &dist);
202  unorm_c((SpiceDouble *) &pB[0], upB, &dist);
203  double cosangle = vdot_c(upB, upsB);
204  double emission;
205  if (cosangle > 1) {
206  emission = 0;
207  }
208  else if (cosangle < -1) {
209  emission = 180.;
210  }
211  else {
212  emission = acos(cosangle) * 180.0 / Isis::PI;
213  }
214 
215  if (fabs(emission) > 90.) {
216  return false;
217  }
218  }
219 
220  // Get the look vector in the camera frame and the instrument rotation
221  m_lookJ.resize(3);
222  m_lookJ = lookJ;
223  vector<double> lookC(3);
224  lookC = instRot->ReferenceVector(m_lookJ);
225 
226  // Get focal length with direction for scaling coordinates
227  double fl = p_camera->DistortionMap()->UndistortedFocalPlaneZ();
228 
229  *cudx = lookC[0] * fl / lookC[2];
230  *cudy = lookC[1] * fl / lookC[2];
231  return true;
232  }
233 
234 
254  bool CameraGroundMap::GetXY(const double lat, const double lon,
255  const double radius, double *cudx, double *cudy) {
256  SurfacePoint spoint(Latitude(lat, Angle::Degrees),
257  Longitude(lon, Angle::Degrees),
258  Distance(radius, Distance::Meters));
259  return GetXY(spoint, cudx, cudy);
260  }
261 
262 
279  bool CameraGroundMap::GetdXYdPosition(const SpicePosition::PartialType varType, int coefIndex,
280  double *dx, double *dy) {
281 
282  //TODO add a check to make sure m_lookJ has been set
283 
284  // Get directional fl for scaling coordinates
285  double fl = p_camera->DistortionMap()->UndistortedFocalPlaneZ();
286 
287  // Rotate look vector into camera frame
288  SpiceRotation *instRot = p_camera->instrumentRotation();
289  vector<double> lookC(3);
290  lookC = instRot->ReferenceVector(m_lookJ);
291 
292  SpicePosition *instPos = p_camera->instrumentPosition();
293 
294  vector<double> d_lookJ = instPos->CoordinatePartial(varType, coefIndex);
295  for (int j = 0; j < 3; j++) d_lookJ[j] *= -1.0;
296  vector<double> d_lookC = instRot->ReferenceVector(d_lookJ);
297  *dx = fl * DQuotient(lookC, d_lookC, 0);
298  *dy = fl * DQuotient(lookC, d_lookC, 1);
299  return true;
300  }
301 
302 
318  bool CameraGroundMap::GetdXYdOrientation(const SpiceRotation::PartialType varType, int coefIndex,
319  double *dx, double *dy) {
320 
321  //TODO add a check to make sure m_lookJ has been set
322 
323  // Get directional fl for scaling coordinates
324  double fl = p_camera->DistortionMap()->UndistortedFocalPlaneZ();
325 
326  // Rotate J2000 look vector into camera frame
327  SpiceRotation *instRot = p_camera->instrumentRotation();
328  vector<double> lookC(3);
329  lookC = instRot->ReferenceVector(m_lookJ);
330 
331  // Rotate J2000 look vector into camera frame through the derivative rotation
332  vector<double> d_lookC = instRot->ToReferencePartial(m_lookJ, varType, coefIndex);
333 
334  *dx = fl * DQuotient(lookC, d_lookC, 0);
335  *dy = fl * DQuotient(lookC, d_lookC, 1);
336  return true;
337  }
338 
339 
354  bool CameraGroundMap::GetdXYdTOrientation(const SpiceRotation::PartialType varType, int coefIndex,
355  double *dx, double *dy) {
356 
357  //TODO add a check to make sure m_pB and m_lookJ have been set.
358  // 0. calculate or save from previous GetXY call lookB. We need toJ2000Partial that is
359  // like a derivative form of J2000Vector
360  // 1. we will call d_lookJ = bodyrot->toJ2000Partial (Make sure the partials are correct for
361  // the target body orientation matrix.
362  // 2. we will then call d_lookC = instRot->ReferenceVector(d_lookJ)
363  // 3. the rest should be the same.
364 
365  // Get directional fl for scaling coordinates
366  double fl = p_camera->DistortionMap()->UndistortedFocalPlaneZ();
367 
368  // Rotate body-fixed look vector into J2000 through the derivative rotation
369  SpiceRotation *bodyRot = p_camera->bodyRotation();
370  SpiceRotation *instRot = p_camera->instrumentRotation();
371  vector<double> dlookJ = bodyRot->toJ2000Partial(m_pB, varType, coefIndex);
372  vector<double> lookC(3);
373  vector<double> dlookC(3);
374 
375  // Rotate both the J2000 look vector and the derivative J2000 look vector into the camera
376  lookC = instRot->ReferenceVector(m_lookJ);
377  dlookC = instRot->ReferenceVector(dlookJ);
378 
379  *dx = fl * DQuotient(lookC, dlookC, 0);
380  *dy = fl * DQuotient(lookC, dlookC, 1);
381  return true;
382  }
383 
384 
398  bool CameraGroundMap::GetdXYdPoint(vector<double> d_pB, double *dx, double *dy) {
399 
400  // TODO add a check to make sure m_lookJ has been set
401 
402  // Get directional fl for scaling coordinates
403  double fl = p_camera->DistortionMap()->UndistortedFocalPlaneZ();
404 
405  // Rotate look vector into camera frame
406  SpiceRotation *instRot = p_camera->instrumentRotation();
407  vector<double> lookC(3);
408  lookC = instRot->ReferenceVector(m_lookJ);
409 
410  SpiceRotation *bodyRot = p_camera->bodyRotation();
411  vector<double> d_lookJ = bodyRot->J2000Vector(d_pB);
412  vector<double> d_lookC = instRot->ReferenceVector(d_lookJ);
413 
414  *dx = fl * DQuotient(lookC, d_lookC, 0);
415  *dy = fl * DQuotient(lookC, d_lookC, 1);
416  return true;
417  }
418 
419 
436  vector<double> CameraGroundMap::EllipsoidPartial(SurfacePoint spoint, PartialType raxis) {
437  double rlat = spoint.GetLatitude().radians();
438  double rlon = spoint.GetLongitude().radians();
439  double sinLon = sin(rlon);
440  double cosLon = cos(rlon);
441  double sinLat = sin(rlat);
442  double cosLat = cos(rlat);
443 
444  vector<double> v(3);
445 
446  switch (raxis) {
447  case WRT_MajorAxis:
448  v[0] = cosLat * cosLon;
449  v[1] = 0.0;
450  v[2] = 0.0;
451  break;
452  case WRT_MinorAxis:
453  v[0] = 0.0;
454  v[1] = cosLat * sinLon;
455  v[2] = 0.0;
456  break;
457  case WRT_PolarAxis:
458  v[0] = 0.0;
459  v[1] = 0.0;
460  v[2] = sinLat;
461  break;
462  default:
463  QString msg = "Invalid partial type for this method";
464  throw IException(IException::Programmer, msg, _FILEINFO_);
465  }
466 
467  return v;
468  }
469 
470 
486  vector<double> CameraGroundMap::MeanRadiusPartial(SurfacePoint spoint, Distance meanRadius) {
487  double radkm = meanRadius.kilometers();
488 
489  vector<double> v(3);
490 
491  v[0] = spoint.GetX().kilometers() / radkm;
492  v[1] = spoint.GetY().kilometers() / radkm;
493  v[2] = spoint.GetZ().kilometers() / radkm;
494 
495  return v;
496  }
497 
498 
508  vector<double> CameraGroundMap::PointPartial(SurfacePoint spoint, PartialType wrt) {
509  double rlat = spoint.GetLatitude().radians();
510  double rlon = spoint.GetLongitude().radians();
511  double sinLon = sin(rlon);
512  double cosLon = cos(rlon);
513  double sinLat = sin(rlat);
514  double cosLat = cos(rlat);
515  double radkm = spoint.GetLocalRadius().kilometers();
516 
517  vector<double> v(3);
518  if (wrt == WRT_Latitude) {
519  v[0] = -radkm * sinLat * cosLon;
520  v[1] = -radkm * sinLon * sinLat;
521  v[2] = radkm * cosLat;
522  }
523  else if (wrt == WRT_Longitude) {
524  v[0] = -radkm * cosLat * sinLon;
525  v[1] = radkm * cosLat * cosLon;
526  v[2] = 0.0;
527  }
528  else {
529  v[0] = cosLon * cosLat;
530  v[1] = sinLon * cosLat;
531  v[2] = sinLat;
532  }
533 
534  return v;
535  }
536 
537 
550  double CameraGroundMap::DQuotient(vector<double> &look,
551  vector<double> &dlook,
552  int index) {
553  return (look[2] * dlook[index] - look[index] * dlook[2]) /
554  (look[2] * look[2]);
555  }
556 }
Isis::Distance::kilometers
double kilometers() const
Get the distance in kilometers.
Definition: Distance.cpp:106
Isis::SpicePosition
Obtain SPICE position information for a body.
Definition: SpicePosition.h:173
Isis::PI
const double PI
The mathematical constant PI.
Definition: Constants.h:40
Isis::Latitude
This class is designed to encapsulate the concept of a Latitude.
Definition: Latitude.h:51
Isis::SpicePosition::CoordinatePartial
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 ...
Definition: SpicePosition.cpp:1167
Isis::Camera::SetGroundMap
void SetGroundMap(CameraGroundMap *map)
Sets the Ground Map.
Definition: Camera.cpp:2387
Isis::SurfacePoint::GetLatitude
Latitude GetLatitude() const
Return the body-fixed latitude for the surface point.
Definition: SurfacePoint.cpp:1665
Isis::Camera
Definition: Camera.h:236
Isis::SpiceRotation::J2000Vector
std::vector< double > J2000Vector(const std::vector< double > &rVec)
Given a direction vector in the reference frame, return a J2000 direction.
Definition: SpiceRotation.cpp:1408
Isis::Distance
Distance measurement, usually in meters.
Definition: Distance.h:34
Isis::Longitude
This class is designed to encapsulate the concept of a Longitude.
Definition: Longitude.h:40
Isis::SpiceRotation::PartialType
PartialType
This enumeration indicates whether the partial derivative is taken with respect to Right Ascension,...
Definition: SpiceRotation.h:258
Isis::SpiceRotation::ToReferencePartial
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...
Definition: SpiceRotation.cpp:2232
Isis::Distance::isValid
bool isValid() const
Test if this distance has been initialized or not.
Definition: Distance.cpp:192
Isis::IException
Isis exception class.
Definition: IException.h:91
Isis::SurfacePoint::GetLongitude
Longitude GetLongitude() const
Return the body-fixed longitude for the surface point.
Definition: SurfacePoint.cpp:1685
Isis::Displacement::kilometers
double kilometers() const
Get the displacement in kilometers.
Definition: Displacement.cpp:94
Isis::SurfacePoint::GetLocalRadius
Distance GetLocalRadius() const
Return the radius of the surface point.
Definition: SurfacePoint.cpp:1732
std
Namespace for the standard library.
Isis::SpiceRotation::toJ2000Partial
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...
Definition: SpiceRotation.cpp:1607
Isis::Angle::degrees
double degrees() const
Get the angle in units of Degrees.
Definition: Angle.h:232
Isis::SpiceRotation::ReferenceVector
std::vector< double > ReferenceVector(const std::vector< double > &jVec)
Given a direction vector in J2000, return a reference frame direction.
Definition: SpiceRotation.cpp:1700
Isis::SurfacePoint
This class defines a body-fixed surface point.
Definition: SurfacePoint.h:132
Isis
This is free and unencumbered software released into the public domain.
Definition: Apollo.h:16
Isis::SpiceRotation
Obtain SPICE rotation information for a body.
Definition: SpiceRotation.h:209
Isis::CameraGroundMap::PartialType
PartialType
Radius axes types to use when computing partials.
Definition: CameraGroundMap.h:87
Isis::Angle::radians
double radians() const
Convert an angle to a double.
Definition: Angle.h:226