# 3rd party / std lib imports
import numpy as np
import pytest
from Basilisk.architecture import messaging
# Modules to test
from Basilisk.fswAlgorithms import hillToAttRef
# Utilities/macros
from Basilisk.utilities import SimulationBaseClass as sbc
from Basilisk.utilities import macros
#from Basilisk.simulation import simFswInterfaceMessages
[docs]
@pytest.mark.parametrize("msg_type", ['AttRefMsg','NavAttMsg'])
@pytest.mark.parametrize("use_limits", [True, False])
def test_hillToAttRef(show_plots, use_limits, msg_type):
"""
**Validation Test Description**
Unit test for hillToAttRef. The unit test specifically covers:
1. Input message types: Does hillToAttRef accept either a NavAttMsg or an AttRefMsg and produce identical behavior with either one?
2. Limit enforcement: When set, does the module correctly use the limits specified by the user?
"""
runner(show_plots, use_limits, msg_type)
def runner(show_plots, use_limits, msg_type):
sim = sbc.SimBaseClass()
procName = 'process'
taskName = 'task'
proc = sim.CreateNewProcess(procName)
task = sim.CreateNewTask(taskName, macros.sec2nano(1.0))
proc.addTask(task)
# Set up a test relative state vector
relative_state = [1000, 0, 0,
0, 5, 0] # m / m/s
# Set up a dummy gain matrix
lqr_gain_set = np.array([[0,1,0],
[0,0,0],
[0,0,0],
[0,0,0],
[0,0,0.25],
[0,0,0], ]).T
hillStateMsgData = messaging.HillRelStateMsgPayload()
hillStateMsgData.r_DC_H = relative_state[0:3]
hillStateMsgData.v_DC_H = relative_state[3:]
hillStateMsg = messaging.HillRelStateMsg().write(hillStateMsgData)
# Set up the hillStateConverter
depAttRef = hillToAttRef.hillToAttRef()
depAttRef.ModelTag = "dep_hillControl"
depAttRef.gainMatrix = hillToAttRef.MultiArray(lqr_gain_set)
depAttRef.hillStateInMsg.subscribeTo(hillStateMsg)
if msg_type == 'NavAttMsg':
attRefMsgData = messaging.NavAttMsgPayload()
attRefMsgData.sigma_BN = [0.5, 0.5, 0.5]
attRefMsg = messaging.NavAttMsg().write(attRefMsgData)
depAttRef.attNavInMsg.subscribeTo(attRefMsg)
else:
attRefMsgData = messaging.AttRefMsgPayload()
attRefMsgData.sigma_RN = [0.2, 0.2, 0.2]
attRefMsg = messaging.AttRefMsg().write(attRefMsgData)
depAttRef.attRefInMsg.subscribeTo(attRefMsg)
if use_limits:
depAttRef.relMRPMin = -0.2 # Configure minimum MRP
depAttRef.relMRPMax = 0.2 # Configure maximum MRP
# ref_vals = [0.2, -0.2, 0.2]
if msg_type == 'NavAttMsg':
ref_vals = [-0.37398374, -0.25203252, -0.57723577]
else:
ref_vals = [0.2165725, 0.32956685, 0.51789077]
else:
# ref_vals = lqr_gain_set.dot(relative_state)
if msg_type == 'NavAttMsg':
ref_vals = [0.5, 0.5, 0.5]
else:
ref_vals = [0.2, 0.2, 0.2]
# Store the output att ref message
depAttRecorder = depAttRef.attRefOutMsg.recorder()
sim.AddModelToTask(taskName, depAttRef)
sim.AddModelToTask(taskName, depAttRecorder)
sim.ConfigureStopTime(macros.sec2nano(1.0))
sim.InitializeSimulation()
sim.ExecuteSimulation()
hill_positions = depAttRecorder.sigma_RN
# Test the attitude calculation:
for val1, val2 in zip(hill_positions[-1], ref_vals):
assert val1 == pytest.approx(val2)
if __name__=="__main__":
test_hillToAttRef(False, True, 'AttRefMsg')