7#include "SpicePosition.h" 
   17#include "BasisFunction.h" 
   18#include "IException.h" 
   19#include "LeastSquares.h" 
   20#include "LineEquation.h" 
   21#include "NaifStatus.h" 
   22#include "NumericalApproximation.h" 
   23#include "PolynomialUnivariate.h" 
   24#include "TableField.h" 
   26using json = nlohmann::json;
 
   38    init(targetCode, observerCode, 
false);
 
 
   71                               bool swapObserverTarget) {
 
   72    init(targetCode, observerCode, swapObserverTarget);
 
 
   88                           const bool &swapObserverTarget) {
 
  112    m_swapObserverTarget = swapObserverTarget;
 
  117    if ( m_swapObserverTarget ) {
 
 
  187    QString abcorr(correction);
 
  188    abcorr.remove(QChar(
' '));
 
  189    abcorr = abcorr.toUpper();
 
  191    validAbcorr << 
"NONE" << 
"LT" << 
"LT+S" << 
"CN" << 
"CN+S" 
  192                << 
"XLT" << 
"XLT+S" << 
"XCN" << 
"XCN+S";
 
  194    if (validAbcorr.indexOf(abcorr) >= 0) {
 
  198      QString msg = 
"Invalid abberation correction [" + correction + 
"]";
 
 
  300      QString msg = 
"A SpicePosition cache has already been created";
 
  304    if(startTime > endTime) {
 
  305      QString msg = 
"Argument startTime must be less than or equal to endTime";
 
  309    if((startTime != endTime) && (size == 1)) {
 
  310      QString msg = 
"Cache size must be more than 1 if startTime endTime differ";
 
  321    std::vector<ale::State> stateCache;
 
  322    for(
int i = 0; i < size; i++) {
 
  325      ale::State currentState = ale::State(ale::Vec3d(
p_coordinate));
 
  327        currentState.velocity = ale::Vec3d(
p_velocity);
 
  329      stateCache.push_back(currentState);
 
 
  377    p_cacheTime = isdPos[
"ephemeris_times"].get<std::vector<double>>();
 
  381    std::vector<ale::State> stateCache;
 
  383      for (
auto it = isdPos[
"positions"].begin(); it != isdPos[
"positions"].end(); it++) {
 
  384        int index = it - isdPos[
"positions"].begin();
 
  385        std::vector<double> pos = it->get<std::vector<double>>();
 
  386        std::vector<double> vel = isdPos[
"velocities"][index];
 
  387        stateCache.push_back(ale::State(ale::Vec3d(pos), ale::Vec3d(vel)));
 
  391      for (
auto it = isdPos[
"positions"].begin(); it != isdPos[
"positions"].end(); it++) {
 
  392        std::vector<double> pos = {it->at(0).get<
double>(), it->at(1).get<
double>(), it->at(2).get<
double>()};
 
  393        stateCache.push_back(ale::State(ale::Vec3d(pos)));
 
 
  433      QString msg = 
"A SpicePosition cache has already been created";
 
  466                       "Invalid value for CacheType keyword in the table " 
  471    std::vector<ale::State> stateCache;
 
  474      for (
int r = 0; r < table.
Records(); r++) {
 
  476        if (rec.Fields() == 7) {
 
  479        else if (rec.Fields() == 4) {
 
  483          QString msg = 
"Expecting four or seven fields in the SpicePosition table";
 
  487        ale::State currentState(ale::Vec3d((
double)rec[0],
 
  494          currentState.velocity = ale::Vec3d((
double)rec[3],
 
  499        stateCache.push_back(currentState);
 
  510      std::vector<double> coeffX, coeffY, coeffZ;
 
  512      for (
int r = 0; r < table.
Records() - 1; r++) {
 
  515        if(rec.Fields() != 3) {
 
  518        coeffX.push_back((
double)rec[0]);
 
  519        coeffY.push_back((
double)rec[1]);
 
  520        coeffZ.push_back((
double)rec[2]);
 
  524      double baseTime = (double)rec[0];
 
  525      double timeScale = (double)rec[1];
 
  526      double degree = (double)rec[2];
 
 
  582      Table table(tableName, record);
 
  586      std::vector<ale::State> stateCache = 
m_state->getStates();
 
  587      for (
int i = 0; i < (int)stateCache.size(); i++) {
 
  588        record[inext++] = stateCache[i].position.x;          
 
  589        record[inext++] = stateCache[i].position.y;          
 
  590        record[inext++] = stateCache[i].position.z;          
 
  592          record[inext++] = stateCache[i].velocity.x;        
 
  593          record[inext++] = stateCache[i].velocity.y;        
 
  594          record[inext++] = stateCache[i].velocity.z;        
 
  618      record += spacecraftX;
 
  619      record += spacecraftY;
 
  620      record += spacecraftZ;
 
  622      Table table(tableName, record);
 
  624      for(
int cindex = 0; cindex < 
p_degree + 1; cindex++) {
 
  644                       "Cannot create Table, no Cache is loaded.",
 
 
  660    QString tabletype = 
"";
 
  663      tabletype = 
"Linear";
 
  666      tabletype = 
"HermiteSpline";
 
  669      tabletype = 
"PolyFunction";
 
 
  710      QString msg = 
"Only cached positions can be returned as a line cache of positions and time";
 
  714    return Cache(tableName);
 
 
  737      QString msg = 
"The SpicePosition has not yet been fit to a function";
 
  750      std::vector<ale::State> stateCache;
 
  751      for (std::vector<double>::size_type pos = 0; pos < 
p_cacheTime.size(); pos++) {
 
  764      std::vector<ale::State> stateCache;
 
  766      std::vector<double> timeCache;
 
  771      m_state = 
new ale::States(timeCache, stateCache);
 
 
  800    if(cacheTimeSize == 1) 
return Cache(tableName);
 
  804      return Cache(tableName);
 
  809      QString msg = 
"A SpicePosition polynomial function has not been created yet";
 
  841    double b1 = function1.Coefficient(1);
 
  842    double c1 = function1.Coefficient(2);
 
  843    double extremumXtime = -b1 / (2.*c1) + 
p_baseTime; 
 
  845    if(extremumXtime < firstTime) {
 
  846      extremumXtime = firstTime;
 
  848    if(extremumXtime > lastTime) {
 
  849      extremumXtime = lastTime;
 
  852    double b2 = function2.Coefficient(1);
 
  853    double c2 = function2.Coefficient(2);
 
  854    double extremumYtime = -b2 / (2.*c2) + 
p_baseTime;
 
  856    if(extremumYtime < firstTime) {
 
  857      extremumYtime = firstTime;
 
  859    if(extremumYtime > lastTime) {
 
  860      extremumYtime = lastTime;
 
  863    double b3 = function3.Coefficient(1);
 
  864    double c3 = function3.Coefficient(2);
 
  865    double extremumZtime = -b3 / (2.*c3) + 
p_baseTime;
 
  867    if(extremumZtime < firstTime) {
 
  868      extremumZtime = firstTime;
 
  870    if(extremumZtime > lastTime) {
 
  871      extremumZtime = lastTime;
 
  895    std::vector<ale::State> stateCache;
 
  896    for(
int i = 0; i < (int) 
p_cacheTime.size(); i++) {
 
  920    return Cache(tableName);
 
 
  931    std::vector<double> XC, YC, ZC;
 
  938    int size = 
m_state->getStates().size();
 
  942    else if (size == 2) {
 
  961    std::vector<double> time;
 
  984      for(
int cIndex = 0; cIndex < 3; cIndex++) {
 
  986        slope[cIndex] = posline.Slope();
 
  987        intercept[cIndex] = posline.Intercept();
 
  989      XC.push_back(intercept[0]);
 
  990      XC.push_back(slope[0]);
 
  991      YC.push_back(intercept[1]);
 
  992      YC.push_back(slope[1]);
 
  993      ZC.push_back(intercept[2]);
 
  994      ZC.push_back(slope[2]);
 
 1002      for(std::vector<double>::size_type pos = 0; pos < 
p_cacheTime.size(); pos++) {
 
 1008        fitX->AddKnown(time, coord[0]);
 
 1009        fitY->AddKnown(time, coord[1]);
 
 1010        fitZ->AddKnown(time, coord[2]);
 
 1027      for(
int i = 0;  i < function1.Coefficients(); i++) {
 
 1028        XC.push_back(function1.Coefficient(i));
 
 1029        YC.push_back(function2.Coefficient(i));
 
 1030        ZC.push_back(function3.Coefficient(i));
 
 
 1055                                    const std::vector<double>& YC,
 
 1056                                    const std::vector<double>& ZC,
 
 1064    function1.SetCoefficients(XC);
 
 1065    function2.SetCoefficients(YC);
 
 1066    function3.SetCoefficients(ZC);
 
 
 1104                                    std::vector<double>& YC,
 
 1105                                    std::vector<double>& ZC) {
 
 
 1168         SpicePosition::PartialType partialVar, 
int coeffIndex) {
 
 1171    std::vector<double> coordinate(3, 0);
 
 1174    int coordIndex = partialVar;
 
 
 1209                    SpicePosition::PartialType partialVar, 
int coeffIndex) {
 
 1212    std::vector<double> dvelocity(3, 0);
 
 1215    int coordIndex = partialVar;
 
 1218    double derivative = 0.;
 
 1221    double Epsilon = 1.0e-15;
 
 1222    if (fabs(time) <= Epsilon) time = 0.0;
 
 1226      derivative = coeffIndex * pow(time, coeffIndex-1) / 
p_timeScale;
 
 1229    dvelocity[coordIndex] = derivative;
 
 
 1245    double derivative = 1.;
 
 1248    if(coeffIndex > 0  && coeffIndex <= 
p_degree) {
 
 1249      derivative = pow(time, coeffIndex);
 
 1251    else if(coeffIndex == 0) {
 
 1255      QString msg = 
"Unable to evaluate the derivative of the SPICE position fit polynomial for " 
 1256                    "the given coefficient index [" + 
toString(coeffIndex) + 
"]. " 
 1257                    "Index is negative or exceeds degree of polynomial [" 
 
 1274      QString msg = 
"No velocity vector available";
 
 
 1297      state = 
m_state->getStates().front();
 
 
 1326      ale::State state = 
m_state->getState(
p_et, ale::SPLINE);
 
 
 1378        ale::Vec3d velocity = 
m_state->getVelocities()[0];
 
 
 1407    std::vector<double> hermiteVelocity = 
p_velocity;
 
 1410    for (
int index = 0; index < 3; index++) {
 
 
 1469                       "Source type is not Memcache, cannot convert.",
 
 1473    ale::States *tempStates = 
new ale::States(
m_state->minimizeCache(tolerance));
 
 
 1521      for(
int icoef = 
p_degree + 1;  icoef <= degree; icoef++) {
 
 1522        coefX.push_back(0.);
 
 1523        coefY.push_back(0.);
 
 1524        coefZ.push_back(0.);
 
 1531      std::vector<double> coefX(degree + 1),
 
 1535      for(
int icoef = 0;  icoef <= degree;  icoef++) {
 
 
 1579    double cacheSlope = 0.0;
 
 
 1613    double velocity = 0.;
 
 1615    for (
int icoef=1; icoef <= 
p_degree; icoef++) {
 
 
 1638     double diffTime = timeEt - 
p_et;
 
 1639     std::vector<double> extrapPos(3, 0.);
 
 
 1658        "Hermite coordinates only available for PolyFunctionOverHermiteConstant",
 
 1667    return hermiteCoordinate;
 
 
 1752                                         const QString &refFrame,
 
 1753                                         const QString &abcorr,
 
 1754                                         double state[6], 
bool &hasVelocity,
 
 1755                                         double &lightTime)
 const {
 
 1761    spkez_c((SpiceInt) target, (SpiceDouble) et, refFrame.toLatin1().data(),
 
 1762            abcorr.toLatin1().data(), (SpiceInt) observer, state, &lightTime);
 
 1767    SpiceBoolean spfailure = failed_c();
 
 1770      hasVelocity = 
false;
 
 1772      spkezp_c((SpiceInt) target, (SpiceDouble) et, refFrame.toLatin1().data(),
 
 1773               abcorr.toLatin1().data(), (SpiceInt) observer, state, &lightTime);
 
 
 1804                                     const bool &hasVelocity) {
 
 1810    if ( hasVelocity ) {
 
 1824    if (m_swapObserverTarget) {
 
 
@ Programmer
This error is for when a programmer made an API call that was illegal.
 
@ Io
A type of error that occurred when performing an actual I/O operation.
 
Generic least square fitting class.
 
Utility class for creating and using cartesean line equations.
 
static void CheckErrors(bool resetNaif=true)
This method looks for any naif errors that might have occurred.
 
Nth degree Polynomial with one variable.
 
A single keyword-value pair.
 
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 ...
 
PvlKeyword & findKeyword(const QString &kname, FindOptions opts)
Finds a keyword in the current PvlObject, or deeper inside other PvlObjects and Pvlgroups within this...
 
Obtain SPICE information for a spacecraft.
 
double DPolynomial(const int coeffIndex)
Evaluate the derivative of the fit polynomial (parabola) defined by the given coefficients with respe...
 
void Memcache2HermiteCache(double tolerance)
This method reduces the cache for position, time and velocity to the minimum number of values needed ...
 
void ComputeBaseTime()
Compute the base time using cached times.
 
Table LineCache(const QString &tableName)
Return a table with J2000 to reference positions.
 
double p_timeScale
Time scale used in fit equations.
 
std::vector< double > p_coordinate
J2000 position at time et.
 
double GetTimeBias() const
Returns the value of the time bias added to ET.
 
double ComputeVelocityInTime(PartialType var)
Compute the velocity with respect to time instead of scaled time.
 
Source p_source
Enumerated value for the location of the SPK information used.
 
std::vector< double > p_coefficients[3]
Coefficients of polynomials fit to 3 coordinates.
 
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...
 
virtual void SetEphemerisTimeSpice()
This is a protected method that is called by SetEphemerisTime() when Source type is Spice.
 
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 ...
 
void setLightTime(const double &lightTime)
Inheritors can set the light time if indicated.
 
const std::vector< double > & Velocity()
Return the current J2000 velocity.
 
void ReloadCache()
Cache J2000 positions over existing cached time range using polynomials.
 
Source
This enum indicates the status of the object.
 
@ HermiteCache
Object is reading from splined table.
 
@ PolyFunction
Object is calculated from nth degree polynomial.
 
@ Memcache
Object is reading from cached table.
 
@ Spice
Object is reading directly from the kernels.
 
@ PolyFunctionOverHermiteConstant
Object is reading from splined.
 
ale::States * m_state
!< Light time correction
 
void LoadCache(double startTime, double endTime, int size)
Cache J2000 position over a time range.
 
double p_baseTime
Base time used in fit equations.
 
void SetEphemerisTimeMemcache()
This is a protected method that is called by SetEphemerisTime() when Source type is Memcache.
 
void LoadTimeCache()
Load the time cache.
 
int p_observerCode
observer body code
 
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...
 
Table LoadHermiteCache(const QString &tableName)
Cache J2000 position over existing cached time range using polynomials stored as Hermite cubic spline...
 
std::vector< double > Extrapolate(double timeEt)
Extrapolate position for a given time assuming a constant velocity.
 
void setStateVector(const double state[6], const bool &hasVelocity)
Sets the state of target relative to observer.
 
double m_lt
!< Swap traditional order
 
std::vector< double > p_cacheTime
iTime for corresponding position
 
std::vector< double > p_velocity
J2000 velocity at time et.
 
double p_overrideTimeScale
Value set by caller to override computed time scale.
 
bool p_degreeApplied
Flag indicating whether or not a polynomial.
 
bool p_hasVelocity
Flag to indicate velocity is available.
 
void ClearCache()
Removes the entire cache from memory.
 
double p_fullCacheEndTime
Original end time of the complete cache after spiceinit.
 
int getTargetCode() const
Returns target code.
 
double p_overrideBaseTime
Value set by caller to override computed base time.
 
const std::vector< double > & GetCenterCoordinate()
Compute and return the coordinate at the center time.
 
void CacheLabel(Table &table)
Add labels to a SpicePosition table.
 
double scaledTime() const
Return the scaled time.
 
int p_targetCode
target body code
 
double getAdjustedEphemerisTime() const
Returns adjusted ephemeris time.
 
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 SetEphemerisTimeHermiteCache()
This is a protected method that is called by SetEphemerisTime() when Source type is HermiteCache.
 
virtual double EphemerisTime() const
Return the current ephemeris time.
 
void init(int targetCode, int observerCode, const bool &swapObserverTarget=false)
Internal initialization of the object support observer/target swap.
 
double p_et
Current ephemeris time.
 
void SetTimeBias(double timeBias)
Apply a time bias when invoking SetEphemerisTime method.
 
virtual ~SpicePosition()
Destructor.
 
double p_timeBias
iTime bias when reading kernels
 
void SetEphemerisTimePolyFunction()
This is a protected method that is called by SetEphemerisTime() when Source type is PolyFunction.
 
int getObserverCode() const
Returns observer code.
 
virtual const std::vector< double > & SetEphemerisTime(double et)
Return J2000 coordinate at given time.
 
SpicePosition(int targetCode, int observerCode)
Construct an empty SpicePosition class using valid body codes.
 
void SetEphemerisTimePolyFunctionOverHermiteConstant()
This is a protected method that is called by SetEphemerisTime() when Source type is PolyFunctionOverH...
 
double GetLightTime() const
Return the light time coorection value.
 
double p_fullCacheSize
Orignial size of the complete cache after spiceinit.
 
std::vector< double > HermiteCoordinate()
This method returns the Hermite coordinate for the current time for PolyFunctionOverHermiteConstant f...
 
OverrideType p_override
Time base and scale override options;.
 
int p_degree
Degree of polynomial function fit to the coordinates of the position.
 
double p_fullCacheStartTime
Original start time of the complete cache after spiceinit.
 
virtual const std::vector< double > & Coordinate()
Return the current J2000 position.
 
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.
 
QString p_aberrationCorrection
Light time correction to apply.
 
virtual void SetAberrationCorrection(const QString &correction)
Set the aberration correction (light time)
 
void SetPolynomialDegree(int degree)
Set the polynomial degree.
 
std::vector< double > VelocityPartial(SpicePosition::PartialType partialVar, int coeffIndex)
Compute the derivative of the velocity with respect to the specified variable.
 
Table Cache(const QString &tableName)
Return a table with J2000 positions.
 
virtual QString GetAberrationCorrection() const
Returns current state of stellar aberration correction.
 
Class for storing an Isis::Table's field information.
 
@ Double
The values in the field are 8 byte doubles.
 
Class for storing Table blobs information.
 
int Records() const
Returns the number of records.
 
PvlObject & Label()
The Table's label.
 
QString Name() const
The Table's name.
 
This is free and unencumbered software released into the public domain.
 
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
 
double toDouble(const QString &string)
Global function to convert from a string to a double.