linux cpu占用率如何看
411
2022-11-13
自动驾驶如何实现车辆配置,Apollo3.5车辆配置方案为你揭晓
Apollo 开放车辆的接口标准主要涉及到两大部分,即线控系统和车辆系统。Apollo 对这两者的功能指标、性能指标、安全指标进行一系列的约定并提出了相关标准。以常见的刹车和油门为例, Apollo 对这两者的控制精度、控制力度、系统的周期时间、响应时间都有着严格的规定。
以下,ENJOY
最近在研究百度无人车 Apollo 的工厂模式及车辆配置方式,有一些小心得希望和大家一起分享。
众所周知,各车厂车型的配置方式、接口、信号都各不相同。那么 Apollo 是如何兼容各个车型的呢?本文将从以下三个层次来回答这个问题。
从平台构架上看,Apollo 借助“开放车辆认证平台 (Open Vehicle Certificate Platform)"完成与汽车的交互,其他上层平台无需关注底层实现。
Apollo 的平台架构如上图所示,Apollo 开放平台包括了以下几个部分:
云端服务平台
开源软件平台
硬件开发平台
开放车辆认证平台
这里我们着重了解一下“开放车辆认证平台”。
目前各个 OEM 厂商的大多使用 CAN 总线协议来进行车辆内部各个 ECU 节点之间的通讯。CAN 总线通讯协议中各节点的信息使用 DBC(Database Can)文件来进行来进行描述。
各车厂的 DBC 文件定义通常并不相同,并且是严格保密的。为了解决开发者在开发无人驾驶系统中与车辆交互的问题,Apollo 搭建了《开放汽车认证平台》,并提出了开放车辆认证计划。
开放车辆认证计划第一次在业内提出标准化的无人驾驶系统与车辆接口,透过这个计划,车企/车辆提供商可以更方便的将车辆平台接入到Apollo开放平台,从而覆盖更广泛的无人驾驶开发者人群,加速无人驾驶能力的上车部署。[2]
该平台作为软硬件中间层,提出了开放车辆接口标准,定义了系统与汽车的线控接口,负责完成系统与汽车的具体交互。该平台抽象出了与车型无关的信号作为上层算法模块的输入,使得上层平台可以与底层车辆信号解耦。
Apollo 的开放车辆接口标准定义了 Apollo 需要的诸多用于控制车辆和接收反馈的信号。大体而言, Apollo 需要车企提供线控转向、驱动、制动、档位、驻车、灯光、雨刮控制、喇叭控制等控制及故障反馈等接口。Apollo 乘用车的线控需求具体的详细信息可参见下列规范。
此外,根据《开放车辆认证车企认证流程》,想要接入到 Apollo 开放平台,车企需要遵循 Apollo 的接口规范,向 Apollo 开放平台提供对应的 DBC 文件。
Apollo 在与开放车辆的信号交互上和开放车辆配置上均使用了Protobuf。
通常车企会使用 DBC 文件来完成 CAN 信号的定义和解析, Apollo 则大量使用了 Protobuf 来进行模块间的通信和配置,因此车企需要使用 Apollo 提供的工具基于 DBC 来生成 Apollo 可用的 Proto 文件 (如下所示)。
Protobuf 提供的 Codegen 工具会根据 Proto 文件中定义的变量生成可直接使用的 C++ 代码,十分便捷。
Protobuf 提供了一种名为TextFormat的序列化格式,该格式类似于Json,清晰易懂。配合事先定义的 Proto 文件, 开发者可以轻易实现从可读的配置文件到具体对象的实例的反射,配置文件经过反序列化后可以作为业务代码类的输入。这种方式使得配置变得便捷,不易出错,且具有很好的向后兼容性。
上述配置文件的参数的含义是由下面的 Proto 文件决定的。
另外要提到一点的是,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]
从软件实现上看,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 类负责完成与汽车底盘的具体交互,下面对部分公有接口做一些解释。
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)通过以上接口来操纵具体的对象,用户无需关心具体的对象是什么,从而实现了业务逻辑和目标对象的解耦。
工厂方法模式的定义和实现的相关讲解有很多,本文就不再赘述,可参考下列链接和书籍:
《设计模式:可复用面向对象软件的基础》
《Head First 设计模式》
Apollo 社区布道师贺志国老师曾对 Apollo 的工厂模式进行过介绍, 接下来本文会在此基础上继续延伸。
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 模块的命令。
Apollo 开放车辆认证平台定义了系统与线控车辆的接口标准,并且从各个车型中抽象出了用于算法的与具体车型无关的信号。
在软件模块中, Canbus 模块负责处理这些信号与车辆底盘信号的映射。
Apollo 以 Protobuf 为基础使得车辆配置管理变得十分简洁易用。
Apollo 使用抽象工厂模式,使业务逻辑得以与具体的车辆解耦。
上述方式的综合应用,使得 Apollo 得以支持多种不同的车辆。
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~