Line | Branch | Decision | Exec | Source |
---|---|---|---|---|
1 | /* | |||
2 | * @file test_pid_auto.cpp | |||
3 | * | |||
4 | * @date Sep 29, 2019 | |||
5 | * @author Andrey Belomutskiy, (c) 2012-2020 | |||
6 | */ | |||
7 | ||||
8 | // see also idle.timingPid test | |||
9 | ||||
10 | #include "pch.h" | |||
11 | ||||
12 | #include "efi_pid.h" | |||
13 | ||||
14 | 4 | TEST(util, pid) { | ||
15 | 1 | pid_s pidS; | ||
16 | 1 | pidS.pFactor = 50; | ||
17 | 1 | pidS.iFactor = 0.5; | ||
18 | 1 | pidS.dFactor = 0; | ||
19 | 1 | pidS.offset = 0; | ||
20 | 1 | pidS.minValue = 10; | ||
21 | 1 | pidS.maxValue = 90; | ||
22 | 1 | pidS.periodMs = 1; | ||
23 | ||||
24 |
1/1✓ Branch 2 taken 1 time.
|
1 | Pid pid(&pidS); | |
25 | ||||
26 |
4/10✓ Branch 2 taken 1 time.
✓ Branch 5 taken 1 time.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 time.
✗ Branch 12 not taken.
✗ Branch 15 not taken.
✗ Branch 20 not taken.
✗ Branch 23 not taken.
✓ Branch 30 taken 1 time.
✗ Branch 31 not taken.
|
1 | ASSERT_FLOAT_EQ( 90, pid.getOutput(14, 12, 0.1)) << "getValue#90"; | |
27 | ||||
28 | ||||
29 |
4/10✓ Branch 2 taken 1 time.
✓ Branch 5 taken 1 time.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 time.
✗ Branch 12 not taken.
✗ Branch 15 not taken.
✗ Branch 20 not taken.
✗ Branch 23 not taken.
✓ Branch 30 taken 1 time.
✗ Branch 31 not taken.
|
1 | ASSERT_FLOAT_EQ( 10, pid.getOutput(14, 16, 0.1)) << "getValue#10"; | |
30 |
4/9✓ Branch 2 taken 1 time.
✓ Branch 5 taken 1 time.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 time.
✗ Branch 12 not taken.
✗ Branch 17 not taken.
✗ Branch 20 not taken.
✓ Branch 27 taken 1 time.
✗ Branch 28 not taken.
|
1 | ASSERT_FLOAT_EQ(10, pid.getOutput(14, 16, 1)); | |
31 | ||||
32 |
1/1✓ Branch 1 taken 1 time.
|
1 | pid.updateFactors(29, 0, 0); | |
33 |
4/9✓ Branch 2 taken 1 time.
✓ Branch 5 taken 1 time.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 time.
✗ Branch 12 not taken.
✗ Branch 17 not taken.
✗ Branch 20 not taken.
✓ Branch 27 taken 1 time.
✗ Branch 28 not taken.
|
1 | ASSERT_FLOAT_EQ(10, pid.getOutput(14, 16, 1)); | |
34 | // ASSERT_FLOAT_EQ(68, pid.getIntegration()); | |||
35 | ||||
36 |
4/9✓ Branch 2 taken 1 time.
✓ Branch 5 taken 1 time.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 time.
✗ Branch 12 not taken.
✗ Branch 17 not taken.
✗ Branch 20 not taken.
✓ Branch 27 taken 1 time.
✗ Branch 28 not taken.
|
1 | ASSERT_FLOAT_EQ(10, pid.getOutput(14, 16, 1)); | |
37 | // ASSERT_FLOAT_EQ(0, pid.getIntegration()); | |||
38 | ||||
39 |
4/9✓ Branch 2 taken 1 time.
✓ Branch 5 taken 1 time.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 time.
✗ Branch 12 not taken.
✗ Branch 17 not taken.
✗ Branch 20 not taken.
✓ Branch 27 taken 1 time.
✗ Branch 28 not taken.
|
1 | ASSERT_FLOAT_EQ(10, pid.getOutput(14, 16, 1)); | |
40 | // ASSERT_FLOAT_EQ(68, pid.getIntegration()); | |||
41 | ||||
42 | ||||
43 | ||||
44 | 1 | pidS.pFactor = 1; | ||
45 | 1 | pidS.iFactor = 0; | ||
46 | 1 | pidS.dFactor = 0; | ||
47 | 1 | pidS.offset = 0; | ||
48 | 1 | pidS.minValue = 0; | ||
49 | 1 | pidS.maxValue = 100; | ||
50 | 1 | pidS.periodMs = 1; | ||
51 | ||||
52 |
1/1✓ Branch 1 taken 1 time.
|
1 | pid.reset(); | |
53 | ||||
54 |
4/10✓ Branch 2 taken 1 time.
✓ Branch 5 taken 1 time.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 time.
✗ Branch 12 not taken.
✗ Branch 15 not taken.
✗ Branch 20 not taken.
✗ Branch 23 not taken.
✓ Branch 30 taken 1 time.
✗ Branch 31 not taken.
|
1 | ASSERT_FLOAT_EQ( 50, pid.getOutput(/*target*/50, /*input*/0)) << "target=50, input=0"; | |
55 |
3/9✓ Branch 2 taken 1 time.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 time.
✗ Branch 9 not taken.
✗ Branch 12 not taken.
✗ Branch 17 not taken.
✗ Branch 20 not taken.
✓ Branch 27 taken 1 time.
✗ Branch 28 not taken.
|
1 | ASSERT_FLOAT_EQ( 0, pid.iTerm) << "target=50, input=0 iTerm"; | |
56 | ||||
57 |
4/10✓ Branch 2 taken 1 time.
✓ Branch 5 taken 1 time.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 time.
✗ Branch 12 not taken.
✗ Branch 15 not taken.
✗ Branch 20 not taken.
✗ Branch 23 not taken.
✓ Branch 30 taken 1 time.
✗ Branch 31 not taken.
|
1 | ASSERT_FLOAT_EQ( 0, pid.getOutput(/*target*/50, /*input*/70)) << "target=50, input=70"; | |
58 |
3/9✓ Branch 2 taken 1 time.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 time.
✗ Branch 9 not taken.
✗ Branch 12 not taken.
✗ Branch 17 not taken.
✗ Branch 20 not taken.
✓ Branch 27 taken 1 time.
✗ Branch 28 not taken.
|
1 | ASSERT_FLOAT_EQ( 0, pid.iTerm) << "target=50, input=70 iTerm"; | |
59 | ||||
60 |
4/10✓ Branch 2 taken 1 time.
✓ Branch 5 taken 1 time.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 time.
✗ Branch 12 not taken.
✗ Branch 15 not taken.
✗ Branch 20 not taken.
✗ Branch 23 not taken.
✓ Branch 30 taken 1 time.
✗ Branch 31 not taken.
|
1 | ASSERT_FLOAT_EQ( 0, pid.getOutput(/*target*/50, /*input*/70)) << "target=50, input=70 #2"; | |
61 |
3/9✓ Branch 2 taken 1 time.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 time.
✗ Branch 9 not taken.
✗ Branch 12 not taken.
✗ Branch 17 not taken.
✗ Branch 20 not taken.
✓ Branch 27 taken 1 time.
✗ Branch 28 not taken.
|
1 | ASSERT_FLOAT_EQ( 0, pid.iTerm) << "target=50, input=70 iTerm #2"; | |
62 | ||||
63 |
4/10✓ Branch 2 taken 1 time.
✓ Branch 5 taken 1 time.
✗ Branch 8 not taken.
✓ Branch 9 taken 1 time.
✗ Branch 12 not taken.
✗ Branch 15 not taken.
✗ Branch 20 not taken.
✗ Branch 23 not taken.
✓ Branch 30 taken 1 time.
✗ Branch 31 not taken.
|
1 | ASSERT_FLOAT_EQ( 0, pid.getOutput(/*target*/50, /*input*/50)) << "target=50, input=50"; | |
64 |
3/9✓ Branch 2 taken 1 time.
✗ Branch 5 not taken.
✓ Branch 6 taken 1 time.
✗ Branch 9 not taken.
✗ Branch 12 not taken.
✗ Branch 17 not taken.
✗ Branch 20 not taken.
✓ Branch 27 taken 1 time.
✗ Branch 28 not taken.
|
1 | ASSERT_FLOAT_EQ( 0, pid.iTerm) << "target=50, input=50 iTerm"; | |
65 | } | |||
66 | ||||
67 | 2 | static void commonPidTestParameters(pid_s * pidS) { | ||
68 | 2 | pidS->pFactor = 0; | ||
69 | 2 | pidS->iFactor = 50; | ||
70 | 2 | pidS->dFactor = 0; | ||
71 | 2 | pidS->offset = 0; | ||
72 | 2 | pidS->minValue = 10; | ||
73 | 2 | pidS->maxValue = 40; | ||
74 | 2 | pidS->periodMs = 1; | ||
75 | 2 | } | ||
76 | ||||
77 | 2 | static void commonPidTest(Pid *pid) { | ||
78 | 2 | pid->iTermMax = 45; | ||
79 | ||||
80 |
4/10✓ Branch 2 taken 2 times.
✓ Branch 5 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 2 times.
✗ Branch 12 not taken.
✗ Branch 15 not taken.
✗ Branch 20 not taken.
✗ Branch 23 not taken.
✓ Branch 30 taken 2 times.
✗ Branch 31 not taken.
|
2 | ASSERT_FLOAT_EQ( 12.5, pid->getOutput(/*target*/50, /*input*/0)) << "target=50, input=0 #0"; | |
81 |
4/9✓ Branch 2 taken 2 times.
✓ Branch 5 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 2 times.
✗ Branch 12 not taken.
✗ Branch 17 not taken.
✗ Branch 20 not taken.
✓ Branch 27 taken 2 times.
✗ Branch 28 not taken.
|
2 | ASSERT_FLOAT_EQ( 12.5, pid->getIntegration()); | |
82 |
4/10✓ Branch 2 taken 2 times.
✓ Branch 5 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 2 times.
✗ Branch 12 not taken.
✗ Branch 15 not taken.
✗ Branch 20 not taken.
✗ Branch 23 not taken.
✓ Branch 30 taken 2 times.
✗ Branch 31 not taken.
|
2 | ASSERT_FLOAT_EQ( 25 , pid->getOutput(/*target*/50, /*input*/0)) << "target=50, input=0 #1"; | |
83 | ||||
84 |
4/10✓ Branch 2 taken 2 times.
✓ Branch 5 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 2 times.
✗ Branch 12 not taken.
✗ Branch 15 not taken.
✗ Branch 20 not taken.
✗ Branch 23 not taken.
✓ Branch 30 taken 2 times.
✗ Branch 31 not taken.
|
2 | ASSERT_FLOAT_EQ( 37.5, pid->getOutput(/*target*/50, /*input*/0)) << "target=50, input=0 #2"; | |
85 |
4/9✓ Branch 2 taken 2 times.
✓ Branch 5 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 2 times.
✗ Branch 12 not taken.
✗ Branch 17 not taken.
✗ Branch 20 not taken.
✓ Branch 27 taken 2 times.
✗ Branch 28 not taken.
|
2 | ASSERT_FLOAT_EQ( 37.5, pid->getIntegration()); | |
86 | ||||
87 |
4/10✓ Branch 2 taken 2 times.
✓ Branch 5 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 2 times.
✗ Branch 12 not taken.
✗ Branch 15 not taken.
✗ Branch 20 not taken.
✗ Branch 23 not taken.
✓ Branch 30 taken 2 times.
✗ Branch 31 not taken.
|
2 | ASSERT_FLOAT_EQ( 40.0, pid->getOutput(/*target*/50, /*input*/0)) << "target=50, input=0 #3"; | |
88 |
4/9✓ Branch 2 taken 2 times.
✓ Branch 5 taken 2 times.
✗ Branch 8 not taken.
✓ Branch 9 taken 2 times.
✗ Branch 12 not taken.
✗ Branch 17 not taken.
✗ Branch 20 not taken.
✓ Branch 27 taken 2 times.
✗ Branch 28 not taken.
|
2 | ASSERT_FLOAT_EQ( 45, pid->getIntegration()); | |
89 | } | |||
90 | ||||
91 | 4 | TEST(util, parallelPidLimits) { | ||
92 | 1 | pid_s pidS; | ||
93 | 1 | commonPidTestParameters(&pidS); | ||
94 | ||||
95 |
1/1✓ Branch 2 taken 1 time.
|
1 | Pid pid(&pidS); | |
96 |
1/1✓ Branch 1 taken 1 time.
|
1 | commonPidTest(&pid); | |
97 | 1 | } | ||
98 | ||||
99 | 4 | TEST(util, industrialPidLimits) { | ||
100 | 1 | pid_s pidS; | ||
101 | 1 | commonPidTestParameters(&pidS); | ||
102 | ||||
103 |
1/1✓ Branch 2 taken 1 time.
|
1 | PidIndustrial pid(&pidS); | |
104 |
1/1✓ Branch 1 taken 1 time.
|
1 | commonPidTest(&pid); | |
105 | 1 | } | ||
106 | ||||
107 | TEST(util, pidIndustrial) { | |||
108 | pid_s pidS; | |||
109 | pidS.pFactor = 1.0; | |||
110 | pidS.iFactor = 1.0; | |||
111 | pidS.dFactor = 1.0; | |||
112 | pidS.offset = 0; | |||
113 | pidS.minValue = 0; | |||
114 | pidS.maxValue = 100; | |||
115 | pidS.periodMs = 1; | |||
116 | ||||
117 | PidIndustrial pid; | |||
118 | pid.initPidClass(&pidS); | |||
119 | ||||
120 | // we want to compare with the "normal" PID controller | |||
121 | Pid pid0(&pidS); | |||
122 | ||||
123 | // no additional features | |||
124 | pid.derivativeFilterLoss = 0; | |||
125 | pid.antiwindupFreq = 0; | |||
126 | ||||
127 | float industValue = pid.getOutput(/*target*/1, /*input*/0); | |||
128 | // check if the first output is clamped because of large deviative | |||
129 | ASSERT_FLOAT_EQ(100.0, industValue); | |||
130 | ||||
131 | // check if all output of the 'zeroed' PidIndustrial (w/o new features) is the same as our "normal" Pid | |||
132 | for (int i = 0; i < 10; i++) { | |||
133 | float normalValue = pid0.getOutput(1, 0); | |||
134 | ASSERT_FLOAT_EQ(normalValue, industValue) << "[" << i << "]"; | |||
135 | industValue = pid.getOutput(1, 0); | |||
136 | } | |||
137 | ||||
138 | pid.reset(); | |||
139 | ||||
140 | // now test the "derivative filter loss" param (some small value) | |||
141 | pid.derivativeFilterLoss = 0.01; | |||
142 | ||||
143 | // now the first value is less (and not clipped!) due to the derivative filtering | |||
144 | ASSERT_FLOAT_EQ(67.671669f, pid.getOutput(1, 0)); | |||
145 | // here we still have some leftovers of the initial D-term | |||
146 | ASSERT_FLOAT_EQ(45.4544487f, pid.getOutput(1, 0)); | |||
147 | // but the value is quickly fading | |||
148 | ASSERT_FLOAT_EQ(30.6446342f, pid.getOutput(1, 0)); | |||
149 | ||||
150 | pid.reset(); | |||
151 | ||||
152 | // now test much stronger "derivative filter loss" | |||
153 | pid.derivativeFilterLoss = 0.1; | |||
154 | ||||
155 | // now the first value is much less due to the derivative filtering | |||
156 | ASSERT_NEAR(10.5288095f, pid.getOutput(1, 0), EPS4D); | |||
157 | // here we still have some leftovers of the initial D-term | |||
158 | ASSERT_NEAR(10.0802946f, pid.getOutput(1, 0), EPS4D); | |||
159 | // but the fading is slower than with 'weaker' derivative filter above | |||
160 | ASSERT_NEAR(9.65337563f, pid.getOutput(1, 0), EPS4D); | |||
161 | ||||
162 | pid.reset(); | |||
163 | pid.derivativeFilterLoss = 0; | |||
164 | ||||
165 | // now test "anti-windup" param | |||
166 | pid.antiwindupFreq = 0.1; | |||
167 | ||||
168 | // the first value is clipped, and that's when the anti-windup comes into effect | |||
169 | ASSERT_FLOAT_EQ(100.0f, pid.getOutput(1, 0)); | |||
170 | // it stores a small negative offset in the I-term to avoid it's saturation! | |||
171 | ASSERT_NEAR(-0.0455025025f, pid.getIntegration(), EPS4D); | |||
172 | // and that's why the second output is smaller then that of normal PID (=1.00999999) | |||
173 | ASSERT_NEAR(0.959497511f, pid.getOutput(1, 0), EPS4D); | |||
174 | ||||
175 | } | |||
176 |