File failed to load: https://isis.astrogeology.usgs.gov/9.0.0/Object/assets/jax/output/NativeMML/config.js
Isis 3 Programmer Reference
Spice.cpp
1
5
6/* SPDX-License-Identifier: CC0-1.0 */
7#include "Spice.h"
8
9#include <cfloat>
10#include <iomanip>
11
12#include <QDebug>
13#include <QVector>
14
15#include <getSpkAbCorrState.hpp>
16
17#include <ale/Load.h>
18
19#include <nlohmann/json.hpp>
20using json = nlohmann::json;
21
22
23#include "Constants.h"
24#include "Distance.h"
25#include "EllipsoidShape.h"
26#include "EndianSwapper.h"
27#include "FileName.h"
28#include "IException.h"
29#include "IString.h"
30#include "iTime.h"
31#include "Longitude.h"
32#include "LightTimeCorrectionState.h"
33#include "NaifStatus.h"
34#include "ShapeModel.h"
35#include "SpacecraftPosition.h"
36#include "Target.h"
37#include "Blob.h"
38
39using namespace std;
40
41namespace Isis {
62
63 // TODO: DOCUMENT EVERYTHING
65 Pvl &lab = *cube.label();
66 if (cube.hasBlob("CSMState", "String")) {
67 csmInit(cube, lab);
68 }
69 else {
70 PvlGroup kernels = lab.findGroup("Kernels", Pvl::Traverse);
71 bool hasTables = (kernels["TargetPosition"][0] == "Table");
72 // BONUS TODO: update to pull out separate init methods
73 init(lab, !hasTables);
74 }
75 }
76
77
84 Spice::Spice(Pvl &lab, json isd) {
85 init(lab, true, isd);
86 }
87
88
97 void Spice::csmInit(Cube &cube, Pvl label) {
99 m_target = new Target;
101 }
102
103
109
110 m_et = nullptr;
112
113 m_startTime = new iTime;
114 m_endTime = new iTime;
115 m_cacheSize = new SpiceDouble;
116 *m_cacheSize = 0;
117
118 m_startTimePadding = new SpiceDouble;
120 m_endTimePadding = new SpiceDouble;
121 *m_endTimePadding = 0;
122
123 m_instrumentPosition = nullptr;
124 m_instrumentRotation = nullptr;
125
126 m_sunPosition = nullptr;
127 m_bodyRotation = nullptr;
128
129 m_allowDownsizing = false;
130
131 m_spkCode = nullptr;
132 m_ckCode = nullptr;
133 m_ikCode = nullptr;
134 m_sclkCode = nullptr;
135 m_spkBodyCode = nullptr;
136 m_bodyFrameCode = nullptr;
137 m_target = nullptr;
138 }
139
140
154 void Spice::init(Pvl &lab, bool noTables, json isd) {
156 // Initialize members
157 defaultInit();
158
159 m_spkCode = new SpiceInt;
160 m_ckCode = new SpiceInt;
161 m_ikCode = new SpiceInt;
162 m_sclkCode = new SpiceInt;
163 m_spkBodyCode = new SpiceInt;
164 m_bodyFrameCode = new SpiceInt;
165
166 m_naifKeywords = new PvlObject("NaifKeywords");
167 // m_sky = false;
168
169 // Get the kernel group and load main kernels
170 PvlGroup kernels = lab.findGroup("Kernels", Pvl::Traverse);
171
172 // Get the time padding first
173 if (kernels.hasKeyword("StartPadding")) {
174 *m_startTimePadding = toDouble(kernels["StartPadding"][0]);
175 }
176 else {
177 *m_startTimePadding = 0.0;
178 }
179
180 if (kernels.hasKeyword("EndPadding")) {
181 *m_endTimePadding = toDouble(kernels["EndPadding"][0]);
182 }
183 else {
184 *m_endTimePadding = 0.0;
185 }
186
187 // We should remove this completely in the near future
188 m_usingNaif = !lab.hasObject("NaifKeywords") || noTables;
189 m_usingAle = false;
190
191
192 // Modified to load planetary ephemeris SPKs before s/c SPKs since some
193 // missions (e.g., MESSENGER) may augment the s/c SPK with new planet
194 // ephemerides. (2008-02-27 (KJB))
195 if (m_usingNaif) {
196 try {
197 if (isd == NULL) {
198 // try using ALE
199 std::ostringstream kernel_pvl;
200 kernel_pvl << kernels;
201
202 json props;
203 if (kernels["InstrumentPointing"][0].toUpper() == "NADIR") {
204 props["nadir"] = true;
205 }
206
207 props["kernels"] = kernel_pvl.str();
208
209 isd = ale::load(lab.fileName().toStdString(), props.dump(), "ale", false, false, true);
210 }
211
212 json aleNaifKeywords = isd["naif_keywords"];
213 m_naifKeywords = new PvlObject("NaifKeywords", aleNaifKeywords);
214
215 // Still need to load clock kernels for now
216 load(kernels["LeapSecond"], noTables);
217 if ( kernels.hasKeyword("SpacecraftClock")) {
218 load(kernels["SpacecraftClock"], noTables);
219 }
220 m_usingAle = true;
221 }
222 catch(...) {
223 // Backup to standard ISIS implementation
224 if (noTables) {
225 load(kernels["TargetPosition"], noTables);
226 load(kernels["InstrumentPosition"], noTables);
227 load(kernels["InstrumentPointing"], noTables);
228 }
229
230 if (kernels.hasKeyword("Frame")) {
231 load(kernels["Frame"], noTables);
232 }
233
234 load(kernels["TargetAttitudeShape"], noTables);
235 if (kernels.hasKeyword("Instrument")) {
236 load(kernels["Instrument"], noTables);
237 }
238 // Always load after instrument
239 if (kernels.hasKeyword("InstrumentAddendum")) {
240 load(kernels["InstrumentAddendum"], noTables);
241 }
242
243 // Still need to load clock kernels for now
244 load(kernels["LeapSecond"], noTables);
245 if ( kernels.hasKeyword("SpacecraftClock")) {
246 load(kernels["SpacecraftClock"], noTables);
247 }
248
249 // Modified to load extra kernels last to allow overriding default values
250 // (2010-04-07) (DAC)
251 if (kernels.hasKeyword("Extra")) {
252 load(kernels["Extra"], noTables);
253 }
254 }
255
256 // Moved the construction of the Target after the NAIF kenels have been loaded or the
257 // NAIF keywords have been pulled from the cube labels, so we can find target body codes
258 // that are defined in kernels and not just body codes build into spicelib
259 // TODO: Move this below the else once the rings code below has been refactored
260 m_target = new Target(this, lab);
261
262 // This should not be here. Consider having spiceinit add the necessary rings kernels to the
263 // Extra parameter if the user has set the shape model to RingPlane.
264 // If Target is Saturn and ShapeModel is RingPlane, load the extra rings pck file
265 // which changes the prime meridian values to report longitudes with respect to
266 // the ascending node of the ringplane.
267 if (m_target->name().toUpper() == "SATURN" && m_target->shape()->name().toUpper() == "PLANE") {
268 PvlKeyword ringPck = PvlKeyword("RingPCK","$cassini/kernels/pck/saturnRings_v001.tpc");
269 load(ringPck, noTables);
270 }
271 }
272 else {
273 *m_naifKeywords = lab.findObject("NaifKeywords");
274
275 // Moved the construction of the Target after the NAIF kenels have been loaded or the
276 // NAIF keywords have been pulled from the cube labels, so we can find target body codes
277 // that are defined in kernels and not just body codes build into spicelib
278 // TODO: Move this below the else once the rings code above has been refactored
279
280 m_target = new Target(this, lab);
281 }
282
283 // Get NAIF ik, spk, sclk, and ck codes
284 //
285 // Use ikcode to get parameters from instrument kernel such as focal
286 // length, distortions, focal plane maps, etc
287 //
288 // Use spkcode to get spacecraft position from spk file
289 //
290 // Use sclkcode to transform times from et to tics
291 //
292 // Use ckcode to transform between frames
293 //
294 // Use bodycode to obtain radii and attitude (pole position/omega0)
295 //
296 // Use spkbodycode to read body position from spk
297
298 QString trykey = "NaifIkCode";
299 if (kernels.hasKeyword("NaifFrameCode")) trykey = "NaifFrameCode";
300 *m_ikCode = toInt(kernels[trykey][0]);
301
302 *m_spkCode = *m_ikCode / 1000;
304 *m_ckCode = *m_ikCode;
305
306 if (!m_target->isSky()) {
307 // Get target body code and radii and store them in the Naif group
308 // DAC modified to look for and store body code so that the radii keyword name
309 // will be able to be constructed even for new bodies not in the standard PCK yet.
310 QString radiiKey = "BODY" + Isis::toString(m_target->naifBodyCode()) + "_RADII";
311 QVariant result = m_target->naifBodyCode();
312 storeValue("BODY_CODE", 0, SpiceIntType, result);
313 std::vector<Distance> radii(3,Distance());
314 radii[0] = Distance(getDouble(radiiKey, 0), Distance::Kilometers);
315 radii[1] = Distance(getDouble(radiiKey, 1), Distance::Kilometers);
316 radii[2] = Distance(getDouble(radiiKey, 2), Distance::Kilometers);
317 // m_target doesn't have the getDouble method so Spice gets the radii for it
318 m_target->setRadii(radii);
319 }
320
321 *m_spkBodyCode = m_target->naifBodyCode();
322
323 // Override them if they exist in the labels
324 if (kernels.hasKeyword("NaifSpkCode")) {
325 *m_spkCode = (int) kernels["NaifSpkCode"];
326 }
327
328 if (kernels.hasKeyword("NaifCkCode")) {
329 *m_ckCode = (int) kernels["NaifCkCode"];
330 }
331
332 if (kernels.hasKeyword("NaifSclkCode")) {
333 *m_sclkCode = (int) kernels["NaifSclkCode"];
334 }
335
336 if (!m_target->isSky()) {
337 if (kernels.hasKeyword("NaifSpkBodyCode")) {
338 *m_spkBodyCode = (int) kernels["NaifSpkBodyCode"];
339 }
340 }
341
342 if (m_target->isSky()) {
343 // Create the identity rotation for sky targets
344 // Everything in bodyfixed will really be J2000
346 }
347 else {
348 // JAA - Modified to store and look for the frame body code in the cube labels
349 SpiceInt frameCode;
350 if (((m_usingNaif) || (!m_naifKeywords->hasKeyword("BODY_FRAME_CODE"))) && !isUsingAle()) {
351 char frameName[32];
352 SpiceBoolean found;
353 cidfrm_c(*m_spkBodyCode, sizeof(frameName), &frameCode, frameName, &found);
354
355 if (!found) {
356 QString naifTarget = "IAU_" + m_target->name().toUpper();
357 namfrm_c(naifTarget.toLatin1().data(), &frameCode);
358 if (frameCode == 0) {
359 QString msg = "Can not find NAIF BODY_FRAME_CODE for target ["
360 + m_target->name() + "]";
361 throw IException(IException::Io, msg, _FILEINFO_);
362 }
363 }
364
365 QVariant result = (int)frameCode;
366 storeValue("BODY_FRAME_CODE", 0, SpiceIntType, result);
367 }
368 else {
369 try {
370 frameCode = getInteger("BODY_FRAME_CODE", 0);
371 }
372 catch(IException &e) {
373 QString msg = "Unable to read BODY_FRAME_CODE from naifkeywords group";
374 throw IException(IException::Io, msg, _FILEINFO_);
375 }
376 }
377
378 m_bodyRotation = new SpiceRotation(frameCode);
379 *m_bodyFrameCode = frameCode;
380 }
381
383
384 // Set up for observer/target and light time correction to between s/c
385 // and target body.
386 LightTimeCorrectionState ltState(*m_ikCode, this);
388
389 vector<Distance> radius = m_target->radii();
390 Distance targetRadius((radius[0] + radius[2])/2.0);
392 ltState, targetRadius);
393
394 m_sunPosition = new SpicePosition(10, m_target->naifBodyCode());
395
396
397 // Check to see if we have nadir pointing that needs to be computed &
398 // See if we have table blobs to load
399 if (m_usingAle) {
400 m_sunPosition->LoadCache(isd["sun_position"]);
401 if (m_sunPosition->cacheSize() > 3) {
402 m_sunPosition->Memcache2HermiteCache(0.01);
403 }
404 m_bodyRotation->LoadCache(isd["body_rotation"]);
406 if (m_bodyRotation->cacheSize() > 5) {
407 m_bodyRotation->LoadTimeCache();
408 }
410 }
411 else if (kernels["TargetPosition"][0].toUpper() == "TABLE") {
412 Table t("SunPosition", lab.fileName(), lab);
413 m_sunPosition->LoadCache(t);
414
415 Table t2("BodyRotation", lab.fileName(), lab);
416 m_bodyRotation->LoadCache(t2);
417 if (t2.Label().hasKeyword("SolarLongitude")) {
418 *m_solarLongitude = Longitude(t2.Label()["SolarLongitude"],
420 }
421 else {
423 }
424 }
425
426 // We can't assume InstrumentPointing & InstrumentPosition exist, old
427 // files may be around with the old keywords, SpacecraftPointing &
428 // SpacecraftPosition. The old keywords were in existance before the
429 // Table option, so we don't need to check for Table under the old
430 // keywords.
431
432 if (kernels["InstrumentPointing"].size() == 0) {
434 "No camera pointing available",
435 _FILEINFO_);
436 }
437
438 // 2009-03-18 Tracie Sucharski - Removed test for old keywords, any files
439 // with the old keywords should be re-run through spiceinit.
440 if (kernels["InstrumentPointing"][0].toUpper() == "NADIR" && !isUsingAle()) {
444 }
445
447 }
448 else if (m_usingAle) {
449 m_instrumentRotation->LoadCache(isd["instrument_pointing"]);
451 if (m_instrumentRotation->cacheSize() > 5) {
452 m_instrumentRotation->LoadTimeCache();
453 }
454 }
455 else if (kernels["InstrumentPointing"][0].toUpper() == "TABLE") {
456 Table t("InstrumentPointing", lab.fileName(), lab);
457 m_instrumentRotation->LoadCache(t);
458 }
459
460
461 if (kernels["InstrumentPosition"].size() == 0) {
463 "No instrument position available",
464 _FILEINFO_);
465 }
466
467 if (m_usingAle) {
468 m_instrumentPosition->LoadCache(isd["instrument_position"]);
469 }
470 else if (kernels["InstrumentPosition"][0].toUpper() == "TABLE") {
471 Table t("InstrumentPosition", lab.fileName(), lab);
472 m_instrumentPosition->LoadCache(t);
473 }
475 }
476
477
486 void Spice::load(PvlKeyword &key, bool noTables) {
488
489 for (int i = 0; i < key.size(); i++) {
490 if (key[i] == "") continue;
491 if (key[i].toUpper() == "NULL") break;
492 if (key[i].toUpper() == "NADIR") break;
493 if (key[i].toUpper() == "TABLE" && !noTables) break;
494 if (key[i].toUpper() == "TABLE" && noTables) continue;
495 FileName file(key[i]);
496 if (!file.fileExists()) {
497 QString msg = "Spice file does not exist [" + file.expanded() + "]";
498 throw IException(IException::Io, msg, _FILEINFO_);
499 }
500 QString fileName = file.expanded();
501 furnsh_c(fileName.toLatin1().data());
502 m_kernels->push_back(key[i]);
503 }
504
506 }
507
513
514 if (m_solarLongitude != NULL) {
515 delete m_solarLongitude;
516 m_solarLongitude = NULL;
517 }
518
519 if (m_et != NULL) {
520 delete m_et;
521 m_et = NULL;
522 }
523
524 if (m_startTime != NULL) {
525 delete m_startTime;
526 m_startTime = NULL;
527 }
528
529 if (m_endTime != NULL) {
530 delete m_endTime;
531 m_endTime = NULL;
532 }
533
534 if (m_cacheSize != NULL) {
535 delete m_cacheSize;
536 m_cacheSize = NULL;
537 }
538
539 if (m_startTimePadding != NULL) {
540 delete m_startTimePadding;
541 m_startTimePadding = NULL;
542 }
543
544 if (m_endTimePadding != NULL) {
545 delete m_endTimePadding;
546 m_endTimePadding = NULL;
547 }
548
549 if (m_instrumentPosition != NULL) {
552 }
553
554 if (m_instrumentRotation != NULL) {
557 }
558
559 if (m_sunPosition != NULL) {
560 delete m_sunPosition;
561 m_sunPosition = NULL;
562 }
563
564 if (m_bodyRotation != NULL) {
565 delete m_bodyRotation;
566 m_bodyRotation = NULL;
567 }
568
569 if (m_spkCode != NULL) {
570 delete m_spkCode;
571 m_spkCode = NULL;
572 }
573
574 if (m_ckCode != NULL) {
575 delete m_ckCode;
576 m_ckCode = NULL;
577 }
578
579 if (m_ikCode != NULL) {
580 delete m_ikCode;
581 m_ikCode = NULL;
582 }
583
584 if (m_sclkCode != NULL) {
585 delete m_sclkCode;
586 m_sclkCode = NULL;
587 }
588
589 if (m_spkBodyCode != NULL) {
590 delete m_spkBodyCode;
591 m_spkBodyCode = NULL;
592 }
593
594 if (m_bodyFrameCode != NULL) {
595 delete m_bodyFrameCode;
596 m_bodyFrameCode = NULL;
597 }
598
599 if (m_target != NULL) {
600 delete m_target;
601 m_target = NULL;
602 }
603
604 // Unload the kernels (TODO: Can this be done faster)
605 for (int i = 0; m_kernels && i < m_kernels->size(); i++) {
606 FileName file(m_kernels->at(i));
607 QString fileName = file.expanded();
608 unload_c(fileName.toLatin1().data());
609 }
610
611 if (m_kernels != NULL) {
612 delete m_kernels;
613 m_kernels = NULL;
614 }
616 }
617
649 void Spice::createCache(iTime startTime, iTime endTime,
650 int cacheSize, double tol) {
652
653 // Check for errors
654 if (cacheSize <= 0) {
655 QString msg = "Argument cacheSize must be greater than zero";
656 throw IException(IException::Programmer, msg, _FILEINFO_);
657 }
658
659 if (startTime > endTime) {
660 QString msg = "Argument startTime must be less than or equal to endTime";
661 throw IException(IException::Programmer, msg, _FILEINFO_);
662 }
663
664 if (*m_cacheSize > 0) {
665 QString msg = "A cache has already been created";
666 throw IException(IException::Programmer, msg, _FILEINFO_);
667 }
668
669 if (cacheSize == 1 && (*m_startTimePadding != 0 || *m_endTimePadding != 0)) {
670 QString msg = "This instrument does not support time padding";
671 throw IException(IException::User, msg, _FILEINFO_);
672 }
673
674 string abcorr;
675 if (getSpkAbCorrState(abcorr)) {
677 }
678
679 iTime avgTime((startTime.Et() + endTime.Et()) / 2.0);
680 computeSolarLongitude(avgTime);
681
682 // Cache everything
683 if (!m_bodyRotation->IsCached()) {
684 int bodyRotationCacheSize = cacheSize;
685 if (cacheSize > 2) bodyRotationCacheSize = 2;
686 m_bodyRotation->LoadCache(
687 startTime.Et() - *m_startTimePadding,
688 endTime.Et() + *m_endTimePadding,
689 bodyRotationCacheSize);
690 }
691
693 if (cacheSize > 3) m_instrumentRotation->MinimizeCache(SpiceRotation::Yes);
694 m_instrumentRotation->LoadCache(
695 startTime.Et() - *m_startTimePadding,
696 endTime.Et() + *m_endTimePadding,
697 cacheSize);
698 }
699
701 m_instrumentPosition->LoadCache(
702 startTime.Et() - *m_startTimePadding,
703 endTime.Et() + *m_endTimePadding,
704 cacheSize);
705 if (cacheSize > 3) m_instrumentPosition->Memcache2HermiteCache(tol);
706 }
707 else if (m_instrumentPosition->GetSource() == SpicePosition::Memcache && m_instrumentPosition->HasVelocity() && isUsingAle()) {
708 int aleCacheSize = m_instrumentPosition->cacheSize();
709 if (aleCacheSize > 3) {
710 m_instrumentPosition->Memcache2HermiteCache(tol);
711 }
712 }
713
714
715 if (!m_sunPosition->IsCached()) {
716 int sunPositionCacheSize = cacheSize;
717 if (cacheSize > 2) sunPositionCacheSize = 2;
718 m_sunPosition->LoadCache(
719 startTime.Et() - *m_startTimePadding,
720 endTime.Et() + *m_endTimePadding,
721 sunPositionCacheSize);
722 }
723
724 // Save the time and cache size
725 *m_startTime = startTime;
726 *m_endTime = endTime;
727 *m_cacheSize = cacheSize;
728 m_et = NULL;
729
730 // Unload the kernels (TODO: Can this be done faster)
731 for (int i = 0; i < m_kernels->size(); i++) {
732 FileName file(m_kernels->at(i));
733 QString fileName = file.expanded();
734 unload_c(fileName.toLatin1().data());
735 }
736
737 m_kernels->clear();
738
740 }
741
742
751 if (m_startTime) {
752 return *m_startTime;
753 }
754
755 return iTime();
756 }
757
766 if (m_endTime) {
767 return *m_endTime;
768 }
769
770 return iTime();
771 }
772
787 void Spice::setTime(const iTime &et) {
788
789 if (m_et == NULL) {
790 m_et = new iTime();
791
792 // Before the Spice is cached, but after the camera aberration correction
793 // is set, check to see if the instrument position kernel was created
794 // by spkwriter. If so turn off aberration corrections because the camera
795 // set aberration corrections are included in the spk already.
796 string abcorr;
797 if (*m_cacheSize == 0) {
798 if (m_startTime->Et() == 0.0 && m_endTime->Et() == 0.0
799 && getSpkAbCorrState(abcorr)) {
801 }
802 }
803 }
804
805 *m_et = et;
806
807 m_bodyRotation->SetEphemerisTime(et.Et());
808 m_instrumentRotation->SetEphemerisTime(et.Et());
809 m_instrumentPosition->SetEphemerisTime(et.Et());
810 m_sunPosition->SetEphemerisTime(et.Et());
811
812 std::vector<double> uB = m_bodyRotation->ReferenceVector(m_sunPosition->Coordinate());
813 m_uB[0] = uB[0];
814 m_uB[1] = uB[1];
815 m_uB[2] = uB[2];
816
818 }
819
829 void Spice::instrumentPosition(double p[3]) const {
831 }
832
842 void Spice::instrumentBodyFixedPosition(double p[3]) const {
843 if (m_et == NULL) {
844 QString msg = "Unable to retrieve instrument's body fixed position."
845 " Spice::SetTime must be called first.";
846 throw IException(IException::Programmer, msg, _FILEINFO_);
847 }
848
849 std::vector<double> sB = m_bodyRotation->ReferenceVector(m_instrumentPosition->Coordinate());
850 p[0] = sB[0];
851 p[1] = sB[1];
852 p[2] = sB[2];
853 }
854
860 void Spice::instrumentBodyFixedVelocity(double v[3]) const {
861 if (m_et == NULL) {
862 QString msg = "Unable to retrieve instrument's body fixed velocity."
863 " Spice::SetTime must be called first.";
864 throw IException(IException::Programmer, msg, _FILEINFO_);
865 }
866
867 std::vector<double> state;
868 state.push_back(m_instrumentPosition->Coordinate()[0]);
869 state.push_back(m_instrumentPosition->Coordinate()[1]);
870 state.push_back(m_instrumentPosition->Coordinate()[2]);
871 state.push_back(m_instrumentPosition->Velocity()[0]);
872 state.push_back(m_instrumentPosition->Velocity()[1]);
873 state.push_back(m_instrumentPosition->Velocity()[2]);
874
875 std::vector<double> vB = m_bodyRotation->ReferenceVector(state);
876 v[0] = vB[3];
877 v[1] = vB[4];
878 v[2] = vB[5];
879 }
880
881
892 if (m_et == NULL) {
893 QString msg = "Unable to retrieve the time."
894 " Spice::SetTime must be called first.";
895 throw IException(IException::Programmer, msg, _FILEINFO_);
896 }
897 return *m_et;
898 }
899
900
909 void Spice::sunPosition(double p[3]) const {
910 if (m_et == NULL) {
911 QString msg = "Unable to retrieve sun's position."
912 " Spice::SetTime must be called first.";
913 throw IException(IException::Programmer, msg, _FILEINFO_);
914 }
915 p[0] = m_uB[0];
916 p[1] = m_uB[1];
917 p[2] = m_uB[2];
918 }
919
926 std::vector<double> sB = m_bodyRotation->ReferenceVector(m_instrumentPosition->Coordinate());
927 return sqrt(pow(sB[0], 2) + pow(sB[1], 2) + pow(sB[2], 2));
928 }
929
937 void Spice::radii(Distance r[3]) const {
938 for (int i = 0; i < 3; i++)
939 r[i] =m_target->radii()[i];
940 }
941
948 SpiceInt Spice::naifBodyCode() const {
949 return (int) m_target->naifBodyCode();
950 }
951
957 SpiceInt Spice::naifSpkCode() const {
958 return *m_spkCode;
959 }
960
966 SpiceInt Spice::naifCkCode() const {
967 return *m_ckCode;
968 }
969
975 SpiceInt Spice::naifIkCode() const {
976 return *m_ikCode;
977 }
978
985 SpiceInt Spice::naifSclkCode() const {
986 return *m_sclkCode;
987 }
988
996 SpiceInt Spice::naifBodyFrameCode() const {
997 return *m_bodyFrameCode;
998 }
999
1000
1008
1009
1017 return 1.0;
1018 };
1019
1020
1032 SpiceInt Spice::getInteger(const QString &key, int index) {
1033 return readValue(key, SpiceIntType, index).toInt();
1034 }
1035
1046 SpiceDouble Spice::getDouble(const QString &key, int index) {
1047 return readValue(key, SpiceDoubleType, index).toDouble();
1048 }
1049
1050
1060 iTime Spice::getClockTime(QString clockValue, int sclkCode, bool clockTicks) {
1061 if (sclkCode == -1) {
1062 sclkCode = naifSclkCode();
1063 }
1064
1065 iTime result;
1066
1067 QString key = "CLOCK_ET_" + Isis::toString(sclkCode) + "_" + clockValue;
1068 QVariant storedClockTime = getStoredResult(key, SpiceDoubleType);
1069
1070 if (storedClockTime.isNull()) {
1071 SpiceDouble timeOutput;
1073 if (clockTicks) {
1074 sct2e_c(sclkCode, (SpiceDouble) clockValue.toDouble(), &timeOutput);
1075 }
1076 else {
1077 scs2e_c(sclkCode, clockValue.toLatin1().data(), &timeOutput);
1078 }
1080 storedClockTime = timeOutput;
1081 storeResult(key, SpiceDoubleType, timeOutput);
1082 }
1083
1084 result = storedClockTime.toDouble();
1085
1086 return result;
1087 }
1088
1089
1100 QVariant Spice::readValue(QString key, SpiceValueType type, int index) {
1101 QVariant result;
1102
1103 if (m_usingNaif && !m_usingAle) {
1105
1106 // This is the success status of the naif call
1107 SpiceBoolean found = false;
1108
1109 // Naif tells us how many values were read, but we always just read one.
1110 // Use this variable to make naif happy.
1111 SpiceInt numValuesRead;
1112
1113 if (type == SpiceDoubleType) {
1114 SpiceDouble kernelValue;
1115 gdpool_c(key.toLatin1().data(), (SpiceInt)index, 1,
1116 &numValuesRead, &kernelValue, &found);
1117
1118 if (found && numValuesRead > 0)
1119 result = kernelValue;
1120 }
1121 else if (type == SpiceStringType) {
1122 char kernelValue[512];
1123 gcpool_c(key.toLatin1().data(), (SpiceInt)index, 1, sizeof(kernelValue),
1124 &numValuesRead, kernelValue, &found);
1125
1126 if (found && numValuesRead > 0)
1127 result = kernelValue;
1128 }
1129 else if (type == SpiceIntType) {
1130 SpiceInt kernelValue;
1131 gipool_c(key.toLatin1().data(), (SpiceInt)index, 1, &numValuesRead,
1132 &kernelValue, &found);
1133
1134 if (found && numValuesRead > 0)
1135 result = (int)kernelValue;
1136 }
1137
1138 if (!found) {
1139 QString msg = "Can not find [" + key + "] in text kernels";
1140 throw IException(IException::Io, msg, _FILEINFO_);
1141 }
1142 else if (numValuesRead == 0){
1143 QString msg = "Found " + key + "] in text kernels, but no values were identified and read.";
1144 throw IException(IException::Io, msg, _FILEINFO_);
1145 }
1146
1147 storeValue(key, index, type, result);
1149 }
1150 else {
1151 // Read from PvlObject that is our naif keywords
1152 result = readStoredValue(key, type, index);
1153
1154 if (result.isNull()) {
1155 QString msg = "The camera is requesting spice data [" + key + "] that "
1156 "was not attached, please re-run spiceinit";
1157 throw IException(IException::Unknown, msg, _FILEINFO_);
1158 }
1159 }
1160
1161 return result;
1162 }
1163
1164
1165 void Spice::storeResult(QString name, SpiceValueType type, QVariant value) {
1166 if (type == SpiceDoubleType) {
1167 EndianSwapper swapper("LSB");
1168
1169 double doubleVal = value.toDouble();
1170 doubleVal = swapper.Double(&doubleVal);
1171 QByteArray byteCode((char *) &doubleVal, sizeof(double));
1172 value = byteCode;
1173 type = SpiceByteCodeType;
1174 }
1175
1176 storeValue(name + "_COMPUTED", 0, type, value);
1177 }
1178
1179
1180 QVariant Spice::getStoredResult(QString name, SpiceValueType type) {
1181 bool wasDouble = false;
1182
1183 if (type == SpiceDoubleType) {
1184 wasDouble = true;
1185 type = SpiceByteCodeType;
1186 }
1187
1188 QVariant stored = readStoredValue(name + "_COMPUTED", type, 0);
1189
1190 if (wasDouble && !stored.isNull()) {
1191 EndianSwapper swapper("LSB");
1192 double doubleVal = swapper.Double((void *)QByteArray::fromHex(
1193 stored.toByteArray()).data());
1194 stored = doubleVal;
1195 }
1196
1197 return stored;
1198 }
1199
1200
1201 void Spice::storeValue(QString key, int index, SpiceValueType type,
1202 QVariant value) {
1203 if (!m_naifKeywords->hasKeyword(key)) {
1204 m_naifKeywords->addKeyword(PvlKeyword(key));
1205 }
1206
1207 PvlKeyword &storedKey = m_naifKeywords->findKeyword(key);
1208
1209 while(index >= storedKey.size()) {
1210 storedKey.addValue("");
1211 }
1212
1213 if (type == SpiceByteCodeType) {
1214 storedKey[index] = QString(value.toByteArray().toHex().data());
1215 }
1216 else if (type == SpiceStringType) {
1217 storedKey[index] = value.toString();
1218 }
1219 else if (type == SpiceDoubleType) {
1220 storedKey[index] = toString(value.toDouble());
1221 }
1222 else if (type == SpiceIntType) {
1223 storedKey[index] = toString(value.toInt());
1224 }
1225 else {
1226 QString msg = "Unable to store variant in labels for key [" + key + "]";
1227 throw IException(IException::Unknown, msg, _FILEINFO_);
1228 }
1229 }
1230
1231
1232 QVariant Spice::readStoredValue(QString key, SpiceValueType type,
1233 int index) {
1234 // Read from PvlObject that is our naif keywords
1235 QVariant result;
1236
1237 if (m_naifKeywords->hasKeyword(key) && (!m_usingNaif || m_usingAle)) {
1238 PvlKeyword &storedKeyword = m_naifKeywords->findKeyword(key);
1239
1240 try {
1241 if (type == SpiceDoubleType) {
1242 result = toDouble(storedKeyword[index]);
1243 }
1244 else if (type == SpiceStringType) {
1245 result = storedKeyword[index];
1246 }
1247 else if (type == SpiceByteCodeType || SpiceStringType) {
1248 result = storedKeyword[index].toLatin1();
1249 }
1250 else if (type == SpiceIntType) {
1251 result = toInt(storedKeyword[index]);
1252 }
1253 }
1254 catch(IException &e) {
1255 e.print();
1256 }
1257 }
1258
1259 return result;
1260 }
1261
1273 QString Spice::getString(const QString &key, int index) {
1274 return readValue(key, SpiceStringType, index).toString();
1275 }
1276
1277
1290 void Spice::subSpacecraftPoint(double &lat, double &lon) {
1292
1293 if (m_et == NULL) {
1294 QString msg = "Unable to retrieve subspacecraft position."
1295 " Spice::SetTime must be called first.";
1296 throw IException(IException::Programmer, msg, _FILEINFO_);
1297 }
1298
1299 SpiceDouble usB[3], dist;
1300 std::vector<double> vsB = m_bodyRotation->ReferenceVector(m_instrumentPosition->Coordinate());
1301 SpiceDouble sB[3];
1302 sB[0] = vsB[0];
1303 sB[1] = vsB[1];
1304 sB[2] = vsB[2];
1305 unorm_c(sB, usB, &dist);
1306
1307 std::vector<Distance> radii = target()->radii();
1308 SpiceDouble a = radii[0].kilometers();
1309 SpiceDouble b = radii[1].kilometers();
1310 SpiceDouble c = radii[2].kilometers();
1311
1312 SpiceDouble originB[3];
1313 originB[0] = originB[1] = originB[2] = 0.0;
1314
1315 SpiceBoolean found;
1316 SpiceDouble subB[3];
1317
1318 surfpt_c(originB, usB, a, b, c, subB, &found);
1319
1320 SpiceDouble mylon, mylat;
1321 reclat_c(subB, &a, &mylon, &mylat);
1322 lat = mylat * 180.0 / PI;
1323 lon = mylon * 180.0 / PI;
1324 if (lon < 0.0) lon += 360.0;
1325
1327 }
1328
1329
1341 void Spice::subSolarPoint(double &lat, double &lon) {
1343
1344 if (m_et == NULL) {
1345 QString msg = "Unable to retrieve subsolar point."
1346 " Spice::SetTime must be called first.";
1347 throw IException(IException::Programmer, msg, _FILEINFO_);
1348 }
1349
1350 SpiceDouble uuB[3], dist;
1351 unorm_c(m_uB, uuB, &dist);
1352 std::vector<Distance> radii = target()->radii();
1353
1354 SpiceDouble a = radii[0].kilometers();
1355 SpiceDouble b = radii[1].kilometers();
1356 SpiceDouble c = radii[2].kilometers();
1357
1358 SpiceDouble originB[3];
1359 originB[0] = originB[1] = originB[2] = 0.0;
1360
1361 SpiceBoolean found;
1362 SpiceDouble subB[3];
1363 surfpt_c(originB, uuB, a, b, c, subB, &found);
1364
1365 SpiceDouble mylon, mylat;
1366 reclat_c(subB, &a, &mylon, &mylat);
1367
1368 lat = mylat * 180.0 / PI;
1369 lon = mylon * 180.0 / PI;
1370 if (lon < 0.0) lon += 360.0;
1372 }
1373
1374
1381 return m_target;
1382 }
1383
1384
1390 QString Spice::targetName() const {
1391 return m_target->name();
1392 }
1393
1394
1395 double Spice::sunToBodyDist() const {
1396 std::vector<double> sunPosition = m_sunPosition->Coordinate();
1397 std::vector<double> bodyRotation = m_bodyRotation->Matrix();
1398
1399 double sunPosFromTarget[3];
1400 mxv_c(&bodyRotation[0], &sunPosition[0], sunPosFromTarget);
1401
1402 return vnorm_c(sunPosFromTarget);
1403 }
1404
1405
1414
1415 if (m_target->isSky()) {
1417 return;
1418 }
1419
1420 if (m_usingAle || !m_usingNaif) {
1421 double og_time = m_bodyRotation->EphemerisTime();
1422 m_bodyRotation->SetEphemerisTime(et.Et());
1423 m_sunPosition->SetEphemerisTime(et.Et());
1424
1425 std::vector<double> bodyRotMat = m_bodyRotation->Matrix();
1426 std::vector<double> sunPos = m_sunPosition->Coordinate();
1427 std::vector<double> sunVel = m_sunPosition->Velocity();
1428 double sunAv[3];
1429
1430 ucrss_c(&sunPos[0], &sunVel[0], sunAv);
1431
1432 double npole[3];
1433 for (int i = 0; i < 3; i++) {
1434 npole[i] = bodyRotMat[6+i];
1435 }
1436
1437 double x[3], y[3], z[3];
1438 vequ_c(sunAv, z);
1439 ucrss_c(npole, z, x);
1440 ucrss_c(z, x, y);
1441
1442 double trans[3][3];
1443 for (int i = 0; i < 3; i++) {
1444 trans[0][i] = x[i];
1445 trans[1][i] = y[i];
1446 trans[2][i] = z[i];
1447 }
1448
1449 double pos[3];
1450 mxv_c(trans, &sunPos[0], pos);
1451
1452 double radius, ls, lat;
1453 reclat_c(pos, &radius, &ls, &lat);
1454
1456
1458 m_bodyRotation->SetEphemerisTime(og_time);
1459 m_sunPosition->SetEphemerisTime(og_time);
1460 return;
1461 }
1462
1463 if (m_bodyRotation->IsCached()) return;
1464
1465 double tipm[3][3], npole[3];
1466 char frameName[32];
1467 SpiceInt frameCode;
1468 SpiceBoolean found;
1469
1470 cidfrm_c(*m_spkBodyCode, sizeof(frameName), &frameCode, frameName, &found);
1471
1472 if (found) {
1473 pxform_c("J2000", frameName, et.Et(), tipm);
1474 }
1475 else {
1476 tipbod_c("J2000", *m_spkBodyCode, et.Et(), tipm);
1477 }
1478
1479 for (int i = 0; i < 3; i++) {
1480 npole[i] = tipm[2][i];
1481 }
1482
1483 double state[6], lt;
1484 spkez_c(*m_spkBodyCode, et.Et(), "J2000", "NONE", 10, state, &lt);
1485
1486 double uavel[3];
1487 ucrss_c(state, &state[3], uavel);
1488
1489 double x[3], y[3], z[3];
1490 vequ_c(uavel, z);
1491 ucrss_c(npole, z, x);
1492 ucrss_c(z, x, y);
1493
1494 double trans[3][3];
1495 for (int i = 0; i < 3; i++) {
1496 trans[0][i] = x[i];
1497 trans[1][i] = y[i];
1498 trans[2][i] = z[i];
1499 }
1500
1501 spkez_c(10, et.Et(), "J2000", "LT+S", *m_spkBodyCode, state, &lt);
1502
1503 double pos[3];
1504 mxv_c(trans, state, pos);
1505
1506 double radius, ls, lat;
1507 reclat_c(pos, &radius, &ls, &lat);
1508
1510
1512
1513 }
1514
1515
1522 if (m_et) {
1524 return *m_solarLongitude;
1525 }
1526
1527 return Longitude();
1528 }
1529
1530
1539
1540 // Get the kernel group and check main kernels
1541 PvlGroup kernels = lab.findGroup("Kernels", Pvl::Traverse);
1542 std::vector<string> keywords;
1543 keywords.push_back("TargetPosition");
1544
1545 if (kernels.hasKeyword("SpacecraftPosition")) {
1546 keywords.push_back("SpacecraftPosition");
1547 }
1548 else {
1549 keywords.push_back("InstrumentPosition");
1550 }
1551
1552 if (kernels.hasKeyword("SpacecraftPointing")) {
1553 keywords.push_back("SpacecraftPointing");
1554 }
1555 else {
1556 keywords.push_back("InstrumentPointing");
1557 }
1558
1559 if (kernels.hasKeyword("Frame")) {
1560 keywords.push_back("Frame");
1561 }
1562
1563 if (kernels.hasKeyword("Extra")) {
1564 keywords.push_back("Extra");
1565 }
1566
1567 PvlKeyword key;
1568 for (int ikey = 0; ikey < (int) keywords.size(); ikey++) {
1569 key = kernels[ikey];
1570
1571 for (int i = 0; i < key.size(); i++) {
1572 if (key[i] == "") return false;
1573 if (key[i].toUpper() == "NULL") return false;
1574 if (key[i].toUpper() == "NADIR") return false;
1575 if (key[i].toUpper() == "TABLE") return false;
1576 }
1577 }
1578 return true;
1579 }
1580
1581
1590 return !(m_et == NULL);
1591 }
1592
1593
1602 return m_sunPosition;
1603 }
1604
1615
1624 return m_bodyRotation;
1625 }
1626
1637
1638 bool Spice::isUsingAle(){
1639 return m_usingAle;
1640 }
1641}
@ Degrees
Degrees are generally considered more human readable, 0-360 is one circle, however most math does not...
Definition Angle.h:56
@ Radians
Radians are generally used in mathematical equations, 0-2*PI is one circle, however these are more di...
Definition Angle.h:63
IO Handler for Isis Cubes.
Definition Cube.h:168
bool hasBlob(const QString &name, const QString &type)
Check to see if the cube contains a BLOB.
Definition Cube.cpp:2052
Pvl * label() const
Returns a pointer to the IsisLabel object associated with the cube.
Definition Cube.cpp:1734
Distance measurement, usually in meters.
Definition Distance.h:34
@ Kilometers
The distance is being specified in kilometers.
Definition Distance.h:45
File name manipulation and expansion.
Definition FileName.h:100
bool fileExists() const
Returns true if the file exists; false otherwise.
Definition FileName.cpp:449
QString expanded() const
Returns a QString of the full file name including the file path, excluding the attributes.
Definition FileName.cpp:196
Isis exception class.
Definition IException.h:91
@ Unknown
A type of error that cannot be classified as any of the other error types.
Definition IException.h:118
@ User
A type of error that could only have occurred due to a mistake on the user's part (e....
Definition IException.h:126
@ Programmer
This error is for when a programmer made an API call that was illegal.
Definition IException.h:146
@ Io
A type of error that occurred when performing an actual I/O operation.
Definition IException.h:155
Provides interface to user configurable Light Time correction feature.
bool checkSpkKernelsForAberrationCorrection()
Check for light time/stellar aberration tag in SPK comments.
This class is designed to encapsulate the concept of a Longitude.
Definition Longitude.h:40
Longitude force360Domain() const
This returns a longitude that is constricted to 0-360 degrees.
static void CheckErrors(bool resetNaif=true)
This method looks for any naif errors that might have occurred.
bool hasKeyword(const QString &name) const
Check to see if a keyword exists.
QString fileName() const
Returns the filename used to initialise the Pvl object.
Contains multiple PvlContainers.
Definition PvlGroup.h:41
Container for cube-like labels.
Definition Pvl.h:119
A single keyword-value pair.
Definition PvlKeyword.h:87
int size() const
Returns the number of values stored in this keyword.
Definition PvlKeyword.h:133
Contains Pvl Groups and Pvl Objects.
Definition PvlObject.h:61
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 ...
bool hasObject(const QString &name) const
Returns a boolean value based on whether the object exists in the current PvlObject or not.
Definition PvlObject.h:323
PvlObjectIterator findObject(const QString &name, PvlObjectIterator beg, PvlObjectIterator end)
Find the index of object with a specified name, between two indexes.
Definition PvlObject.h:274
@ Traverse
Search child objects.
Definition PvlObject.h:158
PvlGroupIterator findGroup(const QString &name, PvlGroupIterator beg, PvlGroupIterator end)
Find a group with the specified name, within these indexes.
Definition PvlObject.h:129
Provides swap observer/target and improved light time correction.
virtual void setTime(const iTime &time)
Sets the ephemeris time and reads the spacecraft and sun position from the kernels at that instant in...
Definition Spice.cpp:787
QString getString(const QString &key, int index=0)
This returns a value from the NAIF text pool.
Definition Spice.cpp:1273
virtual iTime getClockTime(QString clockValue, int sclkCode=-1, bool clockTicks=false)
This converts the spacecraft clock ticks value (clockValue) to an iTime.
Definition Spice.cpp:1060
SpiceDouble * m_startTimePadding
Kernels pvl group StartPadding keyword value.
Definition Spice.h:403
Target * m_target
Target of the observation.
Definition Spice.h:381
bool m_usingNaif
Indicates whether we are reading values from the NaifKeywords PvlObject in cube.
Definition Spice.h:429
QVariant readValue(QString key, SpiceValueType type, int index=0)
This should be used for reading ALL text naif kernel values.
Definition Spice.cpp:1100
Longitude * m_solarLongitude
Body rotation solar longitude value.
Definition Spice.h:383
bool m_usingAle
Indicate whether we are reading values from an ISD returned from ALE.
Definition Spice.h:432
virtual Longitude solarLongitude()
Returns the solar longitude.
Definition Spice.cpp:1521
Spice(Cube &cube)
Constructs a Spice object and loads SPICE kernels using information from the label object.
Definition Spice.cpp:64
SpiceInt * m_ikCode
Instrument kernel (IK) code.
Definition Spice.h:420
virtual void instrumentBodyFixedVelocity(double v[3]) const
Returns the spacecraft velocity in body-fixed frame km/sec units.
Definition Spice.cpp:860
SpiceRotation * m_instrumentRotation
Instrument spice rotation.
Definition Spice.h:407
SpiceInt * m_sclkCode
Spacecraft clock correlation kernel (SCLK) code.
Definition Spice.h:421
void csmInit(Cube &cube, Pvl label)
Initialize the Spice object for a CSMCamera.
Definition Spice.cpp:97
virtual void computeSolarLongitude(iTime et)
Computes the solar longitude for the given ephemeris time.
Definition Spice.cpp:1412
SpicePosition * m_instrumentPosition
Instrument spice position.
Definition Spice.h:406
bool m_allowDownsizing
Indicates whether to allow downsizing.
Definition Spice.h:411
SpiceDouble * m_endTimePadding
Kernels pvl group EndPadding keyword value.
Definition Spice.h:404
SpicePosition * m_sunPosition
Sun spice position.
Definition Spice.h:408
SpiceInt * m_bodyFrameCode
Naif's BODY_FRAME_CODE value.
Definition Spice.h:423
virtual SpiceRotation * bodyRotation() const
Accessor method for the body rotation.
Definition Spice.cpp:1623
virtual double targetCenterDistance() const
Calculates and returns the distance from the spacecraft to the target center.
Definition Spice.cpp:925
virtual void subSolarPoint(double &lat, double &lon)
Returns the sub-solar latitude/longitude in universal coordinates (0-360 positive east,...
Definition Spice.cpp:1341
virtual void createCache(iTime startTime, iTime endTime, const int size, double tol)
This method creates an internal cache of spacecraft and sun positions over a specified time range.
Definition Spice.cpp:649
virtual iTime cacheEndTime() const
Accessor method for the cache end time.
Definition Spice.cpp:765
virtual ~Spice()
Destroys the Spice object.
Definition Spice.cpp:511
void radii(Distance r[3]) const
Returns the radii of the body in km.
Definition Spice.cpp:937
SpiceValueType
NAIF value primitive type.
Definition Spice.h:348
@ SpiceByteCodeType
SpiceByteCode type.
Definition Spice.h:352
@ SpiceIntType
SpiceInt type.
Definition Spice.h:351
@ SpiceStringType
SpiceString type.
Definition Spice.h:350
@ SpiceDoubleType
SpiceDouble type.
Definition Spice.h:349
PvlObject * m_naifKeywords
NaifKeywords PvlObject from cube.
Definition Spice.h:427
void init(Pvl &pvl, bool noTables, nlohmann::json isd=NULL)
Initialization of Spice object.
Definition Spice.cpp:154
SpiceInt naifBodyCode() const
This returns the NAIF body code of the target indicated in the labels.
Definition Spice.cpp:948
SpiceInt naifSpkCode() const
This returns the NAIF SPK code to use when reading from SPK kernels.
Definition Spice.cpp:957
virtual void instrumentBodyFixedPosition(double p[3]) const
Returns the spacecraft position in body-fixed frame km units.
Definition Spice.cpp:842
PvlObject getStoredNaifKeywords() const
This returns the PvlObject that stores all of the requested Naif data and can be a replacement for fu...
Definition Spice.cpp:1005
SpiceInt naifCkCode() const
This returns the NAIF CK code to use when reading from CK kernels.
Definition Spice.cpp:966
virtual Target * target() const
Returns a pointer to the target object.
Definition Spice.cpp:1380
SpiceInt * m_spkBodyCode
Spacecraft and planet ephemeris kernel (SPK) body code.
Definition Spice.h:422
virtual iTime time() const
Returns the ephemeris time in seconds which was used to obtain the spacecraft and sun positions.
Definition Spice.cpp:891
SpiceInt * m_ckCode
Camera kernel (CK) code.
Definition Spice.h:419
SpiceInt * m_spkCode
Spacecraft and planet ephemeris kernel (SPK) code.
Definition Spice.h:418
bool hasKernels(Pvl &lab)
Returns true if the kernel group has kernel files.
Definition Spice.cpp:1538
virtual SpiceRotation * instrumentRotation() const
Accessor method for the instrument rotation.
Definition Spice.cpp:1634
SpiceDouble * m_cacheSize
Cache size. Note: This value is 1 for Framing cameras.
Definition Spice.h:401
void defaultInit()
Default initialize the members of the SPICE object.
Definition Spice.cpp:107
virtual SpicePosition * instrumentPosition() const
Accessor method for the instrument position.
Definition Spice.cpp:1612
SpiceInt naifIkCode() const
This returns the NAIF IK code to use when reading from instrument kernels.
Definition Spice.cpp:975
SpiceInt naifSclkCode() const
This returns the NAIF SCLK code to use when reading from instrument kernels.
Definition Spice.cpp:985
QString targetName() const
Returns the QString name of the target.
Definition Spice.cpp:1390
SpiceInt naifBodyFrameCode() const
This returns the NAIF body frame code.
Definition Spice.cpp:996
void load(PvlKeyword &key, bool notab)
Loads/furnishes NAIF kernel(s)
Definition Spice.cpp:486
SpiceDouble m_uB[3]
This contains the sun position (u) in the bodyfixed reference frame (B).
Definition Spice.h:369
virtual iTime cacheStartTime() const
Accessor method for the cache start time.
Definition Spice.cpp:750
iTime * m_endTime
Corrected end (shutter close) time of the observation.
Definition Spice.h:400
iTime * m_et
Ephemeris time (read NAIF documentation for a detailed description)
Definition Spice.h:382
bool isTimeSet()
Returns true if time has been initialized.
Definition Spice.cpp:1589
QVector< QString > * m_kernels
Vector containing kernels filenames.
Definition Spice.h:396
SpiceRotation * m_bodyRotation
Body spice rotation.
Definition Spice.h:409
iTime * m_startTime
Corrected start (shutter open) time of the observation.
Definition Spice.h:399
virtual SpicePosition * sunPosition() const
Accessor method for the sun position.
Definition Spice.cpp:1601
SpiceDouble getDouble(const QString &key, int index=0)
This returns a value from the NAIF text pool.
Definition Spice.cpp:1046
SpiceInt getInteger(const QString &key, int index=0)
This returns a value from the NAIF text pool.
Definition Spice.cpp:1032
virtual void subSpacecraftPoint(double &lat, double &lon)
Returns the sub-spacecraft latitude/longitude in universal coordinates (0-360 positive east,...
Definition Spice.cpp:1290
virtual double resolution()
Virtual method that returns the pixel resolution of the sensor in meters/pix.
Definition Spice.cpp:1016
Obtain SPICE position information for a body.
@ Memcache
Object is reading from cached table.
virtual const std::vector< double > & Coordinate()
Return the current J2000 position.
virtual void SetAberrationCorrection(const QString &correction)
Set the aberration correction (light time)
Obtain SPICE rotation information for a body.
std::vector< double > Matrix()
Return the full rotation TJ as a matrix.
@ Yes
Downsize the cache.
@ Memcache
From cached table.
Class for storing Table blobs information.
Definition Table.h:61
PvlObject & Label()
The Table's label.
Definition Table.cpp:318
This class is used to create and store valid Isis targets.
Definition Target.h:63
std::vector< Distance > radii() const
Returns the radii of the body in km.
Definition Target.cpp:557
Parse and return pieces of a time string.
Definition iTime.h:65
double Et() const
Returns the ephemeris time (TDB) representation of the time as a double.
Definition iTime.h:126
This is free and unencumbered software released into the public domain.
Definition Calculator.h:18
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition IString.cpp:211
int toInt(const QString &string)
Global function to convert from a string to an integer.
Definition IString.cpp:93
double toDouble(const QString &string)
Global function to convert from a string to a double.
Definition IString.cpp:149
const double PI
The mathematical constant PI.
Definition Constants.h:40
Namespace for the standard library.