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
22using namespace std;
23
24namespace Isis {
25
32 p_camera = parent;
34 }
35
36
50 bool CameraGroundMap::SetFocalPlane(const double ux, const double uy, const double uz) {
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
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)))) {
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))) {
94 return true;
95 }
96 }
97 }
98
99 return false;
100 }
101
102
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)) {
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();
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
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) {
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
286
287 // Rotate look vector into camera frame
289 vector<double> lookC(3);
290 lookC = instRot->ReferenceVector(m_lookJ);
291
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
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
325
326 // Rotate J2000 look vector into camera frame
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
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
367
368 // Rotate body-fixed look vector into J2000 through the derivative rotation
369 SpiceRotation *bodyRot = p_camera->bodyRotation();
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
404
405 // Rotate look vector into camera frame
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
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
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}
@ Degrees
Degrees are generally considered more human readable, 0-360 is one circle, however most math does not...
Definition Angle.h:56
double UndistortedFocalPlaneZ() const
Gets the z-value in the undistorted focal plane coordinate system.
virtual bool SetGround(const Latitude &lat, const Longitude &lon)
Compute undistorted focal plane coordinate from ground position.
PartialType
Radius axes types to use when computing partials.
virtual bool GetXY(const SurfacePoint &spoint, double *cudx, double *cudy, bool test=true)
Compute undistorted focal plane coordinate from ground position using current Spice from SetImage cal...
virtual bool GetdXYdTOrientation(const SpiceRotation::PartialType varType, int coefIndex, double *cudx, double *cudy)
Compute derivative of focal plane coordinate w/r to target body using current state.
CameraGroundMap(Camera *parent)
Constructor.
virtual bool GetdXYdPoint(std::vector< double > d_pB, double *dx, double *dy)
Compute derivative of focal plane coordinate w/r to ground point using current state.
double p_focalPlaneX
Camera's x focal plane coordinate.
std::vector< double > m_lookJ
Look vector in J2000 calculated from ground coordinates in GetXY and used for partials.
double DQuotient(std::vector< double > &look, std::vector< double > &dlook, int index)
Convenience method for quotient rule applied to look vector.
virtual bool SetFocalPlane(const double ux, const double uy, const double uz)
Compute ground position from focal plane coordinate.
virtual bool GetdXYdPosition(const SpicePosition::PartialType varType, int coefIndex, double *cudx, double *cudy)
Compute derivative w/r to position of focal plane coordinate from ground position using current Spice...
virtual bool GetdXYdOrientation(const SpiceRotation::PartialType varType, int coefIndex, double *cudx, double *cudy)
Compute derivative of focal plane coordinate w/r to instrument using current state from SetImage call...
std::vector< double > EllipsoidPartial(SurfacePoint spoint, PartialType raxis)
Compute derivative of focal plane coordinate w/r to one of the ellipsoidal radii (a,...
Camera * p_camera
Camera.
std::vector< double > PointPartial(SurfacePoint spoint, PartialType wrt)
Compute derivative with respect to indicated variable of conversion function from lat/lon/rad to rect...
std::vector< double > m_pB
Surface point calculated from ground coordinates in GetXY and used for partials.
void LookCtoFocalPlaneXY()
Calculate focalplane x/y from lookvector in camera.
double p_focalPlaneY
Camera's y focal plane coordinate.
std::vector< double > MeanRadiusPartial(SurfacePoint spoint, Distance meanRadius)
Compute derivative of focal plane coordinate w/r to mean of the ellipsoidal radii (a,...
CameraDistortionMap * DistortionMap()
Returns a pointer to the CameraDistortionMap object.
Definition Camera.cpp:2856
void SetGroundMap(CameraGroundMap *map)
Sets the Ground Map.
Definition Camera.cpp:2417
double kilometers() const
Get the displacement in kilometers.
Distance measurement, usually in meters.
Definition Distance.h:34
double kilometers() const
Get the distance in kilometers.
Definition Distance.cpp:106
@ Meters
The distance is being specified in meters.
Definition Distance.h:43
Isis exception class.
Definition IException.h:91
@ Programmer
This error is for when a programmer made an API call that was illegal.
Definition IException.h:146
This class is designed to encapsulate the concept of a Latitude.
Definition Latitude.h:51
This class is designed to encapsulate the concept of a Longitude.
Definition Longitude.h:40
static void CheckErrors(bool resetNaif=true)
This method looks for any naif errors that might have occurred.
Distance LocalRadius() const
Returns the local radius at the intersection point.
Definition Sensor.cpp:269
bool SetLookDirection(const double v[3])
Sets the look direction of the spacecraft.
Definition Sensor.cpp:143
virtual SpiceRotation * bodyRotation() const
Accessor method for the body rotation.
Definition Spice.cpp:1623
void instrumentPosition(double p[3]) const
Returns the spacecraft position in body-fixed frame km units.
Definition Spice.cpp:829
virtual Target * target() const
Returns a pointer to the target object.
Definition Spice.cpp:1380
virtual SpiceRotation * instrumentRotation() const
Accessor method for the instrument rotation.
Definition Spice.cpp:1634
Obtain SPICE position information for a body.
Obtain SPICE rotation information for a body.
PartialType
This enumeration indicates whether the partial derivative is taken with respect to Right Ascension,...
This class defines a body-fixed surface point.
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16
const double PI
The mathematical constant PI.
Definition Constants.h:40
Namespace for the standard library.