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.