This repository has been archived by the owner on Jan 3, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 40
/
Copy pathLab2MMIPU.cpp
301 lines (298 loc) · 10.1 KB
/
Lab2MMIPU.cpp
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
#include <iostream>
#include <cmath>
#include <fstream>
/**
* \mainpage
* \brief Лабораторная работа 2. ПИД-регулятор
* \author Горчинский Никита Сергеевич. АС-59
*/
/**
* \class AbstractModel
* \brief Класс, который необходим классам, рассчитывающим линейную и нелинейную модель
*
* Абстрактный класс, который предоставляет виртуальную функцию уравнения calculateModel
* и от которого наследуются классы LinearModel и NonLinearModel
*/
class AbstractModel
{
public:
/**
* \brief Виртуальная функция, переопределенная в дочерних классах LinearModel и NonLinearModel
*
* Функция переопределяется в дочерних классах и служит для рассчета линейной/нелинейной модели.
* \param yCurrent Температура помещения
* \param inputWarm Входящее тепло
*/
virtual double calculateModel(double yCurrent, double inputWarm) = 0;
};
/**
* \class LinearModel
* \brief Класс, который служит для реализации линейной модели
*
* Дочерний класс от AbstractModel, который реализует линейную модель через переопределённую функцию calculateModel
*/
class LinearModel : public AbstractModel
{
private:
double a_, ///< Коэффициент
b_, ///< Коэффициент
yNext_; ///< Получаемая нами температура
public:
LinearModel(double a, double b, double yNext)
{
/**
* Конструктор LinearModel
*
* Код:
* \code
* a_ = a;
* b_ = b;
* yNext_ = yNext;
* \endcode
*/
a_ = a;
b_ = b;
yNext_ = yNext;
}
/**
* Переопределённый метод для рассчёта линейной модели
*
* Код:
* \code
* yNext_ = a_ * yCurrent + b_ * inputWarm;
* return yNext_;
* \endcode
*/
double calculateModel(double yCurrent, double inputWarm)
{
yNext_ = a_ * yCurrent + b_ * inputWarm;
return yNext_;
}
};
/**
* \class NonLinearModel
* \brief Класс, который служит для реализации нелинейной модели
*
* Дочерний класс от AbstractModel, который реализует нелинейную модель через переопределённую функцию calculateModel
*/
class NonLinearModel : public AbstractModel
{
private:
double a_, ///< Коэффициент
b_, ///< Коэффициент
c_, ///< Коэффициент
d_, ///< Коэффициент
yPrev_, ///< Предыдущая температура
yNext_, ///< Получаемая нами температура
wPrev_; ///< Предыдущее тепло
public:
NonLinearModel(double a, double b, double c, double d, double yNext)
{
/**
* Конструктор NonLinearModel
*
* Код:
* \code
* a_ = a;
* b_ = b;
* c_ = c;
* d_ = d;
* wPrev_ = 0;
* yPrev_ = 0;
* yNext_ = yNext;
* \endcode
*/
a_ = a;
b_ = b;
c_ = c;
d_ = d;
yPrev_ = 0;
wPrev_ = 0;
yNext_ = yNext;
}
/**
* Переопределённый метод для рассчёта нелинейной модели
*
* Код:
* \code
* yNext_ = a_ * yCurrent - b_ * pow(yPrev_, 2) + c_ * inputWarm + d_ * sin(wPrev_);
* yPrev_ = yNext_;
* wPrev_ = inputWarm;
* return yNext_;
* \endcode
*/
double calculateModel(double yCurrent, double inputWarm)
{
yNext_ = a_ * yCurrent - b_ * pow(yPrev_, 2) + c_ * inputWarm + d_ * sin(wPrev_);
yPrev_ = yCurrent;
wPrev_ = inputWarm;
return yNext_;
}
};
/**
* \class Regulator
* \brief Класс регулятора
*
* Отдельный класс, в котором мы моделируем регулятор
*/
class Regulator
{
private:
double T_, ///< Постоянная интегрирования
T0_, ///< Шаг для квантования
TD_, ///< Постоянная дифференцирования
K_, ///< Коэффициент передачи
uk_; ///< Текущее значение управляющего воздействия
double calculateUk(double ek, double ek1, double ek2)
{
/**
* \brief Метод для рассчёта uk_
*
* Метод рассчёта текущего значения управляющего воздействия на объект управления
*
* Код:
* \code
* double q0 = K_ * (1 + TD_ / T0_);
* double q1 = -K_ * (1 + 2 * TD_ / T0_ - T0_ / T_);
* double q2 = K_ * TD_ / T0_;
* uk_ += q0 * ek + q1 * ek1 + q2 * ek2;
* return uk_;
* \endcode
*/
double q0 = K_ * (1 + TD_ / T0_); /// q0 - Параметр регулятора
double q1 = -K_ * (1 + 2 * TD_ / T0_ - T0_ / T_); /// q1 - Параметр регулятора
double q2 = K_ * TD_ / T0_; /// q2 - Параметр регулятора
uk_ += q0 * ek + q1 * ek1 + q2 * ek2;
return uk_;
}
public:
Regulator(double T, double T0, double TD, double K)
{
/**
* Конструктор Regulator
*
* Код:
* \code
* T_ = T;
* T0_ = T0;
* TD_ = TD;
* K_ = K;
* uk_ = 0;
* \endcode
*/
T_ = T;
T0_ = T0;
TD_ = TD;
K_ = K;
uk_ = 0;
}
void PIDRegulatorCalculateAndWrite(double need, double start)
{
/**
* \brief Метод моделирования ПИД-регулятора
*
* В данном методе мы моделируем ПИД-регулятор и записываем результаты в файл results.txt
* \param need Желаемое значение
* \param start Стартовое значение y
*
* Код:
* \code
* std::ofstream fout;
* fout.open("results.txt");
* if (fout)
* {
* double ek = 0,ek1 = 0, ek2 = 0, y = start, u = 0;
* LinearModel* linear = new LinearModel(0.333, 0.667, 1);
* fout << "Линейная модель: " << std::endl;
* for (int i = 0; i < 50; ++i)
* {
* ek = need - y;
* u = calculateUk(ek, ek1, ek2);
* y = linear->calculateModel(start, u);
* fout << "E=" << ek << " Y=" << y << " U=" << u << std::endl;
* ek2 = ek1;
* ek1 = ek;
* }
* delete linear;
*
* ek = 0, ek1 = 0, ek2 = 0, y = start, u = 0;
* fout << "Нелинейная модель: " << std::endl;
* NonLinearModel* nonLinear = new NonLinearModel(1, 0.0033, 0.525, 0.525, 1);
* for (int i = 0; i < 50; ++i)
* {
* ek = need - y;
* u = calculateUk(ek, ek1, ek2);
* y = nonLinear->calculateModel(start, u);
* fout << "E=" << ek << " Y=" << y << " U=" << u << std::endl;
* ek2 = ek1;
* ek1 = ek;
* }
* delete nonLinear;
* }
* else
* {
* std::cout << "Не удалось открыть файл для записи результатов." << std::endl;
* }
* fout.close();
* \endcode
*/
std::ofstream fout;
fout.open("results.txt");
if (fout)
{
double ek = 0,ek1 = 0, ek2 = 0, y = start, u = 0;
LinearModel* linear = new LinearModel(0.333, 0.667, 1);
fout << "Линейная модель: " << std::endl;
for (int i = 0; i < 50; ++i)
{
ek = need - y;
u = calculateUk(ek, ek1, ek2);
y = linear->calculateModel(start, u);
fout << "E=" << ek << " Y=" << y << " U=" << u << std::endl;
ek2 = ek1;
ek1 = ek;
}
delete linear;
ek = 0, ek1 = 0, ek2 = 0, y = start, u = 0, uk_ = 0;
fout << "Нелинейная модель: " << std::endl;
NonLinearModel* nonLinear = new NonLinearModel(1, 0.0033, 0.525, 0.525, 1);
for (int i = 0; i < 50; ++i)
{
ek = need - y;
u = calculateUk(ek, ek1, ek2);
y = nonLinear->calculateModel(start, u);
fout << "E=" << ek << " Y=" << y << " U=" << u << std::endl;
ek2 = ek1;
ek1 = ek;
}
delete nonLinear;
}
else
{
std::cout << "Не удалось открыть файл для записи результатов." << std::endl;
}
fout.close();
}
};
int main()
{
/**
* \brief Главная функция main
*
* Создаём объект класса Regulator и вызываем метод для рассчёта и записи результатов в файл
*
* Код:
* \code
* setlocale(0, "");
* Regulator object(10,10,50,0.1);
* object.PIDRegulatorCalculateAndWrite(5, 2);
* std::cout << "Данные были сохранены в файл results.txt" << std::endl;
* return 0;
* \endcode
*/
setlocale(0, "");
Regulator object(10,10,40,0.1);
object.PIDRegulatorCalculateAndWrite(5, 2);
std::cout << "Данные были сохранены в файл results.txt" << std::endl;
return 0;
}