diff --git a/tasks/task_02/doc/doxygen.md b/tasks/task_02/doc/doxygen.md index 63b112ae..c0d4578b 100644 --- a/tasks/task_02/doc/doxygen.md +++ b/tasks/task_02/doc/doxygen.md @@ -225,35 +225,37 @@ The class contains the method to calculate the control signal by [PID](#class_p_ Members | Descriptions --------------------------------|--------------------------------------------- -`public `[`PID`](#class_p_i_d_1a46b78a3e055a6603d1b7980e9320ad81)`(double kp,double ki,double kd)` | The constructor of the [PID](#class_p_i_d) controller. -`public void `[`calculate`](#class_p_i_d_1ac35ae6197f0c54b7797a6e008b3cc31e)`(const std::vector< double > & error)` | The method to calculate the control signal by [PID](#class_p_i_d). -`public std::vector< double > `[`getControlSignals`](#class_p_i_d_1a0dcd91dc972ebf77ec88843565f0b632)`() const` | The method to get the control signals. +`public void `[`calculate`](#class_p_i_d_1ae89c0bb07b0d62a0ea2569ec3338a960)`(const double & w,const double & T0,const std::vector< double > & temps_linear)` | The method to calculate the control signal by [PID](#class_p_i_d). +`public std::vector< std::vector< double > > `[`getControlSignals`](#class_p_i_d_1a4f18b22156745f389a97f73ed4c91e39)`() const` | The method to get the control signals. ## Members -#### `public `[`PID`](#class_p_i_d_1a46b78a3e055a6603d1b7980e9320ad81)`(double kp,double ki,double kd)` +#### `public void `[`calculate`](#class_p_i_d_1ae89c0bb07b0d62a0ea2569ec3338a960)`(const double & w,const double & T0,const std::vector< double > & temps_linear)` -The constructor of the [PID](#class_p_i_d) controller. +The method to calculate the control signal by [PID](#class_p_i_d). #### Parameters -* `kp` The coefficient P in the [PID](#class_p_i_d) controller. +* `error` The vector of errors. -* `ki` The coefficient I in the [PID](#class_p_i_d) controller. +The method calculates the control signal by [PID](#class_p_i_d) using the formulas: Uk = Uk_1 + delta_Uk delta_Uk = q0 * e0 + q1 * e1 + q2 * e2 q0 = K * (1 + TD / T0) q1 = -K * (1 + 2 * TD / T0 - T0 / T) q2 = K * TD / T0 -* `kd` The coefficient D in the [PID](#class_p_i_d) controller. +#### Parameters +* `w` The desired value of the output signal. -#### `public void `[`calculate`](#class_p_i_d_1ac35ae6197f0c54b7797a6e008b3cc31e)`(const std::vector< double > & error)` +* `T0` The time step. -The method to calculate the control signal by [PID](#class_p_i_d). +* `temp` The vector of output signals. -#### Parameters -* `error` The vector of errors. - -#### `public std::vector< double > `[`getControlSignals`](#class_p_i_d_1a0dcd91dc972ebf77ec88843565f0b632)`() const` +#### `public std::vector< std::vector< double > > `[`getControlSignals`](#class_p_i_d_1a4f18b22156745f389a97f73ed4c91e39)`() const` The method to get the control signals. #### Returns The vector of control signals. +The method returns the vector of control signals. + +#### Returns +The vector of control signals. + Generated by [Moxygen](https://sourcey.com/moxygen) \ No newline at end of file diff --git a/tasks/task_02/doc/readme.md b/tasks/task_02/doc/readme.md index e69de29b..ccafd515 100644 --- a/tasks/task_02/doc/readme.md +++ b/tasks/task_02/doc/readme.md @@ -0,0 +1,142 @@ +

Ministry of Education of the Republic of Belarus

+

Educational Institution

+

“Brest State Technical University”

+

Department of Information and Intelligent Technologies

+






+

Laboratory work №2

+

On the discipline “Theory and methods of automatic control”

+

Topic: “PID controllers”

+




+

Performed by:

+

Student of the 3rd course

+

Group AS-63

+

Loginov G. O.

+

Supervised by:

+

Sitkovets J. S.

+




+

Brest 2024

+ +--- + +## Task: + +In C++, implement a program that simulates the PID controller discussed above. Use the mathematical model obtained in the previous work as the control object. To use OOP, the program must have at least 3 classes (+inheritance). + + Add information about the developed program (class diagram, etc.) to the report using Doxygen (in .md format). + +## Example of program output: + +``` bash + Input choice (0 - exit, 1 - start) +Input choice: 1 +Enter the algorithm of the system functioning +Input w(t): 3 +Enter the step +Input T0: 20 + Fill in the data for the Linear model +Input A: 0.2 +Input B: 0.4 +Input current_temperature: 0.1 +Input warm: 0.9 + Fill in the data for the Nonlinear model +Input A: 0.45 +Input B: 0.998 +Input C: 0.876 +Input D: 1.2 +Input current_temperature: 1.1 +Input warm: 0.8 + + RESULTS + + Linear model + +TIME (T0) DEVIATION (e) OUTPUT VARIABLE (Yt) CONTROLLING INFLUENCE (Uk) +===================================================================================== +1 2.62 0.38 91.7 +2 2.564 0.436 5264.24 +3 2.5528 0.4472 10393.2 +4 2.55056 0.44944 15499 +5 2.55011 0.449888 20600.2 +6 2.55002 0.449978 25700.4 +7 2.55 0.449996 30800.5 +8 2.55 0.449999 35900.5 +9 2.55 0.45 41000.5 +10 2.55 0.45 46100.5 +11 2.55 0.45 51200.5 +12 2.55 0.45 56300.5 +13 2.55 0.45 61400.5 +14 2.55 0.45 66500.5 +15 2.55 0.45 71600.5 +16 2.55 0.45 76700.5 +17 2.55 0.45 81800.5 +18 2.55 0.45 86900.5 +19 2.55 0.45 92000.5 +20 2.55 0.45 97100.5 + + RESULTS + + Nonlinear model + +TIME (T0) DEVIATION (e) OUTPUT VARIABLE (Yt) CONTROLLING INFLUENCE (Uk) +===================================================================================== +1 0.943373 2.05663 33.018 +2 1.72047 1.27953 1923.38 +3 5.08384 -2.08384 5462.61 +4 4.01002 -1.01002 15508.6 +5 6.22659 -3.22659 23633.1 +6 3.90844 -0.908444 35949.7 +7 12.2372 -9.23724 44116.1 +8 6.41875 -3.41875 68178.7 +9 88.1327 -85.1327 84021.6 +10 51.4126 -48.4126 256959 +11 7256.31 -7253.31 612874 +12 5604.52 -5601.52 1.48876e+07 +13 5.25078e+07 -5.25078e+07 1.86372e+09 +14 5.49428e+07 -5.49428e+07 1.05652e+11 +15 2.75156e+15 -2.75156e+15 9.63047e+16 +16 4.25087e+15 -4.25087e+15 5.5831e+18 +17 7.55592e+30 -7.55592e+30 2.64457e+32 +18 2.14339e+31 -2.14339e+31 1.56731e+34 +19 5.69777e+61 -5.69777e+61 1.99422e+63 +20 4.84134e+62 -4.84134e+62 1.29476e+65 +``` + +### Input error handling has also been added: +``` bash + Input choice (0 - exit, 1 - start) +Input choice: 1 +Enter the algorithm of the system functioning +Input w(t): h + + ***Input value is not correct*** + +Input w(t): 5 +Enter the step +Input T0: g + + ***Input value is not correct*** +``` + +## Graphs + +### A graph for a linear model +![](../images/Linear_model.png) + +### A graph for a nonlinear model +![](../images/Nonlinear_model.png) + +## Documents +Information about the developed program, created using [Doxygen](https://doxygen.nl/) to generate XML and [Moxygen](https://github.com/sourcey/moxygen) to turn XML into Markdown. + +The resulting file is [doxygen.md](doxygen.md) + +## The source code + +#### The source code is located in the [src folder](/trunk/as0006315/task_01/src). + +- [CMakeLists.txt](/trunk/as0006315/task_01/src/CMakeLists.txt) - this is a file that contains CMake commands to control the project build process. +- [models.h](/trunk/as0006315/task_01/src/models.h) - header file, contains functions declarations for linear and nonlinear models simulation. +- [models.cpp](/trunk/as0006315/task_01/src/models.cpp) - source file, contains functions definitions for linear and nonlinear models simulation. +- [main.cpp](/trunk/as0006315/task_01/src/main.cpp) - source file, contains the main function that controls the program execution. +- [PID.h](/trunk/as0006315/task_01/src/PID.h) - header file, contains the declaration of the `PID` class, which is used to control the system by the PID algorithm. +- [PID.cpp](/trunk/as0006315/task_01/src/PID.cpp) - source file, contains the definition of the `PID` class, which is used to control the system by the PID algorithm. diff --git a/tasks/task_02/src/PID.cpp b/tasks/task_02/src/PID.cpp index 119a667a..d1dab54e 100644 --- a/tasks/task_02/src/PID.cpp +++ b/tasks/task_02/src/PID.cpp @@ -16,7 +16,16 @@ /** * @brief The method to calculate the control signal by PID. * - * @param error The vector of errors. + * The method calculates the control signal by PID using the formulas: + * Uk = Uk_1 + delta_Uk + * delta_Uk = q0 * e0 + q1 * e1 + q2 * e2 + * q0 = K * (1 + TD / T0) + * q1 = -K * (1 + 2 * TD / T0 - T0 / T) + * q2 = K * TD / T0 + * + * @param w The desired value of the output signal. + * @param T0 The time step. + * @param temp The vector of output signals. */ void PID::calculate(const double& w, const double& T0, const std::vector& temp) { double q0; @@ -45,6 +54,8 @@ void PID::calculate(const double& w, const double& T0, const std::vector /** * @brief The method to get the control signals. * + * The method returns the vector of control signals. + * * @return The vector of control signals. */ std::vector> PID::getControlSignals() const { diff --git a/tasks/task_02/src/main.cpp b/tasks/task_02/src/main.cpp index 82a2e3d5..5fbf7473 100644 --- a/tasks/task_02/src/main.cpp +++ b/tasks/task_02/src/main.cpp @@ -28,21 +28,35 @@ void output(const vector >& control_signals, const string& name); /** * @brief The main function. * + * The main function runs the program, it is the entry point of the program. + * * @return 0 if everything is OK. */ -/** - * @brief The array of functions to switch between them. - */ int main() { + /** + * @brief The array of functions to switch between them. + */ void (*point[])() = { []() { exit(0); }, start}; int choice; while (true) { + /** + * @brief Output the choice to the user. + */ cout << "\n\tInput choice (0 - exit, 1 - start)\n"; + /** + * @brief Input the choice from the user. + */ if (!choice_input(choice)) { + /** + * @brief If the input is not correct, output the error message. + */ cerr << "\n\a\t\t***Input value is not correct***\n\n"; continue; } + /** + * @brief Call the function from the array according to the choice. + */ point[choice](); } return 0; @@ -58,40 +72,89 @@ void start() { double w; int T0; - cout << "Enter the algorithm of the system functioning\n"; - input_value(w, "w(t)"); + do { + /** + * @brief Output the request to input the algorithm of the system functioning. + */ + cout << "Enter the algorithm of the system functioning\n"; + } while (!input_value(w, "w(t)")); + /** + * @brief Output the request to input the step. + */ cout << "Enter the step\n"; input_value(T0, "T0"); + /** + * @brief Output the request to input the data for the Linear model. + */ cout << "\tFill in the data for the Linear model\n"; LinearModel liner_model = get_liner_model(T0); + /** + * @brief Get the temperatures from the Linear model. + */ vector temps_linear = liner_model.getTemp(); + /** + * @brief Create the objects of the PID regulator. + */ PID pid_liner, pid_nonlinear; + /** + * @brief Calculate the control signal by PID for the Linear model. + */ pid_liner.calculate(w, T0, temps_linear); + /** + * @brief Get the control signals from the PID regulator for the Linear model. + */ vector > control_signals_liner = pid_liner.getControlSignals(); + /** + * @brief Output the request to input the data for the Nonlinear model. + */ cout << "\tFill in the data for the Nonlinear model\n"; NonLinearModel non_liner_model = get_nonlinear_model(T0); + /** + * @brief Get the temperatures from the Nonlinear model. + */ vector temps_nonlinear = non_liner_model.getTemp(); + /** + * @brief Calculate the control signal by PID for the Nonlinear model. + */ pid_nonlinear.calculate(w, T0, temps_nonlinear); + /** + * @brief Get the control signals from the PID regulator for the Nonlinear model. + */ vector > control_signals_nonlinear = pid_nonlinear.getControlSignals(); + /** + * @brief Output the results for the Linear model. + */ output(control_signals_liner, "Linear model"); + /** + * @brief Output the results for the Nonlinear model. + */ output(control_signals_nonlinear, "Nonlinear model"); } +/** + * @brief The function to output the results. + * + * @param control_signals The control signals to output. + * @param name The name of the model. + */ void output(const vector >& control_signals, const string& name) { + /** + * @brief Output the header of the table. + */ cout << "\n\t\t\t\t\t\t\t\tRESULTS\n\n"; - cout << "\t\t\t\t\t\t\t" << name << "\n\n"; + cout << "\t\t\t\t\t\t\t\t" << name << "\n\n"; cout.setf(ios::left); cout << setw(15) << "TIME (T0)"; cout << setw(20) << "DEVIATION (e)"; @@ -100,6 +163,9 @@ void output(const vector >& control_signals, const string& name) cout << setfill('=') << setw(85) << "" << setfill(' ') << endl; int i = 1; for (const auto& signal : control_signals) { + /** + * @brief Output the row of the table. + */ cout << setw(15) << i++; cout << setw(20) << signal[0]; cout << setw(27) << signal[1]; @@ -117,11 +183,20 @@ void output(const vector >& control_signals, const string& name) */ template bool input_value(T &value, const string &name) { while (true) { + /** + * @brief Output the request to input the value. + */ cout << "Input " << name << ": "; if (cin >> value) { + /** + * @brief If the input is correct, return true. + */ return true; } else { + /** + * @brief If the input is not correct, output the error message. + */ cin.clear(); cin.ignore(numeric_limits::max(), '\n'); cerr << "\n\a\t\t***Input value is not correct***\n\n"; @@ -136,6 +211,9 @@ template bool input_value(T &value, const string &name) { */ LinearModel get_liner_model(const int& T0) { double A, B, current_temperature, warm; + /** + * @brief Input the data for the Linear model. + */ input_value(A, "A"); input_value(B, "B"); input_value(current_temperature, "current_temperature"); @@ -152,6 +230,9 @@ LinearModel get_liner_model(const int& T0) { */ NonLinearModel get_nonlinear_model(const int& T0) { double A, B, C, D, current_temperature, warm; + /** + * @brief Input the data for the Nonlinear model. + */ input_value(A, "A"); input_value(B, "B"); input_value(C, "C"); @@ -173,10 +254,16 @@ NonLinearModel get_nonlinear_model(const int& T0) { bool choice_input(int &choice) { while (true) { if (input_value(choice, "choice")) { - if (choice >= 0 && choice <= 2) { + if (choice >= 0 && choice <= 1) { + /** + * @brief If the input is correct, return true. + */ return true; } else { + /** + * @brief If the input is not correct, output the error message. + */ cerr << "\n\a\t\t***Input value is not correct***\n\n"; } }