crubyflie 0.1.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.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +674 -0
  5. data/README.md +99 -0
  6. data/Rakefile +15 -0
  7. data/bin/crubyflie +85 -0
  8. data/configs/joystick_default.yaml +48 -0
  9. data/crubyflie.gemspec +50 -0
  10. data/examples/params_and_logging.rb +87 -0
  11. data/lib/crubyflie/crazyflie/commander.rb +54 -0
  12. data/lib/crubyflie/crazyflie/console.rb +67 -0
  13. data/lib/crubyflie/crazyflie/log.rb +383 -0
  14. data/lib/crubyflie/crazyflie/log_conf.rb +57 -0
  15. data/lib/crubyflie/crazyflie/param.rb +220 -0
  16. data/lib/crubyflie/crazyflie/toc.rb +239 -0
  17. data/lib/crubyflie/crazyflie/toc_cache.rb +87 -0
  18. data/lib/crubyflie/crazyflie.rb +282 -0
  19. data/lib/crubyflie/crazyradio/crazyradio.rb +301 -0
  20. data/lib/crubyflie/crazyradio/radio_ack.rb +48 -0
  21. data/lib/crubyflie/crubyflie_logger.rb +74 -0
  22. data/lib/crubyflie/driver/crtp_packet.rb +146 -0
  23. data/lib/crubyflie/driver/radio_driver.rb +333 -0
  24. data/lib/crubyflie/exceptions.rb +36 -0
  25. data/lib/crubyflie/input/input_reader.rb +168 -0
  26. data/lib/crubyflie/input/joystick_input_reader.rb +280 -0
  27. data/lib/crubyflie/version.rb +22 -0
  28. data/lib/crubyflie.rb +31 -0
  29. data/spec/commander_spec.rb +67 -0
  30. data/spec/console_spec.rb +76 -0
  31. data/spec/crazyflie_spec.rb +176 -0
  32. data/spec/crazyradio_spec.rb +226 -0
  33. data/spec/crtp_packet_spec.rb +79 -0
  34. data/spec/crubyflie_logger_spec.rb +39 -0
  35. data/spec/crubyflie_spec.rb +20 -0
  36. data/spec/input_reader_spec.rb +136 -0
  37. data/spec/joystick_cfg.yaml +48 -0
  38. data/spec/joystick_input_reader_spec.rb +238 -0
  39. data/spec/log_spec.rb +266 -0
  40. data/spec/param_spec.rb +166 -0
  41. data/spec/radio_ack_spec.rb +43 -0
  42. data/spec/radio_driver_spec.rb +227 -0
  43. data/spec/spec_helper.rb +51 -0
  44. data/spec/toc_cache_spec.rb +87 -0
  45. data/spec/toc_spec.rb +187 -0
  46. data/tools/sdl-joystick-axis.rb +69 -0
  47. metadata +222 -0
@@ -0,0 +1,226 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright (C) 2013 Hector Sanjuan
3
+
4
+ # This file is part of Crubyflie.
5
+
6
+ # Crubyflie is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+
11
+ # Crubyflie is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with Crubyflie. If not, see <http://www.gnu.org/licenses/>
18
+
19
+ require 'crazyradio/crazyradio'
20
+
21
+ describe Crazyradio do
22
+ before :each do
23
+ @device = double("LIBUSB::Device")
24
+ @handle = double("LIBUSB::DevHandler")
25
+
26
+ allow(@device).to receive(:is_a?).and_return(LIBUSB::Device)
27
+ allow(@device).to receive(:open).and_return(@handle)
28
+ allow(@device).to receive(:serial_number).and_return("serial123")
29
+ allow(@device).to receive(:manufacturer).and_return("Bitcraze")
30
+ allow(@handle).to receive(:configuration=)
31
+ allow(@handle).to receive(:claim_interface)
32
+ tr_result = [1,2,3].pack('C*')
33
+ allow(@handle).to receive(:control_transfer).and_return(tr_result)
34
+ allow(@handle).to receive(:release_interface)
35
+ allow(@handle).to receive(:reset_device)
36
+ allow(@handle).to receive(:close)
37
+
38
+ @crazyradio = Crazyradio.new(@device)
39
+ end
40
+
41
+ describe "#initialize" do
42
+ it "should initialize the dongle correctly" do
43
+ settings = [:data_rate, :channel, :cont_carrier,
44
+ :address, :power, :arc, :ard_bytes]
45
+ ssize = settings.size
46
+ expect(@device).to receive(:open)
47
+ expect(@handle).to receive(:configuration=).with(1)
48
+ expect(@handle).to receive(:claim_interface).with(0)
49
+ expect(@handle).to receive(:control_transfer).exactly(ssize).times
50
+ crazyradio = Crazyradio.new(@device)
51
+ defaults = Crazyradio::DEFAULT_SETTINGS
52
+ settings.each do |setting|
53
+ crazyradio[setting].should == defaults[setting]
54
+ end
55
+ end
56
+
57
+ it "should not initialize with a nil device" do
58
+ expect { Crazyradio.new() }.to raise_error(USBDongleException,
59
+ "Wrong USB device")
60
+ end
61
+ end
62
+
63
+ describe "#status" do
64
+ it "should return a status" do
65
+ allow(Crazyradio).to receive(:factory).and_return(@crazyradio)
66
+ status = "Found serial123 USB dongle from Bitcraze"
67
+ Crazyradio.status().should == status
68
+ end
69
+ end
70
+
71
+ describe "#close" do
72
+ it "should close the USB" do
73
+ expect(@handle).to receive(:release_interface).with(0)
74
+ expect(@handle).to receive(:reset_device)
75
+ #expect(@handle).to receive(:close)
76
+ @crazyradio.close()
77
+ end
78
+ end
79
+
80
+ describe "#has_fw_scan" do
81
+ it "should say false" do
82
+ @crazyradio.has_fw_scan.should be_false
83
+ end
84
+ end
85
+
86
+ describe "#scan_channels" do
87
+ it "should scan channels and return them" do
88
+ ack = RadioAck.new(true)
89
+ do_this = receive(:send_packet).with([0xFF]).and_return(ack)
90
+ allow(@crazyradio).to do_this
91
+ @crazyradio.scan_channels(0, 125).should == (0..125).to_a
92
+ end
93
+
94
+ it "should scan channels with fw_scan and return them" do
95
+ allow(@crazyradio).to receive(:has_fw_scan).and_return(true)
96
+ @crazyradio.scan_channels(0, 125).should == [1,2,3]
97
+ end
98
+
99
+ it "should not include bad channels in a scan" do
100
+ ack = RadioAck.new(false)
101
+ do_this = receive(:send_packet).with([0xFF]).and_return(ack)
102
+ allow(@crazyradio).to do_this
103
+ @crazyradio.scan_channels(0, 125).should == []
104
+ end
105
+ end
106
+
107
+ describe "#factory" do
108
+ it "should raise an exception if no dongles are found" do
109
+ do_this = receive(:devices).and_return([])
110
+ allow_any_instance_of(LIBUSB::Context).to do_this
111
+
112
+ expect { Crazyradio.factory() }.to raise_error(USBDongleException,
113
+ "No dongles found")
114
+ end
115
+
116
+ it "should provide a new crazyradio item" do
117
+ do_this = receive(:devices).and_return([@device])
118
+ allow_any_instance_of(LIBUSB::Context).to do_this
119
+ Crazyradio.factory()
120
+ end
121
+ end
122
+
123
+ describe "#send_packet" do
124
+ it "should send a packet and get a response" do
125
+ dataout = { :endpoint => 1, :dataOut => [1,2,3,4,5].pack('C*')}
126
+ datain = { :endpoint => 0x81, :dataIn => 64}
127
+ response = ([0xFF] * 64).pack('C*')
128
+ do_this = receive(:bulk_transfer)
129
+ expect(@handle).to do_this.with(dataout).and_return(response)
130
+ expect(@handle).to do_this.with(datain).and_return(response)
131
+
132
+ ack = @crazyradio.send_packet([1,2,3,4,5])
133
+ ack.should be_an_instance_of RadioAck
134
+ ack.ack.should == true
135
+ ack.data.should == [0xFF] * 63
136
+ end
137
+ end
138
+
139
+ describe "#[]=" do
140
+ it "should set a setting" do
141
+ expect(@crazyradio).to receive(:set_data_rate).with(58)
142
+ @crazyradio[:data_rate] = 58
143
+ end
144
+ it "should no set a bad setting" do
145
+ expect(@crazyradio).not_to receive(:set_data_rate)
146
+ expect(@crazyradio).not_to receive(:set_channel)
147
+ expect(@crazyradio).not_to receive(:set_arc)
148
+ expect(@crazyradio).not_to receive(:set_cont_carrier)
149
+ expect(@crazyradio).not_to receive(:set_address)
150
+ expect(@crazyradio).not_to receive(:set_power)
151
+ expect(@crazyradio).not_to receive(:set_ard_bytes)
152
+ @crazyradio[:abc] = 3
153
+ @crazyradio[:abc].should be_nil
154
+ end
155
+ end
156
+
157
+ describe "[]" do
158
+ it "should get a setting value" do
159
+ expected = Crazyradio::DEFAULT_SETTINGS[:channel]
160
+ @crazyradio[:channel].should == expected
161
+ end
162
+ end
163
+
164
+ describe "#apply_settings" do
165
+ it "should apply one setting" do
166
+ d = Crazyradio::DEFAULT_SETTINGS
167
+ expect(@crazyradio).to receive(:set_channel).with(d[:channel])
168
+ expect(@crazyradio).to receive(:set_data_rate).with(d[:data_rate])
169
+ expect(@crazyradio).to receive(:set_arc).with(d[:arc])
170
+ scr = :set_cont_carrier
171
+ expect(@crazyradio).to receive(scr).with(d[:cont_carrier])
172
+ expect(@crazyradio).to receive(:set_address).with(d[:address])
173
+ expect(@crazyradio).to receive(:set_power).with(d[:power])
174
+ expect(@crazyradio).to receive(:set_ard_bytes).with(d[:ard_bytes])
175
+ @crazyradio.apply_settings(:channel)
176
+ @crazyradio.apply_settings(:data_rate)
177
+ @crazyradio.apply_settings(:arc)
178
+ @crazyradio.apply_settings(:cont_carrier)
179
+ @crazyradio.apply_settings(:power)
180
+ @crazyradio.apply_settings(:ard_bytes)
181
+ @crazyradio.apply_settings(:address)
182
+ end
183
+
184
+ it "should apply all settings" do
185
+ d = Crazyradio::DEFAULT_SETTINGS
186
+ expect(@crazyradio).to receive(:set_channel).with(d[:channel])
187
+ expect(@crazyradio).to receive(:set_data_rate).with(d[:data_rate])
188
+ expect(@crazyradio).to receive(:set_arc).with(d[:arc])
189
+ scr = :set_cont_carrier
190
+ expect(@crazyradio).to receive(scr).with(d[:cont_carrier])
191
+ expect(@crazyradio).to receive(:set_address).with(d[:address])
192
+ expect(@crazyradio).to receive(:set_power).with(d[:power])
193
+ expect(@crazyradio).to receive(:set_ard_bytes).with(d[:ard_bytes])
194
+ @crazyradio.apply_settings()
195
+ end
196
+ end
197
+
198
+ describe "#send_vendor_setup" do
199
+ it "should make a control_transfer with the proper args set" do
200
+ args = {
201
+ :bmRequestType => LIBUSB::REQUEST_TYPE_VENDOR,
202
+ :bRequest => 38,
203
+ :wValue => 3,
204
+ :wIndex => 2,
205
+ :dataOut => ""
206
+ }
207
+ expect(@handle).to receive(:control_transfer).with(args)
208
+ @crazyradio.send(:send_vendor_setup, 38, 3, 2)
209
+ end
210
+ end
211
+
212
+ describe "#get_vendor_setup" do
213
+ it "should make a control_transfer with the proper args set" do
214
+ args = {
215
+ :bmRequestType => LIBUSB::REQUEST_TYPE_VENDOR | 0x80,
216
+ :bRequest => 38,
217
+ :wValue => 3,
218
+ :wIndex => 2,
219
+ :dataIn => 0
220
+ }
221
+ expect(@handle).to receive(:control_transfer).with(args)
222
+ resp = @crazyradio.send(:get_vendor_setup, 38, 3, 2)
223
+ resp.should == [1,2,3]
224
+ end
225
+ end
226
+ end
@@ -0,0 +1,79 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright (C) 2013 Hector Sanjuan
3
+
4
+ # This file is part of Crubyflie.
5
+
6
+ # Crubyflie is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+
11
+ # Crubyflie is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with Crubyflie. If not, see <http://www.gnu.org/licenses/>
18
+
19
+ require 'driver/crtp_packet'
20
+
21
+ describe CRTPPacket do
22
+ describe "#initalize" do
23
+ it "should initialize correctly a packet" do
24
+ header = 0b11101010 # channel 10; port 1110
25
+ payload = [1,2,3]
26
+ packet = CRTPPacket.new(header, payload)
27
+ packet.size.should == 3
28
+ packet.header.should == header
29
+ packet.data.should == payload
30
+ packet.channel.should == 0b10
31
+ packet.port.should == 0b1110
32
+ end
33
+ end
34
+
35
+ describe "#modify_header" do
36
+ it "should modify only with header if provided" do
37
+ header = 0b11101010 # channel 10; port 1110
38
+ payload = [1,2,3]
39
+ packet = CRTPPacket.new(header, payload)
40
+ packet.modify_header(0, 3, 4)
41
+ packet.header.should == 0
42
+ packet.channel.should == 0
43
+ packet.port.should == 0
44
+ end
45
+
46
+ it "should modify channel and port and set the header" do
47
+ channel = 0b10
48
+ port = 0b1101
49
+ payload = [1,2,3]
50
+ packet = CRTPPacket.new(0, payload)
51
+ packet.modify_header(nil, port, channel)
52
+ packet.header.should == 0b11010010
53
+ packet.channel.should == 0b10
54
+ packet.port.should == 0b1101
55
+ end
56
+ end
57
+
58
+ describe "#unpack" do
59
+ it "should return an empty package if data is empty or not array" do
60
+ CRTPPacket.unpack("abc").pack.should == [0]
61
+ CRTPPacket.unpack([]).pack.should == [0]
62
+ end
63
+
64
+ it "should unpack a data array correctly into header and data" do
65
+ packet = CRTPPacket.unpack([1,2,3])
66
+ packet.data.should == [2,3]
67
+ packet.header.should == 1
68
+ end
69
+ end
70
+
71
+ describe "#pack" do
72
+ it "should concat header and data" do
73
+ header = 0b11101010 # channel 10; port 1110
74
+ payload = [1,2,3]
75
+ packet = CRTPPacket.new(header, payload)
76
+ packet.pack.should == [0b11101010, 1, 2, 3]
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,39 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright (C) 2013 Hector Sanjuan
3
+
4
+ # This file is part of Crubyflie.
5
+
6
+ # Crubyflie is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+
11
+ # Crubyflie is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with Crubyflie. If not, see <http://www.gnu.org/licenses/>
18
+
19
+ describe Logging do
20
+ it "should provide a logger" do
21
+ include Logging
22
+ logger.should be_an_instance_of CrubyflieLogger
23
+ end
24
+ end
25
+
26
+ describe CrubyflieLogger do
27
+
28
+ it "should log to debug, info, warn" do
29
+ l = CrubyflieLogger.new(true)
30
+ expect($stderr).to receive(:puts).with("DEBUG: a")
31
+ expect($stdout).to receive(:puts).with("INFO: a")
32
+ expect($stderr).to receive(:puts).with("ERROR: a")
33
+ expect($stderr).to receive(:puts).with("WARNING: a")
34
+ l.debug "a"
35
+ l.info "a"
36
+ l.warn "a"
37
+ l.error "a"
38
+ end
39
+ end
@@ -0,0 +1,20 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright (C) 2013 Hector Sanjuan
3
+
4
+ # This file is part of Crubyflie.
5
+
6
+ # Crubyflie is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+
11
+ # Crubyflie is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with Crubyflie. If not, see <http://www.gnu.org/licenses/>
18
+
19
+ require 'rspec'
20
+ require_relative 'spec_helper'
@@ -0,0 +1,136 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Copyright (C) 2013 Hector Sanjuan
3
+
4
+ # This file is part of Crubyflie.
5
+
6
+ # Crubyflie is free software: you can redistribute it and/or modify
7
+ # it under the terms of the GNU General Public License as published by
8
+ # the Free Software Foundation, either version 3 of the License, or
9
+ # (at your option) any later version.
10
+
11
+ # Crubyflie is distributed in the hope that it will be useful,
12
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ # GNU General Public License for more details.
15
+
16
+ # You should have received a copy of the GNU General Public License
17
+ # along with Crubyflie. If not, see <http://www.gnu.org/licenses/>
18
+
19
+ describe InputReader do
20
+
21
+ before :each do
22
+ @sdl_joystick = double("Joystick")
23
+ allow(SDL::Joystick).to receive(:update_all)
24
+ allow(SDL).to receive(:init).with(SDL::INIT_JOYSTICK)
25
+ allow(SDL::Joystick).to receive(:num).and_return(3)
26
+ allow(SDL::Joystick).to receive(:open).and_return(@sdl_joystick)
27
+ allow(SDL::Joystick).to receive(:index_name).and_return("My Joystick")
28
+ allow(SDL::Joystick).to receive(:poll).with(false)
29
+ expect(SDL::Joystick).not_to receive(:poll).with(true)
30
+ path = File.join(File.dirname(__FILE__), 'joystick_cfg.yaml')
31
+ @joystick = Joystick.new(path)
32
+
33
+ @logger = @joystick.logger
34
+ allow(@logger).to receive(:info)
35
+ @joystick.init()
36
+
37
+ @cf = double("Crazyflie")
38
+ end
39
+
40
+ describe "#read_input" do
41
+ it "should read axis and buttons" do
42
+ do_this = receive(:axis).and_return(0,32768,0,-32767)
43
+ do_this = do_this.exactly(4).times
44
+ expect(@sdl_joystick).to do_this
45
+
46
+ expect(@sdl_joystick).to receive(:button) { |arg|
47
+ false
48
+ }.twice
49
+
50
+ @joystick.read_input()
51
+ @joystick.axis_readings.should == {
52
+ :roll => 0,
53
+ :pitch => -30,
54
+ :yaw => 0,
55
+ :thrust => 49900
56
+ }
57
+
58
+ @joystick.button_readings.should == {
59
+ :switch_xmode => -1,
60
+ :close_link => -1
61
+ }
62
+ end
63
+ end
64
+
65
+
66
+ describe "#apply_input" do
67
+ it "should apply the read input to an active crazyflie" do
68
+ do_this = receive(:axis).and_return(0,32768,0,-32767)
69
+ do_this = do_this.exactly(4).times
70
+ expect(@sdl_joystick).to do_this
71
+
72
+ expect(@sdl_joystick).to receive(:button) { |arg|
73
+ false
74
+ }.twice
75
+
76
+ expect(@cf).to receive(:active?).and_return(true).twice
77
+ cmder = double("Commander")
78
+ expect(@cf).to receive(:commander).and_return(cmder)
79
+ expect(cmder).to receive(:send_setpoint).with(0, -30, 0,
80
+ 49900, false)
81
+ @joystick.read_input()
82
+ @joystick.apply_input(@cf)
83
+ end
84
+
85
+ it "should not send commands to a non active crazyflie" do
86
+ do_this = receive(:axis).and_return(0,32768,0,-32767)
87
+ do_this = do_this.exactly(4).times
88
+ expect(@sdl_joystick).to do_this
89
+
90
+ expect(@sdl_joystick).to receive(:button) { |arg|
91
+ false
92
+ }.twice
93
+
94
+ expect(@cf).to receive(:active?).and_return(false)
95
+ expect(@cf).not_to receive(:commander)
96
+ @joystick.read_input()
97
+ @joystick.apply_input(@cf)
98
+ end
99
+
100
+ it "should close the link to the crazyflie" do
101
+ do_this = receive(:axis).and_return(0,32768,0,-32767)
102
+ do_this = do_this.exactly(4).times
103
+ expect(@sdl_joystick).to do_this
104
+
105
+ expect(@sdl_joystick).to receive(:button) { |arg|
106
+ arg == 0 ? false : true
107
+ }.twice
108
+
109
+ expect(@cf).to receive(:active?).and_return(true, false).twice
110
+ expect(@cf).not_to receive(:commander)
111
+ expect(@cf).to receive(:close_link)
112
+ @joystick.read_input()
113
+ @joystick.apply_input(@cf)
114
+ end
115
+
116
+ it "should enable xmode" do
117
+ do_this = receive(:axis).and_return(0,32768,0,-32767)
118
+ do_this = do_this.exactly(4).times
119
+ expect(@sdl_joystick).to do_this
120
+
121
+ expect(@sdl_joystick).to receive(:button) { |arg|
122
+ arg == 1 ? false : true
123
+ }.twice
124
+
125
+ expect(@cf).to receive(:active?).and_return(true).twice
126
+ cmder = double("Commander")
127
+ expect(@cf).to receive(:commander).and_return(cmder)
128
+ expect(cmder).to receive(:send_setpoint).with(0, -30, 0,
129
+ 49900, true)
130
+ @joystick.read_input()
131
+ @joystick.apply_input(@cf)
132
+ @joystick.xmode.should == true
133
+ end
134
+ end
135
+
136
+ end
@@ -0,0 +1,48 @@
1
+ # Default joystick configuration file. It mimics the PS3_Mode2 original
2
+ # configuration file
3
+ :type: "Joystick"
4
+ :axis:
5
+ 0:
6
+ :description: "Roll Axis"
7
+ :action: :roll
8
+ :input_range: "-32768:32767" # Optional - SDL dependant. Defaults to this.
9
+ :output_range: "-30:30" # Min/Max crazyflie angle in degrees.
10
+ :max_change_rate: 600 # Max angle change rate per second. Optional
11
+ :dead_zone: "-100:100" # Deadzone, within input range
12
+ :invert: false # Invert the axis
13
+ :calibration: 0 # This value is added to the raw value read from joystick
14
+ 1:
15
+ :description: "Pitch Axis"
16
+ :action: :pitch
17
+ :input_range: "-32768:32767"
18
+ :output_range: "-30:30"
19
+ :max_change_rate: 600 # Max angle change rate per second. Optional
20
+ :dead_zone: "-100:100" # Deadzone, within input range
21
+ :invert: true
22
+ :calibration: 0
23
+ 2:
24
+ :description: "Yaw Axis"
25
+ :action: :yaw
26
+ :input_range: "-32768:32767"
27
+ :output_range: "-30:30"
28
+ :max_change_rate: 800
29
+ :dead_zone: "-1000:1000"
30
+ :invert: false
31
+ :calibration: 0
32
+ 3:
33
+ :description: "Thrust axis"
34
+ :action: :thrust
35
+ :input_range: "-32768:32767"
36
+ :output_range: "0:80" # Min/max thrust output is represented in 0-100%
37
+ # Max change rate per second when lowering thrust. Thrust level is
38
+ # ranges 9500 and 60000
39
+ :max_change_rate: 40000
40
+ :dead_zone: "-100:100" # Deadzone, within input range
41
+ :invert: true
42
+ :calibration: 0
43
+
44
+ :buttons:
45
+ 0:
46
+ :action: :switch_xmode
47
+ 1:
48
+ :action: :close_link