Engines are a core aspect of the NRP-core framework. They run the actual simulation software (which can be comprised of any number of heterogeneous modules), with the Simulation Loop and TransceiverFunctions merely being a way to synchronize and exchange data between them. The data exchange is carried out through an engine client (see paragraph below). An Engine can run any type of software, from physics engines to brain simulators. The only requirement is that they should be able to manage progressing through time with fixed-duration time steps.
From the NRP-core perspective, the core component of the engine is its communication interface, which enables it to communicate with the Simulation Loop. Different engine types can have different communication protocols. Nevertheless, all protocols are envisioned as a server-client architecture, with the Engine server running as a separate process, and a client running inside the Simulation Loop process. As such, all EngineClients must at least support the following functionalities:
LaunchEngine: A function to launch the engine process. This will usually in some way use the ProcessLauncherInterface
Initialize: A function that initializes the engine after launch
Reset: A function which resets the Engine simulation or control process
RunLoopStepAsync: A function that will advance the engine by a given time step
UpdateDataPacksFromEngine: A function to retrieve DataPack data from the Engine
SendDataPacksToEngine: A function to send DataPack data to the Engine
Shutdown: A function that gracefully stops the Engine
This page contains a list of currently supported Engines.
The architecture has been designed in a modular way that allows to implement new engines with relative easiness. In this page can be found a tutorial on how to implement a new engine from scratch. An easier approach is to base the implementation on one of the already implemented communication protocol. Tutorials are available teaching how to accomplish that using gRPC and JSON over REST.
Python JSON Engine¶
Most of the engine implementations distributed alongside NRP-core are bound to a specific simulator, eg. NEST or Gazebo. There is one important exception however: the Python JSON Engine.
This versatile engine allows one to execute a user-defined Python script as an engine server, thus ensuring synchronization and enabling datapack data transfer with the Simulation Loop process. It can be used as a quick way of integrating a not-yet supported simulator in a NRP-core experiment. In this page, interested users will find more information on how to use it.
// Define the EngineLauncher. using NewEngineLauncher = NewEngineClient::EngineLauncher<NewEngineConfigConst::EngineType>;
A new Engine library can use then
NewEngineLauncher to make it plugin compatible. Look under plugin system for additional details.
Note that we assign this EngineLauncher the name specified in NewEngineConfigConst::EngineType. Afterwards, a user can select this engine in the main simulation configuration file by setting as EngineType parameter this value. For details about setting up a simulation configuration file, look here.
Should an engine require more complex startup routines, consider overriding EngineClientInterface::launchEngine() in the new EngineClient implementation. Do not modify the default EngineLauncher, as its only purpose is to construct the Engine class and then call the above function.