ROS与STM32通信

本文将实现在ROS上制作上位机节点接收来自STM32发送的IMU数据(这里为自定义),并将接收到的数据作为话题进行发布.由于发送的数据均为float型数据,而串口只支持发送字节型的数据,所以实现两者通信的关键就是float与字节数据的相互转换.目前我知道两种将float拆分成字节数组的方式

定义一个联合体(数据存放在同一地址)

typedef union{
	float data;
	uint8_t data8[4];
}data_u;

STM32端主要代码

// 联合体
typedef union
{
	float data;
	uint8_t data8[4];
} data_u;

//typedef union
//{
//    float yaw;
//    float pit;
//    float rol;
//}imu_data;
struct imu_data {
    float yaw;
    float pit;
    float rol;
};

void DataTrans(struct imu_data imu_data)
{
	uint8_t _cnt = 0;
	data_u _temp; // 声明一个联合体实例,使用它将待发送数据转换为字节数组
    uint8_t data_to_send[14]; // 待发送的字节数组
	
	data_to_send[_cnt++]=0xAA;
	data_to_send[_cnt++]=0xBB;
		
	// 将要发送的数据赋值给联合体的float成员
	// 相应的就能更改字节数组成员的值
	_temp.data = imu_data.yaw;
	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]; // 最高位
	
	_temp.data = imu_data.pit;
	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]; // 最高位
	
//	_temp.data = imu_data.rol;
    _temp.data = imu_data.rol;
	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]; // 最高位
	
    // 串口发送
	HAL_UART_Transmit(&huart2, data_to_send, _cnt, 0xFFFF); 
    HAL_Delay(500);
}

struct imu_data imu_data;
  /* USER CODE END 2 */
      imu_data.pit=1;
      imu_data.rol=2;
      imu_data.yaw=3;
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
      
    DataTrans(imu_data);
    imu_data.pit++;
      imu_data.rol++;
      imu_data.yaw++;
    /* USER CODE BEGIN 3 */
  }

ROS端主要为实现串口数据接收,并发布

新建窗口创建工作空间,编译,将工作空间加到环境变量

mkdir - p test_serial_ws/src
cd test_serial_ws
catkin_make

......

source devel/setup.bash


cd src
catkin_create_pkg serial_node roscpp serial

新建窗口创建工作空间,编译,将工作空间加到环境变量

cd serial_node
cd  src 
touch serial_node.cpp

由于要发布接收到的imu数据,所以我们需要新建一个msg文件,命名为my_msg.msg

float32 roll
float32 pitch
float32 yaw

文件下

#include <iostream>
#include <string>
#include <sstream>
using namespace std;

#include "ros/ros.h"
#include "std_msgs/String.h"
#include "serial/serial.h"

#include "serial_node/my_msg.h"

#define sBUFFER_SIZE 1024
#define rBUFFER_SIZE 1024
unsigned char s_buffer[sBUFFER_SIZE];
unsigned char r_buffer[rBUFFER_SIZE];

serial::Serial ser;
typedef union
{
	float data;
	unsigned char data8[4];
} data_u;
data_u pitch;
data_u roll;
data_u yaw;

int main(int argc, char** argv)
{
	ros::init(argc, argv, "serial_node");
	ros::NodeHandle nh;

	// 打开串口
	try
	{
		ser.setPort("/dev/ttyACM0"); // 这个端口号就是之前用cutecom看到的端口名称
		ser.setBaudrate(115200);
		serial::Timeout to = serial::Timeout::simpleTimeout(1000);
		ser.setTimeout(to);
		ser.open();
	}
	catch(serial::IOException &e)
	{
		ROS_INFO_STREAM("Failed to open port ");
		return -1;
	}
	ROS_INFO_STREAM("Succeed to open port" );

	int cnt = 0;
	ros::Rate loop_rate(500);
	ros::Publisher imu_pub = nh.advertise<serial_node::my_msg>("imu", 1000);
	while(ros::ok())
	{
		serial_node::my_msg msg;
		if(ser.available())
		{
			// 读取串口数据
			size_t bytes_read = ser.read(r_buffer, ser.available());
			// 使用状态机处理读取到的数据,通信协议与STM32端一致
			int state = 0;
			unsigned char buffer[12] = {0};
			for(int i = 0; i < bytes_read && i < rBUFFER_SIZE; i++)
			{
				if(state == 0 && r_buffer[i] == 0xAA)
				{
					state++;
				}
				else if(state == 1 && r_buffer[i] == 0xBB)
				{
					state++;
				}
				else if(state >= 2 && state < 14)
				{
					buffer[state-2]=r_buffer[i];
					state ++;
					if(state == 14)
					{
						for(int k = 0; k < 4; k++)
						{
							roll.data8[k] = buffer[k];
							pitch.data8[k] = buffer[4 + k];
							yaw.data8[k] = buffer[8 + k];
						}						
						ROS_INFO("%f, %f, %f, %d", roll.data, pitch.data, yaw.data, cnt);
						state = 0;
					}
				}
				else state = 0;
			}
		}
		// 发布接收到的imu数据
		msg.roll = roll.data;
		msg.pitch = pitch.data;
		msg.yaw = yaw.data;
		imu_pub.publish(msg);
		// ros::spinOnce();
		loop_rate.sleep();
		cnt++;
	}
	// 关闭串口
	ser.close();
	return 0;
}

修改CMakeList文件

add_executable(serial_node src/serial_demo.cpp)

add(这个还有一个我忘记了)
target_link_libraries(serial_node  ${catkin_LIBRARIES})

新建窗口编译


cd test_serial_ws
catkin_make

烧录进stm32

sudo chmod 666 /dev/ttyUSB0
rosrun rosrun serial_node serial_node

rostopic list
source ./devel/setup.bash
rostopic echo /imu

完成,关于msg的配置可以看bilibili的赵虚左ROS的56集有教程

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值