1.串口配置

ROS串口编程学习笔记:https://blog.csdn.net/u014695839/article/details/81209082
ROS系统的串口数据读取和解析:https://blog.csdn.net/afeik/article/details/91997758

2.GPS协议分析(以GPFPD为例)


可以看出,每一帧数据的头都是由$GPFPD开始的,然后每部分都由逗号隔开,所以如果解析数据的话可以通过逗号来判断。

协议解析代码:

size_t n = sp.available();string str;string Header;string GPSWeek;string GPSTime;string Heading;string Pitch;string Roll;string Lattitude;string Longitude;string Altitude;string Ve;string Vn;string Vu;string Baseline;string NSV1;string NSV2;string Status;string Cs;string CrLf;uint8_t buffer[1024];int num=0;int flag=0;n = sp.read(buffer, n);if(n>0){if(GPS_Data_Check(buffer,n)==0)//如果校验不通过则跳过{continue;}for(int i=0; i<n; i++){if(buffer[i]==','){num++;}else {if(num==0){Header+=buffer[i];   }else if(num==1){GPSWeek+=buffer[i];}else if(num==2){GPSTime+=buffer[i];}else if(num==3){Heading+=buffer[i];}else if(num==4){Pitch+=buffer[i];}else if(num==5){Roll+=buffer[i];}else if(num==6){Lattitude+=buffer[i];}else if(num==7){Longitude+=buffer[i];}else if(num==8){Altitude+=buffer[i];}else if(num==9){Ve+=buffer[i];}else if(num==10){Vn+=buffer[i];}else if(num==11){Vu+=buffer[i];}else if(num==12){Baseline+=buffer[i];}else if(num==13){NSV1+=buffer[i];}else if(num==14){NSV2+=buffer[i];}else if(num==15){if(flag<2){Status+=buffer[i];}else if(flag>=2&&flag<5){Cs+=buffer[i];}else if(flag>=5){CrLf+=buffer[i];}flag++;}}str+=buffer[i];}

3.数据校验


其中第一种方法是针对标准语句的校验方式,第二种方法是针对二进制语句的。
第一种需要校验的数据位在$到*之间并且需要异或操作。

在校验的过程中首先要对帧头进行校验,查看是否含有$GPFPD,然后再进行校验和的计算。

校验和代码:

 for(int i=0;i<length-2;i++){if(i<head_n){head_str+=a[i];}if(flag==3){CS_str+=a[i];//在一帧数据中本来存在的校验位}if(a[i]=='*'){flag=3;}if(flag==2){CS^=a[i];//异或出来的校验位chang++;}if(a[i]=='$'){flag=2;}}

因为异或出来的校验位是unsigned char类型的,而在一帧数据中存在的是string类型十六进制的数据。所以我们首先要将异或出来的校验位转换成十进制的ASCLL码的数值,然后将十进制的整型转换为十六进制的string型,再进行对比。
参考资料:
[C++] 十进制转十六进制

4.ROS消息收发

如果是小白的的话可以先看一下关于topic demo的视频:
ROS机器人操作系统入门-中国大学MOOC-topic_demo(上)
ROS机器人操作系统入门-中国大学MOOC-topic_demo(下)

在创建ROS包的时候要记得添加serial

看完之后修改相关文件:

gps.msg

string Header
string GPSWeek
string GPSTime
string Heading
string Pitch
string Roll
string Lattitude
string Longitude
string Altitude
string Ve
string Vn
string Vu
string Baseline
string NSV1
string NSV2
string Status
string Cs
string CrLf

CMakeLists.txt(部分需要修改的地方)

cmake_minimum_required(VERSION 2.8.3)
project(topic_demo)## Compile as C++11, supported in ROS Kinetic and newer
# add_compile_options(-std=c++11)## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages
find_package(catkin REQUIRED COMPONENTSmessage_generation roscpprospyserialstd_msgs
)add_message_files(FILES gps.msg)
generate_messages(DEPENDENCIES std_msgs)
## System dependencies are found with CMake's conventions
# find_package(Boost REQUIRED COMPONENTS system)catkin_package(
#  INCLUDE_DIRS include
#  LIBRARIES topic_demoCATKIN_DEPENDS roscpp rospy serial std_msgs message_runtime
#  DEPENDS system_lib
)include_directories(
# include${catkin_INCLUDE_DIRS}
)# catkin_add_nosetests(test)
add_executable(talker src/talker.cpp)
add_dependencies(talker topic_demo_generate_messages_cpp)
target_link_libraries(talker ${catkin_LIBRARIES})add_executable(listener src/listener.cpp)
add_dependencies(listener topic_demo_generate_messages_cpp)
target_link_libraries(listener ${catkin_LIBRARIES})

package.xml(部分需要修改的地方)

  <buildtool_depend>catkin</buildtool_depend><build_depend>roscpp</build_depend><build_depend>rospy</build_depend><build_depend>serial</build_depend><build_depend>std_msgs</build_depend><build_export_depend>roscpp</build_export_depend><build_export_depend>rospy</build_export_depend><build_export_depend>serial</build_export_depend><build_export_depend>std_msgs</build_export_depend><exec_depend>roscpp</exec_depend><exec_depend>rospy</exec_depend><exec_depend>serial</exec_depend><exec_depend>std_msgs</exec_depend><exec_depend>message_runtime</exec_depend>

发送端代码(完整):

/***********************************************************/
/*Function:ROS parsing GPS agreement(GPFPD),Post to topic.Author:YuTengDate:2019/10/14Version: V0.0.1
*/
/***********************************************************/
#include "ros/ros.h"
#include "topic_demo/gps.h"
#include <serial/serial.h>
#include <iostream>
#include <string>
#include <ctime>
using namespace std;
int GPS_Data_Check(uint8_t a[],int length);
int GPS_Data_Check(string hex_n,int dex);
int main(int argc,char ** argv)
{ros::init(argc,argv,"talker"); //解析参数,命名节点ros::NodeHandle nh; //创建句柄,实例化nodetopic_demo::gps msg; //创建gps消息serial::Serial sp;ros::Publisher pub = nh.advertise<topic_demo::gps>("gps_info",1); //创建publisherW  ros::Rate loop_rate(1.0); //定义循环发布的频率serial::Timeout to = serial::Timeout::simpleTimeout(100);//设置要打开的串口名称sp.setPort("/dev/ttyUSB0");//设置串口通信的波特率sp.setBaudrate(115200);//窗口设置timeoutsp.setTimeout(to);try{//打开串口sp.open();}catch(serial::IOException& e){ROS_ERROR_STREAM("Unable to open port.");return -1;}//判断串口是否打开成功if(sp.isOpen()){ROS_INFO_STREAM("/dev/ttyUSB0 is opened.");}else{return -1;}clock_t startTime,endTime;    while(ros::ok()){startTime = clock();//计时开始size_t n = sp.available();string str;string Header;string GPSWeek;string GPSTime;string Heading;string Pitch;string Roll;string Lattitude;string Longitude;string Altitude;string Ve;string Vn;string Vu;string Baseline;string NSV1;string NSV2;string Status;string Cs;string CrLf;uint8_t buffer[1024];int num=0;int flag=0;n = sp.read(buffer, n);if(n>0){if(GPS_Data_Check(buffer,n)==0)//如果校验不通过则跳过{continue;}for(int i=0; i<n; i++){if(buffer[i]==','){num++;}else {if(num==0){Header+=buffer[i];   }else if(num==1){GPSWeek+=buffer[i];}else if(num==2){GPSTime+=buffer[i];}else if(num==3){Heading+=buffer[i];}else if(num==4){Pitch+=buffer[i];}else if(num==5){Roll+=buffer[i];}else if(num==6){Lattitude+=buffer[i];}else if(num==7){Longitude+=buffer[i];}else if(num==8){Altitude+=buffer[i];}else if(num==9){Ve+=buffer[i];}else if(num==10){Vn+=buffer[i];}else if(num==11){Vu+=buffer[i];}else if(num==12){Baseline+=buffer[i];}else if(num==13){NSV1+=buffer[i];}else if(num==14){NSV2+=buffer[i];}else if(num==15){if(flag<2){Status+=buffer[i];}else if(flag>=2&&flag<5){Cs+=buffer[i];}else if(flag>=5){CrLf+=buffer[i];}flag++;}}str+=buffer[i];}msg.Header=Header;msg.GPSWeek=GPSWeek;msg.GPSTime=GPSTime;msg.Heading=Heading;msg.Pitch=Pitch;msg.Roll=Roll;msg.Lattitude=Lattitude;msg.Longitude=Longitude;msg.Altitude=Altitude;msg.Ve=Ve;msg.Vn=Vn;msg.Vu=Vu;msg.Baseline=Baseline;msg.NSV1=NSV1;msg.NSV2=NSV2;msg.Status=Status;msg.Cs=Cs;msg.CrLf=CrLf;std::cout <<"GPS:   "<<str<< std::endl;ROS_INFO("Header:%s",msg.Header.c_str());ROS_INFO("GPSWeek:%s",msg.GPSWeek.c_str());ROS_INFO("GPSTime:%s",msg.GPSTime.c_str());ROS_INFO("Heading:%s",msg.Heading.c_str());ROS_INFO("Pitch:%s",msg.Pitch.c_str());ROS_INFO("Roll:%s",msg.Roll.c_str());ROS_INFO("Lattitude:%s",msg.Lattitude.c_str());ROS_INFO("Longitude:%s",msg.Longitude.c_str());ROS_INFO("Altitude:%s",msg.Altitude.c_str());ROS_INFO("Ve:%s",msg.Ve.c_str());ROS_INFO("Vn:%s",msg.Vn.c_str());ROS_INFO("Vu:%s",msg.Vu.c_str());ROS_INFO("Baseline:%s",msg.Baseline.c_str());ROS_INFO("NSV1:%s",msg.NSV1.c_str());ROS_INFO("NSV2:%s",msg.NSV2.c_str());ROS_INFO("Status:%s",msg.Status.c_str());ROS_INFO("Cs:%s",msg.Cs.c_str());ROS_INFO("CrLf:%s",msg.CrLf.c_str());pub.publish(msg); //发布消息sp.write(buffer, n);endTime = clock();//计时结束std::cout << "The run time is: " <<(double)(endTime - startTime) / CLOCKS_PER_SEC << "s" << std::endl;}n=0;loop_rate.sleep(); //根据定义的发布频率,sleep}sp.close();return 0;
}
int GPS_Data_Check(uint8_t a[],int length)//GPS数据校验
{int head_n=6;string head_str; //帧头string CS_str; //数据帧校验位int flag=1; //数据标志位int CS_dex; unsigned char CS=0;int chang=0;for(int i=0;i<length-2;i++){if(i<head_n){head_str+=a[i];}if(flag==3){CS_str+=a[i];//在一帧数据中本来存在的校验位}if(a[i]=='*'){flag=3;}if(flag==2){CS^=a[i];//异或出来的校验位chang++;}if(a[i]=='$'){flag=2;}}CS_dex=CS;  //十进制ASCLL码if((head_str=="$GPFPD")&&(GPS_Data_Check(CS_str,CS_dex))){return 1;}else{return 0;}
}
int GPS_Data_Check(string hex_n,int dex)
{string dex_con_hex;string temp;int j=0;if(dex<=15){string temp="";if(dex<10){temp+=dex+'0';}else{temp+=dex-10+'A';}dex_con_hex=temp;for(int i=temp.length()-1;i>=0;i--){dex_con_hex[j]=temp[i];j++;}}else{string temp="";do{int dex_tmp=dex%16;if(dex_tmp<10){temp+=dex_tmp+'0';}else{temp+=dex_tmp-10+'A';}dex/=16;}while(dex>=16);if(dex<10){temp+=dex+'0';}else{temp+=dex-10+'A';}dex_con_hex=temp;for(int i=temp.length()-1;i>=0;i--){dex_con_hex[j]=temp[i];j++;}}int x;int y;if(dex_con_hex.compare(hex_n))//如果两个字符串相等则为0{return 0;}else{return 1;}
}

接收端代码(完整):

#include "ros/ros.h"
#include "topic_demo/gps.h"
#include <std_msgs/Float32.h>void gpsCallback(const topic_demo::gps::ConstPtr &msg)
{ROS_INFO("Header:%s",msg->Header.c_str());ROS_INFO("GPSWeek:%s",msg->GPSWeek.c_str());ROS_INFO("GPSTime:%s",msg->GPSTime.c_str());ROS_INFO("Heading:%s",msg->Heading.c_str());ROS_INFO("Pitch:%s",msg->Pitch.c_str());ROS_INFO("Roll:%s",msg->Roll.c_str());ROS_INFO("Lattitude:%s",msg->Lattitude.c_str());ROS_INFO("Longitude:%s",msg->Longitude.c_str());ROS_INFO("Altitude:%s",msg->Altitude.c_str());ROS_INFO("Ve:%s",msg->Ve.c_str());ROS_INFO("Vn:%s",msg->Vn.c_str());ROS_INFO("Vu:%s",msg->Vu.c_str());ROS_INFO("Baseline:%s",msg->Baseline.c_str());ROS_INFO("NSV1:%s",msg->NSV1.c_str());ROS_INFO("NSV2:%s",msg->NSV2.c_str());ROS_INFO("Status:%s",msg->Status.c_str());ROS_INFO("Cs:%s",msg->Cs.c_str());ROS_INFO("CrLf:%s",msg->CrLf.c_str());
}int main(int argc, char **argv)
{ros::init(argc, argv, "listener"); //ros::NodeHandle n;                 //ros::Subscriber sub = n.subscribe("gps_info", 1, gpsCallback); //创建subscriberros::spin(); //反复调用当前可触发的回调函数,阻塞return 0;
}

5.运行结果

发送端:

接收端:

ROS实现串口解析GPS协议,并发布到话题相关推荐

  1. 使用modbus4j通过串口解析modbus协议(java)

    前言 项目中需要读取工厂产线中传感器上的数据(温度,粘度等): 传感器连接通讯协议是RS485串口通信(以后打算转成网口) 数据协议类型是modbus ASCII 一.生产工具/资料 提示:下面的工具 ...

  2. ROS下使用单目/双目摄像头发布图像话题

    1.此贴记录一下作者在ros中使用摄像头的方法,如有错误和不足请在评论区批评指正,手上有三种摄像头(1.单目摄像头 2.双目摄像头_俩usb端口 3.双目摄像头_单usb端口)不同摄像头的launch ...

  3. ROS实现串口GPS数据的解析与通信(这篇文章所用的代码和我买的带有ROS功能包的GPS模块的功能包的代码一样)

    我发现这篇文章所用的代码和我买的带有ROS功能包的GPS模块的功能包的代码一样!!! https://gitee.com/maxibooksiyi/gps_driver 转载自:https://blo ...

  4. Jetson nano 使用ROS 实现串口通信,并且解析通信协议(C++)

    Jetson nano 使用ROS 实现串口通信 1:首先安装ros下的serial库 sudo apt-get install ros-melodic-serial 其中的melodic根据自己的r ...

  5. python模拟gps定位_python解析nmea0183协议获取GPS定位信息

    python解析nmea0183协议获取GPS定位信息 nmea0183协议里面定位数据主要在GPRMC报文里面,下面是报文的大体形式: b'$GPRMC,111025.00,A,2517.03374 ...

  6. ROS通过串口,读写STM32和HC-SR04超声波测距信息

    ROS通过串口,读写STM32和HC-SR04超声波传感器测距信息,ROS判断距离值,将控制信息通过串口发回给STM32,点亮led灯 ROS可以通过串口与stm32进行通信,以超声波传感器为例实现R ...

  7. GPS之MTK平台代码小结以及gps协议注释

            分类:             通信硬件与通讯协议              2014-10-20 09:55     337人阅读     评论(0)     收藏     举报   ...

  8. 利用串口解析AIS接收机数据

    串口: 串行接口简称串口,也称串行通信接口或串行通讯接口(通常指COM接口),是采用串行通信方式的扩展接口.串行接口 (Serial Interface) 是指数据一位一位地顺序传送,其特点是通信线路 ...

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

    一.问题简介 自动驾驶小车的底层的数据相当一部分是通过串口发送的,以惯导为例,惯导的定位信息大概如下所示: $GPFPD,0,1666.330,0.000,0.015,0.129,0.00000000 ...

最新文章

  1. Python lambda用法及其与def的区别
  2. [转]几句不可不看的经典人生语句
  3. BASH命令和SHELL脚本学习
  4. Java 动态代理机制分析及扩展
  5. 在ASP.NET中使用Global.asax文件
  6. Cobertura和Maven:集成和单元测试的代码覆盖率
  7. 我的处女作《设计模式之禅》——前言
  8. 在Windows上面安装多个Memcached
  9. 知识图谱需要解决的问题
  10. golang的sync包例子
  11. xpath NOT IE
  12. RIA and volta
  13. JAVA Web开发MySQL数据库记录浏览分页
  14. 4.在屏幕上输出以下图案: * *** ***** ******* ********* *********** ************* *********** *********
  15. HFSS15.0 安装破解说明
  16. eTerm A4电子行程单 提取导出
  17. 思源宋体+Courier New字体
  18. 推荐阅读:《我在赶集网的两个月(完整版)》
  19. Linux下的clk学习
  20. Java自动识别身份证信息

热门文章

  1. 【转】Jabber即时通信系统服务整体框架概述
  2. 2023 彩虹易支付USDT(TRC20)支付收款插件
  3. 上海浦江镇python培训在职班
  4. 用友U8C U8Cloud U8 cloud u8c V2.1 2.2 V2.3 V2.4 V2.5 V2.6 V2.7 V3.0 3.1 3.2文件下载
  5. memoQ助力西门子全球员工宅家翻译
  6. 基于亚马逊自研机器学习训练芯片 Trainium 的 Amazon EC2 Trn1 实例正式上线
  7. 老外发邮件常说“TBD\TBC”是什么意思?
  8. 自动获取中文拼音首字母方法-Asp.net
  9. 有趣的生活,有趣的比赛
  10. matlab二进制定义,MATLAB二进制类型数据相关操作