# 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使自己的应用与设备兼容。
设备接入示意图:

## 可支持设备说明
- 设备硬件按照类型进行了分类,每个类型的的硬件都提供了对应的硬件接口。
- 每种设备会产出各自的动态链接库,如: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