diff --git a/docs/source/Support/bskReleaseNotes.rst b/docs/source/Support/bskReleaseNotes.rst index 275a6b94f04..2c1a67bccd0 100644 --- a/docs/source/Support/bskReleaseNotes.rst +++ b/docs/source/Support/bskReleaseNotes.rst @@ -42,6 +42,7 @@ Version |release| using ``uint64_t`` time values and then converted to a double. - Enhance how ``uint64_t`` values are converted to doubles. BSK now warns if the time value is large enough such that the conversion method has a loss of precision in this process. +- Support including an eclipse message in :ref:`SpacecraftLocation` to more accurately determine illumination. Version 2.7.0 (April 20, 2025) diff --git a/src/architecture/msgPayloadDefC/AccessMsgPayload.h b/src/architecture/msgPayloadDefC/AccessMsgPayload.h index a7ca5c264a2..f8b2305e15b 100644 --- a/src/architecture/msgPayloadDefC/AccessMsgPayload.h +++ b/src/architecture/msgPayloadDefC/AccessMsgPayload.h @@ -21,7 +21,7 @@ #define ACCESSSIMMSG_H /*! @brief Message that defines access to spacecraft from a groundLocation, providing access, range, and elevation with - * repect to a ground location. + * respect to a ground location. */ typedef struct { uint64_t hasAccess;//!< [-] 1 when the writer has access to a spacecraft; 0 otherwise. @@ -33,6 +33,7 @@ typedef struct { double az_dot; //!< [rad/s] Azimuth angle rate for a given spacecraft in the SEZ rotating frame. double r_BL_L[3]; //!<[m] Spacecraft position relative to the groundLocation in the SEZ frame. double v_BL_L[3]; //!<[m/s] SEZ relative time derivative of r_BL vector in SEZ vector components. + uint64_t hasIllumination;//!< [-] 1 when illumination constraints are met; 0 otherwise. double sunIncidenceAngle; //!<[rad] Angle between bore-sight and Sun vector double scViewAngle; //!<[rad] Angle between bore-sight and deputy SC vector }AccessMsgPayload; diff --git a/src/architecture/msgPayloadDefC/EclipseMsgPayload.h b/src/architecture/msgPayloadDefC/EclipseMsgPayload.h index 553942f6f4c..63ea6334063 100644 --- a/src/architecture/msgPayloadDefC/EclipseMsgPayload.h +++ b/src/architecture/msgPayloadDefC/EclipseMsgPayload.h @@ -23,7 +23,7 @@ //!@brief Eclipse shadow factor message definition. typedef struct { - double shadowFactor; //!< Proportion of shadowing due to eclipse + double shadowFactor; //!< Proportion of illumination due to eclipse. 0 = fully shadowed, 1 = fully illuminated. }EclipseMsgPayload; diff --git a/src/simulation/environment/spacecraftLocation/spacecraftLocation.cpp b/src/simulation/environment/spacecraftLocation/spacecraftLocation.cpp index aff845282f2..c906b9f1d88 100644 --- a/src/simulation/environment/spacecraftLocation/spacecraftLocation.cpp +++ b/src/simulation/environment/spacecraftLocation/spacecraftLocation.cpp @@ -36,6 +36,7 @@ SpacecraftLocation::SpacecraftLocation() this->aHat_B.fill(0.0); this->theta = -1.0; this->theta_solar = -1.0; + this->min_shadow_factor = -1.0; this->planetState = this->planetInMsg.zeroMsgPayload; this->planetState.J20002Pfix[0][0] = 1; @@ -85,7 +86,7 @@ SpacecraftLocation::Reset(uint64_t CurrentSimNanos) } if (this->theta_solar >= 0.0) { - if (this->aHat_B.norm() < 0.001){ + if (this->aHat_B.norm() < 0.001) { bskLogger.bskLog(BSK_ERROR, "SpacecraftLocation must set aHat_B if you specify theta_solar"); } } @@ -152,11 +153,20 @@ SpacecraftLocation::ReadMessages() sunRead = this->sunInMsg.isWritten(); this->sunData = this->sunInMsg(); } else { - sunRead = false; this->r_HN_N.setZero(); } - return (planetRead && scRead && sunRead); + //! - Zero eclipse information + this->eclipseInMsgData = eclipseInMsg.zeroMsgPayload; + + bool eclipseRead = true; + if (this->eclipseInMsg.isLinked()) { + eclipseRead = this->eclipseInMsg.isWritten(); + this->eclipseInMsgData = this->eclipseInMsg(); + } + + + return (planetRead && scRead && sunRead && eclipseRead); } /*! write module messages @@ -243,7 +253,13 @@ SpacecraftLocation::computeAccess() } } + this->accessMsgBuffer.at(c).hasIllumination = 0; // default to no illumination + + // Check illumination if sun message is present if (this->sunInMsg.isLinked()) { + // Assume illumination conditions are met; then check for unmet conditions + this->accessMsgBuffer.at(c).hasIllumination = 1; + // aHat vector in inertial frame Eigen::Vector3d aHat_N = dcm_NB * this->aHat_B; @@ -262,6 +278,15 @@ SpacecraftLocation::computeAccess() if (this->theta_solar >= 0.0) { if (sunIncidenceAngle > this->theta_solar) { this->accessMsgBuffer.at(c).hasAccess = 0; // outside solar cone + this->accessMsgBuffer.at(c).hasIllumination = 0; + } + } + + // Check if eclipse is valid + if (this->eclipseInMsg.isLinked() && this->min_shadow_factor > 0.0) { + if (eclipseInMsgData.shadowFactor < this->min_shadow_factor) { + this->accessMsgBuffer.at(c).hasAccess = 0; + this->accessMsgBuffer.at(c).hasIllumination = 0; } } } diff --git a/src/simulation/environment/spacecraftLocation/spacecraftLocation.h b/src/simulation/environment/spacecraftLocation/spacecraftLocation.h index 6288999b7aa..e4ac6907f1e 100644 --- a/src/simulation/environment/spacecraftLocation/spacecraftLocation.h +++ b/src/simulation/environment/spacecraftLocation/spacecraftLocation.h @@ -27,6 +27,7 @@ #include "architecture/messaging/messaging.h" #include "architecture/msgPayloadDefC/AccessMsgPayload.h" +#include "architecture/msgPayloadDefC/EclipseMsgPayload.h" #include "architecture/msgPayloadDefC/SCStatesMsgPayload.h" #include "architecture/msgPayloadDefC/SpicePlanetStateMsgPayload.h" @@ -55,10 +56,12 @@ class SpacecraftLocation : public SysModel Eigen::Vector3d aHat_B; //!< [] (optional) unit direction vector of the sensor/communication boresight axis double theta; //!< [r] (optional) sensor/communication half-cone angle, must be set if shat_B is specified double theta_solar; //!< [r] (optional) illumination half-cone angle, treating aHat_B as the surface normal + double min_shadow_factor; //!< [] (optional) minimum amount of illumination due to eclipse necessary to observe ReadFunctor primaryScStateInMsg; //!< primary spacecraft input message - ReadFunctor planetInMsg; //!< planet state input message - ReadFunctor sunInMsg; //!< [-] sun data input message + ReadFunctor planetInMsg; //!< (optional) planet state input message + ReadFunctor sunInMsg; //!< (optional) sun data input message + ReadFunctor eclipseInMsg; //!< (optional) eclipse input message std::vector*> accessOutMsgs; //!< vector of ground location access messages std::vector> scStateInMsgs; //!< vector of other sc state input messages Eigen::Vector3d @@ -72,6 +75,7 @@ class SpacecraftLocation : public SysModel SCStatesMsgPayload primaryScStatesBuffer; //!< buffer of primary spacecraft states SpicePlanetStateMsgPayload planetState; //!< buffer of planet data SpicePlanetStateMsgPayload sunData; //!< buffer of sun data + EclipseMsgPayload eclipseInMsgData; //!< buffer of eclipse data Eigen::Matrix3d dcm_PN; //!< Rotation matrix from inertial frame N to planet-centered to planet-fixed frame P Eigen::Vector3d r_PN_N; //!< [m] Planet to inertial frame origin vector. diff --git a/src/simulation/environment/spacecraftLocation/spacecraftLocation.i b/src/simulation/environment/spacecraftLocation/spacecraftLocation.i index 5b6e85fd49d..5fe92a1442d 100644 --- a/src/simulation/environment/spacecraftLocation/spacecraftLocation.i +++ b/src/simulation/environment/spacecraftLocation/spacecraftLocation.i @@ -40,6 +40,8 @@ struct SpicePlanetStateMsg_C; struct SCStatesMsg_C; %include "architecture/msgPayloadDefC/AccessMsgPayload.h" struct AccessMsg_C; +%include "architecture/msgPayloadDefC/EclipseMsgPayload.h" +struct EclipseMsg_C; %pythoncode %{ import sys diff --git a/src/simulation/environment/spacecraftLocation/spacecraftLocation.rst b/src/simulation/environment/spacecraftLocation/spacecraftLocation.rst index 8b6d544baad..372fc206441 100644 --- a/src/simulation/environment/spacecraftLocation/spacecraftLocation.rst +++ b/src/simulation/environment/spacecraftLocation/spacecraftLocation.rst @@ -38,7 +38,10 @@ provides information on what this message is used for. - vector of other spacecraft state input messages. These are set through ``addSpacecraftToModel()`` * - sunInMsg - :ref:`SpicePlanetStateMsgPayload` - - (optional) sun state input message. Used for illumination checking if the message is connected and `theta_solar` is set. + - (optional) sun state input message. Used for illumination checking if the message is connected and ``theta_solar`` is set. + * - eclipseInMsg + - :ref:`EclipseMsgPayload` + - (optional) eclipse input message. Used for illumination checking if the message is connected and ``min_shadow_factor`` is set. * - accessOutMsgs - :ref:`AccessMsgPayload` - output vector of ground location access messages @@ -120,6 +123,8 @@ If the ``sunInMsg`` is connected and :math:`\theta_{\text{solar,max}}` is set, t .. math:: \arccos \left( \hat{\bf a} \cdot \hat{\bf s} \right) = \theta_{\text{solar}} \le \theta_{\text{solar,max}} +If an eclipse message is connected and ``min_shadow_factor`` is set, the module will also check that the shadow factor is above this threshold. + User Guide ---------- A new instance of ``spacecraftLocation``, alongside necessary user-supplied parameters, can be created by calling: