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"
33 using json = nlohmann::json;
37 extern int refchg_(integer *frame1, integer *frame2, doublereal *et,
39 extern int frmchg_(integer *frame1, integer *frame2, doublereal *et,
41 extern int invstm_(doublereal *mat, doublereal *invmat);
45 extern 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";
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;
327 return (m_orientation != NULL);
363 QString msg =
"Argument cacheSize must not be less or equal to zero";
367 if (startTime > endTime) {
368 QString msg =
"Argument startTime must be less than or equal to endTime";
372 if ((startTime != endTime) && (size == 1)) {
373 QString msg =
"Cache size must be more than 1 if startTime and endTime differ";
379 QString msg =
"A SpiceRotation cache has already been created";
388 if (m_orientation != NULL) {
389 delete m_orientation;
390 m_orientation = NULL;
405 std::vector<ale::Rotation> rotationCache;
406 std::vector< std::vector<double> > cache;
407 std::vector<ale::Vec3d> avCache;
408 for (
int i = 0; i < cacheSize; i++) {
411 rotationCache.push_back(ale::Rotation(
p_CJ));
412 cache.push_back(
p_CJ);
415 avCache.push_back(ale::Vec3d(
p_av));
419 if (
p_TC.size() > 1) {
420 m_orientation =
new ale::Orientations(rotationCache,
p_cacheTime, avCache,
424 m_orientation =
new ale::Orientations(rotationCache,
p_cacheTime, avCache,
476 delete m_orientation;
477 m_orientation = NULL;
484 p_cacheTime = isdRot[
"ephemeris_times"].get<std::vector<double>>();
485 p_timeFrames = isdRot[
"time_dependent_frames"].get<std::vector<int>>();
487 std::vector<ale::Rotation> rotationCache;
488 for (
auto it = isdRot[
"quaternions"].begin(); it != isdRot[
"quaternions"].end(); it++) {
489 std::vector<double> quat = {it->at(0).get<
double>(), it->at(1).get<
double>(), it->at(2).get<
double>(), it->at(3).get<
double>()};
491 std::vector<double> CJ = q.
ToMatrix();
492 rotationCache.push_back(ale::Rotation(CJ));
495 std::vector<ale::Vec3d> avCache;
496 if (isdRot[
"angular_velocities"].size() != 0) {
497 for (
auto it = isdRot[
"angular_velocities"].begin(); it != isdRot[
"angular_velocities"].end(); it++) {
498 std::vector<double> av = {it->at(0).get<
double>(), it->at(1).get<
double>(), it->at(2).get<
double>()};
499 avCache.push_back(ale::Vec3d(av));
504 bool hasConstantFrames = isdRot.find(
"constant_frames") != isdRot.end();
507 if (hasConstantFrames) {
509 p_TC = isdRot[
"constant_rotation"].get<std::vector<double>>();
510 m_orientation =
new ale::Orientations(rotationCache,
p_cacheTime, avCache,
515 ident_c((SpiceDouble( *)[3]) &
p_TC[0]);
516 m_orientation =
new ale::Orientations(rotationCache,
p_cacheTime, avCache,
559 delete m_orientation;
560 m_orientation = NULL;
566 for (
int i = 0; i < labelTimeFrames.
size(); i++) {
579 for (
int i = 0; i < labelConstantFrames.
size(); i++) {
584 for (
int i = 0; i < labelConstantRotation.
size(); i++) {
590 ident_c((SpiceDouble( *)[3]) &
p_TC[0]);
616 int recFields = table[0].Fields();
623 std::vector<ale::Rotation> rotationCache;
624 std::vector<ale::Vec3d> avCache;
625 if (recFields == 5) {
626 for (
int r = 0; r < table.
Records(); r++) {
629 if (rec.
Fields() != recFields) {
633 std::vector<double> j2000Quat;
634 j2000Quat.push_back((
double)rec[0]);
635 j2000Quat.push_back((
double)rec[1]);
636 j2000Quat.push_back((
double)rec[2]);
637 j2000Quat.push_back((
double)rec[3]);
640 std::vector<double> CJ = q.
ToMatrix();
641 rotationCache.push_back(ale::Rotation(CJ));
645 if (
p_TC.size() > 1) {
646 m_orientation =
new ale::Orientations(rotationCache,
p_cacheTime, avCache,
650 m_orientation =
new ale::Orientations(rotationCache,
p_cacheTime, avCache,
657 else if (recFields == 8) {
658 for (
int r = 0; r < table.
Records(); r++) {
661 if (rec.
Fields() != recFields) {
665 std::vector<double> j2000Quat;
666 j2000Quat.push_back((
double)rec[0]);
667 j2000Quat.push_back((
double)rec[1]);
668 j2000Quat.push_back((
double)rec[2]);
669 j2000Quat.push_back((
double)rec[3]);
673 std::vector<double> CJ = q.
ToMatrix();
674 rotationCache.push_back(ale::Rotation(CJ));
676 std::vector<double> av;
677 av.push_back((
double)rec[4]);
678 av.push_back((
double)rec[5]);
679 av.push_back((
double)rec[6]);
680 avCache.push_back(ale::Vec3d(av));
685 if (
p_TC.size() > 1) {
686 m_orientation =
new ale::Orientations(rotationCache,
p_cacheTime, avCache,
690 m_orientation =
new ale::Orientations(rotationCache,
p_cacheTime, avCache,
697 else if (recFields == 3) {
698 std::vector<double> coeffAng1, coeffAng2, coeffAng3;
700 for (
int r = 0; r < table.
Records() - 1; r++) {
703 if (rec.
Fields() != recFields) {
706 coeffAng1.push_back((
double)rec[0]);
707 coeffAng2.push_back((
double)rec[1]);
708 coeffAng3.push_back((
double)rec[2]);
713 double baseTime = (double)rec[0];
714 double timeScale = (double)rec[1];
715 double degree = (double)rec[2];
721 if (degree == 0 && m_orientation->getAngularVelocities().size() > 0) {
726 QString msg =
"Expecting either three, five, or eight fields in the SpiceRotation table";
746 std::vector<ale::Rotation> rotationCache;
747 std::vector<ale::Vec3d> avCache;
758 for (std::vector<double>::size_type pos = 0; pos <
p_cacheTime.size(); pos++) {
760 rotationCache.push_back(ale::Rotation(
p_CJ));
761 avCache.push_back(ale::Vec3d(
p_av));
767 rotationCache.push_back(ale::Rotation(
p_CJ));
768 avCache.push_back(ale::Vec3d(
p_av));
782 for (std::vector<double>::size_type pos = 0; pos < maxSize; pos++) {
785 rotationCache.push_back(ale::Rotation(CJ));
792 QString msg =
"The SpiceRotation has not yet been fit to a function";
797 delete m_orientation;
798 m_orientation = NULL;
801 if (
p_TC.size() > 1) {
802 m_orientation =
new ale::Orientations(rotationCache,
p_cacheTime, avCache,
806 m_orientation =
new ale::Orientations(rotationCache,
p_cacheTime, avCache,
838 QString msg =
"Only cached rotations can be returned as a line cache of quaternions and time";
842 return Cache(tableName);
907 Table table(tableName, record);
909 std::vector<ale::Rotation> rots = m_orientation->getRotations();
910 std::vector<ale::Vec3d> angularVelocities = m_orientation->getAngularVelocities();
911 for (
int i = 0; i < (int)
p_cacheTime.size(); i++) {
912 std::vector<double> quat = rots[i].toQuaternion();
917 quat[0] = -1 * quat[0];
918 quat[1] = -1 * quat[1];
919 quat[2] = -1 * quat[2];
920 quat[3] = -1 * quat[3];
929 ale::Vec3d angularVelocity = angularVelocities[i];
930 record[4] = angularVelocity.x;
931 record[5] = angularVelocity.y;
932 record[6] = angularVelocity.z;
957 Table table(tableName, record);
959 for (
int cindex = 0; cindex <
p_degree + 1; cindex++) {
978 QString msg =
"To create table source of data must be either Memcache or PolyFunction";
993 SpiceInt centerBodyCode = (SpiceInt) centerBody;
1009 QString naifKeyword =
"BODY" +
toString(centerBodyCode) +
"_CONSTANTS_REF_FRAME" ;
1010 SpiceInt numExpected;
1011 SpiceInt numReturned;
1013 SpiceDouble relativeFrameCode = 0;
1015 dtpool_c(naifKeyword.toLatin1().data(), &found, &numExpected, &naifType);
1019 SpiceDouble relativeFrameCode;
1020 bodvcd_c(centerBodyCode,
"CONSTANTS_REF_FRAME", 1,
1021 &numReturned, &relativeFrameCode);
1024 if (!found || relativeFrameCode == 1) {
1028 naifKeyword =
"BODY" +
toString(centerBodyCode) +
"_POLE_RA" ;
1029 dtpool_c(naifKeyword.toLatin1().data(), &found, &numExpected, &naifType);
1032 std::vector<SpiceDouble> d(3);
1035 m_pm.resize(numExpected);
1037 bodvcd_c(centerBodyCode,
"POLE_RA", numExpected, &numReturned, &d[0]);
1042 bodvcd_c(centerBodyCode,
"POLE_DEC", numExpected, &numReturned, &d[0]);
1047 bodvcd_c(centerBodyCode,
"PM", numExpected, &numReturned, &d[0]);
1048 m_pm[0].setDegrees(d[0]);
1049 m_pm[1].setDegrees(d[1]);
1050 m_pm[2].setDegrees(d[2]);
1057 naifKeyword =
"BODY" +
toString(centerBodyCode) +
"_NUT_PREC_RA" ;
1058 dtpool_c(naifKeyword.toLatin1().data(), &found, &numReturned, &naifType);
1062 SpiceInt bcCode = centerBodyCode/100;
1063 naifKeyword =
"BODY" +
toString(bcCode) +
"_NUT_PREC_ANGLES" ;
1064 dtpool_c(naifKeyword.toLatin1().data(), &found, &numExpected, &naifType);
1065 std::vector<double>npAngles(numExpected, 0.);
1066 bodvcd_c(bcCode,
"NUT_PREC_ANGLES", numExpected, &numReturned, &npAngles[0]);
1072 std::vector<SpiceDouble> angles(numExpected);
1073 bodvcd_c(centerBodyCode,
"NUT_PREC_RA", numExpected, &numReturned, &
m_raNutPrec[0]);
1074 bodvcd_c(centerBodyCode,
"NUT_PREC_DEC", numExpected, &numReturned, &
m_decNutPrec[0]);
1075 bodvcd_c(centerBodyCode,
"NUT_PREC_PM", numExpected, &numReturned, &
m_pmNutPrec[0]);
1080 for (
int i = 0; i < numExpected; i++) {
1119 for (
int i = 0; i < labelCoeffs.
size(); i++){
1126 for (
int i = 0; i < labelCoeffs.
size(); i++){
1132 PvlKeyword labelCoeffs = label[
"PrimeMeridian"];
1133 for (
int i = 0; i < labelCoeffs.
size(); i++){
1141 PvlKeyword labelCoeffs = label[
"PoleRaNutPrec"];
1142 for (
int i = 0; i < labelCoeffs.
size(); i++){
1147 PvlKeyword labelCoeffs = label[
"PoleDecNutPrec"];
1148 for (
int i = 0; i < labelCoeffs.
size(); i++){
1154 for (
int i = 0; i < labelCoeffs.
size(); i++){
1159 PvlKeyword labelCoeffs = label[
"SysNutPrec0"];
1160 for (
int i = 0; i < labelCoeffs.
size(); i++){
1165 PvlKeyword labelCoeffs = label[
"SysNutPrec1"];
1166 for (
int i = 0; i < labelCoeffs.
size(); i++){
1203 for (
int i = 0; i < (int)
p_TC.size(); i++) {
1231 for (
int i = 0; i < (int)
m_raPole.size(); i++) {
1237 for (
int i = 0; i < (int)
m_decPole.size(); i++) {
1243 for (
int i = 0; i < (int)
m_pm.size(); i++) {
1250 for (
int i = 0; i < (int)
m_raNutPrec.size(); i++) {
1262 for (
int i = 0; i < (int)
m_pmNutPrec.size(); i++) {
1312 SpiceDouble ang1, ang2, ang3;
1313 m2eul_c((SpiceDouble *) &
p_CJ[0], axis3, axis2, axis1, &ang3, &ang2, &ang1);
1315 std::vector<double> angles;
1316 angles.push_back(ang1);
1317 angles.push_back(ang2);
1318 angles.push_back(ang3);
1337 eul2m_c(angles[2], angles[1], angles[0], axis3, axis2, axis1, (SpiceDouble (*)[3]) &(
p_CJ[0]));
1339 if (m_orientation) {
1340 delete m_orientation;
1341 m_orientation = NULL;
1343 std::vector<ale::Rotation> rotationCache;
1344 rotationCache.push_back(ale::Rotation(
p_CJ));
1345 if (
p_TC.size() > 1) {
1346 m_orientation =
new ale::Orientations(rotationCache,
p_cacheTime, std::vector<ale::Vec3d>(),
1350 m_orientation =
new ale::Orientations(rotationCache,
p_cacheTime, std::vector<ale::Vec3d>(),
1411 std::vector<double> jVec;
1412 if (rVec.size() == 3) {
1414 mxm_c((SpiceDouble *) &
p_TC[0], (SpiceDouble *) &
p_CJ[0], TJ);
1416 mtxv_c(TJ, (SpiceDouble *) &rVec[0], (SpiceDouble *) &jVec[0]);
1419 else if (rVec.size() == 6) {
1425 std::vector<double> stateTJ(36);
1429 xpose6_c(&stateTJ[0], (SpiceDouble( *) [6]) &stateTJ[0]);
1430 double stateJT[6][6];
1431 invstm_((doublereal *) &stateTJ[0], (doublereal *) stateJT);
1432 xpose6_c(stateJT, stateJT);
1435 mxvg_c(stateJT, (SpiceDouble *) &rVec[0], 6, 6, (SpiceDouble *) &jVec[0]);
1612 std::vector<double> jVec;
1616 int angleIndex = partialVar;
1619 double angle = angles.at(angleIndex);
1622 double dmatrix[3][3];
1623 drotat_(&angle, (integer *) axes + angleIndex, (doublereal *) dmatrix);
1625 xpose_c(dmatrix, dmatrix);
1639 msg =
"Body rotation uses a binary PCK. Solutions for this model are not supported";
1643 msg =
"Body rotation uses a PCK not referenced to J2000. "
1644 "Solutions for this model are not supported";
1648 msg =
"Solutions are not supported for this frame type.";
1653 for (
int row = 0; row < 3; row++) {
1654 for (
int col = 0; col < 3; col++) {
1655 dmatrix[row][col] *= dpoly;
1661 switch (angleIndex) {
1663 rotmat_c(dmatrix, angles[1], axes[1], dCJ);
1664 rotmat_c(dCJ, angles[2], axes[2], dCJ);
1667 rotate_c(angles[0], axes[0], dCJ);
1668 mxm_c(dmatrix, dCJ, dCJ);
1669 rotmat_c(dCJ, angles[2], axes[2], dCJ);
1672 rotate_c(angles[0], axes[0], dCJ);
1673 rotmat_c(dCJ, angles[1], axes[1], dCJ);
1674 mxm_c(dmatrix, dCJ, dCJ);
1680 mxm_c((SpiceDouble *) &
p_TC[0], dCJ[0], dTJ);
1684 std::vector<double> lookdJ(3);
1686 mtxv_c(dTJ, (
const SpiceDouble *) &lookT[0], (SpiceDouble *) &lookdJ[0]);
1703 std::vector<double> rVec(3);
1705 if (jVec.size() == 3) {
1707 mxm_c((SpiceDouble *) &
p_TC[0], (SpiceDouble *) &
p_CJ[0], TJ);
1709 mxv_c(TJ, (SpiceDouble *) &jVec[0], (SpiceDouble *) &rVec[0]);
1711 else if (jVec.size() == 6) {
1717 std::vector<double> stateTJ(36);
1720 mxvg_c((SpiceDouble *) &stateTJ[0], (SpiceDouble *) &jVec[0], 6, 6, (SpiceDouble *) &rVec[0]);
1741 std::vector<double> coeffAng1, coeffAng2, coeffAng3;
1752 int size = m_orientation->getRotations().size();
1756 else if (size == 2) {
1762 coeffAng1.assign(
p_degree + 1, 0.);
1763 coeffAng2.assign(
p_degree + 1, 0.);
1764 coeffAng3.assign(
p_degree + 1, 0.);
1779 std::vector<double> time;
1785 coeffAng1.push_back(angles[0]);
1786 coeffAng2.push_back(angles[1]);
1787 coeffAng3.push_back(angles[2]);
1789 else if (size == 2) {
1802 angles2[0] =
WrapAngle(angles1[0], angles2[0]);
1803 angles2[2] =
WrapAngle(angles1[2], angles2[2]);
1805 double intercept[3];
1808 for (
int angleIndex = 0; angleIndex < 3; angleIndex++) {
1810 slope[angleIndex] = angline.
Slope();
1811 intercept[angleIndex] = angline.
Intercept();
1813 coeffAng1.push_back(intercept[0]);
1814 coeffAng1.push_back(slope[0]);
1815 coeffAng2.push_back(intercept[1]);
1816 coeffAng2.push_back(slope[1]);
1817 coeffAng3.push_back(intercept[2]);
1818 coeffAng3.push_back(slope[2]);
1825 for (std::vector<double>::size_type pos = 0; pos <
p_cacheTime.size(); pos++) {
1837 angles[0] =
WrapAngle(start1, angles[0]);
1838 angles[2] =
WrapAngle(start3, angles[2]);
1841 fitAng1->
AddKnown(time, angles[0]);
1842 fitAng2->
AddKnown(time, angles[1]);
1843 fitAng3->
AddKnown(time, angles[2]);
1892 const std::vector<double> &coeffAng2,
1893 const std::vector<double> &coeffAng3,
1958 QString msg =
"Target body orientation information not available. Rerun spiceinit.";
2029 const std::vector<Angle> &decCoeff,
2030 const std::vector<Angle> &pmCoeff) {
2052 std::vector<double> &coeffAng2,
2053 std::vector<double> &coeffAng3) {
2074 std::vector<Angle> &decCoeff,
2075 std::vector<Angle> &pmCoeff) {
2117 void SpiceRotation::SetCacheTime(std::vector<double> cacheTime) {
2141 if (coeffIndex > 0 && coeffIndex <=
p_degree) {
2142 derivative = pow(time, coeffIndex);
2144 else if (coeffIndex == 0) {
2148 QString msg =
"Unable to evaluate the derivative of the SPICE rotation fit polynomial for "
2149 "the given coefficient index [" +
toString(coeffIndex) +
"]. "
2150 "Index is negative or exceeds degree of polynomial ["
2173 const int coeffIndex) {
2174 const double p_dayScale = 86400;
2176 const double p_centScale = p_dayScale * 36525;
2179 switch (partialVar) {
2182 time =
p_et / p_centScale;
2185 time =
p_et / p_dayScale;
2191 switch (coeffIndex) {
2197 derivative = pow(time, coeffIndex);
2200 QString msg =
"Unable to evaluate the derivative of the target body rotation fit polynomial "
2201 "for the given coefficient index [" +
toString(coeffIndex) +
"]. "
2202 "Index is negative or exceeds degree of polynomial ["
2210 derivative = -derivative;
2240 int angleIndex = partialVar;
2243 double angle = angles.at(angleIndex);
2245 double dmatrix[3][3];
2246 drotat_(&angle, (integer *) axes + angleIndex, (doublereal *) dmatrix);
2248 xpose_c(dmatrix, dmatrix);
2262 QString msg =
"Only CK, DYN, and PCK partials can be calculated";
2267 for (
int row = 0; row < 3; row++) {
2268 for (
int col = 0; col < 3; col++) {
2269 dmatrix[row][col] *= dpoly;
2275 switch (angleIndex) {
2277 rotmat_c(dmatrix, angles[1], axes[1], dCJ);
2278 rotmat_c(dCJ, angles[2], axes[2], dCJ);
2281 rotate_c(angles[0], axes[0], dCJ);
2282 mxm_c(dmatrix, dCJ, dCJ);
2283 rotmat_c(dCJ, angles[2], axes[2], dCJ);
2286 rotate_c(angles[0], axes[0], dCJ);
2287 rotmat_c(dCJ, angles[1], axes[1], dCJ);
2288 mxm_c(dmatrix, dCJ, dCJ);
2294 mxm_c((SpiceDouble *) &
p_TC[0], dCJ[0], dTJ);
2298 std::vector<double> lookdT(3);
2300 mxv_c(dTJ, (
const SpiceDouble *) &lookJ[0], (SpiceDouble *) &lookdT[0]);
2317 double diff1 = compareAngle - angle;
2319 if (diff1 < -1 * pi_c()) {
2322 else if (diff1 > pi_c()) {
2362 for (
int icoef =
p_degree + 1; icoef <= degree; icoef++) {
2363 coefAngle1.push_back(0.);
2364 coefAngle2.push_back(0.);
2365 coefAngle3.push_back(0.);
2372 std::vector<double> coefAngle1(degree + 1),
2373 coefAngle2(degree + 1),
2374 coefAngle3(degree + 1);
2376 for (
int icoef = 0; icoef <= degree; icoef++) {
2451 if (axis1 < 1 || axis2 < 1 || axis3 < 1 || axis1 > 3 || axis2 > 3 || axis3 > 3) {
2452 QString msg =
"A rotation axis is outside the valid range of 1 to 3";
2479 double currentTime = observStart;
2480 bool timeLoaded =
false;
2485 ktotal_c(
"ck", (SpiceInt *) &count);
2494 "Full cache size does NOT match cache size in LoadTimeCache -- should never happen";
2503 std::vector<ale::Rotation> fullRotationCache = m_orientation->getRotations();
2504 std::vector<ale::Vec3d> angularVelocities = m_orientation->getAngularVelocities();
2507 std::vector<double> rotationMatrix = fullRotationCache[r].toRotationMatrix();
2508 SpiceDouble CJ[9] = { rotationMatrix[0], rotationMatrix[1], rotationMatrix[2],
2509 rotationMatrix[3], rotationMatrix[4], rotationMatrix[5],
2510 rotationMatrix[6], rotationMatrix[7], rotationMatrix[8]
2512 m2q_c(CJ, quats[r]);
2514 ale::Vec3d angularVelocity = angularVelocities[r];
2515 vequ_c((SpiceDouble *) &angularVelocity.x, avvs[r]);
2519 double cubeStarts = timeSclkdp[0];
2520 double radTol = 0.000000017453;
2521 SpiceInt avflag = 1;
2527 ck3sdn(radTol, avflag, (
int *) &sizOut, timeSclkdp, (doublereal *) quats,
2528 (SpiceDouble *) avvs, nints, &cubeStarts, dparr, (
int *) intarr);
2532 std::vector<double> av;
2535 if (m_orientation) {
2536 delete m_orientation;
2537 m_orientation = NULL;
2540 std::vector<ale::Rotation> rotationCache;
2541 std::vector<ale::Vec3d> avCache;
2543 for (
int r = 0; r < sizOut; r++) {
2548 std::vector<double> CJ(9);
2549 q2m_c(quats[r], (SpiceDouble( *)[3]) &CJ[0]);
2550 rotationCache.push_back(CJ);
2551 vequ_c(avvs[r], (SpiceDouble *) &av[0]);
2552 avCache.push_back(av);
2555 if (
p_TC.size() > 1 ) {
2556 m_orientation =
new ale::Orientations(rotationCache,
p_cacheTime, avCache,
2560 m_orientation =
new ale::Orientations(rotationCache,
p_cacheTime, std::vector<ale::Vec3d>(),
2573 int SOURCESIZ = 128;
2576 SpiceChar file[FILESIZ];
2577 SpiceChar filtyp[TYPESIZ];
2578 SpiceChar source[SOURCESIZ];
2581 bool observationSpansToNextSegment =
false;
2586 kdata_c(0,
"ck", FILESIZ, TYPESIZ, SOURCESIZ, file, filtyp, source, &handle, &found);
2592 observationSpansToNextSegment =
false;
2603 dafus_c(sum, (SpiceInt) 2, (SpiceInt) 6, dc, ic);
2606 if (ic[2] == 5)
break;
2609 if (ic[0] == spCode && ic[2] == 3) {
2610 sct2e_c((
int) spCode / 1000, dc[0], &segStartEt);
2611 sct2e_c((
int) spCode / 1000, dc[1], &segStopEt);
2616 if (currentTime >= segStartEt && currentTime <= segStopEt) {
2620 if (observationSpansToNextSegment && currentTime > segStartEt) {
2621 QString msg =
"Observation crosses segment boundary--unable to interpolate pointing";
2624 if (observEnd > segStopEt) {
2625 observationSpansToNextSegment =
true;
2629 int dovelocity = ic[3];
2632 dafgda_c(handle, end - 1, end, val);
2634 int ninstances = (int) val[1];
2635 int numvel = dovelocity * 3;
2636 int quatnoff = ic[4] + (4 + numvel) * ninstances - 1;
2638 int sclkdp1off = quatnoff + 1;
2639 int sclkdpnoff = sclkdp1off + ninstances - 1;
2642 int sclkSpCode = spCode / 1000;
2645 std::vector<double> sclkdp(ninstances);
2646 dafgda_c(handle, sclkdp1off, sclkdpnoff, (SpiceDouble *) &sclkdp[0]);
2649 sct2e_c(sclkSpCode, sclkdp[0], &et);
2651 while (instance < (ninstances - 1) && et < currentTime) {
2653 sct2e_c(sclkSpCode, sclkdp[instance], &et);
2656 if (instance > 0) instance--;
2657 sct2e_c(sclkSpCode, sclkdp[instance], &et);
2659 while (instance < (ninstances - 1) && et < observEnd) {
2662 sct2e_c(sclkSpCode, sclkdp[instance], &et);
2666 if (!observationSpansToNextSegment) {
2672 currentTime = segStopEt;
2681 QString msg =
"No camera kernels loaded...Unable to determine time cache to downsize";
2688 double cacheSlope = 0.0;
2712 QString msg =
"Time cache not available -- rerun spiceinit";
2716 std::vector<double> fullCacheTime;
2717 double cacheSlope = 0.0;
2725 return fullCacheTime;
2751 std::vector<int> frameCodes;
2752 std::vector<int> frameTypes;
2755 while (frameCodes[frameCodes.size()-1] != J2000Code) {
2756 frmidx = frameCodes.size() - 1;
2764 frinfo_c((SpiceInt) frameCodes[frmidx],
2765 (SpiceInt *) ¢er,
2767 (SpiceInt *) &typid, &found);
2772 frameTypes.push_back(0);
2776 QString msg =
"The frame" +
toString((
int) frameCodes[frmidx]) +
" is not supported by Naif";
2780 double matrix[3][3];
2784 nextFrame = J2000Code;
2786 else if (type == CK) {
2787 ckfrot_((SpiceInt *) &typid, &et, (
double *) matrix, &nextFrame, (logical *) &found);
2792 frameTypes.push_back(0);
2796 QString msg =
"The ck rotation from frame " +
toString(frameCodes[frmidx]) +
" can not "
2797 +
"be found due to no pointing available at requested time or a problem with the "
2802 else if (type == TK) {
2803 tkfram_((SpiceInt *) &typid, (
double *) matrix, &nextFrame, (logical *) &found);
2805 QString msg =
"The tk rotation from frame " +
toString(frameCodes[frmidx]) +
2806 " can not be found";
2810 else if (type == DYN) {
2817 zzdynrot_((SpiceInt *) &typid, (SpiceInt *) ¢er, &et, (
double *) matrix, &nextFrame);
2821 QString msg =
"The frame " +
toString(frameCodes[frmidx]) +
2822 " has a type " +
toString(type) +
" not supported by your version of Naif Spicelib."
2823 +
"You need to update.";
2827 frameCodes.push_back(nextFrame);
2828 frameTypes.push_back(type);
2839 while (frameTypes[nConstants] == TK && nConstants < (
int) frameTypes.size()) nConstants++;
2842 for (
int i = 0; i <= nConstants; i++) {
2847 for (
int i = nConstants; i < (int) frameCodes.size(); i++) {
2867 std::vector<double> TJ;
2869 mxm_c((SpiceDouble *) &
p_TC[0], (SpiceDouble *) &
p_CJ[0], (SpiceDouble( *) [3]) &TJ[0]);
2882 std::vector<double> q;
2884 m2q_c((SpiceDouble( *)[3]) &
p_TC[0], &q[0]);
2906 p_TC = constantMatrix;
2917 std::vector<double> q;
2919 m2q_c((SpiceDouble( *)[3]) &
p_CJ[0], &q[0]);
2941 p_CJ = timeBasedMatrix;
2957 refchg_((SpiceInt *) &fromFrame, (SpiceInt *) &targetFrame, &et, (doublereal *) &
p_TC[0]);
2959 xpose_c((SpiceDouble( *)[3]) &
p_TC[0], (SpiceDouble( *)[3]) &
p_TC[0]);
2987 QString msg =
"The SpiceRotation pointing angles must be fit to polynomials in order to ";
2988 msg +=
"compute angular velocity.";
2992 QString msg =
"Planetary angular velocity must be fit computed with PCK polynomials ";
2995 std::vector<double> dCJdt;
3013 mtxm_c((SpiceDouble( *)[3]) &dCJdt[0], (SpiceDouble( *)[3]) &
p_CJ[0], omega);
3014 p_av[0] = omega[2][1];
3015 p_av[1] = omega[0][2];
3016 p_av[2] = omega[1][0];
3034 double dmatrix[3][3];
3036 double wmatrix[3][3];
3039 for (
int angleIndex = 0; angleIndex < 3; angleIndex++) {
3040 drotat_(&(angles[angleIndex]), (integer *) axes + angleIndex, (doublereal *) dmatrix);
3042 xpose_c(dmatrix, dmatrix);
3054 for (
int row = 0; row < 3; row++) {
3055 for (
int col = 0; col < 3; col++) {
3056 dmatrix[row][col] *= dangle;
3060 switch (angleIndex) {
3062 rotmat_c(dmatrix, angles[1], axes[1], dmatrix);
3063 rotmat_c(dmatrix, angles[2], axes[2], dmatrix);
3066 rotate_c(angles[0], axes[0], wmatrix);
3067 mxm_c(dmatrix, wmatrix, dmatrix);
3068 rotmat_c(dmatrix, angles[2], axes[2], dmatrix);
3071 rotate_c(angles[0], axes[0], wmatrix);
3072 rotmat_c(wmatrix, angles[1], axes[1], wmatrix);
3073 mxm_c(dmatrix, wmatrix, dmatrix);
3077 for (
int index = 0; index < 9; index++) {
3080 dCJ[index] += dmatrix[i][j];
3094 std::vector<double> stateTJ(36);
3097 double stateCJ[6][6];
3098 rav2xf_c(&
p_CJ[0], &
p_av[0], stateCJ);
3104 for (
int row = 3; row < 6; row++) {
3108 for (
int col = 0; col < 3; col++) {
3111 stateTJ[irow*6 + col] =
p_TC[vpos] * stateCJ[0][col] +
p_TC[vpos+1] * stateCJ[1][col]
3112 +
p_TC[vpos+2] * stateCJ[2][col];
3114 stateTJ[row*6 + col] =
p_TC[vpos] * stateCJ[3][col] +
p_TC[vpos+1] * stateCJ[4][col]
3115 +
p_TC[vpos+2] * stateCJ[5][col];
3117 stateTJ[irow*6 + jcol] = 0;
3119 stateTJ[row*6 +jcol] = stateTJ[irow*6 + col];
3143 double diffTime = timeEt -
p_et;
3144 std::vector<double> CJ(9, 0.0);
3149 axisar_c((SpiceDouble *) &
p_av[0], diffTime*vnorm_c((SpiceDouble *) &
p_av[0]), dmat);
3152 mxm_c(dmat, (SpiceDouble *) &
p_CJ[0], (SpiceDouble( *)[3]) &CJ[0]);
3183 ktotal_c(
"PCK", &count);
3188 int SOURCESIZ = 128;
3189 SpiceChar file[FILESIZ];
3190 SpiceChar filetype[TYPESIZ];
3191 SpiceChar source[SOURCESIZ];
3198 for (SpiceInt knum = 0; knum < count; knum++){
3199 kdata_c(knum,
"PCK", FILESIZ, TYPESIZ, SOURCESIZ, file, filetype, source, &handle, &found);
3202 if (strstr(file,
"bpc") != NULL) {
3219 SpiceInt centerBodyCode;
3220 SpiceInt frameClass;
3222 frinfo_c(frameCode, ¢erBodyCode, &frameClass, &classId, &found);
3225 if (frameClass == 2 || (centerBodyCode > 0 && frameClass != 3)) {
3231 for (std::vector<int>::size_type idx = 1; idx <
p_constantFrames.size(); idx++) {
3233 frinfo_c(frameCode, ¢erBodyCode, &frameClass, &classId, &found);
3238 switch (frameClass) {
3272 p_CJ = m_orientation->getRotations()[0].toRotationMatrix();
3274 ale::Vec3d av = m_orientation->getAngularVelocities()[0];
3282 p_CJ = m_orientation->interpolateTimeDep(
p_et).toRotationMatrix();
3285 ale::Vec3d av = m_orientation->interpolateAV(
p_et);
3310 SpiceDouble stateJ[6];
3313 spkez_c((SpiceInt) spkCode,
p_et,
"J2000",
"LT+S",
3317 SpiceDouble sJ[3], svJ[3];
3318 vpack_c(-1 * stateJ[0], -1 * stateJ[1], -1 * stateJ[2], sJ);
3319 vpack_c(stateJ[3], stateJ[4], stateJ[5], svJ);
3324 (SpiceDouble( *)[3]) &
p_CJ[0]);
3341 SpiceInt j2000 = J2000Code;
3349 double stateCJ[6][6];
3350 frmchg_((integer *) &j2000, (integer *) &toFrame, &time, (doublereal *) stateCJ);
3355 SpiceBoolean ckfailure = failed_c();
3359 xpose6_c(stateCJ, stateCJ);
3360 xf2rav_c(stateCJ, (SpiceDouble( *)[3]) &
p_CJ[0], (SpiceDouble *) &
p_av[0]);
3364 refchg_((integer *) &j2000, (integer *) &toFrame, &time, (SpiceDouble *) &
p_CJ[0]);
3368 getmsg_c(
"SHORT",
sizeof(naifstr), naifstr);
3371 if (eqstr_c(naifstr,
"SPICE(UNKNOWNFRAME)")) {
3373 "reference frame code. Has the mission frames kernel been loaded?";
3377 Isis::IString msg =
"No pointing available at requested time [" +
3385 xpose_c((SpiceDouble( *)[3]) &
p_CJ[0], (SpiceDouble( *)[3]) &
p_CJ[0]);
3408 std::vector<double> rtime;
3410 std::vector<double> angles;
3411 angles.push_back(function1.
Evaluate(rtime));
3412 angles.push_back(function2.
Evaluate(rtime));
3413 angles.push_back(function3.
Evaluate(rtime));
3416 if (angles[0] <= -1 * pi_c()) {
3417 angles[0] += twopi_c();
3419 else if (angles[0] > pi_c()) {
3420 angles[0] -= twopi_c();
3443 std::vector<double> rtime;
3445 double angle1 = function1.
Evaluate(rtime);
3446 double angle2 = function2.
Evaluate(rtime);
3447 double angle3 = function3.
Evaluate(rtime);
3450 if (angle1 < -1 * pi_c()) {
3451 angle1 += twopi_c();
3453 else if (angle1 > pi_c()) {
3454 angle1 -= twopi_c();
3457 eul2m_c((SpiceDouble) angle3, (SpiceDouble) angle2, (SpiceDouble) angle1,
3459 (SpiceDouble( *)[3]) &
p_CJ[0]);
3463 ale::Vec3d av = m_orientation->getAngularVelocities()[0];
3485 std::vector<double> cacheAngles(3);
3486 std::vector<double> cacheVelocity(3);
3488 cacheVelocity =
p_av;
3490 std::vector<double> polyAngles(3);
3494 std::vector<double> polyVelocity(3);
3495 polyVelocity =
p_av;
3496 std::vector<double> angles(3);
3498 for (
int index = 0; index < 3; index++) {
3499 angles[index] = cacheAngles[index] + polyAngles[index];
3500 p_av[index] += cacheVelocity[index];
3503 if (angles[0] <= -1 * pi_c()) {
3504 angles[0] += twopi_c();
3506 else if (angles[0] > pi_c()) {
3507 angles[0] -= twopi_c();
3510 if (angles[2] <= -1 * pi_c()) {
3511 angles[2] += twopi_c();
3513 else if (angles[2] > pi_c()) {
3514 angles[2] -= twopi_c();
3517 eul2m_c((SpiceDouble) angles[2], (SpiceDouble) angles[1], (SpiceDouble) angles[0],
3519 (SpiceDouble( *)[3]) &
p_CJ[0]);
3530 double dTime =
p_et / 86400.;
3531 double centTime = dTime / 36525;
3532 double secondsPerJulianCentury = 86400. * 36525.;
3550 for (
int ia = 0; ia < numNutPrec; ia++) {
3553 costheta = cos(theta.
radians());
3554 sintheta = sin(theta.
radians());
3566 if (ra.
radians() < -1 * pi_c()) {
3569 else if (ra.
radians() > pi_c()) {
3573 if (pm.radians() < -1 * pi_c()) {
3576 else if (pm.radians() > pi_c()) {
3582 SpiceDouble delta =
HALFPI - dec.radians();
3583 SpiceDouble w = pm.radians();
3584 SpiceDouble dphi = dra.radians();
3585 SpiceDouble ddelta = -ddec.
radians();
3586 SpiceDouble dw = dpm.
radians();
3589 SpiceDouble angsDangs[6];
3590 SpiceDouble BJs[6][6];
3591 vpack_c(w, delta, phi, angsDangs);
3592 vpack_c(dw, ddelta, dphi, &angsDangs[3]);
3596 xf2rav_c(BJs, (SpiceDouble( *)[3]) &
p_CJ[0], (SpiceDouble *) &
p_av[0]);