Basilisk Process and Task CreationΒΆ

To execute modules within the simulation, their evaluation is controlled through the Basilisk Process and Task containers. The BSK Task contains a series of modules which are all executed with the same update rate. A Process is essentially a task group which can contain several related tasks. For example, in a multi-satellite simulation you could create a Process for each satellite to keep the associated tasks and embedded modules organized. The illustration below shows a sample layout where the dynamics of bskSat satellite is added to a separate process from the flight software (FSW) algorithms being executed on this satellite. Within each process there are several tasks set up which are evaluated at specified rates. The dynamics process contains a Dynamics task to evaluate the spacecraft translational and rotational motion, as well as a Sensors task to create sensor output messages.

../../_images/qs-bsk-1.svg

The python code example below illustrates a prototypical BSK simulation setup. The Process and Task creation are controlled through the utility package SimulationBaseClass. This is loaded to provide the core Basilisk capabilities including

  • making processes and tasks

  • adding modules to tasks

  • initializing a simulation

  • executing a simulation

The macros utility is loaded to provide some convenient helper functions.

Next, a method run() is created that will execute the BSK simulation. The name of this method is arbitrary. The SimBaseClass() instance scSim is the core Basilisk simulation container to which simulation components are added. Now a process is created using the CreateNewProcess(name) method where name is a string containing the process name.

 1
 2from Basilisk.utilities import SimulationBaseClass
 3from Basilisk.utilities import macros
 4
 5
 6def run():
 7    """
 8    Illustration of Basilisk process and task creation
 9    """
10
11    #  Create a sim module as an empty container
12    scSim = SimulationBaseClass.SimBaseClass()
13
14    #  create the simulation process
15    dynProcess = scSim.CreateNewProcess("dynamicsProcess")
16    fswProcess = scSim.CreateNewProcess("fswProcess")
17
18    # create the dynamics task and specify the integration update time
19    dynProcess.addTask(scSim.CreateNewTask("dynamicsTask", macros.sec2nano(5.)))
20    dynProcess.addTask(scSim.CreateNewTask("sensorTask", macros.sec2nano(10.)))
21    fswProcess.addTask(scSim.CreateNewTask("fswTask", macros.sec2nano(10.)))
22
23    #  initialize Simulation:
24    scSim.InitializeSimulation()
25
26    #   configure a simulation stop time and execute the simulation run
27    scSim.ConfigureStopTime(macros.sec2nano(20.0))
28    scSim.ExecuteSimulation()
29
30    return
31
32
33if __name__ == "__main__":
34    run()

The next step is the creation of three BSK processes: two processes for dynamics, and one process for FSW. Note that the process order of execution is determined here by the order in that they are created. There is an optional priority argument that can be provided to over-ride this execution order using:

dynProcess = scSim.CreateNewProcess("name", priority)

The higher process with a higher priority value is executed before processes with lower priority. The integer priority defaults to -1 which means that this process is executed after all processes with a specified priority, and in the order that the non-priority processes were created.

The next steps create task lists that are contained in a process or task group. The first argument is the string name that identifies the task being created. The second argument is the task update rate in nano-seconds. Here the macros.sec2nano() method is a convenient tool to convert seconds to nano-seconds. When the BSK simulation increments its time variable, it does so in nano-second time steps, the smallest time unit in Basilisk. It is chosen to be small enough such that no dynamics, sensor or algorithm module should require a smaller time step. However, it is still large enough such that with a 64-bit unsigned integer we can simulate a mission lifetime of 584 years.

As with the Process creation, the Task creation by default has a priority of -1. This means that the task lists are evaluated after any prioritized task lists within the process and in the order they are created. To set a positive priority value to a task use:

dynProcess.addTask(scSim.CreateNewTask("name", updateRate, priority))

It is possible to hold a task initially dormant for a period of time by specifying the optional FirstStart input parameter in units of nano-seconds. The task will then be first executed at this time FirstStart. But, afterwards the task execution resumes at the original updateRate interval. For example, consider:

dynProcess.addTask(scSim.CreateNewTask("name", updateRate, priority, FirstStart=delayStartTime))

For example, if the first task execution occurs at delayStartTime of 1s, and updateRate is set to 5s, then the task is exectuted at 1s, 5s, 10s, 15s, etc.

To initialize processes and tasks, call the InitializeSimulation() method which ensures all Basilisk compute and initialized and the modules with a task are reset.

Next, the simulation length is set through ConfigureStopTime(stopTime) where again the stop time must be provided in nano-seconds. Note that this is the absolute stop time. If you run the simulation for 5 seconds, then change some parameters, and then want to continue the simulation for an additional 5 seconds, the second stop time must be the accumulated simulation time of 10 seconds. This is illustrated below:

scSim.ConfigureStopTime(macros.sec2nano(5.0))
scSim.ExecuteSimulation()
scSim.ConfigureStopTime(macros.sec2nano(10.0))
scSim.ExecuteSimulation()