首页 > 其他分享 >GPS开发(2)GPS ROS串口采集-pubx数据解析

GPS开发(2)GPS ROS串口采集-pubx数据解析

时间:2022-12-16 10:01:04浏览次数:91  
标签:std ROS ros add 串口 msg include pubx GPS

 

 

pubx协议数据解析

 

 

 

CMakeLists.txt

 

 

cmake_minimum_required(VERSION 3.0.2)
project(v1_GetGPS)

## Compile as C++11, supported in ROS Kinetic and newer
# add_compile_options(-std=c++11)


find_package(catkin REQUIRED COMPONENTS
  message_generation
  message_runtime
  roscpp
  rospy
  std_msgs
  serial #串口引用
)

add_message_files(
  FILES
  topic_msg.msg#消息引用-添加我们自己定义的xxx.msg文件
)

generate_messages(
  DEPENDENCIES
  std_msgs#消息引用-自带
)

catkin_package(
#  INCLUDE_DIRS include
#  LIBRARIES my_topic002
#  CATKIN_DEPENDS message_generation message_runtime roscpp rospy std_msgs
#  DEPENDS system_lib
)

###########
## Build ##
###########


include_directories(
# include
  ${catkin_INCLUDE_DIRS}
)

# add_executable(publisher_gps src/publisher_gps.cpp)
# target_link_libraries(publisher_gps ${catkin_LIBRARIES})
# add_dependencies(publisher_gps ${PROJECT_NAME}_generate_messages_cpp) 

# add_executable(subscriber_gps src/subscriber_gps.cpp)
# target_link_libraries(subscriber_gps ${catkin_LIBRARIES})
# add_dependencies(subscriber_gps ${PROJECT_NAME}_generate_messages_cpp) 


# add_executable(serialPort src/serialPort.cpp)
# target_link_libraries(serialPort ${catkin_LIBRARIES})
# add_dependencies(serialPort ${PROJECT_NAME}_generate_messages_cpp) 

# add_executable(listener src/listener.cpp)
# target_link_libraries(listener ${catkin_LIBRARIES})
# add_dependencies(listener ${PROJECT_NAME}_generate_messages_cpp) 



add_executable(serialPort_saveTxt src/serialPort_saveTxt_v2.cpp)
target_link_libraries(serialPort_saveTxt ${catkin_LIBRARIES})
add_dependencies(serialPort_saveTxt ${PROJECT_NAME}_generate_messages_cpp) 


add_executable(GPS_save src/serialPort_saveTxt_v1.cpp)
target_link_libraries(GPS_save ${catkin_LIBRARIES})
add_dependencies(GPS_save ${PROJECT_NAME}_generate_messages_cpp) 

  

package.xml 

 

 

<?xml version="1.0"?>
<package format="2">
  <name>v1_GetGPS</name>
  <version>0.0.0</version>
  <description>The v1_GetGPS package</description>

  <!-- One maintainer tag required, multiple allowed, one person per tag -->
  <!-- Example:  -->
  <!-- <maintainer email="[email protected]">Jane Doe</maintainer> -->
  <maintainer email="[email protected]">dongdong</maintainer>


  <!-- One license tag required, multiple allowed, one license per tag -->
  <!-- Commonly used license strings: -->
  <!--   BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 -->
  <license>TODO</license>

  <buildtool_depend>catkin</buildtool_depend>
  
  <build_depend>message_generation</build_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>message_runtime</exec_depend>
  <exec_depend>roscpp</exec_depend>
  <exec_depend>rospy</exec_depend>
  <exec_depend>serial</exec_depend>
  <exec_depend>std_msgs</exec_depend>


  <!-- The export tag contains other, unspecified, tags -->
  <export>
    <!-- Other tools can request additional information be placed here -->

  </export>
</package>

  

msg/topic_msg.msg

 

 

bool bool_msg
float64 lat
float64 lon
float64 high
string string_msg
time time_msg

  

src/serialPort_saveTxt_v2.cpp

 

 

#include <string>
#include <vector>
#include <sstream>
#include <cmath>
#include <cstdlib>//string转化为double
#include <iomanip>//保留有效小数

//txt保存使用
#include <fstream>
#include <iostream>

//ros依赖
#include <ros/ros.h> 
#include <serial/serial.h>  //ROS已经内置了的串口包 

#include "ros/time.h"// 时间戳

//0 导入消息 工程名字/消息名字
#include "v1_GetGPS/topic_msg.h"
#include "std_msgs/String.h"
#include <std_msgs/Empty.h> 

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


//解析GPS
// 0-PUBX 1-00 2-timesharp 3-lat 4-N 5-lon 6-E 7-high 8-G3 9-Hacc 10-Vacc 
void RecePro(std::string s , double& lat , double& lon, double& high )
{
    //分割有效数据,存入vector中
    std::vector<std::string> v;
    std::string::size_type pos1, pos2;
    pos2 = s.find(",");
    pos1 = 0;
    while ( std::string::npos !=pos2 )
    {
        v.push_back( s.substr( pos1, pos2-pos1 ) );
        pos1 = pos2 + 1;
        pos2 = s.find(",",pos1);
    }
    if ( pos1 != s.length() )
        v.push_back( s.substr( pos1 ));
    //解析出经纬度
    //字段6:GPS状态,0=未定位,1=DeadReckonimgslolution,2=标准独立2D,3=标准独立3D,4=差分2D 5-差分3D 6-联合GPS和DeadReckonimgslolution
    if (v.max_size() >= 11 && (v[8] == "G3"))
    {
        //纬度
        if (v[3] != "") lat = std::atof(v[3].c_str()) / 100;
        int ilat = (int)floor(lat) % 100;
        lat = ilat + (lat - ilat) * 100 / 60;
        //经度
        if (v[5] != "") lon = std::atof(v[5].c_str()) / 100;
        int ilon = (int)floor(lon) % 1000;
        lon = ilon + (lon - ilon) * 100 / 60;
        //海拔高度
        if (v[7] != "") high = std::atof(v[7].c_str()) ;


    }
}


//1 txt文件名名字 时间戳
//2 ROS发送 开关参数化
//3 加入hacc 和  vacc

int main(int argc, char** argv)
{   

    string save_name=argv[1];
    cout<< save_name <<endl;
    //保存TXT使用
    string  outFileName = save_name+".txt";
    //ofstream outfile(outFileName, ios::app); //ios::app指追加写入
    ofstream outfile(outFileName); //覆盖方式写入
    if (!outfile.is_open())
    {
        cerr << "Error: can not find file " << outFileName << endl;
        return 0;
    }

    //初始化节点
    ros::init(argc, argv, "serial_node");
    //声明节点句柄
    ros::NodeHandle nh;
    //注册Publisher到话题GPS
    ros::Publisher GPS_pub = nh.advertise<v1_GetGPS::topic_msg>("GPS",1000);
    try
    {
      //串口设置
      ser.setPort("/dev/ttyACM0");
      ser.setBaudrate(115200);
      serial::Timeout to = serial::Timeout::simpleTimeout(5000);
      ser.setTimeout(to);
      ser.open();
    }
    catch (serial::IOException& e)
    {
        ROS_ERROR_STREAM("Unable to open Serial Port !");
        return -1;
    }
    if (ser.isOpen())
    {
        ROS_INFO_STREAM("Serial Port initialized");
    }
    else
    {
        return -1;
    }

    ros::Rate loop_rate(50);

    std::string strRece;
    while (ros::ok())
    {

        if (ser.available())
        {

  

            //1.读取串口信息:
            //ROS_INFO_STREAM("Reading from serial port\n");
            //通过ROS串口对象读取串口信息
            //std::cout << ser.available();
            //std::cout << ser.read(ser.available());
            strRece += ser.read(ser.available());
            std::cout<< "1============"<<strRece << std::endl;
            //std::cout <<"strRece:" << strRece << "\n" ;
            //strRece = "$GNGGA,122020.70,3908.17943107,N,11715.45190423,E,1,17,1.5,19.497,M,-8.620,M,,*54\r\n";
            //2.截取数据、解析数据:
            //GPS起始标志
            std::string gstart = "$PU";
            //GPS终止标志
            std::string gend = "\r\n";
            int i = 0, start = -1, end = -1;
            
            while ( i < strRece.length() )
            {
                //找起始标志

                start = strRece.find(gstart);
                //如果没找到,丢弃这部分数据,但要留下最后2位,避免遗漏掉起始标志
                if ( start == -1)
                {
                    if (strRece.length() > 2)   
                        strRece = strRece.substr(strRece.length()-3);
                        break;

                }
                //如果找到了起始标志,开始找终止标志
                else
                {
                    //找终止标志
                    end = strRece.find(gend);
                    //如果没找到,把起始标志开始的数据留下,前面的数据丢弃,然后跳出循环
                    if (end == -1)
                    {
                        if (end != 0)
                        strRece = strRece.substr(start);
                        break;
                    }
                    //如果找到了终止标志,把这段有效的数据剪切给解析的函数,剩下的继续开始寻找
                    else
                    {
                        i = end;

                        //ros::Time begin = ros::Time::now();
                        double secs =ros::Time::now().toSec();

                        //把有效的数据给解析的函数以获取经纬度
                        double lat, lon, high;
                        std::cout<< "2==========="<<strRece.substr(start,end+2-start) << std::endl;
                        RecePro(strRece.substr(start,end+2-start),lat,lon,high);
                        //保留位数7位
                        std::cout << std::setiosflags(std::ios::fixed)<<std::setprecision(7)<< "纬度:" << lat << " 经度:"<< lon <<" 高度: "<< high <<"   时间:  " << secs << "\n";
                        
                        outfile  << secs << " "<<lat <<" "<< lon <<" " << high<<" " << std::endl;//写TXT文件

                        //发布消息到话题
                        v1_GetGPS::topic_msg GPS_data;
                        GPS_data.lat = lat;
                        GPS_data.lon = lon;
                        GPS_data.high = high;
                        GPS_pub.publish(GPS_data);
                        //如果剩下的字符大于等于4,则继续循环寻找有效数据,如果所剩字符小于等于3则跳出循环
                        if ( i+5 < strRece.length())
                            strRece = strRece.substr(end+2);
                        else
                        {   strRece = strRece.substr(end+2);
                            break;
                        }
                    }
                }
            }
        }
    ros::spinOnce();
    loop_rate.sleep();
    }

    outfile.close();// txt文件关闭
    std::cout<< "采集程序关闭" <<std::endl;
    return 1;
}

  subscriber_gps.cpp

 

 

 

 

 

#include <cstdlib>
#include <iostream>
#include <string>
#include <cstring>

//0 导入ros依赖
#include <ros/ros.h>

//0 导入消息 工程名字/消息名字
#include "v1_GetGPS/topic_msg.h"
#include <std_msgs/String.h>


// 接收到订阅的消息后,会进入消息回调函数
void test_topic_cb(const v1_GetGPS::topic_msg::ConstPtr & msg)
{
    // 将接收到的消息打印出来
    ROS_INFO("------------------ msg ---------------------");
    ROS_INFO("bool_msg:    [%d]", msg->bool_msg);
    ROS_INFO("string_msg:  [%s]", msg->string_msg.c_str());
    ROS_INFO("float32_msg: [%f]", msg->lat);
    ROS_INFO("float64_msg: [%f]", msg->lon);
    ROS_INFO("time_msg:    [%d.%d]", msg->time_msg.sec, msg->time_msg.nsec);
}


int main(int argc, char **argv)
{
    // 初始化ROS节点
    ros::init(argc, argv, "subscriber_gps");

    // 创建节点句柄
    ros::NodeHandle n;

    // 创建一个Subscriber,订阅名为my_topic_msg的消息,注册回调函数test_topic_cb
    ros::Subscriber sub_topic = n.subscribe<v1_GetGPS::topic_msg>("my_topic_msg", 100, test_topic_cb);

    // 循环等待回调函数
    ros::spin();

    return 0;
}

  

 ros_run_gps.sh

 

 

 

 

 

#!/bin/sh


#延迟1秒执行
sleep 1
  
echo "ROS——GPS 测试"
#echo "GPS 测试开始,消息记录到日志里" > /home/pi/start/test_desk1.log


echo "1 开启ros节点 roscore 等待完全开启再往后执行 "
gnome-terminal -t "1_roscore" -x bash -c "\
roscore; \
exit;exec bash;"
sleep 5

# /dev/ttyACM0
# /dev/ttyUSB0
echo "2 开启发送节点 serialPort "
gnome-terminal -t "2_serialPort" -x bash -c "\
echo \"dongdong\" | sudo chmod 777 /dev/ttyACM0; \ 
source /home/dongdong/v2_Project/v4_ROS/catkin_gps/devel/setup.bash; \
rosrun v1_GetGPS serialPort_saveTxt savatxtname; \
exec bash;"
sleep 1

echo "3 开启接收节点 listener"

gnome-terminal -t "3_listener" -x bash -c "\   
source /home/dongdong/v2_Project/v4_ROS/catkin_gps/devel/setup.bash; \
rosrun v1_GetGPS listener; \
exit;exec bash;"
sleep 1


#echo "执行前确保给与脚本本身执行权限 sudo chmod -R 777 xxx.sh"
#echo "查看串口: ls /dev/ttyUSB* "
#echo "临时给与一次串口权限: sudo chmod 777 /dev/ttyUSB0 "
# 开启新的命令窗口执行
# gnome-terminal -t "窗口名字" -x bash -c "要执行的命令1;命令2;exit;exec bash;"
#Shell 脚本自动输入密码 : echo "密码" | sudo 命令

  

 

 

 

标签:std,ROS,ros,add,串口,msg,include,pubx,GPS
From: https://www.cnblogs.com/gooutlook/p/16986578.html

相关文章

  • GPS开发(1)ucenter软件和设置参数
    GPS数据口1USB口 波特率自适应2串口1 根据设定的默认35400 常用设定1152003串口2 根据设定的默认35400 常用设定115200 三个口都被识别为串口,USB下单片......
  • DGIOT边缘主机功能——6USB串口替代普通dtu/网关的设备接入
    [小迪导读]:dgiot边缘主机自带6个USB口、2个RS232串口以及2个网口,可用组态对边缘主机上的USB口、串口和网口等上的外设进行可视化管理,包括如下功能:通过6个USB口外接USB......
  • AT命令的串口
    1)   找到AT命令的串口(一般是ttyUSB2)。驱动正确集成后,确认AT串口有两种方法:一是根据接口的协议号,cat/sys/bus/usb/devices/1-1:1.3/bInterfaceProtocol(红色文件夹根据......
  • 2.4寸串口屏应用于电热饭盒的解决方案
    快节奏的生活与人们逐渐增强的消费水平推动着外卖行业的快速发展,作为对外卖行业做出了不少贡献的上班族来说,以点外卖来解决正餐是他们每天习以为常的事情。但由于近几年健......
  • 【GPS信号】GPS信号的读取以及kalman滤波预测
    根据论文中的要求,我们所需要的经度纬度和高度来自GPS信号的中的GPGGA的数据。所以提取这三个信息主要是对GPGGA中的数据进行整理。   GPGGA的数据格式如下所示:  ......
  • 用状态机实现串口多字节数据发送
    这次设计一个多字节(8-256位)且波特率可更改(通过修改例化模块的参数)的串口发送模块。1、状态机的设定状态机的设定有空闲、发送、和数据移位三个状态,其中空闲状态为......
  • [记] rust获取windows虚拟串口
    comportlist="0.1.2"  usecomportlist::available_ports;foridxinavailable_ports(vec!["CNCPorts","Ports"]){ifletSome(ss)=idx.serial_number......
  • Android手机应用开发之手机GPS定位
    最近在做Android手机应用开发,还是很有意思的。其实如果只是做简单手机应用开发而不是手机游戏开发的话,还是很简单的。把主要的控件掌握了,就可以开发简单的应用了。下面主要......
  • USB转TTL串口
    为什么USB要转TTL串口[1]?单片机串口基本采用TTL电平。家用电脑很少有串口,但是有USB接口USB的电平与TTL电平不兼容。所以需要将USB电平转化为TTL电平。USB是什么?接......
  • stm32f407VET6 串口(usart1)基本操作,【发送数据 + 接收数据】
    完整代码:#include"stm32f4xx.h"#include"delay.h"#include"led.h"#include"usart.h"/**说明:*串口程序*实现发送任意一个字节数据给电脑*电脑发送00/......