############################### AGM (Attitude generator module) ############################### AGM Overview ============ The Attitude Generation Module (AGM) is a software library developed to support implementing science operations planning systems with capabilities to schedule pointing, slew and maintenance blocks according to the Interface Control Documents (ICD) provided by Flight Dynamics (FDY) to the Science Operations Centres (SOC). AGM Configuration File ====================== This section documents certain relevant aspects of the AGM configuration file. Attitude Constraints Checks --------------------------- The attitude constraint checks defines how the slew estimator is going to behave while resolving and assuring the viability of the simulated pointing timeline. In order to configure the attitude constraint checks just add the following settings to the AGM configuration file: - ``AC_POINTINGDURATIONMIN``: Minimum duration of a pointing block in seconds. - ``AC_SLEWDURATIONMIN``: Minimum duration of a slew block in seconds. - ``AC_GSEPSLEWDURATIONMIN``: Minimum duration of a slew block before/after a GSEP block in seconds. - ``AC_COMPOSITEDURATIONMIN``: Minimum duration of each composite internal pointing slot in seconds. - ``AC_COMPOSITETIMEBEFORE``: Minimum time required in composite pointing blocks before the offset rotations in seconds. - ``AC_COMPOSITETIMEAFTER``: Minimum time required in composite pointing blocks after the offset rotations in seconds. - ``AC_FLIPDURATION``: ``NadirPowerOptimize`` flip duration in seconds. - ``AC_FLIPMARGIN``: Margin from the beginning or the end of the pointing in seconds. - ``AC_FLIPACCELERATION``: Acceleration in ``deg/s^2`` for Yaw angle during the acceleration/deceleration periods during a flip. - ``AC_WOLDURATION``: Duration of the WOL (Wheel Off-loading) maintenance block in seconds. - ``AC_CHECKTIMESTEP``: Time step for the attitude constraints checking in seconds. - ``AC_SCANGVELMAX``: Maximum angular velocity allowed for the S/C in degrees/second. If set to 0 then this check is disabled. - ``AC_SCANGVELMAXAXIS``: Vector with the maximum angular velocities allowed for the S/C per axis in degrees/second. If any axis is set to 0 then this axis check is disabled. - ``AC_SCANGACCMAX``: Maximum angular acceleration allowed for the S/C in degrees/second. If set to 0 then this check is disabled. - ``AC_SCANGACCMAXAXIS``: Vector with the maximum angular acceleration allowed for the S/C per axis in degrees/second. If any axis is set to 0 then this axis check is disabled. Reaction Wheels and Wheel Momentum Management --------------------------------------------- In order to configure the reaction wheels just add the following settings to the AGM configuration file: Note: All the vectors in this section have four elements. - ``AC_RWTORQUEMIN``: Vector with the minimum torque allowed for each RW in N*m. NOTE: Just for legacy RW module, not used in the WMM. - ``AC_RWTORQUEMAX``: Vector with the maximum torque allowed for each RW in N*m. NOTE: Just for legacy RW module, not used in the WMM. - ``AC_RW_WMM_GGT_TGT_OBJ``: String with the mnemonic of the object to be used as target body for the gravity gradient torque computation. - ``AC_RWEXCURSIONMIN``: Vector with the minimum wheel excursion allowed for each RW in N*m*s. - ``AC_RWEXCURSIONMAX``: Vector with the maximum wheel excursion allowed for each RW in N*m*s. - ``AC_RW_WMM_ENABLED``: Vector with the enabled RW matrix for Wheel Momentum Management. Use '1' for enable the wheel at that index, or will be disabled otherwise. - ``AC_RW_WMM_RESET_ON_ERROR``: Flag (True/False) for resting accumulated data after a Wheel Momentum Management constraint break. - ``AC_RW_WMM_MOMENTUMMIN``: Vector with the minimum wheel momentum allowed for each RW in N*m*s. - ``AC_RW_WMM_MOMENTUMMAX``: Vector with the maximum wheel momentum allowed for each RW in N*m*s. - ``AC_RW_WMM_MOMENTUMINIT``: Vector with the initial wheel momentum state for each RW in N*m*s. - ``AC_RW_WMM_MAXASSMOMENTUM``: Vector with the maximum assembly wheel momentum in N*m*s. - ``AC_RW_WMM_TORQUEMIN``: Vector with the minimum wheel torque allowed for each RW in N*m*s. - ``AC_RW_WMM_TORQUEMAX``: Vector with the maximum wheel torque allowed for each RW in N*m*s. Medium Gain Antenna ------------------- In order to configure the MGA just add the following settings to the AGM configuration file: - ``AC_MGAELANGMIN``: Minimum dish orientation angle allowed for the Medium Gain Antenna. The elevation angle is defined in the interval (0, 360) as the the angle between dish pointing vector and the MGA Y axis (That for JUICE is the SC X Axis). - ``AC_MGAELANGMAX``: Maximum dish orientation angle allowed for the Medium Gain Antenna. The elevation angle is defined in the interval (0, 360) as the the angle between dish pointing vector and the MGA Y axis (That for JUICE is the S/C +X Axis). - ``AC_MGAELANGVELMAX``: Maximum elevation angular velocity allowed for the Medium Gain Antenna. - ``AC_MGAELANGACCMAX``: Maximum elevation angular acceleration allowed for the Medium Gain Antenna. - ``AC_MGAAZANGMIN``: Minimum boom rotation angle allowed for the Medium Gain Antenna. This is the angle between boom and the MGA X axis (That for JUICE is the S/C -Y Axis). This value ranges from 180 to -180 degrees. - ``AC_MGAAZANGMAX``: Maximum boom rotation angle allowed for the Medium Gain Antenna. This is the angle between boom and the MGA X axis (That for JUICE is the S/C -Y Axis). This value ranges from 180 to -180 degrees. - ``AC_MGAAZANGVELMAX``: Maximum azimuth angular velocity allowed for the Medium Gain Antenna. - ``AC_MGAAZANGACCMAX``: Maximum azimuth angular acceleration allowed for the Medium Gain Antenna. - ``AC_MGA2SC``: Medium Gain Antenna to spacecraft orientation matrix. Can be disabled by setting all values to 0. Use the identity matrix to indicate no rotation. - ``AC_MGAFOV``: The antenna Field of View or the antenna plume cone diameter. Used for computing when the Earth is out of the antenna visibility. You can disable this check by setting a FOV of 0.0 degrees. Maximum FOV supported is 360.0 degrees. - ``AC_MGADEFAULTREQUEST``: MGA Default request type: [stow, track]. AGM Frames Definitions Notes for OSVE ------------------------------------- Frame definitions will be indicated with a "Frame" node in the AGM configuration file under the "Frames" node. The following frame attributes are supported: - ``parserName``: Frame name used by AGM - ``mnemonic``: AGM simulator frame types: + ``ECL``: Ecliptic frame. Internally AGM will consider this frame inertial and non dynamic. + ``EME``: Earth Mean Equator frame. Internally AGM will consider this frame inertial and non dynamic. Cannot be buffered. + ``CBE``: Target body-fixed frame. Internally AGM will consider this frame inertial and dynamic. In case of many CBE frames were defined, the last one will apply as the internal Target body-fixed frame. + ``SBF``: Spacecraft body-fixed frame. Internally AGM will consider this a "spacecraft" frame and non dynamic. Cannot be buffered. In case of many SBF frames were defined, the last one will apply as the internal Spacecraft body-fixed frame. - ``spiceName``: SPICE Reference frame name or alias. - ``refFrame``: [IGNORED/DISMISSED] MAPPS Inheritance. - ``isDynamic``: [IGNORED/DISMISSED] MAPPS Inheritance. - ``bufferAtt``: Flag to buffer frame attitude. Non-dynamic frames are never buffered. - ``bufferAttTimeStep``: Time step for frame attitude buffer [seconds]. - ``isReferenceFrame``: Flag to indicate that the frame will be the AGM internal reference frame. Inertial frames are those defined with respect to the default inertial frame, while spacecraft frames are defined with respect to the spacecraft attitude frame computed by the module. Below an example:: Medium Gain Antenna Modelling ============================= AGM supports optional requests to indicate whether if the MGA should tracking the Earth or in Stowed position. These requests are embedded within the required PTR blocks and are provided with with ``mgaRequests`` of types ``stow`` or ``track``: - Use ``stow`` to keep the MGA stowed during all the pointing block. - Use ``track`` to keep Earth tracking during all the pointing block. Below an example:: 2032-07-01T00:40:33 2032-07-01T08:40:33 false 90 stow DL_ pointing -X towards Earth If two consecutive blocks with a slew between them have the same ``mgaRequest``, then the ``mgaRequest`` will be preserved during the slew block. In order to keep backwards compatibility by default request type if nothing is specified, either in the PTR or in the AGM Config will be "track". In order to change the default MGA request type, the following AGM configuration keyword has been implemented:: stow In order to support or avoid ``mgaRequest`` nodes in the predefined blocks, an ``allowMgaRequest="false/true"`` has been included. With a similar functionality to the Rosetta HGA implementation. In addition the MGA CSV file includes a column indicating if the MGA is stowed or not and an overlay is available ``AGM_MGA_IS_STOWED``. This overlay provides if the MGA is in stowed position. The value reported will be 1 in case of being stowed, or 0 otherwise. The MGA CK also provides stowed orientation whenever required. .. Note:: Please note that as per the current simplified modelling the MGA goes instantaneously from stowed to the tracking position and thus breaking any sensible acceleration constraint. We bypass this situation by temporarily providing fake numbers for the acceleration constraints, at this stage of modelling this is a correct assumption. More details on MGA modelling are provided in the following `page `_. External Constraints ==================== OSVE provides support to define your custom Python implementation of AGM constraints in order to improve and extend already built-in AGM constraints. These constraints are used during the attitude checking phase of AGM in such way that if any constraint notifies an error, the attitude of the pointing block is reported as an error, or in case of a slew, the slew estimator will continue finding the best slew path. Finally during the simulation, all these constraints are reevaluated so all their computed parameters are reported and also their error status. So for defining a new External Constrain just inherit the class ExternalConstraintAbstract defined in osve_subscriber.py For example:: from osve import osve from osve_subscriber import ExternalConstraintAbstract class ExternalConstraint(ExternalConstraintAbstract): current_time = "" def __init__(self): super().__init__("extConstraint1") # Note hardcoded External Constraint Id here. def configureConstraintChecks(self) -> int: #print ("configureConstraintChecks...") return 0 def resetConstraintFlags(self): #print ("resetConstraintFlags...") return def notifyEnvironmentInitialised(self) -> int: print ("notifyEnvironmentInitialised... " + str(self.step)) return 0 def update(self, time, sc_quats) -> int: self.current_time = time #print ("update... " + time + " -> " + str(sc_quats)) return 0 def cleanup(self): #print ("cleanup...") return def getInError(self, skipChecks, showMessages, checkConstraints, breakFound) -> int: if breakFound: print ("Constraints error at " + str(self.current_time) + " - " + str(self.step)) return 0 test_input_path = "SOME_PATH_POINTING_TO_SCENARIO" test_input_config_path = "SOME_PATH_POINTING_TO_SESSION_FILE" # First, instantiate the OSVE Simulator sim = osve.osve() # Second, register the defined external constraint the_osve.register_external_constraint(ExternalConstraint()) # Finally, run simulation sim.execute(test_input_path, test_input_config_path) To allow OSVE to finally search and use your defined External Constraints, you need to specify the list of defined External Constraint Ids in the "attitudeSimulationConfiguration" section of the session file as follows:: ... "attitudeSimulationConfiguration": { ... "externalConstraintIds": ["extConstraint1"] }, ... TODO: Explain call flow: While attitude checking configure, init and cleanup methods are called in order for every pointing plock or slew. But during simulation these methods are called only once. AGM Multi-body Approach ======================= As we need them only for Jupiter and the Galilean moons (we will never have a minor moon as a reference object), so it would be fine to simply have a reference list of Hill radii to be used - OSVE is intended to be used as the main interface to design pointings - the gravity torques of all bodies (Jupiter and icy moons) shall be computed as default all together at any point of the trajectory, such that there is no need to define a main body for torques computations when setting-up a detailed scenario. So for the validation, I would like to know how much you find for the Hills radii of Jupiter, Io, Europa, Ganymede and Callisto In order to AGM to being able to determine the orbiting body of each AGM object we have introduced the attribute "orbitingName" which indicate AGM the primary/massive orbiting body to use for Hill-Sphere calculation. Below the new AGM objects configuration with updated objects that have gravity > 0 . This will indicate AGM that the target body shall be computed using the Hill-Sphere method. In case this param is missing, wrongly configured or set as SINGLE_BODY, the default/legacy single body computation will be performed, but in case of being set by default a warning shall be risen. The Hill-Sphere method will iterate over all the AGM objects sorted ascending by gravity, so the target body will be the first object that its gravity is greater that zero and the distance to the SC is smaller than its Hill-sphere radius. The selection of the target body will only be computed at any block/slew start and will be kept during the whole block. Any time that the target body is updated/changed AGM will report an INFO message notifying the new target body. Hill-Sphere method ------------------ The Hill-Sphere method will iterate over all the AGM objects sorted ascending by gravity, so the target body will be the first object that its gravity is greater than zero and the distance to the SC is smaller than its Hill-sphere radius. The selection of the target body will only be computed at any block/slew start and will be kept during the whole block. Any time that the target body is updated/changed AGM will report an INFO message notifying the new target body. In order to AGM to being able to determine the orbiting body of each AGM object we have introduced the attribute ``orbitingName`` which indicate AGM the primary/massive orbiting body to use for Hill-Sphere calculation:: The Hill-Sphere radius of a orbiting body is computed using an equivalent method than the described below:: // Get object orbit radius around orbiting object, it is assumed that // it has a circular orbit so the distance at any point to the orbiting // body could be considered. ganymede_gm = 9.8878300000E+12 jupiter_gm = 1.2668653499E+17 #[m3/s2] #SPICE: Planetary Mass (GM) [km3/s2] #AGM: Planetary Mass (GM) [m3/s2] (gravity in the AGM parameter) G = 6.67430E-11 #[m3/(kg*s2)] # GMJupiter System 126712764.100000 km3 s−2 (SSD JPL 2020) jupiter_gm = 1.26712767863E+08 # Constants a_ganymede = 1070412 # in kilometers # mass_ganymede = 1.4819e23 # in kilograms # mass_jupiter = 1.898e27 # in kilograms mass_ganymede = ganymede_gm*G mass_jupiter = jupiter_gm*G jupiter_radii = 71492000 # Calculate Hill sphere radius hill_sphere_radius = a_ganymede * ((mass_ganymede / (3 * (mass_jupiter+mass_ganymede))**(1/3))) print(hill_sphere_radius / jupiter_radii ) print(f"The Hill sphere radius of Ganymede with respect to Jupiter is approximately {hill_sphere_radius:.2f} kilometers.") PTR Syntax ========== A Pointing Timeline Request file (PTR) is a PTX file that is defined by a list of pointing blocks (also known as PTR blocks) in pseudo-XML format. Each block is represented by a child element block. Each of these blocks defines the S/C attitude for an interval of time. These blocks must be in order of increasing time and cannot overlap. In general, There are three types of pointing blocks: - observation-blocks: used to implement scientific observations - slew-blocks: mandatory and used to transition from one pointing block to another - operational-blocks: used to perform Trajectory-Correction-Manoeuvre (TCM), Wheel-off-Loading (WOL), or Navigation Imaging Slots (NAV). The attitude in an observation block is defined by help of a basic pointing and optionally an offset rotation or derived pointings. It is beyond the scope of this document to provide a detailed pointing design guide or format description. The SOC is assuming that The PTR follows the syntax described in the Rosetta Pointing ICD ([ROSFD]_). This is an assumption prone to change in the future but so far is in agreement with the current approach of Flight Dynamics. In addition, there is a number of deviations from the Rosetta Pointing ICD that are documented hereunder. In addition, some of these deviations are also specified in the JUICE Mission Planning Assumptions Document ([MPAD]_) and these are agreed with Flight Dynamics. On top of the syntax the PTRs have to follow, there is a set of detailed scenario planning specific rules that the PTRs need to follow, more specifically in their comments section and there are also number of deviations from the Rosetta Pointing ICD that are documented in hereunder. PTR Syntax Rosetta Deviations ----------------------------- In order to accommodate particular needs and requirements from JUICE the SOC incorporates the following deviations from the assumed Rosetta Pointing ICD. Block duration ~~~~~~~~~~~~~~ The minimum block durations for observations or slews of 2 minutes shall be observed as per [MPAD]_ instead of the 5 minutes specified by [ROSFD]_. Custom Pointing ~~~~~~~~~~~~~~~ In a custom pointing a margin of 60 seconds is required after the block ``startTime`` and the ``startTime`` of the custom phase specification. This margin of 60 seconds does not seem to be justified and was an issue in parts of the timeline where there is a high density of observations. This margin has been removed for JUICE. For example, in the following Custom block:: 2032-09-23T07:27:11 2032-09-23T07:52:11 false 90 0 1 0 2032-09-23T07:28:11 0 229 154 229 154 229 154 229 1.8 1.8 0.6 0.6 -0.6 -0.6 -1.8 -1.8 0 0 0 0 0 0 0 0 1.4 1.4 1.4 1.4 1.4 1.4 1.4 1.4 0 0 0 0 0 0 0 0 The ``startTime`` within the ``offsetAngles section``, should be able to be exactly as the ``startTime`` in the block. This is achieved by setting the following AGM configuration parameter from 60 seconds to 0 seconds:: 0.0 0.0 Scan Pointing ~~~~~~~~~~~~~ In a scan pointing a margin of 120 seconds is required after the block startTime and the startTime of the scan specification. This margin of 120 seconds does not seem to be justified in the FD ICD. And should be removed for JUICE for the time being. Example: 2032-09-24T11:29:32 2032-09-24T11:46:00 1.0 0.0 0.0 2032-09-24T11:31:32.000 0.0 4.9 1 1 -9.8 12.4 y false The startTime within the offsetAngles section, should be able to be exactly as the startTime in the block. Updated AGM to being able to skip SCAN border internal slews in such way that the scan can start or end as soon as the block starts or ends. In order to do this the user shall use the following sub-node: "0" and set the startTime of the offsetsAngles exactly the same that the block startTime. PTR Block Meta-data ------------------- Each OBS PTR block needs to contain an observation timeline. This observation timeline acts as a link in between the observation plan and the pointing timeline for these observations that are dependent of the PTR such as the prime or rider observations. This timeline allows to propagate the Pointing Timeline updates to the observation plan. The syntax is as follows:: observation_type observation_definition instrument observation_target start_delta end_delta start_time end_time where: - ``designer_instrument``: is the name of the instrument in charge of designing and delivering the PTR block. - ``observation_type``: indicates whether if the observation is Prime or Rider. Note that there can be multiple prime and rider observations in a block. - ``observation_target``: is the target of the observation as a PDS5 LID identifier, there can be multiple targets. - ``start_delta``: is the delta time with respect to the PTR block start time that the observation is to be scheduled against. - ``end_delta``: is the delta time with respect to the PTR block end time that the observation is to be scheduled against. - ``start_time``: is the resolved start time of the observation WRT to the delta, this is not an input field but an output of a PTR resolved with OSVE/AGM. - ``end_time``: is the resolved end time of the observation WRT to the delta, this is not an input field but an output of a PTR resolved with OSVE/AGM Some notes about the syntax: - ``observations`` node occurrence within the ``planning`` node of ``metadata`` is **OPTIONAL** and can only appear once. - ``observations`` node attribute ``designer`` is **MANDATORY**. - Only ``observation`` nodes are allowed inside the ``observations`` node, - `observation` node attributes will be ignored/dismissed. - Every ``observation`` sub-node shall be considered as a data-node, so internally will be stored as a ``node_name::node_value`` map, and any attribute in this sub-nodes will be ignored/dismissed, and these sub-nodes cannot have children nodes. Therefore each observations element that has a designer key, and then a number of observation elements with the following optional fields: ``definition``, ``unit``, ``target``, ``startDelta`` and ``endDelta``, along with other sub-nodes that are not relevant for JUICE. If the ``startDelta`` or ``endDelta`` are not present, a ZERO delta time will be considered by default. These delta times will be relative to the PTR Block ``StartTime`` and ``EndTime`` respectively. These elements need to be persistent upon resolution i.e.: present in the resolved PTR. It would be required also that every observation in the resolved PTR has a ``startTime`` and an ``endTime`` sub-nodes with the resolved date after applying the delta time respectively. Consequently, every occurrence of a ``startTime`` or a ``endTime`` sub-node will be ignored and overwritten (not in the file itself, but in AGM memory) if found in the input PTR. In addition these elements, along with any other element present in the metadata entries, should be available as part of the ``BlockData`` for AGM to be able to retrieve its value from the OSVE callbacks. Eclipse/Umbra and Penumbra Events ================================= Eclipse (or Umbra) events are the time periods when the Sun disk as seen from the spacecraft is fully covered by the target body. In the computation, both the apparent Sun disk and target body disk shall be used. Penumbra events are the time periods when the Sun disk as seen from the spacecraft is partially covered by the target body. In the computation, both the apparent Sun disk and target body disk shall be used. OSVE/AGM is not computing the eclipse/umbra or penumbra events internally. Instead OSVE uses external events in order to take into account eclipse/umbra or penumbra periods for being handled by AGM or EPS, such as for Solar Array power computations. The user must specify the bodies that could produce an eclipse or penumbra event at the AGM Objects section in the AGM configuration file by specifying the name of the event. Each AGM Object specification supports the following optional attributes for configuring the eclipses or penumbras: - ``eclipseEvt``: String with the EPS Event name indicating that the SC is in an eclipse produced by the AGM Object. - ``penumbraEvt``: String with the EPS Event name indicating that the SC is in a penumbra produced by the AGM Object. - ``penumbraFactor``: Double with the percentage (0.0 - 1.0) of Solar Flux obstruction/filtering when in penumbra. Where 0.0 means no Solar Flux filtered, and 1.0 means full eclipse, so no Solar Flux. Below an example:: .. Note:: When JUICE is close to the Sun (i.e. the cruise phase) the drop in power due to a penumbra event might not be noticeable due to the saturation of the solar arrays. AGM SPICE Blocks ================ AGM supports the obtention of spacecraft attitude directly from the loaded SPICE Kernels for a PTR block. During this SPICE block, AGM will retrieve at each timestep the rotation matrix for passing from the Spacecraft body-fixed frame "SBF" to the AGM internal reference frame using SPICE, instead of computing the rotation matrix internally with the attitude requested in the PTR block. This rotation matrix will be used as the reference attitude during the rest of the waterfall of computations during the simulation. The way to perform this is by introducing and SPICE block within the PTR timeline blocks. The syntax for indicating that we require a SPICE block is as any other PTR block, but in this case the "attitude" node has a "ref" attribute with the value "SPICE". In addition to the "ref" attribute, an optional "skipChecks" boolean attribute could be specified in order to indicate AGM in case of "true" that during this block no constraints shall be checked. If this "skipChecks" attribute is not specified AGM will consider to perform constraint checks by default. See example below:: 2032-05-09T17:34:53 2032-05-09T19:34:53 Some considerations about SPICE block: - While in an AGM simulated PTR the reaction wheels accumulated momentum (WMM_ACC) is handled/reset by the WOL blocks, if the user specifies a SPICE block with a long time period the WMM_ACC will most likely fall out of limits. To handle this, the user shall try to inject as many WOL blocks between shorter SPICE blocks as required by the simulation. Because internally WOLs are treated as SLEWs during the WOLs the user will only appreciate an interpolation between the defined attitude at the WOL borders. - Two consecutive SPICE blocks will not be merged together during PTR resolution. Internally AGM will consider always two SPICE Blocks as non equal. - SPICE PTR Blocks will be written with "" in the resolved PTRs.