[英]Delay in Real-Time Reading from Multiple Serial Ports (GPS, through RS232 - USB adapter)
At the moment i am working on a ROS system with multiple sensors through various interfaces.目前,我正在通过各种接口开发具有多个传感器的 ROS 系统。 Two of the most important sensors are GPS and Gyro that are connected through RS232-USB adapter.
两个最重要的传感器是 GPS 和陀螺仪,它们通过 RS232-USB 适配器连接。
I would like to emphasize that i am not in anyway familiar or expert in serial connections.我想强调的是,我对串行连接并不熟悉或不熟悉。
I use python to read the serial data and publish them to ROS-topic and subscribe them via Matlab Simulink.我使用 python 读取串行数据并将它们发布到 ROS-topic 并通过 Matlab Simulink 订阅它们。
I had been using one GPS and Gyro simultaneously and there were no problem at all (adapters from different manufacturer were used for each, let's say, i have 2 RS232-USB adapter manufacturers; TA and TB).我一直在同时使用一个 GPS 和陀螺仪,完全没有问题(每个制造商都使用了不同制造商的适配器,比方说,我有 2 个 RS232-USB 适配器制造商;TA 和 TB)。
Due to some purposes, i decided to install an additional GPS (hence 2 GPS(s) and a Gyro simultaneously were used in real time).由于某些目的,我决定安装一个额外的 GPS(因此同时使用了 2 个 GPS 和一个陀螺仪)。 Let's say i put those 2 GPS quite close;
假设我把那 2 个 GPS 放得很近; less than 1m.
小于1m。
Those two GPS have identical serial port setting (same baud rate, same parity, same stopbits, same update frequency, etc.) and i used the same RS232-USB adapter TA type for both GPS.这两个 GPS 具有相同的串行端口设置(相同的波特率、相同的奇偶校验、相同的停止位、相同的更新频率等),并且我为两个 GPS 使用了相同的 RS232-USB 适配器 TA 类型。
However, there was a significant delay when subscribing in Matlab Simulink (i used simulation data inspection/logger).但是,订阅 Matlab Simulink 时出现了明显的延迟(我使用了模拟数据检查/记录器)。 One of the GPS was late!
其中一台 GPS 迟到了! What i mean by late is that one GPS did not update in real time.
我的意思是说一个 GPS 没有实时更新。
For example, at t(time)=3, both GPS should be at p(position)=10.例如,在 t(time)=3 时,两个 GPS 都应该在 p(position)=10。 But one GPS reaches p=10 after 40~60 seconds after the other GPS;
但是一个GPS在另一个GPS之后40~60秒后达到p=10; GPS which is correct (time vs position is real time).
GPS 是正确的(时间与位置是实时的)。 Below i attach a graph.
下面我附上一张图。
Those two curves should not be that far那两条曲线应该不会那么远
I dont know what might have caused this problem, Gyro has no delay problem at all, it seems only those 2 GPS are racing each other to send the data.我不知道是什么原因导致了这个问题,陀螺仪根本没有延迟问题,似乎只有那两个 GPS 在互相竞争发送数据。
Edit (12/11/2019 12:34 GMT+9)
编辑 (12/11/2019 12:34 GMT+9)
Below is my code for one GPS, and for other GPS i simply create a new .py, and use exactly the same code but with different node name and rostopic.下面是我的一个 GPS 代码,而对于另一个 GPS,我只是创建一个新的 .py,并使用完全相同的代码,但具有不同的节点名称和 rostopic。
#!/usr/bin/env python
import serial
import types
import re
import rospy
import time
import threading
from datetime import datetime
from shipcon.msg import gps_position
from shipcon.msg import gps_local_position
from shipcon.msg import gps_navinfo
from shipcon.msg import gps_time
#Constants-----------------------------------------------------------------------------------------
PUBLISH_RATE = 10 #Hz
SERIAL_PORT = "/dev/ttyUSB1"
BAUD_RATE = 115200
#Class-----------------------------------------------------------------------------------------
class GpsSerial:
def __init__(self, serial_port, baud_rate):
self.gpsArr = []
self.gpsStr = ""
self.pos = gps_position()
self.localpos = gps_local_position()
self.navinfo = gps_navinfo()
self.time = gps_time()
self.ser = serial.Serial(
port = serial_port,
baudrate = baud_rate,
parity = serial.PARITY_NONE,
bytesize = serial.EIGHTBITS,
stopbits = serial.STOPBITS_ONE,
timeout = None,
xonxoff = 0, #Enable software flow control
rtscts = 0, #Enable Hardware(RTS,CTS) flow control
)
def get_gps(self):
self.gpsStr = self.ser.readline()
self.gpsArr = self.gpsStr.split(',')
if re.match(r"^\$.*", self.gpsArr[0]):
if self.gpsArr[0] == '$PTNL':
if self.gpsArr[1] == 'GGK':
self.pos.latitude_deg = int(float(self.gpsArr[4]) // 100)
self.pos.latitude_min = float(self.gpsArr[4]) - (self.pos.latitude_deg * 100)
self.pos.latitude_dir = self.gpsArr[5]
self.pos.longitude_deg = int(float(self.gpsArr[6]) // 100)
self.pos.longitude_min = float(self.gpsArr[6]) - (self.pos.longitude_deg * 100)
self.pos.longitude_dir = self.gpsArr[7]
self.pos.gps_quality = int(self.gpsArr[8])
self.pos.satellite_number = int(self.gpsArr[9])
elif self.gpsArr[1] == 'VGK':
if self.gpsArr[4] =='-' or self.gpsArr[4] == '':
pass
else:
self.localpos.localpos_e = float(self.gpsArr[4])#float( re.sub(r'\+', "", self.gpsArr[4]) )
if self.gpsArr[5] =='-' or self.gpsArr[5] == '':
pass
else:
self.localpos.localpos_n = float(self.gpsArr[5])#float( re.sub(r'\+', "", self.gpsArr[5]) )
if self.gpsArr[6] =='-' or self.gpsArr[6] == '':
pass
else:
self.localpos.localpos_z = float(self.gpsArr[6])#float( re.sub(r'\+', "", self.gpsArr[6]) )
elif self.gpsArr[1] == 'VHD':
self.localpos.local_azimath = float(self.gpsArr[4])
self.localpos.local_vertical = float(self.gpsArr[6])
self.localpos.local_range = float(self.gpsArr[8])
elif self.gpsArr[0] == '$GPGST':
self.pos.latitude_err = float(self.gpsArr[6])
self.pos.longitude_err = float(self.gpsArr[7])
self.pos.ellipse_err_maj = float(self.gpsArr[3])
self.pos.ellipse_err_min = float(self.gpsArr[4])
self.navinfo.truenorth_heading_err = float(self.gpsArr[5])
elif self.gpsArr[0] == '$GPROT':
if self.gpsArr[1] =='-' or self.gpsArr[1] == '':
pass
else:
self.navinfo.rotation_rate = float(self.gpsArr[1])
elif self.gpsArr[0] == '$GPVTG':
if self.gpsArr[1] =='' or self.gpsArr[5]=='' or self.gpsArr[7]=='':
pass
else:
self.navinfo.truenorth_heading = float(self.gpsArr[1])
self.navinfo.speed_knot = float(self.gpsArr[5])
self.navinfo.speed_km = float(self.gpsArr[7])
elif self.gpsArr[0] == '$GPZDA':
tmptime = datetime.strptime(self.gpsArr[1]+','+self.gpsArr[4]+self.gpsArr[3]+self.gpsArr[2], '%H%M%S.%f,%Y%m%d')
self.time.day = tmptime.day
self.time.month = tmptime.month
self.time.year = tmptime.year
self.time.hour = tmptime.hour
self.time.min = tmptime.minute
self.time.sec = tmptime.second
elif self.gpsArr[0] == '$GPGGA':
self.pos.latitude_deg = int(float(self.gpsArr[2]) // 100)
self.pos.latitude_min = float(self.gpsArr[2]) - (self.pos.latitude_deg * 100)
self.pos.latitude_dir = self.gpsArr[3]
self.pos.longitude_deg = int(float(self.gpsArr[4]) // 100)
self.pos.longitude_min = float(self.gpsArr[4]) - (self.pos.longitude_deg * 100)
self.pos.longitude_dir = self.gpsArr[5]
#self.pos.gps_quality = int(self.gpsArr[8])
#self.pos.satellite_number = int(self.gpsArr[7])
class RosPublish:
def __init__(self):
self.pub_pos = rospy.Publisher('gps_position', gps_position, queue_size = 1)
self.pub_localpos = rospy.Publisher('gps_localposition', gps_local_position, queue_size = 1)
self.pub_navinfo = rospy.Publisher('gps_navinfo', gps_navinfo, queue_size = 1)
self.pub_time = rospy.Publisher('gps_time', gps_time, queue_size = 1)
def ros_log(self, pos, localpos, navinfo, time):
rospy.loginfo(pos)
rospy.loginfo(localpos)
rospy.loginfo(navinfo)
rospy.loginfo(time)
def ros_pub(self, pos, localpos, navinfo, time):
self.pub_pos.publish(pos)
self.pub_localpos.publish(localpos)
self.pub_navinfo.publish(navinfo)
self.pub_time.publish(time)
#Function-----------------------------------------------------------------------------------------
def publish_gps(gps):
rospy.init_node('NODE_Gps', anonymous = True)
ros = rospy.Rate(PUBLISH_RATE)
pub = RosPublish()
pub.ros_log(gps.pos, gps.localpos, gps.navinfo, gps.time)
pub.ros_pub(gps.pos, gps.localpos, gps.navinfo, gps.time)
ros.sleep()
def refresh_gps(gps):
while not rospy.is_shutdown():
gps.get_gps()
#Main-----------------------------------------------------------------------------------------
if __name__ == '__main__':
try:
gps = GpsSerial(SERIAL_PORT, BAUD_RATE)
thread_1 = threading.Thread(target = refresh_gps, args = (gps,))
thread_1.start()
while not rospy.is_shutdown():
publish_gps(gps)
except rospy.ROSInterruptException:
pass
I used Matlab to subscribe and log all the data from the sensors.我使用 Matlab 订阅和记录来自传感器的所有数据。 At the moment the only calculation that i am doing in Matlab is just a conversion of GPS long/lat data to XY coordinates to get the real time trajectory of my vessel.
目前,我在 Matlab 中所做的唯一计算只是将 GPS 长/纬度数据转换为 XY 坐标,以获得我船只的实时轨迹。 This conversion is a very simple calculation which i dont think will cause a serious delay.
这种转换是一个非常简单的计算,我认为不会造成严重的延迟。
If you could give me solution, or even an insight, it would be very appreciated.如果您能给我解决方案,甚至是见解,将不胜感激。 Thank you very much.
非常感谢。
Warmest regards温馨问候
I do not have enough rep to post a comment, so this is not really an answer.我没有足够的代表发表评论,所以这不是一个真正的答案。 There are some issues with the way you have set up your python node.
您设置 Python 节点的方式存在一些问题。 It might appear to be working, but it is definitely doing it quite inefficiently.
它可能看起来有效,但它确实效率很低。 There might be more issues, but the following issues should be solved:
可能还有更多问题,但应解决以下问题:
rospy.init_node('NODE_Gps', anonymous = True)
to your '__main__'.rospy.init_node('NODE_Gps', anonymous = True)
到你的 '__main__'。 Currently you are re-initializing the node every time you publish the message.self.pub_... = rospy.Publisher(...)
lines to your '__main__'.self.pub_... = rospy.Publisher(...)
行移动到您的“__main__”。 Creating the publishers is meant to be done only once, in fact I would get rid of the entire "RosPublish class". However you decide to refactor your node, keep in mind that rospy.init_node and the rospy.Publisher lines should only be called once.不管你决定重构你的节点,记住 rospy.init_node 和 rospy.Publisher 行应该只被调用一次。
Some more notes on the code:关于代码的更多说明:
ros = rospy.Rate(PUBLISH_RATE)
, it really bothers me for some reason. ros = rospy.Rate(PUBLISH_RATE)
,出于某种原因确实让我感到困扰。 The name of the variable has absolutely nothing to do with what it represents and is very misleading.
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.