-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathch13.rb
95 lines (72 loc) · 1.49 KB
/
ch13.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
91
92
93
94
95
require 'distribution'
require_relative './feedback'
# Use shorthand methods.
include Distribution::Shorthand
class Cache < Component
attr_accessor :t, :size, :cache, :demand
def initialize(size, demand)
# Internal time counter. Needed for last access time.
@t = 0
#
@size = size
#
@cache = {}
#
@demand = demand
end
def work(u)
@t += 1
@size = [0, u.to_i].max
i = @demand.call(@t)
if @cache.key? i
@cache[i] = @t
return 1
end
if @cache.size >= @size
# number of elements to delete
m = 1 + @cache.size - @size
tmp = {}
@cache.keys.each do |k|
tmp[@cache[k]] = k
end
tmp.keys.sort.each do |j|
@cache.delete tmp[j]
m -= 1
break if m == 0
end
end
@cache[i] = @t
0
end
end
class SmoothedCache < Cache
def initialize(size, demand, avg)
super(size, demand)
@f = FixedFilter.new(avg)
end
def work(u)
y = super(u)
@f.work(y)
end
end
def demand(t)
norm_rng(mean = 0, stddev = 15).call.to_i
end
def setpoint(t)
0.7
end
def demand2(t)
case t
when t < 3000
norm_rng(mean: 0, stddev: 15).call.to_i
when t < 5000
norm_rng(mean:0, stddev: 35).call.to_i
else
norm_rng(mean: 100, stddev: 15).call.to_i
end
end
# the actual plant stuff.
DT = 1
plant = SmoothedCache.new(0, method(:demand), 100)
controller = PIDController.new(100, 250)
Feedback::closed_loop(method(:setpoint), controller, plant, 10000)