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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2f89d5eb3a36569a8fb2d9e6c17a2eebd17e92d8
4
- data.tar.gz: ec1b2d028705b04ae55f8eeaa5dfb91c4352347f
3
+ metadata.gz: a5bfdb6916c2a3d0cd8dc924b5633e2de3bdbdff
4
+ data.tar.gz: 77c42e8e23f91fa3be7aea5c59b3521ff6e5b9bb
5
5
  SHA512:
6
- metadata.gz: 80bde0b4804b76b9be1d79d8c3c2537767a1fc35027bf52811d1324fc4a407d645412ab441675049e2dcf9bdaac14382c5f39fb2520f71e9469dbb4dafe533e9
7
- data.tar.gz: 330df98c125cfb917f81da99d26dcdc9b25a506e5ffe57ad0c55bc6aad08d035bc2fa6050a377be3f02fe1df58b0d3a1f6e8d587883c5e5753aaba56165244e2
6
+ metadata.gz: f0a9cefb0fcac10f6295cfc990e9bbaed5c419b19a7ec88c4171bff272628e53753db0af6e456c4bf28b29657d3d38302b04557dc6f14ba65202e34519dd25bb
7
+ data.tar.gz: fc58f050f88a77cc0a15cc83f77cad71b1e7610b8ac58f9f679ca956399c96cdf7a02fadf089ad02c5f27b6c93018d2f3f373bb245be6072fb8503b38f86b658
@@ -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
@@ -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
- @at_commander.config("general:navdata_demo", "TRUE")
114
+ config("general:navdata_demo", "TRUE")
114
115
  end
115
116
 
116
117
  def front_camera
117
- @at_commander.config("video:video_channel", "2")
118
+ config("video:video_channel", "2")
118
119
  end
119
120
 
120
121
  def bottom_camera
121
- @at_commander.config("video:video_channel", "1")
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
@@ -7,13 +7,15 @@ module Argus
7
7
  attr_reader :controller, :nav
8
8
 
9
9
  def initialize(opts={})
10
- @host = opts[:remote_host] || '192.168.1.1'
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: @host, port: port)
13
- @at = Argus::ATCommander.new(@sender)
14
- @controller = Argus::Controller.new(@at)
15
- if opts.fetch(:enable_nav_monitor, true)
16
- @nav = NavMonitor.new(@controller, @host)
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
@@ -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?
@@ -26,7 +26,7 @@ module Argus
26
26
  @local_host = opts[:local_host] || '0.0.0.0'
27
27
  @port = opts[:port] || 5554
28
28
  @socket_class = opts[:UDPSocket] || UDPSocket
29
- start_timer
29
+ start_timer unless opts[:disable_timer]
30
30
  end
31
31
 
32
32
  def start
@@ -2,7 +2,7 @@ module Argus
2
2
  module Version # :nodoc: all
3
3
  NUMBERS = [
4
4
  MAJOR = 0,
5
- MINOR = 3,
5
+ MINOR = 4,
6
6
  BUILD = 0,
7
7
  ]
8
8
  end
@@ -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
@@ -77,6 +77,9 @@ describe Argus::ATCommander do
77
77
  Then { sender.should have_received(:send_packet) }
78
78
  end
79
79
 
80
-
80
+ describe "setting the interval" do
81
+ Given { cmdr.interval = 1.0 }
82
+ Then { cmdr.interval == 1.0 }
83
+ end
81
84
 
82
85
  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
- context "navigating commands" do
18
+ describe "controller commands" do
19
19
  Invariant { result.should == controller }
20
20
 
21
- context "when taking off" do
22
- When(:result) { controller.take_off }
23
- Then { at.should have_received(:ref).with(ref_bits(9)) }
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
@@ -12,6 +12,7 @@ module Argus
12
12
 
13
13
  Then { nav_data.sequence_number == 173064 }
14
14
  Then { nav_data.vision_flag == 0 }
15
+ Then { nav_data.raw == raw_nav_bytes }
15
16
 
16
17
  describe "sequence number" do
17
18
  Given(:seq_num) { 1234 }
@@ -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" +
@@ -56,6 +56,7 @@ module Argus
56
56
  Then { d0.y == 20 }
57
57
  Then { d0.width == 30 }
58
58
  Then { d0.height == 40 }
59
+ Then { d0.distance == 50 }
59
60
  Then { d0.orientation_angle == 60.0 }
60
61
  Then { d0.camera_source == 70 }
61
62
  end
@@ -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
@@ -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.3.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-03 00:00:00.000000000 Z
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:
@@ -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