argus 0.0.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/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
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 2f89d5eb3a36569a8fb2d9e6c17a2eebd17e92d8
|
4
|
+
data.tar.gz: ec1b2d028705b04ae55f8eeaa5dfb91c4352347f
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 80bde0b4804b76b9be1d79d8c3c2537767a1fc35027bf52811d1324fc4a407d645412ab441675049e2dcf9bdaac14382c5f39fb2520f71e9469dbb4dafe533e9
|
7
|
+
data.tar.gz: 330df98c125cfb917f81da99d26dcdc9b25a506e5ffe57ad0c55bc6aad08d035bc2fa6050a377be3f02fe1df58b0d3a1f6e8d587883c5e5753aaba56165244e2
|
data/MIT-LICENSE
CHANGED
data/README.md
CHANGED
@@ -1,3 +1,27 @@
|
|
1
1
|
# Argus -- Parrot AR Drone Ruby API
|
2
2
|
|
3
|
-
|
3
|
+
## Current Status
|
4
|
+
|
5
|
+
* Experimental
|
6
|
+
* Subject to change
|
7
|
+
* Use at your own risk
|
8
|
+
* May cause cancer
|
9
|
+
|
10
|
+
## Example
|
11
|
+
|
12
|
+
<pre>
|
13
|
+
require 'argus'
|
14
|
+
|
15
|
+
drone = Argus::Drone.new
|
16
|
+
drone.start
|
17
|
+
|
18
|
+
drone.take_off
|
19
|
+
sleep 5
|
20
|
+
drone.turn_right(1.0)
|
21
|
+
sleep 5
|
22
|
+
drone.turn_left(1.0)
|
23
|
+
sleep 5
|
24
|
+
drone.hover.land
|
25
|
+
sleep 5
|
26
|
+
drone.stop
|
27
|
+
</pre>
|
data/Rakefile
CHANGED
data/lib/argus.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
module Argus
|
2
|
+
module ArdroneControlModes
|
3
|
+
# ARDRONE_CONTROL_MODE values from the ardrone_api.h file.
|
4
|
+
|
5
|
+
CFG_GET_CONTROL_MODE = 4 # Send active configuration file
|
6
|
+
# to a client through the
|
7
|
+
# 'control' socket UDP 5559
|
8
|
+
|
9
|
+
ACK_CONTROL_MODE = 5 # Reset command mask in navdata
|
10
|
+
|
11
|
+
CUSTOM_CFG_GET_CONTROL_MODE = 6 # Requests the list of custom
|
12
|
+
# configuration IDs
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require 'thread'
|
2
|
+
|
3
|
+
module Argus
|
4
|
+
class ATCommander
|
5
|
+
attr_reader :timestamps
|
6
|
+
|
7
|
+
def initialize(sender)
|
8
|
+
@sender = sender
|
9
|
+
@seq = 0
|
10
|
+
@ref_data = "0"
|
11
|
+
@pcmd_data = "0,0,0,0,0"
|
12
|
+
@buffer = ""
|
13
|
+
@thread = nil
|
14
|
+
@interval = 0.020
|
15
|
+
@mutex = Mutex.new
|
16
|
+
@timestamps = []
|
17
|
+
end
|
18
|
+
|
19
|
+
def start
|
20
|
+
@running = true
|
21
|
+
@thread = Thread.new do
|
22
|
+
while @running
|
23
|
+
log_time
|
24
|
+
tick
|
25
|
+
sleep @interval
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def tick
|
31
|
+
@mutex.synchronize do
|
32
|
+
packet do
|
33
|
+
command("REF", @ref_data)
|
34
|
+
command("PCMD", @pcmd_data)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def stop
|
40
|
+
@running = false
|
41
|
+
end
|
42
|
+
|
43
|
+
def join
|
44
|
+
@thread.join if @thread
|
45
|
+
end
|
46
|
+
|
47
|
+
def interval=(new_interval)
|
48
|
+
@mutex.synchronize do @interval = new_interval end
|
49
|
+
end
|
50
|
+
|
51
|
+
def ref(data)
|
52
|
+
@mutex.synchronize do @ref_data = data end
|
53
|
+
end
|
54
|
+
|
55
|
+
def pcmd(data)
|
56
|
+
@mutex.synchronize do @pcmd_data = data end
|
57
|
+
end
|
58
|
+
|
59
|
+
def config(key, value)
|
60
|
+
@mutex.synchronize do
|
61
|
+
command("CONFIG", "\"#{key}\",\"#{value}\"")
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def comwdg
|
66
|
+
@mutex.synchronize do
|
67
|
+
command("COMWDG")
|
68
|
+
end
|
69
|
+
end
|
70
|
+
alias reset_watchdog comwdg # For backward compatibility
|
71
|
+
|
72
|
+
def ctrl(mode)
|
73
|
+
@mutex.synchronize do
|
74
|
+
command("CTRL", "#{mode},0")
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def log_time
|
81
|
+
@timestamps.shift if @timestamps.size >= 1000
|
82
|
+
@timestamps << Time.now.to_f
|
83
|
+
end
|
84
|
+
|
85
|
+
def packet
|
86
|
+
yield self
|
87
|
+
flush
|
88
|
+
end
|
89
|
+
|
90
|
+
def flush
|
91
|
+
@sender.send_packet(@buffer)
|
92
|
+
@buffer = ""
|
93
|
+
end
|
94
|
+
|
95
|
+
def command(name, args=nil)
|
96
|
+
@seq += 1
|
97
|
+
if args
|
98
|
+
@buffer << "AT*#{name}=#{@seq},#{args}\r"
|
99
|
+
else
|
100
|
+
@buffer << "AT*#{name}=#{@seq}\r"
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Argus
|
2
|
+
module CadType
|
3
|
+
|
4
|
+
NAMES = [
|
5
|
+
:horizontal, # Deprecated
|
6
|
+
:vertical, # Deprecated
|
7
|
+
:vision, # Detection of 2D horizontal tags on drone shells
|
8
|
+
:none, # Detection disabled
|
9
|
+
:cocarde, # Detects a roundel under the drone
|
10
|
+
:oriented_cocarde, # Detects an oriented roundel under the drone
|
11
|
+
:stripe, # Detects a uniform stripe on the ground
|
12
|
+
:h_cocarde, # Detects a roundel in front of the drone
|
13
|
+
:h_oriented_cocarde, # Detects an oriented roundel in front of the drone
|
14
|
+
:stripe_v,
|
15
|
+
:multiple_detection_mode, # The drone uses several detections at the same time
|
16
|
+
:cap, # Detects a Cap orange and green in front of the drone
|
17
|
+
:oriented_cocarde_bw, # Detects the black and white roundel
|
18
|
+
:vision_v2, # Detects 2nd version of shell/tag in front of the drone
|
19
|
+
:tower_side, # Detect a tower side with the front camera
|
20
|
+
]
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'argus/float_encoding'
|
2
|
+
|
3
|
+
module Argus
|
4
|
+
|
5
|
+
module CFields
|
6
|
+
def self.included(base)
|
7
|
+
base.send :extend, ClassMethods
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(*args)
|
11
|
+
super
|
12
|
+
@data = unpack_data(args.first)
|
13
|
+
end
|
14
|
+
|
15
|
+
def unpack_data(data)
|
16
|
+
@data = data.unpack(self.class.format_string)
|
17
|
+
end
|
18
|
+
|
19
|
+
module ClassMethods
|
20
|
+
def data_index
|
21
|
+
@data_index ||= 0
|
22
|
+
end
|
23
|
+
|
24
|
+
def format_string
|
25
|
+
@format_string ||= (defined?(initial_format) ? initial_format : "")
|
26
|
+
end
|
27
|
+
|
28
|
+
def allot(n=1)
|
29
|
+
result = data_index
|
30
|
+
@data_index += n
|
31
|
+
result
|
32
|
+
end
|
33
|
+
|
34
|
+
def define_field(name, size, format, width=1, &transform)
|
35
|
+
if size
|
36
|
+
define_array_field(name, size, format, width, transform)
|
37
|
+
else
|
38
|
+
define_scaler_field(name, format, width, transform)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def define_scaler_field(name, format, width, transform)
|
43
|
+
index = allot(width)
|
44
|
+
format_string << (width==1 ? format : "#{format}#{width}")
|
45
|
+
define_method(name) { @data[index] }
|
46
|
+
end
|
47
|
+
|
48
|
+
def define_array_field(name, size, format, width, transform)
|
49
|
+
index = allot(width*size)
|
50
|
+
format_string << "#{format}#{width*size}"
|
51
|
+
define_method(name) { @data[index, width*size] }
|
52
|
+
end
|
53
|
+
|
54
|
+
def uint32_t(name, size=nil)
|
55
|
+
define_field(name, size, "V")
|
56
|
+
end
|
57
|
+
|
58
|
+
def uint16_t(name, size=nil)
|
59
|
+
define_field(name, size, "v")
|
60
|
+
end
|
61
|
+
|
62
|
+
def float32_t(name, size=nil)
|
63
|
+
define_field(name, size, "e")
|
64
|
+
end
|
65
|
+
|
66
|
+
def int32_t(name, size=nil)
|
67
|
+
define_field(name, size, "l<")
|
68
|
+
end
|
69
|
+
|
70
|
+
def matrix33_t(name, size=nil)
|
71
|
+
define_field(name, size, "V", 9)
|
72
|
+
end
|
73
|
+
|
74
|
+
def vector31_t(name, size=nil)
|
75
|
+
define_field(name, size, "V", 3)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
@@ -0,0 +1,165 @@
|
|
1
|
+
require 'argus/float_encoding'
|
2
|
+
require 'argus/ardrone_control_modes'
|
3
|
+
|
4
|
+
module Argus
|
5
|
+
class Controller
|
6
|
+
include FloatEncoding
|
7
|
+
|
8
|
+
def initialize(at_commander)
|
9
|
+
@at_commander = at_commander
|
10
|
+
|
11
|
+
@emergency = false
|
12
|
+
land
|
13
|
+
hover
|
14
|
+
end
|
15
|
+
|
16
|
+
def take_off
|
17
|
+
@flying = true
|
18
|
+
@emergency = false
|
19
|
+
update_ref
|
20
|
+
end
|
21
|
+
|
22
|
+
def land
|
23
|
+
@flying = false
|
24
|
+
update_ref
|
25
|
+
end
|
26
|
+
|
27
|
+
def emergency
|
28
|
+
@flying = false
|
29
|
+
@emergency = true
|
30
|
+
update_ref
|
31
|
+
end
|
32
|
+
|
33
|
+
def hover
|
34
|
+
@moving = false
|
35
|
+
@roll = 0.0
|
36
|
+
@pitch = 0.0
|
37
|
+
@gaz = 0.0
|
38
|
+
@yaw = 0.0
|
39
|
+
update_pcmd
|
40
|
+
end
|
41
|
+
|
42
|
+
def forward(amount)
|
43
|
+
@moving = true
|
44
|
+
@pitch = -amount
|
45
|
+
update_pcmd
|
46
|
+
end
|
47
|
+
|
48
|
+
def backward(amount)
|
49
|
+
@moving = true
|
50
|
+
@pitch = amount
|
51
|
+
update_pcmd
|
52
|
+
end
|
53
|
+
|
54
|
+
def left(amount)
|
55
|
+
@moving = true
|
56
|
+
@roll = -amount
|
57
|
+
update_pcmd
|
58
|
+
end
|
59
|
+
|
60
|
+
def right(amount)
|
61
|
+
@moving = true
|
62
|
+
@roll = amount
|
63
|
+
update_pcmd
|
64
|
+
end
|
65
|
+
|
66
|
+
def up(amount)
|
67
|
+
@moving = true
|
68
|
+
@gaz = amount
|
69
|
+
update_pcmd
|
70
|
+
end
|
71
|
+
|
72
|
+
def down(amount)
|
73
|
+
@moving = true
|
74
|
+
@gaz = -amount
|
75
|
+
update_pcmd
|
76
|
+
end
|
77
|
+
|
78
|
+
def turn_left(amount)
|
79
|
+
@moving = true
|
80
|
+
@yaw = -amount
|
81
|
+
update_pcmd
|
82
|
+
end
|
83
|
+
|
84
|
+
def turn_right(amount)
|
85
|
+
@moving = true
|
86
|
+
@yaw = amount
|
87
|
+
update_pcmd
|
88
|
+
end
|
89
|
+
|
90
|
+
def led(selection, hertz, duration)
|
91
|
+
selection = LedAnimation.lookup_value(selection)
|
92
|
+
value = [
|
93
|
+
selection,
|
94
|
+
FloatEncoding.encode_float(hertz),
|
95
|
+
duration
|
96
|
+
].join(',')
|
97
|
+
@at_commander.config("leds:leds_anim",value)
|
98
|
+
self
|
99
|
+
end
|
100
|
+
|
101
|
+
def enable_detection(colors, type=10, select=32)
|
102
|
+
config("detect:enemy_colors",colors.to_s)
|
103
|
+
config("detect:detect_type", type.to_s)
|
104
|
+
config("detect:detections_select_h", select.to_s)
|
105
|
+
self
|
106
|
+
end
|
107
|
+
|
108
|
+
def config(key, value)
|
109
|
+
@at_commander.config(key, value)
|
110
|
+
end
|
111
|
+
|
112
|
+
def demo_mode
|
113
|
+
@at_commander.config("general:navdata_demo", "TRUE")
|
114
|
+
end
|
115
|
+
|
116
|
+
def front_camera
|
117
|
+
@at_commander.config("video:video_channel", "2")
|
118
|
+
end
|
119
|
+
|
120
|
+
def bottom_camera
|
121
|
+
@at_commander.config("video:video_channel", "1")
|
122
|
+
end
|
123
|
+
|
124
|
+
def reset_watchdog
|
125
|
+
@at_commander.comwdg
|
126
|
+
end
|
127
|
+
|
128
|
+
def ack_control_mode
|
129
|
+
@at_commander.ctrl(ArdroneControlModes::ACK_CONTROL_MODE)
|
130
|
+
self
|
131
|
+
end
|
132
|
+
|
133
|
+
private
|
134
|
+
|
135
|
+
REF_BASE = [18, 20, 22, 24, 28].
|
136
|
+
inject(0) { |flag, bitnum| flag | (1 << bitnum) }
|
137
|
+
REF_FLY_BIT = (1 << 9)
|
138
|
+
REF_EMERGENCY_BIT = (1 << 8)
|
139
|
+
|
140
|
+
def update_ref
|
141
|
+
n = REF_BASE
|
142
|
+
n |= REF_FLY_BIT if @flying
|
143
|
+
n |= REF_EMERGENCY_BIT if @emergency
|
144
|
+
@at_commander.ref(n.to_s)
|
145
|
+
self
|
146
|
+
end
|
147
|
+
|
148
|
+
def update_pcmd
|
149
|
+
flags = 0
|
150
|
+
if @moving
|
151
|
+
flags = 1
|
152
|
+
iroll = encode_float(@roll)
|
153
|
+
ipitch = encode_float(@pitch)
|
154
|
+
igaz = encode_float(@gaz)
|
155
|
+
iyaw = encode_float(@yaw)
|
156
|
+
data = "#{flags},#{iroll},#{ipitch},#{igaz},#{iyaw}"
|
157
|
+
else
|
158
|
+
data = "0,0,0,0,0"
|
159
|
+
end
|
160
|
+
@at_commander.pcmd(data)
|
161
|
+
self
|
162
|
+
end
|
163
|
+
|
164
|
+
end
|
165
|
+
end
|