本实验是实现机器人自主导航的重要步骤,对于轮式机器人,可以通过在底盘加装轮式里程计的方式来获得机器人的速度数据,这些数据可以用来辅助机器人实现自主定位,同时机器人还需要将控制指令发送给移动底盘,实现自主控制,本实验就将实现ros与移动底盘的通信。
实验环境:
· 软件环境:ubuntu18.04 + ros melodic、windows + keil 5、vscode
· 硬件环境:jetson nano(以下称为ros端)、小车(以下称为stm32端)
01 实验内容
ros与stm32的通信流程如图所示
主要包含两个方面:
· 小车里程计数据的上传与接收
· 控制指令的下发与接收
1.1 原始消息内容
在ros中,里程计数据主要包括机器人的位姿(位置和姿态),以及机器人的速度(线速度和角速度)。对于本实验所用到的麦轮地面机器人,只需要知道机器人的x轴与y轴线速度、x轴与y轴位置、z轴角速度、偏航角即可。
由于对速度积分可以得到位置,对角速度积分可以得到角度,所以stm32端上传的里程计数据只需要包括机器人的x轴与y轴线速度、z轴角速度,ros端在接收到这些数据后,进行积分即可得到位置和角度。
另外,在本实验用到的stm32端集成了一个icm20602姿态传感器,其中内置了姿态解算算法,可以获得准确的机器人姿态数据,因此本实验使用stm32端上传的偏航角来代替对角速度积分得到的航向角。
所以stm32上传的里程计数据包括机器人的x轴线速度、y轴线速度、z轴角速度、偏航角。
与里程计数据类似,对于麦轮地面机器人,控制指令只需要包括机器人的x轴速度、y轴速度、z轴角速度即可,机器人坐标系如图所示:
1.2 转换为字节数组
知道了消息的原始数据,还需要将它转换成传输效率更高的字节数组,如图:
在c/c++中,有很多种将原始数据转换为字节数组的方法,其中一种常用的方法是使用联合体(union)。
联合体的所有成员占用同一段内存,修改一个成员会影响其余成员,如果要实现一个float数据与字节数组的互相转换,我们可以定义如下的联合体:
typedef union{float data;uint8_t data8[4];}data_u;
这个联合体中有两个成员,一个是32位的float数据data,另一个同样是占据了32位字长的字节数组data8,根据联合体的性质,这两个成员所在的内存位置是一样的,也就是说,改变其中任何一个成员的值,另一个也会被改变。
利用这个性质,我们就可以实现float与字节数据的互相转换。
1.3 添加帧头和校验码
本实验选择常用的0xaa 0x55作为帧头,同时对原始数据转换得到的字节数组进行求和,将结果保存在1字节数据中,作为校验码。
准备工作:
1. 在ros端安装serial功能包
sudo apt-get install ros-melodic-serial 2. 在ros端创建一个功能包,命名为xrobot,添加依赖项roscpp rospy tf serial
02 里程计数据的上传与接收
2.1 通信协议
里程计数据格式(19字节)
2.2 stm32端/** * @brief 发送里程计数据 */void datatrans_odom(void){uint8_t _cnt = 0; data_u _temp; // 声明一个联合体实例,使用它将待发送数据转换为字节数组uint8_t data_to_send[100] = {0}; // 待发送的字节数组 data_to_send[_cnt++]=0xaa; data_to_send[_cnt++]=0x55;uint8_t _start = _cnt;float datas[] = {kinematics.odom.vel.linear_x, kinematics.odom.vel.linear_y, kinematics.odom.vel.angular_z, kinematics.odom.pose.theta };for(int i = 0; i < sizeof(datas) / sizeof(float); i++) {// 将要发送的数据赋值给联合体的float成员// 相应的就能更改字节数组成员的值 _temp.data = datas[i]; data_to_send[_cnt++]=_temp.data8[0]; data_to_send[_cnt++]=_temp.data8[1]; data_to_send[_cnt++]=_temp.data8[2]; data_to_send[_cnt++]=_temp.data8[3]; // 最高位 }uint8_t checkout = 0;for(int i = _start; i < _cnt; i++) { checkout += data_to_send[i]; } data_to_send[_cnt++] = checkout;// 串口发送 senddata(data_to_send, _cnt); }2.3 ros端
采用状态机的方式来接收stm32端上传的里程计数据,每读取一字节数据,则在状态机中处理一次,部分程序如下:uint8_t buffer = 0;ser.read(&buffer, 1); // ser是串口类的一个实例,该语句表示从串口中读取一个字节if(state == 0 && buffer == 0xaa){ state++;}else if(state == 1 && buffer == 0x55){ state++;}else if(state == 2){ data_receive[data_cnt++]=buffer;if(data_cnt == 17) {/* 进行数据校验 */uint8_t checkout = 0;for(int k = 0; k < data_cnt - 1; k++) { checkout += data_receive[k]; }if(checkout == data_receive[data_cnt - 1]) // 串口接收到的最后一个字节是校验码 {/* 校验通过,进行解码 */float vx, vy, vth, th; // x轴线速度,y轴线速度,z轴角速度,偏航角float* datas_ptr[] = {&vx, &vy, &vth, &th}; data_u temp;for(int i = 0; i linear.x, (float)cmd_vel->linear.y, (float)cmd_vel->angular.z}; for(int i = 0; i < sizeof(datas) / sizeof(float); i++){// 将要发送的数据赋值给联合体的float成员// 相应的就能更改字节数组成员的值 _temp.data = datas[i]; data_to_send[_cnt++]=_temp.data8[0]; data_to_send[_cnt++]=_temp.data8[1]; data_to_send[_cnt++]=_temp.data8[2]; data_to_send[_cnt++]=_temp.data8[3]; // 最高位 }// 添加校验码char checkout = 0;for(int i = _start; i = 13) {// 校验 u8 checkout = 0;for(int i = 0; i < cnt - 1; i++) { checkout += data_receive[i]; }if(checkout == data_receive[cnt - 1]) {// 校验通过,进行解码 datadecoder(data_receive); } state = 0; cnt = 0; } }else state = 0;}/** * @brief 数据解码 * @param data 待解码数组 */void datadecoder(u8 *data){ data_u temp;// x轴线速度 temp.data8[0] = data[0]; temp.data8[1] = data[1]; temp.data8[2] = data[2]; temp.data8[3] = data[3]; kinematics.exp_vel.linear_x = temp.data;// y轴线速度 temp.data8[0] = data[4]; temp.data8[1] = data[5]; temp.data8[2] = data[6]; temp.data8[3] = data[7]; kinematics.exp_vel.linear_y = temp.data;// z轴角速度 temp.data8[0] = data[8]; temp.data8[1] = data[9]; temp.data8[2] = data[10]; temp.data8[3] = data[11]; kinematics.exp_vel.angular_z = temp.data; }
你知道NFC在印刷传感器系统中的应用?
随着AI技术的发展,智能电话机器将越来越智能
芯海科技最新推出CSU11xx系列超低功耗衡器SoC芯片
通友一体成型电感,冷压机,PIM工艺
还在为低电压上电时的毛刺苦恼?这颗IC能搞定
ROS与移动底盘通信教程
Aigtek线束测试仪科普汽车线束故障有哪些
地平线CES展示2款AI专用芯片 打造嵌入式人工智能专用处理器
IC脚距小于2.54 毫米 没有适合的原型板怎么办?
温度传感器在微处理器中的应用
高速PCB的元件布局原则
探讨略显神秘的毫米波系统
针对比特币分叉风险 多个交易平台准备暂停比特币充值及提现
RFID的采用在衣物的识别与管理发挥重要的作用
双重悬念!一加5新品发布会邀请函发出,“飘洋过海”是什么梗?
如何在ELF 1开发板实现命令行显示中文
苹果销售额连续四个季度同比下滑,面临华为、小米等中国企业的正面挑战
HRG创新平台开发出高仿真人形机器人将于明年10月份投入市场
人工智能的研究领域和实现方法
TI推出面向低成本电机应用的 InstaSPIN-FOC 无传感器电机控制技术