hybridgroup-crubyflie 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.travis.yml +8 -0
  4. data/Gemfile +5 -0
  5. data/LICENSE.txt +674 -0
  6. data/README.md +127 -0
  7. data/Rakefile +15 -0
  8. data/bin/crubyflie +94 -0
  9. data/configs/joystick_default.yaml +106 -0
  10. data/crubyflie.gemspec +50 -0
  11. data/examples/params_and_logging.rb +87 -0
  12. data/lib/crubyflie/crazyflie/commander.rb +54 -0
  13. data/lib/crubyflie/crazyflie/console.rb +67 -0
  14. data/lib/crubyflie/crazyflie/log.rb +383 -0
  15. data/lib/crubyflie/crazyflie/log_conf.rb +57 -0
  16. data/lib/crubyflie/crazyflie/param.rb +220 -0
  17. data/lib/crubyflie/crazyflie/toc.rb +239 -0
  18. data/lib/crubyflie/crazyflie/toc_cache.rb +87 -0
  19. data/lib/crubyflie/crazyflie.rb +282 -0
  20. data/lib/crubyflie/crazyradio/crazyradio.rb +301 -0
  21. data/lib/crubyflie/crazyradio/radio_ack.rb +48 -0
  22. data/lib/crubyflie/crubyflie_logger.rb +74 -0
  23. data/lib/crubyflie/driver/crtp_packet.rb +146 -0
  24. data/lib/crubyflie/driver/radio_driver.rb +363 -0
  25. data/lib/crubyflie/exceptions.rb +36 -0
  26. data/lib/crubyflie/input/input_reader.rb +190 -0
  27. data/lib/crubyflie/input/joystick_input_reader.rb +328 -0
  28. data/lib/crubyflie/version.rb +22 -0
  29. data/lib/crubyflie.rb +36 -0
  30. data/spec/commander_spec.rb +67 -0
  31. data/spec/console_spec.rb +76 -0
  32. data/spec/crazyflie_spec.rb +176 -0
  33. data/spec/crazyradio_spec.rb +228 -0
  34. data/spec/crtp_packet_spec.rb +79 -0
  35. data/spec/crubyflie_logger_spec.rb +39 -0
  36. data/spec/crubyflie_spec.rb +21 -0
  37. data/spec/input_reader_spec.rb +136 -0
  38. data/spec/joystick_cfg.yaml +44 -0
  39. data/spec/joystick_input_reader_spec.rb +323 -0
  40. data/spec/log_spec.rb +266 -0
  41. data/spec/param_spec.rb +166 -0
  42. data/spec/radio_ack_spec.rb +43 -0
  43. data/spec/radio_driver_spec.rb +227 -0
  44. data/spec/spec_helper.rb +53 -0
  45. data/spec/toc_cache_spec.rb +87 -0
  46. data/spec/toc_spec.rb +187 -0
  47. data/tools/sdl-joystick-axis.rb +69 -0
  48. metadata +225 -0
data/README.md ADDED
@@ -0,0 +1,127 @@
1
+ Crubyflie - A Ruby client for Crazyflie
2
+ =======================================
3
+
4
+ [![Build Status](https://travis-ci.org/hsanjuan/crubyflie.png?branch=master)](https://travis-ci.org/hsanjuan/crubyflie) [![Coverage Status](https://coveralls.io/repos/hsanjuan/crubyflie/badge.png)](https://coveralls.io/r/hsanjuan/crubyflie)
5
+
6
+ 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.
7
+
8
+ 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.
9
+
10
+ You may be also interested in some other unofficial Crazyflie clients:
11
+
12
+ * C++: https://github.com/fairlight1337/libcflie
13
+ * Node.js: https://github.com/ceejbot/aerogel
14
+ * Haskell: https://github.com/orclev/crazyflie-haskell
15
+
16
+ Disclaimer
17
+ ----------
18
+
19
+ Crubyflie is in early stage of development, very untested.
20
+
21
+ Features
22
+ --------
23
+
24
+ * Crubyflie can be used to fly a Crazyflie device using a Joystick and the Crazyradio USB dongle
25
+ * Crubyflie exposes an API that allows to control the copter, read logging, parameters and console easily
26
+ * Crubyflie runs headless
27
+ * Lightweight: If you just want to fly, Crubyflie consumes around 1/2 memory and 1/3 CPU compared to the original Python `cfheadless` utility.
28
+
29
+ Not included...
30
+ ----------------
31
+ * No fancy UI.
32
+ * No flash utility (yet?).
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
+ * 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
+
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
+
45
+ Fyling the Crazyflie
46
+ --------------------
47
+
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):
49
+
50
+ > crubyflie2.0 -h
51
+ Options:
52
+ --joystick-id, -j <i>: Joystick ID (default: 0)
53
+ --cf-uri, -f <s>: Crazyflie URI (defaults to first one found in scan)
54
+ --config, -c <s>: Joystick configuration, defaults to default cfg in configs/ (default:
55
+ /usr/lib64/ruby/gems/2.0.0/gems/crubyflie-0.0.1/lib/crubyflie/input/../../../configs/joystick_default.yaml)
56
+ --help, -h: Show this message
57
+
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.
59
+
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.
61
+
62
+ If you need help just open an issue or contact me.
63
+
64
+ Raspberry Pi
65
+ ------------
66
+
67
+ If you want to use Crubyflie in your Raspberry Pi you need to:
68
+
69
+ sudo apt-get install ruby ruby-dev libsdl-dev
70
+ sudo gem install crubyflie
71
+
72
+ This should provide everything you need to run the `crubyflie` command. Of course you might need to put your user in the `input` group and modify `udev` rules as explained in the [Crazyflie wiki](http://wiki.bitcraze.se/projects:crazyflie:hacks:rasberrypi).
73
+
74
+ Using the Crazyflie API
75
+ -----------------------
76
+
77
+ While both Python and Ruby APIs expose access to params, logging, console and commander facilities, Crubyflie does it in sligthly different way.
78
+
79
+ Crubyflie access to facilities is offered fully under the Crazyflie instance object, let's see it as code:
80
+
81
+ ```ruby
82
+ require 'crubyflie'
83
+ include Crubyflie
84
+
85
+ # Connect
86
+ @cf = Crazyflie.new()
87
+ @cf.open_link(@radio_uri)
88
+
89
+ # Interface to the logging facility
90
+ @cf.log.create_log_block(...)
91
+ @cf.log.start_logging(...) do |log_values|
92
+ ...
93
+ end
94
+ @cf.log.stop_logging(...)
95
+ @cf.log.delete_log(...)
96
+
97
+
98
+ # Interface to the param facility
99
+ @cf.param.get_value(...) do |value|
100
+ ...
101
+ end
102
+
103
+ @cf.param.get_value(...) do |value|
104
+ ...
105
+ end
106
+
107
+ @cf.param.set_value(...)
108
+
109
+ # Interface to the commander facility
110
+ @cf.commander.send_setpoint(...)
111
+
112
+ # Interface to the console facility
113
+ @cf.console.read do |value|
114
+ ...
115
+ end
116
+ ```
117
+
118
+ 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.
119
+ 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.
120
+
121
+ There are some examples in the `examples` folder. Read the gem documentation to get full information of the parameters for each function call.
122
+
123
+
124
+ Contributing
125
+ ------------
126
+
127
+ 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,94 @@
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
+ opt(:debug, "Enable debug messages",
40
+ :short => '-d')
41
+ end
42
+
43
+ include Crubyflie
44
+ $debug = true if opts[:debug]
45
+
46
+ cf = Crazyflie.new('/tmp/crubyflie')
47
+
48
+ # Before opening any link, scan for interfaces
49
+ uris = cf.scan_interface
50
+ if uris.empty?
51
+ logger.error("No crazyflies found")
52
+ exit 1
53
+ end
54
+ logger.info("Found copters at: #{uris}")
55
+ if uri = opts[:cf_uri] && !uris.include?(opts[:cf_uri])
56
+ logger.error("Provided URI not found")
57
+ exit 1
58
+ end
59
+
60
+ uri ||= uris.first
61
+
62
+ # Open a link to the copter
63
+ cf.open_link(uri)
64
+ # Make sure everything is still good
65
+ exit 1 if !cf.active?
66
+
67
+ # Initialize the joystick - ID defaults to 0
68
+ joystick = Joystick.new(opts[:config], opts[:joystick_id])
69
+ joystick.init()
70
+
71
+ exit = false
72
+ Signal.trap("SIGINT") do
73
+ exit = true
74
+ end
75
+
76
+ logger.info("Cleared for take-off!")
77
+
78
+ while cf.active? && !exit do
79
+ start_time = Time.now.to_f
80
+ joystick.read_input()
81
+ joystick.apply_input(cf)
82
+ # We should be good sending 10 ticks per second,
83
+ # as it says that somewhere in the docs, so we have
84
+ # 1/10 secs of time per loop. If we are fast, we can sleep
85
+ # a little bit
86
+ consumed_time = Time.now.to_f - start_time
87
+ sleep_time = 0.1 - consumed_time
88
+ sleep sleep_time if sleep_time > 0
89
+ end
90
+
91
+ joystick.quit()
92
+ cf.close_link()
93
+ warn "\n"
94
+ logger.info("Bye bye!")
@@ -0,0 +1,106 @@
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
+ # ---------------------------------------------------------------------------
56
+ :type: "Joystick"
57
+ :axis:
58
+ 0:
59
+ :description: "Roll Axis"
60
+ :action: :roll
61
+ :input_range: "-32768:32767" # Optional - SDL dependant. Defaults to this.
62
+ :output_range: "-30:30" # Min/Max crazyflie angle in degrees.
63
+ :max_change_rate: 600 # Max angle change rate per second. Optional
64
+ :dead_zone: "-100:100" # Deadzone, within input range
65
+ :invert: false # Invert the axis
66
+ :calibration: 0 # This value is added to the raw value read from joystick
67
+ 1:
68
+ :description: "Pitch Axis"
69
+ :action: :pitch
70
+ :input_range: "-32768:32767"
71
+ :output_range: "-30:30"
72
+ :max_change_rate: 600
73
+ :dead_zone: "-100:100"
74
+ :invert: true
75
+ :calibration: 0
76
+ 2:
77
+ :description: "Yaw Axis"
78
+ :action: :yaw
79
+ :input_range: "-32768:32767"
80
+ :output_range: "-150:150"
81
+ :max_change_rate: 800
82
+ :dead_zone: "-1000:1000"
83
+ :invert: false
84
+ :calibration: 0
85
+ 3:
86
+ :description: "Thrust axis"
87
+ :action: :thrust
88
+ :input_range: "-32768:32767"
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"
94
+ :invert: true
95
+ :calibration: 0
96
+
97
+ :buttons:
98
+ 0:
99
+ :action: :switch_xmode
100
+ 1:
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
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 = "hybridgroup-crubyflie"
25
+ spec.version = Crubyflie::VERSION
26
+ spec.authors = ["Hector Sanjuan", "Adrian Zankich"]
27
+ spec.email = ["hector@convivencial.org", "adrian@hybridgroup.com"]
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 = "A Ruby client for the Crazyflie quadcopter"
33
+ spec.homepage = "https://github.com/hybridgroup/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 "trollop"
43
+
44
+ spec.add_development_dependency "bundler", "~> 1.3"
45
+ spec.add_development_dependency "rake"
46
+ spec.add_development_dependency "rspec"
47
+ spec.add_development_dependency "yard"
48
+ spec.add_development_dependency "simplecov"
49
+ spec.add_development_dependency "coveralls"
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