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 primary use of this module variable logging is for debugging and unit tests.
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, private C++ variables which have a getter method, or they are variables with the C module configuration structure. Both Module: cModuleTemplate and Module: cppModuleTemplate have the exact same variables for easy comparison.
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 = ...
if the module variable is public (all C modules and some C++ modules). If the C++ module variable is
private, but has a public setter function, then it is set using the setter
method someModule.setSomeVariable(...)
as outlined in Module Header File.
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.setDummy(1)
35 mod2.setDumVector([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 mod2Logger = mod2.logger(["dummy", "dumVector"])
41 scSim.AddModelToTask("dynamicsTask", mod2Logger)
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(mod2Logger.dummy)
58 print("mod2.getDumVector():")
59 print(mod2Logger.dumVector)
60
61if __name__ == "__main__":
62 run()
Logging a user-configurable variable from a module is similar to recording a message:
moduleLogger = module.logger(variableName, recordingTime)
Note
The variableName
must be either a string or a list of strings. This establishes what module variables to log.
The variable must be either public or accessable through a getter method someModule.getVariableName
.
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.