argus 0.0.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 (44) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +1 -1
  3. data/README.md +25 -1
  4. data/Rakefile +4 -0
  5. data/lib/argus.rb +5 -0
  6. data/lib/argus/ardrone_control_modes.rb +14 -0
  7. data/lib/argus/at_commander.rb +104 -0
  8. data/lib/argus/cad_type.rb +22 -0
  9. data/lib/argus/cfields.rb +80 -0
  10. data/lib/argus/controller.rb +165 -0
  11. data/lib/argus/drone.rb +62 -0
  12. data/lib/argus/float_encoding.rb +13 -0
  13. data/lib/argus/led_animation.rb +48 -0
  14. data/lib/argus/nav_data.rb +78 -0
  15. data/lib/argus/nav_monitor.rb +83 -0
  16. data/lib/argus/nav_option.rb +35 -0
  17. data/lib/argus/nav_option_checksum.rb +20 -0
  18. data/lib/argus/nav_option_demo.rb +79 -0
  19. data/lib/argus/nav_option_unknown.rb +9 -0
  20. data/lib/argus/nav_option_vision_detect.rb +83 -0
  21. data/lib/argus/nav_streamer.rb +111 -0
  22. data/lib/argus/nav_tag.rb +35 -0
  23. data/lib/argus/null_nav_monitor.rb +13 -0
  24. data/lib/argus/pave_parser.rb +39 -0
  25. data/lib/argus/tcp_video_streamer.rb +20 -0
  26. data/lib/argus/time_queue.rb +62 -0
  27. data/lib/argus/udp_sender.rb +13 -0
  28. data/lib/argus/version.rb +10 -0
  29. data/spec/argus/at_commander_spec.rb +82 -0
  30. data/spec/argus/controller_spec.rb +149 -0
  31. data/spec/argus/float_encoding_spec.rb +12 -0
  32. data/spec/argus/led_animation_spec.rb +21 -0
  33. data/spec/argus/nav_data_spec.rb +147 -0
  34. data/spec/argus/nav_option_checksum_spec.rb +21 -0
  35. data/spec/argus/nav_option_demo_spec.rb +56 -0
  36. data/spec/argus/nav_option_spec.rb +32 -0
  37. data/spec/argus/nav_option_unknown_spec.rb +19 -0
  38. data/spec/argus/nav_option_vision_detect_spec.rb +65 -0
  39. data/spec/argus/nav_streamer_spec.rb +111 -0
  40. data/spec/argus/null_nav_monitor_spec.rb +17 -0
  41. data/spec/argus/time_queue_spec.rb +61 -0
  42. data/spec/argus/udp_sender_spec.rb +33 -0
  43. data/spec/spec_helper.rb +13 -0
  44. metadata +51 -12
@@ -0,0 +1,62 @@
1
+ require 'socket'
2
+ require 'argus/nav_monitor'
3
+ require 'argus/null_nav_monitor'
4
+
5
+ module Argus
6
+ class Drone
7
+ attr_reader :controller, :nav
8
+
9
+ def initialize(opts={})
10
+ @host = opts[:remote_host] || '192.168.1.1'
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)
17
+ else
18
+ @nav = NullNavMonitor.new
19
+ end
20
+ end
21
+
22
+ def commander
23
+ @at
24
+ end
25
+
26
+ def start(enable_nav_monitor=true)
27
+ @nav.start
28
+ @at.start
29
+ end
30
+
31
+ def stop
32
+ @controller.land
33
+
34
+ @at.stop
35
+ @nav.stop
36
+
37
+ @at.join
38
+ @nav.join
39
+ end
40
+
41
+ def nav_callback(*args, &block)
42
+ @nav.callback(*args, &block)
43
+ end
44
+
45
+ %w(
46
+ take_off land hover emergency
47
+ forward backward
48
+ left right
49
+ up down
50
+ turn_left turn_right
51
+ front_camera bottom_camera
52
+ config
53
+ led
54
+ reset_watchdog
55
+ ).each do |meth|
56
+ define_method(meth) { |*args|
57
+ @controller.send(meth, *args)
58
+ }
59
+ end
60
+
61
+ end
62
+ end
@@ -0,0 +1,13 @@
1
+ module Argus
2
+ module FloatEncoding
3
+ module_function
4
+
5
+ def encode_float(float)
6
+ [float].pack('g').unpack("l>").first
7
+ end
8
+
9
+ def decode_float(encoded_float)
10
+ [encoded_float].pack("l>").unpack("g").first
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,48 @@
1
+ module Argus
2
+
3
+ module LedAnimation
4
+ NAMES = [
5
+ :blink_green_red,
6
+ :blink_green,
7
+ :blink_red,
8
+ :blink_orange,
9
+ :snake_green_red,
10
+ :fire,
11
+ :standard,
12
+ :red,
13
+ :green,
14
+ :red_snake,
15
+ :blank,
16
+ :right_missile,
17
+ :left_missile,
18
+ :double_missile,
19
+ :front_left_green_others_red,
20
+ :front_right_green_others_red,
21
+ :rear_right_green_others_red,
22
+ :rear_left_green_others_red,
23
+ :left_green_right_red,
24
+ :left_red_right_green,
25
+ :blink_standard,
26
+ ]
27
+
28
+ VALUES = {}
29
+ NAMES.each.with_index { |name, index| VALUES[name] = index }
30
+
31
+ def self.lookup_name(numeric_value)
32
+ NAMES[numeric_value]
33
+ end
34
+
35
+ def self.lookup_value(symbolic_name)
36
+ case symbolic_name
37
+ when Symbol
38
+ VALUES[symbolic_name]
39
+ when Integer
40
+ symbolic_name
41
+ when /^\d+/
42
+ symbolic_name.to_i
43
+ when String
44
+ VALUES[symbolic_name.intern]
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,78 @@
1
+ module Argus
2
+ class NavData
3
+ attr_accessor :state_mask, :vision_flag, :sequence_number, :options
4
+
5
+ def initialize(data)
6
+ @data = data
7
+ parse_nav_data(@data)
8
+ end
9
+
10
+ def raw
11
+ @data
12
+ end
13
+
14
+ def self.bit_mask_readers(*names)
15
+ names.each.with_index do |name, bit_number|
16
+ if name.is_a?(Array)
17
+ name, off_value, on_value = name
18
+ else
19
+ off_value = false
20
+ on_value = true
21
+ end
22
+ define_method(name) { @state_mask[bit_number] == 0 ? off_value : on_value }
23
+ end
24
+ end
25
+
26
+ bit_mask_readers(
27
+ :flying?, # FLY MASK : (0) ardrone is landed, (1) ardrone is flying
28
+ :video_enabled?, # VIDEO MASK : (0) video disable, (1) video enable
29
+ :vision_enabled?, # VISION MASK : (0) vision disable, (1) vision enable
30
+ [:control_algorithm, # CONTROL ALGO : (0) euler angles control, (1) angular speed control
31
+ :euler, :angular_speed],
32
+ :altitude_control_algorithm_active?, # ALTITUDE CONTROL ALGO : (0) altitude control inactive (1) altitude control active
33
+ :start_button_pressed?, # USER feedback : Start button state
34
+ :control_command_ack?, # Control command ACK : (0) None, (1) one received
35
+ :camera_ready?, # CAMERA MASK : (0) camera not ready, (1) Camera ready
36
+ :travelling_enabled?, # Travelling mask : (0) disable, (1) enable
37
+ :usb_ready?, # USB key : (0) usb key not ready, (1) usb key ready
38
+ [:mode, :all, :demo], # Navdata demo : (0) All navdata, (1) only navdata demo
39
+ :bootstrap?, # Navdata bootstrap : (0) options sent in all or demo mode, (1) no navdata options sent
40
+ :moter_problem?, # Motors status : (0) Ok, (1) Motors problem
41
+ :communication_lost?, # Communication Lost : (1) com problem, (0) Com is ok
42
+ :software_fault?, # Software fault detected - user should land as quick as possible (1)
43
+ :low_battery?, # VBat low : (1) too low, (0) Ok
44
+ :emergency_landing_requested?, # User Emergency Landing : (1) User EL is ON, (0) User EL is OF
45
+ :timer_elapsed?, # Timer elapsed : (1) elapsed, (0) not elapsed
46
+ :magnometer_needs_calibration?, # Magnetometer calibration state : (0) Ok, no calibration needed, (1) not ok, calibration needed
47
+ :angles_out_of_range?, # Angles : (0) Ok, (1) out of range
48
+ :too_much_wind?, # WIND MASK: (0) ok, (1) Too much wind
49
+ :ultrasonic_sensor_deaf?, # Ultrasonic sensor : (0) Ok, (1) deaf
50
+ :cutout_detected?, # Cutout system detection : (0) Not detected, (1) detected
51
+ :pic_version_number_ok?, # PIC Version number OK : (0) a bad version number, (1) version number is OK
52
+ :at_codec_thread_on?, # ATCodec thread ON : (0) thread OFF (1) thread ON
53
+ :navdata_thread_on?, # Navdata thread ON : (0) thread OFF (1) thread ON
54
+ :video_thread_on?, # Video thread ON : (0) thread OFF (1) thread ON
55
+ :acquisition_thread_on?, # Acquisition thread ON : (0) thread OFF (1) thread ON
56
+ :control_watchdog_delayed?, # CTRL watchdog : (1) delay in control execution (> 5ms), (0) control is well scheduled
57
+ :adc_watchdog_delayed?, # ADC Watchdog : (1) delay in uart2 dsr (> 5ms), (0) uart2 is good
58
+ :com_watchdog_problem?, # Communication Watchdog : (1) com problem, (0) Com is ok
59
+ :emergency_landing?) # Emergency landing : (0) no emergency, (1) emergency
60
+
61
+ private
62
+
63
+ def parse_nav_data(data)
64
+ tag, @state_mask, @sequence_number, @vision_flag = data.unpack("VVVV")
65
+ parse_nav_options(data[16..-1])
66
+ end
67
+
68
+ def parse_nav_options(data)
69
+ @options = []
70
+ loop do
71
+ opt = NavOption.parse(data)
72
+ data = data[opt.size .. -1]
73
+ @options << opt
74
+ break if data.nil? || data.empty?
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,83 @@
1
+ module Argus
2
+
3
+ class NavMonitor
4
+ attr_reader :streamer
5
+
6
+ def initialize(controller, remote_host)
7
+ @controller = controller
8
+ @streamer = NavStreamer.new(remote_host: remote_host)
9
+ @callbacks = []
10
+ @mutex = Mutex.new
11
+ @nav_data = nil
12
+ @nav_options = {}
13
+ end
14
+
15
+ def start
16
+ @streamer.start
17
+ @running = true
18
+ @nav_thread = Thread.new do
19
+ while @running
20
+ data = @streamer.receive_data
21
+ update_nav_data(data) if data
22
+ end
23
+ end
24
+ end
25
+
26
+ def stop
27
+ @running = false
28
+ end
29
+
30
+ def join
31
+ @nav_thread.join
32
+ end
33
+
34
+ def callback(callback=nil, &block)
35
+ @mutex.synchronize do
36
+ @callbacks << callback unless callback.nil?
37
+ @callbacks << block if block_given?
38
+ end
39
+ end
40
+
41
+ def data
42
+ @mutex.synchronize { @nav_data }
43
+ end
44
+
45
+ def option(tag)
46
+ @mutex.synchronize { @nav_options[tag] }
47
+ end
48
+
49
+ private
50
+
51
+ def update_nav_data(data)
52
+ @mutex.synchronize do
53
+ update_internal_nav_data(data)
54
+ do_callbacks(data)
55
+ end
56
+ rescue Exception => ex
57
+ puts "ERROR in callback: #{ex}"
58
+ puts ex.message
59
+ puts ex.backtrace
60
+ $stdout.flush
61
+ end
62
+
63
+ def update_internal_nav_data(data)
64
+ @nav_data = data
65
+ if @nav_data.bootstrap?
66
+ @controller.demo_mode
67
+ end
68
+ if @nav_data.control_command_ack?
69
+ @controller.ack_control_mode
70
+ end
71
+ data.options.each do |opt|
72
+ @nav_options[opt.tag] = opt if opt.tag < 100
73
+ end
74
+ end
75
+
76
+ def do_callbacks(data)
77
+ @callbacks.each do |callback|
78
+ callback.call(data)
79
+ end
80
+ end
81
+ end
82
+
83
+ end
@@ -0,0 +1,35 @@
1
+ module Argus
2
+
3
+ class NavOption
4
+ attr_reader :tag
5
+
6
+ def initialize(data)
7
+ @tag, @size = data.unpack("vv")
8
+ end
9
+
10
+ def size
11
+ @size < 4 ? 4 : @size
12
+ end
13
+
14
+ def self.options
15
+ @options ||= { }
16
+ end
17
+
18
+ def self.register(option)
19
+ options[option.tag] = option
20
+ end
21
+
22
+ def self.parse(raw_data)
23
+ tag = raw_data.unpack("v").first
24
+ option = options[tag] || NavOptionUnknown
25
+ option.new(raw_data)
26
+ end
27
+
28
+ # Skip the tag and size fields, We've already handled them in the
29
+ # base class.
30
+ def self.initial_format
31
+ "x4"
32
+ end
33
+ end
34
+
35
+ end
@@ -0,0 +1,20 @@
1
+ require 'argus/cfields'
2
+ require 'argus/nav_option'
3
+ require 'argus/nav_tag'
4
+
5
+ module Argus
6
+
7
+ class NavOptionChecksum < NavOption
8
+ include CFields
9
+
10
+ uint32_t :chks
11
+ alias :checksum :chks
12
+
13
+ def self.tag
14
+ NavTag::CHECKSUM
15
+ end
16
+
17
+ NavOption.register(self)
18
+ end
19
+
20
+ end
@@ -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 & 0x0f]
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