-
Notifications
You must be signed in to change notification settings - Fork 0
/
ch01.rb
90 lines (72 loc) · 1.54 KB
/
ch01.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
module ControlTheory
class Buffer
attr_accessor :queued, :wip
def initialize(max_wip, max_flow)
@queued = 0
@wip = 0 # Work-in-progress or "ready pool".
@max_wip = max_wip
@max_flow = max_flow
end
def work(u)
# Add to ready pool.
u = [0, u.round].max
u = [u, @max_wip].min
@wip += u
# Transfer from ready pool to queue.
r = Random.rand(0..@wip)
@wip -= r
@queued += r
# Release from queue to downstream process.
r = Random.rand(0..@max_flow)
r = [r, @queued].min
@queued -= r
@queued
end
end
class Controller
attr_accessor :i, :kp, :ki
def initialize(kp, ki)
@kp = kp
@ki = ki
@i = 0
end
def work(e)
@i += e
@kp * e + @ki * @i
end
end
def self.open_loop(p, tm = 5000)
target = Proc.new { |t| 5.0 }
(1..tm).each do |t|
u = target.call(t)
y = p.work(u)
puts "#{t},#{u},0,#{u},#{y}"
end
end
def self.closed_loop(c, p, tm=5000)
setpoint = Proc.new do |t|
case t
when t < 100
0
when t >= 100 && t < 300
50
else
10
end
end
y = 0
(1..tm).each do |t|
r = setpoint.call(t)
e = r - y
u = c.work(e)
y = p.work(u)
puts "#{t},#{r},#{e},#{u},#{y}"
end
end
end
c = ControlTheory::Controller.new(1.25, 0.01)
p = ControlTheory::Buffer.new(10, 3)
puts "OPEN LOOP"
ControlTheory.open_loop(p, 1000)
puts "CLOSED LOOP"
ControlTheory.closed_loop(c, p, 1000)