crubyflie 0.1.2 → 0.1.3
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 +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
|