Commit 95e62c5b authored by Janet Barrett's avatar Janet Barrett
Browse files

Moved Kaguya MI camera class from local to kaguya directory so it is available...

Moved Kaguya MI camera class from local to kaguya directory so it is available in the next public release. Fixes #2047

git-svn-id: http://subversion.wr.usgs.gov/repos/prog/isis3/trunk@5739 41f8697f-d340-4b68-9986-7bafba869bb8
parent 07a328c4
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
Group = KAGUYA/MI-VIS
  Version = 1
  Library = KaguyaMiCamera
  Routine = KaguyaMiCameraPlugin
EndGroup

Group = KAGUYA/MI-NIR
  Version = 1
  Library = KaguyaMiCamera
  Routine = KaguyaMiCameraPlugin
EndGroup
+116 −0
Original line number Diff line number Diff line
/**
 * @file
 *
 *   Unless noted otherwise, the portions of Isis written by the USGS are public
 *   domain. See individual third-party library and package descriptions for 
 *   intellectual property information,user agreements, and related information.
 *
 *   Although Isis has been used by the USGS, no warranty, expressed or implied,
 *   is made by the USGS as to the accuracy and functioning of such software 
 *   and related material nor shall the fact of distribution constitute any such 
 *   warranty, and no responsibility is assumed by the USGS in connection 
 *   therewith.
 *
 *   For additional information, launch
 *   $ISISROOT/doc//documents/Disclaimers/Disclaimers.html in a browser or see 
 *   the Privacy & Disclaimers page on the Isis website,
 *   http://isis.astrogeology.usgs.gov, and the USGS privacy and disclaimers on
 *   http://www.usgs.gov/privacy.html.
 */
#include "KaguyaMiCamera.h"

#include <iomanip>

#include "CameraFocalPlaneMap.h"
#include "IException.h"
#include "IString.h"
#include "iTime.h"
#include "LineScanCameraDetectorMap.h"
#include "LineScanCameraGroundMap.h"
#include "LineScanCameraSkyMap.h"
#include "KaguyaMiCameraDistortionMap.h"
#include "NaifStatus.h"

using namespace std;
namespace Isis {
  /**
   * Constructor for the Kaguya MI Camera Model
   *
   * @param lab Pvl Label to create the camera model from
   *
   * @internal 
   *   @history 2012-06-14 Orrin Thomas - original version
   */
  KaguyaMiCamera::KaguyaMiCamera(Cube &cube) : LineScanCamera(cube) {
    NaifStatus::CheckErrors();
    // Set up the camera info from ik/iak kernels

    SetFocalLength();
    //Kaguya IK kernal uses INS-131???_PIXEL_SIZE instead of PIXEL_PITCH
    QString ikernKey = "INS" + toString(naifIkCode()) + "_PIXEL_SIZE";
    SetPixelPitch(getDouble(ikernKey));
 

    // Get the start time from labels
    Pvl &lab = *cube.label();
    PvlGroup &inst = lab.findGroup("Instrument", Pvl::Traverse);
    QString stime = (QString)inst["StartTime"];
    SpiceDouble etStart=0;

    if(stime != "NULL") {
      etStart = iTime(stime).Et();
    }
    else {
      //TODO throw an error if "StartTime" keyword is absent
    }

    NaifStatus::CheckErrors();


    // Get other info from labels
    double lineRate = (double) inst["CorrectedSamplingInterval"] / 1000.0;
    setTime(etStart);

    // Setup detector map
    LineScanCameraDetectorMap *detectorMap = new LineScanCameraDetectorMap(this, etStart, lineRate);
    detectorMap->SetDetectorSampleSumming(1.0);
    detectorMap->SetStartingDetectorSample(1.0);

    // Setup focal plane map
    CameraFocalPlaneMap *focalMap = new CameraFocalPlaneMap(this, naifIkCode());
    // Retrieve boresight location from instrument kernel (IK) (addendum?)
    ikernKey = "INS" + toString(naifIkCode()) + "_CENTER";
    double sampleBoreSight = getDouble(ikernKey,0);
    double lineBoreSight = getDouble(ikernKey,1)-1.0;

    focalMap->SetDetectorOrigin(sampleBoreSight, lineBoreSight);
    focalMap->SetDetectorOffset(0.0, 0.0);


    KaguyaMiCameraDistortionMap *distMap = new KaguyaMiCameraDistortionMap(this);
    //LroNarrowAngleDistortionMap *distMap = new LroNarrowAngleDistortionMap(this);
    distMap->SetDistortion(naifIkCode());

    // Setup the ground and sky map
    new LineScanCameraGroundMap(this);
    new LineScanCameraSkyMap(this);

    LoadCache();

    NaifStatus::CheckErrors();
  }
}

/**
 * This is the function that is called in order to instantiate a
 * KaguyaMi object.
 *
 * @param lab Cube labels
 *
 * @return Isis::Camera* KaguyaMiCamera
 * @internal
 *   @history 2012-06-14 Orrin Thomas - original version
 */
extern "C" Isis::Camera *KaguyaMiCameraPlugin(Isis::Cube &cube) {
  return new Isis::KaguyaMiCamera(cube);
}
+73 −0
Original line number Diff line number Diff line
#ifndef KaguyaMiCamera_h
#define KaguyaMiCamera_h
/** 
 * @file 
 *  
 *   Unless noted otherwise, the portions of Isis written by the USGS are public
 *   domain. See individual third-party library and package descriptions for
 *   intellectual property information,user agreements, and related information.
 *
 *   Although Isis has been used by the USGS, no warranty, expressed or implied,
 *   is made by the USGS as to the accuracy and functioning of such software
 *   and related material nor shall the fact of distribution constitute any such
 *   warranty, and no responsibility is assumed by the USGS in connection
 *   therewith.
 *
 *   For additional information, launch
 *   $ISISROOT/doc//documents/Disclaimers/Disclaimers.html in a browser or see
 *   the Privacy &amp; Disclaimers page on the Isis website,
 *   http://isis.astrogeology.usgs.gov, and the USGS privacy and disclaimers on
 *   http://www.usgs.gov/privacy.html.
 */

#include "LineScanCamera.h"

namespace Isis {
  /**
   * @brief LRO Narrow Angle Camera Model
   *
   * This is the camera model for the Kaguya Multiband pushbroom imagers (VIR and NIR)
   *
   * @ingroup SpiceInstrumentsAndCameras
   * @ingroup Kaguya
   *
   * @author 2009-02-20 Jacob Danton
   *
   * @internal
   *   @history 2012-06-14 Orrin Thomas - original version
   *   @history 2012-07-06 Debbie A. Cook, Updated Spice members to be more compliant with Isis 
   *                          coding standards. References #972.
   */
  class KaguyaMiCamera : public LineScanCamera {
    public:
      KaguyaMiCamera(Cube &cube);

      //! Destroys the LroNarrowAngleCamera object
      ~KaguyaMiCamera() {};

      /**
       * CK frame ID -  - Instrument Code from spacit run on CK
       *  
       * @return @b int The appropriate instrument code for the "Camera-matrix" 
       *         Kernel Frame ID
       */
      virtual int CkFrameId() const { return (-131000); }

      /** 
       * CK Reference ID - J2000
       * 
       * @return @b int The appropriate instrument code for the "Camera-matrix"
       *         Kernel Reference ID
       */
      virtual int CkReferenceId() const { return (1); }

      /** 
       *  SPK Reference ID - J2000
       *  
       * @return @b int The appropriate instrument code for the Spacecraft 
       *         Kernel Reference ID
       */
      virtual int SpkReferenceId() const { return (1); }
  };
};
#endif
+61 −0
Original line number Diff line number Diff line
Unit Test for KabuyaMiCamera...
FileName: MI_VIS.cub
CK Frame: -131330

Kernel IDs: 
CK Frame ID = -131000
CK Reference ID = 1
SPK Target ID = -131
SPK Reference ID = 1

For upper left corner ...
DeltaSample = 0.000000000
DeltaLine = 0.000000000

For upper right corner ...
DeltaSample = 0.000000000
DeltaLine = 0.000000000

For lower left corner ...
DeltaSample = 0.000000000
DeltaLine = 0.000000000

For lower right corner ...
DeltaSample = 0.000000000
DeltaLine = 0.000000000

For center pixel position ...
Latitude OK
Longitude OK

--------------------------------------------
FileName: MI_NIR.cub
CK Frame: -131340

Kernel IDs: 
CK Frame ID = -131000
CK Reference ID = 1
SPK Target ID = -131
SPK Reference ID = 1

For upper left corner ...
DeltaSample = 0.000000000
DeltaLine = 0.000000000

For upper right corner ...
DeltaSample = 0.000000000
DeltaLine = 0.000000000

For lower left corner ...
DeltaSample = 0.000000000
DeltaLine = 0.000000000

For lower right corner ...
DeltaSample = 0.000000000
DeltaLine = 0.000000000

For center pixel position ...
Latitude OK
Longitude OK

--------------------------------------------
+186 −0
Original line number Diff line number Diff line
/**
 * @file
 *
 *   Unless noted otherwise, the portions of Isis written by the USGS are public
 *   domain. See individual third-party library and package descriptions for 
 *   intellectual property information,user agreements, and related information.
 *
 *   Although Isis has been used by the USGS, no warranty, expressed or implied,
 *   is made by the USGS as to the accuracy and functioning of such software 
 *   and related material nor shall the fact of distribution constitute any such 
 *   warranty, and no responsibility is assumed by the USGS in connection 
 *   therewith.
 *
 *   For additional information, launch
 *   $ISISROOT/doc//documents/Disclaimers/Disclaimers.html in a browser or see 
 *   the Privacy &amp; Disclaimers page on the Isis website,
 *   http://isis.astrogeology.usgs.gov, and the USGS privacy and disclaimers on
 *   http://www.usgs.gov/privacy.html.
 */
#include <cmath>
#include <iostream>

#include "IString.h"
#include "Constants.h"
#include "FunctionTools.h"
#include "KaguyaMiCameraDistortionMap.h"

using namespace std;
using namespace Isis;

namespace Isis {
  /** Camera distortion map constructor
   *
   * Create a camera distortion map.  This class maps between distorted
   * and undistorted focal plane x/y's.  The default mapping is the
   * identity, that is, the focal plane x/y and undistorted focal plane
   * x/y will be identical.
   *
   * @param parent        the parent camera that will use this distortion map
   * @param zDirection    the direction of the focal plane Z-axis
   *                      (either 1 or -1)
   *
   */
  KaguyaMiCameraDistortionMap::KaguyaMiCameraDistortionMap(Camera *parent) : CameraDistortionMap(parent, 1) {
  }

  /**
   * @param naifIkCode 
   */
  void KaguyaMiCameraDistortionMap::SetDistortion(const int naifIkCode) {
    //determine if this is the VIS or the NIR sensor, by loooking at the pixel pitch
    if (p_camera->PixelPitch() == 0.013) m_numDistCoef = 3;  //VIS camera has 3 distortion coefs
    else                       m_numDistCoef = 4;  //NIR camera has 4 distortion coefs
    
    //read the distortion coefs from the NAIF Kernels
    QString naifXKey = "INS" + toString(naifIkCode) + "_DISTORTION_COEF_X";
    QString naifYKey = "INS" + toString(naifIkCode) + "_DISTORTION_COEF_Y";
    for (int i=0; i < m_numDistCoef; i++) {
      m_distCoefX[i] = p_camera->getDouble(naifXKey,i);
      m_distCoefY[i] = p_camera->getDouble(naifYKey,i);
    }

    //now read the boresights, or what I would typicall call the principal point offsets
    naifXKey = "INS" + toString(naifIkCode) + "_BORESIGHT";
    m_boreX = p_camera->getDouble(naifXKey, 0);
    m_boreY = p_camera->getDouble(naifXKey, 1);
  }

  /** Compute undistorted focal plane x/y
   *
   * Compute undistorted focal plane x/y given a distorted focal plane x/y.
   *
   * @param dx distorted focal plane x in millimeters
   * @param dy distorted focal plane y in millimeters
   *
   * @return if the conversion was successful
   * @see SetDistortion
   */
  bool KaguyaMiCameraDistortionMap::SetFocalPlane(const double dx, const double dy) {
    p_focalPlaneX = dx;
    p_focalPlaneY = dy;
    //cout << "focal plane: " << dx << " " << dy << "\n";
    //NOTE: the IK/FK kernel does not include the " + dx" as I do below.  They also define the 
    // radial distance only in terms of Y.  Erroneously (I believe) they use only the
    // DISTORTION_COEF_X's in their model definition.  Finally, they provide different distortion
    // coefficients for each line of the CCD--despite them going throught the same optical path.
    // From this I conclude that this distorion model is only valid if x is very near zero.  Which
    // is exactly the situation we are shooting for when modeling a line scanner (x is the along
    // path direction for this sensor).  However, we can not just arbitarily zero, or almost zero,
    // any along path offset calculated by the back projections.  Those offsets are exactly the cost
    // being zeroed in the iterative LineScanCameraGroundMap routines to find the time that a point
    // on the ground was imaged.  Therefore it must be maintained--with the knowledge that the
    // small adjustmenst being provided by the distortion model are only relevant as the offsets (x)
    // approach zero.
    if (m_numDistCoef == 3) {  //VIS camera
      p_undistortedFocalPlaneX = 
        m_boreX + m_distCoefX[0] + dy*(m_distCoefX[1] + dy*m_distCoefX[2]) + dx;
      p_undistortedFocalPlaneY = 
        m_boreY + m_distCoefY[0] + dy*(m_distCoefY[1] + dy*m_distCoefY[2]) + dy;
    }
    else {  //NIR camera
      p_undistortedFocalPlaneX =  m_boreX +
        m_distCoefX[0] + dy*(m_distCoefX[1] + dy*(m_distCoefX[2] + dy*m_distCoefX[3])) + dx;
      p_undistortedFocalPlaneY =  m_boreY +
        m_distCoefY[0] + dy*(m_distCoefY[1] + dy*(m_distCoefY[2] + dy*m_distCoefY[3])) + dy;
    }
    //cout << "undistorted: " << p_undistortedFocalPlaneX << " " << p_undistortedFocalPlaneY << "\n";
    return true;
  }

  /** Compute distorted focal plane x/y
   *
   * Compute distorted focal plane x/y given an undistorted focal plane x/y.
   *
   * @param ux undistorted focal plane x in millimeters
   * @param uy undistorted focal plane y in millimeters
   *
   * @return if the conversion was successful
   * @see SetDistortion
   */
  bool KaguyaMiCameraDistortionMap::SetUndistortedFocalPlane(const double ux, const double uy) {\
    // image coordinates prior to introducing distortion
    p_undistortedFocalPlaneX = ux;
    p_undistortedFocalPlaneY = uy;

    //std::cout << "Distortionless : " << p_undistortedFocalPlaneX << " " << p_undistortedFocalPlaneY << "\n";

    if (m_numDistCoef == 3) {  //quadratic distortion model
      //use the quadratic equation to find the distorted Y value
      double A,B,C;  //coefficients of the quadric equation
      
      A = m_distCoefY[2];
      B = 1.0 + m_distCoefY[1];
      C = m_distCoefY[0] +m_boreY - uy;

      QList<double> roots = FunctionTools::realQuadraticRoots(A,B,C);

      if (roots.size() == 0) return false;
      else if (roots.size() == 1)
        p_focalPlaneY = roots[0];
      else  //two roots to choose between--choose the one closest to uy
        p_focalPlaneY = fabs(uy - roots[0]) < fabs(uy - roots[1]) ? roots[0] : roots[1];

      //now that we know the distortedY we can directly calculate the X
      p_focalPlaneX = ux - 
        (m_boreX + m_distCoefX[0] + p_focalPlaneY*(m_distCoefX[1] + p_focalPlaneY*m_distCoefX[2]));

      return true;
    }
    else { //cubic distortion model
      //use the cubic equation to find the distorted Y value
      double a,b,c; //coefficients of the cubic (coef x^3 ==1)

      a = m_distCoefY[2] / m_distCoefY[3];
      b = (1.0 + m_distCoefY[1]) / m_distCoefY[3];
      c = (m_distCoefY[0] + m_boreY - uy) / m_distCoefY[3];

      QList<double> roots = FunctionTools::realCubicRoots(1.0,a,b,c);

      if (roots.size() == 1) { //one root
        p_focalPlaneY = roots[0];
      }
      else {  //pick the root closest to the orginal value
        QList<double> delta;

        //store all the distance from undistored to focal plane
        for (int i=0;i<roots.size();i++)
          delta << fabs(roots[i]-uy);

        if ( roots.size() == 3) //three roots to choose among
          p_focalPlaneY = delta[0] < delta[1] ? 
                         (delta[0] < delta[2] ? roots[0]:roots[2]) : 
                         (delta[1] < delta[2] ? roots[1]:roots[2]) ;
        else  //two roots to choose between
          p_focalPlaneY = delta[0] < delta[1] ? roots[0]:roots[1]  ;
      }
     
      //now that we know the distortedY we can directly calculate the X
      p_focalPlaneX = ux - (m_boreX +m_distCoefX[0] + 
                      p_focalPlaneY*(m_distCoefX[1] + 
                      p_focalPlaneY*(m_distCoefX[2] +  
                      p_focalPlaneY* m_distCoefX[3])));
      return true;
    }
  }
}
Loading