0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

自动驾驶如何实现车辆配置,Apollo3.5车辆配置方案为你揭晓

YB7m_Apollo_Dev 来源:lq 2019-05-06 16:45 次阅读

Apollo 开放车辆的接口标准主要涉及到两大部分,即线控系统和车辆系统。Apollo 对这两者的功能指标、性能指标、安全指标进行一系列的约定并提出了相关标准。以常见的刹车和油门为例, Apollo 对这两者的控制精度、控制力度、系统的周期时间、响应时间都有着严格的规定。

线控系统对指令越界保护和控制的处理等安全指标都有着明确约定以及标准化的要求。而车辆系统要求有相对稳定的CAN信号通道,同时对于车辆电源,包括电压、功率、最大波动、输出误差都有一系列的规定,以够保证在整个自动驾驶过程中电源输出稳定。

本文由Apollo开发者社区认证布道师-阿渊撰写,对Apollo 3.5 车辆配置方案进行了详细讲解,希望这篇文章给感兴趣的同学带来更多帮助。

以下,ENJOY

最近在研究百度无人车 Apollo 的工厂模式及车辆配置方式,有一些小心得希望和大家一起分享。

Apollo 无人驾驶平台支持 Lincoln MKZ、WEY VV6 等来自多个 OEM 的不同车型。

Apollo 兼容的开放车型,来源: http://apollo.auto/vehicle/certificate_cn.html

众所周知,各车厂车型的配置方式、接口、信号都各不相同。那么 Apollo 是如何兼容各个车型的呢?本文将从以下三个层次来回答这个问题。

从平台构架上看,Apollo 借助“开放车辆认证平台 (Open Vehicle Certificate Platform)"完成与汽车的交互,其他上层平台无需关注底层实现。

Apollo 3.5 架构图, 来源:https://github.com/ApolloAuto/apollo

Apollo 的平台架构如上图所示,Apollo 开放平台包括了以下几个部分:

云端服务平台

开源软件平台

硬件开发平台

开放车辆认证平台

这里我们着重了解一下“开放车辆认证平台”。

来源:http://apollo.auto/developer_cn.html

目前各个 OEM 厂商的大多使用 CAN 总线协议来进行车辆内部各个 ECU 节点之间的通讯。CAN 总线通讯协议中各节点的信息使用 DBC(Database Can)文件来进行来进行描述。

The DBC file describes the communication of a single CAN network. This information is sufficient to monitor and analyze the network and to simulate nodes not physically available.

DBC文件描述了单个CAN网络通信。 此信息足以监视和分析网络并模拟物理上不可用的节点。[1]

各车厂的 DBC 文件定义通常并不相同,并且是严格保密的。为了解决开发者在开发无人驾驶系统中与车辆交互的问题,Apollo 搭建了《开放汽车认证平台》,并提出了开放车辆认证计划。

开放车辆认证计划第一次在业内提出标准化的无人驾驶系统与车辆接口,透过这个计划,车企/车辆提供商可以更方便的将车辆平台接入到Apollo开放平台,从而覆盖更广泛的无人驾驶开发者人群,加速无人驾驶能力的上车部署。[2]

该平台作为软硬件中间层,提出了开放车辆接口标准,定义了系统与汽车的线控接口,负责完成系统与汽车的具体交互。该平台抽象出了与车型无关的信号作为上层算法模块的输入,使得上层平台可以与底层车辆信号解耦。

Apollo 的开放车辆接口标准定义了 Apollo 需要的诸多用于控制车辆和接收反馈的信号。大体而言, Apollo 需要车企提供线控转向、驱动、制动、档位、驻车、灯光、雨刮控制、喇叭控制等控制及故障反馈等接口。Apollo 乘用车的线控需求具体的详细信息可参见下列规范。

https://link.zhihu.com/?target=http%3A//apollo-homepage.bj.bcebos.com/Apollo_by_wire_requirement.xlsx

此外,根据《开放车辆认证车企认证流程》,想要接入到 Apollo 开放平台,车企需要遵循 Apollo 的接口规范,向 Apollo 开放平台提供对应的 DBC 文件。

Apollo 在与开放车辆的信号交互上和开放车辆配置上均使用了Protobuf。

Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化。它很适合做数据存储或 RPC 数据交换格式。可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。目前提供了 C++JavaPython 三种语言的 API。[3]

通常车企会使用 DBC 文件来完成 CAN 信号的定义和解析, Apollo 则大量使用了 Protobuf 来进行模块间的通信和配置,因此车企需要使用 Apollo 提供的工具基于 DBC 来生成 Apollo 可用的 Proto 文件 (如下所示)。

1//modules/canbus/proto/wey.proto 2messageWey{ 3optionalAds_shifter_115ads_shifter_115=1;//controlmessage 4optionalAds_eps_113ads_eps_113=2;//controlmessage 5optionalStatus_310status_310=3;//reportmessage 6optionalVin_resp3_393vin_resp3_393=4;//reportmessage 7optionalVin_resp2_392vin_resp2_392=5;//reportmessage 8optionalVin_resp1_391vin_resp1_391=6;//reportmessage 9optionalAds_req_vin_390ads_req_vin_390=7;//controlmessage10optionalAds1_111ads1_111=8;//controlmessage11optionalFbs2_240fbs2_240=9;//reportmessage12optionalFbs1_243fbs1_243=10;//reportmessage13optionalFbs4_235fbs4_235=11;//reportmessage14optionalFail_241fail_241=12;//reportmessage15optionalFbs3_237fbs3_237=13;//reportmessage16optionalAds3_38eads3_38e=14;//controlmessage17}

Protobuf 提供的 Codegen 工具会根据 Proto 文件中定义的变量生成可直接使用的 C++ 代码,十分便捷。

Protobuf 提供了一种名为TextFormat的序列化格式,该格式类似于Json,清晰易懂。配合事先定义的 Proto 文件, 开发者可以轻易实现从可读的配置文件到具体对象的实例的反射,配置文件经过反序列化后可以作为业务代码类的输入。这种方式使得配置变得便捷,不易出错,且具有很好的向后兼容性。

Apollo 的代码中大量使用了这种方式来管理配置。Apollo 激活车辆的配置文件为 modules/canbus/conf/canbusconf.pb.txt,开发者可以在这里定义车型及对应的 CAN card 的参数,开发者只需修改 "vehicle_parameter" 相应的字段,即可使 Apollo 支持对应的车型。

1#modules/canbus/conf/canbus_conf.pb.txt 2vehicle_parameter{ 3brand:LINCOLN_MKZ 4max_enable_fail_attempt:5 5driving_mode:COMPLETE_AUTO_DRIVE 6} 7 8can_card_parameter{ 9brand:ESD_CAN10type:PCI_CARD11channel_id:CHANNEL_ID_ZERO12}1314enable_debug_mode:false15enable_receiver_log:false16enable_sender_log:false

上述配置文件的参数的含义是由下面的 Proto 文件决定的。

1//modules/canbus/proto/canbus_conf.proto 2messageCanbusConf{ 3optionalapollo.canbus.VehicleParametervehicle_parameter=1; 4optionalapollo.drivers.canbus.CANCardParametercan_card_parameter=2; 5optionalboolenable_debug_mode=3[default=false]; 6optionalboolenable_receiver_log=4[default=false]; 7optionalboolenable_sender_log=5[default=false]; 8} 910//modules/canbus/proto/vehicle_parameter.proto11//Apollo支持了LINCON_MKZ,GEM,LEXUS等多种车型12messageVehicleParameter{13enumVehicleBrand{14LINCOLN_MKZ=0;15GEM=1;16LEXUS=2;17TRANSIT=3;18GE3=4;19WEY=5;20}21optionalVehicleBrandbrand=1;22optionaldoublemax_engine_pedal=2;23optionalint32max_enable_fail_attempt=3;24optionalChassis.DrivingModedriving_mode=4;25}2627//modules/drivers/canbus/proto/can_card_parameter.proto28messageCANCardParameter{29enumCANCardBrand{30FAKE_CAN=0;31ESD_CAN=1;32SOCKET_CAN_RAW=2;33HERMES_CAN=3;34}35...36}

另外要提到一点的是,Protobuf 提供了两个版本的库,即精简版 ("libprotobuf-lite.so") 和 完整版 ("libprotobuf.so" )。

The "lite" library is much smaller than the full library, and is more appropriate for resource-constrained systems such as mobile phones.

精简版体积远小于完整版,因此更适合使用在诸如移动电话等资源受限的系统上。[4]

精简版的 Protobuf 常用于嵌入式设备,但精简版的库并不支持 TextFormat 的反射功能。开发者如果想兼具代码体积和功能的话,可以考虑自己写一套格式化语言的反射机制,有兴趣的同学可以参考《简单的 C++ 结构体字段反射》。

Apollo Software Overview, 来源:https://github.com/ApolloAuto/apollo

从软件实现上看,Apollo 通过CANBus模块来实现对车辆的管理和通讯 。

CANBus 模块接收并执行来自 Control 模块的指令,同时收集汽车底盘的状态,这些状态是Apollo 抽象出的一组与车型无关的信号。Canbus 模块处理这些状态与各个汽车底盘信号的映射关系,随后将这些状态反馈回 Control 模块。基于这样的设计,Apollo 得以兼容多个不同的车型。

chassis.proto文件对 Apollo 抽象出的信号进行了定义,大体包括下列信息:

Chassis 信号

CANBus 模块主要由以下两个部件组成

Vehicle:the vehicle itself, including itscontrollerandmessage manager

CAN Client- CAN client has been moved to/modules/drivers/canbussince it is shared by different sensors utilizing the canbus protocol[5]

在这里着重介绍一下Vehicle部分。

Vehicle的Controller(modules/canbus/vehicle/vehicle_controller.h)的类图如下(有简化):

Vehicle Controller 类负责完成与汽车底盘的具体交互,下面对部分公有接口做一些解释。

1/***@briefstartthevehiclecontroller.*注:该函数会在内部起一个名为"SecurityDogThreadFunc"的线程,该线程会周期性的检*查与底盘的通讯状况,关键信号是否有响应,是否有错误等等。*@returntrueifsuccessfullystarted.*/ 2virtualboolStart()=0; 3 4/***@briefstopthevehiclecontroller.*/ 5virtualvoidStop()=0; 6 7/***@briefcalculateandreturnthechassis.*注:该函数完成了汽车底盘信号和Apollo内部定义的底盘状态信号的映射。*@returnsacopyofchassis.Usecopyheretoavoidmulti-threadissues.*/ 8virtualChassischassis()=0; 910/***@briefupdatethevehiclecontroller.*注:该函数负责执行来自Control模块的具体的指令。根据指令的要求和汽车目前所处*的模式(完全自动、完全手动、自动转向等)来为执行器的信号(档位、油门、转向等)进行*赋值。*@paramcommandthecontrolcommand*@returnerror_code*/11virtualcommon::ErrorCodeUpdate(constcontrol::ControlCommand&command);

Vehicle 的 MessageManager 类负责完成对具体信号的接收、发送、解析等,其类图如下:

1//modules/drivers/canbus/can_comm/message_manager.h 2//用于指定系统向汽车底盘发送的控制型号 3template 4template 5voidMessageManager::AddSendProtocolData(); 6 7//用于指定系统接收的信号 8template 9template10voidMessageManager::AddRecvProtocolData();

接下来我们以 Wey VV6 车型为例,来分析 Apollo 是如何在代码层面上完成配置任务的。

Wey 文件夹包含有如下文件:

根据 Apollo 的官方文件how_to_add_a_new_vehicle, 想要为 Apollo 添加 Wey 车型需要完成以下内容:

实现新的车辆控制器--wey_controller.cc,继承VehicleController类

实现新的消息管理器--wey_message_manager.cc继承MessageManager类

实现新的车辆工厂类--wey_vehicle_factory.cc, 继承AbstractVehicleFactory类

更新配置文件

在modules/canbus/vehicle/vehicle_factory.cc中进行注册

更新配置文件modules/canbus/conf/canbus_conf.pb.txt

通过上述方式可以增加新车型的原因在于 Apollo 的配置是基于工厂模式实现的。

工厂方法模式(Factory method pattern)是一种实现了“工厂”概念的面向对象设计模式。就像其他创建型模式一样,它也是处理在不指定对象具体类型的情况下创建对象的问题。工厂方法模式的实质是“定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类。工厂方法让类的实例化推迟到子类中进行。”[6]

Canbus 模块中 Vehicle 相关的内容使用工厂模式抽象出了 VehicleController,MessageManager,AbstractVehicleFactory 三个接口。 Canbus 的业务代码(canbus_component.cc)通过以上接口来操纵具体的对象,用户无需关心具体的对象是什么,从而实现了业务逻辑和目标对象的解耦。

工厂方法模式的定义和实现的相关讲解有很多,本文就不再赘述,可参考下列链接和书籍:

https://en.wikipedia.org/wiki/Factory_method_pattern

《设计模式:可复用面向对象软件的基础》

《Head First 设计模式》

Apollo 社区布道师贺志国老师曾对 Apollo 的工厂模式进行过介绍, 接下来本文会在此基础上继续延伸。

https://blog.csdn.net/davidhopper/article/details/79197075

Apollo 提供了一个工厂模版(modules/common/util/factory.h),该模版可支持任何类型的输入,类图如下:

工厂模版

Factory类包含了Register()、Unregister()、Empty()、CreateObjectOrNull()、CreateObject()等公有函数,其中Register()、Unregister()函数用于注册和反注册产品类,其作用与经典模式中抽象工厂接口类的功能类似,Empty()函数用于判断当前工厂类中是否包含产品创建函数,CreateObjectOrNull()、CreateObject()函数用于创建可能包含空指针和不包含空指针的产品类对象。[7]

Factory 工厂模版维护了一个 Map 用来管理 IdentifierType 和 ProductCreator 的键值对,根据输入的 IdentifierType, 模版可返回 ProductCreator 生产的产品,从而实现了从 IdentifierType 到 Product 的“映射“。

在Canbus 模块中,工厂类为 "VehicleFactory", 该类继承于工厂模版 "Factory" 。VehicleFactory 工厂维护了键值对为 VehicleParameter::VehicleBrand和AbstractVehicleFactory 的 Map。

如下所示,每新注册一种车型,该 Map 中就会插入一条汽车品牌(VehicleBrand)和该品牌汽车生产工厂(AbstractVehicleFactory )的键值对。

1voidVehicleFactory::RegisterVehicleFactory(){ 2Register(apollo::common::LINCOLN_MKZ,[]()->AbstractVehicleFactory*{ 3returnnewLincolnVehicleFactory(); 4}); 5Register(apollo::common::GEM,[]()->AbstractVehicleFactory*{ 6returnnewGemVehicleFactory(); 7}); 8Register(apollo::common::LEXUS,[]()->AbstractVehicleFactory*{ 9returnnewLexusVehicleFactory();10});11Register(apollo::common::TRANSIT,[]()->AbstractVehicleFactory*{12returnnewTransitVehicleFactory();13});14Register(apollo::common::GE3,[]()->AbstractVehicleFactory*{15returnnewGe3VehicleFactory();16});17Register(apollo::common::WEY,[]()->AbstractVehicleFactory*{18returnnewWeyVehicleFactory();19});20}

当VehicleFactory类的"CreateVehicle" 方法被调用时, VehicleFactory会根据输入的汽车品牌,在 Map 中查找并返回可以生产这种汽车的工厂 。

例如输入汽车品牌"WEY" , VehicleFactory 会返回 WeyVehicleFactory ,WeyVehicleFactory 继承于 AbstractVehicleFactory 。

1/**2*@briefCreatesanAbstractVehicleFactoryobjectbasedonvehicle_parameter3*@paramvehicle_parameterisdefinedinvehicle_parameter.proto4*/5std::unique_ptrCreateVehicle(6constVehicleParameter&vehicle_parameter);

AbstracVehicleFactory 工厂会产出一组适用于该品牌车型的产品即 MessageManager 和 Vehicle controller。

以 “Wey” 为例, WeyVehicleFactory 会产出 WeyMessageManager 和 WeyController 用于实现 “Wey”车型的通讯和控制。

完整的类图如下所示:

最后对 CANBus 模块的CanbusComponent进行介绍 。该类继承于 " TimerComponent", 主要作用为处理来自控制模块的控制指令,并将信号消息发送至 Can card。

CanbusComponent 的初始化函数 (init )主要完成了以下工作:

1. 读取 CANBus 配置文件

1if(!GetProtoConfig(&canbus_conf_)){2AERROR<< "Unable to load canbus conf file: " << ConfigFilePath();3    return false;4  }

2. 根据配置文件初始化 Can—client.

1can_client_=can_factory->CreateCANClient(canbus_conf_.can_card_parameter());

3. 根据配置文件获取汽车工厂

1VehicleFactoryvehicle_factory;2vehicle_factory.RegisterVehicleFactory();3autovehicle_object=4vehicle_factory.CreateVehicle(canbus_conf_.vehicle_parameter());

4. 获取该汽车工厂生产的 message_manager 和 Vehicle_contorller

1message_manager_=vehicle_object->CreateMessageManager();2...3//初始化can_receiver_和can_sender_4if(can_receiver_.Init(can_client_.get(),message_manager_.get(),5canbus_conf_.enable_receiver_log())!=ErrorCode::OK){...}6if(can_sender_.Init(can_client_.get(),canbus_conf_.enable_sender_log())!=7ErrorCode::OK){...}89vehicle_controller_=vehicle_object->CreateVehicleController();

5. 使能 Can 收发和 Vehicle_contorller

初始化完成之后,CanbusComponent 会周期性的报告车身状态,并执行来自 Control 模块和 Guardian 模块的命令。

1boolCanbusComponent::Proc(){ 2//publish底盘信息 3PublishChassis(); 4if(FLAGS_enable_chassis_detail_pub){ 5//Publish底盘的细节信息 6PublishChassisDetail(); 7} 8returntrue; 9}1011//事件触发,执行来自Control模块的指令12voidCanbusComponent::OnControlCommand(constControlCommand&control_command){...}1314//事件触发,执行来自Gurdian模块的指令15voidCanbusComponent::OnGuardianCommand(16constGuardianCommand&guardian_command){17apollo::control::ControlCommandcontrol_command;18control_command.CopyFrom(guardian_command.control_command());19OnControlCommand(control_command);20}

Apollo 开放车辆认证平台定义了系统与线控车辆的接口标准,并且从各个车型中抽象出了用于算法的与具体车型无关的信号。

在软件模块中, Canbus 模块负责处理这些信号与车辆底盘信号的映射。

Apollo 以 Protobuf 为基础使得车辆配置管理变得十分简洁易用。

Apollo 使用抽象工厂模式,使业务逻辑得以与具体的车辆解耦。

上述方式的综合应用,使得 Apollo 得以支持多种不同的车辆。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 自动驾驶
    +关注

    关注

    773

    文章

    13032

    浏览量

    163206
  • 无人车
    +关注

    关注

    1

    文章

    294

    浏览量

    36276
  • Apollo
    +关注

    关注

    5

    文章

    326

    浏览量

    18292

原文标题:开发者说 | Apollo 3.5 车辆配置方案

文章出处:【微信号:Apollo_Developers,微信公众号:Apollo开发者社区】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    [科普] 谷歌自动驾驶汽车发展简史,都来了解下吧!

    英里(约40公里),计划生产100-200。  一年后,谷歌开始在山景城对原型进行道路测试。  2015年7月,谷歌开始在德克萨斯州奥斯汀测试其自动驾驶汽车,车型雷克萨斯RX45
    发表于 10-25 11:08

    细说关于自动驾驶那些事儿

    展示在市区的自动驾驶情境。这台由光达、定位系统和摄影机组成的自动驾驶,在车辆偏离车道时可自动导回车道。三种系统的作用优先级,第一是光达,不
    发表于 05-15 17:49

    3天造出自动驾驶汽车的百度Apollo,背后竟有50多个后台

    的答案是3天。活动当天,AutonomouStuff利用Apollo1.0开放能力改装而成的循迹自动驾驶在外场路测,而且两台自动驾驶车辆
    发表于 07-07 18:28

    所有看见的车辆都为自动驾驶提供了动力

    系统正在激起业界最大的兴趣和活动,并且预计,并非不合理地,最终它们将成为实现自动驾驶汽车的关键因素,这将使驾驶员成为一个单纯的乘客。这将减轻与人体注意力丧失,误判和疲劳相关的风险。图像感应将成为大量
    发表于 10-16 09:46

    UWB主动定位系统在自动驾驶中的应用实践

    ,确保车辆自动驾驶安全。但即使我们的技术可以实现真正意义上的自动驾驶,目前来看成本还是非常高的。若干企宣布了2020-2021年左右
    发表于 12-14 17:30

    联网对自动驾驶的影响

    联网与智能驾驶联网和自动驾驶密切相关,很大程度上可以理解是对自动驾驶高阶版本的增强和补充,
    发表于 03-19 06:20

    中国自动驾驶行业前景看好,国产技术迅速发展

    作为参照标准,滋生于本土的百度更了解国内复杂的驾驶环境更复杂,也拥有更多的中国道路数据和资源。因此,Apollo必然成为国内外企在切入中国自动驾驶市场的最佳合作方。从最初布局
    发表于 04-03 05:36

    从辅助驾驶自动驾驶: 感知型车辆建立在底层高质量的传感器数据基础之上

    这就好比是我们时代的登月计划。从传感器到人工智能(AI),经典的电子供应链已经形成了一个协作矩阵,致力于实现自动驾驶车辆的安全性。为此,还需进行大量硬件和软件开发工作,以确保驾驶员、乘
    发表于 06-16 18:53

    转发:聊聊边缘计算在自动驾驶中的应用场景

    “智慧” 有效执行,可以实施主动控制,并能够进行人机交互与协同。自动驾驶是“智慧”和“能力” 的有机结合,二者相辅相成,缺一不可。实现“智慧”和“能力”,自动驾驶技术一般包括环境感知
    发表于 07-21 14:12

    自动驾驶的人交互接口设计方案

    。随着驾驶任务的消失和车辆控制权人数的增加,自动驾驶也必然会带来全新的人关系。因此,面向自动驾驶
    发表于 07-30 07:57

    如何保证自动驾驶的安全?

    自动驾驶技术为人们勾勒出了一副美好的未来出行的画面:坐上没有方向盘的汽车,一觉睡到公司门口;甚至我们可能不再拥有一汽车,需要出门时共享自动驾驶汽车会自己到来,送到目的地时会自行离开……不过
    发表于 10-22 07:45

    UWB定位可以用在自动驾驶

    的技术可以实现真正意义上的自动驾驶,目前来看成本还是非常高的。若干企宣布了2020-2021年左右实现L3自动驾驶
    发表于 11-18 14:15

    网联化自动驾驶的含义及发展方向

    数据基础的自动驾驶业务产生不可估量的影响,是成功实现自动驾驶的基础 [4] 。自动驾驶车辆通过
    发表于 01-12 15:42

    自动驾驶车辆中AI面临的挑战

    自动驾驶车辆中采用的AI算法自动驾驶车辆中AI面临的挑战
    发表于 02-22 06:39

    自动驾驶技术的实现

    的带宽有了更高的要求。从而使用以太网技术及中央域控制(Domain)和区域控制(Zonal)架构是下一代车载网络的发展方向。然而对于自动驾驶技术的实现,涉及到感知、规划、执行三个层面。由于车辆行...
    发表于 09-03 08:31