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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +1 -1
- data/README.md +25 -1
- data/Rakefile +4 -0
- data/lib/argus.rb +5 -0
- data/lib/argus/ardrone_control_modes.rb +14 -0
- data/lib/argus/at_commander.rb +104 -0
- data/lib/argus/cad_type.rb +22 -0
- data/lib/argus/cfields.rb +80 -0
- data/lib/argus/controller.rb +165 -0
- data/lib/argus/drone.rb +62 -0
- data/lib/argus/float_encoding.rb +13 -0
- data/lib/argus/led_animation.rb +48 -0
- data/lib/argus/nav_data.rb +78 -0
- data/lib/argus/nav_monitor.rb +83 -0
- data/lib/argus/nav_option.rb +35 -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 +111 -0
- data/lib/argus/nav_tag.rb +35 -0
- data/lib/argus/null_nav_monitor.rb +13 -0
- data/lib/argus/pave_parser.rb +39 -0
- data/lib/argus/tcp_video_streamer.rb +20 -0
- data/lib/argus/time_queue.rb +62 -0
- data/lib/argus/udp_sender.rb +13 -0
- data/lib/argus/version.rb +10 -0
- data/spec/argus/at_commander_spec.rb +82 -0
- data/spec/argus/controller_spec.rb +149 -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 +56 -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 +111 -0
- data/spec/argus/null_nav_monitor_spec.rb +17 -0
- data/spec/argus/time_queue_spec.rb +61 -0
- data/spec/argus/udp_sender_spec.rb +33 -0
- data/spec/spec_helper.rb +13 -0
- metadata +51 -12
data/lib/argus/drone.rb
ADDED
@@ -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,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,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
|