ROS与STM32的通信流程如图所示
主要包含两个方面:
小车里程计数据的上传与接收
控制指令的下发与接收
1.原始消息内容
在ROS中,里程计数据主要包括机器人的位姿(位置和姿态),以及机器人的速度(线速度和角速度)。对于本实验所用到的麦轮地面机器人,只需要知道机器人的x轴与y轴线速度、x轴与y轴位置、z轴角速度、偏航角即可。
由于对速度积分可以得到位置,对角速度积分可以得到角度,所以STM32端上传的里程计数据只需要包括机器人的 x轴与y轴线速度、z轴角速度 ,ROS端在接收到这些数据后,进行积分即可得到位置和角度。
另外,在本实验用到的STM32端集成了一个ICM20602姿态传感器,其中内置了姿态解算算法,可以获得准确的机器人姿态数据,因此本实验使用STM32端上传的偏航角来代替对角速度积分得到的航向角。
所以STM32上传的里程计数据包括机器人的x轴线速度、y轴线速度、z轴角速度、偏航角。
与里程计数据类似,对于麦轮地面机器人,控制指令只需要包括机器人的x轴速度、y轴速度、z轴角速度即可,机器人坐标系如图所示:
2.转换为字节数组
知道了消息的原始数据,还需要将它转换成传输效率更高的字节数组,如图:
在C/C++中,有很多种将原始数据转换为字节数组的方法,其中一种常用的方法是使用联合体(union)。
联合体的所有成员占用同一段内存,修改一个成员会影响其余成员,如果要实现一个float数据与字节数组的互相转换,我们可以定义如下的联合体:
typedef union{ float data; uint8_t data8[4]; }data_u;
这个联合体中有两个成员,一个是32位的float数据data,另一个同样是占据了32位字长的字节数组data8,根据联合体的性质,这两个成员所在的内存位置是一样的,也就是说,改变其中任何一个成员的值,另一个也会被改变。
利用这个性质,我们就可以实现float与字节数据的互相转换。
3.添加帧头和校验码
本实验选择常用的0xAA 0x55作为帧头,同时对原始数据转换得到的字节数组进行求和,将结果保存在1字节数据中,作为校验码。
准备工作:
1.在ROS端安装serial功能包
sudo apt-get install ros-melodic-serial
2.在ROS端创建一个功能包,命名为xrobot,添加依赖项roscpp rospy tf serial