优秀的编程知识分享平台

网站首页 > 技术文章 正文

技术分享 | ROS里多机通信配置太繁琐?带你换个方式来操作

nanyue 2025-05-21 15:30:36 技术文章 5 ℃

在ROS1当中,很多使用Qt开发无人机和无人车交互界面的多数都是使用ROS自带的通信机制多机通信机制,但是在ROS1当中使用这种机制就避免不了多机通信配置问题,操作起来也十分繁琐,为了避免这种问题所以采用了TCP/UDP通信机制来替代ROS多机通信机制,但是怎么样将ROS中msg数据打包传输给Qt交互界面呢?相信很多想更换通信机制的人都想过这个问题,所以这篇文件就带你实现使用序列化和反序列化进行msg数据的传输。分为两种情况,分别是Qt依赖ROS和Qt不依赖ROS。这两种情况都有着属于各自的优点。下面会分别介绍这两种情况。


Qt依赖ROS

这种情况的优点就是可以通过ROS自带的序列化进行传输,可以将订阅的话题数据全部序列化打包进行发送,在由Qt人机交互界面进行反序列化解析还原成话题数据。就比如rviz数据,如果使用TCP/UDP通信同时实现rviz显示可视化数据,则必须使用该方式,将空中端订阅到的rviz话题数据全部打包发送在还原,还原后再在Qt端进行发布话题给rviz订阅。


空中端代码简单示例:

#include <ros/serialization.h>
#include "prometheus_msgs/DroneState.h" //DroneState.msg生成
//msg为进入回调后的 (const prometheus_msgs::DroneState::ConstPtr& msg)
prometheus_msgs::DroneState drone = *msg;
//序列化 buffer为序列化后的数据 serial_size为序列化后的大小
namespace ser = ros::serialization;
uint32_t serial_size = ros::serialization::serializationLength(drone);
boost::shared_array<uint8_t> buffer(new uint8_t[serial_size]);
ser::OStream stream(buffer.get(), serial_size);
ser::serialize(stream, drone);
//将buffer存入 ,udp_send_bufbuff为要发送的数据
char *ptr = udp_send_buf;
//首先存入msg序列化后的长度
*((int*)ptr) = serial_size;
ptr += sizeof(int);
//存入序列化后的数据
for(int i = 0;i < serial_size;i++)
{
*((uint8_t*)ptr) = buffer[i];
ptr += sizeof(uint8_t);
}
//发送数据

地面端(Qt)代码简单示例:

#include <ros/serialization.h>
#include "WorkStation/DroneState.h" //DroneState.msg生成
//通过TCP/UDP接收到数据存入buff
//首先拿到buffer长度
char *ptr = buff;
int serial_size = *((int *)ptr);
ptr += sizeof(int);
//根据buffer长度拿出buffer
boost::shared_array<uint8_t> buffer(new uint8_t[serial_size]);
for(int i = 0;i < serial_size;i++)
{
buffer[i] = *((uint8_t*)ptr);
ptr += sizeof(uint8_t);
}
//将buffer反序列化给drone
WorkStation::DroneState drone;
namespace ser = ros::serialization;
ser::IStream stream(buffer.get(),serial_size);
ser::deserialize(stream,drone);


Qt不依赖ROS

这种情况的优点就是摆脱了ROS环境的影响,移植的时候也不用考虑ROS环境因素。同时在这种情况下我们就不能使用ROS自带的序列化了,同时我们也不能将msg话题数据打包进行发送,而是需要将msg转换为结构体或者类来进行发送。同时因为要将结构体或者类序列化所以采用boost序列化库(这只是其中一种方式,还有其他序列化方式)。


空中端代码简单示例:

#include <vector>
#include <fstream>
#include <cstddef> // NULL
#include <iomanip>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/vector.hpp>
//结构体
struct Book
{
std::string bookname;
int price;
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned int /* file_version */)
{
ar & bookname;
ar & price;
}
};
//temp为将book序列化后的数据
Book book;
book.name = "序列化";
book.price = 10;
std::ostringstream oss;
boost::archive::text_oarchive oa(oss);
oa<<test;
std::string temp = oss.str();
//将temp通过TCP/UDP发送


地面端(Qt)代码简单示例:

#include <vector>
#include <fstream>
#include <cstddef> // NULL
#include <iomanip>
#include <boost/archive/text_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/serialization/vector.hpp>
//结构体
struct Book
{
std::string bookname;
int price;
friend class boost::serialization::access;
template<class Archive>
void serialize(Archive & ar, const unsigned int /* file_version */)
{
ar & bookname;
ar & price;
}
};
//通过TCP/UDP接收数据
//str为发送端发来的数据temp
//将发送端发来的数据反序列化给b,b即为发送的结构体
Book b;
std::istringstream iss(str);
boost::archive::text_iarchive ia(iss);
ia>>b;


结尾

以上操作只是简略的操作,省略了通信部分的代码,只写了序列化和反序列化的操作仅供参考。


阿木实验室致力于为机器人研发提供开源软硬件工具和课程服务,让研发更高效!

- End -

技术发展的日新月异,阿木实验室将紧跟技术的脚步,不断把机器人行业最新的技术和硬件推荐给大家。看到经过我们培训的学员在技术上突飞猛进,是我们培训最大的价值。如果你在机器人行业,就请关注我们的公众号,我们将持续发布机器人行业最有价值的信息和技术。

Tags:

最近发表
标签列表