动机
准备面试了,把以前做的无人驾驶小车项目整理一下。
小车底盘代码解析
小车采用的autolabor pro 1的底盘,官方提供了相应的ROS驱动代码,这里讲解一下他的运行逻辑。
bootst
是一个C拓展库,其中boost::asio::serial_port
类是一个用于处理串行通信的C类。
boost::asio::io_service
用于实现异步I/O操作,允许应用程序在等待I/O操作时同时执行其他任务,充分利用多核处理器。
小车与NUC通信采用串口通信。
//串口通信代码
typedef boost::shared_ptr<boost::asio::serial_port> serial_port_ptr;//首先定义了一个指针指向通信的端口
serial_port_ptr port_;
boost::asio::io_service io_service_;
port_ = serial_port_ptr(new boost::asio::serial_port(io_service_));//port_指向串口设备
port_->open(port_name_, ec_);//打开串口设备 port_name_通过ROS参数设置得到
port_->set_option(boost::asio::serial_port_base::baud_rate(baud_rate_));
port_->set_option(boost::asio::serial_port_base::character_size(8));
port_->set_option(boost::asio::serial_port_base::stop_bits(boost::asio::serial_port_base::stop_bits::one));
port_->set_option(boost::asio::serial_port_base::parity(boost::asio::serial_port_base::parity::none));
port_->set_option(boost::asio::serial_port_base::flow_control(boost::asio::serial_port_base::flow_control::none));
输出化串口后开始进行ROS订阅和发布
//发布者对象实例化,话题和最大保存的消息数(队列)
odom_pub_ = node.advertise<nav_msgs::Odometry>("wheel_odom", 10);//发布里程计信息
battery_pub_ = node.advertise<std_msgs::Int32>("remaining_battery", 1);//发布剩余电量信息
current_pub_ = node.advertise<std_msgs::Float32>("current", 1);//发布电流
voltage_pub_ = node.advertise<std_msgs::Float32>("voltage",1);//发布电压
ros::Subscriber cmd_sub = node.subscribe<geometry_msgs::Twist>("/cmd_vel", 10, &ChassisDriver::twist_callback, this);//订阅控制量,回调函数处理
ros::Timer send_speed_timer = node.createTimer(ros::Duration(1.0/control_rate_), &ChassisDriver::send_speed_callback, this);//定期调用来查询剩余电量
ros::Timer ask_battery_remainder_timer = node.createTimer(ros::Duration(1.0/sensor_rate_), &ChassisDriver::ask_battery_remainder_callback, this);
ros::Timer ask_current_timer = node.createTimer(ros::Duration(1.0/sensor_rate_), &ChassisDriver::ask_current_callback, this);
ros::Timer ask_voltage_timer = node.createTimer(ros::Duration(1.0/sensor_rate_), &ChassisDriver::ask_voltage_callback, this);
boost::thread parse_thread(boost::bind(&ChassisDriver::parse_msg, this));//创建新线程来解析消息
ros::spin();//启动ROS主循环。