Apollo添加新的测试算法

有时候需要对原有的算法进行修改,则需要添加自己定制的算法。这里主要讲解对Camera和lidar添加新的测试算法。

Camera,fusion,lidar添加新的测试算法:

Header file: common_component_example.h
Source file: common_component_example.cc
Build file: BUILD
DAG dependency file: common.dag
Launch file: common.launch

Camera添加新障碍物检测算法例子

(新增交通信号灯和车道线检测算法的步骤相同;fusion,lidar添加新的测试算法也类似)

1. 定义一个继承基类 base_obstacle_detector 的类

所有的camera检测算法都必须继承基类base_obstacle_detector,它定义了一组接口。 以下是检测算法继承基类的示例:

namespace apollo {
namespace perception {
namespace camera {

class NewObstacleDetector : public BaseObstacleDetector {
 public:
  NewObstacleDetector();
  virtual ~NewObstacleDetector() = default;

  bool Init(const ObstacleDetectorInitOptions &options =
            ObstacleDetectorInitOptions()) override;

  bool Detect(const ObstacleDetectorOptions &options,
              CameraFrame *frame) override;

  std::string Name() const override;

};  // class NewObstacleDetector

}  // namespace camera
}  // namespace perception
}  // namespace apollo

2. 实现新类 `NewObstacleDetector

为了确保新的检测算法能顺利工作,NewObstacleDetector 至少需要重写 base_obstacle_detector 中定义的接口Init(),Detect()和Name()。其中Init()函数负责完成加载配置文件,初始化类成员等工作;而Detect()则负责实现算法的主体流程。一个具体的NewObstacleDetector.cc实现示例如下:

namespace apollo {
namespace perception {
namespace camera {

bool NewObstacleDetector::Init(const ObstacleDetectorInitOptions &options) {
    /*
    你的算法初始化部分
    */
}

bool NewObstacleDetector::Detect(const ObstacleDetectorOptions &options,
                                 CameraFrame *frame) {
    /*
    你的算法实现部分
    */
}

std::string NewObstacleDetector::Name() const {
    /*
    返回你的检测算法名称
    */
}

REGISTER_OBSTACLE_DETECTOR(NewObstacleDetector); //注册新的camera_obstacle_detector

}  // namespace camera
}  // namespace perception
}  // namespace apollo

3. 为新类 NewObstacleDetector 配置param的proto文件

按照下面的步骤添加新camera检测算法的参数信息:

  • 根据算法要求为新camera检测算法配置param的proto文件。当然,如果参数适配,您也可以直接使用现有的proto文件,或者对现有proto文件进行更改。作为示例,可以参考以下位置的smokeproto定义:modules/perception/camera/lib/obstacle/detector/smoke/proto/smoke.proto。定义完成后在文件头部输入以下内容:
    syntax = "proto2";
    package apollo.perception.camera.NewObstacleDetector;
    
    //你的param参数
    
  • 参考 yolo_obstacle_detector 在目录 modules/perception/production/data/perception/camera/models/ 中创建 newobstacledetector 文件夹,并根据需求创建 *.pt 文件:

4. 更新config文件使新的算法生效

要使用Apollo系统中的新camera检测算法,需要根据需求依次对以下config文件进行配置:

  • 参考如下内容更新 modules/perception/production/conf/perception/camera/obstacle.pt文件,将之前步骤中新建的 *.pt 配置到加载路径中:

    detector_param {
    plugin_param{
        name : "NewObstacleDetector"
        root_dir : "/apollo/modules/perception/production/data/perception/camera/models/newobstacledetector"
        config_file : "*.pt"
    }
    camera_name : "front_12mm"
    }
    
  • 若需要对步骤1中 detector_param 的结构更新,或需要新增其他 _param,可在 modules/perception/camera/app/proto/perception.proto 文件中操作:

    message PluginParam {
    optional string name = 1;
    optional string root_dir = 2;
    optional string config_file = 3;
    }
    message DetectorParam {
    optional PluginParam plugin_param = 1;
    optional string camera_name = 2;
    }
    
  • 若步骤1中不直接使用 obstacle.pt 文件,而使用其他新建的 *.pt 文件,则需要更改 modules/perception/production/conf/perception/camera/fusion_camera_detection_component.pb.txt. 其对应的 proto 文件为 modules/perception/onboard/proto/fusion_camera_detection_component.proto

    camera_obstacle_perception_conf_dir : "/apollo/modules/perception/production/conf/perception/camera"
    camera_obstacle_perception_conf_file : "NewObstacleDetector.pt"
    

lidar添加新的驱动举例

Velodyne驱动主要功能:

  • Driver: 通过网络端口接收lidar硬件产生的UDP数据包,将每一帧封装成VelodyneScan格式后发送。
  • . Parser: 接收VelodyneScan数据,把VelodyneScan中的点由球面坐标系转换成空间直角坐标系下的pointcldoud点云格式后发送。
  • . Compensator: 接收点云数据和pose数据,根据每个点的对应的pose信息把点转换到点云中最大时刻对应的坐标系下,减小由车辆自身的运动带来的误差。需要点云数据中包含每个点的时间戳信息。

步骤:

  • cyber是一个分布式收发消息,和调度框架,同时对外提供一系列的工具和接口来辅助开发和定位问题。cyber框架下系统中每一个功能单元都可以抽象为一个component,通过channel相互间进行通信,然后根据dag(有向无环图)配置文件,构建成相应的pipeline,实现数据的流式处理。

1. 消息定义

apollo已经预定义了点云的消息格式,所以只需要为新lidar定义一个存储原始扫描数据的proto消息,用于数据的存档和离线开发调试,相比于点云数据,存档原始数据可以大量节省存储空间。一个新的扫描数据消息可以类似如下定义:

// a scan message sample
message ScanData {
  optional apollo.common.Header header = 1;  // apollo header
  optional Model model = 2;                  // device model
  optional Mode mode = 3;                    // work mode
  // device serial number, corresponds to a specific calibration file
  optional string sn = 4;
  repeated bytes raw_data = 5;               // raw scan data
}

在velodyne驱动中,其扫描数据消息定义为VelodyneScan.

2. 读取原始数据

lidar每秒会产生大量数据,一般通过UDP协议来进行数据的高效传输。编写一个DriverComponent类,继承于无模版参数Component类;在Init函数中启动一个异步poll线程,不断从相应的端口读取lidar数据;然后根据需求如将一段时间内的数据打包为一帧ScanData,如扫描一圈为一帧;最后通过writer将ScanData写至相应的channel发送出去。

3. 解析扫描数据,生成点云。

编写一个Parser类,输入为一帧ScanData,根据lidar自己的数据协议,解析出每一个点的时间戳,x/y/z三维坐标,以及反射强度,并组合成一帧点云。每个点都位于以lidar为原点的FLU(Front: x, Left: y, Up: z)坐标系下。
然后定义一个ParserComponent,继承于ScanData实例的Component模板类。接收ScanData消息,生成点云消息,发送点云消息。

4. 对点云进行运行补偿

运动补偿是一个通用的点云处理过程,可以直接复用velodyne driver中compensator模块的算法逻辑。

5. 配置dag文件

将各个数据处理环节定义为component后,需要将各个component组成一个lidar数据处理pipeline,

6. 运行lidar驱动并查看点云

完成以步骤后,就可以通过以下命令来启动lidar驱动。

mainboard -d /path/to/lidar_driver.dag

此时通过cyber_visualizer选择对应的点云channel,就可以可视化查看点云了。

  • 26
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值