Setting and Recording Module Variables

Sometimes it is convenient to record a Basilisk module variable, not just the input or output message. This can be done via a python command as shown below. However, note that such module variable recording will slow down the simulation as this is done in the python layer.

The simulation setup is shown in the figure below. Both a C and C++ module are created and added to the single task. However, no messages are connected here. Rather, this sample code illustrates how to record module internal variables. The variables are either public C++ class variables, or they are variables with the C module configuration structure. Both Module: cModuleTemplate and Module: cppModuleTemplate have the exact same public variables for easy comparison.

../../_images/qs-bsk-6.svg

The sample code is shown below. The C and C++ modules are set up as before. The variable someVariable of module someModule is set in python using someModule.someVariable = ....

 1
 2from Basilisk.moduleTemplates import cModuleTemplate
 3from Basilisk.moduleTemplates import cppModuleTemplate
 4from Basilisk.utilities import SimulationBaseClass
 5from Basilisk.utilities import macros
 6
 7
 8def run():
 9    """
10    Illustration of setting and recording module variables
11    """
12
13    #  Create a sim module as an empty container
14    scSim = SimulationBaseClass.SimBaseClass()
15
16    #  create the simulation process
17    dynProcess = scSim.CreateNewProcess("dynamicsProcess")
18
19    # create the dynamics task and specify the integration update time
20    dynProcess.addTask(scSim.CreateNewTask("dynamicsTask", macros.sec2nano(1.)))
21
22    # create modules
23    mod1 = cModuleTemplate.cModuleTemplate()
24    mod1.ModelTag = "cModule1"
25    scSim.AddModelToTask("dynamicsTask", mod1)
26
27    mod2 = cppModuleTemplate.CppModuleTemplate()
28    mod2.ModelTag = "cppModule2"
29    scSim.AddModelToTask("dynamicsTask", mod2)
30
31    # set module variables
32    mod1.dummy = 1
33    mod1.dumVector = [1., 2., 3.]
34    mod2.dummy = 1
35    mod2.dumVector = [1., 2., 3.]
36
37    # request these module variables to be recorded    
38    mod1Logger = mod1.logger("dummy", macros.sec2nano(1.))
39    scSim.AddModelToTask("dynamicsTask", mod1Logger)
40    mod2WrapLogger = mod2.logger(["dummy", "dumVector"], macros.sec2nano(1.))
41    scSim.AddModelToTask("dynamicsTask", mod2WrapLogger)
42
43    #  initialize Simulation:
44    scSim.InitializeSimulation()
45
46    #   configure a simulation stop time and execute the simulation run
47    scSim.ConfigureStopTime(macros.sec2nano(1.0))
48    scSim.ExecuteSimulation()
49
50    # Print when were the variables logged (the same for every logged variable)
51    print("Times: ", mod1Logger.times())
52
53    # Print values logged
54    print("mod1.dummy:")
55    print(mod1Logger.dummy)
56    print("mod2.dummy:")
57    print(mod2WrapLogger.dummy)
58    print("mod2.dumVector:")
59    print(mod2WrapLogger.dumVector)
60
61if __name__ == "__main__":
62    run()

Logging a variable from a module is similar to recording one from a message:

moduleLogger = module.logger(variableName, recordingTime)

The variableName must be either a string or a list of strings. This establishes what module variables to log.

The optional recordingTime variable is the minimum time that must pass, in nano-seconds again, before the module variable is recorded. If this variable is not provided, then the logging occurs at the module update period.

After executing the script, the recorded variables are retrieved using moduleLogger.variableName where variableName is the the name of the module variable you seek to access.

To access the array of time values where the module variables were recorded use moduleLogger.times(). Note that these times are given in nanoseconds.

Executing the script you should thus see the following output:

source/codeSamples % python bsk-6.py
BSK_INFORMATION: Variable dummy set to 0.000000 in reset.
BSK_INFORMATION: Variable dummy set to 0.000000 in reset.
BSK_INFORMATION: C Module ID 1 ran Update at 0.000000s
BSK_INFORMATION: C++ Module ID 2 ran Update at 0.000000s
BSK_INFORMATION: C Module ID 1 ran Update at 1.000000s
BSK_INFORMATION: C++ Module ID 2 ran Update at 1.000000s
Times:  [         0 1000000000]
mod1.dummy:
[1. 2.]
mod2.dummy:
[1. 2.]
mod2.dumVector:
[[1. 2. 3.]
[1. 2. 3.]]

Note that both the C and C++ module variables are correctly being recorded.

Clearing the Data Log

Similarly to message recorders, module loggers continuously add data to their internal data vectors. If you start and stop the simulation, pull the data, resume the simulation and so on, this data recording process is cumulative. If you stop the simulation and want to clear the data log so that only new data is recorded, you can clear the logger using the .clear() method:

moduleLogger.clear()

Advanced Data Logging

The syntax module.logger(variableName) generates a simple logger for one or more module variables. However, loggers can retrieve data from many other sources, and do arbitrary operations on this data before it is stored. This is done using the class Basilisk.utilities.pythonVariableLogger. See scenarioFuelSlosh for an example.