NTRIP_ROS使用解读

2024-01-09 11:55:06

NTRIP_ROS

First time to upload my code here. This is a beta version for testing.

This program helps you get RTCM messages from NTRIP caster and get RTK solution:

  1. Recieve PVT topic from ublox_driver;
  2. Generate GPGGA string by PVT message;
  3. Send GPGGA string to NTRIP server(NTRIP caster) by httplib.HTTPConnection, and get RTCM data from response;
  4. Send recieved RTCM data to Ublox-F9P module via UART when the port is opened and single point position valid;
  5. Reconnect if network failed.

这段话描述了一个使用GPS数据(从u-blox模块接收)和NTRIP(网络传输实时运动定位信息系统)服务进行实时动态运动定位(RTK)处理的过程。具体步骤如下:

  1. 接收PVT主题来自ublox_driver
  • 这一步涉及从u-blox驱动程序接收PVT(Position, Velocity, Time - 位置、速度、时间)数据。PVT是GPS设备提供的一种常见数据类型,包含了关于设备当前位置、移动速度和时间的信息。
  1. 由PVT消息生成GPGGA字符串
  • GPGGA是一种标准的NMEA(国家海洋电子协会)GPS数据格式,包含了关键的定位信息,如当前时间、纬度、经度、定位质量等。
  • 这一步将从u-blox驱动程序接收到的PVT数据转换为GPGGA格式的字符串。
  1. 通过httplib.HTTPConnection将GPGGA字符串发送到NTRIP服务器,并从响应中获取RTCM数据
  • NTRIP是一种用于传输GPS校正数据的协议,常用于RTK定位,以提高定位精度。
  • 这一步将GPGGA字符串发送到一个NTRIP服务器(或NTRIP caster),通常是为了请求实时的差分校正数据(即RTCM数据)。
  1. 当端口打开且单点位置有效时,通过UART将接收到的RTCM数据发送到Ublox-F9P模块
  • 这一步涉及将从NTRIP服务器接收到的RTCM数据通过UART(通用异步接收/发送)接口发送到Ublox-F9P模块。Ublox-F9P是一个高精度GNSS模块,能够使用RTCM数据提高其定位精度。
  1. 如果网络失败,重新连接
  • 这一步意味着如果在发送或接收数据过程中网络连接失败,系统应该尝试重新建立连接。

总体而言,这个过程是利用NTRIP服务将高精度定位数据(RTCM)集成到一个RTK系统中,使用u-blox设备进行精确定位的典型流程。

NTRIP_ROS

这张图展示了一个使用u-blox F9P模块进行实时定位校正的系统设置。以下是各个组成部分及其相互作用的详细解释:

  1. Laptop(笔记本电脑)

    • 内部运行着两个软件组件,ublox_driverNTRIP_ROS
    • ublox_driver是一个驱动程序,负责与连接到USB1的u-blox GNSS模块通信。
    • NTRIP_ROS可能是一个负责处理NTRIP客户端功能的ROS(机器人操作系统)包,它通过USB2连接到网络,并与NTRIP Caster通信。
  2. 4G LTE / WLAN(无线局域网)

    • 笔记本电脑通过4G LTE移动网络或WLAN连接到互联网。
  3. NTRIP Caster

    • 一个在线服务,它通过互联网提供实时的GNSS校正数据(RTCM数据)。
    • 笔记本电脑上的NTRIP_ROS通过HTTP GET请求发送用户身份验证信息和GxGGA字符串到NTRIP Caster,其中GxGGA是包含定位信息的NMEA格式数据。
    • NTRIP Caster响应这个请求,并发送回RTCM数据。
  4. USB-UART module

    • 这个模块充当了电脑与u-blox F9P模块之间的桥梁。通过USB接口与电脑通信,并通过UART接口与u-blox F9P模块通信。
  5. Ublox-F9P

    • 一个高精度GNSS模块,具有两个UART端口。
    • UART1可能用于接收从笔记本电脑ublox_driver发出的标准GNSS数据(如UBX-RXM-RAWX,UBX-RXM-SFRBX,UBX-NAV-PVT)。
    • UART2用于接收RTCM数据流,这些数据通过USB-UART模块从NTRIP_ROS发送过来,用于实时校正,提高定位精度。

整个系统是为了实现精确的定位校正而设计的。笔记本电脑负责接收原始GNSS数据和RTCM校正数据,并确保这些数据能够传输到u-blox F9P模块,后者最终使用这些数据来提供精确的定位信息。

CSDN blog : https://blog.csdn.net/Millium/article/details/125837995?spm=1001.2014.3001.5502

Realtime test uploaded on Bilibili : https://www.bilibili.com/video/BV1CW4y117Du/

1. Prerequisites

1.1 ROS

ROS melodic (tested)

1.2 Python and 3rdparty library

Python 2.7 is required, NOT Python 3.

httplib (if not installed, run pip installto install this module).

1.3 Test information

I tested this program in Ubuntu 18.04 (with ROS melodic and Python 2.7), it seems to work well.

But in Ubuntu 20.04 (with ROS noetic, Python 3 and http.client), errors occurred.

I did a lot of research, I think the main reason may be that http.client in python 3 DOES NOT support ICY 200 OK response header sent by NTRIP caster, but the problem does not exist in httplib.HTTPConnection in Python 2.7 .

问题描述指出,在Python 3中使用http.client库处理从NTRIP服务器接收到的“ICY 200 OK”响应时存在兼容性问题。这个响应头是非标准的,可能不被Python 3的http.client库支持,而在Python 2.7的httplib中没有这个问题。

要解决这个问题,有几种可能的方法:

  1. 使用低级socket编程
  • 直接使用Python的socket库可以提供更细粒度的控制,允许您手动处理HTTP请求和响应,包括任何非标准的响应头。
  • 通过socket编程,您可以直接读取和解析来自NTRIP caster的原始响应数据。
  1. 第三方库
  • 您可以寻找是否有第三方库能够处理这种特殊情况。例如,requests库有时可以更灵活地处理非标准的HTTP响应。
  1. 修改http.client源码
  • 作为一种更为高级的解决方案,您可以尝试修改http.client库的源码,以支持“ICY 200 OK”响应。这可能涉及到对库中的解析函数进行补丁或扩展。
  1. 捕获异常
  • 如果http.client在解析响应时引发异常,您可以捕获这个异常,并尝试从异常对象中提取所需的数据。
  1. 回退到Python 2.7
  • 如果没有其他选择,临时的解决方案可能是在Python 2.7环境中运行您的代码,直到找到在Python 3中处理ICY响应的方法。
  1. 联系NTRIP服务提供商
  • 如果可能,联系NTRIP服务提供商询问是否有更新或补丁可以解决这个兼容性问题。

2. Build this program

Clone the code to your workspace and:

catkin_make

3. Run with you F9P module

3.1 Install u-center

The version I’m using is v21.09 , you can test NTRIP username and password in Reciever-NTRIP Client.

3.2 Configure PORT and RATE of your F9P module

Firstly you need to correctly configure UART port of your F9P module in Configure-PRT, such as Baudrateand Protocol in/out.

In my case, I use UART1 to send UBX-RXM-RAWX, UBX-RXM-SFRBXand UBX-PVTmessage via USB-UART module to my laptop (and parsed by ublox_driver, published as ROS topic), and send RTCM message to UART2 via USB-UART module to F9P, so UBXin Potocol outof UART1 is needed, and RTCMin Potocol inof UART2 is needed.

Message rate in Configure-RATEmay also be set, for example 10Hz.

After configuration, you can see messages printed in Packet Console.

这段话描述了如何配置u-blox F9P模块以进行RTK(实时动态运动定位)通信和数据处理的步骤:

  1. 配置F9P模块的UART端口
  • 在u-blox软件的“配置 - PRT(端口)”部分中设置F9P模块的UART端口。
  • 需要设置适当的波特率(Baudrate)和输入/输出协议(Protocol in/out)。
  1. UART端口的使用
  • 作者使用F9P模块的UART1端口来发送UBX-RXM-RAWX(原始卫星观测数据)、UBX-RXM-SFRBX(广播星历数据)和UBX-NAV-PVT(导航定位信息)消息。
  • 这些消息通过USB-UART模块发送到笔记本电脑,并由ublox_driver解析,然后发布为ROS(机器人操作系统)的话题。
  • 同时,作者通过另一个USB-UART模块将RTCM消息发送到F9P模块的UART2端口,因此需要在UART1的输出协议中启用UBX协议,以及在UART2的输入协议中启用RTCM协议。
  1. 设置消息频率
  • 在“配置 - RATE(频率)”中设置消息的更新频率,例如10Hz表示每秒更新10次。
  1. 配置后的验证
  • 完成配置后,可以在数据包控制台中看到打印出的消息,这有助于验证配置是否正确。

简而言之,这段话是关于如何设置u-blox F9P模块,以便通过其串行端口接收和发送特定的GNSS数据格式,并且如何在系统中设置数据的传输频率。这对于确保高精度的GNSS数据处理和实时定位是必要的。

3.3 Enable PVT message

Because I’m using ublox_driver, I need to enable UBX-RXM-RAWX, UBX-RXM-SFRBXand UBX-PVTmessage in u-center.

Actually, only UBX-PVTmessage is needed for RTK. You can use other ublox driver to extract PVTmessage and publish as ROS topic so RAWXand SFRBXis not needed anymore. Or you could use ublox driver which supports NMEA, then you just need to enable NMEA-GxGGA and subscribe NMEA message and send it to NTRIP caster.

这段话继续讨论了如何使用u-blox F9P模块,并特别关注与RTK相关的消息类型和如何通过ROS(机器人操作系统)发布这些消息:

  1. 在u-center中启用消息
  • 作者提到他们正在使用ublox_driver,这是一个软件驱动,用于与u-blox模块通信并处理数据。
  • 在u-blox的配置软件u-center中,他们需要启用UBX-RXM-RAWX(原始卫星观测数据),UBX-RXM-SFRBX(卫星导航消息)和UBX-NAV-PVT(导航定位信息)消息,以便这些数据能够被ublox_driver接收和处理。
  1. 针对RTK所需的消息
  • 对于RTK定位,实际上只需要UBX-NAV-PVT消息。PVT代表位置(Position)、速度(Velocity)和时间(Time),这些是进行基本RTK定位所需的关键信息。
  1. 简化消息订阅
  • 作者建议,如果不需要处理原始观测数据或卫星导航消息,可以使用其他的u-blox驱动来提取PVT消息并将其发布为ROS话题,这样就不再需要RAWX和SFRBX消息。
  • 另外,如果使用的u-blox驱动支持NMEA(国家海洋电子协会)数据格式,那么可以只启用NMEA-GxGGA消息。GxGGA是NMEA协议中的一种,提供了定位相关的基本信息,如经纬度、时间、定位质量等。
  1. 发送数据到NTRIP服务器
  • 如果选择使用NMEA格式,可以订阅从u-blox模块发出的NMEA消息,并将其发送到NTRIP服务器(caster)。NTRIP服务器用于提供差分校正数据,可以提高GNSS定位的精确度。

总结来说,这段话说明了如何根据实际需要选择并配置u-blox模块输出的消息类型,并描述了如何将这些消息集成到一个ROS系统中,以便进行RTK定位或将数据发送到NTRIP服务器。

3.4 Run with your Ublox-F9P

  1. Plug in your F9P’s UART ports to your computer via USB-UART module, and check ports’ name, like /dev/ttyUSB0, then change the port name and baudrate in ntripclient.py(F9P’s UART2, for sending RTCM data to module) and driver_config.yaml(F9P’s UART1, for recieve PVT message from module) of ublox_driver, don’t forget to obtain r/w permissions of the ports.

    这段话提供了有关如何连接和配置u-blox F9P模块以用于实时运动定位系统(RTK)的指导。步骤包括:

    1. 连接F9P模块到计算机
    • 使用USB-UART(通用异步接收/发送转换器)模块将F9P模块的UART(通用异步接收/发送)端口连接到计算机。
    1. 检查端口名称
    • 在计算机上检查UART端口的设备名称。在类Unix系统中,这些端口通常以/dev/ttyUSB开头,后面跟着一个数字来区分不同的设备,例如/dev/ttyUSB0
    1. 修改配置文件
    • ntripclient.py文件中更改端口名称和波特率设置。这个Python脚本可能是用来从NTRIP服务器接收RTCM校正数据,并将其发送到F9P模块的UART2端口。
    • ublox_driverdriver_config.yaml配置文件中,也需要设置F9P模块的UART1端口的端口名称和波特率,这是用来接收来自模块的PVT(位置、速度和时间)消息的。
    1. 获取端口读写权限
    • 确保你有足够的权限来读写这些UART端口。在类Unix系统中,这可能涉及修改设备文件的权限或通过使用适当的用户组(如dialout)来运行你的程序。

    总体而言,这段话描述了如何物理连接和配置F9P模块和计算机之间的通信,以便在一个RTK系统中传输必要的数据。这是确保F9P模块能够接收到RTCM校正数据并提供精确定位信息的关键步骤。

  2. Launch ublox_driver, and rostopic echotopic /ublox_driver/receiver_pvt, remember to source devel/setup.bashin your terminal in ublox_driver workspace.

    这段话是关于如何在机器人操作系统(ROS)环境中启动u-blox GNSS设备的驱动程序,并查看发布到特定ROS主题的消息。具体步骤包括:

    1. 启动ublox_driver
    • ublox_driver是一个ROS节点或软件包,它负责与u-blox GNSS模块通信,接收并处理GNSS数据。
    • 这个驱动程序可以通过在ROS环境中运行特定的命令来启动。
    1. 查看ROS主题
    • rostopic echo是一个ROS命令,用于在命令行界面中打印ROS主题的内容。在这种情况下,该命令用于查看名为/ublox_driver/receiver_pvt的主题,该主题可能包含了PVT(Position, Velocity, Time - 位置、速度、时间)消息,这是从u-blox GNSS模块接收的导航定位信息。
    1. source devel/setup.bash
    • 在ROS中,当你编译(或构建)你的工作空间后,会在devel目录中生成setup.bash脚本。
    • 使用source命令运行这个脚本是为了配置环境变量,这样你的终端会知道如何找到和使用你的ROS软件包和节点。
    • 在启动ublox_driver之前,你需要在使用ublox_driver的工作空间的终端中执行这个命令。

    综上所述,这段话指导你如何在ROS环境中设置和验证与u-blox GNSS模块的通信。这通常是在基于ROS的机器人或导航应用程序中实现GNSS集成的一部分。

  3. Run roscore in a terminal:

roscore
  1. In the other terminal, run this program in your workspace:
source devel/setup.bash
rosrun ntrip_ros ntripclient.py

If your network is fine, UART successfully opened and GNSS single point position is fixed, the recieved RTCM data is sent to UART2 of F9P module.

Then, wait for carr_solnof topic /ublox_driver/receiver_pvtturning to 2, which means RTK fixed solution (0means no RTK, 1means RTK float solution), and enjoy it.

Note that RTK solution is obtained in topic /ublox_driver/receiver_pvt.

这段话描述了在配置了u-blox F9P模块和相关软件后,如何确认RTK(实时动态运动定位技术)系统正在正确工作的步骤:

  1. 接收RTCM数据
  • 当网络连接正常,UART端口(即通用异步接收/发送端口)成功打开,并且GNSS模块已经确定了单点位置后,接收到的RTCM校正数据会被发送到F9P模块的UART2端口。
  1. 监控RTK解的状态
  • 在ROS中,/ublox_driver/receiver_pvt主题包含了从u-blox驱动程序接收的导航定位信息,其中carr_soln字段表示RTK解的状态。
  • carr_soln字段的值为2时,表示系统已经获得了固定的RTK解,这意味着定位精度是最高的(厘米级)。
  • 值为0表示没有RTK解,即系统可能仅使用GNSS单点定位,精度较低。
  • 值为1表示系统处于RTK浮点解状态,这是介于单点定位和固定解之间的一种状态,定位精度高于单点定位,但低于固定解。
  1. 享受高精度定位
  • carr_soln字段为2时,可以享受到RTK提供的高精度定位数据。
  1. RTK解的获取
  • 提示用户注意,RTK定位解是通过/ublox_driver/receiver_pvt主题获取的,这是在ROS环境中监控和使用GNSS数据的关键点。

总的来说,这段话说明了如何在配置了RTK系统的ROS环境中验证RTK定位的状态,并确认系统达到了预期的定位精度。

3.5 Hardware configuration

In my case, I’m using

  1. Beitian BT-F9PK4 module;
  2. Beitian BT-345 antenna;
  3. Quectel EC20 4G module;
  4. CH340 USB to UART module made by myself;
  5. Lenovo laptop with i5-8265U.

这段话描述了某个特定设置中使用的硬件组件,它们通常用于构建一个GNSS(全球导航卫星系统)接收系统,可能用于RTK(实时动态运动定位技术)或其他高精度定位应用:

  1. Beitian BT-F9PK4模块
  • 这是一个多频GNSS接收器模块,内置u-blox F9P模块,能够接收包括GPS、GLONASS、Galileo和BeiDou等多个卫星系统的信号。它通常用于需要高精度定位的应用,如无人机导航、测绘和精密农业。
  1. Beitian BT-345天线
  • 这是一个与Beitian GNSS模块配套使用的高增益天线,它用于捕获来自GNSS卫星的信号。天线的质量和放置对接收器的定位精度有显著影响。
  1. Quectel EC20 4G模块
  • 这是一个4G LTE通信模块,提供移动网络接入。在GNSS应用中,它可以用于接收来自NTRIP服务器的差分校正数据或用于其他需要移动数据连接的应用。
  1. CH340 USB到UART模块
  • CH340是一款常用的USB转串口芯片。这个自制的模块用于在GNSS模块和笔记本电脑之间建立串行通信,即通过USB接口与计算机通信,通过UART与GNSS模块通信。
  1. 联想笔记本电脑,搭载i5-8265U处理器
  • 这是用户使用的计算平台,配备了英特尔的i5-8265U处理器。这台笔记本电脑可能运行着处理GNSS数据的软件,例如RTKLIB、u-center或定制的应用程序。

总的来说,这套装备构成了一个完整的GNSS数据收集和处理系统,可以用于各种场合,特别是那些需要精确地理位置信息的场景。

4. Reference

4.1 Msg files

ROS message file GnssPVTSolnMsg.msgand GnssTimeMsg.msgare copied from ublox_driver. Many thanks to Dr. Cao for his work.

4.2 Code reference

Thanks to these code contributors:

ntrip_ros by tilk;

ntrip_client by LORD-MicroStrain;

RTK-NTRIP-RTCM by Archfx;

ntrip_ros by MikHut;

ntrip_ros by Road-Balance.

5. TO DO

TCP method (send RTCM data to a given port to ublox_driver, like str2strin RTKLIB) is not supported yet.

Problem in http.clientin Python 3 might be solved by ntrip_ros_python3, need to check it out later.

And using socketinstead of http.clientmay be a good idea but script written by myself does not work correctly for now, need to work it out later.

这段话继续讨论了如何使用u-blox F9P模块,并特别关注与RTK相关的消息类型和如何通过ROS(机器人操作系统)发布这些消息:

  1. 在u-center中启用消息
  • 作者提到他们正在使用ublox_driver,这是一个软件驱动,用于与u-blox模块通信并处理数据。
  • 在u-blox的配置软件u-center中,他们需要启用UBX-RXM-RAWX(原始卫星观测数据),UBX-RXM-SFRBX(卫星导航消息)和UBX-NAV-PVT(导航定位信息)消息,以便这些数据能够被ublox_driver接收和处理。
  1. 针对RTK所需的消息
  • 对于RTK定位,实际上只需要UBX-NAV-PVT消息。PVT代表位置(Position)、速度(Velocity)和时间(Time),这些是进行基本RTK定位所需的关键信息。
  1. 简化消息订阅
  • 作者建议,如果不需要处理原始观测数据或卫星导航消息,可以使用其他的u-blox驱动来提取PVT消息并将其发布为ROS话题,这样就不再需要RAWX和SFRBX消息。
  • 另外,如果使用的u-blox驱动支持NMEA(国家海洋电子协会)数据格式,那么可以只启用NMEA-GxGGA消息。GxGGA是NMEA协议中的一种,提供了定位相关的基本信息,如经纬度、时间、定位质量等。
  1. 发送数据到NTRIP服务器
  • 如果选择使用NMEA格式,可以订阅从u-blox模块发出的NMEA消息,并将其发送到NTRIP服务器(caster)。NTRIP服务器用于提供差分校正数据,可以提高GNSS定位的精确度。

总结来说,这段话说明了如何根据实际需要选择并配置u-blox模块输出的消息类型,并描述了如何将这些消息集成到一个ROS系统中,以便进行RTK定位或将数据发送到NTRIP服务器。

ntripclient.py

#!/usr/bin/python

import rospy
import datetime
import time
from httplib import HTTPConnection
from httplib import HTTPException
import socket
from base64 import b64encode
from threading import Thread
import serial
from ntrip_ros.msg import GnssPVTSolnMsg # Copy from ublox_driver

######################################### Parameters ########################################

## UART configuration
f9p_uart2_port = '/dev/ttyUSB0'
f9p_uart2_baud = 460800

## NTRIP configuration
_ntrip_server = 'rtk.ntrip.qxwz.com'
_ntrip_port = 8002
_ntrip_mountpoint = 'RTCM32_GGB'
_ntrip_username = 'username'
_ntrip_password = 'password'

#############################################################################################

# Send RTCM Message to UART2 of Ublox-F9P module
uart_port = f9p_uart2_port
uart_baud = f9p_uart2_baud
uart_isopened = False
try:
    uart2_f9p = serial.Serial(uart_port, uart_baud, timeout = 0)
    uart_isopened = True
except:
    rospy.loginfo("Open %s failed! Please make sure you entered right port and baudrate!" % (uart_port))

def calcultateCheckSum(stringToCheck):
        xsum_calc = 0
        for char in stringToCheck:
            xsum_calc = xsum_calc ^ ord(char)
        return "%02X" % xsum_calc

class ntripconnect(Thread):
    def __init__(self, ntc):
        super(ntripconnect, self).__init__()
        self.ntc = ntc
        self.connected = False
        self.connection = HTTPConnection(self.ntc.ntrip_server, self.ntc.ntrip_port, timeout = 5)
        self.stop = False

    def do_connect(self):
        self.connection = HTTPConnection(self.ntc.ntrip_server, self.ntc.ntrip_port, timeout = 5)
        usr_pwd = self.ntc.ntrip_username + ':' + self.ntc.ntrip_password
        headers = {
            'Ntrip-Version': 'Ntrip/1.0',
            'User-Agent': 'NTRIP ntrip_ros',
            'Connection': 'close',
            'Authorization': 'Basic ' + b64encode(usr_pwd)
        }
        try:
            self.connection.request('GET', '/'+self.ntc.ntrip_mountpoint, self.ntc.getGGA(), headers)
            self.connected = True
            print " ------ In connecting process: Connected ------ "
            return True
        except KeyboardInterrupt:
            print " ------ In connecting process: Keyboard interrupt ------ "
            self.connected = False
            self.stop = True
            return False
        except (HTTPException, socket.error) as e:
            print " ------ In connecting process: HTTP error ------ "
            print e
            return False
        

    def run(self):
        while not self.connected:
            try:
                self.connected = self.do_connect()
            except KeyboardInterrupt:
                print " Keyboard interrupt "
                self.connected = False
                self.stop = True
            time.sleep(0.5)

        response = self.connection.getresponse()       
        buf = ""

        while (not self.stop) and self.connected:
            if response.status != 200:
                rospy.logerr("HTTP status is not 200! Reconnecting... ")
                self.do_connect()
                response = self.connection.getresponse()
                continue

            try:
                data = response.read(1) # [1] Sync code : first byte should be '211' , that is 'D3' in hex
            except (HTTPException, socket.error) as e:
                print " Reconnecting..."
                if self.do_connect():
                    response = self.connection.getresponse()
                continue
            except KeyboardInterrupt:
                print "Keyboard interrupt!"
                self.stop = True
                break
            

            if data!=chr(211):
                rospy.logwarn("Header not in sync, continue!")
                continue
            # [2] Reversed code : 6bit , 000000
            # [3] Msg length : 10bit
            l1 = ord(response.read(1)) # Read 2nd byte , including 2 bits in Msg length
            l2 = ord(response.read(1)) # Read 3rd byte , including 8 bits remaining in Msg length
            pkt_len = ((l1&0x3)<<8)+l2 # Got msg length : 2bit + 8bit = 10bit 
    
            pkt = response.read(pkt_len) # [4] Data body : read from 4th byte
            parity = response.read(3) # [5] CRC : read last 3 bytes
            if len(pkt) != pkt_len:
                rospy.logwarn("Wrong package length, continue!")
                continue

            if self.ntc.pvt_valid:
                rospy.loginfo("Got %d bytes from %s" % (pkt_len, self.ntc.ntrip_server))
            else:
                rospy.loginfo(" -[Invalid GGA]- Got %d bytes from %s" % (pkt_len, self.ntc.ntrip_server))

            # RTCM data = Sync code + Reversed code + Msg length + Data body + CRC
            rtcm_data = data + chr(l1) + chr(l2) + pkt + parity
            if uart_isopened and self.ntc.pvt_valid:
                # Send to UART2 of Ublox-F9P
                try:
                    uart2_f9p.write(rtcm_data)
                except:
                    print "did not send!"
                    pass
            elif not uart_isopened:
                rospy.logwarn("Uart not opened! RTCM data won't be sent!")
            elif not self.ntc.pvt_valid:
                rospy.logwarn("Position not fixed! RTCM data won't be sent!")
            time.sleep(0.2)

        self.connection.close()
        self.connected = False
        print "End of the process."

class ntripclient:
    def __init__(self):
        rospy.init_node('ntripclient', anonymous=True)

        self.pvt_topic = "/ublox_driver/receiver_pvt" # Topic from ublox_driver

        self.ntrip_server = _ntrip_server
        self.ntrip_port = _ntrip_port
        self.ntrip_username = _ntrip_username
        self.ntrip_password = _ntrip_password
        self.ntrip_mountpoint = _ntrip_mountpoint 

        self.sub_pvt = rospy.Subscriber(self.pvt_topic, GnssPVTSolnMsg, self.pvt_callback)

        # Some init value
        self.pvt_lat = 34.0     # GGA - <2>
        self.pvt_lon = 108.0    # GGA - <4>
        self.pvt_alt = 430.0    # GGA - <9>
        self.pvt_status = 0     # GGA - <6>
        self.pvt_num_sv = 4     # GGA - <7>
        self.pvt_pdop = 2.0     # GGA - <8>
        self.pvt_geoid_sep = -27.9  # GGA - <10>

        # When fix state turns to 3D fix, pvt_valid = True
        self.pvt_valid = False

        self.connection = None
        self.connection = ntripconnect(self)
        self.connection.start()

    def run(self):
        rospy.spin()
        if self.connection is not None:
            self.connection.stop = True

    def getGGA(self):
        now = datetime.datetime.utcnow()
        ggaString = "GPGGA,%02d%02d%04.2f,%04.4f,N,%05.4f,E,1,%02d,%02.2f,%04.1f,M,-27.9,M,," % \
            (now.hour,now.minute,now.second,self.pvt_lat,self.pvt_lon,self.pvt_num_sv,self.pvt_pdop,self.pvt_alt)
        checksum = calcultateCheckSum(ggaString)
        ggaString = "$%s*%s\r\n" % (ggaString, checksum) # DO NOT forget to add \r\n
        return ggaString


    # Because ublox_driver doesn't support NMEA , so here I use PVT message to generate GPGGA message
    # For NTRIP, latitude, longitude and altitude is enough
    # But for precision, I think maybe it's better to directly get GGA string from Ublox receiver
    def pvt_callback(self, pvt_msg):
        # Wait for 3D fix
        if pvt_msg.fix_type >= 3:
            self.pvt_valid = True
        else:
            self.pvt_valid = False
            rospy.logwarn("Position not fix yet! GGA message won't update and maybe untrusted!")
        
        if self.pvt_valid:
            self.pvt_lat = pvt_msg.latitude * 100   # x100 for GxGGA
            self.pvt_lon = pvt_msg.longitude * 100  # x100 for GxGGA
            self.pvt_alt = pvt_msg.altitude
            self.pvt_status = 1
            self.pvt_num_sv = pvt_msg.num_sv # Used sv of GPS,GLONASS,GALILEO,Beidou , not only GPS
            if self.pvt_num_sv > 12:    # max = 12 in GPGGA
                self.pvt_num_sv = 12    # can't get used GPS number, but it doesn't matter
            self.pvt_pdop = pvt_msg.p_dop


if __name__ == '__main__':
    c = ntripclient()
    c.run()


这段Python代码定义了一个通过ROS(机器人操作系统)节点实现的NTRIP客户端,用于从NTRIP服务器接收RTCM(无线电技术委员会海事服务)校正数据,并将这些数据发送到u-blox F9P模块。这个过程对于使用RTK(实时动态运动定位技术)技术进行高精度定位至关重要。代码中包含了多个部分:

  1. 参数配置

    • 定义了F9P模块的UART2端口名称和波特率。
    • 配置了NTRIP服务器的地址、端口、挂载点、用户名和密码。
  2. UART通信设置

    • 尝试打开定义的UART端口,如果成功,uart_isopened标记为True。
  3. 校验和计算

    • calcultateCheckSum函数用于计算NMEA字符串的校验和。
  4. NTRIP连接类

    • ntripconnect类继承自Thread,用于处理NTRIP连接和数据接收。它尝试连接NTRIP服务器并在连接成功后接收数据流。
  5. NTRIP客户端类

    • ntripclient类负责初始化ROS节点,订阅来自u-blox驱动程序的/ublox_driver/receiver_pvt主题,以及启动NTRIP连接线程。
  6. GGA字符串生成

    • getGGA方法根据当前时间和接收到的PVT消息生成GPGGA字符串。这个字符串需要发送到NTRIP服务器以请求RTCM数据。
  7. PVT消息回调

    • pvt_callback函数是当接收到PVT消息时的回调函数。它检查定位是否已经固定,并根据PVT消息更新用于生成GGA字符串的数据。
  8. RTCM数据处理

    • ntripconnect类的run方法中,接收到的RTCM数据会在UART端口打开且PVT位置有效时通过UART发送到F9P模块。
  9. 主程序

    • 程序的入口点创建了ntripclient的实例,并启动了ROS节点。

这个脚本的整体作用是在ROS环境中桥接NTRIP服务器和u-blox GNSS模块,为后者提供必要的RTCM校正数据。这允许F9P模块使用这些数据来进行更精确的定位,这对于地理测绘、无人机导航和其他需要高精度GNSS数据的应用非常重要。

在您提供的代码中,用户可以配置的参数主要涉及UART(通用异步收发传输器)配置和NTRIP(网络传输参考站)配置,具体包括:

  1. UART配置:

    • f9p_uart2_port: Ublox-F9P模块的UART2端口,例如'/dev/ttyUSB0'
    • f9p_uart2_baud: UART2的波特率,例如460800
  2. NTRIP配置:

    • _ntrip_server: NTRIP服务器的地址,例如'rtk.ntrip.qxwz.com'
    • _ntrip_port: NTRIP服务器的端口,例如8002
    • _ntrip_mountpoint: NTRIP服务器的挂载点,例如'RTCM32_GGB'
    • _ntrip_username: NTRIP服务器的用户名,例如'username'
    • _ntrip_password: NTRIP服务器的密码,例如'password'

这些参数允许用户根据具体需求配置UART连接和NTRIP服务器的连接设置。例如,用户可以更改UART端口和波特率以适应不同的硬件设置,或者更改NTRIP服务器的详细信息以连接到不同的RTK服务。
您提供的代码中,用户可以配置的参数主要涉及UART(通用异步收发传输器)配置和NTRIP(网络传输参考站)配置,具体包括:

  1. UART配置:

    • f9p_uart2_port: Ublox-F9P模块的UART2端口,例如'/dev/ttyUSB0'
    • f9p_uart2_baud: UART2的波特率,例如460800
  2. NTRIP配置:

    • _ntrip_server: NTRIP服务器的地址,例如'rtk.ntrip.qxwz.com'
    • _ntrip_port: NTRIP服务器的端口,例如8002
    • _ntrip_mountpoint: NTRIP服务器的挂载点,例如'RTCM32_GGB'
    • _ntrip_username: NTRIP服务器的用户名,例如'username'
    • _ntrip_password: NTRIP服务器的密码,例如'password'

这些参数允许用户根据具体需求配置UART连接和NTRIP服务器的连接设置。例如,用户可以更改UART端口和波特率以适应不同的硬件设置,或者更改NTRIP服务器的详细信息以连接到不同的RTK服务。

文章来源:https://blog.csdn.net/m0_73640344/article/details/135473670
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。