13
13
Set the RTCM Messages to 10Hz and enable any that are needed.
14
14
'''
15
15
16
- import socket , errno
16
+ import socket , errno , threading
17
17
import time
18
+ from MAVProxy .modules .lib import rtcm3
18
19
from pymavlink import mavutil
19
20
from MAVProxy .modules .lib import mp_module
20
21
from MAVProxy .modules .lib import mp_settings
@@ -37,9 +38,19 @@ def __init__(self, mpstate):
37
38
self .add_completion_function ('(DGPSSETTING)' ,
38
39
self .dgps_settings .completion )
39
40
40
- self .port = None
41
+ self .port = None
42
+ self .waiting = False
41
43
self .last_pkt = None
42
44
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 = {}
43
54
44
55
def log_rtcm (self , data ):
45
56
'''optionally log rtcm data'''
@@ -74,7 +85,10 @@ def cmd_start(self):
74
85
self .connect_tcp_rtcm_base (self .dgps_settings .ip , self .dgps_settings .port )
75
86
else :
76
87
print ("Undefined connection type!" )
77
- return
88
+ return
89
+
90
+ self .last_rate = time .time ()
91
+ self .rate_total = 0
78
92
79
93
def dgps_status (self ):
80
94
'''show dgps status'''
@@ -91,12 +105,12 @@ def dgps_status(self):
91
105
print ("DGPS: no data" )
92
106
return
93
107
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 ))
100
114
101
115
def connect_udp_rtcm_base (self , ip , port ):
102
116
print ("UDP Connection" )
@@ -116,76 +130,79 @@ def connect_tcp_rtcm_base(self, ip, port):
116
130
self .port .settimeout (1 )
117
131
self .port .setblocking (0 )
118
132
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 ()
120
136
else :
121
137
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
169
139
170
140
def idle_task (self ):
171
141
'''called in idle time'''
172
142
if self .port is None :
173
143
return
174
144
145
+ if self .waiting is True :
146
+ return
147
+
175
148
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.
177
150
except socket .error as e :
178
151
if e .errno in [ errno .EAGAIN , errno .EWOULDBLOCK ]:
179
152
return
180
153
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
+
184
164
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
+
185
198
self .last_pkt = now
186
199
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
189
206
190
207
def init (mpstate ):
191
208
'''initialise module'''
0 commit comments