hybridgroup-argus 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/argus/at_commander.rb +24 -3
- data/lib/argus/cad_type.rb +22 -0
- data/lib/argus/cfields.rb +98 -0
- data/lib/argus/controller.rb +34 -5
- data/lib/argus/drone.rb +28 -1
- data/lib/argus/float_encoding.rb +13 -0
- data/lib/argus/led_animation.rb +48 -0
- data/lib/argus/nav_data.rb +66 -49
- data/lib/argus/nav_monitor.rb +78 -0
- data/lib/argus/nav_option.rb +29 -0
- data/lib/argus/nav_option_checksum.rb +20 -0
- data/lib/argus/nav_option_demo.rb +79 -0
- data/lib/argus/nav_option_unknown.rb +9 -0
- data/lib/argus/nav_option_vision_detect.rb +83 -0
- data/lib/argus/nav_streamer.rb +12 -4
- data/lib/argus/nav_tag.rb +35 -0
- 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/lib/argus.rb +5 -9
- data/spec/argus/controller_spec.rb +49 -0
- data/spec/argus/drone_spec.rb +24 -0
- data/spec/argus/float_encoding_spec.rb +12 -0
- data/spec/argus/led_animation_spec.rb +21 -0
- data/spec/argus/nav_data_spec.rb +147 -0
- data/spec/argus/nav_option_checksum_spec.rb +21 -0
- data/spec/argus/nav_option_demo_spec.rb +44 -0
- data/spec/argus/nav_option_spec.rb +32 -0
- data/spec/argus/nav_option_unknown_spec.rb +19 -0
- data/spec/argus/nav_option_vision_detect_spec.rb +65 -0
- data/spec/argus/nav_streamer_spec.rb +28 -0
- data/spec/argus/udp_sender_spec.rb +1 -1
- data/spec/argus/video_data_envelope_spec.rb +26 -0
- data/spec/argus/video_data_spec.rb +18 -0
- data/spec/argus/video_streamer_spec.rb +16 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/support/bytes.rb +48 -0
- metadata +36 -15
- data/lib/argus/pave_parser.rb +0 -39
- data/lib/argus/tcp_video_streamer.rb +0 -20
- data/lib/argus/udp_nav_streamer.rb +0 -24
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'argus/cfields'
|
2
|
+
require 'argus/float_encoding'
|
3
|
+
require 'argus/nav_option'
|
4
|
+
require 'argus/nav_tag'
|
5
|
+
|
6
|
+
module Argus
|
7
|
+
|
8
|
+
class NavOptionDemo < NavOption
|
9
|
+
include CFields
|
10
|
+
|
11
|
+
uint32_t :ctrl_state # Flying state (landed, flying,
|
12
|
+
alias :control_state :ctrl_state
|
13
|
+
# hovering, etc.) defined in
|
14
|
+
# CTRL_STATES enum.
|
15
|
+
uint32_t :vbat_flying_percentage # battery voltage filtered (mV)
|
16
|
+
alias :battery_level :vbat_flying_percentage
|
17
|
+
|
18
|
+
float32_t :theta # UAV's pitch in milli-degrees
|
19
|
+
float32_t :phi # UAV's roll in milli-degrees
|
20
|
+
float32_t :psi # UAV's yaw in milli-degrees
|
21
|
+
|
22
|
+
int32_t :altitude # UAV's altitude in centimeters
|
23
|
+
|
24
|
+
float32_t :vx # UAV's estimated linear velocity
|
25
|
+
float32_t :vy # UAV's estimated linear velocity
|
26
|
+
float32_t :vz # UAV's estimated linear velocity
|
27
|
+
|
28
|
+
uint32_t :num_frames # streamed frame index // Not
|
29
|
+
# used -> To integrate in video
|
30
|
+
# stage.
|
31
|
+
|
32
|
+
# Camera parameters compute by detection
|
33
|
+
matrix33_t :detection_camera_rot # Deprecated ! Don't use !
|
34
|
+
vector31_t :detection_camera_trans # Deprecated ! Don't use !
|
35
|
+
uint32_t :detection_tag_index # Deprecated ! Don't use !
|
36
|
+
|
37
|
+
uint32_t :detection_camera_type # Type of tag searched in detection
|
38
|
+
|
39
|
+
# Camera parameters compute by drone
|
40
|
+
matrix33_t :drone_camera_rot # Deprecated ! Don't use !
|
41
|
+
vector31_t :drone_camera_trans # Deprecated ! Don't use !
|
42
|
+
|
43
|
+
CONTROL_STATE_NAMES = [
|
44
|
+
:default,
|
45
|
+
:init,
|
46
|
+
:landed,
|
47
|
+
:flying,
|
48
|
+
:hovering,
|
49
|
+
:test,
|
50
|
+
:trans_takeoff,
|
51
|
+
:trans_gotofix,
|
52
|
+
:trans_landing,
|
53
|
+
:trans_looping,
|
54
|
+
]
|
55
|
+
|
56
|
+
def control_state_name
|
57
|
+
CONTROL_STATE_NAMES[ctrl_state]
|
58
|
+
end
|
59
|
+
|
60
|
+
def pitch
|
61
|
+
theta / 1000.0
|
62
|
+
end
|
63
|
+
|
64
|
+
def roll
|
65
|
+
phi / 1000.0
|
66
|
+
end
|
67
|
+
|
68
|
+
def yaw
|
69
|
+
psi / 1000.0
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.tag
|
73
|
+
NavTag::DEMO
|
74
|
+
end
|
75
|
+
|
76
|
+
NavOption.register(self)
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'argus/cfields'
|
2
|
+
require 'argus/nav_tag'
|
3
|
+
|
4
|
+
module Argus
|
5
|
+
|
6
|
+
class NavOptionVisionDetect < NavOption
|
7
|
+
include CFields
|
8
|
+
|
9
|
+
NB_NAVDATA_DETECTION_RESULTS = 4
|
10
|
+
|
11
|
+
uint32_t :nb_detected
|
12
|
+
alias :detected_count :nb_detected
|
13
|
+
uint32_t :type, NB_NAVDATA_DETECTION_RESULTS
|
14
|
+
uint32_t :xc, NB_NAVDATA_DETECTION_RESULTS
|
15
|
+
uint32_t :yc, NB_NAVDATA_DETECTION_RESULTS
|
16
|
+
uint32_t :width, NB_NAVDATA_DETECTION_RESULTS
|
17
|
+
uint32_t :height, NB_NAVDATA_DETECTION_RESULTS
|
18
|
+
uint32_t :dist, NB_NAVDATA_DETECTION_RESULTS
|
19
|
+
alias :distance :dist
|
20
|
+
float32_t :orientation_angle, NB_NAVDATA_DETECTION_RESULTS
|
21
|
+
matrix33_t :rotation, NB_NAVDATA_DETECTION_RESULTS
|
22
|
+
vector31_t :translation, NB_NAVDATA_DETECTION_RESULTS
|
23
|
+
uint32_t :camera_source, NB_NAVDATA_DETECTION_RESULTS
|
24
|
+
|
25
|
+
class Detection
|
26
|
+
def initialize(vision_detected, index)
|
27
|
+
@vision_detected = vision_detected
|
28
|
+
@index = index
|
29
|
+
end
|
30
|
+
|
31
|
+
def type
|
32
|
+
@vision_detected.type[@index]
|
33
|
+
end
|
34
|
+
|
35
|
+
def type_name
|
36
|
+
CadType::NAMES[type]
|
37
|
+
end
|
38
|
+
|
39
|
+
def x
|
40
|
+
@vision_detected.xc[@index]
|
41
|
+
end
|
42
|
+
|
43
|
+
def y
|
44
|
+
@vision_detected.yc[@index]
|
45
|
+
end
|
46
|
+
|
47
|
+
def width
|
48
|
+
@vision_detected.width[@index]
|
49
|
+
end
|
50
|
+
|
51
|
+
def height
|
52
|
+
@vision_detected.height[@index]
|
53
|
+
end
|
54
|
+
|
55
|
+
def distance
|
56
|
+
@vision_detected.distance[@index]
|
57
|
+
end
|
58
|
+
|
59
|
+
def orientation_angle
|
60
|
+
@vision_detected.orientation_angle[@index]
|
61
|
+
end
|
62
|
+
|
63
|
+
def camera_source
|
64
|
+
@vision_detected.camera_source[@index]
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def type_name
|
69
|
+
type.map { |t| CadType::NAMES[t] }
|
70
|
+
end
|
71
|
+
|
72
|
+
def detections
|
73
|
+
@detections ||= (0...detected_count).map { |i| Detection.new(self, i) }
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.tag
|
77
|
+
NavTag::VISION_DETECT
|
78
|
+
end
|
79
|
+
|
80
|
+
NavOption.register(self)
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
data/lib/argus/nav_streamer.rb
CHANGED
@@ -1,18 +1,26 @@
|
|
1
1
|
require 'socket'
|
2
2
|
|
3
3
|
module Argus
|
4
|
-
class NavStreamer
|
4
|
+
class NavStreamer
|
5
5
|
def initialize(socket=nil, host='192.168.1.1', port='5554')
|
6
|
+
# TODO: Why is the port a string?
|
6
7
|
@socket = socket || UDPSocket.new
|
7
|
-
@
|
8
|
+
@host = host
|
9
|
+
@port = port
|
10
|
+
@socket.bind("0.0.0.0", port)
|
8
11
|
end
|
9
12
|
|
10
13
|
def start
|
11
|
-
@
|
14
|
+
@socket.send("\x01\x00\x00\x00", 0, @host, @port)
|
12
15
|
end
|
13
16
|
|
14
17
|
def receive_data
|
15
|
-
@
|
18
|
+
data, from = @socket.recvfrom(1024)
|
19
|
+
if data.unpack("V").first == 0x55667788
|
20
|
+
NavData.new(data)
|
21
|
+
else
|
22
|
+
nil
|
23
|
+
end
|
16
24
|
end
|
17
25
|
end
|
18
26
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Argus
|
2
|
+
module NavTag
|
3
|
+
DEMO,
|
4
|
+
TIME,
|
5
|
+
RAW_MEASURES,
|
6
|
+
PHYS_MEASURES,
|
7
|
+
GYROS_OFFSETS,
|
8
|
+
EULER_ANGLES,
|
9
|
+
REFERENCES,
|
10
|
+
TRIMS,
|
11
|
+
RC_REFERENCES,
|
12
|
+
PWM,
|
13
|
+
ALTITUDE,
|
14
|
+
VISION_RAW,
|
15
|
+
VISION_OF,
|
16
|
+
VISION,
|
17
|
+
VISION_PERF,
|
18
|
+
TRACKERS_SEND,
|
19
|
+
VISION_DETECT,
|
20
|
+
WATCHDOG,
|
21
|
+
ADC_DATA_FRAME,
|
22
|
+
VIDEO_STREAM,
|
23
|
+
GAMES,
|
24
|
+
PRESSURE_RAW,
|
25
|
+
MAGNETO,
|
26
|
+
WIND,
|
27
|
+
KALMAN_PRESSURE,
|
28
|
+
HDVIDEO_STREAM,
|
29
|
+
WIFI = (0..100).to_a
|
30
|
+
|
31
|
+
CHECKSUM = 0xffff
|
32
|
+
UNKNOWN = 0xfffe # Not part of the AR Drone DSK, Only used in Argus
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
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(tcp_socket=nil, host='192.168.1.1', port=5555)
|
8
|
+
@tcp_socket = tcp_socket || TCPSocket.new(host, port)
|
9
|
+
@host = host
|
10
|
+
@port = 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
|
data/lib/argus.rb
CHANGED
@@ -1,9 +1,5 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
require
|
5
|
-
|
6
|
-
require 'argus/nav_streamer'
|
7
|
-
require 'argus/drone'
|
8
|
-
require 'argus/tcp_video_streamer'
|
9
|
-
require 'argus/pave_parser'
|
1
|
+
# Require all the top level files in argus/*.rb
|
2
|
+
|
3
|
+
Dir[File.dirname(__FILE__) + "/argus/*.rb"].sort.each do |pn|
|
4
|
+
require "argus/#{File.basename(pn, '.rb')}"
|
5
|
+
end
|
@@ -92,4 +92,53 @@ describe Argus::Controller do
|
|
92
92
|
Then { at.should have_received(:pcmd).with("1,-1090519040,-1082130432,1045220557,-1085485875") }
|
93
93
|
end
|
94
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
|
+
|
95
144
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Argus
|
4
|
+
describe Drone do
|
5
|
+
|
6
|
+
Given(:socket) { flexmock("Socket", send: nil).should_ignore_missing }
|
7
|
+
Given(:drone) { Drone.new(socket) }
|
8
|
+
|
9
|
+
describe "default navigation monitor enabled" do
|
10
|
+
Then { drone.enable_nav_monitor == false }
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "default navigation monitor enabled when started" do
|
14
|
+
When { drone.start }
|
15
|
+
Then { drone.enable_nav_monitor == true }
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "navigation monitor can be disabled when started" do
|
19
|
+
When { drone.start(false) }
|
20
|
+
Then { drone.enable_nav_monitor == false }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Argus
|
4
|
+
|
5
|
+
describe LedAnimation do
|
6
|
+
describe ".lookup_name" do
|
7
|
+
Then { LedAnimation.lookup_name(3) == :blink_orange }
|
8
|
+
end
|
9
|
+
|
10
|
+
describe ".lookup_value" do
|
11
|
+
Then { LedAnimation.lookup_value(:blink_orange) == 3 }
|
12
|
+
Then { LedAnimation.lookup_value("blink_orange") == 3 }
|
13
|
+
Then { LedAnimation.lookup_value(3) == 3 }
|
14
|
+
Then { LedAnimation.lookup_value("3") == 3 }
|
15
|
+
|
16
|
+
Then { LedAnimation.lookup_value(:unknown) == nil }
|
17
|
+
Then { LedAnimation.lookup_value("UNKNOWN") == nil }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Argus
|
4
|
+
describe NavData do
|
5
|
+
Given(:state_bits) { 0xcf8a0c94 }
|
6
|
+
Given(:seq_num) { 173064 }
|
7
|
+
Given(:vision_flag) { 0 }
|
8
|
+
Given(:raw_header) { Bytes.make_header(state_bits, seq_num, vision_flag) }
|
9
|
+
Given(:raw_nav_bytes) { Bytes.make_nav_data(raw_header) }
|
10
|
+
|
11
|
+
When(:nav_data) { NavData.new(raw_nav_bytes) }
|
12
|
+
|
13
|
+
Then { nav_data.sequence_number == 173064 }
|
14
|
+
Then { nav_data.vision_flag == 0 }
|
15
|
+
|
16
|
+
describe "sequence number" do
|
17
|
+
Given(:seq_num) { 1234 }
|
18
|
+
Then { nav_data.sequence_number == 1234 }
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "vision flag" do
|
22
|
+
Given(:vision_flag) { 1 }
|
23
|
+
Then { nav_data.vision_flag == 1 }
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "state queries" do
|
27
|
+
|
28
|
+
def bit(n)
|
29
|
+
0x00000001 << n
|
30
|
+
end
|
31
|
+
|
32
|
+
# Matcher for handling the mask testing for the state mask.
|
33
|
+
#
|
34
|
+
# Usage:
|
35
|
+
# bit(5).should be_the_mask_for(:method [, off_value, on_value])
|
36
|
+
#
|
37
|
+
# If off_value and on_value are not given, then false/true will
|
38
|
+
# be assumed.
|
39
|
+
#
|
40
|
+
matcher :be_the_mask_for do |method, off_result=false, on_result=true|
|
41
|
+
match do |mask|
|
42
|
+
@msg = "OK"
|
43
|
+
try_alternative(method, 0, off_result) &&
|
44
|
+
try_alternative(method, mask, on_result)
|
45
|
+
end
|
46
|
+
|
47
|
+
failure_message_for_should do |mask|
|
48
|
+
@msg
|
49
|
+
end
|
50
|
+
|
51
|
+
# Try one of the alternatives. Sending method to the navdata
|
52
|
+
# constructed with mask should return teh expected value.
|
53
|
+
def try_alternative(method, mask, expected)
|
54
|
+
raw = Bytes.make_nav_data(Bytes.make_header(mask, 1, 0))
|
55
|
+
nav_data = NavData.new(raw)
|
56
|
+
result = nav_data.send(method)
|
57
|
+
return true if result == expected
|
58
|
+
@msg = "expected mask of 0x#{'%08x' % mask} with #{method}\n" +
|
59
|
+
"to return: #{expected.inspect}\n" +
|
60
|
+
"got: #{result.inspect}"
|
61
|
+
false
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
Then { bit(0).should be_the_mask_for(:flying?) }
|
66
|
+
Then { bit(1).should be_the_mask_for(:video_enabled?) }
|
67
|
+
Then { bit(2).should be_the_mask_for(:vision_enabled?) }
|
68
|
+
Then { bit(3).should be_the_mask_for(:control_algorithm, :euler, :angular_speed) }
|
69
|
+
|
70
|
+
Then { bit(4).should be_the_mask_for(:altitude_control_algorithm_active?) }
|
71
|
+
Then { bit(5).should be_the_mask_for(:start_button_pressed?) }
|
72
|
+
Then { bit(6).should be_the_mask_for(:control_command_ack?) }
|
73
|
+
Then { bit(7).should be_the_mask_for(:camera_ready?) }
|
74
|
+
|
75
|
+
Then { bit(8).should be_the_mask_for(:travelling_enabled?) }
|
76
|
+
Then { bit(9).should be_the_mask_for(:usb_ready?) }
|
77
|
+
Then { bit(10).should be_the_mask_for(:mode, :all, :demo) }
|
78
|
+
Then { bit(11).should be_the_mask_for(:bootstrap?) }
|
79
|
+
|
80
|
+
Then { bit(12).should be_the_mask_for(:moter_problem?) }
|
81
|
+
Then { bit(13).should be_the_mask_for(:communication_lost?) }
|
82
|
+
Then { bit(14).should be_the_mask_for(:software_fault?) }
|
83
|
+
Then { bit(15).should be_the_mask_for(:low_battery?) }
|
84
|
+
|
85
|
+
Then { bit(16).should be_the_mask_for(:emergency_landing_requested?) }
|
86
|
+
Then { bit(17).should be_the_mask_for(:timer_elapsed?) }
|
87
|
+
Then { bit(18).should be_the_mask_for(:magnometer_needs_calibration?) }
|
88
|
+
Then { bit(19).should be_the_mask_for(:angles_out_of_range?) }
|
89
|
+
|
90
|
+
Then { bit(20).should be_the_mask_for(:too_much_wind?) }
|
91
|
+
Then { bit(21).should be_the_mask_for(:ultrasonic_sensor_deaf?) }
|
92
|
+
Then { bit(22).should be_the_mask_for(:cutout_detected?) }
|
93
|
+
Then { bit(23).should be_the_mask_for(:pic_version_number_ok?) }
|
94
|
+
|
95
|
+
Then { bit(24).should be_the_mask_for(:at_codec_thread_on?) }
|
96
|
+
Then { bit(25).should be_the_mask_for(:navdata_thread_on?) }
|
97
|
+
Then { bit(26).should be_the_mask_for(:video_thread_on?) }
|
98
|
+
Then { bit(27).should be_the_mask_for(:acquisition_thread_on?) }
|
99
|
+
|
100
|
+
Then { bit(28).should be_the_mask_for(:control_watchdog_delayed?) }
|
101
|
+
Then { bit(29).should be_the_mask_for(:adc_watchdog_delayed?) }
|
102
|
+
Then { bit(30).should be_the_mask_for(:com_watchdog_problem?) }
|
103
|
+
Then { bit(31).should be_the_mask_for(:emergency_landing?) }
|
104
|
+
end
|
105
|
+
|
106
|
+
describe "state mask" do
|
107
|
+
context "all zeros" do
|
108
|
+
Given(:state_bits) { 0 }
|
109
|
+
Then { nav_data.state_mask == state_bits }
|
110
|
+
end
|
111
|
+
|
112
|
+
context "non-zero" do
|
113
|
+
Given(:state_bits) { 12345 }
|
114
|
+
Then { nav_data.state_mask == state_bits }
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
describe "#options" do
|
119
|
+
Then { nav_data.options.size == 1 }
|
120
|
+
Then { nav_data.options.first.is_a?(NavOptionChecksum) }
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
describe "multiple options" do
|
125
|
+
context "with good data" do
|
126
|
+
Given(:raw_header) { Bytes.make_header(0, 0, 0) }
|
127
|
+
Given(:raw_nav_bytes) {
|
128
|
+
Bytes.make_nav_data(raw_header, Bytes.make_demo_data)
|
129
|
+
}
|
130
|
+
When(:nav_data) { NavData.new(raw_nav_bytes) }
|
131
|
+
Then { nav_data.options.size == 2 }
|
132
|
+
Then { nav_data.options[0].is_a?(NavOptionDemo) }
|
133
|
+
Then { nav_data.options[1].is_a?(NavOptionChecksum) }
|
134
|
+
end
|
135
|
+
|
136
|
+
context "with short data" do
|
137
|
+
Given(:raw_nav_bytes) {
|
138
|
+
Bytes.make_header(0, 0, 0).pack("C*") +
|
139
|
+
[4321, 100, 0].pack("vvV")
|
140
|
+
}
|
141
|
+
When(:nav_data) { NavData.new(raw_nav_bytes) }
|
142
|
+
Then { nav_data.options.size == 1 }
|
143
|
+
Then { nav_data.options[0].is_a?(NavOptionUnknown) }
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Argus
|
4
|
+
|
5
|
+
describe NavOptionChecksum do
|
6
|
+
Given(:raw_data) { [NavTag::CHECKSUM, 8, 0x12345678].pack("vvV") }
|
7
|
+
Given(:csum) { NavOptionChecksum.new(raw_data) }
|
8
|
+
|
9
|
+
describe ".tag" do
|
10
|
+
Then { NavOptionChecksum.tag == NavTag::CHECKSUM }
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "data fields" do
|
14
|
+
Then { csum.tag == NavOptionChecksum.tag }
|
15
|
+
Then { csum.size == raw_data.size }
|
16
|
+
Then { csum.chks == 0x12345678 }
|
17
|
+
Then { csum.checksum == 0x12345678 }
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Argus
|
4
|
+
describe NavOptionDemo do
|
5
|
+
def f(float)
|
6
|
+
FloatEncoding.encode_float(float)
|
7
|
+
end
|
8
|
+
|
9
|
+
Given(:raw_data) { [
|
10
|
+
NavTag::DEMO, 148,
|
11
|
+
3, 0xcacacaca,
|
12
|
+
f(5.0), f(6.0), f(7.0),
|
13
|
+
-100000,
|
14
|
+
f(-5.0), f(-6.0), f(-7.0),
|
15
|
+
33,
|
16
|
+
[0]*9, [0]*3,
|
17
|
+
12, 34,
|
18
|
+
[0]*9, [0]*3,
|
19
|
+
].flatten.pack("vv VV V3 l< V3 V V9 V3 VV V9 v3") }
|
20
|
+
|
21
|
+
When(:demo) { NavOptionDemo.new(raw_data) }
|
22
|
+
|
23
|
+
Then { ! demo.nil? }
|
24
|
+
|
25
|
+
Then { demo.ctrl_state == 3 }
|
26
|
+
Then { demo.control_state_name == :flying }
|
27
|
+
Then { demo.vbat_flying_percentage == 0xcacacaca }
|
28
|
+
Then { demo.battery_level == 0xcacacaca }
|
29
|
+
Then { demo.theta == 5.0 }
|
30
|
+
Then { demo.phi == 6.0 }
|
31
|
+
Then { demo.psi == 7.0 }
|
32
|
+
Then { demo.altitude == -100000 }
|
33
|
+
Then { demo.vx == -5.0 }
|
34
|
+
Then { demo.vy == -6.0 }
|
35
|
+
Then { demo.vz == -7.0 }
|
36
|
+
Then { demo.detection_camera_rot.nil? }
|
37
|
+
Then { demo.detection_camera_trans.nil? }
|
38
|
+
Then { demo.detection_tag_index == 12 }
|
39
|
+
Then { demo.detection_camera_type == 34 }
|
40
|
+
Then { demo.drone_camera_rot.nil? }
|
41
|
+
Then { demo.drone_camera_trans.nil? }
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|