sgslib 1.7.1 → 1.8.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/sgs/alarm.rb +34 -34
- data/lib/sgs/bearing.rb +1 -1
- data/lib/sgs/diagnostics.rb +1 -1
- data/lib/sgs/gps.rb +7 -2
- data/lib/sgs/location.rb +3 -3
- data/lib/sgs/mission.rb +9 -6
- data/lib/sgs/navigate.rb +52 -26
- data/lib/sgs/nmea.rb +1 -1
- data/lib/sgs/otto.rb +24 -9
- data/lib/sgs/redis_base.rb +2 -2
- data/lib/sgs/report.rb +1 -1
- data/lib/sgs/version.rb +1 -1
- data/lib/sgs/waypoint.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5b772fccd0d24dd037a52734c72ef29a5203f5e32bbad85a47b4d8b16985c507
|
4
|
+
data.tar.gz: f717f8defef045a95408bbe34217bb8bf60f6ae802e5ddf95d4ff08dc223b8ff
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 739c91c93129d8da5e9271d10d9debe893746c10601fa206efa734498d6cc991ebcf0da3b9462d0f1a0a99eaf054e2ffa5e1b984832445b161b39026fcab8396
|
7
|
+
data.tar.gz: f546060ce3000f7d1c65ca079095863431bcd7b9ed2b2f997a30ac238cdfb8acfb28e1ca2822d586b9eab5058e711528619ab7f171daa60e4f304d1ed4d8197d
|
data/lib/sgs/alarm.rb
CHANGED
@@ -46,25 +46,25 @@ module SGS
|
|
46
46
|
|
47
47
|
#
|
48
48
|
# Alarms generated by Otto.
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
49
|
+
OTTO_RESTART = 0
|
50
|
+
MISSION_SWITCH = 1
|
51
|
+
RUDDER_FAULT = 2
|
52
|
+
SAIL_FAULT = 3
|
53
|
+
BATTERY_FAULT = 4
|
54
|
+
SOLAR_FAULT = 5
|
55
|
+
COMPASS_FAULT = 6
|
56
|
+
ACCEL_FAULT = 7
|
57
|
+
WDI_FAULT = 8
|
58
|
+
MOTHER_UNRESP = 9
|
59
|
+
RESERVED1 = 10
|
60
|
+
RESERVED2 = 11
|
61
|
+
RESERVED3 = 12
|
62
|
+
RESERVED4 = 13
|
63
|
+
RESERVED5 = 14
|
64
|
+
RESERVED6 = 15
|
65
65
|
#
|
66
66
|
# Alarms generated by Mother.
|
67
|
-
|
67
|
+
OTTO_FAULT = 16
|
68
68
|
MISSION_COMMENCE = 17
|
69
69
|
MISSION_COMPLETE = 18
|
70
70
|
MISSION_ABORT = 19
|
@@ -73,23 +73,23 @@ module SGS
|
|
73
73
|
INSIDE_FENCE = 22
|
74
74
|
|
75
75
|
ALARM_NAMES = [
|
76
|
+
"OTTO Restarted Unexpectedly",
|
76
77
|
"Mission Activation Switch",
|
77
|
-
"Rudder
|
78
|
-
"Sail
|
79
|
-
"Battery
|
80
|
-
"
|
81
|
-
"
|
82
|
-
"
|
83
|
-
"
|
84
|
-
"
|
85
|
-
"
|
86
|
-
"
|
87
|
-
"
|
88
|
-
"
|
89
|
-
"
|
90
|
-
"
|
91
|
-
"
|
92
|
-
"OTTO Restarted",
|
78
|
+
"Fault in Rudder Control System",
|
79
|
+
"Fault in Sail Control System",
|
80
|
+
"Battery Failure",
|
81
|
+
"Failure in Solar Array",
|
82
|
+
"Fault in Electronic Compass",
|
83
|
+
"Fault in Accelerometer",
|
84
|
+
"Fault in Wind Direction Indicator",
|
85
|
+
"Mother is Unresponsive",
|
86
|
+
"** Reserved 1 **",
|
87
|
+
"** Reserved 2 **",
|
88
|
+
"** Reserved 3 **",
|
89
|
+
"** Reserved 4 **",
|
90
|
+
"** Reserved 5 **",
|
91
|
+
"** Reserved 6 **",
|
92
|
+
"Fault with OTTO Communications",
|
93
93
|
"Mission has commenced",
|
94
94
|
"Mission is completed",
|
95
95
|
"*** MISSION ABORT ***",
|
@@ -108,7 +108,7 @@ module SGS
|
|
108
108
|
#
|
109
109
|
# Main daemon function (called from executable)
|
110
110
|
def self.daemon
|
111
|
-
puts "Alarm daemon starting up
|
111
|
+
puts "Alarm daemon starting up. VERSION: #{SGS::VERSION}"
|
112
112
|
otto = RPCClient.new(:otto)
|
113
113
|
loop do
|
114
114
|
#puts "Check for any alarms..."
|
data/lib/sgs/bearing.rb
CHANGED
@@ -113,7 +113,7 @@ module SGS
|
|
113
113
|
# This code was derived from formulae on the Movable Type site:
|
114
114
|
# http://www.movable-type.co.uk/scripts/latlong.html
|
115
115
|
#
|
116
|
-
# var d = Math.acos(Math.sin(lat1)*Math.sin(lat2) +
|
116
|
+
# var d = Math.acos(Math.sin(lat1)*Math.sin(lat2) +
|
117
117
|
# Math.cos(lat1)*Math.cos(lat2) *
|
118
118
|
# Math.cos(lon2-lon1)) * R;
|
119
119
|
# var y = Math.sin(dLon) * Math.cos(lat2);
|
data/lib/sgs/diagnostics.rb
CHANGED
data/lib/sgs/gps.rb
CHANGED
@@ -53,17 +53,22 @@ module SGS
|
|
53
53
|
#
|
54
54
|
# Main daemon function (called from executable)
|
55
55
|
def self.daemon
|
56
|
-
puts "GPS reader starting up
|
56
|
+
puts "GPS reader starting up. Version #{SGS::VERSION}"
|
57
57
|
config = Config.load
|
58
58
|
|
59
59
|
sp = SerialPort.new config.gps_device, config.gps_speed
|
60
60
|
sp.read_timeout = 10000
|
61
61
|
|
62
62
|
loop do
|
63
|
-
|
63
|
+
line = sp.readline
|
64
|
+
nmea = NMEA.parse line
|
64
65
|
if nmea.is_gprmc?
|
65
66
|
gps = nmea.parse_gprmc
|
66
67
|
p gps
|
68
|
+
if gps.cmg < 0.0
|
69
|
+
puts "CMG ERROR?!? #{gps.cmg}"
|
70
|
+
p line
|
71
|
+
end
|
67
72
|
gps.save_and_publish if gps and gps.valid?
|
68
73
|
end
|
69
74
|
end
|
data/lib/sgs/location.rb
CHANGED
@@ -75,9 +75,9 @@ module SGS
|
|
75
75
|
# This code was derived from formulae on the Movable Type site:
|
76
76
|
# http://www.movable-type.co.uk/scripts/latlong.html
|
77
77
|
#
|
78
|
-
# var lat2 = Math.asin( Math.sin(lat1)*Math.cos(d/R) +
|
78
|
+
# var lat2 = Math.asin( Math.sin(lat1)*Math.cos(d/R) +
|
79
79
|
# Math.cos(lat1)*Math.sin(d/R)*Math.cos(angle) );
|
80
|
-
# var lon2 = lon1 + Math.atan2(Math.sin(angle)*Math.sin(d/R)*Math.cos(lat1),
|
80
|
+
# var lon2 = lon1 + Math.atan2(Math.sin(angle)*Math.sin(d/R)*Math.cos(lat1),
|
81
81
|
# Math.cos(d/R)-Math.sin(lat1)*Math.sin(lat2));
|
82
82
|
def +(bearing)
|
83
83
|
loc = Location.new
|
@@ -144,7 +144,7 @@ module SGS
|
|
144
144
|
#
|
145
145
|
# Is this location valid?
|
146
146
|
def valid?
|
147
|
-
|
147
|
+
!@latitude.nil? and !@longitude.nil?
|
148
148
|
end
|
149
149
|
|
150
150
|
#
|
data/lib/sgs/mission.rb
CHANGED
@@ -69,7 +69,7 @@ module SGS
|
|
69
69
|
#
|
70
70
|
# Main daemon function (called from executable)
|
71
71
|
def self.daemon
|
72
|
-
puts "Mission management system starting up
|
72
|
+
puts "Mission management system starting up. Version #{SGS::VERSION}"
|
73
73
|
#
|
74
74
|
# Load the mission data from Redis and augment it with the
|
75
75
|
# contents of the mission file.
|
@@ -87,14 +87,14 @@ module SGS
|
|
87
87
|
# a compass course), and set the Otto register accordingly.
|
88
88
|
# Repeat until we run out of waypoints.
|
89
89
|
GPS.subscribe do |count|
|
90
|
-
puts "Mission received new GPS count: #{count}"
|
91
|
-
|
92
|
-
if new_course.nil?
|
90
|
+
puts "\n***** Mission received new GPS count: #{count} *****"
|
91
|
+
if nav.navigate
|
93
92
|
mission.status.completed!
|
94
93
|
break
|
95
94
|
end
|
96
95
|
mission.status.save
|
97
|
-
compass = Bearing.rtox(
|
96
|
+
compass = Bearing.rtox(nav.course.heading)
|
97
|
+
puts "Proposed compass course: #{compass}xd"
|
98
98
|
otto.set_register(Otto::COMPASS_HEADING_REGISTER, compass)
|
99
99
|
end
|
100
100
|
else
|
@@ -166,7 +166,10 @@ module SGS
|
|
166
166
|
hash["attractors"] << waypt.to_hash
|
167
167
|
end
|
168
168
|
hash["repellors"] = []
|
169
|
-
|
169
|
+
@repellors.each do |waypt|
|
170
|
+
hash["repellors"] << waypt.to_hash
|
171
|
+
end
|
172
|
+
return hash
|
170
173
|
end
|
171
174
|
end
|
172
175
|
end
|
data/lib/sgs/navigate.rb
CHANGED
@@ -49,16 +49,20 @@
|
|
49
49
|
#
|
50
50
|
module SGS
|
51
51
|
class Navigate
|
52
|
+
attr_reader :course, :gps, :otto, :waypoint
|
53
|
+
|
52
54
|
#
|
53
55
|
# Initialize the navigational parameters
|
54
56
|
def initialize(mission)
|
55
57
|
@mission = mission
|
58
|
+
@course = nil
|
56
59
|
@swing = 45
|
57
60
|
end
|
58
61
|
|
59
62
|
#
|
60
63
|
# Compute the best heading based on our current position and the position
|
61
|
-
# of the current attractor. This is where the heavy-lifting happens
|
64
|
+
# of the current attractor. This is where the heavy-lifting happens.
|
65
|
+
# Returns TRUE if we're done.
|
62
66
|
def navigate
|
63
67
|
if @mission.status.current_waypoint == -1
|
64
68
|
@mission.status.current_waypoint = 0
|
@@ -66,35 +70,29 @@ module SGS
|
|
66
70
|
end
|
67
71
|
set_waypoint
|
68
72
|
puts "Attempting to navigate to #{@waypoint}..."
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
puts "GPS: #{@gps}"
|
73
|
-
return unless @gps.valid?
|
74
|
-
#
|
75
|
-
# Pull the latest Otto data...
|
76
|
-
@otto = Otto.load
|
77
|
-
puts "OTTO:"
|
78
|
-
p @otto
|
79
|
-
puts "Compass: #{@otto.compass}"
|
80
|
-
puts "AWA: #{@otto.awa}"
|
81
|
-
puts "Wind: #{@otto.wind}"
|
82
|
-
#
|
83
|
-
# Update our local copy of the course based on what Otto says.
|
84
|
-
puts "Course:"
|
85
|
-
@course = Course.new
|
86
|
-
@course.heading = @otto.compass
|
87
|
-
@course.awa = @otto.awa
|
88
|
-
@course.compute_wind
|
89
|
-
#
|
90
|
-
# Compute a new course from the parameter set
|
91
|
-
compute_new_course
|
73
|
+
pull_gps_data
|
74
|
+
pull_otto_data
|
75
|
+
return compute_new_course
|
92
76
|
end
|
93
77
|
|
94
78
|
#
|
95
79
|
# Compute a new course based on our position and other information.
|
96
80
|
def compute_new_course
|
81
|
+
#
|
82
|
+
# Update our local copy of the course based on what Otto says.
|
97
83
|
puts "Compute new course..."
|
84
|
+
unless @course
|
85
|
+
#
|
86
|
+
# First time through, the current course is whichever way the boat
|
87
|
+
# is pointing.
|
88
|
+
@course = Course.new
|
89
|
+
@course.heading = @otto.compass
|
90
|
+
end
|
91
|
+
#
|
92
|
+
# Really it's the AWA we're interested in, not the boat heading.
|
93
|
+
@course.awa = @otto.awa
|
94
|
+
@course.compute_wind
|
95
|
+
p @course
|
98
96
|
#
|
99
97
|
# First off, compute distance and bearing from our current location
|
100
98
|
# to every attractor and repellor. We only look at forward attractors,
|
@@ -107,7 +105,7 @@ module SGS
|
|
107
105
|
while active? and reached?
|
108
106
|
next_waypoint!
|
109
107
|
end
|
110
|
-
return
|
108
|
+
return true unless active?
|
111
109
|
puts "Angle to next waypoint: #{@waypoint.bearing.angle_d}d"
|
112
110
|
puts "Adjusted distance to waypoint is #{@waypoint.distance}"
|
113
111
|
#
|
@@ -142,10 +140,13 @@ module SGS
|
|
142
140
|
best_course = new_course
|
143
141
|
end
|
144
142
|
end
|
143
|
+
puts "Best course: AWA: #{best_course.awa_d} degrees, Course: #{best_course.heading_d} degrees, Speed: #{best_course.speed} knots"
|
144
|
+
p best_course
|
145
145
|
if best_course.tack != @course.tack
|
146
146
|
puts "TACKING!!!!"
|
147
147
|
end
|
148
|
-
best_course
|
148
|
+
@course = best_course
|
149
|
+
return false
|
149
150
|
end
|
150
151
|
|
151
152
|
#
|
@@ -253,6 +254,31 @@ module SGS
|
|
253
254
|
dist
|
254
255
|
end
|
255
256
|
|
257
|
+
#
|
258
|
+
# Pull the latest GPS data. Failure is not an option.
|
259
|
+
def pull_gps_data
|
260
|
+
loop do
|
261
|
+
@gps = GPS.load
|
262
|
+
puts "GPS: #{@gps}"
|
263
|
+
break if @gps.valid?
|
264
|
+
puts "Retrying GPS..."
|
265
|
+
sleep 1
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
#
|
270
|
+
# Pull the latest Otto data.
|
271
|
+
def pull_otto_data
|
272
|
+
#
|
273
|
+
# Pull the latest Otto data...
|
274
|
+
@otto = Otto.load
|
275
|
+
puts "OTTO:"
|
276
|
+
p @otto
|
277
|
+
puts "Compass: #{@otto.compass}"
|
278
|
+
puts "AWA: #{@otto.awa}"
|
279
|
+
puts "Wind: #{@otto.wind}"
|
280
|
+
end
|
281
|
+
|
256
282
|
#
|
257
283
|
# Navigate a course up to a windward mark which is one nautical mile
|
258
284
|
# upwind of the start position. From there, navigate downwind to the
|
data/lib/sgs/nmea.rb
CHANGED
data/lib/sgs/otto.rb
CHANGED
@@ -53,6 +53,14 @@ module SGS
|
|
53
53
|
attr_reader :actual_rudder, :actual_sail
|
54
54
|
attr_reader :otto_mode, :otto_timestamp, :telemetry
|
55
55
|
|
56
|
+
MISSION_SWITCH = 1
|
57
|
+
RUDDER_FAULT = 2
|
58
|
+
SAIL_FAULT = 3
|
59
|
+
BATTERY_FAULT = 4
|
60
|
+
SOLAR_FAULT = 5
|
61
|
+
COMPASS_FAULT = 6
|
62
|
+
ACCEL_FAULT = 7
|
63
|
+
WDI_FAULT = 8
|
56
64
|
#
|
57
65
|
# Updates to Otto are done by setting an 8bit register value, as below.
|
58
66
|
ALARM_CLEAR_REGISTER = 0
|
@@ -112,10 +120,13 @@ module SGS
|
|
112
120
|
|
113
121
|
#
|
114
122
|
# Set up some useful defaults. We assume rudder goes from 0 to 255 as does
|
115
|
-
# the sail angle.
|
123
|
+
# the sail angle.
|
116
124
|
def initialize
|
117
125
|
serial_port = nil
|
118
126
|
#
|
127
|
+
# Keep a local copy of the register set to avoid duplication.
|
128
|
+
@registers = Array.new(MAX_REGISTER)
|
129
|
+
#
|
119
130
|
# Set some defaults for the read-back parameters
|
120
131
|
# The following five parameters are reported back by Otto with a status
|
121
132
|
# message, and are read-only. @alarm_status is 16 bits while the other
|
@@ -148,7 +159,7 @@ module SGS
|
|
148
159
|
# to do an initial sync with the device as it will ignore the
|
149
160
|
# usual serial console boot-up gumph awaiting our sync message.
|
150
161
|
def self.daemon
|
151
|
-
puts "Low-level (Otto) communication subsystem starting up
|
162
|
+
puts "Low-level (Otto) communication subsystem starting up. Version #{SGS::VERSION}"
|
152
163
|
otto = new
|
153
164
|
config = Config.load
|
154
165
|
otto.serial_port = SerialPort.new config.otto_device, config.otto_speed
|
@@ -250,13 +261,17 @@ module SGS
|
|
250
261
|
request = MessagePack.unpack(request)
|
251
262
|
puts "Req:[#{request.inspect}]"
|
252
263
|
params = request['params']
|
253
|
-
next if request['method'] != "set_local_register"
|
254
264
|
puts "PARAMS: #{params}"
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
265
|
+
case request['method']
|
266
|
+
when "set_local_register"
|
267
|
+
reg, value = params
|
268
|
+
if @registers[reg] != value
|
269
|
+
cmd = "R%d=%X\r\n" % [reg, value]
|
270
|
+
puts "Command: #{cmd}"
|
271
|
+
@serial_port.write cmd
|
272
|
+
@registers[reg] = value
|
273
|
+
end
|
274
|
+
end
|
260
275
|
end
|
261
276
|
end
|
262
277
|
|
@@ -294,7 +309,7 @@ module SGS
|
|
294
309
|
# representing the elapsed seconds since Otto restarted.
|
295
310
|
def parse_tstamp(tstamp)
|
296
311
|
newval = tstamp.to_i(16)
|
297
|
-
if newval < @otto_timestamp
|
312
|
+
if @otto_timestamp.nil? or newval < @otto_timestamp
|
298
313
|
puts "ALARM! Otto rebooted (or something)..."
|
299
314
|
end
|
300
315
|
@otto_timestamp = newval
|
data/lib/sgs/redis_base.rb
CHANGED
@@ -96,7 +96,7 @@ 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
|
99
|
+
lval[idx] = redis_read_var var, idx_val.class, :idx => idx
|
100
100
|
end
|
101
101
|
elsif lval.kind_of? Location
|
102
102
|
#
|
@@ -206,7 +206,7 @@ module SGS
|
|
206
206
|
case
|
207
207
|
when klass == Time
|
208
208
|
redis_val = Time.at(redis_val.to_f).gmtime
|
209
|
-
when klass ==
|
209
|
+
when klass == Integer
|
210
210
|
redis_val = redis_val.to_i
|
211
211
|
when klass == Float
|
212
212
|
redis_val = redis_val.to_f
|
data/lib/sgs/report.rb
CHANGED
@@ -42,7 +42,7 @@ module SGS
|
|
42
42
|
#
|
43
43
|
# Main daemon function (called from executable)
|
44
44
|
def self.daemon
|
45
|
-
puts "Reporting subsystem starting up
|
45
|
+
puts "Reporting subsystem starting up. Version #{SGS::VERSION}"
|
46
46
|
config = Config.load
|
47
47
|
sp = SerialPort.new config.comm_device, config.comm_speed
|
48
48
|
sp.read_timeout = 10000
|
data/lib/sgs/version.rb
CHANGED
data/lib/sgs/waypoint.rb
CHANGED
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.8.5
|
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-10-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -204,7 +204,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
204
204
|
- !ruby/object:Gem::Version
|
205
205
|
version: '0'
|
206
206
|
requirements: []
|
207
|
-
rubygems_version: 3.
|
207
|
+
rubygems_version: 3.3.5
|
208
208
|
signing_key:
|
209
209
|
specification_version: 4
|
210
210
|
summary: Sailboat Guidance System
|