sgslib 1.5.1 → 1.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/sgs/alarm.rb +2 -2
- data/lib/sgs/bearing.rb +31 -3
- data/lib/sgs/config.rb +0 -1
- data/lib/sgs/course.rb +18 -5
- data/lib/sgs/diagnostics.rb +1 -1
- data/lib/sgs/gps.rb +23 -3
- data/lib/sgs/location.rb +116 -59
- data/lib/sgs/logger.rb +1 -1
- data/lib/sgs/mission.rb +62 -185
- data/lib/sgs/mission_status.rb +16 -4
- data/lib/sgs/navigate.rb +203 -79
- data/lib/sgs/nmea.rb +3 -2
- data/lib/sgs/otto.rb +190 -78
- data/lib/sgs/redis_base.rb +9 -9
- data/lib/sgs/report.rb +2 -2
- data/lib/sgs/rpc.rb +5 -6
- data/lib/sgs/version.rb +1 -1
- data/lib/sgs/waypoint.rb +3 -2
- data/sgslib.gemspec +3 -3
- metadata +7 -9
- data/exe/sgs_nav +0 -43
data/lib/sgs/otto.rb
CHANGED
@@ -31,6 +31,13 @@
|
|
31
31
|
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
32
32
|
#
|
33
33
|
# ABSTRACT
|
34
|
+
# This daemon handles all serial I/O with the low-level board (Otto). Otto
|
35
|
+
# publishes various status messages at regular intervals, and has a series
|
36
|
+
# of registers which can be used to alter the low-level operational state.
|
37
|
+
# This daemon code has two threads. One thread listens for RPCs to update
|
38
|
+
# Otto register state, and the other listens for status messages from Otto.
|
39
|
+
# The class also has helper functions for converting between Otto data
|
40
|
+
# formats (usually 8bit) and internal formats (usually floating point).
|
34
41
|
#
|
35
42
|
require 'serialport'
|
36
43
|
require 'msgpack'
|
@@ -40,49 +47,96 @@ require 'msgpack'
|
|
40
47
|
#
|
41
48
|
module SGS
|
42
49
|
class Otto < RedisBase
|
43
|
-
attr_accessor :
|
44
|
-
attr_accessor :mode, :rudder_m, :rudder_c, :sail_m, :sail_c
|
50
|
+
attr_accessor :mode, :serial_port
|
45
51
|
attr_accessor :bv_m, :bv_c, :bi_m, :bi_c, :bt_m, :bt_c, :sv_m, :sv_c
|
46
|
-
|
47
|
-
attr_reader :
|
52
|
+
attr_reader :alarm_status
|
53
|
+
attr_reader :actual_rudder, :actual_sail
|
48
54
|
attr_reader :otto_mode, :otto_timestamp, :telemetry
|
49
55
|
|
56
|
+
#
|
57
|
+
# Updates to Otto are done by setting an 8bit register value, as below.
|
58
|
+
ALARM_CLEAR_REGISTER = 0
|
59
|
+
MISSION_CONTROL_REGISTER = 1
|
60
|
+
MODE_REGISTER = 2
|
61
|
+
BUZZER_REGISTER = 3
|
62
|
+
RUDDER_ANGLE_REGISTER = 4
|
63
|
+
SAIL_ANGLE_REGISTER = 5
|
64
|
+
COMPASS_HEADING_REGISTER = 6
|
65
|
+
MIN_COMPASS_REGISTER = 7
|
66
|
+
MAX_COMPASS_REGISTER =8
|
67
|
+
AWA_HEADING_REGISTER = 9
|
68
|
+
MIN_AWA_REGISTER = 10
|
69
|
+
MAX_AWA_REGISTER = 11
|
70
|
+
WAKE_DURATION_REGISTER = 12
|
71
|
+
NEXT_WAKEUP_REGISTER = 13
|
72
|
+
RUDDER_PID_P = 14
|
73
|
+
RUDDER_PID_I = 15
|
74
|
+
RUDDER_PID_D = 16
|
75
|
+
RUDDER_PID_E_NUM = 17
|
76
|
+
RUDDER_PID_E_DEN = 18
|
77
|
+
RUDDER_PID_U_DIV = 19
|
78
|
+
SAIL_MXC_M_VALUE = 20
|
79
|
+
SAIL_MXC_C_VALUE = 21
|
80
|
+
SAIL_MXC_U_DIV = 22
|
81
|
+
MAX_REGISTER = 23
|
82
|
+
|
83
|
+
#
|
84
|
+
# This is different from mission mode. This mode defines how Otto should
|
85
|
+
# operate. Inert means "do nothing". Diagnostic mode is for the low-level
|
86
|
+
# code to run self-checks and calibrations. Manual means that the upper
|
87
|
+
# level system controls the rudder and sail angle without any higher-level
|
88
|
+
# PID controller. Track compass means that the boat will try to keep the
|
89
|
+
# actual compass reading within certain parameters, and track AWA will
|
90
|
+
# try to maintain a specific "apparent wind angle".
|
50
91
|
MODE_INERT = 0
|
51
|
-
|
92
|
+
MODE_DIAG = 1
|
52
93
|
MODE_MANUAL = 2
|
53
|
-
|
54
|
-
|
94
|
+
MODE_REMOTE = 3
|
95
|
+
MODE_TRACK_COMPASS = 4
|
96
|
+
MODE_TRACK_AWA = 5
|
55
97
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
98
|
+
#
|
99
|
+
# Define some tweaks for rudder and sail setting. Rudder goes from
|
100
|
+
# +/-40 degrees, with zero indicating a straight rudder. On Otto, this
|
101
|
+
# translates to 0 (for -40.0), 128 (for the zero position) and 255 (for
|
102
|
+
# +40 degrees of rudder). A fully trimmed-in sail is zero and a fully
|
103
|
+
# extended sail is 255 (0->100 from a function perspective).
|
104
|
+
RUDDER_MAX = 40.0
|
105
|
+
RUDDER_MIN = -40.0
|
106
|
+
RUDDER_M = 3.175
|
107
|
+
RUDDER_C = 128.0
|
108
|
+
SAIL_MAX = 100.0
|
109
|
+
SAIL_MIN = 0.0
|
110
|
+
SAIL_M = 2.55
|
111
|
+
SAIL_C = 0.0
|
60
112
|
|
61
113
|
#
|
62
|
-
# Set up some useful defaults. We assume rudder goes from 0 to
|
63
|
-
# the sail angle.
|
114
|
+
# Set up some useful defaults. We assume rudder goes from 0 to 255 as does
|
115
|
+
# the sail angle.
|
64
116
|
def initialize
|
65
117
|
serial_port = nil
|
66
118
|
#
|
67
|
-
# Configure the Mx + C values for sail and rudder
|
68
|
-
@rudder_m = 2.5
|
69
|
-
@rudder_c = 100.0
|
70
|
-
@sail_m = 2.0
|
71
|
-
@sail_c = 0.0
|
72
|
-
#
|
73
|
-
# Now set the rudder and sail to default positions (rudder is centered)
|
74
|
-
rudder = 0.0
|
75
|
-
sail = 0.0
|
76
|
-
#
|
77
119
|
# Set some defaults for the read-back parameters
|
78
|
-
|
79
|
-
@
|
80
|
-
|
120
|
+
# The following five parameters are reported back by Otto with a status
|
121
|
+
# message, and are read-only. @alarm_status is 16 bits while the other
|
122
|
+
# four are 8-bit values. The helper methods convert these 8-bit values
|
123
|
+
# into radians, etc. The telemetry parameters are used to capture
|
124
|
+
# telemetry data from Otto.
|
125
|
+
@alarm_status = 0
|
126
|
+
@actual_rudder = @actual_sail = @actual_awa = @actual_compass = 0
|
81
127
|
@telemetry = Array.new(16)
|
82
128
|
#
|
129
|
+
# Mode is used by Otto to decide how to steer the boat and trim the
|
130
|
+
# sails.
|
131
|
+
@otto_mode = MODE_INERT
|
132
|
+
@otto_timestamp = 1000
|
133
|
+
#
|
83
134
|
# Set up some basic parameters for battery/solar readings
|
84
135
|
@bv_m = @bi_m = @bt_m = @sv_m = 1.0
|
85
136
|
@bv_c = @bi_c = @bt_c = @sv_c = 0.0
|
137
|
+
#
|
138
|
+
# RPC client / server
|
139
|
+
@rpc_client = @rpc_server = nil
|
86
140
|
super
|
87
141
|
end
|
88
142
|
|
@@ -96,7 +150,7 @@ module SGS
|
|
96
150
|
def self.daemon
|
97
151
|
puts "Low-level (Otto) communication subsystem starting up..."
|
98
152
|
otto = new
|
99
|
-
config =
|
153
|
+
config = Config.load
|
100
154
|
otto.serial_port = SerialPort.new config.otto_device, config.otto_speed
|
101
155
|
otto.serial_port.read_timeout = 10000
|
102
156
|
#
|
@@ -111,9 +165,31 @@ module SGS
|
|
111
165
|
t2.join
|
112
166
|
end
|
113
167
|
|
168
|
+
#
|
169
|
+
# Build a C include file based on the current register definitions
|
170
|
+
def self.build_include(fname)
|
171
|
+
otto = new
|
172
|
+
File.open(fname, "w") do |f|
|
173
|
+
f.puts "/*\n * Autogenerated by #{__FILE__}.\n * DO NOT HAND-EDIT!\n */"
|
174
|
+
constants.sort.each do |c|
|
175
|
+
if c.to_s =~ /REGISTER$/
|
176
|
+
cval = Otto.const_get(c)
|
177
|
+
str = "#define SGS_#{c.to_s}"
|
178
|
+
str += "\t" if str.length < 32
|
179
|
+
str += "\t#{cval}"
|
180
|
+
f.puts str
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
114
186
|
#
|
115
187
|
# Synchronize with the low-level board by sending CQ messages until
|
116
|
-
# they respond.
|
188
|
+
# they respond. When Mother boots up, the serial console is shared with
|
189
|
+
# Otto so a lot of rubbish is sent to the low-level board. To notify
|
190
|
+
# Otto that we are now talking sense, we send @@CQ! and Otto responds
|
191
|
+
# with +CQOK. Note that this function, which is always called before any
|
192
|
+
# of the threads, is bidirectional in terms of serial I/O.
|
117
193
|
def synchronize
|
118
194
|
index = 0
|
119
195
|
backoffs = [1, 1, 1, 1, 2, 2, 3, 5, 10, 10, 20, 30, 60]
|
@@ -154,6 +230,10 @@ module SGS
|
|
154
230
|
#
|
155
231
|
# Telemetry data (every two seconds)
|
156
232
|
parse_telemetry(data[1..])
|
233
|
+
when '*'
|
234
|
+
#
|
235
|
+
# Message for the debug log
|
236
|
+
parse_debug(data[1..])
|
157
237
|
end
|
158
238
|
end
|
159
239
|
end
|
@@ -164,31 +244,19 @@ module SGS
|
|
164
244
|
puts "Starting OTTO writer thread..."
|
165
245
|
#
|
166
246
|
# Now listen for Redis PUB/SUB requests and act on each one.
|
247
|
+
myredis = Redis.new
|
167
248
|
while true
|
168
|
-
channel, request =
|
249
|
+
channel, request = myredis.brpop("otto")
|
169
250
|
request = MessagePack.unpack(request)
|
170
251
|
puts "Req:[#{request.inspect}]"
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
puts "
|
176
|
-
|
177
|
-
# Don't let the command stack get too big.
|
178
|
-
while @command_stack.length > 5
|
179
|
-
sleep 5
|
180
|
-
end
|
181
|
-
|
252
|
+
params = request['params']
|
253
|
+
next if request['method'] != "set_local_register"
|
254
|
+
puts "PARAMS: #{params}"
|
255
|
+
cmd = "R%d=%X\r\n" % params
|
256
|
+
puts "Command: #{cmd}"
|
257
|
+
@serial_port.write cmd
|
182
258
|
puts "> Sending command: #{str}"
|
183
259
|
@serial_port.puts "#{str}"
|
184
|
-
|
185
|
-
reply = {
|
186
|
-
'id' => id,
|
187
|
-
'jsonrpc' => '2.0',
|
188
|
-
'result' => result
|
189
|
-
}
|
190
|
-
SGS::RedisBase.redis.rpush(id, MessagePack.pack(reply))
|
191
|
-
SGS::RedisBase.redis.expire(id, 30)
|
192
260
|
end
|
193
261
|
end
|
194
262
|
|
@@ -208,13 +276,13 @@ module SGS
|
|
208
276
|
# Parse a status message from Otto. In the form:
|
209
277
|
# 0001:C000:0000
|
210
278
|
def parse_status(status)
|
211
|
-
puts "
|
279
|
+
puts "OTTO PARSE: #{status}"
|
212
280
|
args = status.split /:/
|
213
281
|
@alarm_status = args[0].to_i(16)
|
214
282
|
wc = args[1].to_i(16)
|
215
283
|
rs = args[2].to_i(16)
|
216
|
-
@
|
217
|
-
@
|
284
|
+
@actual_awa = (wc >> 8) & 0xff
|
285
|
+
@actual_compass = (wc & 0xff)
|
218
286
|
@actual_rudder = (rs >> 8) & 0xff
|
219
287
|
@actual_sail = (rs & 0xff)
|
220
288
|
p self
|
@@ -225,7 +293,6 @@ module SGS
|
|
225
293
|
# Parse a timestamp message from Otto. In the form: "000FE2" 24 bits
|
226
294
|
# representing the elapsed seconds since Otto restarted.
|
227
295
|
def parse_tstamp(tstamp)
|
228
|
-
puts "Parse timestamp: #{tstamp}"
|
229
296
|
newval = tstamp.to_i(16)
|
230
297
|
if newval < @otto_timestamp
|
231
298
|
puts "ALARM! Otto rebooted (or something)..."
|
@@ -237,7 +304,6 @@ module SGS
|
|
237
304
|
# Parse a mode state message from Otto. In the form: "00". An eight bit
|
238
305
|
# quantity.
|
239
306
|
def parse_mode(mode)
|
240
|
-
puts "Parse Otto Mode State: #{mode}"
|
241
307
|
@otto_mode = mode.to_i(16)
|
242
308
|
end
|
243
309
|
|
@@ -245,80 +311,126 @@ module SGS
|
|
245
311
|
# Parse a telemetry message from Otto. In the form: "7327" where the first
|
246
312
|
# character is the channel (0->9) and the remaining 12 bits are the value.
|
247
313
|
def parse_telemetry(telemetry)
|
248
|
-
puts "Parse Otto Telemetry Data: #{telemetry}"
|
249
314
|
data = telemetry.to_i(16)
|
250
315
|
chan = (data >> 12) & 0xf
|
251
|
-
@telemetry[chan] = data &
|
316
|
+
@telemetry[chan] = data & 0xfff
|
317
|
+
end
|
318
|
+
|
319
|
+
#
|
320
|
+
# Parse a debug message from the low-level code. Basically just append it
|
321
|
+
# to a log file.
|
322
|
+
def parse_debug(debug_data)
|
323
|
+
puts "DEBUG: [#{debug_data}].\n"
|
324
|
+
end
|
325
|
+
|
326
|
+
#
|
327
|
+
# Clear an alarm setting
|
328
|
+
def alarm_clear(alarm)
|
329
|
+
set_register(ALARM_CLEAR_REGISTER, alarm)
|
330
|
+
end
|
331
|
+
|
332
|
+
#
|
333
|
+
# Set the Otto mode
|
334
|
+
def mode=(val)
|
335
|
+
set_register(MODE_REGISTER, val) if @otto_mode != val
|
252
336
|
end
|
253
337
|
|
254
338
|
#
|
255
339
|
# Set the required rudder angle. Input values range from +/- 40.0 degrees
|
256
340
|
def rudder=(val)
|
257
|
-
val =
|
258
|
-
val =
|
259
|
-
|
341
|
+
val = RUDDER_MIN if val < RUDDER_MIN
|
342
|
+
val = RUDDER_MAX if val > RUDDER_MAX
|
343
|
+
val = (RUDDER_M * val.to_f + RUDDER_C).to_i
|
344
|
+
if val != @actual_rudder
|
345
|
+
@actual_rudder = val
|
346
|
+
set_register(RUDDER_ANGLE_REGISTER, val)
|
347
|
+
end
|
348
|
+
mode = MODE_MANUAL
|
260
349
|
end
|
261
350
|
|
262
351
|
#
|
263
352
|
# Return the rudder angle in degrees
|
264
353
|
def rudder
|
265
|
-
(@
|
354
|
+
(@actual_rudder.to_f - RUDDER_C) / RUDDER_M
|
266
355
|
end
|
267
356
|
|
268
357
|
#
|
269
|
-
# Set the required sail angle. Input values range from 0 ->
|
358
|
+
# Set the required sail angle. Input values range from 0 -> 100.
|
270
359
|
def sail=(val)
|
271
|
-
val =
|
272
|
-
val =
|
273
|
-
|
360
|
+
val = SAIL_MIN if val < SAIL_MIN
|
361
|
+
val = SAIL_MAX if val > SAIL_MAX
|
362
|
+
val = (SAIL_M * val.to_f + SAIL_C).to_i
|
363
|
+
if val != @actual_sail
|
364
|
+
@actual_sail = val
|
365
|
+
set_register(SAIL_ANGLE_REGISTER, val)
|
366
|
+
end
|
367
|
+
mode = MODE_MANUAL
|
274
368
|
end
|
275
369
|
|
276
370
|
#
|
277
371
|
# Return the sail setting (0.0 -> 100.0)
|
278
372
|
def sail
|
279
|
-
(@
|
373
|
+
(@actual_sail.to_f - SAIL_C) / SAIL_M
|
280
374
|
end
|
281
375
|
|
282
376
|
#
|
283
377
|
# Return the compass angle (in radians)
|
284
378
|
def compass
|
285
|
-
@
|
379
|
+
Bearing.xtor(@actual_compass)
|
286
380
|
end
|
287
381
|
|
288
382
|
#
|
289
383
|
# Return the apparent wind angle (in radians)
|
290
384
|
def awa
|
291
|
-
@
|
385
|
+
@actual_awa -= 256 if @actual_awa > 128
|
386
|
+
Bearing.xtor(@actual_awa)
|
387
|
+
end
|
388
|
+
|
389
|
+
#
|
390
|
+
# Return the actual wind direction (in radians)
|
391
|
+
def wind
|
392
|
+
Bearing.xtor(@actual_compass + @actual_awa)
|
292
393
|
end
|
293
394
|
|
294
395
|
#
|
295
|
-
# Set the required compass reading
|
396
|
+
# Set the required compass reading (in radians)
|
296
397
|
def track_compass=(val)
|
297
|
-
|
298
|
-
|
398
|
+
val = Bearing.rtox(val)
|
399
|
+
if @track_compass.nil? or @track_compass != val
|
400
|
+
@track_compass = val
|
401
|
+
set_register(COMPASS_HEADING_REGISTER, val)
|
299
402
|
end
|
300
|
-
|
301
|
-
@raw_tc = (val.to_f * 128.0 / Math::PI).to_i
|
403
|
+
mode = MODE_TRACK_COMPASS
|
302
404
|
end
|
303
405
|
|
304
406
|
#
|
305
407
|
# Return the compass value for tracking.
|
306
408
|
def track_compass
|
307
|
-
@
|
409
|
+
Bearing.xtor(@track_compass)
|
308
410
|
end
|
309
411
|
|
310
412
|
#
|
311
|
-
# Set the required AWA for tracking.
|
413
|
+
# Set the required AWA for tracking (in radians).
|
312
414
|
def track_awa=(val)
|
313
|
-
val =
|
314
|
-
|
315
|
-
|
415
|
+
val = Bearing.rtox(val)
|
416
|
+
if @track_awa.nil? or @track_awa != val
|
417
|
+
@track_awa = val
|
418
|
+
set_register(AWA_HEADING_REGISTER, val)
|
419
|
+
end
|
420
|
+
mode = MODE_TRACK_AWA
|
316
421
|
end
|
317
422
|
|
318
423
|
#
|
319
|
-
# Return the current tracking AWA.
|
424
|
+
# Return the current tracking AWA (in radians).
|
320
425
|
def track_awa
|
321
|
-
@
|
426
|
+
Bearing.xtor(@track_awa)
|
427
|
+
end
|
428
|
+
|
429
|
+
#
|
430
|
+
# RPC client call to set register - sent to writer function above
|
431
|
+
def set_register(regno, value)
|
432
|
+
@rpc_client = RPCClient.new("otto") unless @rpc_client
|
433
|
+
@rpc_client.set_local_register(regno, value)
|
322
434
|
end
|
323
435
|
end
|
324
436
|
end
|
data/lib/sgs/redis_base.rb
CHANGED
@@ -75,7 +75,7 @@ module SGS
|
|
75
75
|
# Initialize a Redis variable.
|
76
76
|
def self.var_init(var, val, idx = nil)
|
77
77
|
cls = new
|
78
|
-
|
78
|
+
RedisBase.redis.setnx cls.make_redis_name(var, :idx => idx), self.to_redis(var, val, idx)
|
79
79
|
end
|
80
80
|
|
81
81
|
#
|
@@ -96,8 +96,8 @@ module SGS
|
|
96
96
|
# It's an array - iterate and read the values.
|
97
97
|
lval.size.times do |idx|
|
98
98
|
idx_val = lval[idx]
|
99
|
-
lval[idx] = redis_read_var var, idx_val.class, :idx => idx
|
100
|
-
|
99
|
+
lval[idx] = redis_read_var var, idx_val.class, :idx => idx
|
100
|
+
end
|
101
101
|
elsif lval.kind_of? Location
|
102
102
|
#
|
103
103
|
# ::FIXME:: Yes. this is a hack.
|
@@ -141,7 +141,7 @@ module SGS
|
|
141
141
|
#
|
142
142
|
# Inside a multi-block, set all the variables and increment
|
143
143
|
# the count.
|
144
|
-
|
144
|
+
RedisBase.redis.multi do |pipeline|
|
145
145
|
var_list.each do |key, value|
|
146
146
|
pipeline.set key, value
|
147
147
|
end
|
@@ -157,7 +157,7 @@ module SGS
|
|
157
157
|
# class name), you can remember the last received count and decide if
|
158
158
|
# there is fresh data. Or, you can just act anyway.
|
159
159
|
def publish
|
160
|
-
|
160
|
+
RedisBase.redis.publish self.class.redis_handle, count.to_s
|
161
161
|
end
|
162
162
|
|
163
163
|
#
|
@@ -182,7 +182,7 @@ module SGS
|
|
182
182
|
#
|
183
183
|
# Retrieve the count
|
184
184
|
def count
|
185
|
-
|
185
|
+
RedisBase.redis.get count_name
|
186
186
|
end
|
187
187
|
|
188
188
|
#
|
@@ -195,7 +195,7 @@ module SGS
|
|
195
195
|
# Get an instance variable value from a Redis value.
|
196
196
|
def redis_read_var(var, klass, opts = {})
|
197
197
|
redis_name = make_redis_name var, opts
|
198
|
-
redis_val =
|
198
|
+
redis_val = RedisBase.redis.get redis_name
|
199
199
|
redis_val = nil if redis_val == ""
|
200
200
|
if redis_val
|
201
201
|
if not klass or klass == NilClass
|
@@ -211,9 +211,9 @@ module SGS
|
|
211
211
|
when klass == Float
|
212
212
|
redis_val = redis_val.to_f
|
213
213
|
when klass == FalseClass
|
214
|
-
redis_val =
|
214
|
+
redis_val = (redis_val == "true" or redis_val == "TRUE")
|
215
215
|
when klass == TrueClass
|
216
|
-
redis_val = true
|
216
|
+
redis_val = (redis_val == "true" or redis_val == "TRUE")
|
217
217
|
end
|
218
218
|
end
|
219
219
|
redis_val
|
data/lib/sgs/report.rb
CHANGED
@@ -38,12 +38,12 @@ require 'serialport'
|
|
38
38
|
# Routines for handling sailboat navigation and route planning.
|
39
39
|
#
|
40
40
|
module SGS
|
41
|
-
class Report
|
41
|
+
class Report
|
42
42
|
#
|
43
43
|
# Main daemon function (called from executable)
|
44
44
|
def self.daemon
|
45
45
|
puts "Reporting subsystem starting up..."
|
46
|
-
config =
|
46
|
+
config = Config.load
|
47
47
|
sp = SerialPort.new config.comm_device, config.comm_speed
|
48
48
|
sp.read_timeout = 10000
|
49
49
|
loop do
|
data/lib/sgs/rpc.rb
CHANGED
@@ -55,9 +55,8 @@ module SGS
|
|
55
55
|
'method' => name,
|
56
56
|
'params' => args
|
57
57
|
}
|
58
|
-
|
59
|
-
|
60
|
-
MessagePack.unpack(response)['result']
|
58
|
+
puts "RPC CLIENT SENDING MESSAGE! request: #{request.inspect}, channel: #{@channel}"
|
59
|
+
RedisBase.redis.lpush(@channel, request.to_msgpack)
|
61
60
|
end
|
62
61
|
end
|
63
62
|
|
@@ -70,7 +69,7 @@ module SGS
|
|
70
69
|
def start
|
71
70
|
puts "Starting RPC server for #{@channel}"
|
72
71
|
loop do
|
73
|
-
channel, request =
|
72
|
+
channel, request = RedisBase.redis.brpop(@channel)
|
74
73
|
request = MessagePack.unpack(request)
|
75
74
|
|
76
75
|
puts "Working on request: #{request['id']}"
|
@@ -84,8 +83,8 @@ module SGS
|
|
84
83
|
'id' => request['id']
|
85
84
|
}
|
86
85
|
|
87
|
-
|
88
|
-
|
86
|
+
RedisBase.redis.rpush(request['id'], MessagePack.pack(reply))
|
87
|
+
RedisBase.redis.expire(request['id'], 30)
|
89
88
|
end
|
90
89
|
end
|
91
90
|
end
|
data/lib/sgs/version.rb
CHANGED
data/lib/sgs/waypoint.rb
CHANGED
@@ -39,7 +39,7 @@
|
|
39
39
|
module SGS
|
40
40
|
#
|
41
41
|
# Waypoint, Attractor, and Repellor definitions
|
42
|
-
class Waypoint
|
42
|
+
class Waypoint
|
43
43
|
attr_accessor :location, :normal, :range, :name, :attractor
|
44
44
|
attr_reader :bearing, :distance
|
45
45
|
|
@@ -58,7 +58,8 @@ module SGS
|
|
58
58
|
def parse(data)
|
59
59
|
@@count += 1
|
60
60
|
@name = data["name"] || "Waypoint ##{@@count}"
|
61
|
-
@location =
|
61
|
+
@location = Location.new
|
62
|
+
@location.parse_hash(data)
|
62
63
|
@normal = data["normal"] || 0.0
|
63
64
|
@range = data["range"] || 0.1
|
64
65
|
end
|
data/sgslib.gemspec
CHANGED
@@ -34,15 +34,15 @@ Gem::Specification.new do |spec|
|
|
34
34
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
35
35
|
spec.require_paths = ["lib"]
|
36
36
|
|
37
|
-
spec.required_ruby_version = '>=
|
37
|
+
spec.required_ruby_version = '>= 2.7.6'
|
38
38
|
|
39
39
|
spec.add_development_dependency "bundler", "~> 2.2"
|
40
40
|
spec.add_development_dependency "rake", ">= 12.3.3"
|
41
41
|
spec.add_development_dependency "rspec", "~> 3.0"
|
42
42
|
|
43
|
-
spec.add_runtime_dependency "redis", "~>
|
43
|
+
spec.add_runtime_dependency "redis", "~> 5.0"
|
44
44
|
spec.add_runtime_dependency "serialport", "~> 1.3"
|
45
|
-
spec.add_runtime_dependency "msgpack", "~> 1.
|
45
|
+
spec.add_runtime_dependency "msgpack", "~> 1.6"
|
46
46
|
spec.add_runtime_dependency "json"
|
47
47
|
spec.add_runtime_dependency "securerandom"
|
48
48
|
spec.add_runtime_dependency "yaml"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sgslib
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.7.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Dermot Tynan
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-
|
11
|
+
date: 2023-05-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -58,14 +58,14 @@ dependencies:
|
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '5.0'
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
68
|
+
version: '5.0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: serialport
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -86,14 +86,14 @@ dependencies:
|
|
86
86
|
requirements:
|
87
87
|
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: '1.
|
89
|
+
version: '1.6'
|
90
90
|
type: :runtime
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
|
-
version: '1.
|
96
|
+
version: '1.6'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: json
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -146,7 +146,6 @@ executables:
|
|
146
146
|
- sgs_gpsread
|
147
147
|
- sgs_logger
|
148
148
|
- sgs_mission
|
149
|
-
- sgs_nav
|
150
149
|
- sgs_otto
|
151
150
|
- sgs_report
|
152
151
|
extensions: []
|
@@ -162,7 +161,6 @@ files:
|
|
162
161
|
- exe/sgs_gpsread
|
163
162
|
- exe/sgs_logger
|
164
163
|
- exe/sgs_mission
|
165
|
-
- exe/sgs_nav
|
166
164
|
- exe/sgs_otto
|
167
165
|
- exe/sgs_report
|
168
166
|
- lib/sgs/alarm.rb
|
@@ -199,7 +197,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
199
197
|
requirements:
|
200
198
|
- - ">="
|
201
199
|
- !ruby/object:Gem::Version
|
202
|
-
version:
|
200
|
+
version: 2.7.6
|
203
201
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
204
202
|
requirements:
|
205
203
|
- - ">="
|