From cf27c65bff0cfcfae84e27358d0641566a782a81 Mon Sep 17 00:00:00 2001 From: Andru Liu <90433630+WallabyLester@users.noreply.github.com> Date: Wed, 9 Oct 2024 00:14:53 -0700 Subject: [PATCH] Updated README for cpp implementation. --- README.md | 52 ++++++++++++++++---- images/cpp_impl.png | Bin 0 -> 27161 bytes images/cpp_impl_trained.png | Bin 0 -> 29643 bytes images/{trained.png => tf_impl_trained.png} | Bin 4 files changed, 43 insertions(+), 9 deletions(-) create mode 100644 images/cpp_impl.png create mode 100644 images/cpp_impl_trained.png rename images/{trained.png => tf_impl_trained.png} (100%) diff --git a/README.md b/README.md index e5b5752..9e151d5 100644 --- a/README.md +++ b/README.md @@ -2,24 +2,58 @@ RBF Neural Net Adaptive PID Controller Implementations of a radial basis function (RBF) neural network adaptive PID controller. Uses -neural net and error information from PID control to adapt the control signal. Provides one -adaptation value, using error, integral, and derivative. +neural net and error information from PID control to adapt the control signal. -To adapt the PID gains themselves, network outputs must be made to 3 neurons. Example usage -with simulated data can be found in [first_order_sim.py](first_order_sim.py) +### Python Implementation +Developed to provide one adaptation value to the control signal +using the error, integral, and derivative terms. Done in `TensorFlow` and `Numpy`. +To adapt the PID gains instead of the control signal in TF, the network outputs +must be made to 3 neurons and added to the gains. In Numpy, the gains will need to +be added to inputs and the adapted signal added to the gains. -The method has been implemented in three ways: +Example usage with simulated data can be found in [first_order_sim.py](first_order_sim.py). Tests +to be added. + +### C++ Implementation +A hybrid method; uses the error and PID gains (Kp, Ki, and Kd) to adapt the control signal. +This gives more flexibility to the control model as the gains can be easily adapted since +the RBF model already learns from them. The dual inputs should provide greater stability to +the system, but will be more sensitive to the gains. + +The C++ implementation can already be used for any adaptation, adding the result of `predict()` to +whatever values are desired to adapt. Uses just the `cmath` and `cstdlib` libraries with memory +management handled manually as the system it was designed for could not import additional libraries. +`cstdlib` can be removed if you don't care about random initialization of the centers. + +Example usage with simulated data can be found in [main.cpp](/CPP_Implementation/main.cpp). +It includes some additional libraries in order to show an example usage with a simple first +order simulation. + +The project doesn't currently implement a CMake build as it was pulled from a greater build implementation.\ +An example manual compilation: +``` +g++ -std=c++20 -o rbf_model_test rbf_model.cpp rbf_model_test.cpp -lgtest -lgtest_main -pthread -g -Wall +g++ -std=c++20 -o apid_controller_test apid_controller.cpp apid_controller_test.cpp -lgtest -lgtest_main -pthread -g -Wall + +./apid_controller_test +./rbf_model_test + +g++ -std=c++20 -o control_system main.cpp apid_controller.cpp rbf_model.cpp -lgtest -lgtest_main -pthread -g -Wall +./control_system +``` + +Simulation examples from the three implementations: 1. [TF_Implementation](/TF_Implementation/): Using TensorFlow to build and train the RBF Model. ![TensorFlow](images/tf_impl.png "TensorFlow") -![TF_Trained](images/trained.png "TF_Trained") +![TF_Trained](images/tf_impl_trained.png "TF_Trained") 2. [NP_Implementation](/NP_Implementation/): Using Numpy to build and train the RBF Model. ![Numpy](images/nump_impl.png "Numpy") -3. [CPP_Implementation](/CPP_Implementation/): Written in C++ (requiring `cmath`), for use on embedded systems. +3. [CPP_Implementation](/CPP_Implementation/): Using C++ for embedded systems to build and train the RBF Model. -To build executable: `g++ RBF_aPID.cpp -o RBF_aPID.exe`\ -To run: `./RBF_aPID.exe` +![CPP](images/cpp_impl.png "CPP") +![CPP_Trained](images/cpp_impl_trained.png "CPP_Trained") diff --git a/images/cpp_impl.png b/images/cpp_impl.png new file mode 100644 index 0000000000000000000000000000000000000000..5bfc53f5ba71137a321da132eec7b36b73caecf7 GIT binary patch literal 27161 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 literal 0 HcmV?d00001 diff --git a/images/cpp_impl_trained.png b/images/cpp_impl_trained.png new file mode 100644 index 0000000000000000000000000000000000000000..b1b95999c343dc342589a701a846bc24682d6319 GIT binary patch literal 29643 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
LE^M&5p~YX_3D<>PK2zxVE`Cl8`Gyv4 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 CtN)__ literal 0 HcmV?d00001 diff --git a/images/trained.png b/images/tf_impl_trained.png similarity index 100% rename from images/trained.png rename to images/tf_impl_trained.png