argus 0.3.0 → 0.4.0
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/argus/at_commander.rb +1 -4
- data/lib/argus/controller.rb +5 -3
- data/lib/argus/drone.rb +8 -6
- data/lib/argus/nav_monitor.rb +5 -4
- data/lib/argus/nav_streamer.rb +1 -1
- data/lib/argus/version.rb +1 -1
- data/lib/argus/video_data.rb +15 -0
- data/lib/argus/video_data_envelope.rb +55 -0
- data/lib/argus/video_streamer.rb +23 -0
- data/spec/argus/at_commander_spec.rb +4 -1
- data/spec/argus/cfields_spec.rb +39 -0
- data/spec/argus/controller_spec.rb +145 -127
- data/spec/argus/drone_spec.rb +53 -0
- data/spec/argus/nav_data_spec.rb +1 -0
- data/spec/argus/nav_monitor_spec.rb +65 -0
- data/spec/argus/nav_option_demo_spec.rb +0 -4
- data/spec/argus/nav_option_vision_detect_spec.rb +1 -0
- data/spec/argus/nav_streamer_spec.rb +6 -1
- data/spec/argus/video_data_envelope_spec.rb +26 -0
- data/spec/argus/video_data_spec.rb +17 -0
- data/spec/argus/video_streamer_spec.rb +21 -0
- data/spec/spec_helper.rb +5 -1
- metadata +13 -5
- data/lib/argus/pave_parser.rb +0 -39
- data/lib/argus/tcp_video_streamer.rb +0 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a5bfdb6916c2a3d0cd8dc924b5633e2de3bdbdff
|
4
|
+
data.tar.gz: 77c42e8e23f91fa3be7aea5c59b3521ff6e5b9bb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f0a9cefb0fcac10f6295cfc990e9bbaed5c419b19a7ec88c4171bff272628e53753db0af6e456c4bf28b29657d3d38302b04557dc6f14ba65202e34519dd25bb
|
7
|
+
data.tar.gz: fc58f050f88a77cc0a15cc83f77cad71b1e7610b8ac58f9f679ca956399c96cdf7a02fadf089ad02c5f27b6c93018d2f3f373bb245be6072fb8503b38f86b658
|
data/lib/argus/at_commander.rb
CHANGED
@@ -3,6 +3,7 @@ require 'thread'
|
|
3
3
|
module Argus
|
4
4
|
class ATCommander
|
5
5
|
attr_reader :timestamps
|
6
|
+
attr_accessor :interval
|
6
7
|
|
7
8
|
def initialize(sender)
|
8
9
|
@sender = sender
|
@@ -44,10 +45,6 @@ module Argus
|
|
44
45
|
@thread.join if @thread
|
45
46
|
end
|
46
47
|
|
47
|
-
def interval=(new_interval)
|
48
|
-
@mutex.synchronize do @interval = new_interval end
|
49
|
-
end
|
50
|
-
|
51
48
|
def ref(data)
|
52
49
|
@mutex.synchronize do @ref_data = data end
|
53
50
|
end
|
data/lib/argus/controller.rb
CHANGED
@@ -107,22 +107,24 @@ module Argus
|
|
107
107
|
|
108
108
|
def config(key, value)
|
109
109
|
@at_commander.config(key, value)
|
110
|
+
self
|
110
111
|
end
|
111
112
|
|
112
113
|
def demo_mode
|
113
|
-
|
114
|
+
config("general:navdata_demo", "TRUE")
|
114
115
|
end
|
115
116
|
|
116
117
|
def front_camera
|
117
|
-
|
118
|
+
config("video:video_channel", "2")
|
118
119
|
end
|
119
120
|
|
120
121
|
def bottom_camera
|
121
|
-
|
122
|
+
config("video:video_channel", "1")
|
122
123
|
end
|
123
124
|
|
124
125
|
def reset_watchdog
|
125
126
|
@at_commander.comwdg
|
127
|
+
self
|
126
128
|
end
|
127
129
|
|
128
130
|
def ack_control_mode
|
data/lib/argus/drone.rb
CHANGED
@@ -7,13 +7,15 @@ module Argus
|
|
7
7
|
attr_reader :controller, :nav
|
8
8
|
|
9
9
|
def initialize(opts={})
|
10
|
-
|
10
|
+
host = opts[:remote_host] || '192.168.1.1'
|
11
11
|
port = opts[:post] || '5556'
|
12
|
-
@sender = opts[:sender] || Argus::UdpSender.new(socket: opts[:socket], remote_host:
|
13
|
-
@at = Argus::ATCommander.new(@sender)
|
14
|
-
@controller = Argus::Controller.new(@at)
|
15
|
-
if opts
|
16
|
-
@nav =
|
12
|
+
@sender = opts[:sender] || Argus::UdpSender.new(socket: opts[:socket], remote_host: host, port: port)
|
13
|
+
@at = opts[:commander] || Argus::ATCommander.new(@sender)
|
14
|
+
@controller = opts[:controller] || Argus::Controller.new(@at)
|
15
|
+
if opts[:nav_monitor]
|
16
|
+
@nav = opts[:nav_monitor]
|
17
|
+
elsif opts.fetch(:enable_nav_monitor, true)
|
18
|
+
@nav = NavMonitor.new(@controller, host)
|
17
19
|
else
|
18
20
|
@nav = NullNavMonitor.new
|
19
21
|
end
|
data/lib/argus/nav_monitor.rb
CHANGED
@@ -3,9 +3,9 @@ module Argus
|
|
3
3
|
class NavMonitor
|
4
4
|
attr_reader :streamer
|
5
5
|
|
6
|
-
def initialize(controller, remote_host)
|
6
|
+
def initialize(controller, remote_host, opts={})
|
7
7
|
@controller = controller
|
8
|
-
@streamer = NavStreamer.new(remote_host: remote_host)
|
8
|
+
@streamer = opts.fetch(:streamer) { NavStreamer.new(remote_host: remote_host) }
|
9
9
|
@callbacks = []
|
10
10
|
@mutex = Mutex.new
|
11
11
|
@nav_data = nil
|
@@ -28,6 +28,7 @@ module Argus
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def join
|
31
|
+
stop
|
31
32
|
@nav_thread.join
|
32
33
|
end
|
33
34
|
|
@@ -46,8 +47,6 @@ module Argus
|
|
46
47
|
@mutex.synchronize { @nav_options[tag] }
|
47
48
|
end
|
48
49
|
|
49
|
-
private
|
50
|
-
|
51
50
|
def update_nav_data(data)
|
52
51
|
@mutex.synchronize do
|
53
52
|
update_internal_nav_data(data)
|
@@ -60,6 +59,8 @@ module Argus
|
|
60
59
|
$stdout.flush
|
61
60
|
end
|
62
61
|
|
62
|
+
private
|
63
|
+
|
63
64
|
def update_internal_nav_data(data)
|
64
65
|
@nav_data = data
|
65
66
|
if @nav_data.bootstrap?
|
data/lib/argus/nav_streamer.rb
CHANGED
data/lib/argus/version.rb
CHANGED
@@ -0,0 +1,15 @@
|
|
1
|
+
module Argus
|
2
|
+
class VideoData
|
3
|
+
attr_reader :socket, :envelope, :frame
|
4
|
+
|
5
|
+
def initialize(socket)
|
6
|
+
@socket = socket
|
7
|
+
@envelope = VideoDataEnvelope.new(@socket)
|
8
|
+
@frame = parse_frame
|
9
|
+
end
|
10
|
+
|
11
|
+
def parse_frame
|
12
|
+
socket.read(envelope.payload_size) if envelope
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module Argus
|
2
|
+
class VideoDataEnvelope
|
3
|
+
attr_reader :socket
|
4
|
+
|
5
|
+
def initialize(socket)
|
6
|
+
@socket = socket
|
7
|
+
parse
|
8
|
+
end
|
9
|
+
|
10
|
+
def parse
|
11
|
+
data(:signature, 4, "A*")
|
12
|
+
data(:version, 1, "C")
|
13
|
+
data(:video_codec, 1, "C")
|
14
|
+
data(:header_size, 2, "v")
|
15
|
+
data(:payload_size, 4, "V")
|
16
|
+
data(:encoded_stream_width, 2, "v")
|
17
|
+
data(:encoded_stream_height, 2, "v")
|
18
|
+
data(:display_width, 2, "v")
|
19
|
+
data(:display_height, 2, "v")
|
20
|
+
data(:frame_number, 4, "V")
|
21
|
+
data(:timestamp, 4, "V")
|
22
|
+
data(:total_chunks, 1, "C")
|
23
|
+
data(:chunk_index, 1, "C")
|
24
|
+
data(:frame_type, 1, "C")
|
25
|
+
data(:control, 1, "C")
|
26
|
+
data(:stream_byte_position_lw, 4, "V")
|
27
|
+
data(:stream_byte_position_uw, 4, "V")
|
28
|
+
data(:stream_id, 2, "v")
|
29
|
+
data(:total_slices, 1, "C")
|
30
|
+
data(:slice_index, 1, "C")
|
31
|
+
data(:header1_size, 1, "C")
|
32
|
+
data(:header2_size, 1, "C")
|
33
|
+
data(:reserved_2, 2, "H*")
|
34
|
+
data(:advertised_size, 4, "V")
|
35
|
+
data(:reserved_12, 12, "H*")
|
36
|
+
socket.read(4) # TODO: look at why just throwing this data away
|
37
|
+
end
|
38
|
+
|
39
|
+
def data(name, size, format)
|
40
|
+
define_data(name, get_data(size, format))
|
41
|
+
end
|
42
|
+
|
43
|
+
def get_data(size, format)
|
44
|
+
socket.read(size).unpack(format).first
|
45
|
+
end
|
46
|
+
|
47
|
+
def define_data(name, value)
|
48
|
+
ivar = "@#{name}".to_sym
|
49
|
+
instance_variable_set(ivar, value)
|
50
|
+
self.class.send(:define_method, name) do
|
51
|
+
instance_variable_get(ivar)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'socket'
|
2
|
+
|
3
|
+
module Argus
|
4
|
+
class VideoStreamer
|
5
|
+
attr_reader :tcp_socket, :host, :port
|
6
|
+
|
7
|
+
def initialize(opts={})
|
8
|
+
@host = opts[:host] || '192.168.1.1'
|
9
|
+
@port = opts[:port] || 5555
|
10
|
+
@tcp_socket = opts[:socket] || TCPSocket.new(@host, @port)
|
11
|
+
end
|
12
|
+
|
13
|
+
def start(udp_socket=nil)
|
14
|
+
@udp_socket = udp_socket || UDPSocket.new
|
15
|
+
@udp_socket.send("\x01\x00\x00\x00", 0, host, port)
|
16
|
+
@udp_socket.close
|
17
|
+
end
|
18
|
+
|
19
|
+
def receive_data
|
20
|
+
VideoData.new(tcp_socket)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module CFieldsSpec
|
4
|
+
describe Argus::CFields do
|
5
|
+
class Example < Argus::NavOption
|
6
|
+
include Argus::CFields
|
7
|
+
uint32_t :u32
|
8
|
+
uint16_t :u16
|
9
|
+
float32_t :f32
|
10
|
+
int32_t :i32
|
11
|
+
matrix33_t :m33
|
12
|
+
vector31_t :v31
|
13
|
+
|
14
|
+
def self.tag
|
15
|
+
14263
|
16
|
+
end
|
17
|
+
|
18
|
+
Argus::NavOption.register(self)
|
19
|
+
end
|
20
|
+
|
21
|
+
Given(:raw_data) {
|
22
|
+
[
|
23
|
+
Bytes.int16(Example.tag),
|
24
|
+
Bytes.int16(10),
|
25
|
+
Bytes.int32(1),
|
26
|
+
Bytes.int16(2),
|
27
|
+
Bytes.float32(3.4),
|
28
|
+
].flatten.pack("C*")
|
29
|
+
}
|
30
|
+
|
31
|
+
When(:data) { Example.new(raw_data) }
|
32
|
+
|
33
|
+
Then { data.size == 10 }
|
34
|
+
Then { data.tag == Example.tag }
|
35
|
+
Then { data.u32 == 1 }
|
36
|
+
Then { data.u16 == 2 }
|
37
|
+
Then { data.f32 == about(3.4).percent(1) }
|
38
|
+
end
|
39
|
+
end
|
@@ -15,135 +15,153 @@ describe Argus::Controller do
|
|
15
15
|
Given(:at) { flexmock(:on, Argus::ATCommander) }
|
16
16
|
Given(:controller) { Argus::Controller.new(at) }
|
17
17
|
|
18
|
-
|
18
|
+
describe "controller commands" do
|
19
19
|
Invariant { result.should == controller }
|
20
20
|
|
21
|
-
context "
|
22
|
-
|
23
|
-
|
21
|
+
context "navigating commands" do
|
22
|
+
context "when taking off" do
|
23
|
+
When(:result) { controller.take_off }
|
24
|
+
Then { at.should have_received(:ref).with(ref_bits(9)) }
|
25
|
+
end
|
26
|
+
|
27
|
+
context "when landing" do
|
28
|
+
When(:result) { controller.land }
|
29
|
+
Then { at.should have_received(:ref).with(ref_bits).twice }
|
30
|
+
end
|
31
|
+
|
32
|
+
context "when emergency" do
|
33
|
+
Given { controller.take_off }
|
34
|
+
When(:result) { controller.emergency }
|
35
|
+
Then { at.should have_received(:ref).with(ref_bits(8)) }
|
36
|
+
end
|
37
|
+
|
38
|
+
context "when taking off after an emergency" do
|
39
|
+
Given { controller.emergency }
|
40
|
+
When(:result) { controller.take_off }
|
41
|
+
Then { at.should have_received(:ref).with(ref_bits(9)) }
|
42
|
+
end
|
43
|
+
|
44
|
+
context "when hovering" do
|
45
|
+
When(:result) { controller.hover }
|
46
|
+
Then { at.should have_received(:pcmd).with("0,0,0,0,0") }
|
47
|
+
end
|
48
|
+
|
49
|
+
context "when moving forward" do
|
50
|
+
When(:result) { controller.forward(0.80) }
|
51
|
+
Then { at.should have_received(:pcmd).with("1,0,-1085485875,0,0") }
|
52
|
+
end
|
53
|
+
|
54
|
+
context "when moving backward" do
|
55
|
+
When(:result) { controller.backward(0.80) }
|
56
|
+
Then { at.should have_received(:pcmd).with("1,0,1061997773,0,0") }
|
57
|
+
end
|
58
|
+
|
59
|
+
context "when moving to the left" do
|
60
|
+
When(:result) { controller.left(0.80) }
|
61
|
+
Then { at.should have_received(:pcmd).with("1,-1085485875,0,0,0") }
|
62
|
+
end
|
63
|
+
|
64
|
+
context "when moving to the right" do
|
65
|
+
When(:result) { controller.right(0.80) }
|
66
|
+
Then { at.should have_received(:pcmd).with("1,1061997773,0,0,0") }
|
67
|
+
end
|
68
|
+
|
69
|
+
context "when moving up" do
|
70
|
+
When(:result) { controller.up(0.80) }
|
71
|
+
Then { at.should have_received(:pcmd).with("1,0,0,1061997773,0") }
|
72
|
+
end
|
73
|
+
|
74
|
+
context "when moving down" do
|
75
|
+
When(:result) { controller.down(0.80) }
|
76
|
+
Then { at.should have_received(:pcmd).with("1,0,0,-1085485875,0") }
|
77
|
+
end
|
78
|
+
|
79
|
+
context "when turning left" do
|
80
|
+
When(:result) { controller.turn_left(0.80) }
|
81
|
+
Then { at.should have_received(:pcmd).with("1,0,0,0,-1085485875") }
|
82
|
+
end
|
83
|
+
|
84
|
+
context "when turning right" do
|
85
|
+
When(:result) { controller.turn_right(0.80) }
|
86
|
+
Then { at.should have_received(:pcmd).with("1,0,0,0,1061997773") }
|
87
|
+
end
|
88
|
+
|
89
|
+
context "when executing several directions" do
|
90
|
+
When(:result) {
|
91
|
+
controller.forward(1.0).left(0.5).up(0.2).turn_left(0.8)
|
92
|
+
}
|
93
|
+
Then { at.should have_received(:pcmd).with("1,-1090519040,-1082130432,1045220557,-1085485875") }
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
describe "config command" do
|
98
|
+
context "when setting with numeric sequence" do
|
99
|
+
When(:result) { controller.led(3, 2.0, 4) }
|
100
|
+
Then {
|
101
|
+
at.should have_received(:config)
|
102
|
+
.with("leds:leds_anim", "3,1073741824,4")
|
103
|
+
}
|
104
|
+
end
|
105
|
+
|
106
|
+
context "when setting with symbolic sequence" do
|
107
|
+
When(:result) { controller.led(:blink_orange, 2.0, 4) }
|
108
|
+
Then {
|
109
|
+
at.should have_received(:config)
|
110
|
+
.with("leds:leds_anim", "3,1073741824,4")
|
111
|
+
}
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
describe "enabled detection command" do
|
116
|
+
context "when setting all parameters" do
|
117
|
+
Given(:enemy) { 2 }
|
118
|
+
Given(:type) { 11 }
|
119
|
+
Given(:select) { 33 }
|
120
|
+
|
121
|
+
When(:result) { controller.enable_detection(enemy, type, select) }
|
122
|
+
|
123
|
+
Then { at.should have_received(:config).with("detect:enemy_colors", enemy.to_s) }
|
124
|
+
Then { at.should have_received(:config).with("detect:detect_type", type.to_s) }
|
125
|
+
Then { at.should have_received(:config).with("detect:detections_select_h", select.to_s) }
|
126
|
+
end
|
127
|
+
|
128
|
+
context "when setting with only enemy" do
|
129
|
+
Given(:enemy) { 2 }
|
130
|
+
Given(:type) { 10 }
|
131
|
+
Given(:select) { 32 }
|
132
|
+
|
133
|
+
When(:result) { controller.enable_detection(enemy) }
|
134
|
+
|
135
|
+
Then { at.should have_received(:config).with("detect:enemy_colors", enemy.to_s) }
|
136
|
+
Then { at.should have_received(:config).with("detect:detect_type", type.to_s) }
|
137
|
+
Then { at.should have_received(:config).with("detect:detections_select_h", select.to_s) }
|
138
|
+
end
|
139
|
+
|
140
|
+
context "when doing demo mode" do
|
141
|
+
When(:result) { controller.demo_mode }
|
142
|
+
Then { at.should have_received(:config).with("general:navdata_demo", "TRUE") }
|
143
|
+
end
|
144
|
+
|
145
|
+
context "when selecting the forward camera" do
|
146
|
+
When(:result) { controller.front_camera }
|
147
|
+
Then { at.should have_received(:config).with("video:video_channel", "2") }
|
148
|
+
end
|
149
|
+
|
150
|
+
context "when selecting the bottom camera" do
|
151
|
+
When(:result) { controller.bottom_camera }
|
152
|
+
Then { at.should have_received(:config).with("video:video_channel", "1") }
|
153
|
+
end
|
154
|
+
|
155
|
+
end
|
156
|
+
|
157
|
+
describe "reset watchdog command" do
|
158
|
+
When(:result) { controller.reset_watchdog}
|
159
|
+
Then { at.should have_received(:comwdg).with() }
|
160
|
+
end
|
161
|
+
|
162
|
+
describe "ack control mode command" do
|
163
|
+
When(:result) { controller.ack_control_mode }
|
164
|
+
Then { at.should have_received(:ctrl).with(5) }
|
24
165
|
end
|
25
|
-
|
26
|
-
context "when landing" do
|
27
|
-
When(:result) { controller.land }
|
28
|
-
Then { at.should have_received(:ref).with(ref_bits).twice }
|
29
|
-
end
|
30
|
-
|
31
|
-
context "when emergency" do
|
32
|
-
Given { controller.take_off }
|
33
|
-
When(:result) { controller.emergency }
|
34
|
-
Then { at.should have_received(:ref).with(ref_bits(8)) }
|
35
|
-
end
|
36
|
-
|
37
|
-
context "when taking off after an emergency" do
|
38
|
-
Given { controller.emergency }
|
39
|
-
When(:result) { controller.take_off }
|
40
|
-
Then { at.should have_received(:ref).with(ref_bits(9)) }
|
41
|
-
end
|
42
|
-
|
43
|
-
context "when hovering" do
|
44
|
-
When(:result) { controller.hover }
|
45
|
-
Then { at.should have_received(:pcmd).with("0,0,0,0,0") }
|
46
|
-
end
|
47
|
-
|
48
|
-
context "when moving forward" do
|
49
|
-
When(:result) { controller.forward(0.80) }
|
50
|
-
Then { at.should have_received(:pcmd).with("1,0,-1085485875,0,0") }
|
51
|
-
end
|
52
|
-
|
53
|
-
context "when moving backward" do
|
54
|
-
When(:result) { controller.backward(0.80) }
|
55
|
-
Then { at.should have_received(:pcmd).with("1,0,1061997773,0,0") }
|
56
|
-
end
|
57
|
-
|
58
|
-
context "when moving to the left" do
|
59
|
-
When(:result) { controller.left(0.80) }
|
60
|
-
Then { at.should have_received(:pcmd).with("1,-1085485875,0,0,0") }
|
61
|
-
end
|
62
|
-
|
63
|
-
context "when moving to the right" do
|
64
|
-
When(:result) { controller.right(0.80) }
|
65
|
-
Then { at.should have_received(:pcmd).with("1,1061997773,0,0,0") }
|
66
|
-
end
|
67
|
-
|
68
|
-
context "when moving up" do
|
69
|
-
When(:result) { controller.up(0.80) }
|
70
|
-
Then { at.should have_received(:pcmd).with("1,0,0,1061997773,0") }
|
71
|
-
end
|
72
|
-
|
73
|
-
context "when moving down" do
|
74
|
-
When(:result) { controller.down(0.80) }
|
75
|
-
Then { at.should have_received(:pcmd).with("1,0,0,-1085485875,0") }
|
76
|
-
end
|
77
|
-
|
78
|
-
context "when turning left" do
|
79
|
-
When(:result) { controller.turn_left(0.80) }
|
80
|
-
Then { at.should have_received(:pcmd).with("1,0,0,0,-1085485875") }
|
81
|
-
end
|
82
|
-
|
83
|
-
context "when turning right" do
|
84
|
-
When(:result) { controller.turn_right(0.80) }
|
85
|
-
Then { at.should have_received(:pcmd).with("1,0,0,0,1061997773") }
|
86
|
-
end
|
87
|
-
|
88
|
-
context "when executing several directions" do
|
89
|
-
When(:result) {
|
90
|
-
controller.forward(1.0).left(0.5).up(0.2).turn_left(0.8)
|
91
|
-
}
|
92
|
-
Then { at.should have_received(:pcmd).with("1,-1090519040,-1082130432,1045220557,-1085485875") }
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
describe "led command" do
|
97
|
-
Invariant { result.should == controller }
|
98
|
-
|
99
|
-
context "when setting with numeric sequence" do
|
100
|
-
When(:result) { controller.led(3, 2.0, 4) }
|
101
|
-
Then {
|
102
|
-
at.should have_received(:config)
|
103
|
-
.with("leds:leds_anim", "3,1073741824,4")
|
104
|
-
}
|
105
|
-
end
|
106
|
-
|
107
|
-
context "when setting with symbolic sequence" do
|
108
|
-
When(:result) { controller.led(:blink_orange, 2.0, 4) }
|
109
|
-
Then {
|
110
|
-
at.should have_received(:config)
|
111
|
-
.with("leds:leds_anim", "3,1073741824,4")
|
112
|
-
}
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
describe "enabled detection command" do
|
117
|
-
Invariant { result.should == controller }
|
118
|
-
|
119
|
-
context "when setting all parameters" do
|
120
|
-
Given(:enemy) { 2 }
|
121
|
-
Given(:type) { 11 }
|
122
|
-
Given(:select) { 33 }
|
123
|
-
|
124
|
-
When(:result) { controller.enable_detection(enemy, type, select) }
|
125
|
-
|
126
|
-
Then { at.should have_received(:config).with("detect:enemy_colors", enemy.to_s) }
|
127
|
-
Then { at.should have_received(:config).with("detect:detect_type", type.to_s) }
|
128
|
-
Then { at.should have_received(:config).with("detect:detections_select_h", select.to_s) }
|
129
|
-
end
|
130
|
-
|
131
|
-
context "when setting with only enemy" do
|
132
|
-
Given(:enemy) { 2 }
|
133
|
-
Given(:type) { 10 }
|
134
|
-
Given(:select) { 32 }
|
135
|
-
|
136
|
-
When(:result) { controller.enable_detection(enemy) }
|
137
|
-
|
138
|
-
Then { at.should have_received(:config).with("detect:enemy_colors", enemy.to_s) }
|
139
|
-
Then { at.should have_received(:config).with("detect:detect_type", type.to_s) }
|
140
|
-
Then { at.should have_received(:config).with("detect:detections_select_h", select.to_s) }
|
141
|
-
end
|
142
|
-
end
|
143
|
-
|
144
|
-
describe "ack controll command" do
|
145
|
-
Invariant { result.should == controller }
|
146
|
-
When(:result) { controller.ack_control_mode }
|
147
|
-
Then { at.should have_received(:ctrl).with(5) }
|
148
166
|
end
|
149
167
|
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'argus'
|
3
|
+
|
4
|
+
describe Argus::Drone do
|
5
|
+
Given(:controller) { flexmock("controller", :on, Argus::Controller) }
|
6
|
+
Given(:commander) { flexmock("commander", :on, Argus::ATCommander) }
|
7
|
+
Given(:nav_monitor) { flexmock("navmonitor", :on, Argus::NavMonitor) }
|
8
|
+
Given(:drone) {
|
9
|
+
Argus::Drone.new(
|
10
|
+
nav_monitor: nav_monitor,
|
11
|
+
commander: commander,
|
12
|
+
controller: controller)
|
13
|
+
}
|
14
|
+
|
15
|
+
Then { drone.commander == commander }
|
16
|
+
|
17
|
+
context "when starting the drone" do
|
18
|
+
When { drone.start }
|
19
|
+
Then { commander.should have_received(:start).once }
|
20
|
+
Then { nav_monitor.should have_received(:start).once }
|
21
|
+
|
22
|
+
context "and then stopped" do
|
23
|
+
When { drone.stop }
|
24
|
+
Then { controller.should have_received(:land).once }
|
25
|
+
Then { commander.should have_received(:stop).once }
|
26
|
+
Then { commander.should have_received(:join).once }
|
27
|
+
Then { nav_monitor.should have_received(:stop).once }
|
28
|
+
Then { nav_monitor.should have_received(:join).once }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "setting nav callbacks" do
|
33
|
+
When { drone.nav_callback(:a) }
|
34
|
+
Then { nav_monitor.should have_received(:callback).with(:a).once }
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "flight controls" do
|
38
|
+
When { drone.take_off }
|
39
|
+
Then { controller.should have_received(:take_off).once }
|
40
|
+
end
|
41
|
+
|
42
|
+
context "when created normally" do
|
43
|
+
Given { flexmock(Argus::NavMonitor).should_receive(:new => nil) }
|
44
|
+
When { Argus::Drone.new }
|
45
|
+
Then { Argus::NavMonitor.should have_received(:new).with(Argus::Controller, String).once }
|
46
|
+
end
|
47
|
+
|
48
|
+
context "when NavMonitor is disabled" do
|
49
|
+
Given { flexmock(Argus::NullNavMonitor).should_receive(:new => nil) }
|
50
|
+
When { Argus::Drone.new(enable_nav_monitor: false) }
|
51
|
+
Then { Argus::NullNavMonitor.should have_received(:new).with().once }
|
52
|
+
end
|
53
|
+
end
|
data/spec/argus/nav_data_spec.rb
CHANGED
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'thread'
|
3
|
+
|
4
|
+
describe Argus::NavMonitor do
|
5
|
+
Given(:streamer) { flexmock("streamer", :on, Argus::NavStreamer) }
|
6
|
+
Given(:controller) { flexmock("controller", :on, Argus::Controller) }
|
7
|
+
Given(:nav) {
|
8
|
+
Argus::NavMonitor.new(controller, "localhost", streamer: streamer)
|
9
|
+
}
|
10
|
+
|
11
|
+
context "when the monitor is started" do
|
12
|
+
after do nav.join end
|
13
|
+
When { nav.start; Thread.pass }
|
14
|
+
Then { streamer.should have_received(:start).once }
|
15
|
+
end
|
16
|
+
|
17
|
+
context "when data is received" do
|
18
|
+
Given(:bootstrap) { false }
|
19
|
+
Given(:ack) { false }
|
20
|
+
Given(:nav_options) { [ ] }
|
21
|
+
Given(:nav_data) {
|
22
|
+
flexmock("NavData",
|
23
|
+
:bootstrap? => bootstrap,
|
24
|
+
:control_command_ack? => ack,
|
25
|
+
:options => nav_options)
|
26
|
+
}
|
27
|
+
|
28
|
+
When {
|
29
|
+
capture_io { nav.update_nav_data(nav_data) }
|
30
|
+
}
|
31
|
+
|
32
|
+
context "when typical data is received" do
|
33
|
+
Then { nav.data == nav_data }
|
34
|
+
Then { controller.should have_received(:demo_mode).never }
|
35
|
+
Then { controller.should have_received(:ack_control_mode).never }
|
36
|
+
end
|
37
|
+
|
38
|
+
context "when the bootstrap flag is set" do
|
39
|
+
Given(:bootstrap) { true }
|
40
|
+
Then { controller.should have_received(:demo_mode).once }
|
41
|
+
end
|
42
|
+
|
43
|
+
context "when the control command ack is set" do
|
44
|
+
Given(:ack) { true }
|
45
|
+
Then { controller.should have_received(:ack_control_mode).once }
|
46
|
+
end
|
47
|
+
|
48
|
+
context "with nav option sections" do
|
49
|
+
Given(:opt) { flexmock("option", tag: 0) }
|
50
|
+
Given(:nav_options) { [ opt ] }
|
51
|
+
Then { nav.data == nav_data }
|
52
|
+
Then { nav.option(0) == opt }
|
53
|
+
end
|
54
|
+
|
55
|
+
context "with a callback" do
|
56
|
+
Given { nav.callback { |data| @cb_data = data } }
|
57
|
+
Then { @cb_data == nav_data }
|
58
|
+
end
|
59
|
+
|
60
|
+
context "with a callback with errors" do
|
61
|
+
Given { nav.callback { |data| fail "OUCH" } }
|
62
|
+
Then { captured_out =~ /OUCH/ }
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -3,10 +3,6 @@ require 'base64'
|
|
3
3
|
|
4
4
|
module Argus
|
5
5
|
describe NavOptionDemo do
|
6
|
-
def f(float)
|
7
|
-
FloatEncoding.encode_float(float)
|
8
|
-
end
|
9
|
-
|
10
6
|
# NOTE: This is a Base 64 encoded NavData packet recorded directly from the drone.
|
11
7
|
Given(:base64_data) {
|
12
8
|
"iHdmVdAEgA/5iwAAAAAAAAAAlAAAAAIAPAAAAADwREUAgCNFQFEiyAAAAABk" +
|
@@ -5,7 +5,7 @@ module Argus
|
|
5
5
|
Given(:remote_host) { '192.168.1.1' }
|
6
6
|
Given(:port) { 5554 }
|
7
7
|
Given(:socket) { flexmock("Socket", send: nil).should_ignore_missing }
|
8
|
-
Given(:streamer) { NavStreamer.new(remote_host: remote_host, UDPSocket: flexmock(new: socket)) }
|
8
|
+
Given(:streamer) { NavStreamer.new(remote_host: remote_host, UDPSocket: flexmock(new: socket, disabled_timer: true)) }
|
9
9
|
|
10
10
|
context "after starting" do
|
11
11
|
Given { streamer.start }
|
@@ -23,6 +23,11 @@ module Argus
|
|
23
23
|
When(:nav_data) { streamer.receive_data }
|
24
24
|
Then { nav_data.nil? }
|
25
25
|
end
|
26
|
+
|
27
|
+
context "when receiving and extra start event" do
|
28
|
+
Given { streamer.start }
|
29
|
+
Then { socket.should have_received(:close) }
|
30
|
+
end
|
26
31
|
end
|
27
32
|
|
28
33
|
describe "State Transitions" do
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Argus
|
4
|
+
describe VideoDataEnvelope do
|
5
|
+
Given(:unpacker) { flexmock("Unpacker", :unpack => values) }
|
6
|
+
Given(:socket) { flexmock("socket", :read => unpacker) }
|
7
|
+
Given(:video_data_envelope) { VideoDataEnvelope.new(socket) }
|
8
|
+
|
9
|
+
describe "version" do
|
10
|
+
When(:values) { flexmock("Values", :first => 3) }
|
11
|
+
Then { video_data_envelope.version == 3 }
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "frame_number" do
|
15
|
+
When(:values) { flexmock("Values", :first => 42) }
|
16
|
+
Then { video_data_envelope.frame_number == 42 }
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "payload_size" do
|
20
|
+
When(:values) { flexmock("Values", :first => 2048) }
|
21
|
+
Then { video_data_envelope.payload_size == 2048 }
|
22
|
+
end
|
23
|
+
|
24
|
+
# TODO: handle invalid envelope
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Argus
|
4
|
+
describe VideoData do
|
5
|
+
Given(:raw_header) { Bytes.make_video_envelope }
|
6
|
+
Given(:raw_video_bytes) { Bytes.make_video_data(raw_header) }
|
7
|
+
Given(:video_data) { VideoData.new(socket) }
|
8
|
+
|
9
|
+
describe "valid envelope" do
|
10
|
+
When(:socket) { StringIO.new(raw_header) }
|
11
|
+
Then {video_data.envelope.signature == "PaVE"}
|
12
|
+
end
|
13
|
+
|
14
|
+
# TODO: handle invalid envelope
|
15
|
+
# TODO: handle valid envelope but invalid frame
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Argus
|
4
|
+
describe VideoStreamer do
|
5
|
+
Given(:tcp_socket) { flexmock("TCPSocket", send: nil).should_ignore_missing }
|
6
|
+
Given(:streamer) { VideoStreamer.new(socket: tcp_socket) }
|
7
|
+
Given(:udp_socket) { flexmock("UDPSocket", send: nil).should_ignore_missing }
|
8
|
+
|
9
|
+
describe "starting the stream" do
|
10
|
+
When { streamer.start(udp_socket) }
|
11
|
+
Then { udp_socket.should have_received(:send) }
|
12
|
+
Then { udp_socket.should have_received(:close) }
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "receiving data" do
|
16
|
+
Given { streamer.start(udp_socket) }
|
17
|
+
When(:result) { streamer.receive_data }
|
18
|
+
Then { result.is_a?(VideoData) }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,10 +1,14 @@
|
|
1
1
|
#!/usr/bin/ruby -wKU
|
2
|
+
require 'simplecov'
|
3
|
+
SimpleCov.start do
|
4
|
+
add_filter "spec/"
|
5
|
+
end
|
2
6
|
|
3
7
|
require 'rspec/given'
|
4
8
|
require 'flexmock'
|
5
|
-
|
6
9
|
require 'argus'
|
7
10
|
require 'support/bytes'
|
11
|
+
require 'support/capture_io'
|
8
12
|
|
9
13
|
RSpec.configure do |config|
|
10
14
|
config.mock_with :flexmock
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: argus
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jim Weirich
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2013-09-
|
13
|
+
date: 2013-09-07 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rspec-given
|
@@ -58,17 +58,21 @@ files:
|
|
58
58
|
- lib/argus/nav_streamer.rb
|
59
59
|
- lib/argus/nav_tag.rb
|
60
60
|
- lib/argus/null_nav_monitor.rb
|
61
|
-
- lib/argus/pave_parser.rb
|
62
|
-
- lib/argus/tcp_video_streamer.rb
|
63
61
|
- lib/argus/time_queue.rb
|
64
62
|
- lib/argus/udp_sender.rb
|
65
63
|
- lib/argus/version.rb
|
64
|
+
- lib/argus/video_data.rb
|
65
|
+
- lib/argus/video_data_envelope.rb
|
66
|
+
- lib/argus/video_streamer.rb
|
66
67
|
- spec/spec_helper.rb
|
67
68
|
- spec/argus/at_commander_spec.rb
|
69
|
+
- spec/argus/cfields_spec.rb
|
68
70
|
- spec/argus/controller_spec.rb
|
71
|
+
- spec/argus/drone_spec.rb
|
69
72
|
- spec/argus/float_encoding_spec.rb
|
70
73
|
- spec/argus/led_animation_spec.rb
|
71
74
|
- spec/argus/nav_data_spec.rb
|
75
|
+
- spec/argus/nav_monitor_spec.rb
|
72
76
|
- spec/argus/nav_option_checksum_spec.rb
|
73
77
|
- spec/argus/nav_option_demo_spec.rb
|
74
78
|
- spec/argus/nav_option_spec.rb
|
@@ -78,9 +82,13 @@ files:
|
|
78
82
|
- spec/argus/null_nav_monitor_spec.rb
|
79
83
|
- spec/argus/time_queue_spec.rb
|
80
84
|
- spec/argus/udp_sender_spec.rb
|
85
|
+
- spec/argus/video_data_envelope_spec.rb
|
86
|
+
- spec/argus/video_data_spec.rb
|
87
|
+
- spec/argus/video_streamer_spec.rb
|
81
88
|
- MIT-LICENSE
|
82
89
|
homepage: http://github.com/jimweirich/argus
|
83
|
-
licenses:
|
90
|
+
licenses:
|
91
|
+
- MIT-LICENSE
|
84
92
|
metadata: {}
|
85
93
|
post_install_message:
|
86
94
|
rdoc_options:
|
data/lib/argus/pave_parser.rb
DELETED
@@ -1,39 +0,0 @@
|
|
1
|
-
module Argus
|
2
|
-
class PaVEParser
|
3
|
-
def initialize(tcp_video_streamer)
|
4
|
-
@tcp_video_streamer = tcp_video_streamer
|
5
|
-
end
|
6
|
-
|
7
|
-
def get_frame
|
8
|
-
frame = {
|
9
|
-
:signature=>(@tcp_video_streamer.read(4)).unpack("A*").first,
|
10
|
-
:version=>(@tcp_video_streamer.read(1)).unpack("C").first,
|
11
|
-
:video_codec=>(@tcp_video_streamer.read(1)).unpack("C").first,
|
12
|
-
:header_size=>(@tcp_video_streamer.read(2)).unpack("v").first,
|
13
|
-
:payload_size=>(@tcp_video_streamer.read(4)).unpack("V").first,
|
14
|
-
:encoded_stream_width=>(@tcp_video_streamer.read(2)).unpack("v").first,
|
15
|
-
:encoded_stream_height=>(@tcp_video_streamer.read(2)).unpack("v").first,
|
16
|
-
:display_width=>(@tcp_video_streamer.read(2)).unpack("v").first,
|
17
|
-
:display_height=>(@tcp_video_streamer.read(2)).unpack("v").first,
|
18
|
-
:frame_number=>(@tcp_video_streamer.read(4)).unpack("V").first,
|
19
|
-
:timestamp=>(@tcp_video_streamer.read(4)).unpack("V").first,
|
20
|
-
:total_chunks=>(@tcp_video_streamer.read(1)).unpack("C").first,
|
21
|
-
:chunk_index=>(@tcp_video_streamer.read(1)).unpack("C").first,
|
22
|
-
:frame_type=>(@tcp_video_streamer.read(1)).unpack("C").first,
|
23
|
-
:control=>(@tcp_video_streamer.read(1)).unpack("C").first,
|
24
|
-
:stream_byte_position_lw=>(@tcp_video_streamer.read(4)).unpack("V").first,
|
25
|
-
:stream_byte_position_uw=>(@tcp_video_streamer.read(4)).unpack("V").first,
|
26
|
-
:stream_id=>(@tcp_video_streamer.read(2)).unpack("v").first,
|
27
|
-
:total_slices=>(@tcp_video_streamer.read(1)).unpack("C").first,
|
28
|
-
:slice_index=>(@tcp_video_streamer.read(1)).unpack("C").first,
|
29
|
-
:header1_size=>(@tcp_video_streamer.read(1)).unpack("C").first,
|
30
|
-
:header2_size=>(@tcp_video_streamer.read(1)).unpack("C").first,
|
31
|
-
:reserved[2]=>(@tcp_video_streamer.read(2)).unpack("H*").first,
|
32
|
-
:advertised_size=>(@tcp_video_streamer.read(4)).unpack("V").first,
|
33
|
-
:reserved[12]=>(@tcp_video_streamer.read(12)).unpack("H*").first
|
34
|
-
}
|
35
|
-
@tcp_video_streamer.read(4)
|
36
|
-
return @tcp_video_streamer.read(frame[:payload_size])
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
@@ -1,20 +0,0 @@
|
|
1
|
-
require 'socket'
|
2
|
-
module Argus
|
3
|
-
class TcpVideoStreamer
|
4
|
-
def initialize(opts={})
|
5
|
-
@host = opts.fetch(:remote_host)
|
6
|
-
@port = opts.fetch(:port, 5555)
|
7
|
-
@tcp_socket = TCPSocket.new(@host, @port)
|
8
|
-
end
|
9
|
-
|
10
|
-
def start_stream(udp_socket=nil)
|
11
|
-
sock = udp_socket || UDPSocket.new
|
12
|
-
sock.send("\x01\x00\x00\x00", 0, @host, @port)
|
13
|
-
sock.close
|
14
|
-
end
|
15
|
-
|
16
|
-
def read(n)
|
17
|
-
@tcp_socket.read(n)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|