/** Set the coefficients of a polynomial fit to each * of the three camera angles for the time period covered by the * cache, angle = a + bt + ct**2, where t = (time - p_baseTime)/ p_timeScale. * */ void PixelOffset::SetPolynomial () { Isis::PolynomialUnivariate function1(p_degree); //!< Basis function fit to 1st rotation angle Isis::PolynomialUnivariate function2(p_degree); //!< Basis function fit to 2nd rotation angle // LeastSquares *fitAng1 = new LeastSquares ( function1 ); LeastSquares *fitAng2 = new LeastSquares ( function2 ); std::vector<double> time; // Load the known values to compute the fit equation for (std::vector<double>::size_type pos=0;pos < p_cacheTime.size();pos++) { double t = p_cacheTime.at(pos); // Base fit on extent of coverage in the input offset file if (t >= p_times[0] && t <= p_times[p_times.size()-1]) { time.push_back( (t - p_baseTime) / p_timeScale ); SetEphemerisTime( t ); fitAng1->AddKnown ( time, p_cacheAngle1[pos] ); fitAng2->AddKnown ( time, p_cacheAngle2[pos] ); time.clear(); } } if (fitAng1->Knowns() == 0) { std::string msg; msg = "Cube time range is not covered by jitter file"; throw iException::Message(Isis::iException::User,msg,_FILEINFO_); } //Solve the equations for the coefficients fitAng1->Solve(); fitAng2->Solve(); // Delete the least squares objects now that we have all the coefficients delete fitAng1; delete fitAng2; // For now assume both angles are fit to a polynomial. Later they may // each be fit to a unique basis function. // Fill the coefficient vectors for ( int i = 0; i < function1.Coefficients(); i++) { p_ang1Coefficients.push_back( function1.Coefficient( i ) ); p_ang2Coefficients.push_back( function2.Coefficient( i ) ); } // std::cout<<"Angle1 coeff="<<p_ang1Coefficients[0]<<" "<<p_ang1Coefficients[1]<<" "<<p_ang1Coefficients[2]<<std::endl; // std::cout<<"Angle2 coeff="<<p_ang2Coefficients[0]<<" "<<p_ang2Coefficients[1]<<" "<<p_ang2Coefficients[2]<<std::endl; }
HiresCamera::HiresCamera (Pvl &lab) : FramingCamera(lab) { // Get the camera characteristics iString filter = (string)(lab.FindGroup("BandBin", Pvl::Traverse))["FilterName"]; filter = filter.UpCase(); SetFocalLength (); SetPixelPitch (); // Get the start time in et PvlGroup inst = lab.FindGroup ("Instrument",Pvl::Traverse); string stime = inst["StartTime"]; double time; str2et_c(stime.c_str(),&time); // Do not correct time for center of the exposure duration. This is because // the kernels were built to accept the start times of the images. // time += ((double)inst["ExposureDuration"] / 1000.0) / 2.0; // Add half // exposure duration in milliseconds // Setup detector map new CameraDetectorMap(this); // Setup focal plane map CameraFocalPlaneMap *focalMap = new CameraFocalPlaneMap(this,NaifIkCode()); focalMap->SetDetectorOrigin ( Spice::GetDouble("INS" + (iString)(int)NaifIkCode() + "_BORESIGHT_SAMPLE"), Spice::GetDouble("INS" + (iString)(int)NaifIkCode() + "_BORESIGHT_LINE")); // Setup distortion map new CameraDistortionMap(this); // Setup the ground and sky map new CameraGroundMap(this); new CameraSkyMap(this); SetEphemerisTime(time); LoadCache(); }
/** Cache J2000 rotation quaternion over a time range. * * This method will load an internal cache with frames over a time * range. This prevents the NAIF kernels from being read over-and-over * again and slowing an application down due to I/O performance. Once the * cache has been loaded then the kernels can be unloaded from the NAIF * system. * * @param startTime Starting ephemeris time in seconds for the cache * @param endTime Ending ephemeris time in seconds for the cache * @param size Number of frames to keep in the cache * */ void PixelOffset::LoadAngles ( std::vector<double> cacheTime ) { p_cacheTime = cacheTime; // Make sure angles aren't already loaded TBD /* if () { std::string msg = "An angle cache has already been created"; throw Isis::iException::Message(Isis::iException::Programmer,msg,_FILEINFO_); } */ // Loop and load the angle caches for (size_t i=0; i<p_cacheTime.size(); i++) { double et = p_cacheTime[i]; SetEphemerisTime(et); p_cacheAngle1.push_back( (p_angle1 - p_sampOff)/p_sampScale ); p_cacheAngle2.push_back( (p_angle2 - p_lineOff)/p_lineScale); // std::cout<<p_angle1<<" "<<p_angle2<<" "<<et <<std::endl; } }
IssWACamera::IssWACamera (Pvl &lab) : FramingCamera(lab) { PvlGroup bandBin = lab.FindGroup ("BandBin",Pvl::Traverse); // Get the camera characteristics iString key = string("INS"+(iString)(int)NaifIkCode()+"_")+ (string)bandBin["FilterName"] + "_FOCAL_LENGTH"; key = key.Convert("/",'_'); double focalLength = Spice::GetDouble(key); SetFocalLength (focalLength); SetPixelPitch (); InstrumentRotation()->SetFrame(Spice::GetInteger("INS_"+(iString)(int)NaifIkCode()+"_FRAME_ID")); // Get the start time in et PvlGroup inst = lab.FindGroup ("Instrument",Pvl::Traverse); string stime = inst["StartTime"]; double et; str2et_c(stime.c_str(),&et); double exposureDuration = (double)inst["ExposureDuration"] /1000.0; et += exposureDuration / 2.0; // Setup detector map int summingMode = inst["SummingMode"]; CameraDetectorMap *detectorMap = new CameraDetectorMap(this); detectorMap->SetDetectorLineSumming(summingMode); detectorMap->SetDetectorSampleSumming(summingMode); // Setup focal plane map CameraFocalPlaneMap *focalMap = new CameraFocalPlaneMap(this,NaifIkCode()); focalMap->SetDetectorOrigin (Spice::GetDouble("INS" + (iString)(int)NaifIkCode() + "_BORESIGHT_SAMPLE"), Spice::GetDouble("INS" + (iString)(int)NaifIkCode() + "_BORESIGHT_LINE")); // Setup distortion map double k1 = Spice::GetDouble("INS" + (iString)(int)NaifIkCode() + "_K1"); new RadialDistortionMap(this, k1); // Setup the ground and sky map new CameraGroundMap(this); new CameraSkyMap(this); SetEphemerisTime(et); LoadCache(); }
// constructors LoHighCamera::LoHighCamera (Pvl &lab) : FramingCamera(lab) { // Get the Instrument label information needed to define the camera for this frame PvlGroup inst = lab.FindGroup ("Instrument",Pvl::Traverse); iString spacecraft = (string)inst["SpacecraftName"]; iString instId = (string)inst["InstrumentId"]; // Turn off the aberration corrections for the instrument position object InstrumentPosition()->SetAberrationCorrection("NONE"); // Get the camera characteristics SetFocalLength (); SetPixelPitch (); // Get the start time in et string stime = inst["StartTime"]; double time; str2et_c(stime.c_str(),&time); // Setup focal plane map LoCameraFiducialMap fid( inst, NaifIkCode()); // Setup detector map new CameraDetectorMap(this); // Setup focalplane map CameraFocalPlaneMap *focalMap = new CameraFocalPlaneMap(this,NaifIkCode()); // Try (0.,0.) focalMap->SetDetectorOrigin(0.0,0.0); // Setup distortion map LoHighDistortionMap *distortionMap = new LoHighDistortionMap(this); distortionMap->SetDistortion(NaifIkCode()); // Setup the ground and sky map new CameraGroundMap(this); new CameraSkyMap(this); SetEphemerisTime(time); LoadCache(); }
/** Set ephemeris time for the high pass filtered rotation * from the instrument frame to the true (corrected) instrument * frame. [TC] = [angle2 - Pangle2(t)] [angle1 - Pangle1(t)] * 2 1 * where t = (time - p_baseTime) / p_timeScale, and n = p_degree. * * @param [in] et Ephemeris time * */ std::vector<double> PixelOffset::SetEphemerisTimeHPF ( const double et ) { Isis::PolynomialUnivariate function1( p_degree ); Isis::PolynomialUnivariate function2( p_degree ); //If outside the range of the offsets just return the identity matrix if (et < p_times[0] || et > p_times[p_times.size()-1]) { return (p_I); } // Load the functions with the coefficients function1.SetCoefficients ( p_ang1Coefficients ); function2.SetCoefficients ( p_ang2Coefficients ); // Compute polynomial approximations to angles, pangle1 and pangle2 std::vector<double> rtime; rtime.push_back((et - p_baseTime) / p_timeScale); double pangle1 = p_sampOff + p_sampScale*function1.Evaluate (rtime); double pangle2 = p_lineOff + p_lineScale*function2.Evaluate (rtime); // Compute p_angles for this time SetEphemerisTime(et); double angle1 = p_angleScale*(p_angle1 - pangle1); double angle2 = p_angleScale*(p_angle2 - pangle2); // std::cout<<" "<<p_angle1*p_angleScale<<" "<<pangle1*p_angleScale<<" "<<angle1<<" "<<et<<std::endl; // std::cout<<" "<<p_angle2*p_angleScale<<" "<<pangle2*p_angleScale<<" "<<angle2<<" "<<et<<std::endl; std::vector<double> TC(9); eul2m_c ( (SpiceDouble) 0., (SpiceDouble) angle2, (SpiceDouble) angle1, 3, 2, 1, (SpiceDouble(*) [3]) &TC[0]); return (TC); }
/** Cache J2000 rotation over existing cached time range using polynomials * * This method will reload an internal cache with matrices * formed from rotation angles fit to polynomials over a time * range. * * @param function1 The first polynomial function used to * find the rotation angles * @param function2 The second polynomial function used to * find the rotation angles * @param function3 The third polynomial function used to * find the rotation angles */ void LineScanCameraRotation::ReloadCache() { NaifStatus::CheckErrors(); // Make sure caches are already loaded if(!p_cachesLoaded) { QString msg = "A LineScanCameraRotation cache has not been loaded yet"; throw IException(IException::Programmer, msg, _FILEINFO_); } // Clear existing matrices from cache p_cache.clear(); // Create polynomials fit to angles & use to reload cache Isis::PolynomialUnivariate function1(p_degree); Isis::PolynomialUnivariate function2(p_degree); Isis::PolynomialUnivariate function3(p_degree); // Get the coefficients of the polynomials already fit to the angles of rotation defining [CI] std::vector<double> coeffAng1; std::vector<double> coeffAng2; std::vector<double> coeffAng3; GetPolynomial(coeffAng1, coeffAng2, coeffAng3); // Reset linear term to center around zero -- what works best is either roll-avg & pitchavg+ or pitchavg+ & yawavg- // coeffAng1[1] -= 0.0000158661225; // coeffAng2[1] = 0.0000308433; // coeffAng3[0] = -0.001517547; if(p_pitchRate) coeffAng2[1] = p_pitchRate; if(p_yaw) coeffAng3[0] = p_yaw; // Load the functions with the coefficients function1.SetCoefficients(coeffAng1); function2.SetCoefficients(coeffAng2); function3.SetCoefficients(coeffAng3); double CI[3][3]; double IJ[3][3]; std::vector<double> rtime; SpiceRotation *prot = p_spi->bodyRotation(); std::vector<double> CJ; CJ.resize(9); for(std::vector<double>::size_type pos = 0; pos < p_cacheTime.size(); pos++) { double et = p_cacheTime.at(pos); rtime.push_back((et - GetBaseTime()) / GetTimeScale()); double angle1 = function1.Evaluate(rtime); double angle2 = function2.Evaluate(rtime); double angle3 = function3.Evaluate(rtime); rtime.clear(); // Get the first angle back into the range Naif expects [180.,180.] if(angle1 < -1 * pi_c()) { angle1 += twopi_c(); } else if(angle1 > pi_c()) { angle1 -= twopi_c(); } eul2m_c((SpiceDouble) angle3, (SpiceDouble) angle2, (SpiceDouble) angle1, p_axis3, p_axis2, p_axis1, CI); mxm_c((SpiceDouble( *)[3]) & (p_jitter->SetEphemerisTimeHPF(et))[0], CI, CI); prot->SetEphemerisTime(et); mxm_c((SpiceDouble( *)[3]) & (p_cacheIB.at(pos))[0], (SpiceDouble( *)[3]) & (prot->Matrix())[0], IJ); mxm_c(CI, IJ, (SpiceDouble( *)[3]) &CJ[0]); p_cache.push_back(CJ); // J2000 to constant frame } // Set source to cache to get updated values SetSource(SpiceRotation::Memcache); // Make sure SetEphemerisTime updates the matrix by resetting it twice (in case the first one // matches the current et. p_et is private and not available from the child class NaifStatus::CheckErrors(); SetEphemerisTime(p_cacheTime[0]); SetEphemerisTime(p_cacheTime[1]); NaifStatus::CheckErrors(); }