Isis 3 Programmer Reference
Sensor.cpp
1
6/* SPDX-License-Identifier: CC0-1.0 */
7#include "Sensor.h"
8
9#include <iomanip>
10
11#include <QDebug>
12#include <QString>
13
14#include "MathUtils.h"
15
16#include "Angle.h"
17#include "Constants.h"
18#include "CubeManager.h"
19#include "Distance.h"
20#include "EllipsoidShape.h"
21#include "IException.h"
22#include "IString.h"
23#include "iTime.h"
24#include "Latitude.h"
25#include "Longitude.h"
26#include "NaifStatus.h"
27#include "Projection.h"
28#include "ShapeModel.h"
29#include "SpecialPixel.h"
30#include "SurfacePoint.h"
31#include "Target.h"
32#include "UniqueIOCachingAlgorithm.h"
33
34#define MAX(x,y) (((x) > (y)) ? (x) : (y))
35
36using namespace std;
37
38namespace Isis {
39
47 Sensor::Sensor(Cube &cube) : Spice(cube) {
48 m_newLookB = false;
49 }
50
51
55
56
62 void Sensor::IgnoreElevationModel(bool ignore) {
63 // if we have an elevation model and are not ignoring it,
64 // set p_hasElevationModel to true
65 if (!ignore) {
66 target()->restoreShape();
67 }
68 else {
69 target()->setShapeEllipsoid();
70 }
71 }
72
73
83 QList<QPointF> Sensor::PixelIfovOffsets() {
84
85 QString message = "Pixel Ifov offsets not implemented for this camera.";
86 throw IException(IException::Programmer, message, _FILEINFO_);
87 }
88
89
99 void Sensor::setTime(const iTime &time) {
101 target()->shape()->clearSurfacePoint();
102 }
103
104
143 bool Sensor::SetLookDirection(const double v[3]) {
144 // std::cout << "Sensor::SetLookDirection()\n";
145 // The look vector must be in the camera coordinate system
146
147 // copy v to LookC
148 // lookC[0] = v[0];
149 // lookC[1] = v[1];
150 // lookC[2] = v[2]
151 vector<double> lookC(v, v + 3);
152
153 // Convert it to body-fixed
154 const vector<double> &lookJ = instrumentRotation()->J2000Vector(lookC);
155 const vector<double> &lookB = bodyRotation()->ReferenceVector(lookJ);
156
157 // This memcpy does:
158 // m_lookB[0] = lookB[0];
159 // m_lookB[1] = lookB[1];
160 // m_lookB[2] = lookB[2];
161 memcpy(m_lookB, &lookB[0], sizeof(double) * 3);
162 m_newLookB = true;
163
164 // Don't try to intersect the sky
165 if (target()->isSky()) {
166 target()->shape()->setHasIntersection(false);
167 return false;
168 }
169
170 // See if it intersects the planet
171 const vector<double> &sB = bodyRotation()->ReferenceVector(
173
174 // double tolerance = resolution() / 100.0; return
175 // target()->shape()->intersectSurface(sB, lookB, tolerance);
176 return target()->shape()->intersectSurface(sB, lookB);
177 }
178
179
189 return target()->shape()->hasIntersection();
190 }
191
192
198 void Sensor::Coordinate(double p[3]) const {
199 ShapeModel *shape = target()->shape();
200 p[0] = shape->surfaceIntersection()->GetX().kilometers();
201 p[1] = shape->surfaceIntersection()->GetY().kilometers();
202 p[2] = shape->surfaceIntersection()->GetZ().kilometers();
203 }
204
205
213 return GetLatitude().degrees();
214 }
215
216
224 return target()->shape()->surfaceIntersection()->GetLatitude();
225 }
226
227
236 return GetLongitude().degrees();
237 }
238
239
248 return target()->shape()->surfaceIntersection()->GetLongitude();
249 }
250
251
258 return *(target()->shape()->surfaceIntersection());
259 }
260
261
270 //TODO: We probably need to be validating surface intersect point is not NULL
271 // Here? or in ShapeModel? or what, man?
272 return target()->shape()->surfaceIntersection()->GetLocalRadius();
273 }
274
275
288 return target()->shape()->localRadius(lat, lon);
289 }
290
291
303 Distance Sensor::LocalRadius(double lat, double lon) {
304 return target()->shape()->localRadius(Latitude(lat, Angle::Degrees),
306 }
307
308
314 double Sensor::PhaseAngle() const {
315 double sensorPosBf[3];
316 instrumentBodyFixedPosition(sensorPosBf);
317 double groundPtBf[3];
318 Coordinate(groundPtBf);
319 return RAD2DEG * SensorUtilities::sepAngle(sensorPosBf, groundPtBf, m_uB);
320 }
321
322
328 double Sensor::EmissionAngle() const {
329 return target()->shape()->emissionAngle(
330 bodyRotation()->ReferenceVector(instrumentPosition()->Coordinate()));
331 }
332
333
339 double Sensor::IncidenceAngle() const {
340 std::vector<double> sunB(m_uB, m_uB+3);
341 return target()->shape()->incidenceAngle(sunB);
342 }
343
344
363 bool Sensor::SetUniversalGround(const double latitude,
364 const double longitude,
365 bool backCheck) {
366
367 ShapeModel *shape = target()->shape();
368 shape->clearSurfacePoint();
369
370 // Can't intersect the sky
371 if (target()->isSky()) {
372 return false;
373 }
374
375 // Load the latitude/longitude
376 Latitude lat(latitude, Angle::Degrees);
377 Longitude lon(longitude, Angle::Degrees);
378 // Local radius is deferred to (possible derived) shape model method
379 shape->intersectSurface(lat, lon,
380 bodyRotation()->ReferenceVector(instrumentPosition()->Coordinate()),
381 backCheck);
382
383 return SetGroundLocal(backCheck);
384 }
385
405 bool Sensor::SetUniversalGround(const double latitude,
406 const double longitude,
407 const double radius,
408 bool backCheck) {
409
410 ShapeModel *shape = target()->shape();
411 shape->clearSurfacePoint();
412
413 // Can't intersect the sky
414 if (target()->isSky()) {
415 return false;
416 }
417
418 Latitude lat(latitude, Angle::Degrees);
419 Longitude lon(longitude, Angle::Degrees);
420 Distance rad(radius, Distance::Meters);
421
422 shape->intersectSurface(SurfacePoint(lat, lon, rad),
423 bodyRotation()->ReferenceVector(instrumentPosition()->Coordinate()),
424 backCheck);
425
426 return SetGroundLocal(backCheck);
427 }
428
429
447 bool Sensor::SetGround(const SurfacePoint &surfacePt, bool backCheck) {
448 //std::cout << "Sensor::SetGround()\n";
449 ShapeModel *shape = target()->shape();
450 shape->clearSurfacePoint();
451
452 // Can't intersect the sky
453 if (target()->isSky()) {
454 return false;
455 }
456
457 shape->intersectSurface(surfacePt,
458 bodyRotation()->ReferenceVector(instrumentPosition()->Coordinate()),
459 backCheck);
460
461 return SetGroundLocal(backCheck);
462 }
463
464
479 bool Sensor::SetGroundLocal(bool backCheck) {
480 ShapeModel *shape = target()->shape();
481 // With the 3 spherical value compute the x/y/z coordinate
482 //latrec_c(m_radius, (m_longitude * PI / 180.0), (m_latitude * PI / 180.0), m_pB);
483
484
485 if (!(shape->hasIntersection())) {
486 return false;
487 }
488
489 // Make sure the point isn't on the backside of the body
490
491 // This is static purely for performance reasons. A significant speedup
492 // is achieved here.
493 const vector<double> &sB =
494 bodyRotation()->ReferenceVector(instrumentPosition()->Coordinate());
495
496 m_lookB[0] = shape->surfaceIntersection()->GetX().kilometers() - sB[0];
497 m_lookB[1] = shape->surfaceIntersection()->GetY().kilometers() - sB[1];
498 m_lookB[2] = shape->surfaceIntersection()->GetZ().kilometers() - sB[2];
499 m_newLookB = true;
500
501 // See if the point is on the backside of the target. Note occlusion handling
502 // now handles this in derived shape models that can support it. (KJB 2017-03-23)
503 // This may be good if the computation of the look direction is more sophisticated.
504 if (backCheck) {
505 // Assume the intersection point is good in order to get the emission angle
506 // shape->setHasIntersection(true); //KJB there should be a formal intersection in ShapeModel
507 std::vector<double> lookdir = lookDirectionBodyFixed();
508 if ( !shape->isVisibleFrom(sB, lookdir) ) {
509 shape->clearSurfacePoint();
510 shape->setHasIntersection(false);
511 return false;
512 }
513 }
514
515 // return with success
516 shape->setHasIntersection(true);
517
518 return true;
519 }
520
521
527 void Sensor::LookDirection(double v[3]) const {
528 vector<double> lookC = instrumentRotation()->ReferenceVector(lookDirectionJ2000());
529 v[0] = lookC[0];
530 v[1] = lookC[1];
531 v[2] = lookC[2];
532 }
533
539 vector<double> Sensor::lookDirectionBodyFixed() const {
540 vector<double> lookB(3);
541 lookB[0] = m_lookB[0];
542 lookB[1] = m_lookB[1];
543 lookB[2] = m_lookB[2];
544 return lookB;
545 }
546
547
553 vector<double> Sensor::lookDirectionJ2000() const {
554 vector<double> lookJ = bodyRotation()->J2000Vector(lookDirectionBodyFixed());
555 return lookJ;
556 }
557
558
559
566 if (m_newLookB) {
567 computeRaDec();
568 }
569 return m_ra;
570 }
571
572
579 if (m_newLookB) {
580 computeRaDec();
581 }
582 return m_dec;
583 }
584
585
590 m_newLookB = false;
591 vector<double> lookB = {m_lookB[0], m_lookB[1], m_lookB[2]};
592 vector<double> lookJ = bodyRotation()->J2000Vector(lookB);
593
594 SensorUtilities::GroundPt3D sphericalPt = SensorUtilities::rectToSpherical(&lookJ[0]);
595 m_ra = sphericalPt.lon;
596 // Convert to [0, 2pi] domain
597 if (m_ra < 0) {
598 m_ra += 2 * PI;
599 }
600 m_ra *= RAD2DEG;
601 m_dec = sphericalPt.lat * RAD2DEG;
602 }
603
604
613 bool Sensor::SetRightAscensionDeclination(const double ra, const double dec) {
614 double raRad = ra * DEG2RAD;
615 double decRad = dec * DEG2RAD;
616
617 // Make the radius bigger, some multiple of the body radius -or- use sensor position at the reference point
618 SensorUtilities::GroundPt3D sphericalPt = {decRad, raRad, 1};
619 SensorUtilities::Vec rectPt = SensorUtilities::sphericalToRect(sphericalPt);
620
621 vector<double> lookC = instrumentRotation()->ReferenceVector(rectPt);
622 return SetLookDirection(&lookC[0]);
623 }
624
625
634 void Sensor::SpacecraftSurfaceVector(double scSurfaceVector[3]) const {
635 scSurfaceVector[0] = m_lookB[0];
636 scSurfaceVector[1] = m_lookB[1];
637 scSurfaceVector[2] = m_lookB[2];
638 }
639
640
646 double Sensor::SlantDistance() const {
647 double sensorPos[3];
649
650 SurfacePoint *surfPoint = target()->shape()->surfaceIntersection();
651 SensorUtilities::Vec groundPt = {
652 surfPoint->GetX().kilometers(),
653 surfPoint->GetY().kilometers(),
654 surfPoint->GetZ().kilometers()};
655
656 return SensorUtilities::distance(sensorPos, groundPt);
657 }
658
659
666 double slat, slon;
667 subSolarPoint(slat, slon);
668
669 double lst = UniversalLongitude() - slon + 180.0;
670 lst = lst / 15.0; // 15 degress per hour
671 if (lst < 0.0) lst += 24.0;
672 if (lst > 24.0) lst -= 24.0;
673 return lst;
674 }
675
676
682 double Sensor::SolarDistance() const {
683 // Get the sun coord
684 double sB[3];
686
687 SurfacePoint *intersection = target()->shape()->surfaceIntersection();
688 SensorUtilities::Vec groundPt = {
689 intersection->GetX().kilometers(),
690 intersection->GetY().kilometers(),
691 intersection->GetZ().kilometers()};
692
693 return SensorUtilities::distance(groundPt, sB) / 149597870.691;
694 }
695
696
704 // Get the spacecraft coord
705 double sensorPos[3];
706 Spice::instrumentPosition(sensorPos);
707
708 // Get subspacecraft point
709 double lat, lon;
710 subSpacecraftPoint(lat, lon);
711
712 // Compute radius
713 Distance rad = LocalRadius(lat, lon);
714
715 // Take the difference
716 return SensorUtilities::magnitude(sensorPos) - rad.kilometers();
717 }
718}
double degrees() const
Get the angle in units of Degrees.
Definition Angle.h:232
@ Degrees
Degrees are generally considered more human readable, 0-360 is one circle, however most math does not...
Definition Angle.h:56
IO Handler for Isis Cubes.
Definition Cube.h:168
double kilometers() const
Get the displacement in kilometers.
Distance measurement, usually in meters.
Definition Distance.h:34
@ 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
void setTime(const iTime &time)
By setting the time you essential set the position of the spacecraft and body as indicated in the cla...
Definition Sensor.cpp:99
virtual SurfacePoint GetSurfacePoint() const
Returns the surface point (most efficient accessor).
Definition Sensor.cpp:257
bool SetUniversalGround(const double latitude, const double longitude, bool backCheck=true)
This is the opposite routine for SetLookDirection.
Definition Sensor.cpp:363
double LocalSolarTime()
Return the local solar time in hours.
Definition Sensor.cpp:665
SpiceDouble m_lookB[3]
Look direction in body fixed.
Definition Sensor.h:234
SpiceDouble m_dec
Decliation (sky latitude)
Definition Sensor.h:242
virtual double UniversalLatitude() const
Returns the planetocentric latitude, in degrees, at the surface intersection point in the body fixed ...
Definition Sensor.cpp:212
virtual double RightAscension()
Returns the right ascension angle (sky longitude).
Definition Sensor.cpp:565
Longitude GetLongitude() const
Returns a positive east, 0-360 domain longitude object at the surface intersection point in the body ...
Definition Sensor.cpp:247
virtual double SolarDistance() const
Returns the distance between the sun and surface point in AU.
Definition Sensor.cpp:682
bool HasSurfaceIntersection() const
Returns if the last call to either SetLookDirection or SetUniversalGround had a valid intersection wi...
Definition Sensor.cpp:188
virtual double SlantDistance() const
Return the distance between the spacecraft and surface point in kmv.
Definition Sensor.cpp:646
void SpacecraftSurfaceVector(double scSurfaceVector[3]) const
Sets the vector between the spacecraft and surface point in body-fixed.
Definition Sensor.cpp:634
bool m_newLookB
flag to indicate we need to recompute ra/dec
Definition Sensor.h:235
virtual QList< QPointF > PixelIfovOffsets()
This method is implemented in Camera which defaults to the (pixel pitch * summing mode ) / 2.
Definition Sensor.cpp:83
Latitude GetLatitude() const
Returns a planetocentric latitude object at the surface intersection point in body fixed.
Definition Sensor.cpp:223
SpiceDouble m_ra
Right ascension (sky longitude)
Definition Sensor.h:241
double SpacecraftAltitude()
Returns the distance from the spacecraft to the subspacecraft point in km.
Definition Sensor.cpp:703
virtual ~Sensor()
Destroys the Sensor.
Definition Sensor.cpp:53
virtual std::vector< double > lookDirectionBodyFixed() const
Returns the look direction in the body fixed coordinate system.
Definition Sensor.cpp:539
bool SetGround(const SurfacePoint &surfacePt, bool backCheck=true)
This overloaded method has the opposite function as SetLookDirection.
Definition Sensor.cpp:447
bool SetGroundLocal(bool backCheck)
Computes look vector.
Definition Sensor.cpp:479
virtual std::vector< double > lookDirectionJ2000() const
Returns the look direction in the camera coordinate system.
Definition Sensor.cpp:553
void IgnoreElevationModel(bool ignore)
This allows you to ignore the cube elevation model and use the ellipse.
Definition Sensor.cpp:62
virtual double PhaseAngle() const
Returns the phase angle in degrees.
Definition Sensor.cpp:314
bool SetRightAscensionDeclination(const double ra, const double dec)
Given the ra/dec compute the look direction.
Definition Sensor.cpp:613
virtual double IncidenceAngle() const
Returns the incidence angle in degrees.
Definition Sensor.cpp:339
virtual double UniversalLongitude() const
Returns the positive east, 0-360 domain longitude, in degrees, at the surface intersection point in t...
Definition Sensor.cpp:235
void Coordinate(double p[3]) const
Returns the x,y,z of the surface intersection in BodyFixed km.
Definition Sensor.cpp:198
Sensor(Cube &cube)
Constructs a Sensor object and loads SPICE kernels using information from the label object.
Definition Sensor.cpp:47
Distance LocalRadius() const
Returns the local radius at the intersection point.
Definition Sensor.cpp:269
virtual double Declination()
Returns the declination angle (sky latitude).
Definition Sensor.cpp:578
virtual double EmissionAngle() const
Returns the emission angle in degrees.
Definition Sensor.cpp:328
void LookDirection(double v[3]) const
Returns the look direction in the camera coordinate system.
Definition Sensor.cpp:527
bool SetLookDirection(const double v[3])
Sets the look direction of the spacecraft.
Definition Sensor.cpp:143
void computeRaDec()
Computes the ra/dec from the look direction.
Definition Sensor.cpp:589
Define shapes and provide utilities for Isis targets.
Definition ShapeModel.h:66
virtual void clearSurfacePoint()
Clears or resets the current surface point.
bool hasIntersection()
Returns intersection status.
void setHasIntersection(bool b)
Sets the flag to indicate whether this ShapeModel has an intersection.
virtual SurfacePoint * surfaceIntersection() const
Returns the surface intersection for this ShapeModel.
virtual bool isVisibleFrom(const std::vector< double > observerPos, const std::vector< double > lookDirection)
Default occulsion implementation.
Obtain SPICE information for a spacecraft.
Definition Spice.h:283
virtual void setTime(const iTime &time)
Sets the ephemeris time and reads the spacecraft and sun position from the kernels at that instant in...
Definition Spice.cpp:787
virtual SpiceRotation * bodyRotation() const
Accessor method for the body rotation.
Definition Spice.cpp:1623
virtual void subSolarPoint(double &lat, double &lon)
Returns the sub-solar latitude/longitude in universal coordinates (0-360 positive east,...
Definition Spice.cpp:1341
virtual void instrumentBodyFixedPosition(double p[3]) const
Returns the spacecraft position in body-fixed frame km units.
Definition Spice.cpp:842
virtual Target * target() const
Returns a pointer to the target object.
Definition Spice.cpp:1380
virtual iTime time() const
Returns the ephemeris time in seconds which was used to obtain the spacecraft and sun positions.
Definition Spice.cpp:891
virtual SpiceRotation * instrumentRotation() const
Accessor method for the instrument rotation.
Definition Spice.cpp:1634
virtual SpicePosition * instrumentPosition() const
Accessor method for the instrument position.
Definition Spice.cpp:1612
SpiceDouble m_uB[3]
This contains the sun position (u) in the bodyfixed reference frame (B).
Definition Spice.h:369
virtual SpicePosition * sunPosition() const
Accessor method for the sun position.
Definition Spice.cpp:1601
virtual void subSpacecraftPoint(double &lat, double &lon)
Returns the sub-spacecraft latitude/longitude in universal coordinates (0-360 positive east,...
Definition Spice.cpp:1290
This class defines a body-fixed surface point.
Parse and return pieces of a time string.
Definition iTime.h:65
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16
const double DEG2RAD
Multiplier for converting from degrees to radians.
Definition Constants.h:43
const double RAD2DEG
Multiplier for converting from radians to degrees.
Definition Constants.h:44
const double PI
The mathematical constant PI.
Definition Constants.h:40
Namespace for the standard library.