技术分享 | ROS里多机通信配置太繁琐?带你换个方式来操作
在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 #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 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长度拿出bufferboost::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反序列化给droneWorkStation::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;
结尾
以上操作只是简略的操作,省略了通信部分的代码,只写了序列化和反序列化的操作仅供参考。
阿木实验室致力于为机器人研发提供开源软硬件工具和课程服务,让研发更高效!
公众号:阿木实验室 ( 领取免费资料包)
官方淘宝店:阿木实验室(可购买硬件配件)
硬件咨询:yanyue199506(欢迎洽谈合作)
课程咨询:jiayue199506 (免费领取机器人工程师学习计划)
- End -
技术发展的日新月异,阿木实验室将紧跟技术的脚步,不断把机器人行业最新的技术和硬件推荐给大家。看到经过我们培训的学员在技术上突飞猛进,是我们培训最大的价值。如果你在机器人行业,就请关注我们的公众号,我们将持续发布机器人行业最有价值的信息和技术。