7#include "SpiceRotation.h"
22#include "BasisFunction.h"
23#include "IException.h"
25#include "LeastSquares.h"
26#include "LineEquation.h"
27#include "NaifStatus.h"
28#include "PolynomialUnivariate.h"
29#include "Quaternion.h"
31#include "TableField.h"
33using json = nlohmann::json;
37extern int refchg_(integer *frame1, integer *frame2, doublereal *et,
39extern int frmchg_(integer *frame1, integer *frame2, doublereal *et,
41extern int invstm_(doublereal *mat, doublereal *invmat);
45extern int ck3sdn(
double sdntol,
bool avflag,
int *nrec,
46 double *sclkdp,
double *quats,
double *avvs,
47 int nints,
double *starts,
double *dparr,
119 m_orientation = NULL;
122 QString key =
"INS" +
toString(frameCode) +
"_TRANSX";
123 SpiceDouble transX[2];
127 gdpool_c(key.toLatin1().data(), 1, 2, &number, transX, &found);
130 QString msg =
"Cannot find [" + key +
"] in text kernels";
131 throw IException(IException::Io, msg, _FILEINFO_);
135 if (transX[0] < transX[1])
p_axisV = 1;
170 for (
int i = 0; i < 3; i++)
187 if (rotToCopy.m_orientation) {
188 m_orientation =
new ale::Orientations;
189 *m_orientation = *rotToCopy.m_orientation;
192 m_orientation = NULL;
202 delete m_orientation;
203 m_orientation = NULL;
263 if (
p_et == et)
return;
317 return (m_orientation != NULL);
353 QString msg =
"Argument cacheSize must not be less or equal to zero";
354 throw IException(IException::Programmer, msg, _FILEINFO_);
357 if (startTime > endTime) {
358 QString msg =
"Argument startTime must be less than or equal to endTime";
359 throw IException(IException::Programmer, msg, _FILEINFO_);
362 if ((startTime != endTime) && (size == 1)) {
363 QString msg =
"Cache size must be more than 1 if startTime and endTime differ";
364 throw IException(IException::Programmer, msg, _FILEINFO_);
369 QString msg =
"A SpiceRotation cache has already been created";
370 throw IException(IException::Programmer, msg, _FILEINFO_);
378 if (m_orientation != NULL) {
379 delete m_orientation;
380 m_orientation = NULL;
395 std::vector<ale::Rotation> rotationCache;
396 std::vector< std::vector<double> > cache;
397 std::vector<ale::Vec3d> avCache;
398 for (
int i = 0; i < cacheSize; i++) {
401 rotationCache.push_back(ale::Rotation(
p_CJ));
402 cache.push_back(
p_CJ);
405 avCache.push_back(ale::Vec3d(
p_av));
409 if (
p_TC.size() > 1) {
410 m_orientation =
new ale::Orientations(rotationCache,
p_cacheTime, avCache,
414 m_orientation =
new ale::Orientations(rotationCache,
p_cacheTime, avCache,
456 throw IException(IException::Programmer,
"SpiceRotation::LoadCache(json) only supports Spice source", _FILEINFO_);
466 delete m_orientation;
467 m_orientation = NULL;
474 p_cacheTime = isdRot[
"ephemeris_times"].get<std::vector<double>>();
475 p_timeFrames = isdRot[
"time_dependent_frames"].get<std::vector<int>>();
477 std::vector<ale::Rotation> rotationCache;
478 for (
auto it = isdRot[
"quaternions"].begin(); it != isdRot[
"quaternions"].end(); it++) {
479 std::vector<double> quat = {it->at(0).get<
double>(), it->at(1).get<
double>(), it->at(2).get<
double>(), it->at(3).get<
double>()};
481 std::vector<double> CJ = q.
ToMatrix();
482 rotationCache.push_back(ale::Rotation(CJ));
485 std::vector<ale::Vec3d> avCache;
486 if (isdRot[
"angular_velocities"].size() != 0) {
487 for (
auto it = isdRot[
"angular_velocities"].begin(); it != isdRot[
"angular_velocities"].end(); it++) {
488 std::vector<double> av = {it->at(0).get<
double>(), it->at(1).get<
double>(), it->at(2).get<
double>()};
489 avCache.push_back(ale::Vec3d(av));
494 if (isdRot.contains(
"constant_frames")) {
496 p_TC = isdRot[
"constant_rotation"].get<std::vector<double>>();
497 m_orientation =
new ale::Orientations(rotationCache,
p_cacheTime, avCache,
502 ident_c((SpiceDouble( *)[3]) &
p_TC[0]);
503 m_orientation =
new ale::Orientations(rotationCache,
p_cacheTime, avCache,
546 delete m_orientation;
547 m_orientation = NULL;
551 if (table.Label().hasKeyword(
"TimeDependentFrames")) {
552 PvlKeyword labelTimeFrames = table.Label()[
"TimeDependentFrames"];
553 for (
int i = 0; i < labelTimeFrames.size(); i++) {
562 if (table.Label().hasKeyword(
"ConstantRotation")) {
563 PvlKeyword labelConstantFrames = table.Label()[
"ConstantFrames"];
566 for (
int i = 0; i < labelConstantFrames.size(); i++) {
569 PvlKeyword labelConstantRotation = table.Label()[
"ConstantRotation"];
571 for (
int i = 0; i < labelConstantRotation.size(); i++) {
572 p_TC.push_back(toDouble(labelConstantRotation[i]));
577 ident_c((SpiceDouble( *)[3]) &
p_TC[0]);
581 if (table.Label().hasKeyword(
"CkTableStartTime")) {
584 if (table.Label().hasKeyword(
"CkTableEndTime")) {
587 if (table.Label().hasKeyword(
"CkTableOriginalSize")) {
588 p_fullCacheSize = toInt(table.Label().findKeyword(
"CkTableOriginalSize")[0]);
592 if (table.Label().hasKeyword(
"FrameTypeCode")) {
603 int recFields = table[0].Fields();
610 std::vector<ale::Rotation> rotationCache;
611 std::vector<ale::Vec3d> avCache;
612 if (recFields == 5) {
613 for (
int r = 0; r < table.Records(); r++) {
614 TableRecord &rec = table[r];
616 if (rec.Fields() != recFields) {
620 std::vector<double> j2000Quat;
621 j2000Quat.push_back((
double)rec[0]);
622 j2000Quat.push_back((
double)rec[1]);
623 j2000Quat.push_back((
double)rec[2]);
624 j2000Quat.push_back((
double)rec[3]);
627 std::vector<double> CJ = q.
ToMatrix();
628 rotationCache.push_back(ale::Rotation(CJ));
632 if (
p_TC.size() > 1) {
633 m_orientation =
new ale::Orientations(rotationCache,
p_cacheTime, avCache,
637 m_orientation =
new ale::Orientations(rotationCache,
p_cacheTime, avCache,
644 else if (recFields == 8) {
645 for (
int r = 0; r < table.Records(); r++) {
646 TableRecord &rec = table[r];
648 if (rec.Fields() != recFields) {
652 std::vector<double> j2000Quat;
653 j2000Quat.push_back((
double)rec[0]);
654 j2000Quat.push_back((
double)rec[1]);
655 j2000Quat.push_back((
double)rec[2]);
656 j2000Quat.push_back((
double)rec[3]);
660 std::vector<double> CJ = q.
ToMatrix();
661 rotationCache.push_back(ale::Rotation(CJ));
663 std::vector<double> av;
664 av.push_back((
double)rec[4]);
665 av.push_back((
double)rec[5]);
666 av.push_back((
double)rec[6]);
667 avCache.push_back(ale::Vec3d(av));
672 if (
p_TC.size() > 1) {
673 m_orientation =
new ale::Orientations(rotationCache,
p_cacheTime, avCache,
677 m_orientation =
new ale::Orientations(rotationCache,
p_cacheTime, avCache,
684 else if (recFields == 3) {
685 std::vector<double> coeffAng1, coeffAng2, coeffAng3;
687 for (
int r = 0; r < table.Records() - 1; r++) {
688 TableRecord &rec = table[r];
690 if (rec.Fields() != recFields) {
693 coeffAng1.push_back((
double)rec[0]);
694 coeffAng2.push_back((
double)rec[1]);
695 coeffAng3.push_back((
double)rec[2]);
699 TableRecord &rec = table[table.Records()-1];
700 double baseTime = (double)rec[0];
701 double timeScale = (double)rec[1];
702 double degree = (double)rec[2];
708 if (degree == 0 && m_orientation->getAngularVelocities().size() > 0) {
713 QString msg =
"Expecting either three, five, or eight fields in the SpiceRotation table";
714 throw IException(IException::Programmer, msg, _FILEINFO_);
733 std::vector<ale::Rotation> rotationCache;
734 std::vector<ale::Vec3d> avCache;
745 for (std::vector<double>::size_type pos = 0; pos <
p_cacheTime.size(); pos++) {
747 rotationCache.push_back(ale::Rotation(
p_CJ));
748 avCache.push_back(ale::Vec3d(
p_av));
754 rotationCache.push_back(ale::Rotation(
p_CJ));
755 avCache.push_back(ale::Vec3d(
p_av));
769 for (std::vector<double>::size_type pos = 0; pos < maxSize; pos++) {
772 rotationCache.push_back(ale::Rotation(CJ));
779 QString msg =
"The SpiceRotation has not yet been fit to a function";
780 throw IException(IException::Programmer, msg, _FILEINFO_);
784 delete m_orientation;
785 m_orientation = NULL;
788 if (
p_TC.size() > 1) {
789 m_orientation =
new ale::Orientations(rotationCache,
p_cacheTime, avCache,
793 m_orientation =
new ale::Orientations(rotationCache,
p_cacheTime, avCache,
825 QString msg =
"Only cached rotations can be returned as a line cache of quaternions and time";
826 throw IException(IException::Programmer, msg, _FILEINFO_);
829 return Cache(tableName);
870 TableField q0(
"J2000Q0", TableField::Double);
871 TableField q1(
"J2000Q1", TableField::Double);
872 TableField q2(
"J2000Q2", TableField::Double);
873 TableField q3(
"J2000Q3", TableField::Double);
874 TableField t(
"ET", TableField::Double);
884 TableField av1(
"AV1", TableField::Double);
885 TableField av2(
"AV2", TableField::Double);
886 TableField av3(
"AV3", TableField::Double);
894 Table table(tableName, record);
896 std::vector<ale::Rotation> rots = m_orientation->getRotations();
897 std::vector<ale::Vec3d> angularVelocities = m_orientation->getAngularVelocities();
898 for (
int i = 0; i < (int)
p_cacheTime.size(); i++) {
899 std::vector<double> quat = rots[i].toQuaternion();
904 quat[0] = -1 * quat[0];
905 quat[1] = -1 * quat[1];
906 quat[2] = -1 * quat[2];
907 quat[3] = -1 * quat[3];
916 ale::Vec3d angularVelocity = angularVelocities[i];
917 record[4] = angularVelocity.x;
918 record[5] = angularVelocity.y;
919 record[6] = angularVelocity.z;
935 TableField angle1(
"J2000Ang1", TableField::Double);
936 TableField angle2(
"J2000Ang2", TableField::Double);
937 TableField angle3(
"J2000Ang3", TableField::Double);
944 Table table(tableName, record);
946 for (
int cindex = 0; cindex <
p_degree + 1; cindex++) {
965 QString msg =
"To create table source of data must be either Memcache or PolyFunction";
966 throw IException(IException::Programmer, msg, _FILEINFO_);
980 SpiceInt centerBodyCode = (SpiceInt) centerBody;
996 QString naifKeyword =
"BODY" +
toString(centerBodyCode) +
"_CONSTANTS_REF_FRAME" ;
997 SpiceInt numExpected;
998 SpiceInt numReturned;
1000 SpiceDouble relativeFrameCode = 0;
1002 dtpool_c(naifKeyword.toLatin1().data(), &found, &numExpected, &naifType);
1006 SpiceDouble relativeFrameCode;
1007 bodvcd_c(centerBodyCode,
"CONSTANTS_REF_FRAME", 1,
1008 &numReturned, &relativeFrameCode);
1011 if (!found || relativeFrameCode == 1) {
1015 naifKeyword =
"BODY" +
toString(centerBodyCode) +
"_POLE_RA" ;
1016 dtpool_c(naifKeyword.toLatin1().data(), &found, &numExpected, &naifType);
1019 std::vector<SpiceDouble> d(3);
1022 m_pm.resize(numExpected);
1024 bodvcd_c(centerBodyCode,
"POLE_RA", numExpected, &numReturned, &d[0]);
1029 bodvcd_c(centerBodyCode,
"POLE_DEC", numExpected, &numReturned, &d[0]);
1034 bodvcd_c(centerBodyCode,
"PM", numExpected, &numReturned, &d[0]);
1035 m_pm[0].setDegrees(d[0]);
1036 m_pm[1].setDegrees(d[1]);
1037 m_pm[2].setDegrees(d[2]);
1044 naifKeyword =
"BODY" +
toString(centerBodyCode) +
"_NUT_PREC_RA" ;
1045 dtpool_c(naifKeyword.toLatin1().data(), &found, &numReturned, &naifType);
1049 SpiceInt bcCode = centerBodyCode/100;
1050 naifKeyword =
"BODY" +
toString(bcCode) +
"_NUT_PREC_ANGLES" ;
1051 dtpool_c(naifKeyword.toLatin1().data(), &found, &numExpected, &naifType);
1052 std::vector<double>npAngles(numExpected, 0.);
1053 bodvcd_c(bcCode,
"NUT_PREC_ANGLES", numExpected, &numReturned, &npAngles[0]);
1059 std::vector<SpiceDouble> angles(numExpected);
1060 bodvcd_c(centerBodyCode,
"NUT_PREC_RA", numExpected, &numReturned, &
m_raNutPrec[0]);
1061 bodvcd_c(centerBodyCode,
"NUT_PREC_DEC", numExpected, &numReturned, &
m_decNutPrec[0]);
1062 bodvcd_c(centerBodyCode,
"NUT_PREC_PM", numExpected, &numReturned, &
m_pmNutPrec[0]);
1067 for (
int i = 0; i < numExpected; i++) {
1104 if (label.hasKeyword(
"PoleRa")) {
1105 PvlKeyword labelCoeffs = label[
"PoleRa"];
1106 for (
int i = 0; i < labelCoeffs.size(); i++){
1111 if (label.hasKeyword(
"PoleDec")) {
1112 PvlKeyword labelCoeffs = label[
"PoleDec"];
1113 for (
int i = 0; i < labelCoeffs.size(); i++){
1118 if (label.hasKeyword(
"PrimeMeridian")) {
1119 PvlKeyword labelCoeffs = label[
"PrimeMeridian"];
1120 for (
int i = 0; i < labelCoeffs.size(); i++){
1127 if (label.hasKeyword(
"PoleRaNutPrec")) {
1128 PvlKeyword labelCoeffs = label[
"PoleRaNutPrec"];
1129 for (
int i = 0; i < labelCoeffs.size(); i++){
1133 if (label.hasKeyword(
"PoleDecNutPrec")) {
1134 PvlKeyword labelCoeffs = label[
"PoleDecNutPrec"];
1135 for (
int i = 0; i < labelCoeffs.size(); i++){
1139 if (label.hasKeyword(
"PmNutPrec")) {
1140 PvlKeyword labelCoeffs = label[
"PmNutPrec"];
1141 for (
int i = 0; i < labelCoeffs.size(); i++){
1145 if (label.hasKeyword(
"SysNutPrec0")) {
1146 PvlKeyword labelCoeffs = label[
"SysNutPrec0"];
1147 for (
int i = 0; i < labelCoeffs.size(); i++){
1151 if (label.hasKeyword(
"SysNutPrec1")) {
1152 PvlKeyword labelCoeffs = label[
"SysNutPrec1"];
1153 for (
int i = 0; i < labelCoeffs.size(); i++){
1174 table.Label() += PvlKeyword(
"TimeDependentFrames");
1182 table.Label() += PvlKeyword(
"ConstantFrames");
1188 table.Label() += PvlKeyword(
"ConstantRotation");
1190 for (
int i = 0; i < (int)
p_TC.size(); i++) {
1191 table.Label()[
"ConstantRotation"].addValue(
toString(
p_TC[i]));
1197 table.Label() += PvlKeyword(
"CkTableStartTime");
1201 table.Label() += PvlKeyword(
"CkTableEndTime");
1205 table.Label() += PvlKeyword(
"CkTableOriginalSize");
1210 table.Label() += PvlKeyword(
"FrameTypeCode");
1216 table.Label() += PvlKeyword(
"PoleRa");
1218 for (
int i = 0; i < (int)
m_raPole.size(); i++) {
1223 table.Label() += PvlKeyword(
"PoleDec");
1224 for (
int i = 0; i < (int)
m_decPole.size(); i++) {
1229 table.Label() += PvlKeyword(
"PrimeMeridian");
1230 for (
int i = 0; i < (int)
m_pm.size(); i++) {
1231 table.Label()[
"PrimeMeridian"].addValue(
toString(
m_pm[i].degrees()));
1236 table.Label() += PvlKeyword(
"PoleRaNutPrec");
1237 for (
int i = 0; i < (int)
m_raNutPrec.size(); i++) {
1242 table.Label() += PvlKeyword(
"PoleDecNutPrec");
1248 table.Label() += PvlKeyword(
"PmNutPrec");
1249 for (
int i = 0; i < (int)
m_pmNutPrec.size(); i++) {
1254 table.Label() += PvlKeyword(
"SysNutPrec0");
1260 table.Label() += PvlKeyword(
"SysNutPrec1");
1299 SpiceDouble ang1, ang2, ang3;
1300 m2eul_c((SpiceDouble *) &
p_CJ[0], axis3, axis2, axis1, &ang3, &ang2, &ang1);
1302 std::vector<double> angles;
1303 angles.push_back(ang1);
1304 angles.push_back(ang2);
1305 angles.push_back(ang3);
1324 eul2m_c(angles[2], angles[1], angles[0], axis3, axis2, axis1, (SpiceDouble (*)[3]) &(
p_CJ[0]));
1326 if (m_orientation) {
1327 delete m_orientation;
1328 m_orientation = NULL;
1330 std::vector<ale::Rotation> rotationCache;
1331 rotationCache.push_back(ale::Rotation(
p_CJ));
1332 if (
p_TC.size() > 1) {
1333 m_orientation =
new ale::Orientations(rotationCache,
p_cacheTime, std::vector<ale::Vec3d>(),
1337 m_orientation =
new ale::Orientations(rotationCache,
p_cacheTime, std::vector<ale::Vec3d>(),
1398 std::vector<double> jVec;
1399 if (rVec.size() == 3) {
1401 mxm_c((SpiceDouble *) &
p_TC[0], (SpiceDouble *) &
p_CJ[0], TJ);
1403 mtxv_c(TJ, (SpiceDouble *) &rVec[0], (SpiceDouble *) &jVec[0]);
1406 else if (rVec.size() == 6) {
1412 std::vector<double> stateTJ(36);
1416 xpose6_c(&stateTJ[0], (SpiceDouble( *) [6]) &stateTJ[0]);
1417 double stateJT[6][6];
1418 invstm_((doublereal *) &stateTJ[0], (doublereal *) stateJT);
1419 xpose6_c(stateJT, stateJT);
1422 mxvg_c(stateJT, (SpiceDouble *) &rVec[0], 6, 6, (SpiceDouble *) &jVec[0]);
1599 std::vector<double> jVec;
1603 int angleIndex = partialVar;
1606 double angle = angles.at(angleIndex);
1609 double dmatrix[3][3];
1610 drotat_(&angle, (integer *) axes + angleIndex, (doublereal *) dmatrix);
1612 xpose_c(dmatrix, dmatrix);
1626 msg =
"Body rotation uses a binary PCK. Solutions for this model are not supported";
1627 throw IException(IException::User, msg, _FILEINFO_);
1630 msg =
"Body rotation uses a PCK not referenced to J2000. "
1631 "Solutions for this model are not supported";
1632 throw IException(IException::User, msg, _FILEINFO_);
1635 msg =
"Solutions are not supported for this frame type.";
1636 throw IException(IException::User, msg, _FILEINFO_);
1640 for (
int row = 0; row < 3; row++) {
1641 for (
int col = 0; col < 3; col++) {
1642 dmatrix[row][col] *= dpoly;
1648 switch (angleIndex) {
1650 rotmat_c(dmatrix, angles[1], axes[1], dCJ);
1651 rotmat_c(dCJ, angles[2], axes[2], dCJ);
1654 rotate_c(angles[0], axes[0], dCJ);
1655 mxm_c(dmatrix, dCJ, dCJ);
1656 rotmat_c(dCJ, angles[2], axes[2], dCJ);
1659 rotate_c(angles[0], axes[0], dCJ);
1660 rotmat_c(dCJ, angles[1], axes[1], dCJ);
1661 mxm_c(dmatrix, dCJ, dCJ);
1667 mxm_c((SpiceDouble *) &
p_TC[0], dCJ[0], dTJ);
1671 std::vector<double> lookdJ(3);
1673 mtxv_c(dTJ, (
const SpiceDouble *) &lookT[0], (SpiceDouble *) &lookdJ[0]);
1690 std::vector<double> rVec(3);
1692 if (jVec.size() == 3) {
1694 mxm_c((SpiceDouble *) &
p_TC[0], (SpiceDouble *) &
p_CJ[0], TJ);
1696 mxv_c(TJ, (SpiceDouble *) &jVec[0], (SpiceDouble *) &rVec[0]);
1698 else if (jVec.size() == 6) {
1704 std::vector<double> stateTJ(36);
1707 mxvg_c((SpiceDouble *) &stateTJ[0], (SpiceDouble *) &jVec[0], 6, 6, (SpiceDouble *) &rVec[0]);
1728 std::vector<double> coeffAng1, coeffAng2, coeffAng3;
1739 int size = m_orientation->getRotations().size();
1743 else if (size == 2) {
1749 coeffAng1.assign(
p_degree + 1, 0.);
1750 coeffAng2.assign(
p_degree + 1, 0.);
1751 coeffAng3.assign(
p_degree + 1, 0.);
1766 std::vector<double> time;
1772 coeffAng1.push_back(angles[0]);
1773 coeffAng2.push_back(angles[1]);
1774 coeffAng3.push_back(angles[2]);
1776 else if (size == 2) {
1789 angles2[0] =
WrapAngle(angles1[0], angles2[0]);
1790 angles2[2] =
WrapAngle(angles1[2], angles2[2]);
1792 double intercept[3];
1795 for (
int angleIndex = 0; angleIndex < 3; angleIndex++) {
1797 slope[angleIndex] = angline.
Slope();
1798 intercept[angleIndex] = angline.
Intercept();
1800 coeffAng1.push_back(intercept[0]);
1801 coeffAng1.push_back(slope[0]);
1802 coeffAng2.push_back(intercept[1]);
1803 coeffAng2.push_back(slope[1]);
1804 coeffAng3.push_back(intercept[2]);
1805 coeffAng3.push_back(slope[2]);
1812 for (std::vector<double>::size_type pos = 0; pos <
p_cacheTime.size(); pos++) {
1824 angles[0] =
WrapAngle(start1, angles[0]);
1825 angles[2] =
WrapAngle(start3, angles[2]);
1828 fitAng1->
AddKnown(time, angles[0]);
1829 fitAng2->
AddKnown(time, angles[1]);
1830 fitAng3->
AddKnown(time, angles[2]);
1879 const std::vector<double> &coeffAng2,
1880 const std::vector<double> &coeffAng3,
1884 QString msg =
"The quaternion SPICE tables are no longer available. "
1885 "Either re-run spiceinit or set OVEREXISTING to False.";
1886 throw IException(IException::User, msg, _FILEINFO_);
1950 QString msg =
"Target body orientation information not available. Rerun spiceinit.";
1951 throw IException(IException::User, msg, _FILEINFO_);
2021 const std::vector<Angle> &decCoeff,
2022 const std::vector<Angle> &pmCoeff) {
2044 std::vector<double> &coeffAng2,
2045 std::vector<double> &coeffAng3) {
2066 std::vector<Angle> &decCoeff,
2067 std::vector<Angle> &pmCoeff) {
2109 void SpiceRotation::SetCacheTime(std::vector<double> cacheTime) {
2133 if (coeffIndex > 0 && coeffIndex <=
p_degree) {
2134 derivative = pow(time, coeffIndex);
2136 else if (coeffIndex == 0) {
2140 QString msg =
"Unable to evaluate the derivative of the SPICE rotation fit polynomial for "
2141 "the given coefficient index [" +
toString(coeffIndex) +
"]. "
2142 "Index is negative or exceeds degree of polynomial ["
2144 throw IException(IException::Programmer, msg, _FILEINFO_);
2165 const int coeffIndex) {
2166 const double p_dayScale = 86400;
2168 const double p_centScale = p_dayScale * 36525;
2171 switch (partialVar) {
2174 time =
p_et / p_centScale;
2177 time =
p_et / p_dayScale;
2183 switch (coeffIndex) {
2189 derivative = pow(time, coeffIndex);
2192 QString msg =
"Unable to evaluate the derivative of the target body rotation fit polynomial "
2193 "for the given coefficient index [" +
toString(coeffIndex) +
"]. "
2194 "Index is negative or exceeds degree of polynomial ["
2196 throw IException(IException::Programmer, msg, _FILEINFO_);
2202 derivative = -derivative;
2232 int angleIndex = partialVar;
2235 double angle = angles.at(angleIndex);
2237 double dmatrix[3][3];
2238 drotat_(&angle, (integer *) axes + angleIndex, (doublereal *) dmatrix);
2240 xpose_c(dmatrix, dmatrix);
2254 QString msg =
"Only CK, DYN, and PCK partials can be calculated";
2255 throw IException(IException::Programmer, msg, _FILEINFO_);
2259 for (
int row = 0; row < 3; row++) {
2260 for (
int col = 0; col < 3; col++) {
2261 dmatrix[row][col] *= dpoly;
2267 switch (angleIndex) {
2269 rotmat_c(dmatrix, angles[1], axes[1], dCJ);
2270 rotmat_c(dCJ, angles[2], axes[2], dCJ);
2273 rotate_c(angles[0], axes[0], dCJ);
2274 mxm_c(dmatrix, dCJ, dCJ);
2275 rotmat_c(dCJ, angles[2], axes[2], dCJ);
2278 rotate_c(angles[0], axes[0], dCJ);
2279 rotmat_c(dCJ, angles[1], axes[1], dCJ);
2280 mxm_c(dmatrix, dCJ, dCJ);
2286 mxm_c((SpiceDouble *) &
p_TC[0], dCJ[0], dTJ);
2290 std::vector<double> lookdT(3);
2292 mxv_c(dTJ, (
const SpiceDouble *) &lookJ[0], (SpiceDouble *) &lookdT[0]);
2309 double diff1 = compareAngle - angle;
2311 if (diff1 < -1 * pi_c()) {
2314 else if (diff1 > pi_c()) {
2354 for (
int icoef =
p_degree + 1; icoef <= degree; icoef++) {
2355 coefAngle1.push_back(0.);
2356 coefAngle2.push_back(0.);
2357 coefAngle3.push_back(0.);
2364 std::vector<double> coefAngle1(degree + 1),
2365 coefAngle2(degree + 1),
2366 coefAngle3(degree + 1);
2368 for (
int icoef = 0; icoef <= degree; icoef++) {
2443 if (axis1 < 1 || axis2 < 1 || axis3 < 1 || axis1 > 3 || axis2 > 3 || axis3 > 3) {
2444 QString msg =
"A rotation axis is outside the valid range of 1 to 3";
2445 throw IException(IException::Programmer, msg, _FILEINFO_);
2471 double currentTime = observStart;
2472 bool timeLoaded =
false;
2477 ktotal_c(
"ck", (SpiceInt *) &count);
2486 "Full cache size does NOT match cache size in LoadTimeCache -- should never happen";
2487 throw IException(IException::Programmer, msg, _FILEINFO_);
2494 std::vector<ale::Rotation> fullRotationCache = m_orientation->getRotations();
2495 std::vector<ale::Vec3d> angularVelocities = m_orientation->getAngularVelocities();
2498 std::vector<double> rotationMatrix = fullRotationCache[r].toRotationMatrix();
2499 SpiceDouble CJ[9] = { rotationMatrix[0], rotationMatrix[1], rotationMatrix[2],
2500 rotationMatrix[3], rotationMatrix[4], rotationMatrix[5],
2501 rotationMatrix[6], rotationMatrix[7], rotationMatrix[8]
2503 m2q_c(CJ, &quats[r * 4]);
2505 ale::Vec3d angularVelocity = angularVelocities[r];
2506 vequ_c((SpiceDouble *) &angularVelocity.x, &avvs[r*3]);
2510 double cubeStarts = timeSclkdp[0];
2511 double radTol = 0.000000017453;
2512 SpiceInt avflag = 1;
2518 ck3sdn(radTol, avflag, (
int *) &sizOut, &timeSclkdp[0], (doublereal *) &quats[0],
2519 (SpiceDouble *) &avvs[0], nints, &cubeStarts, dparr, (
int *) intarr);
2523 std::vector<double> av;
2526 if (m_orientation) {
2527 delete m_orientation;
2528 m_orientation = NULL;
2531 std::vector<ale::Rotation> rotationCache;
2532 std::vector<ale::Vec3d> avCache;
2534 for (
int r = 0; r < sizOut; r++) {
2539 std::vector<double> CJ(9);
2540 q2m_c(&quats[r*4], (SpiceDouble(*)[3]) &CJ[0]);
2541 rotationCache.push_back(CJ);
2542 vequ_c(&avvs[r*3], (SpiceDouble *) &av[0]);
2543 avCache.push_back(av);
2546 if (
p_TC.size() > 1 ) {
2547 m_orientation =
new ale::Orientations(rotationCache,
p_cacheTime, avCache,
2551 m_orientation =
new ale::Orientations(rotationCache,
p_cacheTime, std::vector<ale::Vec3d>(),
2564 int SOURCESIZ = 128;
2567 SpiceChar file[FILESIZ];
2568 SpiceChar filtyp[TYPESIZ];
2569 SpiceChar source[SOURCESIZ];
2572 bool observationSpansToNextSegment =
false;
2577 kdata_c(0,
"ck", FILESIZ, TYPESIZ, SOURCESIZ, file, filtyp, source, &handle, &found);
2583 observationSpansToNextSegment =
false;
2594 dafus_c(sum, (SpiceInt) 2, (SpiceInt) 6, dc, ic);
2597 if (ic[2] == 5)
break;
2600 if (ic[0] == spCode && ic[2] == 3) {
2601 sct2e_c((
int) spCode / 1000, dc[0], &segStartEt);
2602 sct2e_c((
int) spCode / 1000, dc[1], &segStopEt);
2607 if (currentTime >= segStartEt && currentTime <= segStopEt) {
2611 if (observationSpansToNextSegment && currentTime > segStartEt) {
2612 QString msg =
"Observation crosses segment boundary--unable to interpolate pointing";
2613 throw IException(IException::Programmer, msg, _FILEINFO_);
2615 if (observEnd > segStopEt) {
2616 observationSpansToNextSegment =
true;
2620 int dovelocity = ic[3];
2623 dafgda_c(handle, end - 1, end, val);
2625 int ninstances = (int) val[1];
2626 int numvel = dovelocity * 3;
2627 int quatnoff = ic[4] + (4 + numvel) * ninstances - 1;
2629 int sclkdp1off = quatnoff + 1;
2630 int sclkdpnoff = sclkdp1off + ninstances - 1;
2633 int sclkSpCode = spCode / 1000;
2636 std::vector<double> sclkdp(ninstances);
2637 dafgda_c(handle, sclkdp1off, sclkdpnoff, (SpiceDouble *) &sclkdp[0]);
2640 sct2e_c(sclkSpCode, sclkdp[0], &et);
2642 while (instance < (ninstances - 1) && et < currentTime) {
2644 sct2e_c(sclkSpCode, sclkdp[instance], &et);
2647 if (instance > 0) instance--;
2648 sct2e_c(sclkSpCode, sclkdp[instance], &et);
2650 while (instance < (ninstances - 1) && et < observEnd) {
2653 sct2e_c(sclkSpCode, sclkdp[instance], &et);
2657 if (!observationSpansToNextSegment) {
2663 currentTime = segStopEt;
2672 QString msg =
"No camera kernels loaded...Unable to determine time cache to downsize";
2673 throw IException(IException::User, msg, _FILEINFO_);
2679 double cacheSlope = 0.0;
2703 QString msg =
"Time cache not available -- rerun spiceinit";
2704 throw IException(IException::User, msg, _FILEINFO_);
2707 std::vector<double> fullCacheTime;
2708 double cacheSlope = 0.0;
2716 return fullCacheTime;
2742 std::vector<int> frameCodes;
2743 std::vector<int> frameTypes;
2746 while (frameCodes[frameCodes.size()-1] != J2000Code) {
2747 frmidx = frameCodes.size() - 1;
2755 frinfo_c((SpiceInt) frameCodes[frmidx],
2756 (SpiceInt *) ¢er,
2758 (SpiceInt *) &typid, &found);
2763 frameTypes.push_back(0);
2767 QString msg =
"The frame" +
toString((
int) frameCodes[frmidx]) +
" is not supported by Naif";
2768 throw IException(IException::Programmer, msg, _FILEINFO_);
2771 double matrix[3][3];
2775 nextFrame = J2000Code;
2777 else if (type == CK) {
2778 ckfrot_((SpiceInt *) &typid, &et, (
double *) matrix, &nextFrame, (logical *) &found);
2783 frameTypes.push_back(0);
2787 QString msg =
"The ck rotation from frame " +
toString(frameCodes[frmidx]) +
" can not "
2788 +
"be found due to no pointing available at requested time or a problem with the "
2790 throw IException(IException::Programmer, msg, _FILEINFO_);
2793 else if (type == TK) {
2794 tkfram_((SpiceInt *) &typid, (
double *) matrix, &nextFrame, (logical *) &found);
2796 QString msg =
"The tk rotation from frame " +
toString(frameCodes[frmidx]) +
2797 " can not be found";
2798 throw IException(IException::Programmer, msg, _FILEINFO_);
2801 else if (type == DYN) {
2808 zzdynrot_((SpiceInt *) &typid, (SpiceInt *) ¢er, &et, (
double *) matrix, &nextFrame);
2812 QString msg =
"The frame " +
toString(frameCodes[frmidx]) +
2813 " has a type " +
toString(type) +
" not supported by your version of Naif Spicelib."
2814 +
"You need to update.";
2815 throw IException(IException::Programmer, msg, _FILEINFO_);
2818 frameCodes.push_back(nextFrame);
2819 frameTypes.push_back(type);
2830 while (frameTypes[nConstants] == TK && nConstants < (
int) frameTypes.size()) nConstants++;
2833 for (
int i = 0; i <= nConstants; i++) {
2838 for (
int i = nConstants; i < (int) frameCodes.size(); i++) {
2858 std::vector<double> TJ;
2860 mxm_c((SpiceDouble *) &
p_TC[0], (SpiceDouble *) &
p_CJ[0], (SpiceDouble( *) [3]) &TJ[0]);
2873 std::vector<double> q;
2875 m2q_c((SpiceDouble( *)[3]) &
p_TC[0], &q[0]);
2897 p_TC = constantMatrix;
2908 std::vector<double> q;
2910 m2q_c((SpiceDouble( *)[3]) &
p_CJ[0], &q[0]);
2932 p_CJ = timeBasedMatrix;
2948 refchg_((SpiceInt *) &fromFrame, (SpiceInt *) &targetFrame, &et, (doublereal *) &
p_TC[0]);
2950 xpose_c((SpiceDouble( *)[3]) &
p_TC[0], (SpiceDouble( *)[3]) &
p_TC[0]);
2978 QString msg =
"The SpiceRotation pointing angles must be fit to polynomials in order to ";
2979 msg +=
"compute angular velocity.";
2980 throw IException(IException::Programmer, msg, _FILEINFO_);
2983 QString msg =
"Planetary angular velocity must be fit computed with PCK polynomials ";
2984 throw IException(IException::Programmer, msg, _FILEINFO_);
2986 std::vector<double> dCJdt;
3004 mtxm_c((SpiceDouble( *)[3]) &dCJdt[0], (SpiceDouble( *)[3]) &
p_CJ[0], omega);
3005 p_av[0] = omega[2][1];
3006 p_av[1] = omega[0][2];
3007 p_av[2] = omega[1][0];
3025 double dmatrix[3][3];
3027 double wmatrix[3][3];
3030 for (
int angleIndex = 0; angleIndex < 3; angleIndex++) {
3031 drotat_(&(angles[angleIndex]), (integer *) axes + angleIndex, (doublereal *) dmatrix);
3033 xpose_c(dmatrix, dmatrix);
3045 for (
int row = 0; row < 3; row++) {
3046 for (
int col = 0; col < 3; col++) {
3047 dmatrix[row][col] *= dangle;
3051 switch (angleIndex) {
3053 rotmat_c(dmatrix, angles[1], axes[1], dmatrix);
3054 rotmat_c(dmatrix, angles[2], axes[2], dmatrix);
3057 rotate_c(angles[0], axes[0], wmatrix);
3058 mxm_c(dmatrix, wmatrix, dmatrix);
3059 rotmat_c(dmatrix, angles[2], axes[2], dmatrix);
3062 rotate_c(angles[0], axes[0], wmatrix);
3063 rotmat_c(wmatrix, angles[1], axes[1], wmatrix);
3064 mxm_c(dmatrix, wmatrix, dmatrix);
3068 for (
int index = 0; index < 9; index++) {
3071 dCJ[index] += dmatrix[i][j];
3085 std::vector<double> stateTJ(36);
3088 double stateCJ[6][6];
3089 rav2xf_c(&
p_CJ[0], &
p_av[0], stateCJ);
3095 for (
int row = 3; row < 6; row++) {
3099 for (
int col = 0; col < 3; col++) {
3102 stateTJ[irow*6 + col] =
p_TC[vpos] * stateCJ[0][col] +
p_TC[vpos+1] * stateCJ[1][col]
3103 +
p_TC[vpos+2] * stateCJ[2][col];
3105 stateTJ[row*6 + col] =
p_TC[vpos] * stateCJ[3][col] +
p_TC[vpos+1] * stateCJ[4][col]
3106 +
p_TC[vpos+2] * stateCJ[5][col];
3108 stateTJ[irow*6 + jcol] = 0;
3110 stateTJ[row*6 +jcol] = stateTJ[irow*6 + col];
3134 double diffTime = timeEt -
p_et;
3135 std::vector<double> CJ(9, 0.0);
3140 axisar_c((SpiceDouble *) &
p_av[0], diffTime*vnorm_c((SpiceDouble *) &
p_av[0]), dmat);
3143 mxm_c(dmat, (SpiceDouble *) &
p_CJ[0], (SpiceDouble( *)[3]) &CJ[0]);
3174 ktotal_c(
"PCK", &count);
3179 int SOURCESIZ = 128;
3180 SpiceChar file[FILESIZ];
3181 SpiceChar filetype[TYPESIZ];
3182 SpiceChar source[SOURCESIZ];
3189 for (SpiceInt knum = 0; knum < count; knum++){
3190 kdata_c(knum,
"PCK", FILESIZ, TYPESIZ, SOURCESIZ, file, filetype, source, &handle, &found);
3193 if (strstr(file,
"bpc") != NULL) {
3210 SpiceInt centerBodyCode;
3211 SpiceInt frameClass;
3213 frinfo_c(frameCode, ¢erBodyCode, &frameClass, &classId, &found);
3216 if (frameClass == 2 || (centerBodyCode > 0 && frameClass != 3)) {
3222 for (std::vector<int>::size_type idx = 1; idx <
p_constantFrames.size(); idx++) {
3224 frinfo_c(frameCode, ¢erBodyCode, &frameClass, &classId, &found);
3229 switch (frameClass) {
3263 p_CJ = m_orientation->getRotations()[0].toRotationMatrix();
3265 ale::Vec3d av = m_orientation->getAngularVelocities()[0];
3273 p_CJ = m_orientation->interpolateTimeDep(
p_et).toRotationMatrix();
3276 ale::Vec3d av = m_orientation->interpolateAV(
p_et);
3301 SpiceDouble stateJ[6];
3304 spkez_c((SpiceInt) spkCode,
p_et,
"J2000",
"LT+S",
3308 SpiceDouble sJ[3], svJ[3];
3309 vpack_c(-1 * stateJ[0], -1 * stateJ[1], -1 * stateJ[2], sJ);
3310 vpack_c(stateJ[3], stateJ[4], stateJ[5], svJ);
3315 (SpiceDouble( *)[3]) &
p_CJ[0]);
3332 SpiceInt j2000 = J2000Code;
3340 double stateCJ[6][6];
3341 frmchg_((integer *) &j2000, (integer *) &toFrame, &time, (doublereal *) stateCJ);
3346 SpiceBoolean ckfailure = failed_c();
3350 xpose6_c(stateCJ, stateCJ);
3351 xf2rav_c(stateCJ, (SpiceDouble( *)[3]) &
p_CJ[0], (SpiceDouble *) &
p_av[0]);
3355 refchg_((integer *) &j2000, (integer *) &toFrame, &time, (SpiceDouble *) &
p_CJ[0]);
3359 getmsg_c(
"SHORT",
sizeof(naifstr), naifstr);
3362 if (eqstr_c(naifstr,
"SPICE(UNKNOWNFRAME)")) {
3363 Isis::IString msg = Isis::IString((
int)
p_constantFrames[0]) +
" is an unrecognized " +
3364 "reference frame code. Has the mission frames kernel been loaded?";
3365 throw IException(IException::Io, msg, _FILEINFO_);
3368 Isis::IString msg =
"No pointing available at requested time [" +
3371 throw IException(IException::Io, msg, _FILEINFO_);
3376 xpose_c((SpiceDouble( *)[3]) &
p_CJ[0], (SpiceDouble( *)[3]) &
p_CJ[0]);
3399 std::vector<double> rtime;
3401 std::vector<double> angles;
3402 angles.push_back(function1.
Evaluate(rtime));
3403 angles.push_back(function2.
Evaluate(rtime));
3404 angles.push_back(function3.
Evaluate(rtime));
3407 if (angles[0] <= -1 * pi_c()) {
3408 angles[0] += twopi_c();
3410 else if (angles[0] > pi_c()) {
3411 angles[0] -= twopi_c();
3434 std::vector<double> rtime;
3436 double angle1 = function1.
Evaluate(rtime);
3437 double angle2 = function2.
Evaluate(rtime);
3438 double angle3 = function3.
Evaluate(rtime);
3441 if (angle1 < -1 * pi_c()) {
3442 angle1 += twopi_c();
3444 else if (angle1 > pi_c()) {
3445 angle1 -= twopi_c();
3448 eul2m_c((SpiceDouble) angle3, (SpiceDouble) angle2, (SpiceDouble) angle1,
3450 (SpiceDouble( *)[3]) &
p_CJ[0]);
3454 ale::Vec3d av = m_orientation->getAngularVelocities()[0];
3476 std::vector<double> cacheAngles(3);
3477 std::vector<double> cacheVelocity(3);
3479 cacheVelocity =
p_av;
3481 std::vector<double> polyAngles(3);
3485 std::vector<double> polyVelocity(3);
3486 polyVelocity =
p_av;
3487 std::vector<double> angles(3);
3489 for (
int index = 0; index < 3; index++) {
3490 angles[index] = cacheAngles[index] + polyAngles[index];
3491 p_av[index] += cacheVelocity[index];
3494 if (angles[0] <= -1 * pi_c()) {
3495 angles[0] += twopi_c();
3497 else if (angles[0] > pi_c()) {
3498 angles[0] -= twopi_c();
3501 if (angles[2] <= -1 * pi_c()) {
3502 angles[2] += twopi_c();
3504 else if (angles[2] > pi_c()) {
3505 angles[2] -= twopi_c();
3508 eul2m_c((SpiceDouble) angles[2], (SpiceDouble) angles[1], (SpiceDouble) angles[0],
3510 (SpiceDouble( *)[3]) &
p_CJ[0]);
3521 double dTime =
p_et / 86400.;
3522 double centTime = dTime / 36525;
3523 double secondsPerJulianCentury = 86400. * 36525.;
3541 for (
int ia = 0; ia < numNutPrec; ia++) {
3544 costheta = cos(theta.
radians());
3545 sintheta = sin(theta.
radians());
3557 if (ra.
radians() < -1 * pi_c()) {
3560 else if (ra.
radians() > pi_c()) {
3564 if (pm.radians() < -1 * pi_c()) {
3567 else if (pm.radians() > pi_c()) {
3572 SpiceDouble phi = ra.
radians() + HALFPI;
3573 SpiceDouble delta = HALFPI - dec.radians();
3574 SpiceDouble w = pm.radians();
3575 SpiceDouble dphi = dra.radians();
3576 SpiceDouble ddelta = -ddec.
radians();
3577 SpiceDouble dw = dpm.
radians();
3580 SpiceDouble angsDangs[6];
3581 SpiceDouble BJs[6][6];
3582 vpack_c(w, delta, phi, angsDangs);
3583 vpack_c(dw, ddelta, dphi, &angsDangs[3]);
3587 xf2rav_c(BJs, (SpiceDouble( *)[3]) &
p_CJ[0], (SpiceDouble *) &
p_av[0]);
Defines an angle and provides unit conversions.
double radians() const
Convert an angle to a double.
@ Degrees
Degrees are generally considered more human readable, 0-360 is one circle, however most math does not...
@ Radians
Radians are generally used in mathematical equations, 0-2*PI is one circle, however these are more di...
double Evaluate(const std::vector< double > &vars)
Compute the equation using the input variables.
int Coefficients() const
Returns the number of coefficients for the equation.
double Coefficient(int i) const
Returns the ith coefficient.
void SetCoefficients(const std::vector< double > &coefs)
Set the coefficients for the equation.
Generic least square fitting class.
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...
void AddKnown(const std::vector< double > &input, double expected, double weight=1.0)
Invoke this method for each set of knowns.
Utility class for creating and using cartesean line equations.
double Slope()
Compute the slope of the line.
double Intercept()
Compute the intercept of the line.
static void CheckErrors(bool resetNaif=true)
This method looks for any naif errors that might have occurred.
Nth degree Polynomial with one variable.
double DerivativeVar(const double value)
This will take the Derivative with respect to the variable and evaluate at given value.
Provide operations for quaternion arithmetic.
std::vector< double > ToMatrix()
Converts quaternion to 3x3 rotational matrix.
std::vector< double > toJ2000Partial(const std::vector< double > &lookT, PartialType partialVar, int coeffIndex)
Given a direction vector in the reference frame, compute the derivative with respect to one of the co...
void setEphemerisTimePolyFunction()
When setting the ephemeris time, updates the rotation according to a polynomial that defines the thre...
std::vector< double > GetFullCacheTime()
Return full listing (cache) of original time coverage requested.
void SetPolynomial(const Source type=PolyFunction)
Set the coefficients of a polynomial fit to each of the three camera angles for the time period cover...
std::vector< double > m_decNutPrec
Coefficients of pole decliniation nut/prec terms.
void loadPCFromTable(const PvlObject &Label)
Initialize planetary orientation constants from an cube body rotation label.
void SetConstantMatrix(std::vector< double > constantMatrix)
Set the constant 3x3 rotation TC matrix from a vector of length 9.
void SetFullCacheParameters(double startTime, double endTime, int cacheSize)
Set the full cache time parameters.
double GetTimeScale()
Accessor method to get the rotation time scale.
int Frame()
Accessor method that returns the frame code.
void setPckPolynomial(const std::vector< Angle > &raCoeff, const std::vector< Angle > &decCoeff, const std::vector< Angle > &pmCoeff)
Set the coefficients of a polynomial fit to each of the three planet angles for the time period cover...
void setFrameType()
Set the frame type (m_frameType).
FrameType getFrameType()
Accessor method to get the rotation frame type.
int p_targetCode
For computing Nadir rotation only.
double p_fullCacheStartTime
Initial requested starting time of cache.
int p_degree
Degree of fit polynomial for angles.
Source p_source
The source of the rotation data.
void setEphemerisTimePckPolyFunction()
When setting the ephemeris time, updates the rotation state based on the PcK polynomial.
void CacheLabel(Table &table)
Add labels to a SpiceRotation table.
void SetTimeBasedMatrix(std::vector< double > timeBasedMatrix)
Set the time-based 3x3 rotation CJ matrix from a vector of length 9.
double p_fullCacheEndTime
Initial requested ending time of cache.
std::vector< double > Matrix()
Return the full rotation TJ as a matrix.
double EphemerisTime() const
Accessor method to get current ephemeris time.
void SetAxes(int axis1, int axis2, int axis3)
Set the axes of rotation for decomposition of a rotation matrix into 3 angles.
double GetBaseTime()
Accessor method to get the rotation base time.
std::vector< double > EvaluatePolyFunction()
Evaluate the polynomial fit function for the three pointing angles for the current ephemeris time.
std::vector< double > ToReferencePartial(std::vector< double > &lookJ, PartialType partialVar, int coeffIndex)
Compute the derivative with respect to one of the coefficients in the angle polynomial fit equation o...
int p_axisV
The axis defined by the velocity vector for defining a nadir rotation.
void ReloadCache()
Cache J2000 rotation over existing cached time range using polynomials.
bool p_hasAngularVelocity
Flag indicating whether the rotation includes angular velocity.
double p_baseTime
Base time used in fit equations.
std::vector< Angle > poleDecCoefs()
Return the coefficients used to calculate the target body pole dec.
int p_axisP
The axis defined by the spacecraft vector for defining a nadir rotation.
std::vector< Angle > m_pm
Coefficients of a quadratic polynomial fitting pole pm.
double WrapAngle(double compareAngle, double angle)
Wrap the input angle to keep it within 2pi radians of the angle to compare.
std::vector< double > GetCenterAngles()
Return the camera angles at the center time of the observation.
void setEphemerisTimeNadir()
When setting the ephemeris time, uses spacecraft nadir source to update the rotation state.
Source GetSource()
Accessor method to get the rotation source.
std::vector< Angle > m_decPole
Coefficients of a quadratic polynomial fitting pole dec.
void LoadTimeCache()
Load the time cache.
std::vector< double > & TimeBasedMatrix()
Return time-based 3x3 rotation CJ matrix as a vector of length 9.
std::vector< double > p_CJ
Rotation matrix from J2000 to first constant rotation.
std::vector< double > Angles(int axis3, int axis2, int axis1)
Return the camera angles (right ascension, declination, and twist) for the time-based matrix CJ.
void InitConstantRotation(double et)
Initialize the constant rotation.
int p_axis1
Axis of rotation for angle 1 of rotation.
int p_axis3
Axis of rotation for angle 3 of rotation.
Table Cache(const QString &tableName)
Return a table with J2000 to reference rotations.
void LoadCache(double startTime, double endTime, int size)
Cache J2000 rotation quaternion over a time range.
std::vector< double > ConstantRotation()
Return the constant 3x3 rotation TC matrix as a quaternion.
std::vector< double > ReferenceVector(const std::vector< double > &jVec)
Given a direction vector in J2000, return a reference frame direction.
std::vector< double > AngularVelocity()
Accessor method to get the angular velocity.
double p_overrideBaseTime
Value set by caller to override computed base time.
double p_overrideTimeScale
Value set by caller to override computed time scale.
std::vector< Angle > sysNutPrecCoefs()
Return the coefficients used to calculate the target body system nut/prec angles.
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...
Table LineCache(const QString &tableName)
Return a table with J2000 to reference rotations.
std::vector< double > J2000Vector(const std::vector< double > &rVec)
Given a direction vector in the reference frame, return a J2000 direction.
double DPckPolynomial(PartialType partialVar, const int coeffIndex)
Evaluate the derivative of the fit polynomial defined by the given coefficients with respect to the c...
DownsizeStatus p_minimizeCache
Status of downsizing the cache (set to No to ignore)
void SetEphemerisTime(double et)
Return the J2000 to reference frame quaternion at given time.
void SetFrame(int frameCode)
Change the frame to the given frame code.
std::vector< double > m_raNutPrec
Coefficients of pole right ascension nut/prec terms.
std::vector< int > TimeFrameChain()
Accessor method to get the frame chain for the rotation (begins in J2000).
std::vector< double > p_coefficients[3]
Coefficients defining functions fit to 3 pointing angles.
SpiceRotation(int frameCode)
Construct an empty SpiceRotation class using a valid Naif frame code to set up for getting rotation f...
double p_timeScale
Time scale used in fit equations.
std::vector< Angle > sysNutPrecConstants()
Return the constants used to calculate the target body system nut/prec angles.
std::vector< double > Extrapolate(double timeEt)
Extrapolate pointing for a given time assuming a constant angular velocity.
bool p_degreeApplied
Flag indicating whether or not a polynomial of degree p_degree has been created and used to fill the ...
std::vector< double > poleRaNutPrecCoefs()
Return the coefficients used to calculate the target body pole ra nut/prec coefficients.
std::vector< double > p_cacheTime
iTime for corresponding rotation
DownsizeStatus
Status of downsizing the cache.
@ Done
Cache is downsized.
@ No
Do not downsize the cache.
void checkForBinaryPck()
Check loaded pck to see if any are binary and set frame type to indicate binary pck.
std::vector< Angle > poleRaCoefs()
Return the coefficients used to calculate the target body pole ra.
void setEphemerisTimePolyFunctionOverSpice()
When setting the ephemeris time, updates the rotation state based on a polynomial fit over spice kern...
std::vector< double > p_av
Angular velocity for rotation at time p_et.
void SetSource(Source source)
Resets the source of the rotation to the given value.
int p_fullCacheSize
Initial requested cache size.
void setEphemerisTimeSpice()
When setting the ephemeris time, updates the rotation state based on data read directly from NAIF ker...
bool p_noOverride
Flag to compute base time;.
bool m_tOrientationAvailable
Target orientation constants are available.
void GetPolynomial(std::vector< double > &abcAng1, std::vector< double > &abcAng2, std::vector< double > &abcAng3)
Return the coefficients of a polynomial fit to each of the three camera angles for the time period co...
std::vector< double > StateTJ()
State matrix (6x6) for rotating state vectors from J2000 to target frame.
Source
The rotation can come from one of 3 places for an Isis cube.
@ PolyFunction
From nth degree polynomial.
@ Spice
Directly from the kernels.
@ PckPolyFunction
Quadratic polynomial function with linear trignometric terms.
@ Memcache
From cached table.
@ PolyFunctionOverSpice
Kernels plus nth degree polynomial.
PartialType
This enumeration indicates whether the partial derivative is taken with respect to Right Ascension,...
@ WRT_RightAscension
With respect to Right Ascension.
@ WRT_Twist
With respect to Twist or Prime Meridian Rotation.
@ WRT_Declination
With respect to Declination.
void loadPCFromSpice(int CenterBodyCode)
Initialize planetary orientation constants from Spice PCK.
void setEphemerisTimeMemcache()
Updates rotation state based on the rotation cache.
void ComputeAv()
Compute the angular velocity from the time-based functions fit to the pointing angles This method com...
double DPolynomial(const int coeffIndex)
Evaluate the derivative of the fit polynomial defined by the given coefficients with respect to the c...
void ComputeBaseTime()
Compute the base time using cached times.
void SetPolynomialDegree(int degree)
Set the degree of the polynomials to be fit to the three camera angles for the time period covered by...
void MinimizeCache(DownsizeStatus status)
Set the downsize status to minimize cache.
void SetAngles(std::vector< double > angles, int axis3, int axis2, int axis1)
Set the rotation angles (phi, delta, and w) for the current time to define the time-based matrix CJ.
bool HasAngularVelocity()
Checks whether the rotation has angular velocities.
double p_et
Current ephemeris time.
std::vector< double > m_pmNutPrec
Coefficients of prime meridian nut/prec terms.
std::vector< Angle > m_raPole
Coefficients of a quadratic polynomial fitting pole ra.
std::vector< int > p_timeFrames
Chain of Naif frame codes in time-based rotation CJ.
void DCJdt(std::vector< double > &dRJ)
Compute the derivative of the 3x3 rotation matrix CJ with respect to time.
void SetTimeBias(double timeBias)
Apply a time bias when invoking SetEphemerisTime method.
bool p_matrixSet
Flag indicating p_TJ has been set.
std::vector< int > ConstantFrameChain()
Accessor method to get the frame chain for the constant part of the rotation (ends in target)
std::vector< double > p_TC
Rotation matrix from first constant rotation (after all time-based rotations in frame chain from J200...
void FrameTrace(double et)
Compute frame trace chain from target frame to J2000.
int p_axis2
Axis of rotation for angle 2 of rotation.
std::vector< Angle > m_sysNutPrec0
Constants of planetary system nut/prec periods.
std::vector< double > & ConstantMatrix()
Return the constant 3x3 rotation TC matrix as a vector of length 9.
void getPckPolynomial(std::vector< Angle > &raCoeff, std::vector< Angle > &decCoeff, std::vector< Angle > &pmCoeff)
Return the coefficients of a polynomial fit to each of the three planet angles.
double p_timeBias
iTime bias when reading kernels
std::vector< double > pmNutPrecCoefs()
Return the coefficients used to calculate the target body pm nut/prec coefficients.
FrameType
Enumeration for the frame type of the rotation.
@ INERTL
See Naif Frames.req document for.
@ NOTJ2000PCK
PCK frame not referenced to J2000.
@ UNKNOWN
Isis specific code for unknown frame type.
@ BPC
Isis specific code for binary pck.
bool IsCached() const
Checks if the cache is empty.
FrameType m_frameType
The type of rotation frame.
std::vector< double > poleDecNutPrecCoefs()
Return the coefficients used to calculate the target body pole dec nut/prec coefficients.
std::vector< Angle > pmCoefs()
Return the coefficients used to calculate the target body prime meridian.
std::vector< Angle > m_sysNutPrec1
Linear terms of planetary system nut/prec periods.
std::vector< int > p_constantFrames
Cached orientation information.
virtual ~SpiceRotation()
Destructor for SpiceRotation object.
Quaternion p_quaternion
Quaternion for J2000 to reference rotation at et.
void usePckPolynomial()
Set the coefficients of a polynomial fit to each of the three planet angles for the time period cover...
std::vector< double > TimeBasedRotation()
Return time-based 3x3 rotation CJ matrix as a quaternion.
This is free and unencumbered software released into the public domain.
QString toString(const LinearAlgebra::Vector &vector, int precision)
A global function to format LinearAlgebra::Vector as a QString with the given precision.