NRP Core  1.4.1
Python GRPC Engine

This versatile Python-based engine is well suited for integrating components with a Python API, and in particular, in the cases where efficient data transmission is required. To this end, this engine employs protobuf messages over GRPC as a communication mechanism. The engine server is defined as a Python class based on GrpcEngineScript (as in the example listed below).

For a complete example of an nrp-core experiment using the Python GRPC Engine see examples/tf_exchange/simulation_config_grpc.json.

GrpcEngineScript

GrpcEngineScript provides a base class from which custom Engines must inherit. The derived class must implement methods:

  • initialize(): initialize the engine and registers required DataPacks with a protobuf message type.
  • runLoop(timestep_ns): advance required simulation and communicate with other engines via TransceiverFunctions.
  • shutdown(): executed when the engine is requested to shutdown.

Besides, GrpcEngineScript provides the following ready-to-use methods and properties to handle datapack communication:

  • _time_ns: returns the internal simulation time of the Engine in nanoseconds.
  • _registerDataPack(datapack_name, protobuf_type): registers a datapack to the engine with the name datapack_name. Registered datapacks are stored in a python dictionary and can be accessed with _setDataPack and _getDataPack. protobuf_type must a Python Protobuf message type and is the expected type of the data stored in this datapack. The stored data will be updated, under the hood, from datapacks returned by TransceiverFunctions at every loop.
  • _getDataPack(datapack_name): returns "datapack_name" datapack data, as a protobuf message.
  • _setDataPack(datapack_name, data): sets "datapack_name" datapack data. "data" is always protobuf a message of type the registered for "datapack_name".

Below is an example of a class inheriting from GrpcEngineScript. The example is taken from the examples/tf_exchange experiment.

"""Python Engine 1. Will get current engine time and make it accessible as a datapack"""
from nrp_core.engines.python_grpc import GrpcEngineScript
from nrp_protobuf import dump_pb2
class Script(GrpcEngineScript):
def initialize(self):
"""Initialize datapack1 with time"""
print("Engine 1 is initializing. Registering datapack...")
self._registerDataPack("datapack1", dump_pb2.String)
d = dump_pb2.String()
d.string_stream = str(self._time_ns)
self._setDataPack("datapack1", d)
def runLoop(self, timestep_ns):
"""Update datapack1 at every timestep"""
self._getDataPack("datapack1").string_stream = str(self._time_ns)
print("DataPack 1 data is ", self._getDataPack("datapack1").string_stream)
def shutdown(self):
print("Engine 1 is shutting down")
def reset(self):
print("Engine 1 is resetting")

DataPacks

The Python GRPC engine supports Protobuf DataPacks, which can be used to transfer information between the engine and TFs.

Any of the Protobuf message definitions compiled with nrp-core can be used in the Python GRPC Engine. These can be found in the folder nrp-core-msgs/protobuf/engine_proto_defs. Also it is possible to compile your own Protobuf message definitions from .proto files and use them with this Engine. See here for a full example showing how to compile .proto files and using the new message types in an NRPCore experiment including a Python GRPC Engine.

Engine Configuration Parameters

This engined is based on EngineBase and EngineGRPC schemas.

NameDescriptionTypeDefaultRequiredArray
EngineNameName of the enginestringX
EngineTypeEngine type. Used by EngineLauncherManager to select the correct engine launcherstringX
EngineProcCmdEngine Process Launch commandstring
EngineProcStartParamsEngine Process Start Parametersstring[]X
EngineEnvParamsEngine Process Environment Parametersstring[]X
EngineLaunchCommandLaunchCommand with parameters that will be used to launch the engine processobject{"LaunchType":"BasicFork"}
EngineTimestepEngine Timestep in secondsnumber0.01
EngineCommandTimeoutEngine Timeout (in seconds). It tells how long to wait for the completion of the engine runStep. 0 or negative values are interpreted as no timeoutnumber0.0
  • Parameters inherited from the EngineGRPC schema:
NameDescriptionTypeDefaultRequiredArray
ServerAddressgRPC Server address. Should this address already be in use, simulation initialization will failstringlocalhost:9004
ProtobufPluginsPathPath were to search for specified ProtobufPlugin librariesstring
ProtobufPackagesProtobuf Packages containing protobuf msg types that will be exchanged by this Engine. It is assumed that these packages have been compiled with NRPCorestring[]X
  • Parameters specific to this engine type:
NameDescriptionTypeDefaultRequiredArray
PythonFileNamePath to the Python script containing the engine definitionstringX

Schema

As explained above, the schema used by the PythonGrpc engine inherits from EngineBase and EngineGRPC schemas. A complete schema for the configuration of this engine is given below:

{"python_base" : {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Python Engine Base",
"description": "Python Engine Base Configuration",
"$id": "#PythonEngineBase",
"allOf": [
{ "$ref": "json://nrp-core/engines/engine_comm_protocols.json#/engine_json" },
{
"properties": {
"PythonFileName" : {
"type": "string",
"description": "Path to the python script containing the engine definition"
}
},
"required": ["PythonFileName"]
}
]
},
"python_json" : {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Python Json Engine",
"description": "Python Json Engine Configuration",
"$id": "#PythonJSONEngine",
"allOf": [
{ "$ref": "#/python_base" },
{
"properties": {
"EngineType": { "enum": ["python_json"] },
"ServerOptions" : {
"type": "string",
"default": "",
"description": "Additional options that will be used by the server (gunicorn) on startup. The string should contain a Python dictionary in the following format - \"{'key1': value, 'key2': 'value_str'}\". The full list of options can be found at the official page - https://docs.gunicorn.org/en/stable/settings.html."
}
}
}
]
},
"python_grpc" : {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Python Grpc Engine",
"description": "Python Grpc Engine Configuration",
"$id": "#PythonGRPCEngine",
"allOf": [
{ "$ref": "#/python_base" },
{
"properties": {
"EngineType": { "enum": ["python_grpc"] }
}
}
]
},
"py_sim" : {
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "Python Simulation Engine",
"description": "A simulation engine for simulators offering a Python API.",
"$id": "#PySim",
"allOf": [
{ "$ref": "#/python_base" },
{
"properties": {
"EngineType": {
"enum": ["py_sim"]
},
"ServerOptions" : {
"type": "string",
"default": "",
"description": "Additional options that will be used by the server (gunicorn) on startup. The string should contain a Python dictionary in the following format - \"{'key1': value, 'key2': 'value_str'}\". The full list of options can be found at the official page - https://docs.gunicorn.org/en/stable/settings.html."
},
"Simulator": {
"enum": ["Opensim","OpenAI","Mujoco","Bullet"],
"description": "The simulators that are supported"
},
"WorldFileName": {
"type": "string",
"description": "Path to the file of simulation world"
},
"Visualizer": {
"type": "boolean",
"default": false,
"description": "To show the simulation in visualizer or not"
}
},
"required": ["Simulator", "WorldFileName"]
}
]
}
}
python_json_engine.shutdown
def shutdown()
Definition: python_json_engine.py:104
python_json_engine.reset
def reset()
Definition: python_json_engine.py:99
python_json_engine.initialize
def initialize()
Definition: python_json_engine.py:79
python_grpc_engine.str
str
Definition: python_grpc_engine.py:63