ROS机器人平台搭建

搭建ROS的机器人平台
2016-09-12  机器人2025
作者:雷一鸣
此次开发的目的是针对履带式底盘开发出完整的自主导航机器人,机器人基于ROS架构,能够实现SLAM,目标识别,交互控制等功能。
    
第一步,针对基于mbed的STM32F4系列控制器开发机器人底层功能,如:控速,反馈,里程测量等;
    
第二步,利用rosserial完成上位机与控制器的通信,并且实现Navigation Stack所需接口;
    
第三步,开发上层功能包,完成交互控制,自主建图,仿真等功能。第四步,针对特定要求,加入目标识别功能,加入GPS加强室外导航准度。

开发计划总览
ROS Navigation Stack 简介
功能
    
Navigation Stack能够根据机器人的里程计数据,传感器数据完成自定位并测绘地图,还能做出路径规划使机器人安全地自主地抵达目标地点。

话题结构图解
ROS机器人平台搭建_第1张图片

上图是Navigation Stack中各个包之间的话题关系。小方框和椭圆代表的是各个部件,箭头上标出了相连部件之间通信的话题名称以及消息类型。中间的大方框代表非常重要的move_base包,其中包含了全局地图,局部地图,全局路径以及局部路径,还有恢复机制,其中的结构我们暂时不需要了解。以大方框为界可以看到有五个话题输入(”tf”, “odom”, “/map”, “sensor topics”),一个话题输出(“cmd_vel”)。输入的话题对应着五个需要的接口:tf转换关系,odom里程信息,map地图数据,传感器数据;一个输出的话题即底盘的速度控制。

 各个部件由不同的颜色划分重要级。白色 代表必需但已经实现的部件,灰色 代表可选且已经实现的部件,蓝色 代表必需并且是针对硬件平台的部件。所以底层开发至少需要实现以下功能:
    
1、解析cmd_vel话题数据,并将相应的速度命令送达给电机执行
    
2、将速度反馈累加,计算成odom里程信息,并传达给ROS上层
    
3、完成机器人的tf构建
   
 4、发布必要的传感器数据,一般是激光数据(sensor_msgs/LaserScan),或者是点云数据(sensor_msgs/PointCloud)

底层必需的接口实现
接收 cmd_vel 话题,并将其转换为左右轮速

消息类型:geometry_msgs/Twist

消息格式:


说明:消息中 linear 和 angular 分别为线速度和角速度,都是3维向量,每一维分别表示x,y,z方向上的值。cmd_vel是 move_base 发布的速度控制话题,底层需要将其解析为左右轮速并转换成相应 PWM 信号发送给电机。

发布 odom 话题,提供粗略的里程信息

消息类型:nav_msgs/Odometry

消息格式:


说明:实现较为精准的自定位是一个很重要同时难度也很大的问题,Navigation中主要是由激光数据和底盘的里程数据来融合定位。计算里程信息需要将底层反馈的速度值积分得到实时的位姿和速度。 pose 表示的是实时的粗略的位姿, twist 表示的是实时的速度。 header 包含了时间戳,以及父坐标系等信息。 child_frame_id 表示子坐标系。

根据底盘配置Navigation Stack
TF 配置
    
系统在运行过程中必须知道各个坐标系之间的转换关系,这一部分由 TF tree 来管理。简单的实现方法是调用 robot_state_publisher 包,输入建模好的 urdf 文件,就可以自动往外广播 TF 消息。所以这部分主要工作在于 urdf 的建模。

传感器数据采集
    
这里的传感器指激光雷达或者深度相机。由于单片机的性能问题,这部分拿到上位机来做,主要是由相关设备的驱动来完成。所以选择设备时,最好选择有相应的ROS驱动的设备。这部分主要工作在于调试设备的参数。

多传感器融合定位
    
自定位是很重要的一部分,自定为的精度直接影响到建图导航的准确性。单靠一个传感器可能是不够的,尤其是采用 kinect 之类只有小角度的景深设备。这时候就需要用到多传感器融合的方法,ROS中提供了一个非常好的包—— robot_pose_ekf ,其利用扩展卡尔曼滤波,融合里程,激光,GPS数据来定位。这里的GPS是可选的。

调试方法
第一步:只调试底盘。包括测试底盘速度控制以及反馈速度是否准确, IMU , 码盘等机械参数设置等等
    
第二步:调试底层和上位机之间的通信,即 rosserial 的工作状况。有时候会产生数据量过大,波特率设置太小导致连接超时等问题。
    
第三步:确定底层和通信层无误后,针对环境要求,机械要求调试上层包的参数。

基于mbed的STM32F4系列控制器
总体思路
底盘的开发比较耗时的部分绝对是串口通信,特别是在linux下还没有windows下各种方便串口调试的工具。如果把大量的时间花在了串口通信显然是不划算的。这里我们用到了 rosserial 包,它是用python写的一个串口工具,能够很方便的实现底层与上位机的串口通讯,并且通信方式与ROS传统方式无异。

用这种方法的话,底盘完全就可以当成一个node,直接接收和发布相关的通信节点,对于整个系统的架构是非常清晰的。不过 rosserial 常被用于 Arduino ,STM系列的控制器只能使用 mbed 进行开发,才可以顺利地使用 rosserial 。

mbed 简介
mbed是一个面向ARM处理器的原型开发平台,它具体包括免费的软件库(SDK),硬件参考设计(HDK)和在线工具(Web)三部分内容,各个部分的具体介绍如下:
   
 SDK:mbed设计了一个硬件抽象层,从而屏蔽了不同mcu厂商提供了微处理之间的差异,对于用户来说,他只需要和这个硬件抽象层打交道即可,也就是说,用户基于mbed开发的应用可以很方便地更换使用不同厂商的arm微处理器,从而留给用户更多的选择。
   
 HDK:HDK是mbed提供的硬件参考设计,它是面向用户开发设计的,所以HDK提供了统一了程序上载接口,单步调试接口,串口调试接口,用户无需购买其它硬件就可以开始软件开发工作。
    
WEB:为了省去用户开发环境安装的麻烦,mbed提供了一个完备的基于浏览器的微处理器软件开发环境,包括代码编写,程序编译,版本控制等功能,用户只要上网就可以开发,编译结果只要下载保存到mbed开发板上即可工作,非常方便。

mbed 本身提供了比较好用的网页编辑器,能够针对不同平台调用相应的硬件库,并且只需要一键编译就可以得到二进制文件,文件可通过浏览器下载。 选择平台网址
https://developer.mbed.org/platforms/
ROS机器人平台搭建_第2张图片

上图就是选择控制器的页面,mbed目前支持的只是一小部分的控制器。对于初学者来说,在linux下有这样类似IDE的环境是很不错的。

gcc4mbed
老司机还是得离线用,然后自己编译呀,要不然总是不放心的~~而且离线之后就可以针对自己的板子来修改库文件达到移植的目的了。
我们需要下载一个编译工具—— gcc4mbed , https://github.com/adamgreen/gcc4mbed , 在这个网页下方有具体的安装方法,使用的时候只需要按照linux下安装的方法即可。

移植到新的设备: 添加新的设备到mbed
https://github.com/adamgreen/gcc4mbed/blob/master/notes/new_devices.creole#adding-new-devices-to-gcc4mbed

gcc4mbed例子:例子
https://github.com/adamgreen/gcc4mbed/tree/master/samples

makefile 配置选项: makefile
https://github.com/adamgreen/gcc4mbed/blob/master/notes/makefile.creole#make-variables

mbed API手册: handbook
https://developer.mbed.org/handbook/Homepage

下载工具则选用普通的JLink即可, 调试也是用JLink官网的 Debuger。具体下载地址可自行搜索,这里就不在赘述。

移植时需要注意的点
我根据自己的板子型号来具体介绍一下移植过程中需要注意的点。板子芯片型号是 STM32F405RG。

在移植的时候,我们需要在 gcc4mbed-master/external/mbed/libraries/mbed/targets/hal/TARGET_STM/TARGET_STM32F4 文件夹中新建一个针对我自己平台的文件夹。命名规则是 TARGET_BROADNAME BROADNAME 是给你的板子的一个命名,在写 makefiel 时也必须用这个名字。我这里选择了 TARGET_RED_F405RG 。

建立好了文件夹之后,把相近的 TARGET_NUCLEO_F401RE 文件夹中的内容拷贝过来。修改 PinNames.h 文件添加你需要重命名的引脚口。比如需要添加一个电机1的ADC,可以写成MOTOR1ADC=PC_0, 这样程序中使用 MOTOR1ADC 就相当于在使用 PC_0 端口了。

同样的方法,我们在 gcc4mbed-master/external/mbed/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4 中再使用一次。不过这次添加的是跟硬件有关的信息了。比如时钟频率等等。对于几个重要的属性,一定要仔细修改,否则程序运行的时候会出莫名其妙的错误。

rosserial
简单地介绍完 mbed ,接下来的重点则是 rosserial_mbed 了,参考网址: http://wiki.ros.org/rosserial_mbed/Tutorials/rosserial_mbed%20Setup

第一步,先下载 rosserial 包至可用的工作空间,并编译。
   
 第二步,执行以下命令,生成 rosserial_mbed 库。
    
注意:这里的 ros-lib-dir 是要存放库的地址,后面会用到。


第三步,添加相关环境变量。请分别把 gcc4mbed-dir, ros-lib-dir 替换为你的 gcc4mbed 所在的文件夹,和 rosserial_mbed 库所在文件夹。

 
第四步,修改 makefile ,添加外部库,示例如下:

ROS机器人平台搭建_第3张图片
PROJECT 是项目名称,编译链接后生成的二进制文件会以其命名。

DEVICES  是目标平台,必需是已有的目标平台,而且可以添加多个,用空格符分隔。可以添加自己的设备,方法参考上面的网址。

GCC4MBED_DIR 是 gcc4mbed 的文件夹,这里用环境变量的值代替。

USER_LIBS 是用户使用的库的文件夹,用到了什么库,就需要在这里声明库的文件夹。

剩下的不需要改动,进行编译之后,会生成一个或多个和目标平台名相同的文件夹,其中就包含了编译链接产生的文件,其中就有可以下载到板子里的 .bin 或者 .hex 文件。

底层功能的开发
速度控制与反馈
ROS 的 Navigation Stack 能够根据记录的地图自动进行路径规划,产生的速度控制命令话题 /cmd_vel 。同时,底盘也需要将实际速度反馈给上层,这个反馈的话题是 /odom

/cmd_vel

/cmd_vel 话题发布的消息类型是 geometry_msgs/Twist ,结构如下:

ROS机器人平台搭建_第4张图片
linear 表示线速度, angular 表示角速度。我们需要接收 /cmd_vel 话题,并将数据转换为左右轮速。这里我使用的是轨迹推演算法,具体推导请看
https://www.cs.princeton.edu/courses/archive/fall11/cos495/COS495-Lecture5-Odometry.pdf

设置轮速

由线速度和角速度推导出差速轮轮速的公式如下:
ROS机器人平台搭建_第5张图片

这里的 Vl , Vr 为计算得到的左右轮速, l 为轮轴距, V 为 X 轴线速度, w 为 Z 轴角速度。

注意:ROS中的坐标系是右手坐标系,简单地说就是以机器人正前方为 X 轴正向,正左方为 Y 轴正向,正上方为 Z 轴正向。右手法则中四指的方向为旋转正向,即逆时针方向。如下图:

ROS机器人平台搭建_第6张图片
OK,了解完这些,我们就可以开始了动手了。

ROS机器人平台搭建_第7张图片
只要接收到 cmd_vel 话题,就转换为差速轮轮速,并马上设置电机速度,到达控制的效果。

反馈轮速
同时,为后面的发布 /odom 做准备,我们需要发布反馈速度话题 cmd_vel_feedback 。周期和编码器采集周期相同,我这里设置的是20ms,每当编码器数据更新新,就立即计算为 Twist 消息,然后发布出去。

公式如下:
ROS机器人平台搭建_第8张图片

代码:
ROS机器人平台搭建_第9张图片

/odom

除了接收速度话题,我们还需要发布 /odom 话题,来告诉上层目前机器人的一个粗略的定位。话题消息为 nav_msgs/Odometry ,格式如下:


header 是ROS常用的信息头,child_frame_id 是子坐标系, pose 是 header.frame_id 坐标系中,即机器人初始位置(0,0,0)的一个三维坐标,轮式机器人就只有二维信息了。 twist 是机器人当前的速度信息,处于 child_frame_id 坐标系中。之所以说这个是粗略的定位,是因为在实际情况中可能会碰到轮子打滑,地面不平整等因素的干扰。(当然上层会通过激光信息来匹配校准)

由于发布频率比较快,消息量比较大,这部分放到底层做会使串口中断过长,导致编码器采集遗漏的问题,所以这部分我们放到上位机来做。上位机程序我们需要接收上面提到的 cmd_vel_feedback 话题,然后进行累加计算。

ROS机器人平台搭建_第10张图片
这里我整个功能封装为一个 Odom 类,主要参考 roswiki 的 发布Odometry教程, vel_sub 是接收 cmd_vel_feedback 的接受者,在其回调函数 feedbackCB 中计算出 odometry 信息,并发布出去。注意,这里还需要广播一个 tf 消息,用以实时更新 base_link 与 odom 坐标系之间的转换关系。

原文链接:http://leiym.com/


你可能感兴趣的:(ROS平台搭建)