# airos-al **Repository Path**: mayray/airos-al ## Basic Information - **Project Name**: airos-al - **Description**: 设备抽象位于OS系统最底层,是基于OS框架层中的设备抽象层实现的各种设备接入驱动程序。 - **Primary Language**: C++ - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 6 - **Created**: 2022-11-23 - **Last Updated**: 2022-11-23 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README AIROS 设备抽象使用说明 目录 - [设备抽象与开路OS](#设备抽象与开路os) - [可支持设备说明](#可支持设备说明) - [环境要求](#环境要求) - [快速开始](#快速开始) - [编译](#编译) - [以信号灯设备为例](#以信号灯设备为例) - [测试与验证](#测试与验证) ## 设备抽象与AIROS 设备抽象位于OS系统最底层,是基于OS框架层中的设备抽象层实现的各种设备接入驱动程序。 开发者可以省去开发直接与硬件设备进行通信的程序的步骤,设备抽象会将OS应该执行的操作传达给操作系统,然后OS会向设备生成硬件相关的指令。开发者不需要知道特定设备的工作方式,可以直接通过调用OS使自己的应用与设备兼容。 设备接入示意图: ![设备接入示意](./docs/images/airos-al.png) ## 可支持设备说明 - 设备硬件按照类型进行了分类,每个类型的的硬件都提供了对应的硬件接口。 - 每种设备会产出各自的动态链接库,如:libxxx.so.。 - 每个具体的硬件设备需要继承并实现对应类型设备的抽象xxxDevice接口。 - 接口功能涵盖了设备初始化、设备启动、设备输出格式化数据、设备状态查询等功能。 | 设备类型 | 对应目录 | 接口详细文档 | | ------- | ------- | --- | | 相机 | *`./camera`* | [使用指南](camera/README.md) | | 激光雷达 | *`./lidar`* | [使用指南](lidar/README.md) | | 毫米波雷达 | *`./radar`* | [使用指南](radar/README.md) | | 路侧通信单元 | *`./rsu`* | [使用指南](rsu/README.md) | | 信号灯 | *`./traffic_light`* | [使用指南](traffic_light/README.md) | | 第三方库 | *`./third_party`* | 请参考第三方库的文档 | ## 环境要求: - 系统:Ubuntu 18.04 - CPU: x86_64 - 内存:16G - Docker-CE:>= 19.03 [(官方文档)](https://docs.docker.com/engine/install/ubuntu/) ## 快速开始 ### 获取docker ```bash # docker拉取 bash docker/scripts/docker_start.sh ``` ### 进入docker ```bash bash docker/scripts/docker_into.sh ``` ### 编译 在docker内工程目录下执行 ```bash bash device.sh build ``` ### 产出说明 产出位于`/airos-al/output`,目录结构如下 ```bash ... ... ├── ins │   ├── conf │   │   ├── ins1.yaml │   │   └── ins2.yaml │   ├── include │   │   ├── device_base.h │   │   ├── device_factory.h │   │   ├── ins_data.pb.h │   │   └── ins_data.proto │   ├── ins_test_tool │   ├── libins_device.so │   └── run_test.bash ├── lidar │   ├── conf │   │   ├── lidar1.yaml │   │   ├── lidar2.yaml │   │   └── lidar3.yaml │   ├── include │   │   ├── device_base.h │   │   ├── device_factory.h │   │   ├── lidar_data.pb.h │   │   └── lidar_data.proto │   ├── liblidar_device.so │   ├── lidar_test_tool │   └── run_test.bash ... ... ``` - conf: 设备配置文件 - include:设备接口相关头文件 - xxx_test_tool:xxx类型设备接口测试工具bin - libxxx_device.so:xxx类型设备实现库,每类型设备产出一个,含有用户注册的多个设备实现 - run_test.bash:设备接口测试工具启动脚本 ### 设备接口测试 我们提供了设备接口测试工具,用于验证用户是否成功适配设备接口,使用方式如下: 在docker内工程目录下执行 ```bash # 编译 bash device.sh build # 配置设备测试工具的运行环境 source setup.bash # 进入产出目录中需要测试的设备目录,以lidar设备为例 cd /airos-al/output/lidar # 启动设备 ./lidar_test_tool conf/lidar1.yaml conf/lidar2.yaml [conf/lidar3.yaml..] ``` 设备选型由位于conf下的配置文件控制,每个具体设备对应一个启动配置文件,测试工具支持多个设备测试,配置文件字段如下: ```bash device_type: dummy_lidar # 设备类型名称,与注册给工厂的设备类型名称保持一直 lidar_name: lidar1 # 具体设备名称 lidar_config: /airos-al/lidar/ut/lidar.cfg # 该具体设备启动参数,用于用户传参 ``` 我们为每类型设备提供了接口测试工具使用的demo,启动方式如下: ``` # 以lidar为例,docker内执行 cd /airos-al/output/lidar bash run_test.bash ``` ### UT测试 在docker内工程目录下执行 ```bash bash device.sh test ``` ### 清理编译 在docker内工程目录下执行 ```bash bash device.sh clean ``` ## 开发样例 ### 以信号灯设备为例 1. 继承`traffic_light`设备接口 ```c++ #include "traffic_light/device_base.h" namespace os { namespace v2x { namespace device { class DummyTrafficLight : public TrafficLightDevice { public: /** * @brief 红绿灯采集设备构造函数 * @param[in] cb AIROS框架注册的回调函数 */ DummyTrafficLight(const TrafficLightCallBack& cb) : TrafficLightDevice(cb) {} ~DummyTrafficLight() = default; /** * @brief 用于红绿灯采集设备初始化 * @param[in] config_file 红绿灯采集设备初始化参数配置文件 * @retval 初始化是否成功 */ bool Init(const std::string& config_file) override; /** * @brief 用于启动红绿灯采集设备,产出AIROS结构化的标准红绿灯采集输出数据 */ void Start() override; /** * @brief 用于获取红绿灯采集设备状态 * @retval 设备状态码红绿灯采集DeviceState */ TrafficLightDeviceState GetState() override { return TrafficLightDeviceState::RUNNING; } /** * @brief 用于将数据写入红绿灯采集设备状态 * @param[in] re_proto AIROS结构化的标准红绿灯采集写入数据 */ void WriteToDevice(const std::shared_ptr& re_proto) override; }; } // namespace device } // namespace v2x } // namespace os ``` 2. 实现`traffic_light`接口,并将具体设备注册给设备工厂 ```c++ #include #include #include namespace os { namespace v2x { namespace device { bool DummyTrafficLight::Init(const std::string& config_file) { std::ofstream fs; fs.open(config_file, std::ios::in); if (!fs.is_open()) { return false; } /* 解析config_file参数,初始化相机各项参数 code here... */ return true; } void DummyTrafficLight::Start() { int i = 0; while(true) { // 设备数据产生与格式化制备 auto data = std::make_shared(); data->set_time_stamp(i); // 将设备产出的结构化数据输出给回调函数 sender_(data); i += 1; i %= 100; std::this_thread::sleep_for(std::chrono::seconds(1)); } return; } void DummyTrafficLight::WriteToDevice(const std::shared_ptr& re_proto) { return; } // 通过工厂注册宏将具体设备注册给工厂 V2XOS_TRAFFIC_Light_REG_FACTORY(DummyTrafficLight, "dummy_traffic_light"); } // namespace device } // namespace v2x } // namespace os ``` 3. 使用注册的`dummy_traffic_light`设备 ```c++ #include "traffic_light/device_factory.h" #include #include #include // 设备输出数据回调函数 void callback(const std::shared_ptr& data) { if (data){ std::cout << data->time_stamp() << std::endl; } } int main() { // 基于注册设备时的key,利用traffic_light工厂构建指定的traffic_light设备 auto device = os::v2x::device::TrafficLightDeviceFactory::Instance().GetUnique("dummy_traffic_light", callback); if (device == nullptr) { return 0; } // 初始化设备 if (!device->Init("xxx/config.yaml")) { return 0; } // 启动设备 device->Start(); std::cout << "device start" << std::endl; while(true) { std::this_thread::sleep_for(std::chrono::seconds(10)); } return 0; } ``` 完成以上步骤后,您即可获得一个配置好的信号灯设备。 ## 测试与验证 如果您已经基于开源代码,完成了相关研发工作(包括但不限于应用、驱动等),希望能够在真实硬件上进行测试。我们在北京亦庄搭建了一套具备测试、验证、调试的联合实验室,将为您提供专业的实验环境和技术对接,欢迎您前来接洽。 联合实验室地址:中国北京市大兴区北京经济技术开发区宏达中路10号永晖大厦B座4层 联系方式:发送邮件至zhiluos@163.com