ROS获取串口信息及后续处理(以惯导IMU XW-GI5651为例)

2023-10-27

一、问题简介

自动驾驶小车的底层的数据相当一部分是通过串口发送的,以惯导为例,惯导的定位信息大概如下所示:

$GPFPD,0,1666.330,0.000,0.015,0.129,0.00000000,0.00000000,0.000,0.000,0.000,0.000,0.000,0,0,00*4E

报文中包含着丰富的车辆状态信息,通过ROS节点,拿到这些数据,并进行处理在自动驾驶中是非常重要的,本文主要介绍了利用ROS获取串口信息的方式。
点击跳至原贴

二、ROS获取串口数据信息

  1. 下载serial包
sudo apt-get install ros-kinetic-serial  #ros为Kinect版本

2.编写ros节点cpp文件

#include <ros/ros.h> 
#include <serial/serial.h>  //ROS已经内置了的串口包 
#include <std_msgs/String.h> 
#include <std_msgs/Empty.h> 

serial::Serial ser; //声明串口对象 

//回调函数 
void write_callback(const std_msgs::String::ConstPtr& msg) 
{ 
    ROS_INFO_STREAM("Writing to serial port" <<msg->data); 
    ser.write(msg->data);   //发送串口数据 
} 

int main (int argc, char** argv) 
{ 
    //初始化节点 
    ros::init(argc, argv, "serial_example_node"); 
    //声明节点句柄 
    ros::NodeHandle nh; 

    //订阅主题,并配置回调函数 ,此处未使用,后续通过串口发送数据可以进行配置
    ros::Subscriber write_sub = nh.subscribe("write", 1000, write_callback); 
    //发布主题 ,主题为“read”
    ros::Publisher read_pub = nh.advertise<std_msgs::String>("read", 1000); 

    try 
    { 
    //设置串口属性,并打开串口 
        ser.setPort("/dev/ttyS0"); //此处需要根据惯导接的串口来进行修改。
        ser.setBaudrate(115200); //波特率
        serial::Timeout to = serial::Timeout::simpleTimeout(1000); 
        ser.setTimeout(to); 
        ser.open(); 
    } 
    catch (serial::IOException& e) 
    { 
        ROS_ERROR_STREAM("Unable to open port "); 
        return -1; 
    } 

    //检测串口是否已经打开,并给出提示信息 
    if(ser.isOpen()) 
    { 
        ROS_INFO_STREAM("Serial Port initialized"); 
    } 
    else 
    { 
        return -1; 
    } 

    //指定循环的频率 
    ros::Rate loop_rate(10); 
    while(ros::ok()) 
    { 

        if(ser.available()){ 
            ROS_INFO_STREAM("Reading from serial port\n"); 
            std_msgs::String result; 
            result.data = ser.read(ser.available()); 
            ROS_INFO_STREAM("Read: " << result.data); //将接收到的信息打印在终端上
            read_pub.publish(result);//发送话题数据 
        } 

        //处理ROS的信息,比如订阅消息,并调用回调函数 
        ros::spinOnce(); 
        loop_rate.sleep(); 

    } 
} //别忘了添加serial依赖,否则编译失败

串口信息的处理

在通过上面的ROS节点可以收到串口的信息,在终端上可以显示,但是串口信息在局部的回调函数上,要想真正拿到串口信息,还要进一步处理,本文列举了部分方法

  1. 采用全局变量的方法
#include "ros/ros.h"
#include "std_msgs/String.h"
#include <sstream>//包含流的操作的C++头文件
std::string myStr="init";//定义全局变量并进行初始化
void chatterCallback(const std_msgs::String::ConstPtr& msg)
{
  std::stringstream ss;
  ss << msg->data.c_str();
  ss >> ::myStr;//通过流操作进行传参。此处不能用=,报错显示=没有被重装载。该全局变量就可以在main()中使用了。
  std::cout <<"copy_data is: " << myStr <<"\n";
}
int main(int argc, char **argv)
{
  ros::init(argc, argv, "listener");
  ros::NodeHandle n;
  ros::Subscriber sub = n.subscribe("read", 1000, chatterCallback);
  ros::spin();
  return 0;
}
  1. 使用类方法作为回调函数

代码来自:https://blog.csdn.net/xinwenfei/article/details/89384578
http://wiki.ros.org/roscpp_tutorials/Tutorials/UsingClassMethodsAsCallbacks

#include <ros/ros.h>
#include <std_msgs/String.h>
#include <sstream>

/**
 * This tutorial demonstrates subscribing to a topic using a class method as the callback.
 */

// %Tag(CLASS_WITH_DECLARATION)%
class Listener
{
public:
  std::string copy_data = "init init init";
  int count = 0;
public:
  void callback(const std_msgs::String::ConstPtr& msg);
  void print_data2(){std::cout << "Copy data is :" << copy_data << "\n";}
};
// %EndTag(CLASS_WITH_DECLARATION)%

void Listener::callback(const std_msgs::String::ConstPtr& msg)
{
  ROS_INFO("I heard: [%s]", msg->data.c_str());
  std::stringstream ss;
  ss << msg->data.c_str();
  ss >> copy_data;
  std::cout <<"copy_data is: " << copy_data <<"\n";
  print_data2();
  ++count;
}

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

// %Tag(SUBSCRIBER)%
  Listener listener;
  ros::Subscriber sub = n.subscribe("chatter", 1000, &Listener::callback, &listener);
  ros::Rate loop_rate(10);
// %EndTag(SUBSCRIBER)%
  while(ros::ok() and listener.count <=3){
    ros::spinOnce();
    loop_rate.sleep();
  }
  std::cout << "After spin: \n";
  listener.print_data2();
  return 0;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ROS获取串口信息及后续处理(以惯导IMU XW-GI5651为例) 的相关文章

随机推荐

  • 安装Ubuntu系统详细教程

    一 前言 本篇文章详解介绍一下如何安装Ubuntu系统 笔者在安装的过程中踩过很多坑 重装了很多次 现在把安装过程中遇到的问题也列出来 供大家参考 二 准备工作 这个环节很重要 工欲善其事 必先利其器 2 1 固态硬盘 如果是做系统源码开发
  • Android GB28181设备接入端语音广播和语音对讲技术实现探究

    上篇文章提到Android端GB28181接入端的语音广播和语音对讲的实现 从spec角度大概介绍了下流程和简单的接口设计 好多开发者私信我 希望展开说一下 其实这块难度不大 只是广播和对讲涉及到双向实现 如果之前没有相关的积累 从头实现麻
  • gitlab常用操作总结

    1 常用命令 1 git clone xx git 首先从git项目xx gitclone项目到本地 2 clone之后 使用命令行项目进入项目所在文件夹 此时一般在master分支下 为了不影响主分支代码 进行新建分支 git check
  • 40个大数据学习资源,个个是干货,最后7个太给力

    数据是驱动商业向前发展的核心 更是人类社会的未来 尽管将马云的这句话断章取义地拿出来说会显得唐突 但这话所表达的意思却显而易见 今天给大家分享的这40个教程 送给对未来抱有远见的乐观主义者 涵盖了大数据入门的大多基础知识 从Java基础到S
  • 沉浸式翻译 安装及使用

    介绍一下最近非常或的沉浸式翻译工具 非常有助于外文阅读 包括网页 pdf等 可以同时显示原文和译文 操作简单 使用起来还是非常友好的 先上链接 介绍 沉浸式翻译 如何使用 沉浸式翻译 1 安装 支持Edge Chrome Firefox和S
  • algorithm 不修改序列的操作

    文章目录 非修正序列算法 adjacent find first last count first last val for each first last func 相关参考 非修正序列算法 非修正序列算法不修改他们所作用的容器 例如计算
  • SpringBoot 集成Kafka

    Kafka项目整体结构图 父类项目 pom xml 依赖
  • 高血糖克星!育润齐梅牌胰力佳奶粉调节血糖大作用

    21世纪以来 健康一直是大家关注的重点 保健品市场行业正在慢慢扩张 尽管很多人对其有一定的争议 但不可否认的是 越来越多的消费者最终选择了接受 并且消费群体逐渐往年轻态发展 不再是老年人的专属需求 在健康大数据的观测下 已知我国目前是全球糖
  • Unity第一人称视角相机跟随鼠标移动

    基于Unity实现第一人称视角相机跟随鼠标移动 private float xRotate 0 0f private float yRotate 0 0f Void Update xRotate Input GetAxis Mouse Y
  • Vue-cli 相关webpack配置-量化打包时间和打包后分析

    参考 https blog csdn net weixin 41779718 article details 110038340 主要介绍两个插件 用于量化打包时间 和打包后分析 speed measure webpack plugin 可
  • Android中Fragmnet的跳转

    1 Fragment跳转到Fragment中 描述 我的项目是由MainActivity启动的Fragment作为底部导航栏 HomeFragment StoreFragment PersonalFragment 情景一 点击HomeFra
  • HTTP 1.1与HTTP 1.0的比较

    HTTP 1 1与HTTP 1 0的比较 一个WEB站点每天可能要接收到上百万的用户请求 为了提高系统的效率 HTTP 1 0规定浏览器与服务器只保持短暂的连接 浏览器的每次请求都需要与服务器建立一个TCP连接 服务器完成请求处理后立即断开
  • Allegro学习笔记:Allegro快速入门之一--查看BRD Layout

    由于工作需要 需要学习在Allegro下查看以及简单修改pcb 然而在网上找了一阵子资料 发现很多资料都很零碎 不成系统 而成系统的 又把读者当成要学习用Allegro Layout的对象 从头到尾完整的讲解 但是虽然完整 却并不详细 导致
  • 代码审计工具学习之RISP(安装以及初步操作)

    目录 1 代码审计 1 1名词解释 1 2代码审计的重要性 1 3代码审计的步骤 1 4代码审计的内容 1 5常见的代码审计工具 2 RIPS 2 1什么是RIPS 2 2 RIPS的安装过程 3典型漏洞分析 3 1 文件包含漏洞分析 3
  • Vue3/ 父组件 ref 获取子组件内属性或方法 子组件 defineExpose 暴露方法 或 属性 总结、

    一 父组件 ref 获取子组件内属性或方法 总结 介绍 Vue3中 父组件拿到 子组件内方法 属性 可以通过 ref 但是将 ref 插入子组件标签身上后 打印出来是 什么都没有的 是空的 这个是为什么呢 哦 原来 Vue3严格性问题 属性
  • 崩溃了没有生成dump的分析步骤

    文章目录 1 系统日志的错误信息 2 分析崩溃 1 获取exe和pdb 2 ide打开对应exe 3 找基址 4 查找错误位置 很大可能 在用户现场的时候 可能存在崩溃了但是没有生成dump的情况 可能只能有一些系统日志或者直接给你个截图什
  • Oracle 11g ADG(Active Data Guard)切换脚本的示例

    以下是一个Oracle 11g ADG Active Data Guard 切换脚本的示例 用于将ADG从当前主服务器切换到备用服务器 bin bash Set Oracle environment variables ORACLE SID
  • Ubuntu22.04 安装Anaconda

    文章目录 1 下载Anaconda 2 安装Anaconda 3 启动环境 4 常用命令 4 1创建虚拟环境 4 2查询当前系统conda虚拟环境 4 3挂载虚拟环境 4 4退出虚拟环境 4 5查看已安装的工具包 4 6删除虚拟环境 1 下
  • python文件的写入

    wirte 方法把字符串写入文件 writelines 方法可以把列表中存储的内容写入文件 f file hello txt w li hello world n hello china n f writelines li f close
  • ROS获取串口信息及后续处理(以惯导IMU XW-GI5651为例)

    一 问题简介 自动驾驶小车的底层的数据相当一部分是通过串口发送的 以惯导为例 惯导的定位信息大概如下所示 GPFPD 0 1666 330 0 000 0 015 0 129 0 00000000 0 00000000 0 000 0 00