spicerotation.cpp
上传用户:center1979
上传日期:2022-07-26
资源大小:50633k
文件大小:5k
源码类别:

OpenGL

开发平台:

Visual C++

  1. // spicerotation.cpp
  2. //
  3. // Rotation model interface to the SPICE Toolkit
  4. //
  5. // Copyright (C) 2008, Celestia Development Team
  6. // Initial implementation by Chris Laurel <claurel@gmail.com>
  7. //
  8. // This program is free software; you can redistribute it and/or
  9. // modify it under the terms of the GNU General Public License
  10. // as published by the Free Software Foundation; either version 2
  11. // of the License, or (at your option) any later version.
  12. #include <iostream>
  13. #include <cstdio>
  14. #include <limits>
  15. #include "SpiceUsr.h"
  16. #include "astro.h"
  17. #include "spicerotation.h"
  18. #include "spiceinterface.h"
  19. using namespace std;
  20. static const double MILLISEC = astro::secsToDays(0.001);
  21. static const Quatd Rx90 = Quatd::xrotation(PI / 2.0);
  22. /*! Create a new rotation model based on a SPICE frame. The 
  23.  *  orientation of the rotation model is the orientation of the
  24.  *  named SPICE frame relative to the base frame orientation.
  25.  *  The rotation is valid during a time range between beginning
  26.  *  and end. The period can be specified for periodic rotations
  27.  *  (units are Julian days), or set to zero for aperiodic rotation
  28.  *  models.
  29.  */
  30. SpiceRotation::SpiceRotation(const std::string& frameName,
  31.                              const std::string& baseFrameName,
  32.                              double period,
  33.                              double beginning,
  34.                              double ending) :
  35.     m_frameName(frameName),
  36.     m_baseFrameName(baseFrameName),
  37.     m_period(period),
  38.     m_spiceErr(false),
  39.     m_validIntervalBegin(beginning),
  40.     m_validIntervalEnd(ending),
  41. m_useDefaultTimeInterval(false)
  42. {
  43. }
  44. /*! Create a new rotation model based on a SPICE frame. The 
  45.  *  orientation of the rotation model is the orientation of the
  46.  *  named SPICE frame relative to the base frame orientation.
  47.  *  The rotation is valid during a time range between beginning
  48.  *  and end. The period can be specified for periodic rotations
  49.  *  (units are Julian days), or set to zero for aperiodic rotation
  50.  *  models.
  51.  */
  52. SpiceRotation::SpiceRotation(const std::string& frameName,
  53.                          const std::string& baseFrameName,
  54.                              double period) :
  55. m_frameName(frameName),
  56. m_baseFrameName(baseFrameName),
  57. m_period(period),
  58. m_spiceErr(false),
  59.     m_validIntervalBegin(-numeric_limits<double>::infinity()),
  60.     m_validIntervalEnd(numeric_limits<double>::infinity()),
  61. m_useDefaultTimeInterval(true)
  62. {
  63. }
  64. SpiceRotation::~SpiceRotation()
  65. {
  66. }
  67. bool
  68. SpiceRotation::isPeriodic() const
  69. {
  70.     return m_period != 0.0;
  71. };
  72. double
  73. SpiceRotation::getPeriod() const
  74. {
  75.     if (isPeriodic())
  76.     {
  77.         return m_period;
  78.     }
  79.     else
  80.     {
  81.         return m_validIntervalEnd - m_validIntervalBegin;
  82.     }
  83. }
  84. bool
  85. SpiceRotation::init(const string& path,
  86.                     const list<string>* requiredKernels)
  87. {
  88.     // Load required kernel files
  89.     if (requiredKernels != NULL)
  90.     {
  91.         for (list<string>::const_iterator iter = requiredKernels->begin(); iter != requiredKernels->end(); iter++)
  92.         {
  93.             string filepath = path + string("/data/") + *iter;
  94.         if (!LoadSpiceKernel(filepath))
  95.             {    
  96.         m_spiceErr = true;
  97.                 break;
  98.             }
  99.         }
  100.     }
  101.     // Reduce valid interval by a millisecond at each end.
  102.     m_validIntervalBegin += MILLISEC;
  103.     m_validIntervalEnd -= MILLISEC;
  104.     // Test getting the frame rotation matrix to make sure that there's
  105.     // adequate data in the kernel.
  106.     double beginning = astro::daysToSecs(m_validIntervalBegin - astro::J2000);
  107.     double xform[3][3];
  108.     pxform_c(m_frameName.c_str(), m_frameName.c_str(), beginning, xform);
  109.     if (failed_c())
  110.     {
  111.         // Print the error message
  112.         char errMsg[1024];
  113.         getmsg_c("long", sizeof(errMsg), errMsg);
  114.         clog << errMsg << "n";
  115.         m_spiceErr = true;
  116.         reset_c();
  117.     }
  118.     return !m_spiceErr;
  119. }
  120. Quatd
  121. SpiceRotation::computeSpin(double jd) const
  122. {
  123.     if (jd < m_validIntervalBegin)
  124.         jd = m_validIntervalBegin;
  125.     else if (jd > m_validIntervalEnd)
  126.         jd = m_validIntervalEnd;
  127.     if (m_spiceErr)
  128.     {
  129.         return Quatd(1.0);
  130.     }
  131.     else
  132.     {
  133.         // Input time for SPICE is seconds after J2000
  134.         double t = astro::daysToSecs(jd - astro::J2000);
  135.         double xform[3][3];
  136.         pxform_c(m_frameName.c_str(), m_baseFrameName.c_str(), t, xform);
  137.         if (failed_c())
  138.         {
  139.             // Print the error message
  140.             char errMsg[1024];
  141.             getmsg_c("long", sizeof(errMsg), errMsg);
  142.             clog << errMsg << "n";
  143.             // Reset the error state
  144.             reset_c();
  145.         }
  146. #if 1
  147.         Mat3d m(Vec3d(xform[0][0], xform[0][1], xform[0][2]),
  148.                 Vec3d(xform[1][0], xform[1][1], xform[1][2]),
  149.                 Vec3d(xform[2][0], xform[2][1], xform[2][2]));
  150. #else
  151.         Mat3d m(Vec3d(xform[0][0], xform[1][0], xform[2][0]),
  152.                 Vec3d(xform[0][1], xform[1][1], xform[2][1]),
  153.                 Vec3d(xform[0][2], xform[1][2], xform[2][2]));
  154. #endif
  155.         Quatd q = Quatd::matrixToQuaternion(m);
  156.         // Transform into Celestia's coordinate system
  157.         return Quatd::yrotation(PI) * Quatd::xrotation(-PI / 2.0) * ~q * Quatd::xrotation(PI / 2.0);
  158.     }
  159. }