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
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
|