pid_controller 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 +11 -0
- data/.rspec +3 -0
- data/.rubocop.yml +7 -0
- data/.travis.yml +14 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +58 -0
- data/README.md +33 -0
- data/Rakefile +8 -0
- data/bin/console +7 -0
- data/bin/setup +8 -0
- data/lib/pid_controller.rb +63 -0
- data/lib/pid_controller/version.rb +3 -0
- data/pid_controller.gemspec +27 -0
- metadata +126 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: ed3b92ab6f402ed7ca931150c9832a245c62a8fa
|
4
|
+
data.tar.gz: 02b6b58e47954514a8b89d79bc5a3b30bb99595c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 28b63c397d384f6f06f077185c1b833a5330702286c4e5f0072cfea0dcd77c8f60adcec4b0ff8bcd92bd1e8bff251a32ab16a3852e2b89f78d7da9c55f6d1e86
|
7
|
+
data.tar.gz: 90bee02b13d177287108d51f869001061856a4b14bc4c2955dedc3fa97138c15ae8ca6f7df70df1c352f3923242f3ab76a61261ff2b959ae338d30dce3188780
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
pid_controller (0.1.0)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
ast (2.3.0)
|
10
|
+
coderay (1.1.2)
|
11
|
+
diff-lcs (1.3)
|
12
|
+
method_source (0.9.0)
|
13
|
+
parallel (1.12.0)
|
14
|
+
parser (2.4.0.2)
|
15
|
+
ast (~> 2.3)
|
16
|
+
powerpack (0.1.1)
|
17
|
+
pry (0.11.3)
|
18
|
+
coderay (~> 1.1.0)
|
19
|
+
method_source (~> 0.9.0)
|
20
|
+
rainbow (2.2.2)
|
21
|
+
rake
|
22
|
+
rake (10.5.0)
|
23
|
+
rspec (3.7.0)
|
24
|
+
rspec-core (~> 3.7.0)
|
25
|
+
rspec-expectations (~> 3.7.0)
|
26
|
+
rspec-mocks (~> 3.7.0)
|
27
|
+
rspec-core (3.7.0)
|
28
|
+
rspec-support (~> 3.7.0)
|
29
|
+
rspec-expectations (3.7.0)
|
30
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
31
|
+
rspec-support (~> 3.7.0)
|
32
|
+
rspec-mocks (3.7.0)
|
33
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
34
|
+
rspec-support (~> 3.7.0)
|
35
|
+
rspec-support (3.7.0)
|
36
|
+
rubocop (0.51.0)
|
37
|
+
parallel (~> 1.10)
|
38
|
+
parser (>= 2.3.3.1, < 3.0)
|
39
|
+
powerpack (~> 0.1)
|
40
|
+
rainbow (>= 2.2.2, < 3.0)
|
41
|
+
ruby-progressbar (~> 1.7)
|
42
|
+
unicode-display_width (~> 1.0, >= 1.0.1)
|
43
|
+
ruby-progressbar (1.9.0)
|
44
|
+
unicode-display_width (1.3.0)
|
45
|
+
|
46
|
+
PLATFORMS
|
47
|
+
ruby
|
48
|
+
|
49
|
+
DEPENDENCIES
|
50
|
+
bundler (~> 1.16)
|
51
|
+
pid_controller!
|
52
|
+
pry
|
53
|
+
rake (~> 10.0)
|
54
|
+
rspec (~> 3.0)
|
55
|
+
rubocop (~> 0.51)
|
56
|
+
|
57
|
+
BUNDLED WITH
|
58
|
+
1.16.0
|
data/README.md
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# PidController
|
2
|
+
|
3
|
+
This is a Ruby implementation of a [PID Controller](https://en.wikipedia.org/wiki/PID_controller). A PID controller is a feedback system that is configured with a target setpoint, can read measurements of the system to see how close we are to the setpoint, and will omit an output. Every day examples include:
|
4
|
+
|
5
|
+
- Cruise control
|
6
|
+
- Thermostats
|
7
|
+
- Quadcopters (appearently, because they predominate search results)
|
8
|
+
- Database load (yay! This is why the purpose I'm actually writing this for).
|
9
|
+
|
10
|
+
## Usage
|
11
|
+
|
12
|
+
I mentioned databases, so here's an example of how we can prevent a low priority task (e.g. bulk deletion) from contending with customer traffic:
|
13
|
+
|
14
|
+
```ruby
|
15
|
+
sensor = MySQLSensor.new # Use your imagination
|
16
|
+
controller = PIDController.new(setpoint: 60.0, kp: 5.0, ki: 1.0, kd: 0.1)
|
17
|
+
|
18
|
+
Event.where(account_id: account_id).in_batches do |relation|
|
19
|
+
relation.delete_all
|
20
|
+
backoff = controller << sensor.cpu_utilization
|
21
|
+
sleep backoff if backoff > 0
|
22
|
+
end
|
23
|
+
```
|
24
|
+
|
25
|
+
## Development
|
26
|
+
|
27
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
28
|
+
|
29
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
30
|
+
|
31
|
+
## Contributing
|
32
|
+
|
33
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/gabetax/pid_controller.
|
data/Rakefile
ADDED
data/bin/console
ADDED
data/bin/setup
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'pid_controller/version'
|
2
|
+
|
3
|
+
# https://en.wikipedia.org/wiki/PID_controller
|
4
|
+
class PidController
|
5
|
+
attr_accessor :setpoint, :kp, :ki, :kd
|
6
|
+
|
7
|
+
def initialize(setpoint:, kp: 1.0, ki: 1.0, kd: 1.0)
|
8
|
+
@setpoint = setpoint
|
9
|
+
@kp = kp
|
10
|
+
@ki = ki
|
11
|
+
@kd = kd
|
12
|
+
@integral = 0.0
|
13
|
+
@derivative = 0.0
|
14
|
+
@last_error = nil
|
15
|
+
@last_update = nil
|
16
|
+
end
|
17
|
+
|
18
|
+
def update(measurement)
|
19
|
+
now = clock_time
|
20
|
+
dt = if @last_update
|
21
|
+
now - @last_update
|
22
|
+
else
|
23
|
+
0.0
|
24
|
+
end
|
25
|
+
@last_update = now
|
26
|
+
update_with_duration(measurement, dt)
|
27
|
+
end
|
28
|
+
|
29
|
+
alias << update
|
30
|
+
|
31
|
+
def update_with_duration(measurement, dt)
|
32
|
+
error = setpoint - measurement.to_f
|
33
|
+
|
34
|
+
if dt > 0.0
|
35
|
+
@integral += error * dt
|
36
|
+
@derivative = (error - @last_error) / dt
|
37
|
+
end
|
38
|
+
|
39
|
+
@last_error = error
|
40
|
+
|
41
|
+
output
|
42
|
+
end
|
43
|
+
|
44
|
+
def output
|
45
|
+
p_term + i_term + d_term
|
46
|
+
end
|
47
|
+
|
48
|
+
def p_term
|
49
|
+
kp * @last_error
|
50
|
+
end
|
51
|
+
|
52
|
+
def i_term
|
53
|
+
ki * @integral
|
54
|
+
end
|
55
|
+
|
56
|
+
def d_term
|
57
|
+
kd * @derivative
|
58
|
+
end
|
59
|
+
|
60
|
+
def clock_time
|
61
|
+
Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'pid_controller/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'pid_controller'
|
8
|
+
spec.version = PidController::VERSION
|
9
|
+
spec.authors = ['Gabe Martin-Dempesy']
|
10
|
+
spec.email = ['gabetax@gmail.com']
|
11
|
+
|
12
|
+
spec.summary = 'A Ruby PID controller implementation'
|
13
|
+
spec.homepage = 'https://github.com/gabetax/pid_controller'
|
14
|
+
|
15
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
16
|
+
f.match(%r{^(test|spec|features)/})
|
17
|
+
end
|
18
|
+
spec.bindir = 'exe'
|
19
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
|
+
spec.require_paths = ['lib']
|
21
|
+
|
22
|
+
spec.add_development_dependency 'bundler', '~> 1.16'
|
23
|
+
spec.add_development_dependency 'pry'
|
24
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
25
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
26
|
+
spec.add_development_dependency 'rubocop', '~> 0.51'
|
27
|
+
end
|
metadata
ADDED
@@ -0,0 +1,126 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pid_controller
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Gabe Martin-Dempesy
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-11-29 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.16'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.16'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: pry
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '10.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '10.0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '3.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '3.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rubocop
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0.51'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0.51'
|
83
|
+
description:
|
84
|
+
email:
|
85
|
+
- gabetax@gmail.com
|
86
|
+
executables: []
|
87
|
+
extensions: []
|
88
|
+
extra_rdoc_files: []
|
89
|
+
files:
|
90
|
+
- ".gitignore"
|
91
|
+
- ".rspec"
|
92
|
+
- ".rubocop.yml"
|
93
|
+
- ".travis.yml"
|
94
|
+
- Gemfile
|
95
|
+
- Gemfile.lock
|
96
|
+
- README.md
|
97
|
+
- Rakefile
|
98
|
+
- bin/console
|
99
|
+
- bin/setup
|
100
|
+
- lib/pid_controller.rb
|
101
|
+
- lib/pid_controller/version.rb
|
102
|
+
- pid_controller.gemspec
|
103
|
+
homepage: https://github.com/gabetax/pid_controller
|
104
|
+
licenses: []
|
105
|
+
metadata: {}
|
106
|
+
post_install_message:
|
107
|
+
rdoc_options: []
|
108
|
+
require_paths:
|
109
|
+
- lib
|
110
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
111
|
+
requirements:
|
112
|
+
- - ">="
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: '0'
|
115
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
116
|
+
requirements:
|
117
|
+
- - ">="
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: '0'
|
120
|
+
requirements: []
|
121
|
+
rubyforge_project:
|
122
|
+
rubygems_version: 2.6.13
|
123
|
+
signing_key:
|
124
|
+
specification_version: 4
|
125
|
+
summary: A Ruby PID controller implementation
|
126
|
+
test_files: []
|