hybridgroup-argus 0.2.0 → 0.3.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.
Files changed (43) hide show
  1. checksums.yaml +7 -0
  2. data/lib/argus/at_commander.rb +24 -3
  3. data/lib/argus/cad_type.rb +22 -0
  4. data/lib/argus/cfields.rb +98 -0
  5. data/lib/argus/controller.rb +34 -5
  6. data/lib/argus/drone.rb +28 -1
  7. data/lib/argus/float_encoding.rb +13 -0
  8. data/lib/argus/led_animation.rb +48 -0
  9. data/lib/argus/nav_data.rb +66 -49
  10. data/lib/argus/nav_monitor.rb +78 -0
  11. data/lib/argus/nav_option.rb +29 -0
  12. data/lib/argus/nav_option_checksum.rb +20 -0
  13. data/lib/argus/nav_option_demo.rb +79 -0
  14. data/lib/argus/nav_option_unknown.rb +9 -0
  15. data/lib/argus/nav_option_vision_detect.rb +83 -0
  16. data/lib/argus/nav_streamer.rb +12 -4
  17. data/lib/argus/nav_tag.rb +35 -0
  18. data/lib/argus/version.rb +1 -1
  19. data/lib/argus/video_data.rb +15 -0
  20. data/lib/argus/video_data_envelope.rb +55 -0
  21. data/lib/argus/video_streamer.rb +23 -0
  22. data/lib/argus.rb +5 -9
  23. data/spec/argus/controller_spec.rb +49 -0
  24. data/spec/argus/drone_spec.rb +24 -0
  25. data/spec/argus/float_encoding_spec.rb +12 -0
  26. data/spec/argus/led_animation_spec.rb +21 -0
  27. data/spec/argus/nav_data_spec.rb +147 -0
  28. data/spec/argus/nav_option_checksum_spec.rb +21 -0
  29. data/spec/argus/nav_option_demo_spec.rb +44 -0
  30. data/spec/argus/nav_option_spec.rb +32 -0
  31. data/spec/argus/nav_option_unknown_spec.rb +19 -0
  32. data/spec/argus/nav_option_vision_detect_spec.rb +65 -0
  33. data/spec/argus/nav_streamer_spec.rb +28 -0
  34. data/spec/argus/udp_sender_spec.rb +1 -1
  35. data/spec/argus/video_data_envelope_spec.rb +26 -0
  36. data/spec/argus/video_data_spec.rb +18 -0
  37. data/spec/argus/video_streamer_spec.rb +16 -0
  38. data/spec/spec_helper.rb +3 -0
  39. data/spec/support/bytes.rb +48 -0
  40. metadata +36 -15
  41. data/lib/argus/pave_parser.rb +0 -39
  42. data/lib/argus/tcp_video_streamer.rb +0 -20
  43. 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,9 @@
1
+ module Argus
2
+
3
+ class NavOptionUnknown < NavOption
4
+ def self.tag
5
+ NavTag::UNKNOWN
6
+ end
7
+ end
8
+
9
+ 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
@@ -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
- @streamer = Argus::UdpNavStreamer.new(@socket, host, port)
8
+ @host = host
9
+ @port = port
10
+ @socket.bind("0.0.0.0", port)
8
11
  end
9
12
 
10
13
  def start
11
- @streamer.start_stream
14
+ @socket.send("\x01\x00\x00\x00", 0, @host, @port)
12
15
  end
13
16
 
14
17
  def receive_data
15
- @streamer.receive_packet
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
@@ -2,7 +2,7 @@ module Argus
2
2
  module Version # :nodoc: all
3
3
  NUMBERS = [
4
4
  MAJOR = 0,
5
- MINOR = 2,
5
+ MINOR = 3,
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(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
- require 'argus/at_commander'
2
- require 'argus/controller'
3
- require 'argus/udp_sender'
4
- require 'argus/udp_nav_streamer'
5
- require 'argus/nav_data'
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,12 @@
1
+ require 'spec_helper'
2
+
3
+ module Argus
4
+
5
+ describe FloatEncoding do
6
+ Given(:f) { 5.0 }
7
+ Given(:encoded_f) { 1084227584 }
8
+ Then { FloatEncoding.encode_float(f) == encoded_f }
9
+ Then { FloatEncoding.decode_float(encoded_f) == f }
10
+ end
11
+
12
+ end
@@ -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