Isis 3 Programmer Reference
SpicePosition.cpp
1 #include "SpicePosition.h"
2 
3 #include <algorithm>
4 #include <cfloat>
5 #include <iomanip>
6 
7 #include <QString>
8 #include <QStringList>
9 #include <QChar>
10 
11 #include "BasisFunction.h"
12 #include "IException.h"
13 #include "LeastSquares.h"
14 #include "LineEquation.h"
15 #include "NaifStatus.h"
16 #include "NumericalApproximation.h"
17 #include "PolynomialUnivariate.h"
18 #include "TableField.h"
19 
20 namespace Isis {
29  SpicePosition::SpicePosition(int targetCode, int observerCode) {
30  init(targetCode, observerCode, false);
31  }
32 
62  SpicePosition::SpicePosition(int targetCode, int observerCode,
63  bool swapObserverTarget) {
64  init(targetCode, observerCode, swapObserverTarget);
65  }
66 
79  void SpicePosition::init(int targetCode, int observerCode,
80  const bool &swapObserverTarget) {
81 
82  p_aberrationCorrection = "LT+S";
83  p_baseTime = 0.;
84  p_coefficients[0].clear();
85  p_coefficients[1].clear();
86  p_coefficients[2].clear();
87  p_coordinate.resize(3);
88  p_degree = 2;
89  p_degreeApplied = false;
90  p_et = -DBL_MAX;
93  p_fullCacheSize = 0;
94  p_hasVelocity = false;
95 
96  p_override = NoOverrides;
97  p_source = Spice;
98 
99  p_timeBias = 0.0;
100  p_timeScale = 1.;
101  p_velocity.resize(3);
102  p_xhermite = NULL;
103  p_yhermite = NULL;
104  p_zhermite = NULL;
105 
106  m_swapObserverTarget = swapObserverTarget;
107  m_lt = 0.0;
108 
109  // Determine observer/target ordering
110  if ( m_swapObserverTarget ) {
111  // New/improved settings.. Results in vector negation in SetEphemerisTimeSpice
112  p_targetCode = observerCode;
113  p_observerCode = targetCode;
114  }
115  else {
116  // Traditional settings
117  p_targetCode = targetCode;
118  p_observerCode = observerCode;
119  }
120  }
121 
122 
127  ClearCache();
128  }
129 
130 
143  void SpicePosition::SetTimeBias(double timeBias) {
144  p_timeBias = timeBias;
145  }
146 
154  double SpicePosition::GetTimeBias() const {
155  return (p_timeBias);
156  }
157 
179  void SpicePosition::SetAberrationCorrection(const QString &correction) {
180  QString abcorr(correction);
181  abcorr.remove(QChar(' '));
182  abcorr = abcorr.toUpper();
183  QStringList validAbcorr;
184  validAbcorr << "NONE" << "LT" << "LT+S" << "CN" << "CN+S"
185  << "XLT" << "XLT+S" << "XCN" << "XCN+S";
186 
187  if (validAbcorr.indexOf(abcorr) >= 0) {
188  p_aberrationCorrection = abcorr;
189  }
190  else {
191  QString msg = "Invalid abberation correction [" + correction + "]";
193  }
194  }
195 
207  return (p_aberrationCorrection);
208  }
209 
224  return (m_lt);
225  }
226 
242  const std::vector<double> &SpicePosition::SetEphemerisTime(double et) {
244 
245  // Save the time
246  if(et == p_et) return p_coordinate;
247  p_et = et;
248 
249  // Read from the cache
250  if(p_source == Memcache) {
252  }
253  else if(p_source == HermiteCache) {
255  }
256  else if(p_source == PolyFunction) {
258  }
261  }
262  else { // Read from the kernel
264  }
265 
267 
268  // Return the coordinate
269  return p_coordinate;
270  }
271 
272 
287  void SpicePosition::LoadCache(double startTime, double endTime, int size) {
288  // Make sure cache isn't already loaded
289  if(p_source == Memcache || p_source == HermiteCache) {
290  QString msg = "A SpicePosition cache has already been created";
292  }
293 
294  if(startTime > endTime) {
295  QString msg = "Argument startTime must be less than or equal to endTime";
297  }
298 
299  if((startTime != endTime) && (size == 1)) {
300  QString msg = "Cache size must be more than 1 if startTime endTime differ";
302  }
303 
304  // Save full cache parameters
305  p_fullCacheStartTime = startTime;
306  p_fullCacheEndTime = endTime;
307  p_fullCacheSize = size;
308  LoadTimeCache();
309 
310  // Loop and load the cache
311  for(int i = 0; i < size; i++) {
312  double et = p_cacheTime[i];
313  SetEphemerisTime(et);
314  p_cache.push_back(p_coordinate);
316  }
317 
318  p_source = Memcache;
319  }
320 
321 
335  void SpicePosition::LoadCache(double time) {
336  LoadCache(time, time, 1);
337  }
338 
339 
363 
364  // Make sure cache isn't alread loaded
365  if(p_source == Memcache || p_source == HermiteCache) {
366  QString msg = "A SpicePosition cache has already been created";
368  }
369 
370  // Load the full cache time information from the label if available
371  if(table.Label().hasKeyword("SpkTableStartTime")) {
372  p_fullCacheStartTime = toDouble(table.Label().findKeyword("SpkTableStartTime")[0]);
373  }
374  if(table.Label().hasKeyword("SpkTableEndTime")) {
375  p_fullCacheEndTime = toDouble(table.Label().findKeyword("SpkTableEndTime")[0]);
376  }
377  if(table.Label().hasKeyword("SpkTableOriginalSize")) {
378  p_fullCacheSize = toDouble(table.Label().findKeyword("SpkTableOriginalSize")[0]);
379  }
380 
381 
382  // set source type by table's label keyword
383  if(!table.Label().hasKeyword("CacheType")) {
384  p_source = Memcache;
385  }
386  else if(table.Label().findKeyword("CacheType")[0] == "Linear") {
387  p_source = Memcache;
388  }
389  else if(table.Label().findKeyword("CacheType")[0] == "HermiteSpline") {
391  p_overrideTimeScale = 1.;
392  p_override = ScaleOnly;
393  }
394  else if(table.Label().findKeyword("CacheType")[0] == "PolyFunction") {
396  }
397  else {
399  "Invalid value for CacheType keyword in the table "
400  + table.Name(),
401  _FILEINFO_);
402  }
403 
404  // Loop through and move the table to the cache
405  if (p_source != PolyFunction) {
406  for (int r = 0; r < table.Records(); r++) {
407  TableRecord &rec = table[r];
408  if (rec.Fields() == 7) {
409  p_hasVelocity = true;
410  }
411  else if (rec.Fields() == 4) {
412  p_hasVelocity = false;
413  }
414  else {
415  QString msg = "Expecting four or seven fields in the SpicePosition table";
417  }
418 
419  std::vector<double> j2000Coord;
420  j2000Coord.push_back((double)rec[0]);
421  j2000Coord.push_back((double)rec[1]);
422  j2000Coord.push_back((double)rec[2]);
423  int inext = 3;
424 
425  p_cache.push_back(j2000Coord);
426  if (p_hasVelocity) {
427  std::vector<double> j2000Velocity;
428  j2000Velocity.push_back((double)rec[3]);
429  j2000Velocity.push_back((double)rec[4]);
430  j2000Velocity.push_back((double)rec[5]);
431  inext = 6;
432 
433  p_cacheVelocity.push_back(j2000Velocity);
434  }
435  p_cacheTime.push_back((double)rec[inext]);
436  }
437  }
438  else {
439  // Coefficient table for postion coordinates x, y, and z
440  std::vector<double> coeffX, coeffY, coeffZ;
441 
442  for (int r = 0; r < table.Records() - 1; r++) {
443  TableRecord &rec = table[r];
444 
445  if(rec.Fields() != 3) {
446  // throw an error
447  }
448  coeffX.push_back((double)rec[0]);
449  coeffY.push_back((double)rec[1]);
450  coeffZ.push_back((double)rec[2]);
451  }
452  // Take care of function time parameters
453  TableRecord &rec = table[table.Records()-1];
454  double baseTime = (double)rec[0];
455  double timeScale = (double)rec[1];
456  double degree = (double)rec[2];
457  SetPolynomialDegree((int) degree);
458  SetOverrideBaseTime(baseTime, timeScale);
459  SetPolynomial(coeffX, coeffY, coeffZ);
460  if (degree > 0) p_hasVelocity = true;
461  if(degree == 0 && p_cacheVelocity.size() > 0) p_hasVelocity = true;
462  }
463  }
464 
465 
479  Table SpicePosition::Cache(const QString &tableName) {
481  LineCache(tableName);
482  // TODO Figure out how to get the tolerance -- for now hard code .01
483  Memcache2HermiteCache(0.01);
484 
485  //std::cout << "Cache size is " << p_cache.size();
486 
487  }
488 
489  // record to be added to table
490  TableRecord record;
491 
492  if (p_source != PolyFunction) {
493  // add x,y,z position labels to record
494  TableField x("J2000X", TableField::Double);
495  TableField y("J2000Y", TableField::Double);
496  TableField z("J2000Z", TableField::Double);
497  record += x;
498  record += y;
499  record += z;
500 
501  if (p_hasVelocity) {
502  // add x,y,z velocity labels to record
503  TableField vx("J2000XV", TableField::Double);
504  TableField vy("J2000YV", TableField::Double);
505  TableField vz("J2000ZV", TableField::Double);
506  record += vx;
507  record += vy;
508  record += vz;
509  }
510  // add time label to record
512  record += t;
513 
514  // create output table
515  Table table(tableName, record);
516 
517  int inext = 0;
518 
519  for (int i = 0; i < (int)p_cache.size(); i++) {
520  record[inext++] = p_cache[i][0]; // record[0]
521  record[inext++] = p_cache[i][1]; // record[1]
522  record[inext++] = p_cache[i][2]; // record[2]
523  if (p_hasVelocity) {
524  record[inext++] = p_cacheVelocity[i][0]; // record[3]
525  record[inext++] = p_cacheVelocity[i][1]; // record[4]
526  record[inext++] = p_cacheVelocity[i][2]; // record[5]
527  }
528  record[inext] = p_cacheTime[i]; // record[6]
529  table += record;
530 
531  inext = 0;
532  }
533  CacheLabel(table);
534  return table;
535  }
536 
537  else if(p_source == PolyFunction && p_degree == 0 && p_fullCacheSize == 1)
538  // Just load the position for the single epoch
539  return LineCache(tableName);
540 
541  // Load the coefficients for the curves fit to the 3 camera angles
542  else if (p_source == PolyFunction) {
543  // PolyFunction case
544  TableField spacecraftX("J2000SVX", TableField::Double);
545  TableField spacecraftY("J2000SVY", TableField::Double);
546  TableField spacecraftZ("J2000SVZ", TableField::Double);
547 
548  TableRecord record;
549  record += spacecraftX;
550  record += spacecraftY;
551  record += spacecraftZ;
552 
553  Table table(tableName, record);
554 
555  for(int cindex = 0; cindex < p_degree + 1; cindex++) {
556  record[0] = p_coefficients[0][cindex];
557  record[1] = p_coefficients[1][cindex];
558  record[2] = p_coefficients[2][cindex];
559  table += record;
560  }
561 
562  // Load one more table entry with the time adjustments for the fit equation
563  // t = (et - baseTime)/ timeScale
564  record[0] = p_baseTime;
565  record[1] = p_timeScale;
566  record[2] = (double) p_degree;
567 
568  CacheLabel(table);
569  table += record;
570  return table;
571  }
572 
573  else {
575  "Cannot create Table, no Cache is loaded.",
576  _FILEINFO_);
577  }
578 
579  }
580 
581 
582 
590  // determine type of table to return
591  QString tabletype = "";
592 
593  if(p_source == Memcache) {
594  tabletype = "Linear";
595  }
596  else if(p_source == HermiteCache) {
597  tabletype = "HermiteSpline";
598  }
599  else {
600  tabletype = "PolyFunction";
601  }
602 
603  table.Label() += PvlKeyword("CacheType", tabletype);
604 
605  // Write original time coverage
606  if(p_fullCacheStartTime != 0) {
607  table.Label() += PvlKeyword("SpkTableStartTime");
608  table.Label()["SpkTableStartTime"].addValue(toString(p_fullCacheStartTime));
609  }
610  if(p_fullCacheEndTime != 0) {
611  table.Label() += PvlKeyword("SpkTableEndTime");
612  table.Label()["SpkTableEndTime"].addValue(toString(p_fullCacheEndTime));
613  }
614  if(p_fullCacheSize != 0) {
615  table.Label() += PvlKeyword("SpkTableOriginalSize");
616  table.Label()["SpkTableOriginalSize"].addValue(toString(p_fullCacheSize));
617  }
618  }
619 
620 
621 
635  Table SpicePosition::LineCache(const QString &tableName) {
636 
637  // Apply the function and fill the caches
639 
640  if(p_source != Memcache) {
641  QString msg = "Only cached positions can be returned as a line cache of positions and time";
643  }
644  // Load the table and return it to caller
645  return Cache(tableName);
646  }
647 
648 
649 
662 
663  // Save current et
664  double et = p_et;
665 
666  // Make sure source is a function
667  if(p_source < HermiteCache) {
668  QString msg = "The SpicePosition has not yet been fit to a function";
670  }
671 
672  // Clear existing positions from thecache
673  p_cacheTime.clear();
674  p_cache.clear();
675 
676  // Clear the velocity cache if we can calculate it instead. It can't be calculated for
677  // functions of degree 0 (framing cameras), so keep the original velocity. It is better than nothing.
678  if (p_degree > 0 && p_cacheVelocity.size() > 1) p_cacheVelocity.clear();
679 
680  // Load the time cache first
681  LoadTimeCache();
682 
683  if (p_fullCacheSize > 1) {
684  // Load the positions and velocity caches
685  p_et = -DBL_MAX; // Forces recalculation in SetEphemerisTime
686 
687  for (std::vector<double>::size_type pos = 0; pos < p_cacheTime.size(); pos++) {
688  // p_et = p_cacheTime.at(pos);
689  SetEphemerisTime(p_cacheTime.at(pos));
690  p_cache.push_back(p_coordinate);
691  p_cacheVelocity.push_back(p_velocity);
692  }
693  }
694  else {
695  // Load the position for the single updated time instance
696  p_et = p_cacheTime[0];
698  p_cache.push_back(p_coordinate);
699  }
700 
701  // Set source to cache and reset current et
702  p_source = Memcache;
703  p_et = -DBL_MAX;
704  SetEphemerisTime(et);
705 
707  }
708 
709 
720  Table SpicePosition::LoadHermiteCache(const QString &tableName) {
721  // find the first and last time values
722  double firstTime = p_fullCacheStartTime;
723  double lastTime = p_fullCacheEndTime;
724  int cacheTimeSize = (int) p_fullCacheSize;
725 
726  // Framing cameras are already cached and don't need to be reduced.
727  if(cacheTimeSize == 1) return Cache(tableName);
728 
729  //If it's already a hermite cache, just return it.
730  if (p_source == HermiteCache) {
731  return Cache(tableName);
732  }
733 
734  // Make sure a polynomial function is already loaded
735  if(p_source != PolyFunction) {
736  QString msg = "A SpicePosition polynomial function has not been created yet";
738  }
739 
740  // Load the polynomial functions
744  function1.SetCoefficients(p_coefficients[0]);
745  function2.SetCoefficients(p_coefficients[1]);
746  function3.SetCoefficients(p_coefficients[2]);
747 
748  // Clear existing coordinates from cache
749  ClearCache();
750 
751  // Set velocity vector to true since it is calculated
752  p_hasVelocity = true;
753 
754 // std::cout <<"time cache size is " << p_cacheTime.size() << std::endl;
755 
756  // Calculate new postition coordinates from polynomials fit to coordinates &
757  // fill cache
758 // std::cout << "Before" << std::endl;
759 // double savetime = p_cacheTime.at(0);
760 // SetEphemerisTime(savetime);
761 // std::cout << " at time " << savetime << std::endl;
762 // for (int i=0; i<3; i++) {
763 // std::cout << p_coordinate[i] << std::endl;
764 // }
765 
766 
767  // find time for the extremum of each polynomial
768  // since this is only a 2nd degree polynomial,
769  // finding these extrema is simple
770  double b1 = function1.Coefficient(1);
771  double c1 = function1.Coefficient(2);
772  double extremumXtime = -b1 / (2.*c1) + p_baseTime; // extremum is time value for root of 1st derivative
773  // make sure we are in the domain
774  if(extremumXtime < firstTime) {
775  extremumXtime = firstTime;
776  }
777  if(extremumXtime > lastTime) {
778  extremumXtime = lastTime;
779  }
780 
781  double b2 = function2.Coefficient(1);
782  double c2 = function2.Coefficient(2);
783  double extremumYtime = -b2 / (2.*c2) + p_baseTime;
784  // make sure we are in the domain
785  if(extremumYtime < firstTime) {
786  extremumYtime = firstTime;
787  }
788  if(extremumYtime > lastTime) {
789  extremumYtime = lastTime;
790  }
791 
792  double b3 = function3.Coefficient(1);
793  double c3 = function3.Coefficient(2);
794  double extremumZtime = -b3 / (2.*c3) + p_baseTime;
795  // make sure we are in the domain
796  if(extremumZtime < firstTime) {
797  extremumZtime = firstTime;
798  }
799  if(extremumZtime > lastTime) {
800  extremumZtime = lastTime;
801  }
802 
803  // refill the time vector
804  p_cacheTime.clear();
805  p_cacheTime.push_back(firstTime);
806  p_cacheTime.push_back(extremumXtime);
807  p_cacheTime.push_back(extremumYtime);
808  p_cacheTime.push_back(extremumZtime);
809  p_cacheTime.push_back(lastTime);
810  // we don't know order of extrema, so sort
811  sort(p_cacheTime.begin(), p_cacheTime.end());
812  // in case an extremum is an endpoint
813  std::vector <double>::iterator it = unique(p_cacheTime.begin(), p_cacheTime.end());
814  p_cacheTime.resize(it - p_cacheTime.begin());
815 
816  if(p_cacheTime.size() == 2) {
817  p_cacheTime.clear();
818  p_cacheTime.push_back(firstTime);
819  p_cacheTime.push_back((firstTime + lastTime) / 2);
820  p_cacheTime.push_back(lastTime);
821  }
822 
823  // add positions and velocities for these times
824  for(int i = 0; i < (int) p_cacheTime.size(); i++) {
825  // x,y,z positions
826  double time;
827  time = p_cacheTime[i] - p_baseTime;
828  p_coordinate[0] = function1.Evaluate(time);
829  p_coordinate[1] = function2.Evaluate(time);
830  p_coordinate[2] = function3.Evaluate(time);
831  p_cache.push_back(p_coordinate);
832 
833  // x,y,z velocities
834  p_velocity[0] = b1 + 2 * c1 * (p_cacheTime[i] - p_baseTime);
835  p_velocity[1] = b2 + 2 * c2 * (p_cacheTime[i] - p_baseTime);
836  p_velocity[2] = b3 + 2 * c3 * (p_cacheTime[i] - p_baseTime);
837  p_cacheVelocity.push_back(p_velocity);
838  }
839 
841  double et = p_et;
842  p_et = -DBL_MAX;
843  SetEphemerisTime(et);
844 
845  return Cache(tableName);
846  }
847 
848 
856  std::vector<double> XC, YC, ZC;
857 
858  // Check to see if the position is already a Polynomial Function
859  if (p_source == PolyFunction)
860  return;
861 
862  // Adjust the degree of the polynomial to the available data
863  if (p_cache.size() == 1) {
864  p_degree = 0;
865  }
866  else if (p_cache.size() == 2) {
867  p_degree = 1;
868  }
869 
870  //Check for polynomial over Hermite constant and initialize coefficients
871  if (type == PolyFunctionOverHermiteConstant) {
872  XC.assign(p_degree + 1, 0.);
873  YC.assign(p_degree + 1, 0.);
874  ZC.assign(p_degree + 1, 0.);
875  SetPolynomial(XC, YC, ZC, type);
876  return;
877  }
878 
882 
883  // Compute the base time
884  ComputeBaseTime();
885  std::vector<double> time;
886 
887  if(p_cache.size() == 1) {
888  double t = p_cacheTime.at(0);
889  SetEphemerisTime(t);
890  XC.push_back(p_coordinate[0]);
891  YC.push_back(p_coordinate[1]);
892  ZC.push_back(p_coordinate[2]);
893  }
894  else if(p_cache.size() == 2) {
895 // Load the times and get the corresponding coordinates
896  double t1 = p_cacheTime.at(0);
897  SetEphemerisTime(t1);
898  std::vector<double> coord1 = p_coordinate;
899  t1 = (t1 - p_baseTime) / p_timeScale;
900  double t2 = p_cacheTime.at(1);
901  SetEphemerisTime(t2);
902  std::vector<double> coord2 = p_coordinate;
903  t2 = (t2 - p_baseTime) / p_timeScale;
904  double slope[3];
905  double intercept[3];
906 
907 // Compute the linear equation for each coordinate and save them
908  for(int cIndex = 0; cIndex < 3; cIndex++) {
909  Isis::LineEquation posline(t1, coord1[cIndex], t2, coord2[cIndex]);
910  slope[cIndex] = posline.Slope();
911  intercept[cIndex] = posline.Intercept();
912  }
913  XC.push_back(intercept[0]);
914  XC.push_back(slope[0]);
915  YC.push_back(intercept[1]);
916  YC.push_back(slope[1]);
917  ZC.push_back(intercept[2]);
918  ZC.push_back(slope[2]);
919  }
920  else {
921  LeastSquares *fitX = new LeastSquares(function1);
922  LeastSquares *fitY = new LeastSquares(function2);
923  LeastSquares *fitZ = new LeastSquares(function3);
924 
925  // Load the known values to compute the fit equation
926  for(std::vector<double>::size_type pos = 0; pos < p_cacheTime.size(); pos++) {
927  double t = p_cacheTime.at(pos);
928  time.push_back( (t - p_baseTime) / p_timeScale);
929  SetEphemerisTime(t);
930  std::vector<double> coord = p_coordinate;
931 
932  fitX->AddKnown(time, coord[0]);
933  fitY->AddKnown(time, coord[1]);
934  fitZ->AddKnown(time, coord[2]);
935  time.clear();
936  }
937  //Solve the equations for the coefficients
938  fitX->Solve();
939  fitY->Solve();
940  fitZ->Solve();
941 
942  // Delete the least squares objects now that we have all the coefficients
943  delete fitX;
944  delete fitY;
945  delete fitZ;
946 
947  // For now assume all three coordinates are fit to a polynomial function.
948  // Later they may each be fit to a unique basis function.
949  // Fill the coefficient vectors
950 
951  for(int i = 0; i < function1.Coefficients(); i++) {
952  XC.push_back(function1.Coefficient(i));
953  YC.push_back(function2.Coefficient(i));
954  ZC.push_back(function3.Coefficient(i));
955  }
956 
957  }
958 
959  // Now that the coefficients have been calculated set the polynomial with them
960  SetPolynomial(XC, YC, ZC);
961  return;
962  }
963 
964 
965 
978  void SpicePosition::SetPolynomial(const std::vector<double>& XC,
979  const std::vector<double>& YC,
980  const std::vector<double>& ZC,
981  const Source type) {
982 
986 
987  // Load the functions with the coefficients
988  function1.SetCoefficients(XC);
989  function2.SetCoefficients(YC);
990  function3.SetCoefficients(ZC);
991 
992  // Compute the base time
993  ComputeBaseTime();
994 
995  // Save the current coefficients
996  p_coefficients[0] = XC;
997  p_coefficients[1] = YC;
998  p_coefficients[2] = ZC;
999 
1000  // Set the flag indicating p_degree has been applied to the spacecraft
1001  // positions and the coefficients of the polynomials have been saved.
1002  p_degreeApplied = true;
1003 
1004  // Reset the interpolation source
1005  p_source = type;
1006 
1007  // Update the current position
1008  double et = p_et;
1009  p_et = -DBL_MAX;
1010  SetEphemerisTime(et);
1011 
1012  return;
1013  }
1014 
1015 
1016 
1027  void SpicePosition::GetPolynomial(std::vector<double>& XC,
1028  std::vector<double>& YC,
1029  std::vector<double>& ZC) {
1030  XC = p_coefficients[0];
1031  YC = p_coefficients[1];
1032  ZC = p_coefficients[2];
1033 
1034  return;
1035  }
1036 
1037 
1038 
1041  if(p_override == NoOverrides) {
1042  p_baseTime = (p_cacheTime.at(0) + p_cacheTime.at(p_cacheTime.size() - 1)) / 2.;
1044  }
1045  else if (p_override == ScaleOnly) {
1046  p_baseTime = (p_cacheTime.at(0) + p_cacheTime.at(p_cacheTime.size() - 1)) / 2.;
1048  }
1049  else {
1052  }
1053 
1054  // Take care of case where 1st and last times are the same
1055  if(p_timeScale == 0) p_timeScale = 1.0;
1056  return;
1057  }
1058 
1059 
1071  void SpicePosition::SetOverrideBaseTime(double baseTime, double timeScale) {
1072  p_overrideBaseTime = baseTime;
1073  p_overrideTimeScale = timeScale;
1074  p_override = BaseAndScale;
1075  return;
1076  }
1077 
1078 
1079 
1092  SpicePosition::PartialType partialVar, int coeffIndex) {
1093  // Start with a zero vector since the derivative of the other coordinates
1094  // with respect to the partial var will be 0.
1095  std::vector<double> coordinate(3, 0);
1096 
1097  // Get the index of the coordinate to update with the partial derivative
1098  int coordIndex = partialVar;
1099 
1100 // if(coeffIndex > 2) {
1101 // QString msg = "SpicePosition only supports up to a 2nd order fit for the spacecraft position";
1102 // throw IException(IException::Programmer, msg, _FILEINFO_);
1103 // }
1104 //
1105  // Reset the coordinate to its derivative
1106  coordinate[coordIndex] = DPolynomial(coeffIndex);
1107  return coordinate;
1108  }
1109 
1110 
1111 
1132  std::vector<double> SpicePosition::VelocityPartial(
1133  SpicePosition::PartialType partialVar, int coeffIndex) {
1134  // Start with a zero vector since the derivative of the other coordinates with
1135  // respect to the partial var will be 0.
1136  std::vector<double> dvelocity(3, 0);
1137 
1138  // Get the index of the coordinate to update with the partial derivative
1139  int coordIndex = partialVar;
1140 
1141  double time = (p_et - p_baseTime) / p_timeScale;
1142  double derivative = 0.;
1143 
1144  // Handle arithmetic failures
1145  double Epsilon = 1.0e-15;
1146  if (fabs(time) <= Epsilon) time = 0.0;
1147 
1148  // Only compute for coefficient index > 0 to avoid problems like 0 ** -1
1149  if (coeffIndex > 0)
1150  derivative = coeffIndex * pow(time, coeffIndex-1) / p_timeScale;
1151 
1152  // Reset the velocity coordinate to its derivative
1153  dvelocity[coordIndex] = derivative;
1154  return dvelocity;
1155  }
1156 
1157 
1168  double SpicePosition::DPolynomial(const int coeffIndex) {
1169  double derivative = 1.;
1170  double time = (p_et - p_baseTime) / p_timeScale;
1171 
1172  if(coeffIndex > 0 && coeffIndex <= p_degree) {
1173  derivative = pow(time, coeffIndex);
1174  }
1175  else if(coeffIndex == 0) {
1176  derivative = 1;
1177  }
1178  else {
1179  QString msg = "Unable to evaluate the derivative of the SPICE position fit polynomial for "
1180  "the given coefficient index [" + toString(coeffIndex) + "]. "
1181  "Index is negative or exceeds degree of polynomial ["
1182  + toString(p_degree) + "]";
1184  }
1185 
1186  return derivative;
1187  }
1188 
1193  const std::vector<double> &SpicePosition::Velocity() {
1194  if(p_hasVelocity) {
1195  return p_velocity;
1196  }
1197  else {
1198  QString msg = "No velocity vector available";
1200  }
1201  }
1202 
1203 
1204 
1219  // If the cache has only one position return it
1220  if(p_cache.size() == 1) {
1221  p_coordinate[0] = p_cache[0][0];
1222  p_coordinate[1] = p_cache[0][1];
1223  p_coordinate[2] = p_cache[0][2];
1224 
1225  if(p_hasVelocity) {
1226  p_velocity[0] = p_cacheVelocity[0][0];
1227  p_velocity[1] = p_cacheVelocity[0][1];
1228  p_velocity[2] = p_cacheVelocity[0][2];
1229  }
1230  }
1231 
1232  else {
1233  // Otherwise determine the interval to interpolate
1234  std::vector<double>::iterator pos;
1235  pos = upper_bound(p_cacheTime.begin(), p_cacheTime.end(), p_et);
1236 
1237  int cacheIndex;
1238  if(pos != p_cacheTime.end()) {
1239  cacheIndex = distance(p_cacheTime.begin(), pos);
1240  cacheIndex--;
1241  }
1242  else {
1243  cacheIndex = p_cacheTime.size() - 2;
1244  }
1245 
1246  if(cacheIndex < 0) cacheIndex = 0;
1247 
1248  // Interpolate the coordinate
1249  double mult = (p_et - p_cacheTime[cacheIndex]) /
1250  (p_cacheTime[cacheIndex+1] - p_cacheTime[cacheIndex]);
1251  std::vector<double> p2 = p_cache[cacheIndex+1];
1252  std::vector<double> p1 = p_cache[cacheIndex];
1253 
1254  p_coordinate[0] = (p2[0] - p1[0]) * mult + p1[0];
1255  p_coordinate[1] = (p2[1] - p1[1]) * mult + p1[1];
1256  p_coordinate[2] = (p2[2] - p1[2]) * mult + p1[2];
1257 
1258  if(p_hasVelocity) {
1259  p2 = p_cacheVelocity[cacheIndex+1];
1260  p1 = p_cacheVelocity[cacheIndex];
1261  p_velocity[0] = (p2[0] - p1[0]) * mult + p1[0];
1262  p_velocity[1] = (p2[1] - p1[1]) * mult + p1[1];
1263  p_velocity[2] = (p2[2] - p1[2]) * mult + p1[2];
1264  }
1265  }
1266  }
1267 
1268 
1269 
1282 
1283  // what if framing camera???
1284 
1285  // On the first SetEphemerisTime, create our splines. Later calls should
1286  // reuse these splines.
1287  if(p_xhermite == NULL) {
1288  p_overrideTimeScale = 1.;
1289  p_override = ScaleOnly;
1290  ComputeBaseTime();
1291 
1298 
1299  vector<double> xvalues(p_cache.size());
1300  vector<double> xhermiteYValues(p_cache.size());
1301  vector<double> yhermiteYValues(p_cache.size());
1302  vector<double> zhermiteYValues(p_cache.size());
1303 
1304  vector<double> xhermiteVelocities(p_cache.size());
1305  vector<double> yhermiteVelocities(p_cache.size());
1306  vector<double> zhermiteVelocities(p_cache.size());
1307 
1308  for(unsigned int i = 0; i < p_cache.size(); i++) {
1309  vector<double> &cache = p_cache[i];
1310  double &cacheTime = p_cacheTime[i];
1311  xvalues[i] = (cacheTime - p_baseTime) / p_timeScale;
1312 
1313  xhermiteYValues[i] = cache[0];
1314  yhermiteYValues[i] = cache[1];
1315  zhermiteYValues[i] = cache[2];
1316 
1317  if(p_hasVelocity) { // Line scan camera
1318  vector<double> &cacheVelocity = p_cacheVelocity[i];
1319  xhermiteVelocities[i] = cacheVelocity[0];
1320  yhermiteVelocities[i] = cacheVelocity[1];
1321  zhermiteVelocities[i] = cacheVelocity[2];
1322  }
1323  else { // Not line scan camera
1324  throw IException(IException::Io, "No velocities available.",
1325  _FILEINFO_);
1326  }
1327  }
1328 
1329  p_xhermite->AddData(xvalues, xhermiteYValues);
1330  p_xhermite->AddCubicHermiteDeriv(xhermiteVelocities);
1331 
1332  p_yhermite->AddData(xvalues, yhermiteYValues);
1333  p_yhermite->AddCubicHermiteDeriv(yhermiteVelocities);
1334 
1335  p_zhermite->AddData(xvalues, zhermiteYValues);
1336  p_zhermite->AddCubicHermiteDeriv(zhermiteVelocities);
1337  }
1338 
1339  // Next line added 07/13/2009 to prevent Camera unit test from bombing
1340  // because time is outside domain. DAC Also added etype to Evaluate calls
1343 
1344  vector<double> &coordinate = p_coordinate;
1345  double sTime = (p_et - p_baseTime) / p_timeScale;
1346  coordinate[0] = p_xhermite->Evaluate(sTime, etype);
1347  coordinate[1] = p_yhermite->Evaluate(sTime, etype);
1348  coordinate[2] = p_zhermite->Evaluate(sTime, etype);
1349 
1350  vector<double> &velocity = p_velocity;
1351  velocity[0] = p_xhermite->EvaluateCubicHermiteFirstDeriv(sTime);
1352  velocity[1] = p_yhermite->EvaluateCubicHermiteFirstDeriv(sTime);
1353  velocity[2] = p_zhermite->EvaluateCubicHermiteFirstDeriv(sTime);
1354  }
1355 
1356 
1357 
1370  // Create the empty functions
1374 
1375  // Load the coefficients to define the functions
1376  functionX.SetCoefficients(p_coefficients[0]);
1377  functionY.SetCoefficients(p_coefficients[1]);
1378  functionZ.SetCoefficients(p_coefficients[2]);
1379 
1380  // Normalize the time
1381  double rtime;
1382  rtime = (p_et - p_baseTime) / p_timeScale;
1383 
1384  // Evaluate the polynomials at current et to get position;
1385  p_coordinate[0] = functionX.Evaluate(rtime);
1386  p_coordinate[1] = functionY.Evaluate(rtime);
1387  p_coordinate[2] = functionZ.Evaluate(rtime);
1388 
1389  if(p_hasVelocity) {
1390 
1391  if( p_degree == 0) {
1393  }
1394  else {
1395  p_velocity[0] = ComputeVelocityInTime(WRT_X);
1396  p_velocity[1] = ComputeVelocityInTime(WRT_Y);
1397  p_velocity[2] = ComputeVelocityInTime(WRT_Z);
1398  }
1399 
1400 // p_velocity[0] = functionX.DerivativeVar(rtime);
1401 // p_velocity[1] = functionY.DerivativeVar(rtime);
1402 // p_velocity[2] = functionZ.DerivativeVar(rtime);
1403  }
1404  }
1405 
1406 
1420  std::vector<double> hermiteCoordinate = p_coordinate;
1421 
1422 // std::cout << hermiteCoordinate << std::endl;
1423 
1424  std::vector<double> hermiteVelocity = p_velocity;
1426 
1427  for (int index = 0; index < 3; index++) {
1428  p_coordinate[index] += hermiteCoordinate[index];
1429  p_velocity[index] += hermiteVelocity[index];
1430  }
1431  }
1432 
1433 
1450 
1451  double state[6];
1452  bool hasVelocity;
1453  double lt;
1454 
1455  // NOTE: Prefer method getter access as some are virtualized and portray
1456  // the appropriate internal representation!!!
1458  "J2000", GetAberrationCorrection(), state, hasVelocity,
1459  lt);
1460 
1461  // Set the internal state
1462  setStateVector(state, hasVelocity);
1463  setLightTime(lt);
1464  return;
1465  }
1466 
1467 
1480  void SpicePosition::Memcache2HermiteCache(double tolerance) {
1481  if(p_source == HermiteCache) {
1482  return;
1483  }
1484  else if(p_source != Memcache) {
1486  "Source type is not Memcache, cannot convert.",
1487  _FILEINFO_);
1488  }
1489 
1490  // make sure base time is set before it is needed
1491  p_overrideTimeScale = 1.;
1492  p_override = ScaleOnly;
1493  ComputeBaseTime();
1494 
1495  // find current size of cache
1496  int n = p_cacheTime.size() - 1;
1497 
1498  // create 3 starting values for the new table
1499  vector <int> inputIndices;
1500  inputIndices.push_back(0);
1501  inputIndices.push_back(n / 2);
1502  inputIndices.push_back(n);
1503 
1504  // find all indices needed to make a hermite table within the appropriate tolerance
1505  vector <int> indexList = HermiteIndices(tolerance, inputIndices);
1506 
1507  // remove all lines from cache vectors that are not in the index list????
1508  for(int i = n; i >= 0; i--) {
1509  if(!binary_search(indexList.begin(), indexList.end(), i)) {
1510  p_cache.erase(p_cache.begin() + i);
1511  p_cacheTime.erase(p_cacheTime.begin() + i);
1512  p_cacheVelocity.erase(p_cacheVelocity.begin() + i);
1513  }
1514  }
1515 
1517  }
1518 
1540  std::vector<int> SpicePosition::HermiteIndices(double tolerance, std::vector <int> indexList) {
1541 
1542  unsigned int n = indexList.size();
1543  double sTime;
1544 
1548  for(unsigned int i = 0; i < indexList.size(); i++) {
1549  sTime = (p_cacheTime[indexList[i]] - p_baseTime) / p_timeScale;
1550  xhermite.AddData(sTime, p_cache[indexList[i]][0]); // add time, x-position to x spline
1551  yhermite.AddData(sTime, p_cache[indexList[i]][1]); // add time, y-position to y spline
1552  zhermite.AddData(sTime, p_cache[indexList[i]][2]); // add time, z-position to z spline
1553 
1554  if(p_hasVelocity) { // Line scan camera
1555  xhermite.AddCubicHermiteDeriv(p_cacheVelocity[i][0]); // add x-velocity to x spline
1556  yhermite.AddCubicHermiteDeriv(p_cacheVelocity[i][1]); // add y-velocity to y spline
1557  zhermite.AddCubicHermiteDeriv(p_cacheVelocity[i][2]); // add z-velocity to z spline
1558  }
1559  else { // Not line scan camera
1560  throw IException(IException::Io, "No velocities available.", _FILEINFO_);
1561  // xhermite.AddCubicHermiteDeriv(0.0); // spacecraft didn't move => velocity = 0
1562  // yhermite.AddCubicHermiteDeriv(0.0); // spacecraft didn't move => velocity = 0
1563  // zhermite.AddCubicHermiteDeriv(0.0); // spacecraft didn't move => velocity = 0
1564  }
1565  }
1566 
1567  // loop through the saved indices from the end
1568  for(unsigned int i = indexList.size() - 1; i > 0; i--) {
1569  double xerror = 0;
1570  double yerror = 0;
1571  double zerror = 0;
1572 
1573  // check every value of the original kernel values within interval
1574  for(int line = indexList[i-1] + 1; line < indexList[i]; line++) {
1575  sTime = (p_cacheTime[line] - p_baseTime) / p_timeScale;
1576 
1577  // find the errors at each value
1578  xerror = fabs(xhermite.Evaluate(sTime) - p_cache[line][0]);
1579  yerror = fabs(yhermite.Evaluate(sTime) - p_cache[line][1]);
1580  zerror = fabs(zhermite.Evaluate(sTime) - p_cache[line][2]);
1581 
1582  if(xerror > tolerance || yerror > tolerance || zerror > tolerance) {
1583  // if any error is greater than tolerance, no need to continue looking, break
1584  break;
1585  }
1586  }
1587 
1588  if(xerror < tolerance && yerror < tolerance && zerror < tolerance) {
1589  // if errors are less than tolerance after looping interval, no new point is necessary
1590  continue;
1591  }
1592  else {
1593  // if any error is greater than tolerance, add midpoint of interval to indexList vector
1594  indexList.push_back((indexList[i] + indexList[i-1]) / 2);
1595  }
1596  }
1597 
1598  if(indexList.size() > n) {
1599  sort(indexList.begin(), indexList.end());
1600  indexList = HermiteIndices(tolerance, indexList);
1601  }
1602  return indexList;
1603  }
1604 
1605 
1610  p_cache.clear();
1611  p_cacheVelocity.clear();
1612  p_cacheTime.clear();
1613 
1614  if(p_xhermite) {
1615  delete p_xhermite;
1616  p_xhermite = NULL;
1617  }
1618 
1619  if(p_yhermite) {
1620  delete p_xhermite;
1621  p_xhermite = NULL;
1622  }
1623 
1624  if(p_zhermite) {
1625  delete p_xhermite;
1626  p_xhermite = NULL;
1627  }
1628  }
1629 
1630 
1631 
1641  // Adjust the degree for the data
1642  if(p_fullCacheSize == 1) {
1643  degree = 0;
1644  }
1645  else if(p_fullCacheSize == 2) {
1646  degree = 1;
1647  }
1648  // If polynomials have not been applied yet simply set the degree and return
1649  if(!p_degreeApplied) {
1650  p_degree = degree;
1651  }
1652 
1653  // Otherwise the existing polynomials need to be either expanded ...
1654  else if(p_degree < degree) { // (increase the number of terms)
1655  std::vector<double> coefX(p_coefficients[0]),
1656  coefY(p_coefficients[1]),
1657  coefZ(p_coefficients[2]);
1658 
1659  for(int icoef = p_degree + 1; icoef <= degree; icoef++) {
1660  coefX.push_back(0.);
1661  coefY.push_back(0.);
1662  coefZ.push_back(0.);
1663  }
1664  p_degree = degree;
1665  SetPolynomial(coefX, coefY, coefZ);
1666  }
1667  // ... or reduced (decrease the number of terms)
1668  else if(p_degree > degree) {
1669  std::vector<double> coefX(degree + 1),
1670  coefY(degree + 1),
1671  coefZ(degree + 1);
1672 
1673  for(int icoef = 0; icoef <= degree; icoef++) {
1674  coefX.push_back(p_coefficients[0][icoef]);
1675  coefY.push_back(p_coefficients[1][icoef]);
1676  coefZ.push_back(p_coefficients[2][icoef]);
1677  }
1678  p_degree = degree;
1679  SetPolynomial(coefX, coefY, coefZ);
1680  }
1681  }
1682 
1683 
1684 
1697  p_source = Spice;
1698  ClearCache();
1699  LoadCache(table);
1700  }
1701 
1707  // Loop and load the time cache
1708  double cacheSlope = 0.0;
1709 
1710  if(p_fullCacheSize > 1)
1711  cacheSlope = (p_fullCacheEndTime - p_fullCacheStartTime) /
1712  (double)(p_fullCacheSize - 1);
1713 
1714  for(int i = 0; i < p_fullCacheSize; i++) {
1715  double et = p_fullCacheStartTime + (double) i * cacheSlope;
1716  p_cacheTime.push_back(et);
1717  }
1718  }
1719 
1723  const std::vector<double> &SpicePosition::GetCenterCoordinate() {
1724  // Compute the center time
1725  double etCenter = (p_fullCacheEndTime + p_fullCacheStartTime) / 2.;
1726  SetEphemerisTime(etCenter);
1727 
1728  return Coordinate();
1729  }
1730 
1731 
1740  double SpicePosition::ComputeVelocityInTime(PartialType var) {
1741  double velocity = 0.;
1742 
1743  for (int icoef=1; icoef <= p_degree; icoef++) {
1744  velocity += icoef*p_coefficients[var][icoef]*pow((p_et - p_baseTime), (icoef - 1))
1745  / pow(p_timeScale, icoef);
1746  }
1747 
1748  return velocity;
1749  }
1750 
1751 
1763  std::vector<double> SpicePosition::Extrapolate(double timeEt) {
1764  if (!p_hasVelocity) return p_coordinate;
1765 
1766  double diffTime = timeEt - p_et;
1767  std::vector<double> extrapPos(3, 0.);
1768  extrapPos[0] = p_coordinate[0] + diffTime*p_velocity[0];
1769  extrapPos[1] = p_coordinate[1] + diffTime*p_velocity[1];
1770  extrapPos[2] = p_coordinate[2] + diffTime*p_velocity[2];
1771 
1772  return extrapPos;
1773  }
1774 
1775 
1783  std::vector<double> SpicePosition::HermiteCoordinate() {
1786  "Hermite coordinates only available for PolyFunctionOverHermiteConstant",
1787  _FILEINFO_);
1788  }
1789 
1790  // Save the current coordinate so it can be reset
1791  std::vector<double> coordinate = p_coordinate;
1793  std::vector<double> hermiteCoordinate = p_coordinate;
1794  p_coordinate = coordinate;
1795  return hermiteCoordinate;
1796  }
1797 
1798  //=========================================================================
1799  // Observer/Target swap and light time correction methods
1800  //=========================================================================
1801 
1813  return (p_observerCode);
1814  }
1815 
1827  return (p_targetCode);
1828  }
1829 
1830 
1843  return (EphemerisTime() + GetTimeBias());
1844  }
1845 
1846 
1879  void SpicePosition::computeStateVector(double et, int target, int observer,
1880  const QString &refFrame,
1881  const QString &abcorr,
1882  double state[6], bool &hasVelocity,
1883  double &lightTime) const {
1884 
1885  // First try getting the entire state (including the velocity vector)
1887  hasVelocity = true;
1888  lightTime = 0.0;
1889  spkez_c((SpiceInt) target, (SpiceDouble) et, refFrame.toLatin1().data(),
1890  abcorr.toLatin1().data(), (SpiceInt) observer, state, &lightTime);
1891 
1892  // If Naif fails attempting to get the entire state, assume the velocity vector is
1893  // not available and just get the position. First turn off Naif error reporting and
1894  // return any error without printing them.
1895  SpiceBoolean spfailure = failed_c();
1896  reset_c(); // Reset Naif error system to allow caller to recover
1897  if ( spfailure ) {
1898  hasVelocity = false;
1899  lightTime = 0.0;
1900  spkezp_c((SpiceInt) target, (SpiceDouble) et, refFrame.toLatin1().data(),
1901  abcorr.toLatin1().data(), (SpiceInt) observer, state, &lightTime);
1902  }
1904  return;
1905  }
1906 
1931  void SpicePosition::setStateVector(const double state[6],
1932  const bool &hasVelocity) {
1933 
1934  p_coordinate[0] = state[0];
1935  p_coordinate[1] = state[1];
1936  p_coordinate[2] = state[2];
1937 
1938  if ( hasVelocity ) {
1939  p_velocity[0] = state[3];
1940  p_velocity[1] = state[4];
1941  p_velocity[2] = state[5];
1942  }
1943  else {
1944  p_velocity[0] = 0.0;
1945  p_velocity[1] = 0.0;
1946  p_velocity[2] = 0.0;
1947  }
1948  p_hasVelocity = hasVelocity;
1949 
1950  // Negate vectors if swap of observer target is requested so interface
1951  // remains consistent
1952  if (m_swapObserverTarget) {
1953  vminus_c(&p_velocity[0], &p_velocity[0]);
1954  vminus_c(&p_coordinate[0], &p_coordinate[0]);
1955  }
1956 
1957  return;
1958  }
1959 
1961  void SpicePosition::setLightTime(const double &lightTime) {
1962  m_lt = lightTime;
1963  return;
1964  }
1965 
1966  // /** Resets the source interpolation of the position.
1967  // *
1968  // * @param [in] source The interpolation to use for calculating position
1969  // *
1970  // */
1971  // void SetSource(Source source) {
1972  // p_source = source;
1973  // return;
1974  // }
1975 }
1976 
1977 
1978 
1979 
1980 
1981 
int Records() const
Returns the number of records.
Definition: Table.cpp:224
int getObserverCode() const
Returns observer code.
double p_timeScale
Time scale used in fit equations.
Object is reading from splined table.
void CacheLabel(Table &table)
Add labels to a SpicePosition table.
const std::vector< double > & GetCenterCoordinate()
Compute and return the coordinate at the center time.
double p_timeBias
iTime bias when reading kernels
Source p_source
Enumerated value for the location of the SPK information used.
double GetLightTime() const
Return the light time coorection value.
virtual ~SpicePosition()
Destructor.
void SetCoefficients(const std::vector< double > &coefs)
Set the coefficients for the equation.
Object is calculated from nth degree polynomial.
int p_degree
Degree of polynomial function fit to the coordinates of the position.
virtual void SetAberrationCorrection(const QString &correction)
Set the aberration correction (light time)
std::vector< double > Extrapolate(double timeEt)
Extrapolate position for a given time assuming a constant velocity.
Utility class for creating and using cartesean line equations.
Definition: LineEquation.h:44
void SetTimeBias(double timeBias)
Apply a time bias when invoking SetEphemerisTime method.
int p_targetCode
target body code
double Intercept()
Compute the intercept of the line.
OverrideType p_override
Time base and scale override options;.
double p_fullCacheStartTime
Original start time of the complete cache after spiceinit.
Nth degree Polynomial with one variable.
Object is reading from cached table.
double EphemerisTime() const
Return the current ephemeris time.
int getTargetCode() const
Returns target code.
std::vector< double > CoordinatePartial(SpicePosition::PartialType partialVar, int coeffIndex)
Set the coefficients of a polynomial fit to each of the three coordinates of the position vector for ...
void ComputeBaseTime()
Compute the base time using cached times.
NumericalApproximation provides various numerical analysis methods of interpolation, extrapolation and approximation of a tabulated set of x, y data.
double ComputeVelocityInTime(PartialType var)
Compute the velocity with respect to time instead of scaled time.
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition: IString.cpp:226
void SetEphemerisTimePolyFunctionOverHermiteConstant()
This is a protected method that is called by SetEphemerisTime() when Source type is PolyFunctionOverH...
double toDouble(const QString &string)
Global function to convert from a string to a double.
Definition: IString.cpp:164
This error is for when a programmer made an API call that was illegal.
Definition: IException.h:162
A type of error that occurred when performing an actual I/O operation.
Definition: IException.h:171
double p_fullCacheEndTime
Original end time of the complete cache after spiceinit.
double EvaluateCubicHermiteFirstDeriv(const double a)
Approximates the first derivative of the data set function evaluated at the given domain value for Cu...
void LoadCache(double startTime, double endTime, int size)
Cache J2000 position over a time range.
void computeStateVector(double et, int target, int observer, const QString &refFrame, const QString &abcorr, double state[6], bool &hasVelocity, double &lightTime) const
Computes the state vector of the target w.r.t observer.
void init(int targetCode, int observerCode, const bool &swapObserverTarget=false)
Internal initialization of the object support observer/target swap.
void LoadTimeCache()
Load the time cache.
void AddCubicHermiteDeriv(unsigned int n, double *fprimeOfx)
Adds values for the first derivatives of the data points.
double p_fullCacheSize
Orignial size of the complete cache after spiceinit.
bool hasKeyword(const QString &kname, FindOptions opts) const
See if a keyword is in the current PvlObject, or deeper inside other PvlObjects and Pvlgroups within ...
Definition: PvlObject.cpp:207
void ReloadCache()
Cache J2000 positions over existing cached time range using polynomials.
Table Cache(const QString &tableName)
Return a table with J2000 positions.
Cubic Spline interpolation using the Hermite cubic polynomial.
void SetEphemerisTimePolyFunction()
This is a protected method that is called by SetEphemerisTime() when Source type is PolyFunction...
double Evaluate(const double a, const ExtrapType &etype=ThrowError)
Calculates interpolated or extrapolated value of tabulated data set for given domain value...
std::vector< double > p_coordinate
J2000 position at time et.
NumericalApproximation * p_xhermite
Hermite spline for x coordinate if Source == HermiteCache.
std::vector< double > p_coefficients[3]
Coefficients of polynomials fit to 3 coordinates.
virtual QString GetAberrationCorrection() const
Returns current state of stellar aberration correction.
double p_baseTime
Base time used in fit equations.
double getAdjustedEphemerisTime() const
Returns adjusted ephemeris time.
PvlKeyword & findKeyword(const QString &kname, FindOptions opts)
Finds a keyword in the current PvlObject, or deeper inside other PvlObjects and Pvlgroups within this...
Definition: PvlObject.cpp:148
void ClearCache()
Removes the entire cache from memory.
ExtrapType
This enum defines the manner in which a value outside of the domain should be handled if passed to th...
#define _FILEINFO_
Macro for the filename and line number.
Definition: IException.h:40
bool p_hasVelocity
Flag to indicate velocity is available.
QString p_aberrationCorrection
Light time correction to apply.
A single keyword-value pair.
Definition: PvlKeyword.h:98
void setStateVector(const double state[6], const bool &hasVelocity)
Sets the state of target relative to observer.
const std::vector< double > & Coordinate()
Return the current J2000 position.
void SetPolynomialDegree(int degree)
Set the polynomial degree.
void SetOverrideBaseTime(double baseTime, double timeScale)
Set an override base time to be used with observations on scanners to allow all images in an observat...
int p_observerCode
observer body code
std::vector< int > HermiteIndices(double tol, std::vector< int > indexList)
This method is called by Memcache2HermiteCache() to determine which indices from the orginal cache sh...
double p_overrideBaseTime
Value set by caller to override computed base time.
NumericalApproximation * p_zhermite
Hermite spline for z coordinate if Source == HermiteCache.
Generic least square fitting class.
Definition: LeastSquares.h:115
void SetEphemerisTimeHermiteCache()
This is a protected method that is called by SetEphemerisTime() when Source type is HermiteCache...
The values in the field are 8 byte doubles.
Definition: TableField.h:70
void Memcache2HermiteCache(double tolerance)
This method reduces the cache for position, time and velocity to the minimum number of values needed ...
double p_et
Current ephemeris time.
double DPolynomial(const int coeffIndex)
Evaluate the derivative of the fit polynomial (parabola) defined by the given coefficients with respe...
void AddKnown(const std::vector< double > &input, double expected, double weight=1.0)
Invoke this method for each set of knowns.
double Coefficient(int i) const
Returns the ith coefficient.
void SetEphemerisTimeMemcache()
This is a protected method that is called by SetEphemerisTime() when Source type is Memcache...
QString Name() const
Accessor method that returns a string containing the Blob name.
Definition: Blob.cpp:149
std::vector< double > p_velocity
J2000 velocity at time et.
bool p_degreeApplied
Flag indicating whether or not a polynomial.
Class for storing Table blobs information.
Definition: Table.h:77
NumericalApproximation * p_yhermite
Hermite spline for y coordinate if Source == HermiteCache.
void AddData(const double x, const double y)
Add a datapoint to the set.
double Evaluate(const std::vector< double > &vars)
Compute the equation using the input variables.
std::vector< double > VelocityPartial(SpicePosition::PartialType partialVar, int coeffIndex)
Compute the derivative of the velocity with respect to the specified variable.
static void CheckErrors(bool resetNaif=true)
This method looks for any naif errors that might have occurred.
Definition: NaifStatus.cpp:43
Isis exception class.
Definition: IException.h:107
const std::vector< double > & Velocity()
Return the current J2000 velocity.
Namespace for ISIS/Bullet specific routines.
Definition: Apollo.h:31
Table LineCache(const QString &tableName)
Return a table with J2000 to reference positions.
int Fields() const
Returns the number of fields that are currently in the record.
Definition: TableRecord.cpp:94
void setLightTime(const double &lightTime)
Inheritors can set the light time if indicated.
Table LoadHermiteCache(const QString &tableName)
Cache J2000 position over existing cached time range using polynomials stored as Hermite cubic spline...
const std::vector< double > & SetEphemerisTime(double et)
Return J2000 coordinate at given time.
Class for storing an Isis::Table&#39;s field information.
Definition: TableField.h:63
PvlObject & Label()
Accessor method that returns a PvlObject containing the Blob label.
Definition: Blob.cpp:167
double m_lt
!< Swap traditional order
Evaluate() attempts to extrapolate if a is outside of the domain. This is only valid for NumericalApp...
std::vector< std::vector< double > > p_cacheVelocity
Cached velocities.
std::vector< double > HermiteCoordinate()
This method returns the Hermite coordinate for the current time for PolyFunctionOverHermiteConstant f...
SpicePosition(int targetCode, int observerCode)
Construct an empty SpicePosition class using valid body codes.
Object is reading directly from the kernels.
std::vector< double > p_cacheTime
iTime for corresponding position
double p_overrideTimeScale
Value set by caller to override computed time scale.
double Slope()
Compute the slope of the line.
virtual void SetEphemerisTimeSpice()
This is a protected method that is called by SetEphemerisTime() when Source type is Spice...
double GetTimeBias() const
Returns the value of the time bias added to ET.
int Solve(Isis::LeastSquares::SolveMethod method=SVD)
After all the data has been registered through AddKnown, invoke this method to solve the system of eq...
int Coefficients() const
Returns the number of coefficients for the equation.
Definition: BasisFunction.h:80
void GetPolynomial(std::vector< double > &XC, std::vector< double > &YC, std::vector< double > &ZC)
Return the coefficients of a polynomial fit to each of the three coordinates of the position for the ...
std::vector< std::vector< double > > p_cache
Cached positions.
Source
This enum indicates the status of the object.
void SetPolynomial(const Source type=PolyFunction)
Set the coefficients of a polynomial fit to each of the components (X, Y, Z) of the position vector f...