Apollo之Canbus模块学习总结

Apollo之Canbus学习总结

根目录下的Canbus模块,其实是Chassis底盘控制模块,主要的作用是反馈车当前的状态(速度、航向、yaw_rate等信息),并且发送控制命令到车线控底盘,其底层实现基于 ’ drivers/canbus驱动模块.
此处的Canbus模块是车和自动驾驶软件之间的桥梁,通过canbus驱动(drivers/canbus)来实现车身信息发送给apollo上层软件,同时接收控制命令,发送给汽车线控底盘实现对车的控制

Canbus模块主流程

Canbus模块的目录结构如下:

|--- BUILD                       //bazel编译文件
|--- canbus_component.cc        //canbus主入口
|--- canbus_component.h
|--- canbus_test.cc            //canbus测试
|--- common                   //gflag配置
|--- conf                    //配置文件
|--- dag                    //dag依赖
|--- launch                //launch加载
|--- proto                //protobuf文件
|--- testdata            //测试数据
|--- tools  			//测试canbus总线工具
|--- vehicle		   //车辆控制协议

Canbus模块的主流程在文件"canbus_component.cc"中,canbus模块为定时触发,每10ms执行一次,发布chassis信息,而ControlCommand则是每次读取到之后触发回调"OnControlCommand",发送"control_command"到线控底盘.
定时触发回调函数,发布chassis信息:

bool CanbusComponent::Proc() {
	PublishChassis();
	if(FLAGS_enable_chassis_detail_pub) {
		PublishChassisDetail();
	}
	return true;
}

由于不同型号的车辆Canbus命令不一样,在"/vehicle"中适配不同型号车辆的canbus消息格式,所有的车都继承自Vehicle_controller基类,通过对Vehicle_controller的抽象来发送和读取canbus消息.
在这里插入图片描述车辆工厂模式(VehicleFactory)
在vehicle中可以适配不同的车型,而每种车型对应一个vehicle_controller,创建每种车辆的控制器(VehicleController)和消息管理(MessageMannger)流程如下:
在这里插入图片描述上述代码流程用到了设计模式的工厂模式,通过车辆工厂创造不用的车辆类型.

车辆控制器(VehicleController)

  1. Controller的init->start->stop流程
    在这里插入图片描述
    模块初始化(Init)过程获取了发送的消息格式,通过can_sender应该发送哪些消息,之后启动(start)之后启动一个看门狗,检查canbus消息格式是否正确,最后关闭(stop)模块则结束看门狗进程.
  2. chassis信息的获取
    在这里插入图片描述chassis的获取则是通过message_manager_获取chassis_detail,之后对chassis进行赋值.

CAN驱动程序(drivers/canbus)

canbus中的发送(CanSender)和接收(CanReceiver),还有消息管理(MessageManager)都是在"driver/canbus"中实现.

1. MessageManager
MessageManager主要作用是解析和保存canbus数据,而具体的接收和发送则是在"CanReceiver"和"CanSender"中,拿接收消息举例子,也就是说CanReceiver收到消息后,会调用MessageManager中的parse去解析消息,消息的解析协议在"modules/canbus/vehicle/lincoln/protocol"中,每个消息把自己对应的信息塞到"chassis_detail"中完成了消息的接收.
在这里插入图片描述
2. 消息接收(CanReceiver)
CanReceiver中的"Start"调用"RecvThreadFunc"实现消息的接收,这里会启动一个异步进程去完成接收.

template <typename SensorType>
::apollo::common::ErrorCode CanReceiver<SensorType>::Start() {
	if (is_init_ == false) {
		return::apollo:ErrorCode::CANBUS_ERROR;
	}
	is_running_.exchange(true);
	//启动异步接收消息
	async_result = cyber::Async(&CanReceiver<SensorType>::RecvThreadFunc, this);
	return ::apollo::common::ErrorCode::OK;
}

RecvThreadFunc通过"can_client"接收消息,然后通过"MessageManager"解析消息.

template <typename SensorType>
void CanReceiver<SensorType>::RecvThreadFunc() {
	while (isRunning()) {
		std::vector<CanFrame> buf;
		int32_t frame_num =  MAX_CAN_RECV_FRAME_LEN;
		
		//1. can_client_接收canbus数据
		if (can_client_->Receive(&buf, &frame_num)) !=
		::apollo::common::ErrorCode::OK {
			cyber::USleep(default_period);
			continue;
		}
		for (const auto &frame : buf) {
			uint8_t len = frame.len;
			uint32_t uid = frame.id;
			const uint8_t  *data = frame.data;
		}
		//2. MessageManager解析canbus数据
		pt_manager_->Parse(uid, data, len);
		if (enable_log_) {
			ADBUG << "recv_can_frame#" << frame.CanFrameString();
		}
	}
	cyber::Yield();
}
	AINFO << "can client receiver thread stopped";
}

消息发送(CanSender)
消息发送对应的是在CanSender中的"Start"调用"PowerSendThreadFunc",具体实现:

template <typename SensorType>
common::ErrorCode CanSender<SensorType>::Start() {
	if(is_running_) {
		AERROR << "Cansender has already started.";
		return common::ErrorCode::CANBUS_ERROR;
	}
	is_running_ = true;
	// 启动线程发送消息
	thread_.reset(new std::thread([this] { PowerSendThreadFunc(); } ));
	return common::ErrorCode::OK;
}

PowerSendThreadFunc再通过"can_client"发送消息:

	std::vector<CanFrame> can_frames;
	CanFrame can_frame = message.CanFrame();
	can_frames.push_back(can_frame);
   // 通过can_client发送消息
   if (can_client_ ->SendSingleFrame(can_frames) != common::ErrorCode::OK) {
		AERROR << "Send msg failed: "  << can_frame.CanFrameString();
	}

canbus客户端(CanClient)
CanClient 是canbus客户端,同时也是canbus的驱动程序,针对不同的canbus卡,对发送和接收进行封装,并且提供给消息发送和接收控制器使用.
在这里插入图片描述

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值