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
data/README.md
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
Crubyflie - A Ruby client and libraries for Crazyflie
|
2
|
+
=====================================================
|
3
|
+
|
4
|
+
Crubyflie is a Ruby rewrite of the [Crazyflie quadcopter](http://www.bitcraze.se/category/crazyflie/) Python [client libraries](https://bitbucket.org/bitcraze/crazyflie-pc-client), with some customizations.
|
5
|
+
|
6
|
+
The Crazyflie is awesome, but I did not know where to start contributing. Therefore I thought that rewriting the code in Ruby would be one way of knowing what is going on and how it works. Along the way I took the time to document all the code so that others can understand it and create tests.
|
7
|
+
|
8
|
+
Disclaimer
|
9
|
+
----------
|
10
|
+
|
11
|
+
Crubyflie is in early stage of development, very untested.
|
12
|
+
|
13
|
+
Features
|
14
|
+
--------
|
15
|
+
|
16
|
+
* Crubyflie can be used to fly a Crazyflie device using a Joystick and the Crazyradio USB dongle
|
17
|
+
* Crubyflie exposes an API that allows to control the copter, read logging, parameters and console easily
|
18
|
+
* Crubyflie runs headless
|
19
|
+
|
20
|
+
Not included...
|
21
|
+
----------------
|
22
|
+
* No fancy UI.
|
23
|
+
* No flash utility (yet?).
|
24
|
+
* 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.
|
25
|
+
* 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).
|
26
|
+
|
27
|
+
Fyling the Crazyflie
|
28
|
+
--------------------
|
29
|
+
|
30
|
+
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):
|
31
|
+
|
32
|
+
> crubyflie2.0 -h
|
33
|
+
Options:
|
34
|
+
--joystick-id, -j <i>: Joystick ID (default: 0)
|
35
|
+
--cf-uri, -f <s>: Crazyflie URI (defaults to first one found in scan)
|
36
|
+
--config, -c <s>: Joystick configuration, defaults to default cfg in configs/ (default:
|
37
|
+
/usr/lib64/ruby/gems/2.0.0/gems/crubyflie-0.0.1/lib/crubyflie/input/../../../configs/joystick_default.yaml)
|
38
|
+
--help, -h: Show this message
|
39
|
+
|
40
|
+
A template/default configuration file (which works for me and my PS3-like controller :)) is provided with the gem (in the `configs/` folder). 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.
|
41
|
+
|
42
|
+
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.
|
43
|
+
|
44
|
+
If you need help just open an issue or contact me.
|
45
|
+
|
46
|
+
Using the Crazyflie API
|
47
|
+
-----------------------
|
48
|
+
|
49
|
+
While both Python and Ruby APIs expose access to params, logging, console and commander facilities, Crubyflie does it in sligthly different way.
|
50
|
+
|
51
|
+
Crubyflie access to facilities is offered fully under the Crazyflie instance object, let's see it as code:
|
52
|
+
|
53
|
+
```ruby
|
54
|
+
require 'crubyflie'
|
55
|
+
include Crubyflie
|
56
|
+
|
57
|
+
# Connect
|
58
|
+
@cf = Crazyflie.new()
|
59
|
+
@cf.open_link(@radio_uri)
|
60
|
+
|
61
|
+
# Interface to the logging facility
|
62
|
+
@cf.log.create_log_block(...)
|
63
|
+
@cf.log.start_logging(...) do |log_values|
|
64
|
+
...
|
65
|
+
end
|
66
|
+
@cf.log.stop_logging(...)
|
67
|
+
@cf.log.delete_log(...)
|
68
|
+
|
69
|
+
|
70
|
+
# Interface to the param facility
|
71
|
+
@cf.param.get_value(...) do |value|
|
72
|
+
...
|
73
|
+
end
|
74
|
+
|
75
|
+
@cf.param.get_value(...) do |value|
|
76
|
+
...
|
77
|
+
end
|
78
|
+
|
79
|
+
@cf.param.set_value(...)
|
80
|
+
|
81
|
+
# Interface to the commander facility
|
82
|
+
@cf.commander.send_setpoint(...)
|
83
|
+
|
84
|
+
# Interface to the console facility
|
85
|
+
@cf.console.read do |value|
|
86
|
+
...
|
87
|
+
end
|
88
|
+
```
|
89
|
+
|
90
|
+
That's pretty much all. As you see, instead of declaring callbacks, registering them etc. We let the user pass blocks, which are run when the data is available.
|
91
|
+
In Crubyflie, params are read and set synchronously, while the block passed to `start_logging()` will be called repeteadly and asynchrnously until `stop_logging()` is invoked. Console offers both synchronous `read()` and asynchronous `start_reading()` options.
|
92
|
+
|
93
|
+
There are some examples in the `examples` folder. Read the gem documentation to get full information of the parameters for each function call.
|
94
|
+
|
95
|
+
|
96
|
+
Contributing
|
97
|
+
------------
|
98
|
+
|
99
|
+
Contributions are awesome! :) I'd love some help here, so be invited to open issues, send pull requests or give me your opinion.
|
data/Rakefile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
2
|
+
require "rspec/core/rake_task"
|
3
|
+
require "yard"
|
4
|
+
require "yard/rake/yardoc_task"
|
5
|
+
|
6
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
7
|
+
t.pattern = 'spec/crubyflie_spec.rb'
|
8
|
+
end
|
9
|
+
|
10
|
+
YARD::Rake::YardocTask.new(:yard)
|
11
|
+
|
12
|
+
task :doc => :yard
|
13
|
+
task :test => :spec
|
14
|
+
task :default => [:spec, :doc]
|
15
|
+
|
data/bin/crubyflie
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
# Copyright (C) 2013 Hector Sanjuan
|
4
|
+
|
5
|
+
# This file is part of Crubyflie.
|
6
|
+
|
7
|
+
# Crubyflie is free software: you can redistribute it and/or modify
|
8
|
+
# it under the terms of the GNU General Public License as published by
|
9
|
+
# the Free Software Foundation, either version 3 of the License, or
|
10
|
+
# (at your option) any later version.
|
11
|
+
|
12
|
+
# Crubyflie is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU General Public License for more details.
|
16
|
+
|
17
|
+
# You should have received a copy of the GNU General Public License
|
18
|
+
# along with Crubyflie. If not, see <http://www.gnu.org/licenses/>
|
19
|
+
|
20
|
+
require 'crubyflie'
|
21
|
+
require 'trollop'
|
22
|
+
|
23
|
+
# This script allows to fly the Crazyflie usingi the Joystick controller
|
24
|
+
# and initializing a Crazyflie. It might need a bit of cleanup but it does
|
25
|
+
# the job.
|
26
|
+
|
27
|
+
opts = Trollop::options do
|
28
|
+
opt(:joystick_id, "Joystick ID",
|
29
|
+
:type => :int,
|
30
|
+
:default => 0,
|
31
|
+
:short => '-j')
|
32
|
+
opt(:cf_uri, "Crazyflie URI (defaults to first one found in scan)",
|
33
|
+
:type => :string,
|
34
|
+
:short => '-f')
|
35
|
+
opt(:config, "Joystick configuration, defaults to default cfg in configs/",
|
36
|
+
:type => :string,
|
37
|
+
:default => Crubyflie::Joystick::DEFAULT_CONFIG_PATH,
|
38
|
+
:short => '-c')
|
39
|
+
end
|
40
|
+
|
41
|
+
include Crubyflie
|
42
|
+
# Uncomment to turn on debugging
|
43
|
+
# $debug = true
|
44
|
+
cf = Crazyflie.new('/tmp/crubyflie')
|
45
|
+
|
46
|
+
# Before opening any link, scan for interfaces
|
47
|
+
uris = cf.scan_interface
|
48
|
+
if uris.empty?
|
49
|
+
logger.error("No crazyflies found")
|
50
|
+
exit 1
|
51
|
+
end
|
52
|
+
logger.info("Found copters at: #{uris}")
|
53
|
+
if uri = opts[:cf_uri] && !uris.include?(opts[:cf_uri])
|
54
|
+
logger.error("Provided URI not found")
|
55
|
+
exit 1
|
56
|
+
end
|
57
|
+
|
58
|
+
uri ||= uris.first
|
59
|
+
|
60
|
+
# Open a link to the copter
|
61
|
+
cf.open_link(uri)
|
62
|
+
# Make sure everything is still good
|
63
|
+
exit 1 if !cf.active?
|
64
|
+
|
65
|
+
# Initialize the joystick - ID defaults to 0
|
66
|
+
joystick = Joystick.new(opts[:config], opts[:joystick_id])
|
67
|
+
joystick.init()
|
68
|
+
|
69
|
+
exit = false
|
70
|
+
Signal.trap("SIGINT") do
|
71
|
+
exit = true
|
72
|
+
end
|
73
|
+
|
74
|
+
while cf.active? && !exit do
|
75
|
+
# We should be good sending 10 ticks per second
|
76
|
+
# it says that somewhere in the docs
|
77
|
+
joystick.read_input()
|
78
|
+
joystick.apply_input(cf)
|
79
|
+
sleep 0.1
|
80
|
+
end
|
81
|
+
|
82
|
+
joystick.quit()
|
83
|
+
cf.close_link()
|
84
|
+
warn "\n"
|
85
|
+
logger.info("Bye bye!")
|
@@ -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
|
20
|
+
:dead_zone: "-100:100"
|
21
|
+
:invert: true
|
22
|
+
:calibration: 0
|
23
|
+
2:
|
24
|
+
:description: "Yaw Axis"
|
25
|
+
:action: :yaw
|
26
|
+
:input_range: "-32768:32767"
|
27
|
+
:output_range: "-200:200"
|
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" # Exception: Min/max thrust output is represented in 0-100%!
|
37
|
+
# Max change rate per second when lowering thrust. Note that this
|
38
|
+
# is a change ranging between 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
|
data/crubyflie.gemspec
ADDED
@@ -0,0 +1,50 @@
|
|
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
|
+
lib = File.expand_path('../lib', __FILE__)
|
20
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
21
|
+
require 'crubyflie/version'
|
22
|
+
|
23
|
+
Gem::Specification.new do |spec|
|
24
|
+
spec.name = "crubyflie"
|
25
|
+
spec.version = Crubyflie::VERSION
|
26
|
+
spec.authors = ["Hector Sanjuan"]
|
27
|
+
spec.email = ["hector@convivencial.org"]
|
28
|
+
spec.description = <<EOF
|
29
|
+
Client library to control a Crazyflie. This library allows to talk to a
|
30
|
+
crazyflie using the USB radio dongle.
|
31
|
+
EOF
|
32
|
+
spec.summary = "Crazyflie ruby client"
|
33
|
+
spec.homepage = "https://github.com/hsanjuan/crubyflie"
|
34
|
+
spec.license = "GPLv3"
|
35
|
+
|
36
|
+
spec.files = `git ls-files`.split($/)
|
37
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
38
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
39
|
+
spec.require_paths = ["lib"]
|
40
|
+
|
41
|
+
spec.add_dependency "libusb"
|
42
|
+
spec.add_dependency "rubysdl"
|
43
|
+
spec.add_dependency "trollop"
|
44
|
+
|
45
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
46
|
+
spec.add_development_dependency "rake"
|
47
|
+
spec.add_development_dependency "rspec"
|
48
|
+
spec.add_development_dependency "yard"
|
49
|
+
spec.add_development_dependency "simplecov"
|
50
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
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 the Crubyflie gem
|
20
|
+
require 'crubyflie'
|
21
|
+
include Crubyflie # easy to use things in namespace
|
22
|
+
|
23
|
+
# Create a new Crazyflie with cache folder "cache"
|
24
|
+
cf = Crazyflie.new('cache')
|
25
|
+
# Before opening any link, scan for interfaces
|
26
|
+
ifaces = cf.scan_interface
|
27
|
+
if ifaces.empty?
|
28
|
+
logger.error("No crazyflies found")
|
29
|
+
exit 1
|
30
|
+
end
|
31
|
+
logger.info("Found interfaces: #{ifaces}")
|
32
|
+
|
33
|
+
# Open a link to the first interface
|
34
|
+
cf.open_link(ifaces.first)
|
35
|
+
# Make sure everything is still good
|
36
|
+
exit 1 if !cf.active?
|
37
|
+
|
38
|
+
# Write the TOCs to stdout
|
39
|
+
puts "Log TOC"
|
40
|
+
puts cf.log.toc.to_s
|
41
|
+
puts
|
42
|
+
puts "Param TOC"
|
43
|
+
puts cf.param.toc.to_s
|
44
|
+
|
45
|
+
# Read some parameters
|
46
|
+
puts "--------"
|
47
|
+
cf.param.get_value("attitudepid.kp_pitch") do |value|
|
48
|
+
puts "kp_pitch: #{value}"
|
49
|
+
end
|
50
|
+
cf.param.get_value("attitudepid.ki_pitch") do |value|
|
51
|
+
puts "ki_pitch: #{value}"
|
52
|
+
end
|
53
|
+
cf.param.get_value("attitudepid.kd_pitch") do |value|
|
54
|
+
puts "kd_pitch: #{value}"
|
55
|
+
end
|
56
|
+
puts "--------"
|
57
|
+
|
58
|
+
|
59
|
+
# We use 1 variable, is_toc = true
|
60
|
+
# The last two 7 means it is stored and fetched as float
|
61
|
+
log_conf_var = LogConfVariable.new("stabilizer.pitch", true, 7, 7)
|
62
|
+
|
63
|
+
# We create a configuration object
|
64
|
+
# We want to fetch it every 0.1 secs
|
65
|
+
log_conf = LogConf.new([log_conf_var], {:period => 10})
|
66
|
+
|
67
|
+
# With the configuration object, register a log_block
|
68
|
+
block_id = cf.log.create_log_block(log_conf)
|
69
|
+
|
70
|
+
# Start logging
|
71
|
+
# Counter on how many times we have logged the pitch
|
72
|
+
logged = 0
|
73
|
+
cf.log.start_logging(block_id) do |data|
|
74
|
+
warn "Pitch: #{data['stabilizer.pitch']}"
|
75
|
+
logged += 1
|
76
|
+
end
|
77
|
+
|
78
|
+
# Wait until we have hit the log_cb 10 times
|
79
|
+
while (logged < 10)
|
80
|
+
sleep 1
|
81
|
+
end
|
82
|
+
|
83
|
+
# Stop logging
|
84
|
+
cf.log.stop_logging(block_id)
|
85
|
+
|
86
|
+
# After finishing, close the link!
|
87
|
+
cf.close_link()
|
@@ -0,0 +1,54 @@
|
|
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
|
+
module Crubyflie
|
20
|
+
# The Commander facility is used to send control information to the
|
21
|
+
# Crazyflie. You want to use this class to fly your Crazyflie
|
22
|
+
class Commander
|
23
|
+
# Initialize the facility
|
24
|
+
def initialize(crazyflie)
|
25
|
+
@crazyflie = crazyflie
|
26
|
+
end
|
27
|
+
|
28
|
+
# Send a setpoint to the Crazyflie
|
29
|
+
#
|
30
|
+
# The roll, pitch, yaw values are floats with positive or negative
|
31
|
+
# values. The range should be the value read from the controller
|
32
|
+
# ([-1,1]) multiplied by the maximum angle change rate
|
33
|
+
# @param roll [float] the roll value
|
34
|
+
# @param pitch [float] the pitch value
|
35
|
+
# @param yaw [float] the yaw value
|
36
|
+
# @param thrust [Integer] thrust is an integer value ranging
|
37
|
+
# from 10001 (next to no power) to
|
38
|
+
# 60000 (full power)
|
39
|
+
def send_setpoint(roll, pitch, yaw, thrust, xmode=false)
|
40
|
+
if xmode
|
41
|
+
roll = 0.707 * (roll - pitch)
|
42
|
+
pitch = 0.707 * (roll + pitch)
|
43
|
+
end
|
44
|
+
|
45
|
+
packet = CRTPPacket.new()
|
46
|
+
packet.modify_header(nil, Crazyflie::CRTP_PORTS[:commander], nil)
|
47
|
+
data = [roll, -pitch, yaw, thrust]
|
48
|
+
# send 3 floats and one unsigned short (16 bits) (all little endian)
|
49
|
+
data = data.pack('eeeS<')
|
50
|
+
packet.data = data.unpack('C*')
|
51
|
+
@crazyflie.send_packet(packet, false)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,67 @@
|
|
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
|
+
|
20
|
+
module Crubyflie
|
21
|
+
# The Console facility is used to read characters that have been
|
22
|
+
# printer using printf in the crazyflie firmware
|
23
|
+
class Console
|
24
|
+
|
25
|
+
# Initialize the console
|
26
|
+
# @param crazyflie [Crazyflie]
|
27
|
+
def initialize(crazyflie)
|
28
|
+
@crazyflie = crazyflie
|
29
|
+
@in_queue = crazyflie.crtp_queues[:console]
|
30
|
+
@read_thread = nil
|
31
|
+
end
|
32
|
+
|
33
|
+
# Reads all the characters from the Crazyflie that are queued, until
|
34
|
+
# the queue is empty, and then return only after executing the
|
35
|
+
# given block for each packet that was in the queue.
|
36
|
+
# @param block [Proc] a block to call with the read information
|
37
|
+
def read(&block)
|
38
|
+
while @in_queue.size > 0 do
|
39
|
+
packet = @in_queue.pop() # block
|
40
|
+
yield(packet.data_repack) if block_given?
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
# Reads all the characters from the Crazyflie constantly
|
46
|
+
# and yields on the the given block is called with the payload.
|
47
|
+
# This call will return immediately, but the block will be
|
48
|
+
# called asynchronously until #stop_reading() is called.
|
49
|
+
# Use stop_read() to stop.
|
50
|
+
# @param block [Proc] a block to call with the read information
|
51
|
+
def start_reading(&block)
|
52
|
+
stop_reading()
|
53
|
+
@read_thread = Thread.new do
|
54
|
+
loop do
|
55
|
+
read(&block)
|
56
|
+
sleep 0.3 # no hurries?
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Stops reading characters from the Crazyflie
|
62
|
+
def stop_reading
|
63
|
+
@read_thread.kill() if @read_thread
|
64
|
+
@read_thread = nil
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|