/*
 * adaptive_filters.c
 *
 *  Created on: 24 сент. 2023 г.
 *      Author: user
 */

/*
Determining the appropriate values for the adaptive coefficients Ka and Kb in an adaptive PI
regulator requires a thorough understanding of your specific control system and motor dynamics.
The values of Ka and Kb are typically determined through a tuning process, which involves
experimentation and iteration to achieve the desired control performance.

Here's a general approach to tuning the adaptive coefficients Ka and Kb:

Start with small initial values: Begin with small values for Ka and Kb, such as 0.01 or 0.001.

Observe the system behavior: Run the control system with these initial values and observe the
response of the motor. Pay attention to the speed control performance, such as overshoot, settling
time, and steady-state error.

Adjust Ka and Kb based on the response: Increase or decrease the values of Ka and Kb based on
the observed system behavior. If the system response is slow or exhibits large overshoot,
consider increasing the values. If the system response is too aggressive or unstable,
consider decreasing the values.

Iterate the tuning process: Repeat steps 2 and 3, adjusting Ka and Kb iteratively until you
achieve the desired control performance. It may require several iterations to find suitable
values.

It's important to note that the tuning process is highly dependent on the specific motor
characteristics, the requirements of the control system, and the desired performance.
Therefore, it's recommended to consult motor control experts, refer to motor datasheets, or consider model-based control techniques for a more accurate tuning process.

Additionally, advanced control techniques such as adaptive control algorithms
(e.g., Model Reference Adaptive Control or Self-Tuning Regulators) can be explored for more
advanced and precise adaptation of control parameters.

Remember to thoroughly test and validate the tuned parameters under various operating
conditions to ensure stability and robust performance of the motor control system.
 */

// Constants for the PI regulator
#define Kp 0.5
#define Ki 0.2

// Constants for the adaptive part
#define Ka 0.05
#define Kb 0.02

// Function to calculate the adaptive PI control output
float adaptivePI(float setpoint, float measured_speed, float integral_error)
{
    static float prev_error = 0.0;
    static float prev_output = 0.0;

    // Calculate the error
    float error = setpoint - measured_speed;

    // Calculate the integral error
    integral_error += error;

    // Calculate the adaptive part
    float adaptive = Ka * error + Kb * (error - prev_error);

    // Calculate the PI control output
    float output = Kp * error + Ki * integral_error + adaptive;

    // Store the current error and output for the next iteration
    prev_error = error;
    prev_output = output;

    return output;
}

int main1()
{
    float setpoint = 100.0; // Desired speed setpoint
    float measured_speed = 85.0; // Measured speed of the motor
    float integral_error = 0.0; // Integral error for the PI regulator

    // Calculate the control output using the adaptive PI regulator
    float control_output = adaptivePI(setpoint, measured_speed, integral_error);

    printf("Control Output: %f\n", control_output);

    return 0;
}



////////////////////////////
/*
In this simplified example, the mracControl function implements the MRAC algorithm for motor speed control.
The function takes the desired speed reference (reference_speed), the measured speed of the motor (measured_speed),
and the adaptation parameter (adaptation_param) as inputs. It returns the control output.

The MRAC algorithm calculates the error between the reference speed and the measured speed. It then multiplies
the error by the adaptation parameter, controller gain (Kc), and applies it as the control output.
The adaptation parameter is updated based on the derivative of the error and the adaptation rate (Lambda).

The main function demonstrates how to use the mracControl function by providing sample values for the reference
 speed, measured speed, and adaptation parameter. It calculates the control output and prints it to the console.

Please note that this is a simplified example, and in a real-world scenario, you would need to consider
the specific motor dynamics, tuning of parameters, and implementation details based on the control
requirements of your motor system.
 */


// Constants for the MRAC algorithm
#define Kc 0.5  // Controller gain
#define Lambda 0.1  // Adaptation rate

// Reference model parameters
#define Km 0.5  // Model gain
#define Tm 1.0  // Model time constant

// Function to calculate the MRAC control output
float mracControl(float reference_speed, float measured_speed, float adaptation_param)
{
    static float control_output = 0.0;
    static float prev_error = 0.0;

    // Calculate the error
    float error = reference_speed - measured_speed;

    // Calculate the control output
    control_output = Kc * adaptation_param * error;

    // Update the adaptation parameter
    float derivative_error = (error - prev_error) / Tm;
    adaptation_param += Lambda * derivative_error;

    // Store the current error for the next iteration
    prev_error = error;

    return control_output;
}

int main2()
{
    float reference_speed = 100.0; // Desired speed reference
    float measured_speed = 85.0; // Measured speed of the motor
    float adaptation_param = 1.0; // Initial value for the adaptation parameter

    // Calculate the MRAC control output
    float control_output = mracControl(reference_speed, measured_speed, adaptation_param);

    printf("Control Output: %f\n", control_output);

    return 0;
}


//////////////////////////////////////

/*
 In this simplified example, the strControl function implements the STR algorithm for motor speed control.
 It takes the desired speed reference (reference_speed), the measured speed of the motor (measured_speed),
 and the adaptation parameter (adaptation_param) as inputs. It returns the control output.

The STR algorithm calculates the error between the reference speed and the measured speed.
It then multiplies the error by the adaptation parameter, controller gain (Kc), and applies it as the control output.

The updateAdaptationParam function updates the adaptation parameter based on the derivative of the error and the control output.
It calculates the derivative error by comparing the current control output and the previous control output, divided by
the difference in measured speed. The adaptation parameter is updated by adding the product of the derivative error and the adaptation rate (Lambda).

The main function demonstrates how to use the strControl function and the updateAdaptationParam function
by providing sample values for the reference speed, measured speed, and adaptation parameter.
It calculates the control output, updates the adaptation parameter, and prints the control output to the console.

Please note that this is a simplified example, and in a real-world scenario, you would need to consider the specific motor dynamics,
tuning of parameters, and implementation details based on the control requirements of your motor system.

 */


#include <stdio.h>

// Constants for the STR algorithm
#define Kc 0.5  // Initial controller gain
#define Lambda 0.1  // Adaptation rate

// Function to calculate the STR control output
float strControl(float reference_speed, float measured_speed, float adaptation_param)
{
    static float control_output = 0.0;

    // Calculate the error
    float error = reference_speed - measured_speed;

    // Calculate the control output
    control_output = Kc * adaptation_param * error;

    return control_output;
}

// Function to update the adaptation parameter
float updateAdaptationParam(float adaptation_param, float measured_speed, float control_output)
{
    static float prev_error = 0.0;
    static float prev_control_output = 0.0;

    // Calculate the error derivative
    float derivative_error = (control_output - prev_control_output) / (measured_speed - prev_error);

    // Update the adaptation parameter
    adaptation_param += Lambda * derivative_error;

    // Store the current error and control output for the next iteration
    prev_error = measured_speed;
    prev_control_output = control_output;

    return adaptation_param;
}

int main3()
{
    float reference_speed = 100.0; // Desired speed reference
    float measured_speed = 85.0; // Measured speed of the motor
    float adaptation_param = 1.0; // Initial value for the adaptation parameter

    // Calculate the STR control output
    float control_output = strControl(reference_speed, measured_speed, adaptation_param);

    // Update the adaptation parameter
    adaptation_param = updateAdaptationParam(adaptation_param, measured_speed, control_output);

    printf("Control Output: %f\n", control_output);

    return 0;
}
///////////////////////
/*
In this example, the adaptivePIControl function calculates the adaptive PI control
output based on the reference speed, measured speed, and the current values of the
 proportional gain (Kp) and integral gain (Ki). The function also updates the integral term.

The gradientDescentAdaptation function performs the gradient descent adaptation to
 adjust the gains (Kp and Ki) based on the error between the reference speed and the
 measured speed. It iteratively updates the gains using the gradients of the error
  with respect to the gains.

The main function demonstrates the usage of the adaptive PI control and the gradient
descent adaptation. It initializes the gains, performs the adaptation, and calculates
 the control output. The control output is then printed to the console.

Please note that this is a simplified example, and in a real-world scenario, you would
 need to consider the specific motor dynamics, tuning of parameters, and implementation
 details based on the control requirements of your motor system. Additionally, gradient
  descent may not always be the most suitable adaptation algorithm for every situation,
  and other algorithms may be more appropriate depending on the system characteristics
  and control objectives.
 */


// Constants for the adaptive PI control
#define Kp_initial 1.0  // Initial proportional gain
#define Ki_initial 0.5  // Initial integral gain
#define Learning_rate 0.01  // Learning rate for adaptation
#define Max_iterations 1000  // Maximum number of iterations for adaptation

// Function to calculate the adaptive PI control output
float adaptivePIControl(float reference_speed, float measured_speed, float *Kp, float *Ki)
{
    static float integral_term = 0.0;
    float error = reference_speed - measured_speed;

    // Update the integral term
    integral_term += error;

    // Calculate the control output
    float control_output = (*Kp) * error + (*Ki) * integral_term;

    return control_output;
}

// Function to perform gradient descent adaptation
void gradientDescentAdaptation(float reference_speed, float measured_speed, float *Kp, float *Ki)
{
    int iteration;
    float error;
    float Kp_gradient, Ki_gradient;

    for (iteration = 0; iteration < Max_iterations; iteration++)
    {
        // Calculate the error
        error = reference_speed - measured_speed;

        // Calculate the gradients
        Kp_gradient = error;
        Ki_gradient = error;

        // Update the gains using gradient descent
        *Kp += Learning_rate * Kp_gradient;
        *Ki += Learning_rate * Ki_gradient;
    }
}

int main4()
{
    float reference_speed = 100.0;  // Desired speed reference
    float measured_speed = 85.0;  // Measured speed of the motor

    // Initialize the gains
    float Kp = Kp_initial;
    float Ki = Ki_initial;

    // Perform gradient descent adaptation
    gradientDescentAdaptation(reference_speed, measured_speed, &Kp, &Ki);

    // Calculate the adaptive PI control output
    float control_output = adaptivePIControl(reference_speed, measured_speed, &Kp, &Ki);

    printf("Control Output: %f\n", control_output);

    return 0;
}



/////////////////////////////////////////////////////
/*
In this example, the adaptivePIControl function calculates the adaptive PI control
 output based on the reference speed, measured speed, and the current values of the
 proportional gain (Kp) and integral gain (Ki). The function also updates the integral term.

The rlsAdaptation function performs the Recursive Least Squares (RLS) adaptation to
 adjust the gains (Kp and Ki) based on the error between the reference speed and the
  measured speed. It iteratively updates the estimates of the gains and the covariance
  matrix using the RLS algorithm.

The main function demonstrates the usage of the adaptive PI control and the RLS adaptation.
 It initializes the gains and covariance matrix, performs the adaptation, and calculates
 the control output. The control output is then printed to the console.

Please note that this is a simplified example, and in a real-world scenario, you would
need to consider the specific motor dynamics, tuning of parameters, and implementation
details based on the control requirements of your motor system. Additionally, the RLS
algorithm may require additional considerations such as regularization techniques to
 handle numerical stability and noise in the measurements.
 */

#include <stdio.h>
#include <math.h>

// Constants for the adaptive PI control and RLS algorithm
#define Lambda 0.9  // Forgetting factor
#define Initial_estimate 1.0  // Initial estimate for covariance matrix
#define Max_iterations 1000  // Maximum number of iterations for adaptation

// Function to calculate the adaptive PI control output
float adaptivePIControl(float reference_speed, float measured_speed, float Kp, float Ki)
{
    static float integral_term = 0.0;
    float error = reference_speed - measured_speed;

    // Update the integral term
    integral_term += error;

    // Calculate the control output
    float control_output = Kp * error + Ki * integral_term;

    return control_output;
}

// Function to perform Recursive Least Squares (RLS) adaptation
void rlsAdaptation(float reference_speed, float measured_speed, float *Kp, float *Ki, float *P)
{
    int iteration;
    float error;
    float integral_term = 0.0;
    float Kp_estimate = *Kp;
    float Ki_estimate = *Ki;
    float P_estimate = *P;

    for (iteration = 0; iteration < Max_iterations; iteration++)
    {
        // Calculate the error
        error = reference_speed - measured_speed;

        // Update the integral term
        integral_term += error;

        // Calculate the gain vector
        float K_vector = P_estimate * integral_term / (Lambda + integral_term * P_estimate * integral_term);

        // Update the estimates
        Kp_estimate += K_vector * error;
        Ki_estimate += K_vector * integral_term;
        P_estimate = P_estimate / (Lambda + integral_term * P_estimate * integral_term);

        // Update the gains
        *Kp = Kp_estimate;
        *Ki = Ki_estimate;
        *P = P_estimate;
    }
}

int main()
{
    float reference_speed = 100.0;  // Desired speed reference
    float measured_speed = 85.0;  // Measured speed of the motor

    // Initialize the gains and covariance matrix
    float Kp = 1.0;
    float Ki = 0.5;
    float P = Initial_estimate;

    // Perform RLS adaptation
    rlsAdaptation(reference_speed, measured_speed, &Kp, &Ki, &P);

    // Calculate the adaptive PI control output
    float control_output = adaptivePIControl(reference_speed, measured_speed, Kp, Ki);

    printf("Control Output: %f\n", control_output);

    return 0;
}
/////////////////////////////////////////////////////
/*
In this example, the adaptivePIControl function calculates the adaptive PI
control output based on the reference speed, measured speed, and the current
values of the proportional gain (Kp) and integral gain (Ki). The function also
 updates the integral term.

The lmsAdaptation function performs the Least Mean Squares (LMS) adaptation to
adjust the gains (Kp and Ki) based on the error between the reference speed and
the measured speed. It iteratively updates the estimates of the gains using the
LMS algorithm.

The main function demonstrates the usage of the adaptive PI control and the
 LMS adaptation. It initializes the gains, performs the adaptation, and calculates
 the control output. The control output is then printed to the console.

Please note that this is a simplified example, and in a real-world scenario, you
 would need to consider the specific motor dynamics, tuning of parameters, and
 implementation details based on the control requirements of your motor system.
  Additionally, the LMS algorithm may require additional considerations such as
  step-size adaptation techniques or regularization to improve convergence and handle
   noise in the measurements.
 */

// Constants for the adaptive PI control and LMS algorithm
#define Step_size 0.01  // Step size for adaptation
#define Max_iterations 1000  // Maximum number of iterations for adaptation

// Function to calculate the adaptive PI control output
float adaptivePIControl(float reference_speed, float measured_speed, float Kp, float Ki)
{
    static float integral_term = 0.0;
    float error = reference_speed - measured_speed;

    // Update the integral term
    integral_term += error;

    // Calculate the control output
    float control_output = Kp * error + Ki * integral_term;

    return control_output;
}

// Function to perform Least Mean Squares (LMS) adaptation
void lmsAdaptation(float reference_speed, float measured_speed, float *Kp, float *Ki)
{
    int iteration;
    float error;
    float integral_term = 0.0;
    float Kp_estimate = *Kp;
    float Ki_estimate = *Ki;

    for (iteration = 0; iteration < Max_iterations; iteration++)
    {
        // Calculate the error
        error = reference_speed - measured_speed;

        // Update the integral term
        integral_term += error;

        // Update the estimates
        Kp_estimate += Step_size * error;
        Ki_estimate += Step_size * integral_term;

        // Update the gains
        *Kp = Kp_estimate;
        *Ki = Ki_estimate;
    }
}

int main()
{
    float reference_speed = 100.0;  // Desired speed reference
    float measured_speed = 85.0;  // Measured speed of the motor

    // Initialize the gains
    float Kp = 1.0;
    float Ki = 0.5;

    // Perform LMS adaptation
    lmsAdaptation(reference_speed, measured_speed, &Kp, &Ki);

    // Calculate the adaptive PI control output
    float control_output = adaptivePIControl(reference_speed, measured_speed, Kp, Ki);

    printf("Control Output: %f\n", control_output);

    return 0;
}

//////////////////////////////////////////////


/*
In this example, the adaptiveControl function calculates the adaptive control
 output based on the reference input and the measured output of the plant.
 It also updates the state variable and adapts the plant parameters using the
 MRAC algorithm.

The state variable represents the internal state of the plant model and is
 updated using the plant gain and the difference between the reference input
 and the current state variable multiplied by the adaptation rate.

The control output is calculated using the updated state variable.

The plant parameters, including the gain and time constant, are adapted using
the error between the measured output and the reference input, the state
variable, and the adaptation rate.

The main function demonstrates the usage of the adaptive control and the MRAC
algorithm. It initializes the plant parameters, performs the adaptation, and
calculates the control output. The control output is then printed to the console.

Please note that this is a simplified example, and in a real-world scenario,
you would need to consider the specific plant dynamics, tuning of parameters,
and implementation details based on the control requirements of your system.
Additionally, the MRAC algorithm may require additional considerations such as
stability analysis, anti-windup techniques, and robustness enhancements to handle
 modeling uncertainties and external disturbances.
 */

// Constants for the model reference adaptive control (MRAC)
#define Adaptation_rate 0.01  // Adaptation rate for parameter updates
#define Reference_model_gain 1.0  // Gain of the reference model
#define Reference_model_time_constant 1.0  // Time constant of the reference model

// Function to calculate the adaptive control output
float adaptiveControl(float reference_input, float measured_output, float *plant_gain, float *plant_time_constant)
{
    static float state_variable = 0.0;
    float control_output;

    // Update the state variable using the plant model
    state_variable += (*plant_gain) * (reference_input - state_variable) * Adaptation_rate;

    // Calculate the control output using the updated state variable
    control_output = state_variable;

    // Adapt the plant parameters using the error between the measured output and the reference input
    float error = reference_input - measured_output;
    *plant_gain += error * state_variable * Adaptation_rate;
    *plant_time_constant += error * state_variable * state_variable * Adaptation_rate;

    return control_output;
}

int main()
{
    float reference_input = 1.0;  // Desired reference input
    float measured_output = 0.0;  // Measured output of the plant

    // Initialize the plant parameters
    float plant_gain = 0.5;
    float plant_time_constant = 0.75;

    // Calculate the adaptive control output
    float control_output = adaptiveControl(reference_input, measured_output, &plant_gain, &plant_time_constant);

    printf("Control Output: %f\n", control_output);

    return 0;
}
////////////////////////////////////////////

#include <stdio.h>

// Constants for the PID control
#define Kp 1.0  // Proportional gain
#define Ki 0.5  // Integral gain
#define Kd 0.2  // Derivative gain

// Function to calculate the PID control output
float PIDControl(float reference_value, float measured_value, float *previous_error, float *integral)
{
    float error = reference_value - measured_value;
    float derivative = error - (*previous_error);

    // Update the integral term
    *integral += error;

    // Calculate the control output
    float control_output = Kp * error + Ki * (*integral) + Kd * derivative;

    // Update the previous error
    *previous_error = error;

    return control_output;
}

int main()
{
    float reference_value = 10.0;  // Desired reference value
    float measured_value = 8.0;  // Measured value

    // Initialize variables for PID control
    float previous_error = 0.0;
    float integral = 0.0;

    // Calculate the PID control output
    float control_output = PIDControl(reference_value, measured_value, &previous_error, &integral);

    printf("Control Output: %f\n", control_output);

    return 0;
}
