(2)ROS传感器之GPS实践

一. GPS接口类型

GPS接口大体可以分为两类,一是单独的GPS接收器,通常为USB接口;二是与其他传感器集成,例如激光雷达或者imu,大多是USB或者网络接口,本文主要介绍USB接口实例。

二. 概念

这里有三个概念,需要明确下:驱动,SDK和ROS驱动。以USB GPS为例,GPS驱动是作为操作系统层面的驱动程序,一般需要事先安装,安装成功后,接入GPS设备时,会出现相应的设备文件,

通常为/dev/ttyUSBx,x是一个数字,代表设备号,与主机接入的设备个数和顺序有关。在驱动安装完成之后,我们就获得了设备文件。GPS SDK是一套应用层程序,可以从设备文件中获取设备数据,驱动和SDK一般都由厂家提供。

ROS驱动通常是基于SDK进行ROS封装而成,目前有不少传感器厂商和ROS社区提供了常用传感器的ROS驱动。

三.GPS ROS驱动获取

当我们拿到一个GPS之后,可以首先查下这款GPS有没有ROS驱动,可以咨询厂商或者到ros wiki查询,链接:

Sensors - ROS Wiki​wiki.ros.org

如果没有现成的ROS驱动,可以基于厂商提供的SDK自己封装,可以参考同类型ros驱动设计。

四. nmea_navsat_driver

nmea_navsat_driver是一套用于获取并解析GPS数据的ROS驱动包,使用Python语言实现。GPS设备使用此包的条件是:遵守或者兼容NMEA0184协议。nmea_navsat_driver提供四个节点:nmea_topic_driver,

nmea_serial_driver,nmea_topic_serial_reader和nmea_socket_driver。

1. 文件结构

执行以下指令:

roscd nmea_navsat_driver
sudo  apt install tree
tree -L 4

执行效果如图:

scripts目录存放顶层节点文件,对应上述四个节点,其中的文件只是调用main()函数,实际实现在src/nodes目录下对应文件名的Python文件中。launch目录存放启动nmea_serial_driver节点launch文件。

setup.py是Python语言ROS包编译配置文件,内容不要更改。

2. nmea_topic_serial_reader节点

此节点从串口读入GPS数据,然后封装为nmea_msgs/Sentence数据格式,发布话题nmea_sentence。

nmea_topic_serial_reader文件只有两行,如下:

import libnmea_navsat_driver.nodes.nmea_topic_serial_reader
libnmea_navsat_driver.nodes.nmea_topic_serial_reader.main()

第一行导入nodes目录下的nmea_topic_serial_reader.py文件,第二行调用nmea_topic_serial_reader.py中的main()函数。

nmea_topic_serial_reader.py文件内容如下,因为增加中文注释,所以需要包含“# -*- coding: UTF-8 -*-”。

# -*- coding: UTF-8 -*-
import serial   #引入串口模块
from nmea_msgs.msg import Sentence  #引入nmea_msgs/Sentence结构
import rospy    #引入ROS的Python接口模块
from libnmea_navsat_driver.driver import RosNMEADriver  #引入driver.py中的RosNMEADriver

def main():
    rospy.init_node('nmea_topic_serial_reader')     #初始化ros节点名
    nmea_pub = rospy.Publisher("nmea_sentence", Sentence, queue_size=1)     #定义发布者
    serial_port = rospy.get_param('~port', '/dev/ttyUSB0')      #设置串口设备文件名
    serial_baud = rospy.get_param('~baud', 4800)                #设置波特率

    # Get the frame_id
    frame_id = RosNMEADriver.get_frame_id()                 #设置frame_id
    try:
        GPS = serial.Serial(port=serial_port, baudrate=serial_baud, timeout=2)      #调用python串口模块Serial
        while not rospy.is_shutdown():
            data = GPS.readline().strip()         #从串口读入数据

            sentence = Sentence()       #创建nmea_msgs/Sentence结构变量sentence
            sentence.header.stamp = rospy.get_rostime()     #设置sentence的时间戳为当前时间
            sentence.header.frame_id = frame_id             #设置sentence的frame_id
            sentence.sentence = data                        #设置sentence的sentence变量。

            nmea_pub.publish(sentence)                      #发布sentence

    except rospy.ROSInterruptException:                     #异常处理
        GPS.close()  # Close GPS serial port

文件添加了详细的注释,大家可以对比阅读。需要注意的是,在串口设置时需要根据实际情况,配置设备文件以及波特率。

3. nmea_topic_driver节点

此节点订阅话题nmea_sentence,然后根据NMEA0184协议解析,并发布解析后的数据,发布话题为:经纬度/fix,速度/vel,gps时间/time_reference和航向角/heading。

执行以下指令:

rosrun nmea_navsat_driver nmea_topic_driver
rqt_graph

执行效果如图

 nmea_topic_driver节点文件流程同nmea_topic_serial_reader,顶层节点文件nmea_topic_driver调用nmea_topic_driver.py中的main函数,nmea_topic_driver.py内容如下:

# -*- coding: UTF-8 -*-
from nmea_msgs.msg import Sentence
import rospy

from libnmea_navsat_driver.driver import RosNMEADriver
def nmea_sentence_callback(nmea_sentence, driver):
    try:
        driver.add_sentence(
            nmea_sentence.sentence,
            frame_id=nmea_sentence.header.frame_id,
            timestamp=nmea_sentence.header.stamp)   #add_sentence()接收frame_id和时间戳,接收sentence并解析,发布解析后的时间,位置,速度和航向角信息。
    except ValueError as e:
        rospy.logwarn(
            "Value error, likely due to missing fields in the NMEA message. "
            "Error was: %s. Please report this issue at ros-drivers/nmea_navsat_driver, "
            "including a bag file with the NMEA sentences that caused it." %
            e)

def main():
    rospy.init_node('nmea_topic_driver')
    driver = RosNMEADriver()    #实例化RosNMEADriver()类
    rospy.Subscriber("nmea_sentence", Sentence, nmea_sentence_callback,driver)    #订阅话题nmea_sentence,话题类型Sentence,回调函数nmea_sentence_callback,回调函数第二个参数driver。

    rospy.spin()

这里比较关键的是add_sentence()函数,此函数是driver.py文件RosNMEADriver类的成员函数,主要功能是根据NMEA0184协议,对sentence数据进行解析,进而获取gps时间,位置,速度以及航向角信息,然后发布出来,

感兴趣的可以对照NMEA0184协议研究此函数,这里不再深入分析。

需要说明的是,虽然此函数提供了四个话题,但是不同的GPS设备,其提供的信息可能也不一样,所以有的话题可能是空的,例如heading和vel。

4. nmea_serial_driver节点

此节点从串口读数据,直接解析发布数据,相当于nmea_topic_driver节点和nmea_topic_serial_reader节点的结合体,有了上面两个基础,相信应该可以看懂这个程序,就不再介绍了。

此节点是通过网口读取gps数据,除了接口不同外,在拿到sentence之后的处理流程是一致的,这里就不在介绍,需要说明的是利用网口,只需要配置ip和端口号,不需要安装驱动。

五. 说明

虽然GPS设备输出数据兼容NMEA0184,但是不同厂家的设备,可能需要不同的配置,所以一个GPS ROS驱动不一定适应所有GPS设备,即使GPS设备遵守NMEA0184,nmea_navsat_driver包在Garmin GPS 18x以及

Venus Venus634LPx上测试,其他GPS设备未必可以直接使用,最终还是以厂家手册为准。

六. 参考

本篇参考wiki:

nmea_navsat_driver - ROS Wiki​wiki.ros.org

代码取自其中的github仓库:

ros-drivers/nmea_navsat_driver​github.com

添加了部分中文注释,修改后的代码提交到仓库:

https://github.com/ahuer2435/ros_program_melodic.git​github.com

七. 小结

本篇首先明确驱动,sdk以及ros驱动的概念,介绍了实现ros驱动的几种途径,然后以nmea_navsat_driver为例,介绍在ros系统中,如何获取,解析以及发布gps数据,由于没有实际硬件,所以没有运行串口读取的节点,有条件的话,大家可以自行测试。

GPS可以实现全球范围内定位,但是由于其频率较低,且易受外界影响,在实际使用中多与IMU配合使用,下一篇介绍GPS的黄金搭档:惯性测量单元IMU。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值