Beispiel #1
0
static VALUE latrec(VALUE self, VALUE radius, VALUE longitude, VALUE latitude) {
  double vector[3];
  
  latrec_c(NUM2DBL(radius), NUM2DBL(longitude), NUM2DBL(latitude),  vector);
  
  return rb_nmatrix_dense_create(FLOAT64, (size_t *) VECTOR_SHAPE, 2, (void *) vector, 3);
}
Beispiel #2
0
  /** Compute undistorted focal plane coordinate from ground position using current Spice from SetImage call
   * 
   * This method will compute the undistorted focal plane coordinate for 
   * a ground position, using the current Spice settings (time and kernels) 
   * without resetting the current point values for lat/lon/radius/x/y.
   *  
   * @param lat planetocentric latitude in degrees
   * @param lon planetocentric longitude in degrees 
   * @param radius local radius in m 
   * 
   * @return conversion was successful
   */
  bool CameraGroundMap::GetXY(const double lat, const double lon, const double radius,
                              std::vector<double> &lookJ) {

    // Check for Sky images
    if ( p_camera->IsSky() ) {
      return false;
    }

    // Should a check be added to make sure SetImage has been called???
    
    // Compute the look vector in body-fixed coordinates
    double pB[3]; // Point on surface
    latrec_c( radius/1000.0, lon*Isis::PI/180.0, lat*Isis::PI/180.0, pB);

    // Get spacecraft vector in body-fixed coordinates
    SpiceRotation *bodyRot = p_camera->BodyRotation();
    std::vector<double> sB = bodyRot->ReferenceVector(p_camera->InstrumentPosition()->Coordinate());
    std::vector<double> lookB(3);
    for (int ic=0; ic<3; ic++)   lookB[ic] = pB[ic] - sB[ic];

    // Check for point on back of planet by checking to see if surface point is viewable (test emission angle)
    // During iterations, we may not want to do the back of planet test???
    double upsB[3],upB[3],dist;
    vminus_c ( (SpiceDouble *) &lookB[0], upsB);
    unorm_c (upsB, upsB, &dist);
    unorm_c (pB, upB, &dist);
    double angle = vdot_c(upB, upsB);
    double emission;
    if (angle > 1) {
      emission = 0;
    }
    else if (angle < -1) {
      emission = 180.;
    }
    else {
      emission = acos (angle) * 180.0 / Isis::PI;
    }
    if (fabs(emission) > 90.) return false;

    // Get the look vector in the camera frame and the instrument rotation
    lookJ.resize(3);
    lookJ = p_camera->BodyRotation()->J2000Vector( lookB );
    return true;
  }
Beispiel #3
0
  /** Compute undistorted focal plane coordinate from ground position that includes a local radius
   *
   * @param lat planetocentric latitude in degrees
   * @param lon planetocentric longitude in degrees
   * @param radius local radius in meters
   *
   * @return conversion was successful
   */
  bool RadarGroundMap::SetGround(const double lat, const double lon, const double radius) {
    // Get the ground point in rectangular coordinates (X)
    SpiceDouble X[3];
    SpiceDouble rlat = lat*Isis::PI/180.0;
    SpiceDouble rlon = lon*Isis::PI/180.0;
    latrec_c(radius,rlon,rlat,X);

    // Compute lower bound for Doppler shift 
    double et1 = p_camera->Spice::CacheStartTime();
    p_camera->Sensor::SetEphemerisTime(et1);
    double xv1 = ComputeXv(X);

    // Compute upper bound for Doppler shift
    double et2 = p_camera->Spice::CacheEndTime();
    p_camera->Sensor::SetEphemerisTime(et2);
    double xv2 = ComputeXv(X);

    // Make sure we bound root (xv = 0.0)
    if ((xv1 < 0.0) && (xv2 < 0.0)) return false;
    if ((xv1 > 0.0) && (xv2 > 0.0)) return false;

    // Order the bounds
    double fl,fh,xl,xh;
    if (xv1 < xv2) {
      fl = xv1;
      fh = xv2;
      xl = et1;
      xh = et2;
    }
    else {
      fl = xv2;
      fh = xv1;
      xl = et2;
      xh = et1;
    }

    // Iterate a max of 30 times
    for (int j=0; j<30; j++) {
      // Use the secant method to guess the next et
      double etGuess = xl + (xh - xl) * fl / (fl - fh);

      // Compute the guessed Doppler shift.  Hopefully
      // this guess converges to zero at some point
      p_camera->Sensor::SetEphemerisTime(etGuess);
      double fGuess = ComputeXv(X);

      // Update the bounds
      double delTime;
      if (fGuess < 0.0) {
        delTime = xl - etGuess;
        xl = etGuess;
        fl = fGuess;
      }
      else {
        delTime = xh - etGuess;
        xh = etGuess;
        fh = fGuess;
      }

      // See if we are done
      if ((fabs(delTime) <= p_timeTolerance) || (fGuess == 0.0)) {
        SpiceRotation *bodyFrame = p_camera->BodyRotation();
        SpicePosition *spaceCraft = p_camera->InstrumentPosition();

        // Get body fixed spacecraft velocity and position
        std::vector<double> Ssc(6);

        // Load the state into Ssc and rotate to body-fixed
        vequ_c ( (SpiceDouble *) &(spaceCraft->Coordinate()[0]), &Ssc[0]);
        vequ_c ( (SpiceDouble *) &(spaceCraft->Velocity()[0]), &Ssc[3]);
        std::vector<double> bfSsc(6);
        bfSsc = bodyFrame->ReferenceVector(Ssc);

        // Extract the body-fixed position and velocity from the state
        std::vector<double> Vsc(3);
        std::vector<double> Xsc(3);
        vequ_c ( &bfSsc[0], (SpiceDouble *) &(Xsc[0]) );
        vequ_c ( &bfSsc[3], (SpiceDouble *) &(Vsc[0]) );

        // Determine if focal plane coordinate falls on the correct side of the
        // spacecraft. Radar has both left and right look directions. Make sure
        // the coordinate is on the same side as the look direction. This is done
        // by (X - S) . (V x S) where X=ground point vector, S=spacecraft position
        // vector, and V=velocity vector. If the dot product is greater than 0, then
        // the point is on the right side. If the dot product is less than 0, then
        // the point is on the left side. If the dot product is 0, then the point is
        // directly under the spacecraft (neither left or right) and is invalid.
        SpiceDouble vout1[3];
        SpiceDouble vout2[3];
        SpiceDouble dp;
        vsub_c(X,&Xsc[0],vout1);
        vcrss_c(&Vsc[0],&Xsc[0],vout2);
        dp = vdot_c(vout1,vout2);
        if (dp > 0.0 && p_lookDirection == Radar::Left) return false;
        if (dp < 0.0 && p_lookDirection == Radar::Right) return false;
        if (dp == 0.0) return false;

        // Compute body fixed look direction
        std::vector<double> lookB;
        lookB.resize(3);
        lookB[0] = X[0] - Xsc[0];
        lookB[1] = X[1] - Xsc[1];
        lookB[2] = X[2] - Xsc[2];

        std::vector<double> lookJ = bodyFrame->J2000Vector(lookB);
        SpiceRotation *cameraFrame = p_camera->InstrumentRotation();
        std::vector<double> lookC = cameraFrame->ReferenceVector(lookJ);

        SpiceDouble unitLookC[3];
        vhat_c(&lookC[0],unitLookC);
        p_camera->SetLookDirection(unitLookC);

        p_camera->SetFocalLength(p_slantRange*1000.0);
        p_focalPlaneX = p_slantRange / p_rangeSigma;
        p_focalPlaneY = 0.0;
        return true;
      }
    }

    return false;
  }
Beispiel #4
0
   void radrec_c ( SpiceDouble range, 
                   SpiceDouble ra, 
                   SpiceDouble dec, 
                   SpiceDouble rectan[3] ) 
/*

-Brief_I/O
 
   VARIABLE  I/O  DESCRIPTION 
   --------  ---  --------------------------------------------------- 
   range      I   Distance of a point from the origin. 
   ra         I   Right ascension of point in radians. 
   dec        I   Declination of point in radians. 
   rectan     O   Rectangular coordinates of the point.
 
-Detailed_Input
 
   range      is the distance of the point from the origin.  Output
              units are the same as the units associated with `range.'
 
   ra         is the right ascension of the input point:  the angular
              distance measured toward the east from the prime meridian
              to the meridian containing the input point. The direction
              of increasing right ascension is from the +X axis towards
              the +Y axis.

              The range (i.e., the set of allowed values) of 
              `ra' is unrestricted.  Units are radians.

   dec        is the declination of the point.  This is the angular 
              distance from the XY plane to the point.  

              The range of `dec' is unrestricted.  Units are radians.
 
-Detailed_Output
 
   rectan     is the array containing the rectangular coordinates of 
              the point.  The output units associated with `rectan'
              are those associated with the input `range.'

-Parameters
 
   None. 
 
-Exceptions
 
   Error free. 
 
-Files
 
   None. 
 
-Particulars

   None.
 
-Examples
 
   The following code fragment converts right ascension and 
   declination from the B1950 reference frame to the J2000 frame.
 
      #include "SpiceUsr.h"

      SpiceDouble      ra;
      SpiceDouble      dec; 
      SpiceDouble      r;
      SpiceDouble      rotab  [ 3 ][ 3 ]; 
      SpiceDouble      oldvec [ 3 ];
      SpiceDouble      newvec [ 3 ];


      radrec_c ( 1.0, ra, dec, oldvec );

      pxform_c ( "B1950", "J2000", 0.0, rotab );

      mxv_c    ( rotab,   oldvec, newvec );
      recrad_c ( newvec,  &r,     &ra,    &dec ); 
 
 
-Restrictions
 
   None. 
 
-Author_and_Institution
 
   N.J. Bachman    (JPL)
   H.A. Neilan     (JPL) 
   E.D. Wright     (JPL)
 
-Literature_References
 
   "Celestial Mechanics, A Computational Guide for the Practitioner" 
   by Laurence G. Taff 
 
-Version
 
   -CSPICE Version 1.0.2, 28-JUL-2003 (NJB) 
   
      Various header corrections were made.

   -CSPICE Version 1.0.1, 13-APR-2000 (NJB) 
   
      Made some minor updates and corrections in the code example.
      
   -CSPICE Version 1.0.0, 08-FEB-1998 (EDW)

-Index_Entries
 
   range ra and dec to rectangular coordinates 
   right_ascension and declination to rectangular 
 
-&
*/

{ /* Begin radrec_c */

   /*
   There isn't much to say or do...
   */

   latrec_c ( range, ra, dec, rectan );


} /* End radrec_c */
Beispiel #5
0
  /** Compute undistorted focal plane coordinate from ground position
   *
   * @param lat Planetocentric latitude in degrees
   * @param lon Planetocentric longitude in degrees
   *
   * @return @b bool Indicates whether the conversion was successful
   *
   * @internal
   * @history 2007-04-18  Tracie Sucharski - Added check for reasonable
   *                             match when attempting to find closest
   *                             lat/lon in map arrays.
   * @history 2007-09-14  Tracie Sucharski - Added check for longitude
   *                             outside min/max bounds.  Don't know why
   *                             this wasn't put in before (lat check was
   *                             in), was it oversight, or did I take it out
   *                             for some reason???
   * @history 2007-12-14  Tracie Sucharski - Remove resolution test, too
   *                            image dependent and the resolution for vims is
   *                            incorrect due to the instrument having
   *                            rectangular pixels.
   * @history 2008-01-02  Tracie Sucharski -  Check validity of resulting
   *                            sample and line against edge of starting
   *                            ending pixels (0.5/Parent+0.5) instead of
   *                            center of pixels.
   * @history 2012-12-03  Tracie Sucharski - Check for valid minLat/maxLat, minLon/maxLon.  If 
   *                            none are valid, this means the latMap and lonMap have no valid
   *                            data, therefore we cannot back project, so return false.
   *
   */
  bool VimsGroundMap::SetGround(const Latitude &lat, const Longitude &lon) {

    QVector3D xyz;
    if (p_camera->target()->shape()->name() == "Plane") {
        double radius = lat.degrees();
        if(radius <= 0.0)
          return false;

        double xCheck = radius * 0.001 * cos(lon.radians());
        double yCheck = radius * 0.001 * sin(lon.radians());

        xyz.setX(xCheck);
        xyz.setY(yCheck);
        xyz.setZ(0.);
      }
    else {
        //  Convert lat/lon to x/y/z
        Distance radius = p_camera->LocalRadius(lat, lon);
        SpiceDouble pB[3];
        latrec_c(radius.kilometers(), lon.radians(), lat.radians(), pB);

        xyz.setX(pB[0]);
        xyz.setY(pB[1]);
        xyz.setZ(pB[2]);
    }

    double minDist = DBL_MAX;
    int minSamp = -1;
    int minLine = -1;

    //  Find closest points  ??? what tolerance ???
    for (int line = 0; line < p_camera->ParentLines(); line++) {
      for (int samp = 0; samp < p_camera->ParentSamples(); samp++) {

        if (p_xyzMap[line][samp].isNull()) continue;

        //  Subtract map from coordinate then get length
        QVector3D deltaXyz = xyz - p_xyzMap[line][samp];
        if (deltaXyz.length() < minDist) {
          minDist = deltaXyz.length();
          minSamp = samp;
          minLine = line;
        }
      }
    }

    //-----------------------------------------------------------------
    //  If dist is less than some ??? tolerance ??? this is the
    //  closest point.  Use this point and surrounding 8 pts as
    //  control pts.
    //----------------------------------------------------------------
    if (minDist >= DBL_MAX) return false;

    //-------------------------------------------------------------
    //  Set-up for LU decomposition (least2 fit).
    //  Assume we will have 9 control points, this may not be true
    //  and will need to be adjusted before the final solution.
    //-------------------------------------------------------------
    BasisFunction sampXyzBasis("Sample", 4, 4);
    BasisFunction lineXyzBasis("Line", 4, 4);
    LeastSquares sampXyzLsq(sampXyzBasis);
    LeastSquares lineXyzLsq(lineXyzBasis);
    vector<double> knownXyz(4);

    //  Solve using x/y/z
    for (int line = minLine - 1; line < minLine + 2; line++) {
      if (line < 0 || line > p_camera->ParentLines() - 1) continue;
      for (int samp = minSamp - 1; samp < minSamp + 2; samp++) {
        //  Check for edges
        if (samp < 0 || samp > p_camera->ParentSamples() - 1) continue;
        if (p_xyzMap[line][samp].isNull()) continue;

        knownXyz[0] = p_xyzMap[line][samp].x();
        knownXyz[1] = p_xyzMap[line][samp].y();
        knownXyz[2] = p_xyzMap[line][samp].z();
        knownXyz[3] = 1;
        sampXyzLsq.AddKnown(knownXyz, samp + 1);
        lineXyzLsq.AddKnown(knownXyz, line + 1);
      }
    }

    if (sampXyzLsq.Knowns() < 4) return false;

    sampXyzLsq.Solve();
    lineXyzLsq.Solve();

    //  Solve for sample, line position corresponding to input lat, lon
    knownXyz[0] = xyz.x();
    knownXyz[1] = xyz.y();
    knownXyz[2] = xyz.z();
    knownXyz[3] = 1;
    double inSamp = sampXyzLsq.Evaluate(knownXyz);
    double inLine = lineXyzLsq.Evaluate(knownXyz);


    if (inSamp < 0.5 || inSamp > p_camera->ParentSamples() + 0.5 ||
        inLine < 0.5 || inLine > p_camera->ParentLines() + 0.5) {
      return false;
    }

    p_camera->IgnoreProjection(true);
    p_camera->SetImage(inSamp, inLine);
    p_camera->IgnoreProjection(false);
    if (!p_camera->HasSurfaceIntersection()) return false;

    p_focalPlaneX = inSamp;
    p_focalPlaneY = inLine;

    return true;
  }