Isis 3 Programmer Reference
Sensor.cpp
Go to the documentation of this file.
1 
23 #include "Sensor.h"
24 
25 #include <iomanip>
26 
27 #include <QDebug>
28 #include <QString>
29 
30 #include "Angle.h"
31 #include "Constants.h"
32 #include "CubeManager.h"
33 #include "Distance.h"
34 #include "EllipsoidShape.h"
35 #include "IException.h"
36 #include "IString.h"
37 #include "iTime.h"
38 #include "Latitude.h"
39 #include "Longitude.h"
40 #include "NaifStatus.h"
41 #include "Projection.h"
42 #include "ShapeModel.h"
43 #include "SpecialPixel.h"
44 #include "SurfacePoint.h"
45 #include "Target.h"
47 
48 #define MAX(x,y) (((x) > (y)) ? (x) : (y))
49 
50 using namespace std;
51 
52 namespace Isis {
53 
61  Sensor::Sensor(Cube &cube) : Spice(cube) {
62  }
63 
64 
67  }
68 
69 
75  void Sensor::IgnoreElevationModel(bool ignore) {
76  // if we have an elevation model and are not ignoring it,
77  // set p_hasElevationModel to true
78  if (!ignore) {
79  target()->restoreShape();
80  }
81  else {
83  }
84  }
85 
86 
97 
98  QString message = "Pixel Ifov offsets not implemented for this camera.";
100  }
101 
102 
112  void Sensor::setTime(const iTime &time) {
115  }
116 
117 
156  bool Sensor::SetLookDirection(const double v[3]) {
157  //std::cout << "Sensor::SetLookDirection()\n";
158  // The look vector must be in the camera coordinate system
159 
160  // copy v to LookC
161  // lookC[0] = v[0];
162  // lookC[1] = v[1];
163  // lookC[2] = v[2];
164  vector<double> lookC(v, v + 3);
165 
166  // Convert it to body-fixed
167  const vector<double> &lookJ = instrumentRotation()->J2000Vector(lookC);
168  const vector<double> &lookB = bodyRotation()->ReferenceVector(lookJ);
169 
170  // This memcpy does:
171  // m_lookB[0] = lookB[0];
172  // m_lookB[1] = lookB[1];
173  // m_lookB[2] = lookB[2];
174  memcpy(m_lookB, &lookB[0], sizeof(double) * 3);
175  m_newLookB = true;
176 
177  // Don't try to intersect the sky
178  if (target()->isSky()) {
179  target()->shape()->setHasIntersection(false);
180  return false;
181  }
182 
183  // See if it intersects the planet
184  const vector<double> &sB = bodyRotation()->ReferenceVector(
186 
187  // double tolerance = resolution() / 100.0; return
188  // target()->shape()->intersectSurface(sB, lookB, tolerance);
189  return target()->shape()->intersectSurface(sB, lookB);
190  }
191 
192 
202  return target()->shape()->hasIntersection();
203  }
204 
205 
211  void Sensor::Coordinate(double p[3]) const {
212  ShapeModel *shape = target()->shape();
213  p[0] = shape->surfaceIntersection()->GetX().kilometers();
214  p[1] = shape->surfaceIntersection()->GetY().kilometers();
215  p[2] = shape->surfaceIntersection()->GetZ().kilometers();
216  }
217 
218 
225  double Sensor::UniversalLatitude() const {
226  return GetLatitude().degrees();
227  }
228 
229 
237  return target()->shape()->surfaceIntersection()->GetLatitude();
238  }
239 
240 
248  double Sensor::UniversalLongitude() const {
249  return GetLongitude().degrees();
250  }
251 
252 
261  return target()->shape()->surfaceIntersection()->GetLongitude();
262  }
263 
264 
271  return *(target()->shape()->surfaceIntersection());
272  }
273 
274 
283  //TODO: We probably need to be validating surface intersect point is not NULL
284  // Here? or in ShapeModel? or what, man?
286  }
287 
288 
301  return target()->shape()->localRadius(lat, lon);
302  }
303 
304 
316  Distance Sensor::LocalRadius(double lat, double lon) {
317  return target()->shape()->localRadius(Latitude(lat, Angle::Degrees),
318  Longitude(lon, Angle::Degrees));
319  }
320 
321 
327  double Sensor::PhaseAngle() const {
328  std::vector<double> sunB(m_uB, m_uB+3);
329  return target()->shape()->phaseAngle(
330  bodyRotation()->ReferenceVector(instrumentPosition()->Coordinate()), sunB);
331  }
332 
333 
339  double Sensor::EmissionAngle() const {
340  return target()->shape()->emissionAngle(
341  bodyRotation()->ReferenceVector(instrumentPosition()->Coordinate()));
342  }
343 
344 
350  double Sensor::IncidenceAngle() const {
351  std::vector<double> sunB(m_uB, m_uB+3);
352  return target()->shape()->incidenceAngle(sunB);
353  }
354 
355 
374  bool Sensor::SetUniversalGround(const double latitude,
375  const double longitude,
376  bool backCheck) {
377 
378  ShapeModel *shape = target()->shape();
379  shape->clearSurfacePoint();
380 
381  // Can't intersect the sky
382  if (target()->isSky()) {
383  return false;
384  }
385 
386  // Load the latitude/longitude
387  Latitude lat(latitude, Angle::Degrees);
388  Longitude lon(longitude, Angle::Degrees);
389  // Local radius is deferred to (possible derived) shape model method
390  shape->intersectSurface(lat, lon,
391  bodyRotation()->ReferenceVector(instrumentPosition()->Coordinate()),
392  backCheck);
393 
394  return SetGroundLocal(backCheck);
395  }
396 
416  bool Sensor::SetUniversalGround(const double latitude,
417  const double longitude,
418  const double radius,
419  bool backCheck) {
420 
421  ShapeModel *shape = target()->shape();
422  shape->clearSurfacePoint();
423 
424  // Can't intersect the sky
425  if (target()->isSky()) {
426  return false;
427  }
428 
429  Latitude lat(latitude, Angle::Degrees);
430  Longitude lon(longitude, Angle::Degrees);
431  Distance rad(radius, Distance::Meters);
432 
433  shape->intersectSurface(SurfacePoint(lat, lon, rad),
434  bodyRotation()->ReferenceVector(instrumentPosition()->Coordinate()),
435  backCheck);
436 
437  return SetGroundLocal(backCheck);
438  }
439 
440 
458  bool Sensor::SetGround(const SurfacePoint &surfacePt, bool backCheck) {
459  //std::cout << "Sensor::SetGround()\n";
460  ShapeModel *shape = target()->shape();
461  shape->clearSurfacePoint();
462 
463  // Can't intersect the sky
464  if (target()->isSky()) {
465  return false;
466  }
467 
468  shape->intersectSurface(surfacePt,
469  bodyRotation()->ReferenceVector(instrumentPosition()->Coordinate()),
470  backCheck);
471 
472  return SetGroundLocal(backCheck);
473  }
474 
475 
490  bool Sensor::SetGroundLocal(bool backCheck) {
491  ShapeModel *shape = target()->shape();
492  // With the 3 spherical value compute the x/y/z coordinate
493  //latrec_c(m_radius, (m_longitude * PI / 180.0), (m_latitude * PI / 180.0), m_pB);
494 
495 
496  if (!(shape->hasIntersection())) {
497  return false;
498  }
499 
500  // Make sure the point isn't on the backside of the body
501 
502  // This is static purely for performance reasons. A significant speedup
503  // is achieved here.
504  const vector<double> &sB =
506 
507  m_lookB[0] = shape->surfaceIntersection()->GetX().kilometers() - sB[0];
508  m_lookB[1] = shape->surfaceIntersection()->GetY().kilometers() - sB[1];
509  m_lookB[2] = shape->surfaceIntersection()->GetZ().kilometers() - sB[2];
510  m_newLookB = true;
511 
512  // See if the point is on the backside of the target. Note occlusion handling
513  // now handles this in derived shape models that can support it. (KJB 2017-03-23)
514  // This may be good if the computation of the look direction is more sophisticated.
515  if (backCheck) {
516  // Assume the intersection point is good in order to get the emission angle
517  // shape->setHasIntersection(true); //KJB there should be a formal intersection in ShapeModel
518  std::vector<double> lookdir = lookDirectionBodyFixed();
519  if ( !shape->isVisibleFrom(sB, lookdir) ) {
520  shape->clearSurfacePoint();
521  shape->setHasIntersection(false);
522  return false;
523  }
524  }
525 
526  // return with success
527  shape->setHasIntersection(true);
528 
529  return true;
530  }
531 
532 
538  void Sensor::LookDirection(double v[3]) const {
539  vector<double> lookC = instrumentRotation()->ReferenceVector(lookDirectionJ2000());
540  v[0] = lookC[0];
541  v[1] = lookC[1];
542  v[2] = lookC[2];
543  }
544 
550  vector<double> Sensor::lookDirectionBodyFixed() const {
551  vector<double> lookB(3);
552  lookB[0] = m_lookB[0];
553  lookB[1] = m_lookB[1];
554  lookB[2] = m_lookB[2];
555  return lookB;
556  }
557 
558 
564  vector<double> Sensor::lookDirectionJ2000() const {
565  vector<double> lookJ = bodyRotation()->J2000Vector(lookDirectionBodyFixed());
566  return lookJ;
567  }
568 
569 
570 
577  if (m_newLookB) computeRaDec();
578  return m_ra;
579  }
580 
581 
588  if (m_newLookB) computeRaDec();
589  return m_dec;
590  }
591 
592 
597  m_newLookB = false;
598  vector<double> lookB(3);
599  lookB[0] = m_lookB[0];
600  lookB[1] = m_lookB[1];
601  lookB[2] = m_lookB[2];
602  vector<double> lookJ = bodyRotation()->J2000Vector(lookB);
603 
604  SpiceDouble range;
605  recrad_c((SpiceDouble *)&lookJ[0], &range, &m_ra, &m_dec);
606  m_ra *= 180.0 / PI;
607  m_dec *= 180.0 / PI;
608  }
609 
610 
619  bool Sensor::SetRightAscensionDeclination(const double ra, const double dec) {
620  vector<double> lookJ(3);
621  radrec_c(1.0, ra * PI / 180.0, dec * PI / 180.0, (SpiceDouble *)&lookJ[0]);
622 
623  vector<double> lookC = instrumentRotation()->ReferenceVector(lookJ);
624  return SetLookDirection((double *)&lookC[0]);
625  }
626 
627 
636  void Sensor::SpacecraftSurfaceVector(double scSurfaceVector[3]) const {
637  scSurfaceVector[0] = m_lookB[0];
638  scSurfaceVector[1] = m_lookB[1];
639  scSurfaceVector[2] = m_lookB[2];
640  }
641 
642 
648  double Sensor::SlantDistance() const {
649  SpiceDouble psB[3], upsB[3];
650  SpiceDouble dist;
651 
652  std::vector<double> sB = bodyRotation()->ReferenceVector(instrumentPosition()->Coordinate());
653 
654  SpiceDouble pB[3];
655  ShapeModel *shape = target()->shape();
656  pB[0] = shape->surfaceIntersection()->GetX().kilometers();
657  pB[1] = shape->surfaceIntersection()->GetY().kilometers();
658  pB[2] = shape->surfaceIntersection()->GetZ().kilometers();
659 
660  vsub_c(pB, (SpiceDouble *) &sB[0], psB);
661  unorm_c(psB, upsB, &dist);
662  return dist;
663  }
664 
665 
672  double slat, slon;
673  subSolarPoint(slat, slon);
674 
675  double lst = UniversalLongitude() - slon + 180.0;
676  lst = lst / 15.0; // 15 degress per hour
677  if (lst < 0.0) lst += 24.0;
678  if (lst > 24.0) lst -= 24.0;
679  return lst;
680  }
681 
682 
688  double Sensor::SolarDistance() const {
689  // Get the sun coord
690  double sB[3];
691  Spice::sunPosition(sB);
692 
693  // Calc the change
694  ShapeModel *shape = target()->shape();
695  double xChange = sB[0] - shape->surfaceIntersection()->GetX().kilometers();
696  double yChange = sB[1] - shape->surfaceIntersection()->GetY().kilometers();
697  double zChange = sB[2] - shape->surfaceIntersection()->GetZ().kilometers();
698 
699  // Calc the distance and convert to AU
700  double dist = sqrt(xChange*xChange + yChange*yChange + zChange*zChange);
701  dist /= 149597870.691;
702  return dist;
703  }
704 
705 
713  // Get the spacecraft coord
714  double spB[3];
716 
717  // Get subspacecraft point
718  double lat, lon;
719  subSpacecraftPoint(lat, lon);
720  double rlat = lat * PI / 180.0;
721  double rlon = lon * PI / 180.0;
722 
723  // Compute radius
724  Distance rad = LocalRadius(lat, lon);
725 
726  // Now with the 3 spherical value compute the x/y/z coordinate
727  double ssB[3];
728  latrec_c(rad.kilometers(), rlon, rlat, ssB);
729 
730  // Calc the change
731  double xChange = spB[0] - ssB[0];
732  double yChange = spB[1] - ssB[1];
733  double zChange = spB[2] - ssB[2];
734 
735  // Calc the distance
736  double dist = sqrt(xChange*xChange + yChange*yChange + zChange*zChange);
737  return dist;
738  }
739 
740 
746 // Distance Sensor::DemRadius(const SurfacePoint &pt) {
747 // return DemRadius(pt.GetLatitude(), pt.GetLongitude());
748 // }
749 
750 
757 // Distance Sensor::DemRadius(const Latitude &lat, const Longitude &lon) {
758 // if (!m_hasElevationModel) return Distance();
759 // //if (!lat.Valid() || !lon.Valid()) return Distance();
760 // m_demProj->SetUniversalGround(lat.degrees(), lon.degrees());
761 // if (!m_demProj->IsGood()) {
762 // return Distance();
763 // }
764 
765 // m_portal->SetPosition(m_demProj->WorldX(), m_demProj->WorldY(), 1);
766 
767 // m_demCube->read(*m_portal);
768 
769 // const double &radius = m_interp->Interpolate(m_demProj->WorldX(),
770 // m_demProj->WorldY(),
771 // m_portal->DoubleBuffer());
772 
773 // return Distance(radius, Distance::Meters);
774 // Distance fred;
775 // return fred;
776 // }
777 
778 
789 // double Sensor::DemRadius(double lat, double lon) {
790 // if (!m_demProj->SetUniversalGround(lat, lon)) {
791 // return Isis::Null;
792 // }
793 
794 // m_portal->SetPosition(m_demProj->WorldX(), m_demProj->WorldY(), 1);
795 // m_demCube->read(*m_portal);
796 
797 // double radius = m_interp->Interpolate(m_demProj->WorldX(),
798 // m_demProj->WorldY(),
799 // m_portal->DoubleBuffer());
800 // if (Isis::IsSpecial(radius)) {
801 // return Isis::Null;
802 // }
803 
804 // return radius / 1000.0;
805 // double fred;
806 // return fred;
807 // }
814 // bool HasElevationModel() {
815 // return m_hasElevationModel;
816 // };
817 
818 }
This class defines a body-fixed surface point.
Definition: SurfacePoint.h:148
SpicePosition * instrumentPosition() const
Accessor method for the instrument position.
Definition: Spice.cpp:1467
void Coordinate(double p[3]) const
Returns the x,y,z of the surface intersection in BodyFixed km.
Definition: Sensor.cpp:211
double RightAscension()
Returns the right ascension angle (sky longitude).
Definition: Sensor.cpp:576
void IgnoreElevationModel(bool ignore)
This allows you to ignore the cube elevation model and use the ellipse.
Definition: Sensor.cpp:75
double SolarDistance() const
Returns the distance between the sun and surface point in AU.
Definition: Sensor.cpp:688
Parse and return pieces of a time string.
Definition: iTime.h:78
const double PI
The mathematical constant PI.
Definition: Constants.h:56
virtual QList< QPointF > PixelIfovOffsets()
This method is implemented in Camera which defaults to the (pixel pitch * summing mode ) / 2...
Definition: Sensor.cpp:96
double UniversalLatitude() const
Returns the planetocentric latitude, in degrees, at the surface intersection point in the body fixed ...
Definition: Sensor.cpp:225
SpiceDouble m_dec
Decliation (sky latitude)
Definition: Sensor.h:261
bool hasIntersection()
Returns intersection status.
Definition: ShapeModel.cpp:362
SpiceRotation * bodyRotation() const
Accessor method for the body rotation.
Definition: Spice.cpp:1478
bool SetRightAscensionDeclination(const double ra, const double dec)
Given the ra/dec compute the look direction.
Definition: Sensor.cpp:619
bool SetGround(const SurfacePoint &surfacePt, bool backCheck=true)
This overloaded method has the opposite function as SetLookDirection.
Definition: Sensor.cpp:458
Namespace for the standard library.
SpiceDouble m_lookB[3]
Look direction in body fixed.
Definition: Sensor.h:257
This class is designed to encapsulate the concept of a Latitude.
Definition: Latitude.h:63
void computeRaDec()
Computes the ra/dec from the look direction.
Definition: Sensor.cpp:596
bool SetUniversalGround(const double latitude, const double longitude, bool backCheck=true)
This is the opposite routine for SetLookDirection.
Definition: Sensor.cpp:374
SurfacePoint * surfaceIntersection() const
Returns the surface intersection for this ShapeModel.
Definition: ShapeModel.cpp:352
bool SetLookDirection(const double v[3])
Sets the look direction of the spacecraft.
Definition: Sensor.cpp:156
bool m_newLookB
flag to indicate we need to recompute ra/dec
Definition: Sensor.h:259
double SlantDistance() const
Return the distance between the spacecraft and surface point in kmv.
Definition: Sensor.cpp:648
virtual double emissionAngle(const std::vector< double > &sB)
Computes and returns emission angle, in degrees, given the observer position.
Definition: ShapeModel.cpp:179
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
This error is for when a programmer made an API call that was illegal.
Definition: IException.h:162
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
bool SetGroundLocal(bool backCheck)
Computes look vector.
Definition: Sensor.cpp:490
Distance LocalRadius() const
Returns the local radius at the intersection point.
Definition: Sensor.cpp:282
void setHasIntersection(bool b)
Sets the flag to indicate whether this ShapeModel has an intersection.
Definition: ShapeModel.cpp:548
double EmissionAngle() const
Returns the emission angle in degrees.
Definition: Sensor.cpp:339
This class is designed to encapsulate the concept of a Longitude.
Definition: Longitude.h:52
virtual double phaseAngle(const std::vector< double > &sB, const std::vector< double > &uB)
Computes and returns phase angle, in degrees, given the positions of the observer and illuminator...
Definition: ShapeModel.cpp:318
void restoreShape()
Restores the shape to the original after setShapeEllipsoid has overridden it.
Definition: Target.cpp:575
virtual ~Sensor()
Destroys the Sensor.
Definition: Sensor.cpp:66
Degrees are generally considered more human readable, 0-360 is one circle, however most math does not...
Definition: Angle.h:73
std::vector< double > ReferenceVector(const std::vector< double > &jVec)
Given a direction vector in J2000, return a reference frame direction.
Target * target() const
Returns a pointer to the target object.
Definition: Spice.cpp:1290
void subSolarPoint(double &lat, double &lon)
Returns the sub-solar latitude/longitude in universal coordinates (0-360 positive east...
Definition: Spice.cpp:1251
#define _FILEINFO_
Macro for the filename and line number.
Definition: IException.h:40
SpicePosition * sunPosition() const
Accessor method for the sun position.
Definition: Spice.cpp:1456
virtual double incidenceAngle(const std::vector< double > &uB)
Computes and returns incidence angle, in degrees, given the illuminator position. ...
Definition: ShapeModel.cpp:226
ShapeModel * shape() const
Return the shape.
Definition: Target.cpp:615
Longitude GetLongitude() const
Returns a positive east, 0-360 domain longitude object at the surface intersection point in the body ...
Definition: Sensor.cpp:260
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:112
double UniversalLongitude() const
Returns the positive east, 0-360 domain longitude, in degrees, at the surface intersection point in t...
Definition: Sensor.cpp:248
virtual void clearSurfacePoint()
Clears or resets the current surface point.
Definition: ShapeModel.cpp:380
double PhaseAngle() const
Returns the phase angle in degrees.
Definition: Sensor.cpp:327
double SpacecraftAltitude()
Returns the distance from the spacecraft to the subspacecraft point in km.
Definition: Sensor.cpp:712
Define shapes and provide utilities for Isis3 targets.
Definition: ShapeModel.h:78
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
SpiceDouble m_ra
Right ascension (sky longitude)
Definition: Sensor.h:260
Longitude GetLongitude() const
Return the body-fixed longitude for the surface point.
virtual bool isVisibleFrom(const std::vector< double > observerPos, const std::vector< double > lookDirection)
Default occulsion implementation.
Definition: ShapeModel.cpp:425
std::vector< double > J2000Vector(const std::vector< double > &rVec)
Given a direction vector in the reference frame, return a J2000 direction.
void LookDirection(double v[3]) const
Returns the look direction in the camera coordinate system.
Definition: Sensor.cpp:538
void setShapeEllipsoid()
Set the shape to the ellipsoid and save the original shape.
Definition: Target.cpp:593
Isis exception class.
Definition: IException.h:107
SurfacePoint GetSurfacePoint() const
Returns the surface point (most efficient accessor).
Definition: Sensor.cpp:270
Namespace for ISIS/Bullet specific routines.
Definition: Apollo.h:31
SpiceRotation * instrumentRotation() const
Accessor method for the instrument rotation.
Definition: Spice.cpp:1489
double IncidenceAngle() const
Returns the incidence angle in degrees.
Definition: Sensor.cpp:350
std::vector< double > lookDirectionJ2000() const
Returns the look direction in the camera coordinate system.
Definition: Sensor.cpp:564
Obtain SPICE information for a spacecraft.
Definition: Spice.h:294
The distance is being specified in meters.
Definition: Distance.h:56
double kilometers() const
Get the displacement in kilometers.
double LocalSolarTime()
Return the local solar time in hours.
Definition: Sensor.cpp:671
std::vector< double > lookDirectionBodyFixed() const
Returns the look direction in the body fixed coordinate system.
Definition: Sensor.cpp:550
SpiceDouble m_uB[3]
This contains the sun position (u) in the bodyfixed reference frame (B).
Definition: Spice.h:377
void SpacecraftSurfaceVector(double scSurfaceVector[3]) const
Sets the vector between the spacecraft and surface point in body-fixed.
Definition: Sensor.cpp:636
Distance GetLocalRadius() const
Return the radius of the surface point.
Latitude GetLatitude() const
Returns a planetocentric latitude object at the surface intersection point in body fixed...
Definition: Sensor.cpp:236
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:705
bool HasSurfaceIntersection() const
Returns if the last call to either SetLookDirection or SetUniversalGround had a valid intersection wi...
Definition: Sensor.cpp:201
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
double Declination()
Returns the declination angle (sky latitude).
Definition: Sensor.cpp:587
IO Handler for Isis Cubes.
Definition: Cube.h:170
iTime time() const
Returns the ephemeris time in seconds which was used to obtain the spacecraft and sun positions...
Definition: Spice.cpp:809
void subSpacecraftPoint(double &lat, double &lon)
Returns the sub-spacecraft latitude/longitude in universal coordinates (0-360 positive east...
Definition: Spice.cpp:1202