211 lines
6.0 KiB
Markdown
211 lines
6.0 KiB
Markdown
|
||
# Runtime Interface
|
||
|
||
## 相关链接
|
||
|
||
参考示例:
|
||
- {{ '[helloworld]({}/src/examples/py/helloworld)'.format(code_site_root_path_url) }}
|
||
- {{ '[examples_py_helloworld_app_mode.py]({}/src/examples/py/helloworld/examples_py_helloworld_app_mode.py)'.format(code_site_root_path_url) }}
|
||
- {{ '[examples_py_helloworld_registration_mode.py]({}/src/examples/py/helloworld/examples_py_helloworld_registration_mode.py)'.format(code_site_root_path_url) }}
|
||
|
||
|
||
## 简介
|
||
|
||
与 CPP 接口不一样的是,AimRT Python 接口只提供**App模式**,开发者需要自行管理 python 中的 main 方法,并在其中创建、管理 AimRT Core 实例。在**App模式**模式下,AimRT Python 接口与 CPP 接口类似,提供了**注册**或**创建**这两种方式去开发用户的模块逻辑。
|
||
|
||
|
||
## AimRT Core
|
||
|
||
`aimrt_py`包中的`Core`类型用于控制 AimRT 实例的运行。该类型提供了以下几个关键的方法:
|
||
- `Initialize(core_options)`: 初始化 AimRT 运行时;
|
||
- `Start()`: 启动 AimRT 运行时,注意,该方法将阻塞当前线程,直到在其他线程中调用了`Shutdown`方法;
|
||
- `Shutdown()`: 停止 AimRT 运行时,支持重入;
|
||
- `RegisterModule(module)`: 注册一个模块;
|
||
- `CreateModule(module_name)->module_handle`: 创建一个模块;
|
||
|
||
|
||
前三个方法是 AimRT 实例的运行控制方法,后两个方法则对应了**注册**和**创建**这两种开发用户的模块逻辑的方式。其中,`Initialize`方法接收一个`CoreOptions`类型作为参数。此类型包含以下几个成员:
|
||
- `cfg_file_path`:str,配置文件路径
|
||
|
||
|
||
以下是一个简单的示例,该示例启动了一个 AimRT 运行时,但没有加载任何业务逻辑:
|
||
```python
|
||
import threading
|
||
import time
|
||
import aimrt_py
|
||
|
||
def main():
|
||
aimrt_core = aimrt_py.Core()
|
||
|
||
# init
|
||
core_options = aimrt_py.CoreOptions()
|
||
core_options.cfg_file_path = "path/to/cfg/xxx_cfg.yaml"
|
||
aimrt_core.Initialize(core_options)
|
||
|
||
# start
|
||
thread = threading.Thread(target=aimrt_core.Start)
|
||
thread.start()
|
||
|
||
# shutdown
|
||
time.sleep(1)
|
||
aimrt_core.Shutdown()
|
||
|
||
thread.join()
|
||
|
||
if __name__ == '__main__':
|
||
main()
|
||
```
|
||
|
||
|
||
## 注册模块
|
||
|
||
在注册模式下,开发者需要继承`ModuleBase`基类来创建一个自己的`Module`,并实现其中的`Initialize`、`Start`等方法,然后在`Core`实例调用`Initialize`方法之前将该`Module`注册到`Core`实例中。在此方式下仍然有一个比较清晰的`Module`边界。
|
||
|
||
关于`ModuleBase`基类的相关信息,请参考[ModuleBase](./module_base.md)文档。
|
||
|
||
|
||
以下是一个简单的例子,展示了如何编写一个自己的模块,并注册到`Core`实例中:
|
||
```python
|
||
import threading
|
||
import signal
|
||
import sys
|
||
import aimrt_py
|
||
import yaml
|
||
|
||
# 继承 aimrt_py.ModuleBase 实现一个Module
|
||
class HelloWorldModule(aimrt_py.ModuleBase):
|
||
def __init__(self):
|
||
super().__init__()
|
||
self.core = aimrt_py.CoreRef()
|
||
self.logger = aimrt_py.LoggerRef()
|
||
|
||
def Info(self):
|
||
info = aimrt_py.ModuleInfo()
|
||
info.name = "HelloWorldModule"
|
||
return info
|
||
|
||
def Initialize(self, core):
|
||
assert(isinstance(core, aimrt_py.CoreRef))
|
||
|
||
self.core = core
|
||
self.logger = self.core.GetLogger()
|
||
|
||
# log
|
||
aimrt_py.info(self.logger, "Module initialize")
|
||
|
||
return True
|
||
|
||
def Start(self):
|
||
aimrt_py.info(self.logger, "Module start")
|
||
|
||
return True
|
||
|
||
def Shutdown(self):
|
||
aimrt_py.info(self.logger, "Module shutdown")
|
||
|
||
|
||
global_aimrt_core = None
|
||
|
||
def signal_handler(sig, frame):
|
||
global global_aimrt_core
|
||
if (global_aimrt_core and (sig == signal.SIGINT or sig == signal.SIGTERM)):
|
||
global_aimrt_core.Shutdown()
|
||
return
|
||
|
||
sys.exit(0)
|
||
|
||
|
||
def main():
|
||
# 注册ctrl-c信号
|
||
signal.signal(signal.SIGINT, signal_handler)
|
||
signal.signal(signal.SIGTERM, signal_handler)
|
||
|
||
print("AimRT start.")
|
||
|
||
# 创建 aimrt_py.Core 实例
|
||
aimrt_core = aimrt_py.Core()
|
||
|
||
global global_aimrt_core
|
||
global_aimrt_core = aimrt_core
|
||
|
||
# 注册模块
|
||
module = HelloWorldModule()
|
||
aimrt_core.RegisterModule(module)
|
||
|
||
# 初始化 aimrt_py.Core 实例
|
||
core_options = aimrt_py.CoreOptions()
|
||
core_options.cfg_file_path = "path/to/cfg/xxx_cfg.yaml"
|
||
aimrt_core.Initialize(core_options)
|
||
|
||
# 启动 aimrt_py.Core 实例
|
||
thread = threading.Thread(target=aimrt_core.Start)
|
||
thread.start()
|
||
|
||
# 等待停止
|
||
while thread.is_alive():
|
||
thread.join(1.0)
|
||
|
||
aimrt_core.Shutdown()
|
||
|
||
global_aimrt_core = None
|
||
|
||
print("AimRT exit.")
|
||
|
||
if __name__ == '__main__':
|
||
main()
|
||
```
|
||
|
||
|
||
## 创建模块
|
||
|
||
在`Core`实例调用`Initialize`方法之后,通过`CreateModule`可以创建一个模块,并返回一个句柄,开发者可以直接基于此句柄调用一些框架的方法,比如 RPC 或者 Log 等。在此方式下没有一个比较清晰的`Module`边界,一般仅用于快速做一些小工具。
|
||
|
||
|
||
以下是一个简单的例子,开发者需要编写的 Python 文件如下:
|
||
|
||
```python
|
||
import argparse
|
||
import threading
|
||
import time
|
||
import aimrt_py
|
||
import yaml
|
||
|
||
def main():
|
||
aimrt_core = aimrt_py.Core()
|
||
|
||
core_options = aimrt_py.CoreOptions()
|
||
core_options.cfg_file_path = "path/to/cfg/xxx_cfg.yaml"
|
||
aimrt_core.Initialize(core_options)
|
||
|
||
# create module handle
|
||
module_handle = aimrt_core.CreateModule("HelloWorldModule")
|
||
assert(isinstance(module_handle, aimrt_py.CoreRef))
|
||
|
||
# use cfg and log
|
||
module_cfg_file_path = module_handle.GetConfigurator().GetConfigFilePath()
|
||
with open(module_cfg_file_path, 'r') as file:
|
||
data = yaml.safe_load(file)
|
||
aimrt_py.info(module_handle.GetLogger(), str(data))
|
||
|
||
# start
|
||
thread = threading.Thread(target=aimrt_core.Start)
|
||
thread.start()
|
||
time.sleep(1)
|
||
|
||
# use log
|
||
count = 0
|
||
while(count < 10):
|
||
count = count + 1
|
||
aimrt_py.info(module_handle.GetLogger(), "Conut : {}.".format(count))
|
||
|
||
# shutdown
|
||
time.sleep(1)
|
||
aimrt_core.Shutdown()
|
||
|
||
thread.join()
|
||
|
||
if __name__ == '__main__':
|
||
main()
|
||
```
|
||
|