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.
- checksums.yaml +7 -0
- data/.gitignore +18 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +674 -0
- data/README.md +99 -0
- data/Rakefile +15 -0
- data/bin/crubyflie +85 -0
- data/configs/joystick_default.yaml +48 -0
- data/crubyflie.gemspec +50 -0
- data/examples/params_and_logging.rb +87 -0
- data/lib/crubyflie/crazyflie/commander.rb +54 -0
- data/lib/crubyflie/crazyflie/console.rb +67 -0
- data/lib/crubyflie/crazyflie/log.rb +383 -0
- data/lib/crubyflie/crazyflie/log_conf.rb +57 -0
- data/lib/crubyflie/crazyflie/param.rb +220 -0
- data/lib/crubyflie/crazyflie/toc.rb +239 -0
- data/lib/crubyflie/crazyflie/toc_cache.rb +87 -0
- data/lib/crubyflie/crazyflie.rb +282 -0
- data/lib/crubyflie/crazyradio/crazyradio.rb +301 -0
- data/lib/crubyflie/crazyradio/radio_ack.rb +48 -0
- data/lib/crubyflie/crubyflie_logger.rb +74 -0
- data/lib/crubyflie/driver/crtp_packet.rb +146 -0
- data/lib/crubyflie/driver/radio_driver.rb +333 -0
- data/lib/crubyflie/exceptions.rb +36 -0
- data/lib/crubyflie/input/input_reader.rb +168 -0
- data/lib/crubyflie/input/joystick_input_reader.rb +280 -0
- data/lib/crubyflie/version.rb +22 -0
- data/lib/crubyflie.rb +31 -0
- data/spec/commander_spec.rb +67 -0
- data/spec/console_spec.rb +76 -0
- data/spec/crazyflie_spec.rb +176 -0
- data/spec/crazyradio_spec.rb +226 -0
- data/spec/crtp_packet_spec.rb +79 -0
- data/spec/crubyflie_logger_spec.rb +39 -0
- data/spec/crubyflie_spec.rb +20 -0
- data/spec/input_reader_spec.rb +136 -0
- data/spec/joystick_cfg.yaml +48 -0
- data/spec/joystick_input_reader_spec.rb +238 -0
- data/spec/log_spec.rb +266 -0
- data/spec/param_spec.rb +166 -0
- data/spec/radio_ack_spec.rb +43 -0
- data/spec/radio_driver_spec.rb +227 -0
- data/spec/spec_helper.rb +51 -0
- data/spec/toc_cache_spec.rb +87 -0
- data/spec/toc_spec.rb +187 -0
- data/tools/sdl-joystick-axis.rb +69 -0
- 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
|