crubyflie 0.1.2 → 0.1.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +12 -3
- data/bin/crubyflie +6 -4
- data/configs/joystick_default.yaml +67 -9
- data/lib/crubyflie/input/input_reader.rb +29 -7
- data/lib/crubyflie/input/joystick_input_reader.rb +33 -15
- data/lib/crubyflie/version.rb +1 -1
- data/spec/input_reader_spec.rb +2 -2
- data/spec/joystick_cfg.yaml +10 -14
- data/spec/joystick_input_reader_spec.rb +2 -2
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 02c5195ea21e56d89557355913944da49b894f21
|
4
|
+
data.tar.gz: 92b4e05341df2db63e05149e82b17099d5015eb3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a141f33049bae4a6bb67a80164514d42141cc303d66d460a0b3987c73c716ecd3ce2bbd5d181cc69f706ca3dc933f5de479e32f5fb8a6ffd32956b016468d805
|
7
|
+
data.tar.gz: a34a3b8d723f5154d2f71753f3345d25d42d6b54d818d47b5d7f13edf344125268d1c69c48c4184805dde548e7950f3a250b0876300d8dda5807ed94f9ed5688
|
data/README.md
CHANGED
@@ -33,10 +33,19 @@ Not included...
|
|
33
33
|
* No idea how this works in other OSs that are not Linux, but in theory it should work in all with some small fixes. I welcome you to take on this task if you are interested.
|
34
34
|
* No support for Ruby <= 1.8.7 (maybe it works who knows... I haven't tested but since Crubyflie relies heavily on threading probably it does not work so good).
|
35
35
|
|
36
|
+
Installation
|
37
|
+
------------
|
38
|
+
|
39
|
+
Crubyflie depends on `rubysdl`, for which you will need the SDL library and headers. Make sure you install `libsdl-dev` (Debian/Ubuntu), `libSDL-devel` (Opensuse) or whatever your distro calls it. Then:
|
40
|
+
|
41
|
+
gem install crubyflie
|
42
|
+
|
43
|
+
That's all.
|
44
|
+
|
36
45
|
Fyling the Crazyflie
|
37
46
|
--------------------
|
38
47
|
|
39
|
-
The easiest way to do it is to run the `crubyflie` command. This will connect to the first visible quadcopter using the first available joystick on your computer (you can modify this parameters with the appropiate flags):
|
48
|
+
The easiest way to do it is to `gem install crubyflie` and then run the `crubyflie` command. This will connect to the first visible quadcopter using the first available joystick on your computer (you can modify this parameters with the appropiate flags):
|
40
49
|
|
41
50
|
> crubyflie2.0 -h
|
42
51
|
Options:
|
@@ -46,13 +55,13 @@ The easiest way to do it is to run the `crubyflie` command. This will connect to
|
|
46
55
|
/usr/lib64/ruby/gems/2.0.0/gems/crubyflie-0.0.1/lib/crubyflie/input/../../../configs/joystick_default.yaml)
|
47
56
|
--help, -h: Show this message
|
48
57
|
|
49
|
-
|
58
|
+
There is a [template/default configuration file](https://github.com/hsanjuan/crubyflie/blob/master/configs/joystick_default.yaml) with instructions (which works for me and my PS3-like controller :) ). You should modify this file to fit it to your needs (configuration parameters are commented). The most tricky parameter in axis is the `:max_change_rate`. Depending on your controller, you will find the input is excessively throotled or not. I recommend that you play with this value.
|
50
59
|
|
51
60
|
If you are wondering about your Joystick's axis IDs, ranges etc, you will find a `sdl-joystick-axis.rb` script under `tools` that lets you open a joystick and check what the SDL library can read from it. It might come handy.
|
52
61
|
|
53
62
|
If you need help just open an issue or contact me.
|
54
63
|
|
55
|
-
|
64
|
+
Raspberry Pi
|
56
65
|
------------
|
57
66
|
|
58
67
|
If you want to use Crubyflie in your Raspberry Pi you need to:
|
data/bin/crubyflie
CHANGED
@@ -36,11 +36,13 @@ opts = Trollop::options do
|
|
36
36
|
:type => :string,
|
37
37
|
:default => Crubyflie::Joystick::DEFAULT_CONFIG_PATH,
|
38
38
|
:short => '-c')
|
39
|
-
|
39
|
+
opt(:debug, "Enable debug messages",
|
40
|
+
:short => '-d')
|
41
|
+
end
|
40
42
|
|
41
43
|
include Crubyflie
|
42
|
-
|
43
|
-
|
44
|
+
$debug = true if opts[:debug]
|
45
|
+
|
44
46
|
cf = Crazyflie.new('/tmp/crubyflie')
|
45
47
|
|
46
48
|
# Before opening any link, scan for interfaces
|
@@ -80,7 +82,7 @@ while cf.active? && !exit do
|
|
80
82
|
# 1/10 secs of time per loop. If we are fast, we can sleep
|
81
83
|
# a little bit
|
82
84
|
consumed_time = Time.now.to_f - start_time
|
83
|
-
sleep_time = 0.1 -
|
85
|
+
sleep_time = 0.1 - consumed_time
|
84
86
|
sleep sleep_time if sleep_time > 0
|
85
87
|
end
|
86
88
|
|
@@ -1,5 +1,58 @@
|
|
1
|
-
# Default joystick configuration file.
|
2
|
-
#
|
1
|
+
# Default joystick configuration file. A file looks like:
|
2
|
+
# --------------------------------------------------------------------------
|
3
|
+
# :type: Joystick
|
4
|
+
# :axis:
|
5
|
+
# <axis_id>:
|
6
|
+
# :action: <action>
|
7
|
+
# :description: A short description to remember what this is
|
8
|
+
# :input_range: "<start>:<end>"
|
9
|
+
# The range read from the joystick.
|
10
|
+
# Defaults to -32768:32767 which is SDL-dependant
|
11
|
+
#
|
12
|
+
# :output_range: "<start>:<end>"
|
13
|
+
# The values we should yield to
|
14
|
+
# the Crazyflie, normally degrees (roll, pitch...). For
|
15
|
+
# thrust it is expressed in % of thrust
|
16
|
+
#
|
17
|
+
# :max_change_rate: <number>
|
18
|
+
# The output_range change rate per second. Must
|
19
|
+
# e a number. Defaults to 10000 (so a lot). For thrust
|
20
|
+
# it is expressed in % of thrust
|
21
|
+
# :dead_zone: "<start>:<end>"
|
22
|
+
# The dead range around 0. Defaults to 0:0
|
23
|
+
#
|
24
|
+
# :invert: true|false - Invert this axis
|
25
|
+
#
|
26
|
+
# :calibration: <number>
|
27
|
+
# This value is added to the raw joystick reading
|
28
|
+
#
|
29
|
+
# <axis_id2>: ...
|
30
|
+
#
|
31
|
+
# :buttons:
|
32
|
+
# <button_id>:
|
33
|
+
# :action: <action>
|
34
|
+
# :value: <value when pressed>
|
35
|
+
# A number, optional, defaults to 1.
|
36
|
+
#
|
37
|
+
# <button_id2>: ...
|
38
|
+
#
|
39
|
+
# --------------------------------------------------------------------------
|
40
|
+
# Valid actions:
|
41
|
+
# :roll - Controls roll. Assignable a axis or a button with value tag.
|
42
|
+
# :pitch - Controls pitch. Assignable a axis or a button with value tag.
|
43
|
+
# :thrust - Controls thrust. Assignable a axis or a button with value tag.
|
44
|
+
# :yaw - Controls yaw. Assignable a axis or a button with value tag.
|
45
|
+
# :switch_xmode - Enables/disables xmode. Assignable to a button.
|
46
|
+
# :close_link - Kills the link and shuts Crubyflie. Assignable to a button.
|
47
|
+
# :switch_scaled_output_mode - Enables/disabled scaled output mode. Assignable
|
48
|
+
# to a button with value tag (the multiplier)
|
49
|
+
# :roll_inc_cal, :roll_dec_cal - Increase/decrease calibration for :roll axis.
|
50
|
+
# Assignable to a button with optional value.
|
51
|
+
#
|
52
|
+
# :pitch_inc_cal, :pitch_dec_cal - Increase/decrease calibration for :pitch
|
53
|
+
# axis. Assignable to a button with optional
|
54
|
+
# value.
|
55
|
+
# ---------------------------------------------------------------------------
|
3
56
|
:type: "Joystick"
|
4
57
|
:axis:
|
5
58
|
0:
|
@@ -24,7 +77,7 @@
|
|
24
77
|
:description: "Yaw Axis"
|
25
78
|
:action: :yaw
|
26
79
|
:input_range: "-32768:32767"
|
27
|
-
:output_range: "-
|
80
|
+
:output_range: "-150:150"
|
28
81
|
:max_change_rate: 800
|
29
82
|
:dead_zone: "-1000:1000"
|
30
83
|
:invert: false
|
@@ -33,11 +86,11 @@
|
|
33
86
|
:description: "Thrust axis"
|
34
87
|
:action: :thrust
|
35
88
|
:input_range: "-32768:32767"
|
36
|
-
|
37
|
-
|
38
|
-
#
|
39
|
-
:max_change_rate:
|
40
|
-
:dead_zone: "-100:100"
|
89
|
+
# Exception: Min/max thrust output is represented in 0-100%!
|
90
|
+
:output_range: "0:80"
|
91
|
+
# Max change rate per second when lowering thrust in % of thrust
|
92
|
+
:max_change_rate: 70
|
93
|
+
:dead_zone: "-100:100"
|
41
94
|
:invert: true
|
42
95
|
:calibration: 0
|
43
96
|
|
@@ -45,4 +98,9 @@
|
|
45
98
|
0:
|
46
99
|
:action: :switch_xmode
|
47
100
|
1:
|
48
|
-
:action: :close_link
|
101
|
+
:action: :close_link
|
102
|
+
4:
|
103
|
+
# When enabled, this mode will will multiply axis readings (except thrust)
|
104
|
+
# by the value of the button (must be a positive number)
|
105
|
+
:action: :switch_scaled_output_mode
|
106
|
+
:value: 0.50 # Softer output, useful for landing
|
@@ -30,31 +30,32 @@ module Crubyflie
|
|
30
30
|
#
|
31
31
|
# The InputReader will also apply the #INPUT_ACTIONS to a given
|
32
32
|
# Crazyflie. In order to do that it will go through all the
|
33
|
-
# read values and perform
|
34
|
-
# a setpoint
|
33
|
+
# read values and perform actions associated to them, like sending
|
34
|
+
# a setpoint, shutting down the connection or altering the calibration.
|
35
35
|
class InputReader
|
36
36
|
|
37
37
|
# List of current recognized actions that controllers can declare
|
38
38
|
INPUT_ACTIONS = [:roll, :pitch, :yaw, :thrust,
|
39
39
|
:roll_inc_cal, :roll_dec_cal,
|
40
40
|
:pitch_inc_cal, :pitch_dec_cal,
|
41
|
+
:switch_scaled_output_mode,
|
41
42
|
:switch_xmode, :close_link]
|
42
43
|
|
43
44
|
attr_reader :axis, :buttons, :axis_readings, :button_readings
|
44
45
|
attr_accessor :xmode
|
45
|
-
# An input is composed by several necessary axis
|
46
|
-
# calibrations.
|
46
|
+
# An input is composed by several necessary axis and buttons.
|
47
47
|
# @param axis [Hash] A hash of keys identifying axis IDs
|
48
48
|
# (the controller should know to what the
|
49
|
-
# ID maps, and values from #INPUT_ACTIONS
|
49
|
+
# ID maps), and values from #INPUT_ACTIONS
|
50
50
|
# @param buttons [Hash] A hash of keys identifying button IDs (the
|
51
|
-
# controller should know to what the ID maps,
|
51
|
+
# controller should know to what the ID maps),
|
52
52
|
# and values from #INPUT_ACTIONS
|
53
53
|
def initialize(axis, buttons)
|
54
54
|
@axis = axis
|
55
55
|
@buttons = buttons
|
56
56
|
@calibrations = {}
|
57
57
|
@xmode = false
|
58
|
+
@output_scale = 0 # off
|
58
59
|
|
59
60
|
# Calibrate defaults to 0
|
60
61
|
INPUT_ACTIONS.each do |action|
|
@@ -73,12 +74,20 @@ module Crubyflie
|
|
73
74
|
poll() # In case we need to poll the device
|
74
75
|
actions_to_axis = @axis.invert()
|
75
76
|
actions_to_axis.each do |action, axis_id|
|
77
|
+
if !INPUT_ACTIONS.include?(action)
|
78
|
+
logger.error("Unknown action #{action}. Skipping")
|
79
|
+
next
|
80
|
+
end
|
76
81
|
@axis_readings[action] = read_axis(axis_id)
|
77
82
|
@axis_readings[action] += @calibrations[action]
|
78
83
|
end
|
79
84
|
|
80
85
|
actions_to_buttons = @buttons.invert()
|
81
86
|
actions_to_buttons.each do |action, button_id|
|
87
|
+
if !INPUT_ACTIONS.include?(action)
|
88
|
+
logger.error("Unknown action #{action}. Skipping")
|
89
|
+
next
|
90
|
+
end
|
82
91
|
@button_readings[action] = read_button(button_id)
|
83
92
|
@button_readings[action] += @calibrations[action]
|
84
93
|
end
|
@@ -86,7 +95,7 @@ module Crubyflie
|
|
86
95
|
|
87
96
|
# This will act on current axis readings (by sendint a setpoint to
|
88
97
|
# the crazyflie) and on button readings (by, for example, shutting
|
89
|
-
# down the link or modifying the calibrations.
|
98
|
+
# down the link or modifying the calibrations).
|
90
99
|
# If the link to the crazyflie is down, it will not send anything.
|
91
100
|
# @param crazyflie [Crazyflie] A crazyflie instance to send the
|
92
101
|
# setpoint to.
|
@@ -120,6 +129,14 @@ module Crubyflie
|
|
120
129
|
when :switch_xmode
|
121
130
|
@xmode = !@xmode if value > 0
|
122
131
|
logger.info("Xmode is #{@xmode}") if value > 0
|
132
|
+
when :switch_scaled_output_mode
|
133
|
+
if value > 0 && @output_scale == 0
|
134
|
+
logger.info("Scaling output: x#{value}")
|
135
|
+
@output_scale = value.to_f
|
136
|
+
elsif value > 0 && @output_scale > 0
|
137
|
+
logger.info("Scaling output disabled")
|
138
|
+
@output_scale = 0
|
139
|
+
end
|
123
140
|
when :close_link
|
124
141
|
crazyflie.close_link() if value > 0
|
125
142
|
end
|
@@ -140,6 +157,11 @@ module Crubyflie
|
|
140
157
|
end
|
141
158
|
end
|
142
159
|
|
160
|
+
setpoint.keys().each do |k|
|
161
|
+
next if k == :thrust
|
162
|
+
setpoint[k] *= @output_scale
|
163
|
+
end if @output_scale > 0
|
164
|
+
|
143
165
|
pitch = setpoint[:pitch]
|
144
166
|
roll = setpoint[:roll]
|
145
167
|
yaw = setpoint[:yaw]
|
@@ -41,6 +41,8 @@ module Crubyflie
|
|
41
41
|
# Default configuration file
|
42
42
|
DEFAULT_CONFIG_PATH = File.join(File.dirname(__FILE__), "..","..","..",
|
43
43
|
"configs", "joystick_default.yaml")
|
44
|
+
THRUST_MAX = 60000
|
45
|
+
THRUST_MIN = 9500
|
44
46
|
|
45
47
|
attr_reader :config, :joystick_index
|
46
48
|
# Initializes the Joystick configuration and the SDL library
|
@@ -107,7 +109,14 @@ module Crubyflie
|
|
107
109
|
|
108
110
|
# output value max jump per second. We covert to rate/ms
|
109
111
|
max_chrate = axis_cfg[:max_change_rate] || 10000
|
110
|
-
|
112
|
+
if action == :thrust
|
113
|
+
# Thrust expressed in %
|
114
|
+
w = THRUST_MAX - THRUST_MIN
|
115
|
+
max_chrate = (max_chrate.to_f * w /100) / 1000
|
116
|
+
else
|
117
|
+
max_chrate = max_chrate.to_f / 1000
|
118
|
+
end
|
119
|
+
axis_cfg[:max_change_rate] = max_chrate
|
111
120
|
|
112
121
|
axis_cfg[:last_poll] ||= 0
|
113
122
|
axis_cfg[:last_value] ||= 0
|
@@ -117,7 +126,7 @@ module Crubyflie
|
|
117
126
|
end
|
118
127
|
|
119
128
|
buttons = {}
|
120
|
-
config_h[:buttons] =
|
129
|
+
config_h[:buttons] = {} if config_h[:buttons].nil?
|
121
130
|
|
122
131
|
config_h[:buttons].each do |id, button_cfg|
|
123
132
|
action = button_cfg[:action]
|
@@ -125,6 +134,7 @@ module Crubyflie
|
|
125
134
|
raise JoystickException.new("Button #{id} needs an action")
|
126
135
|
end
|
127
136
|
buttons[id] = action
|
137
|
+
button_cfg[:value] ||= 1
|
128
138
|
end
|
129
139
|
|
130
140
|
@config = config_h
|
@@ -189,7 +199,13 @@ module Crubyflie
|
|
189
199
|
# the dead zone
|
190
200
|
if dead_zone[:start] < value && dead_zone[:end] > value
|
191
201
|
value = 0
|
192
|
-
elsif
|
202
|
+
elsif dead_zone[:start] >= value
|
203
|
+
value = value - dead_zone[:start]
|
204
|
+
elsif dead_zone[:end] <= value
|
205
|
+
value = value - dead_zone[:end]
|
206
|
+
end
|
207
|
+
|
208
|
+
if value > input_range[:end]
|
193
209
|
value = input_range[:end]
|
194
210
|
elsif value < input_range[:start]
|
195
211
|
value = input_range[:start]
|
@@ -206,7 +222,7 @@ module Crubyflie
|
|
206
222
|
current_time = Time.now.to_f
|
207
223
|
timespan = current_time - last_poll
|
208
224
|
# How many ms have passed since last time
|
209
|
-
timespan_ms = timespan
|
225
|
+
timespan_ms = timespan * 1000
|
210
226
|
# How much have we changed/ms
|
211
227
|
change = (value - last_value) / timespan_ms.to_f
|
212
228
|
|
@@ -252,9 +268,9 @@ module Crubyflie
|
|
252
268
|
}
|
253
269
|
|
254
270
|
cf_range = {
|
255
|
-
:start =>
|
256
|
-
:end =>
|
257
|
-
:width =>
|
271
|
+
:start => THRUST_MIN,
|
272
|
+
:end => THRUST_MAX,
|
273
|
+
:width => THRUST_MAX - THRUST_MIN
|
258
274
|
}
|
259
275
|
return normalize(value, range, cf_range).round
|
260
276
|
end
|
@@ -269,17 +285,19 @@ module Crubyflie
|
|
269
285
|
def read_button(button_id)
|
270
286
|
return -1 if !@joystick
|
271
287
|
|
272
|
-
|
273
|
-
|
274
|
-
|
288
|
+
button = @config[:buttons][button_id]
|
289
|
+
last_poll = button[:last_poll] || 0
|
290
|
+
last_value = button[:last_value] || -1
|
291
|
+
pressed = @joystick.button(button_id)
|
292
|
+
value_pressed = button[:value]
|
275
293
|
current_time = Time.now.to_f
|
276
294
|
|
277
295
|
if (current_time - last_poll) > 0.5
|
278
|
-
|
279
|
-
|
280
|
-
return
|
296
|
+
button[:last_value] = value_pressed
|
297
|
+
button[:last_poll] = current_time
|
298
|
+
return pressed ? value_pressed : 0
|
281
299
|
else
|
282
|
-
return
|
300
|
+
return 0
|
283
301
|
end
|
284
302
|
end
|
285
303
|
private :read_button
|
@@ -304,7 +322,7 @@ module Crubyflie
|
|
304
322
|
from_w = from_range[:width]
|
305
323
|
# puts "#{to_min}+(#{value.to_f}-#{from_min})*(#{to_w}/#{from_w})
|
306
324
|
r = to_min + (value.to_f - from_min) * (to_w / from_w)
|
307
|
-
return r.round(
|
325
|
+
return r.round(2)
|
308
326
|
end
|
309
327
|
end
|
310
328
|
end
|
data/lib/crubyflie/version.rb
CHANGED
data/spec/input_reader_spec.rb
CHANGED
data/spec/joystick_cfg.yaml
CHANGED
@@ -1,23 +1,21 @@
|
|
1
|
-
# Default joystick configuration file. It mimics the PS3_Mode2 original
|
2
|
-
# configuration file
|
3
1
|
:type: "Joystick"
|
4
2
|
:axis:
|
5
3
|
0:
|
6
4
|
:description: "Roll Axis"
|
7
5
|
:action: :roll
|
8
|
-
:input_range: "-32768:32767"
|
9
|
-
:output_range: "-30:30"
|
10
|
-
:max_change_rate: 600
|
11
|
-
:dead_zone: "-100:100"
|
12
|
-
:invert: false
|
13
|
-
:calibration: 0
|
6
|
+
:input_range: "-32768:32767"
|
7
|
+
:output_range: "-30:30"
|
8
|
+
:max_change_rate: 600
|
9
|
+
:dead_zone: "-100:100"
|
10
|
+
:invert: false
|
11
|
+
:calibration: 0
|
14
12
|
1:
|
15
13
|
:description: "Pitch Axis"
|
16
14
|
:action: :pitch
|
17
15
|
:input_range: "-32768:32767"
|
18
16
|
:output_range: "-30:30"
|
19
|
-
:max_change_rate: 600
|
20
|
-
:dead_zone: "
|
17
|
+
:max_change_rate: 600
|
18
|
+
:dead_zone: "0:0"
|
21
19
|
:invert: true
|
22
20
|
:calibration: 0
|
23
21
|
2:
|
@@ -33,11 +31,9 @@
|
|
33
31
|
:description: "Thrust axis"
|
34
32
|
:action: :thrust
|
35
33
|
:input_range: "-32768:32767"
|
36
|
-
:output_range: "0:80"
|
37
|
-
# Max change rate per second when lowering thrust. Thrust level is
|
38
|
-
# ranges 9500 and 60000
|
34
|
+
:output_range: "0:80"
|
39
35
|
:max_change_rate: 40000
|
40
|
-
:dead_zone: "-100:100"
|
36
|
+
:dead_zone: "-100:100"
|
41
37
|
:invert: true
|
42
38
|
:calibration: 0
|
43
39
|
|
@@ -233,7 +233,7 @@ describe Joystick do
|
|
233
233
|
expect(@sdl_joystick).to receive(:axis).with(8).and_return(140)
|
234
234
|
@joystick.read_configuration('baa')
|
235
235
|
value = @joystick.read_axis(8)
|
236
|
-
value.should ==
|
236
|
+
value.should == 34497.5
|
237
237
|
end
|
238
238
|
|
239
239
|
it "should not throotle the change rate when increasing thrust" do
|
@@ -317,7 +317,7 @@ describe Joystick do
|
|
317
317
|
it "should return -1 when not pressed" do
|
318
318
|
expect(@sdl_joystick).to receive(:button).and_return(false)
|
319
319
|
v = @joystick.send(:read_button, 0)
|
320
|
-
v.should ==
|
320
|
+
v.should == 0
|
321
321
|
end
|
322
322
|
end
|
323
323
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: crubyflie
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Hector Sanjuan
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-08-
|
11
|
+
date: 2013-08-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: libusb
|