|
Isis 3.0 Application Source Code Reference |
Home |
00001 #include <string> 00002 #include <algorithm> 00003 #include <vector> 00004 #include <cfloat> 00005 #include <cmath> 00006 #include <iomanip> 00007 00008 #include "LineScanCameraRotation.h" 00009 #include "Quaternion.h" 00010 #include "LineEquation.h" 00011 #include "BasisFunction.h" 00012 #include "LeastSquares.h" 00013 #include "BasisFunction.h" 00014 #include "PolynomialUnivariate.h" 00015 #include "IString.h" 00016 #include "iTime.h" 00017 #include "IException.h" 00018 #include "Table.h" 00019 #include "NaifStatus.h" 00020 00021 // Declarations for binding for Naif Spicelib routine refchg_ that does not have 00022 // a wrapper 00023 extern int refchg_(integer *frame1, integer *frame2, doublereal *et, 00024 doublereal *rotate); 00025 00026 namespace Isis { 00027 /** 00028 * Construct an empty SpiceRotation class using a valid Naif frame code to 00029 * set up for getting rotation from Spice kernels. See required reading 00030 * ftp://naif.jpl.nasa.gov/pub/naif/toolkit_docs/C/ascii/individual_docs/naif_ids.req 00031 * 00032 * @param frameCode Valid naif frame code. 00033 */ 00034 LineScanCameraRotation::LineScanCameraRotation(int frameCode, Isis::Pvl &lab, std::vector<double> timeCache, double tol) : SpiceRotation(frameCode) { 00035 // Initialize optional paramters; 00036 p_pitchRate = 0.; 00037 p_yaw = 0.; 00038 00039 // Load the Spice kernels to get state matrices 00040 p_spi = 0; 00041 p_spi = new Isis::Spice(lab); 00042 00043 // Make sure the kernels are written to the labels and not just the tables (blobs) 00044 if(!p_spi->hasKernels(lab)) { 00045 QString msg = "The master file must contain the kernel files. Rerun spiceinit with attach=no"; 00046 throw IException(IException::User, msg, _FILEINFO_); 00047 } 00048 00049 // Get the kernel group and save the instrument pointing keyword 00050 Isis::PvlGroup kernels = lab.FindGroup("Kernels", Isis::Pvl::Traverse); 00051 p_ckKeyword = kernels["InstrumentPointing"]; 00052 00053 p_cacheTime = timeCache; 00054 // std::cout<<std::setprecision(24); 00055 // std::cout<<timeCache.at(0)<<"-"<<timeCache.at(50000)<<std::endl; 00056 00057 InitConstantRotation(p_cacheTime[0]); 00058 00059 p_cachesLoaded = false; 00060 p_spi->instrumentRotation()->SetFrame(frameCode); 00061 p_crot = p_spi->instrumentRotation(); 00062 p_prot = p_spi->bodyRotation(); 00063 p_spos = p_spi->instrumentPosition(); 00064 // Load the line scan specific rotation matrix caches before loading the regular Spice caches because 00065 // the CreateCache method will unload all the kernels after the caches are created 00066 LoadCache(); 00067 p_spi->createCache(timeCache[0], timeCache[timeCache.size()-1], timeCache.size(), tol); 00068 } 00069 00070 00071 00072 /** 00073 * Destroys the LineScanComeraRotation object 00074 */ 00075 LineScanCameraRotation::~LineScanCameraRotation() { 00076 if(p_spi != 0) delete p_spi; 00077 } 00078 00079 00080 00081 /** Cache J2000 rotation quaternion over a time range. 00082 * 00083 * This method will load an internal cache with frames over a time 00084 * range. This prevents the NAIF kernels from being read over-and-over 00085 * again and slowing an application down due to I/O performance. Once the 00086 * cache has been loaded then the kernels can be unloaded from the NAIF 00087 * system. 00088 * 00089 * @internal 00090 * @history 2010-12-23 Debbie A. Cook Added set of full cache time 00091 * parameters 00092 */ 00093 void LineScanCameraRotation::LoadCache() { 00094 NaifStatus::CheckErrors(); 00095 00096 double startTime = p_cacheTime[0]; 00097 int size = p_cacheTime.size(); 00098 double endTime = p_cacheTime[size-1]; 00099 SetFullCacheParameters(startTime, endTime, size); 00100 00101 // TODO Add a label value to indicate pointing is already decomposed to line scan angles 00102 // and set p_pointingDecomposition=none,framing angles, or line scan angles. 00103 // Also add a label value to indicate jitterOffsets=jitterFileName 00104 // Then we can decide whether to simply grab the crot angles or do new decomposition and whether 00105 // to apply jitter or throw an error because jitter has already been applied. 00106 00107 // *** May need to do a frame trace and load the frames (at least the constant ones) *** 00108 00109 // Loop and load the cache 00110 double state[6]; 00111 double lt; 00112 NaifStatus::CheckErrors(); 00113 00114 double R[3]; // Direction of radial axis of line scan camera 00115 double C[3]; // Direction of cross-track axis 00116 double I[3]; // Direction of in-track axis 00117 double *velocity; 00118 std::vector<double> IB(9); 00119 std::vector<double> CI(9); 00120 SpiceRotation *prot = p_spi->bodyRotation(); 00121 SpiceRotation *crot = p_spi->instrumentRotation(); 00122 00123 for(std::vector<double>::iterator i = p_cacheTime.begin(); i < p_cacheTime.end(); i++) { 00124 double et = *i; 00125 00126 prot->SetEphemerisTime(et); 00127 crot->SetEphemerisTime(et); 00128 00129 // The following code will be put into method LoadIBcache() 00130 spkezr_c("MRO", et, "IAU_MARS", "NONE", "MARS", state, <); 00131 NaifStatus::CheckErrors(); 00132 00133 // Compute the direction of the radial axis (3) of the line scan camera 00134 vscl_c(1. / vnorm_c(state), state, R); // vscl and vnorm only operate on first 3 members of state 00135 00136 // Compute the direction of the cross-track axis (2) of the line scan camera 00137 velocity = state + 3; 00138 vscl_c(1. / vnorm_c(velocity), velocity, C); 00139 vcrss_c(R, C, C); 00140 00141 // Compute the direction of the in-track axis (1) of the line scan camera 00142 vcrss_c(C, R, I); 00143 00144 // Load the matrix IB and enter it into the cache 00145 vequ_c(I, (SpiceDouble( *)) &IB[0]); 00146 vequ_c(C, (SpiceDouble( *)) &IB[3]); 00147 vequ_c(R, (SpiceDouble( *)) &IB[6]); 00148 p_cacheIB.push_back(IB); 00149 // end IB code 00150 00151 // Compute the CIcr matrix - in-track, cross-track, radial frame to constant frame 00152 mxmt_c((SpiceDouble( *)[3]) & (crot->TimeBasedMatrix())[0], (SpiceDouble( *)[3]) & (prot->Matrix())[0], 00153 (SpiceDouble( *)[3]) &CI[0]); 00154 00155 // Put CI into parent cache to use the parent class methods on it 00156 mxmt_c((SpiceDouble( *)[3]) &CI[0], (SpiceDouble( *)[3]) &IB[0], (SpiceDouble( *)[3]) &CI[0]); 00157 p_cache.push_back(CI); 00158 } 00159 p_cachesLoaded = true; 00160 SetSource(Memcache); 00161 00162 NaifStatus::CheckErrors(); 00163 } 00164 00165 /** Cache J2000 rotation over existing cached time range using polynomials 00166 * 00167 * This method will reload an internal cache with matrices 00168 * formed from rotation angles fit to polynomials over a time 00169 * range. 00170 * 00171 * @param function1 The first polynomial function used to 00172 * find the rotation angles 00173 * @param function2 The second polynomial function used to 00174 * find the rotation angles 00175 * @param function3 The third polynomial function used to 00176 * find the rotation angles 00177 */ 00178 void LineScanCameraRotation::ReloadCache() { 00179 NaifStatus::CheckErrors(); 00180 00181 // Make sure caches are already loaded 00182 if(!p_cachesLoaded) { 00183 QString msg = "A LineScanCameraRotation cache has not been loaded yet"; 00184 throw IException(IException::Programmer, msg, _FILEINFO_); 00185 } 00186 00187 // Clear existing matrices from cache 00188 p_cache.clear(); 00189 00190 // Create polynomials fit to angles & use to reload cache 00191 Isis::PolynomialUnivariate function1(p_degree); 00192 Isis::PolynomialUnivariate function2(p_degree); 00193 Isis::PolynomialUnivariate function3(p_degree); 00194 00195 // Get the coefficients of the polynomials already fit to the angles of rotation defining [CI] 00196 std::vector<double> coeffAng1; 00197 std::vector<double> coeffAng2; 00198 std::vector<double> coeffAng3; 00199 GetPolynomial(coeffAng1, coeffAng2, coeffAng3); 00200 00201 // Reset linear term to center around zero -- what works best is either roll-avg & pitchavg+ or pitchavg+ & yawavg- 00202 // coeffAng1[1] -= 0.0000158661225; 00203 // coeffAng2[1] = 0.0000308433; 00204 // coeffAng3[0] = -0.001517547; 00205 if(p_pitchRate) coeffAng2[1] = p_pitchRate; 00206 if(p_yaw) coeffAng3[0] = p_yaw; 00207 00208 // Load the functions with the coefficients 00209 function1.SetCoefficients(coeffAng1); 00210 function2.SetCoefficients(coeffAng2); 00211 function3.SetCoefficients(coeffAng3); 00212 00213 double CI[3][3]; 00214 double IJ[3][3]; 00215 std::vector<double> rtime; 00216 SpiceRotation *prot = p_spi->bodyRotation(); 00217 std::vector<double> CJ; 00218 CJ.resize(9); 00219 00220 for(std::vector<double>::size_type pos = 0; pos < p_cacheTime.size(); pos++) { 00221 double et = p_cacheTime.at(pos); 00222 rtime.push_back((et - GetBaseTime()) / GetTimeScale()); 00223 double angle1 = function1.Evaluate(rtime); 00224 double angle2 = function2.Evaluate(rtime); 00225 double angle3 = function3.Evaluate(rtime); 00226 rtime.clear(); 00227 00228 // Get the first angle back into the range Naif expects [180.,180.] 00229 if(angle1 < -1 * pi_c()) { 00230 angle1 += twopi_c(); 00231 } 00232 else if(angle1 > pi_c()) { 00233 angle1 -= twopi_c(); 00234 } 00235 00236 eul2m_c((SpiceDouble) angle3, (SpiceDouble) angle2, (SpiceDouble) angle1, 00237 p_axis3, p_axis2, p_axis1, 00238 CI); 00239 mxm_c((SpiceDouble( *)[3]) & (p_jitter->SetEphemerisTimeHPF(et))[0], CI, CI); 00240 00241 prot->SetEphemerisTime(et); 00242 mxm_c((SpiceDouble( *)[3]) & (p_cacheIB.at(pos))[0], (SpiceDouble( *)[3]) & (prot->Matrix())[0], IJ); 00243 mxm_c(CI, IJ, (SpiceDouble( *)[3]) &CJ[0]); 00244 00245 p_cache.push_back(CJ); // J2000 to constant frame 00246 } 00247 00248 // Set source to cache to get updated values 00249 SetSource(SpiceRotation::Memcache); 00250 00251 // Make sure SetEphemerisTime updates the matrix by resetting it twice (in case the first one 00252 // matches the current et. p_et is private and not available from the child class 00253 NaifStatus::CheckErrors(); 00254 SetEphemerisTime(p_cacheTime[0]); 00255 SetEphemerisTime(p_cacheTime[1]); 00256 00257 NaifStatus::CheckErrors(); 00258 } 00259 00260 }