sgslib 1.5.0 → 1.5.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/exe/sgs_otto +0 -0
- data/lib/sgs/alarm.rb +20 -10
- data/lib/sgs/bearing.rb +1 -0
- data/lib/sgs/diagnostics.rb +1 -0
- data/lib/sgs/gps.rb +14 -1
- data/lib/sgs/logger.rb +0 -7
- data/lib/sgs/mission.rb +1 -0
- data/lib/sgs/mission_status.rb +4 -5
- data/lib/sgs/navigate.rb +21 -2
- data/lib/sgs/otto.rb +173 -4
- data/lib/sgs/report.rb +5 -0
- data/lib/sgs/version.rb +1 -1
- data/lib/sgslib.rb +1 -4
- data/sgslib.gemspec +5 -3
- metadata +52 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b5dffcc970035c48e2b6026c72884b6ab97cc14ac43ba255cb4386244b46287c
|
4
|
+
data.tar.gz: 347c958575c0e9510047c75b997426083d4e3abf8ee479ff9b407c3395bbe118
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bdee04756fe59509497bc455f7874e9c05ecca6c9031f55133460a28ea987d9a0dd788588e2b449b9fe0630f734f23b6c968722361153b9130fa0362c354b67c
|
7
|
+
data.tar.gz: de267f01e59622938cfb1ad3ebbcb7c08c72bb02a625f1de72c93255b5e3be868cae29a1625383890c4c4aa57292b27942d735adb0abb4f36763dd481ca62893
|
data/exe/sgs_otto
CHANGED
File without changes
|
data/lib/sgs/alarm.rb
CHANGED
@@ -44,7 +44,9 @@ module SGS
|
|
44
44
|
class Alarm < RedisBase
|
45
45
|
attr_accessor :last_report, :time
|
46
46
|
|
47
|
-
|
47
|
+
#
|
48
|
+
# Alarms generated by Otto.
|
49
|
+
MISSION_SWITCH = 0
|
48
50
|
RUDDSRV_FAULT = 1
|
49
51
|
SAILSRV_FAULT = 2
|
50
52
|
VBATT_CRITICAL = 3
|
@@ -60,16 +62,18 @@ module SGS
|
|
60
62
|
RUDDER_NOZERO = 13
|
61
63
|
SAIL_NOZERO = 14
|
62
64
|
MOTHER_UNRESP = 15
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
65
|
+
#
|
66
|
+
# Alarms generated by Mother.
|
67
|
+
OTTO_RESTART = 16
|
68
|
+
MISSION_COMMENCE = 17
|
69
|
+
MISSION_COMPLETE = 18
|
70
|
+
MISSION_ABORT = 19
|
71
|
+
WAYPOINT_REACHED = 20
|
72
|
+
CROSS_TRACK_ERROR = 21
|
73
|
+
INSIDE_FENCE = 22
|
70
74
|
|
71
75
|
ALARM_NAMES = [
|
72
|
-
"
|
76
|
+
"Mission Activation Switch",
|
73
77
|
"Rudder Servo Fault",
|
74
78
|
"Sail Servo Fault",
|
75
79
|
"Battery voltage is critically low",
|
@@ -85,6 +89,7 @@ module SGS
|
|
85
89
|
"Cannot zero the rudder position",
|
86
90
|
"Cannot zero the sail position",
|
87
91
|
"Mother is unresponsive",
|
92
|
+
"OTTO Restarted",
|
88
93
|
"Mission has commenced",
|
89
94
|
"Mission is completed",
|
90
95
|
"*** MISSION ABORT ***",
|
@@ -103,8 +108,13 @@ module SGS
|
|
103
108
|
#
|
104
109
|
# Main daemon function (called from executable)
|
105
110
|
def self.daemon
|
111
|
+
puts "Alarm daemon starting up..."
|
112
|
+
otto = SGS::RPCClient.new(:otto)
|
106
113
|
loop do
|
107
|
-
|
114
|
+
#puts "Check for any alarms..."
|
115
|
+
#resp = otto.command "A?"
|
116
|
+
#puts "Response: #{resp}"
|
117
|
+
sleep 30
|
108
118
|
end
|
109
119
|
end
|
110
120
|
|
data/lib/sgs/bearing.rb
CHANGED
data/lib/sgs/diagnostics.rb
CHANGED
data/lib/sgs/gps.rb
CHANGED
@@ -32,6 +32,8 @@
|
|
32
32
|
#
|
33
33
|
# ABSTRACT
|
34
34
|
#
|
35
|
+
require 'serialport'
|
36
|
+
|
35
37
|
module SGS
|
36
38
|
class GPS < RedisBase
|
37
39
|
attr_accessor :time, :location, :sog, :cmg, :magvar
|
@@ -49,8 +51,19 @@ module SGS
|
|
49
51
|
#
|
50
52
|
# Main daemon function (called from executable)
|
51
53
|
def self.daemon
|
54
|
+
puts "GPS reader starting up..."
|
55
|
+
config = SGS::Config.load
|
56
|
+
|
57
|
+
sp = SerialPort.new config.gps_device, config.gps_speed
|
58
|
+
sp.read_timeout = 10000
|
59
|
+
|
52
60
|
loop do
|
53
|
-
|
61
|
+
nmea = SGS::NMEA.parse sp.readline
|
62
|
+
if nmea.is_gprmc?
|
63
|
+
gps = nmea.parse_gprmc
|
64
|
+
p gps
|
65
|
+
gps.save_and_publish if gps and gps.valid?
|
66
|
+
end
|
54
67
|
end
|
55
68
|
end
|
56
69
|
|
data/lib/sgs/logger.rb
CHANGED
data/lib/sgs/mission.rb
CHANGED
data/lib/sgs/mission_status.rb
CHANGED
@@ -73,7 +73,6 @@ module SGS
|
|
73
73
|
@state = STATE_AWAITING
|
74
74
|
@current_waypoint = 0
|
75
75
|
@start_time = @end_time = nil
|
76
|
-
@logger = Logger.new(STDOUT)
|
77
76
|
end
|
78
77
|
|
79
78
|
#
|
@@ -91,7 +90,7 @@ module SGS
|
|
91
90
|
#
|
92
91
|
# Commence a mission...
|
93
92
|
def start_test!(time = nil)
|
94
|
-
|
93
|
+
puts "***** Starting test phase *****"
|
95
94
|
@start_time = time || Time.now
|
96
95
|
@state = STATE_START_TEST
|
97
96
|
@current_waypoint = 0
|
@@ -104,7 +103,7 @@ module SGS
|
|
104
103
|
@end_time = time || Time.now
|
105
104
|
@state = STATE_COMPLETE
|
106
105
|
save_and_publish
|
107
|
-
|
106
|
+
puts "***** Mission completed! *****"
|
108
107
|
end
|
109
108
|
|
110
109
|
#
|
@@ -113,7 +112,7 @@ module SGS
|
|
113
112
|
@end_time = time || Time.now
|
114
113
|
@state = STATE_TERMINATED
|
115
114
|
save_and_publish
|
116
|
-
|
115
|
+
puts "***** Mission terminated! *****"
|
117
116
|
end
|
118
117
|
|
119
118
|
#
|
@@ -122,7 +121,7 @@ module SGS
|
|
122
121
|
@end_time = time || Time.now
|
123
122
|
@state = STATE_FAILURE
|
124
123
|
save_and_publish
|
125
|
-
|
124
|
+
puts "***** Mission failure! *****"
|
126
125
|
end
|
127
126
|
end
|
128
127
|
end
|
data/lib/sgs/navigate.rb
CHANGED
@@ -71,8 +71,27 @@ module SGS
|
|
71
71
|
#
|
72
72
|
# Main daemon function (called from executable)
|
73
73
|
def self.daemon
|
74
|
-
|
75
|
-
|
74
|
+
puts "Navigation system starting up..."
|
75
|
+
#
|
76
|
+
# Load the mission data from Redis and augment it with the
|
77
|
+
# contents of the mission file.
|
78
|
+
config = SGS::Config.load
|
79
|
+
mission = SGS::Mission.file_load config.mission_file
|
80
|
+
#
|
81
|
+
# Now listen for GPS data...
|
82
|
+
SGS::GPS.subscribe do |count|
|
83
|
+
puts "Received new GPS count: #{count}"
|
84
|
+
case SGS::MissionStatus.state
|
85
|
+
when STATE_COMPASS_FOLLOW
|
86
|
+
when STATE_WIND_FOLLOW
|
87
|
+
mission.navigate
|
88
|
+
when STATE_COMPLETE
|
89
|
+
when STATE_TERMINATED
|
90
|
+
when STATE_FAILURE
|
91
|
+
mission.hold_station
|
92
|
+
end
|
93
|
+
gps = SGS::GPS.load
|
94
|
+
p gps
|
76
95
|
end
|
77
96
|
end
|
78
97
|
|
data/lib/sgs/otto.rb
CHANGED
@@ -32,6 +32,8 @@
|
|
32
32
|
#
|
33
33
|
# ABSTRACT
|
34
34
|
#
|
35
|
+
require 'serialport'
|
36
|
+
require 'msgpack'
|
35
37
|
|
36
38
|
##
|
37
39
|
# Routines for interfacing with the low-level microcontroller.
|
@@ -41,6 +43,9 @@ module SGS
|
|
41
43
|
attr_accessor :raw_rudder, :raw_sail, :raw_compass, :raw_awa, :raw_tc, :raw_ta
|
42
44
|
attr_accessor :mode, :rudder_m, :rudder_c, :sail_m, :sail_c
|
43
45
|
attr_accessor :bv_m, :bv_c, :bi_m, :bi_c, :bt_m, :bt_c, :sv_m, :sv_c
|
46
|
+
attr_accessor :serial_port
|
47
|
+
attr_reader :alarm_status, :wind, :compass, :actual_rudder, :actual_sail
|
48
|
+
attr_reader :otto_mode, :otto_timestamp, :telemetry
|
44
49
|
|
45
50
|
MODE_INERT = 0
|
46
51
|
MODE_DIAGNOSTICS = 1
|
@@ -57,8 +62,9 @@ module SGS
|
|
57
62
|
# Set up some useful defaults. We assume rudder goes from 0 to 200 as does
|
58
63
|
# the sail angle.
|
59
64
|
def initialize
|
65
|
+
serial_port = nil
|
60
66
|
#
|
61
|
-
|
67
|
+
# Configure the Mx + C values for sail and rudder
|
62
68
|
@rudder_m = 2.5
|
63
69
|
@rudder_c = 100.0
|
64
70
|
@sail_m = 2.0
|
@@ -68,6 +74,12 @@ module SGS
|
|
68
74
|
rudder = 0.0
|
69
75
|
sail = 0.0
|
70
76
|
#
|
77
|
+
# Set some defaults for the read-back parameters
|
78
|
+
@alarm_status = @wind = @compass = @actual_rudder = @actual_sail = 0
|
79
|
+
@otto_mode = 0
|
80
|
+
@otto_timestamp = 1000
|
81
|
+
@telemetry = Array.new(16)
|
82
|
+
#
|
71
83
|
# Set up some basic parameters for battery/solar readings
|
72
84
|
@bv_m = @bi_m = @bt_m = @sv_m = 1.0
|
73
85
|
@bv_c = @bi_c = @bt_c = @sv_c = 0.0
|
@@ -75,13 +87,170 @@ module SGS
|
|
75
87
|
end
|
76
88
|
|
77
89
|
#
|
78
|
-
# Main daemon function (called from executable)
|
90
|
+
# Main daemon function (called from executable). The job of
|
91
|
+
# this daemon is to accept commands from the Redis pub/sub
|
92
|
+
# stream and send them to the low-level device, recording the
|
93
|
+
# response and sending it back to the caller. Note that we need
|
94
|
+
# to do an initial sync with the device as it will ignore the
|
95
|
+
# usual serial console boot-up gumph awaiting our sync message.
|
79
96
|
def self.daemon
|
80
|
-
|
81
|
-
|
97
|
+
puts "Low-level (Otto) communication subsystem starting up..."
|
98
|
+
otto = new
|
99
|
+
config = SGS::Config.load
|
100
|
+
otto.serial_port = SerialPort.new config.otto_device, config.otto_speed
|
101
|
+
otto.serial_port.read_timeout = 10000
|
102
|
+
#
|
103
|
+
# Start by getting a sync message from Otto.
|
104
|
+
otto.synchronize()
|
105
|
+
#
|
106
|
+
# Run the communications service with Otto. Two threads are used, one for
|
107
|
+
# reading and one for writing. Don't let the command stack get too big.
|
108
|
+
t1 = Thread.new { otto.reader_thread }
|
109
|
+
t2 = Thread.new { otto.writer_thread }
|
110
|
+
t1.join
|
111
|
+
t2.join
|
112
|
+
end
|
113
|
+
|
114
|
+
#
|
115
|
+
# Synchronize with the low-level board by sending CQ messages until
|
116
|
+
# they respond.
|
117
|
+
def synchronize
|
118
|
+
index = 0
|
119
|
+
backoffs = [1, 1, 1, 1, 2, 2, 3, 5, 10, 10, 20, 30, 60]
|
120
|
+
puts "Attempting to synchronize with Otto..."
|
121
|
+
while true do
|
122
|
+
begin
|
123
|
+
@serial_port.puts "@@CQ!"
|
124
|
+
resp = read_data
|
125
|
+
break if resp =~ /^\+CQOK/ or resp =~ /^\+OK/
|
126
|
+
sleep backoffs[index]
|
127
|
+
index += 1 if index < (backoffs.count - 1)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
puts "Synchronization complete!"
|
131
|
+
end
|
132
|
+
|
133
|
+
#
|
134
|
+
# Thread to read status messages from Otto and handle them
|
135
|
+
def reader_thread
|
136
|
+
puts "Starting OTTO reader thread..."
|
137
|
+
while true
|
138
|
+
data = read_data
|
139
|
+
next if data.nil? or data.length == 0
|
140
|
+
case data[0]
|
141
|
+
when '$'
|
142
|
+
#
|
143
|
+
# Status message (every second)
|
144
|
+
parse_status(data[1..])
|
145
|
+
when '@'
|
146
|
+
#
|
147
|
+
# Otto elapsed time (every four seconds)
|
148
|
+
parse_tstamp(data[1..])
|
149
|
+
when '!'
|
150
|
+
#
|
151
|
+
# Otto mode state (every four seconds)
|
152
|
+
parse_mode(data[1..])
|
153
|
+
when '>'
|
154
|
+
#
|
155
|
+
# Telemetry data (every two seconds)
|
156
|
+
parse_telemetry(data[1..])
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
#
|
162
|
+
# Thread to write commands direct to Otto.
|
163
|
+
def writer_thread
|
164
|
+
puts "Starting OTTO writer thread..."
|
165
|
+
#
|
166
|
+
# Now listen for Redis PUB/SUB requests and act on each one.
|
167
|
+
while true
|
168
|
+
channel, request = SGS::RedisBase.redis.brpop("otto")
|
169
|
+
request = MessagePack.unpack(request)
|
170
|
+
puts "Req:[#{request.inspect}]"
|
171
|
+
cmd = {
|
172
|
+
id: request['id'],
|
173
|
+
args: request['params'].unshift(request['method'])
|
174
|
+
}
|
175
|
+
puts "CMD:#{cmd.inspect}"
|
176
|
+
#
|
177
|
+
# Don't let the command stack get too big.
|
178
|
+
while @command_stack.length > 5
|
179
|
+
sleep 5
|
180
|
+
end
|
181
|
+
|
182
|
+
puts "> Sending command: #{str}"
|
183
|
+
@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)
|
82
192
|
end
|
83
193
|
end
|
84
194
|
|
195
|
+
#
|
196
|
+
# Read data from the serial port
|
197
|
+
def read_data
|
198
|
+
begin
|
199
|
+
data = @serial_port.readline.chomp
|
200
|
+
rescue EOFError => error
|
201
|
+
puts "Otto Read Timeout!"
|
202
|
+
data = nil
|
203
|
+
end
|
204
|
+
data
|
205
|
+
end
|
206
|
+
|
207
|
+
#
|
208
|
+
# Parse a status message from Otto. In the form:
|
209
|
+
# 0001:C000:0000
|
210
|
+
def parse_status(status)
|
211
|
+
puts "Parse status: #{status}"
|
212
|
+
args = status.split /:/
|
213
|
+
@alarm_status = args[0].to_i(16)
|
214
|
+
wc = args[1].to_i(16)
|
215
|
+
rs = args[2].to_i(16)
|
216
|
+
@wind = (wc >> 8) & 0xff
|
217
|
+
@compass = (wc & 0xff)
|
218
|
+
@actual_rudder = (rs >> 8) & 0xff
|
219
|
+
@actual_sail = (rs & 0xff)
|
220
|
+
p self
|
221
|
+
self.save_and_publish
|
222
|
+
end
|
223
|
+
|
224
|
+
#
|
225
|
+
# Parse a timestamp message from Otto. In the form: "000FE2" 24 bits
|
226
|
+
# representing the elapsed seconds since Otto restarted.
|
227
|
+
def parse_tstamp(tstamp)
|
228
|
+
puts "Parse timestamp: #{tstamp}"
|
229
|
+
newval = tstamp.to_i(16)
|
230
|
+
if newval < @otto_timestamp
|
231
|
+
puts "ALARM! Otto rebooted (or something)..."
|
232
|
+
end
|
233
|
+
@otto_timestamp = newval
|
234
|
+
end
|
235
|
+
|
236
|
+
#
|
237
|
+
# Parse a mode state message from Otto. In the form: "00". An eight bit
|
238
|
+
# quantity.
|
239
|
+
def parse_mode(mode)
|
240
|
+
puts "Parse Otto Mode State: #{mode}"
|
241
|
+
@otto_mode = mode.to_i(16)
|
242
|
+
end
|
243
|
+
|
244
|
+
#
|
245
|
+
# Parse a telemetry message from Otto. In the form: "7327" where the first
|
246
|
+
# character is the channel (0->9) and the remaining 12 bits are the value.
|
247
|
+
def parse_telemetry(telemetry)
|
248
|
+
puts "Parse Otto Telemetry Data: #{telemetry}"
|
249
|
+
data = telemetry.to_i(16)
|
250
|
+
chan = (data >> 12) & 0xf
|
251
|
+
@telemetry[chan] = data & 0xff
|
252
|
+
end
|
253
|
+
|
85
254
|
#
|
86
255
|
# Set the required rudder angle. Input values range from +/- 40.0 degrees
|
87
256
|
def rudder=(val)
|
data/lib/sgs/report.rb
CHANGED
@@ -32,6 +32,7 @@
|
|
32
32
|
#
|
33
33
|
# ABSTRACT
|
34
34
|
#
|
35
|
+
require 'serialport'
|
35
36
|
|
36
37
|
##
|
37
38
|
# Routines for handling sailboat navigation and route planning.
|
@@ -41,6 +42,10 @@ module SGS
|
|
41
42
|
#
|
42
43
|
# Main daemon function (called from executable)
|
43
44
|
def self.daemon
|
45
|
+
puts "Reporting subsystem starting up..."
|
46
|
+
config = SGS::Config.load
|
47
|
+
sp = SerialPort.new config.comm_device, config.comm_speed
|
48
|
+
sp.read_timeout = 10000
|
44
49
|
loop do
|
45
50
|
sleep 300
|
46
51
|
end
|
data/lib/sgs/version.rb
CHANGED
data/lib/sgslib.rb
CHANGED
@@ -31,13 +31,10 @@
|
|
31
31
|
# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
32
32
|
#
|
33
33
|
# ABSTRACT
|
34
|
-
#
|
34
|
+
# Include all of the various components.
|
35
35
|
|
36
36
|
##
|
37
37
|
#
|
38
|
-
require 'date'
|
39
|
-
require 'logger'
|
40
|
-
|
41
38
|
require "sgs/version"
|
42
39
|
require 'sgs/redis_base'
|
43
40
|
require 'sgs/config'
|
data/sgslib.gemspec
CHANGED
@@ -40,8 +40,10 @@ Gem::Specification.new do |spec|
|
|
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 "
|
43
|
+
spec.add_runtime_dependency "redis", "~> 4.7"
|
44
|
+
spec.add_runtime_dependency "serialport", "~> 1.3"
|
44
45
|
spec.add_runtime_dependency "msgpack", "~> 1.3"
|
45
|
-
|
46
|
-
spec.
|
46
|
+
spec.add_runtime_dependency "json"
|
47
|
+
spec.add_runtime_dependency "securerandom"
|
48
|
+
spec.add_runtime_dependency "yaml"
|
47
49
|
end
|
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.5.
|
4
|
+
version: 1.5.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-01-
|
11
|
+
date: 2023-01-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -53,21 +53,21 @@ dependencies:
|
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '3.0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: redis
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
61
|
+
version: '4.7'
|
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: '4.7'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
70
|
+
name: serialport
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - "~>"
|
@@ -81,19 +81,61 @@ dependencies:
|
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '1.3'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
84
|
+
name: msgpack
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: '
|
89
|
+
version: '1.3'
|
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: '
|
96
|
+
version: '1.3'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: json
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: securerandom
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :runtime
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: yaml
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :runtime
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
97
139
|
description: Sailboat Guidance System - an autonomous navigation and control system
|
98
140
|
for robotic sailboats.
|
99
141
|
email:
|
@@ -164,7 +206,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
164
206
|
- !ruby/object:Gem::Version
|
165
207
|
version: '0'
|
166
208
|
requirements: []
|
167
|
-
rubygems_version: 3.
|
209
|
+
rubygems_version: 3.1.6
|
168
210
|
signing_key:
|
169
211
|
specification_version: 4
|
170
212
|
summary: Sailboat Guidance System
|