Skip to content

Commit 4b3cb23

Browse files
committed
rework to use RTCM3 Library
1 parent 0ef853c commit 4b3cb23

File tree

1 file changed

+80
-63
lines changed

1 file changed

+80
-63
lines changed

MAVProxy/modules/mavproxy_DGPS.py

Lines changed: 80 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@
1313
Set the RTCM Messages to 10Hz and enable any that are needed.
1414
'''
1515

16-
import socket, errno
16+
import socket, errno, threading
1717
import time
18+
from MAVProxy.modules.lib import rtcm3
1819
from pymavlink import mavutil
1920
from MAVProxy.modules.lib import mp_module
2021
from MAVProxy.modules.lib import mp_settings
@@ -37,9 +38,19 @@ def __init__(self, mpstate):
3738
self.add_completion_function('(DGPSSETTING)',
3839
self.dgps_settings.completion)
3940

40-
self.port = None
41+
self.port = None
42+
self.waiting = False
4143
self.last_pkt = None
4244
self.inject_seq_nr = 0
45+
self.pkt_count = 0
46+
self.last_rate = None
47+
self.rate_total = 0
48+
self.rate = 0
49+
# RTCM3 parser
50+
self.rtcm3 = rtcm3.RTCM3()
51+
self.last_id = None
52+
self.id_counts = {}
53+
self.last_by_id = {}
4354

4455
def log_rtcm(self, data):
4556
'''optionally log rtcm data'''
@@ -74,7 +85,10 @@ def cmd_start(self):
7485
self.connect_tcp_rtcm_base(self.dgps_settings.ip, self.dgps_settings.port)
7586
else:
7687
print("Undefined connection type!")
77-
return
88+
return
89+
90+
self.last_rate = time.time()
91+
self.rate_total = 0
7892

7993
def dgps_status(self):
8094
'''show dgps status'''
@@ -91,12 +105,12 @@ def dgps_status(self):
91105
print("DGPS: no data")
92106
return
93107

94-
print ("Last packet recieved %.3fs ago" % (now - self.last_pkt))
95-
# frame_size = 0
96-
# for id in sorted(self.id_counts.keys()):
97-
# print(" %4u: %u (len %u)" % (id, self.id_counts[id], len(self.last_by_id[id])))
98-
# frame_size += len(self.last_by_id[id])
99-
# print("dgps: %u packets, %.1f bytes/sec last %.1fs ago framesize %u" % (self.pkt_count, self.rate, now - self.last_pkt, frame_size))
108+
# print ("Last packet recieved %.3fs ago" % (now - self.last_pkt))
109+
frame_size = 0
110+
for id in sorted(self.id_counts.keys()):
111+
print(" %4u: %u (len %u)" % (id, self.id_counts[id], len(self.last_by_id[id])))
112+
frame_size += len(self.last_by_id[id])
113+
print("dgps: %u packets, %.2f bytes/sec last %.3fs ago framesize %u" % (self.pkt_count, self.rate, now - self.last_pkt, frame_size))
100114

101115
def connect_udp_rtcm_base(self, ip, port):
102116
print ("UDP Connection")
@@ -116,76 +130,79 @@ def connect_tcp_rtcm_base(self, ip, port):
116130
self.port.settimeout(1)
117131
self.port.setblocking(0)
118132
except:
119-
print ("ERROR: Failed to connect to RTCM base over TCP")
133+
print ("ERROR: Failed to connect to RTCM base over TCP, retrying in 2.5s")
134+
self.waiting = True
135+
threading.Timer(2.5,self.connect_tcp_rtcm_base(ip, port)).start()
120136
else:
121137
print ("Connected to base using TCP")
122-
123-
def send_rtcm_msg(self, data):
124-
msglen = 180;
125-
126-
if (len(data) > msglen * 4):
127-
print("DGPS: Message too large", len(data))
128-
return
129-
130-
# How many messages will we send?
131-
msgs = 0
132-
if (len(data) % msglen == 0):
133-
msgs = len(data) / msglen
134-
else:
135-
msgs = (len(data) / msglen) + 1
136-
137-
for a in range(0, msgs):
138-
139-
flags = 0
140-
141-
# Set the fragment flag if we're sending more than 1 packet.
142-
if (msgs) > 1:
143-
flags = 1
144-
145-
# Set the ID of this fragment
146-
flags |= (a & 0x3) << 1
147-
148-
# Set an overall sequence number
149-
flags |= (self.inject_seq_nr & 0x1f) << 3
150-
151-
152-
amount = min(len(data) - a * msglen, msglen)
153-
datachunk = data[a*msglen : a*msglen + amount]
154-
155-
self.master.mav.gps_rtcm_data_send(
156-
flags,
157-
len(datachunk),
158-
bytearray(datachunk.ljust(180, '\0')))
159-
160-
# Send a terminal 0-length message if we sent 2 or 3 exactly-full messages.
161-
if (msgs < 4) and (len(data) % msglen == 0) and (len(data) > msglen):
162-
flags = 1 | (msgs & 0x3) << 1 | (self.inject_seq_nr & 0x1f) << 3
163-
self.master.mav.gps_rtcm_data_send(
164-
flags,
165-
0,
166-
bytearray("".ljust(180, '\0')))
167-
168-
self.inject_seq_nr += 1
138+
self.waiting = False
169139

170140
def idle_task(self):
171141
'''called in idle time'''
172142
if self.port is None:
173143
return
174144

145+
if self.waiting is True:
146+
return
147+
175148
try:
176-
data = self.port.recv(1024) # Attempt to read up to 1024 bytes.
149+
data = self.port.recv(1) # Attempt to read up to 1024 bytes.
177150
except socket.error as e:
178151
if e.errno in [ errno.EAGAIN, errno.EWOULDBLOCK ]:
179152
return
180153
raise
181-
try:
182-
now = time.time()
183-
self.send_rtcm_msg(data)
154+
155+
now = time.time()
156+
if self.rtcm3.read(data):
157+
self.last_id = self.rtcm3.get_packet_ID()
158+
# print(self.last_id)
159+
rtcm3Data = self.rtcm3.get_packet()
160+
if self.rtcm3.get_packet() is None:
161+
print ("No packet")
162+
return
163+
184164
self.log_rtcm(data)
165+
166+
if not self.last_id in self.id_counts:
167+
self.id_counts[self.last_id] = 0
168+
self.last_by_id[self.last_id] = data[:]
169+
self.id_counts[self.last_id] += 1
170+
171+
blen = len(data)
172+
if blen > 4*180:
173+
# can't send this with GPS_RTCM_DATA
174+
print("WTF")
175+
return
176+
self.rate_total += blen
177+
178+
if blen > 180:
179+
flags = 1 # fragmented
180+
else:
181+
flags = 0
182+
183+
# add in the sequence number
184+
flags |= (self.pkt_count & 0x1F) << 3
185+
186+
fragment = 0
187+
while blen > 0:
188+
send_data = bytearray(data[:180])
189+
frag_len = len(send_data)
190+
data = data[frag_len:]
191+
if frag_len < 180:
192+
send_data.extend(bytearray([0]*(180-frag_len)))
193+
self.master.mav.gps_rtcm_data_send(flags | (fragment<<1), frag_len, send_data)
194+
fragment += 1
195+
blen -= frag_len
196+
self.pkt_count += 1
197+
185198
self.last_pkt = now
186199

187-
except Exception as e:
188-
print("DGPS: GPS Inject Failed:", e)
200+
if now - self.last_rate > 1:
201+
dt = now - self.last_rate
202+
rate_now = self.rate_total / float(dt)
203+
self.rate = 0.9 * self.rate + 0.1 * rate_now
204+
self.last_rate = now
205+
self.rate_total = 0
189206

190207
def init(mpstate):
191208
'''initialise module'''

0 commit comments

Comments
 (0)