/*
 * @Author: wzh
 * @Date: 2024-05-27 08:57:33
 * @LastEditors: mypx mypx_coder@163.com
 * @LastEditTime: 2025-09-16 15:28:47
 * @Description:
 *
 * Copyright (c) 2024 by wzh, All Rights Reserved.
 */
#ifndef __ETK_PID_H__
#define __ETK_PID_H__
#include "etk_utils.h"
/**
 * @brief Structure for the positional PID controller.
 */
typedef struct
{
    float  kp;              /**< Proportional gain */
    float  ki;              /**< Integral gain */
    float  kd;              /**< Derivative gain */
    float  set_point;       /**< Desired target value */
    float  prev_error;      /**< Previous error for derivative calculation */
    float  integral;        /**< Integral term to accumulate the error */
    float  integral_limit;  /**< Maximum limit for integral term to prevent wind-up */
    float  prev_derivative; /**< Previous derivative term for filtering */
    float  min_output;
    float  max_output;
    int8_t direction; /**< Error direction control: 1 for normal, -1 for inverted */
} etk_pos_pid_t;

/**
 * @brief Structure for the incremental PID controller.
 */
typedef struct
{
    float kp;          /**< Proportional gain */
    float ki;          /**< Integral gain */
    float kd;          /**< Derivative gain */
    float set_point;   /**< Desired target value */
    float prev_error;  /**< Previous error for derivative calculation */
    float prev2_error; /**< Previous second error for derivative calculation */
    float prev_output; /**< Previous output for incremental calculation */
    float max_output;
    float min_output;
    float max_integral;
    float integral_sum;
} et_inc_pid_t;
/**
 * @brief Structure for the fuzzy PID controller.
 */
typedef struct
{
    float error;      /**< Current error */
    float prev_error; /**< Previous error */
    float integral;   /**< Integral term */
    float kp;         /**< Proportional gain */
    float ki;         /**< Integral gain */
    float kd;         /**< Derivative gain */
    float set_point;  /**< Desired target value */
} et_fuzzy_pid_t;

/**
 * @brief Structure for the adaptive PID controller.
 */
typedef struct
{
    float kp;         /**< Proportional gain */
    float ki;         /**< Integral gain */
    float kd;         /**< Derivative gain */
    float adapt_gain; /**< Gain for adapting PID parameters */
    float set_point;  /**< Desired target value */
    float prev_error; /**< Previous error */
    float integral;   /**< Integral term */
} et_adaptive_pid_t;

/**
 * @brief Structure for the integral separation PID controller.
 */
typedef struct
{
    float kp;                 /**< Proportional gain */
    float ki;                 /**< Integral gain */
    float kd;                 /**< Derivative gain */
    float set_point;          /**< Desired target value */
    float prev_error;         /**< Previous error */
    float integral;           /**< Integral term */
    float integral_threshold; /**< Threshold for enabling integral action */
} et_integral_separation_pid_t;

/**
 * @brief Structure for the feed forward PID controller.
 */
typedef struct
{
    float kp;         /**< Proportional gain */
    float ki;         /**< Integral gain */
    float kd;         /**< Derivative gain */
    float ff_gain;    /**< Feed forward gain */
    float set_point;  /**< Desired target value */
    float prev_error; /**< Previous error */
    float integral;   /**< Integral term */
} et_ff_pid_t;

/**
 * @brief Structure for the digital PID controller.
 */
typedef struct
{
    float kp;         /**< Proportional gain */
    float ki;         /**< Integral gain */
    float kd;         /**< Derivative gain */
    float set_point;  /**< Desired target value */
    float prev_error; /**< Previous error */
    float integral;   /**< Integral term */
} et_digital_pid_t;

#ifdef __cplusplus
extern "C"
{
#endif
/**
     * @brief Initialize a positional PID controller with specified gains.
     * @param pid Pointer to the positional PID structure to initialize.
     * @param kp Proportional gain.
     * @param ki Integral gain.
     * @param kd Derivative gain.
     * @param set_point Desired target value.
     * @param integral_limit Maximum limit for the integral term to prevent wind-up.
     */
int etk_position_pid_init(etk_pos_pid_t *pid, float kp, float ki, float kd, float set_point, float integral_limit,
                         float min_output, float max_output, int8_t direction);

/**
 * @brief Update the positional PID controller output based on feedback.
 * @param pid Pointer to the positional PID structure.
 * @param feedback Current feedback value from the system.
 * @param dt Time difference (in seconds) between the current and previous update.
 * @param derivative_filter_gain Gain for smoothing the derivative term.
 * @return PID output after applying the control law.
*/
float etk_position_pid_update(etk_pos_pid_t *pid, float feedback, float dt, float derivative_filter_gain);

/**
     * @brief Update the set point of the positional PID controller.
     * @param pid Pointer to the positional PID structure.
     * @param set_point New desired target value.
     */
void etk_position_pid_update_set_point(etk_pos_pid_t *pid, float set_point);

/**
     * @brief Reset the states of the positional PID controller.
     * @param pid Pointer to the positional PID structure.
     */
void etk_position_pid_reset(etk_pos_pid_t *pid);

/**
     * @brief Set the direction control for positional PID controller.
     * @param pid Pointer to the positional PID structure.
     * @param direction Error direction: 1 for normal, -1 for inverted.
     */
void etk_position_pid_set_direction(etk_pos_pid_t *pid, int8_t direction);

/**
     * @brief Initialize an incremental PID controller with specified gains.
     * @param pid Pointer to the incremental PID structure.
     * @param kp Proportional gain.
     * @param ki Integral gain.
     * @param kd Derivative gain.
     */
// void et_incremental_pid_init(et_inc_pid_t *pid, float kp, float ki, float kd);

void et_incremental_pid_init(et_inc_pid_t *pid, float kp, float ki, float kd, float min_output, float max_output);

/**
     * @brief Set a new set point for the incremental PID controller.
     * @param pid Pointer to the incremental PID structure.
     * @param set_point New target set point.
     */
void et_incremental_pid_set_point(et_inc_pid_t *pid, float set_point);

/**
     * @brief Reset the states of the incremental PID controller.
     * @param pid Pointer to the incremental PID structure.
     */
void et_incremental_pid_reset(et_inc_pid_t *pid);

/**
     * @brief Update the incremental PID controller with current feedback.
     * @param pid Pointer to the incremental PID structure.
     * @param feedback Current feedback value.
     * @return The output value after applying the control law.
     */
float et_incremental_pid_update(et_inc_pid_t *pid, float feedback);

/**
     * @brief Initialize a fuzzy PID controller with specified gains.
     * @param pid Pointer to the fuzzy PID structure.
     * @param kp Proportional gain.
     * @param ki Integral gain.
     * @param kd Derivative gain.
     */
void fuzzy_pid_init(et_fuzzy_pid_t *pid, float kp, float ki, float kd);

/**
     * @brief Update the fuzzy PID controller based on feedback and adjust gains.
     * @param pid Pointer to the fuzzy PID structure.
     * @param set_point Desired target value.
     * @param feedback Current feedback value.
     * @param dt Time difference since the last update.
     * @return The PID output after fuzzy adjustment.
     */
float fuzzy_pid_update(et_fuzzy_pid_t *pid, float set_point, float feedback, float dt);

/**
     * @brief Initialize an adaptive PID controller with specified gains.
     * @param pid Pointer to the adaptive PID structure.
     * @param kp Proportional gain.
     * @param ki Integral gain.
     * @param kd Derivative gain.
     * @param adapt_gain Gain for adapting PID parameters.
     */
void et_adaptive_pid_init(et_adaptive_pid_t *pid, float kp, float ki, float kd, float adapt_gain);

/**
     * @brief Update the adaptive PID controller output based on feedback.
     * @param pid Pointer to the adaptive PID structure.
     * @param feedback Current feedback value.
     * @param dt Time difference since the last update.
     * @return The adaptive PID output after applying the control law.
     */
float et_adaptive_pid_update(et_adaptive_pid_t *pid, float feedback, float dt);

/**
     * @brief Initialize an integral separation PID controller.
     * @param pid Pointer to the integral separation PID structure.
     * @param kp Proportional gain.
     * @param ki Integral gain.
     * @param kd Derivative gain.
     * @param threshold Threshold for enabling integral action.
     */
void et_integral_separation_pid_init(et_integral_separation_pid_t *pid, float kp, float ki, float kd, float threshold);

/**
     * @brief Update the integral separation PID controller output based on feedback.
     * @param pid Pointer to the integral separation PID structure.
     * @param feedback Current feedback value.
     * @param dt Time difference since the last update.
     * @return PID output after applying the control law.
     */
float et_integral_separation_pid_update(et_integral_separation_pid_t *pid, float feedback, float dt);

void et_integral_separation_pid_reset(et_integral_separation_pid_t *pid);
/**
     * @brief Initialize a feed forward PID controller with specified gains.
     * @param pid Pointer to the feed forward PID structure to initialize.
     * @param kp Proportional gain.
     * @param ki Integral gain.
     * @param kd Derivative gain.
     * @param ff_gain Feed forward gain to adjust the system based on disturbance.
     */
void et_ff_pid_init(et_ff_pid_t *pid, float kp, float ki, float kd, float ff_gain);

/**
     * @brief Update the feed forward PID controller output based on feedback and disturbance.
     * @param pid Pointer to the feed forward PID structure.
     * @param feedback Current feedback value from the system.
     * @param disturbance External disturbance affecting the system (to be compensated with feed forward).
     * @param dt Time difference (in seconds) between the current and previous update.
     * @return The PID output after applying the control law and feed forward compensation.
     */
float et_ff_pid_update(et_ff_pid_t *pid, float feedback, float disturbance, float dt);

/**
     * @brief Initialize a digital PID controller with specified gains.
     * @param pid Pointer to the digital PID structure to initialize.
     * @param kp Proportional gain.
     * @param ki Integral gain.
     * @param kd Derivative gain.
     */
void et_digital_pid_init(et_digital_pid_t *pid, float kp, float ki, float kd);

/**
     * @brief Update the digital PID controller output based on feedback.
     * @param pid Pointer to the digital PID structure.
     * @param feedback Current feedback value.
     * @param dt Time difference (in seconds) since the last update.
     * @return The digital PID output after applying the control law.
     */
float et_digital_pid_update(et_digital_pid_t *pid, float feedback, float dt);
/**
     * @brief Cascade control: outer positional PID and inner feed-forward PID.
     * @param outer_pid Pointer to the outer positional PID structure.
     * @param inner_pid Pointer to the inner feed-forward PID structure.
     * @param outer_feedback Feedback value for the outer loop.
     * @param inner_feedback Feedback value for the inner loop.
     * @param disturbance External disturbance for feed-forward compensation.
     * @param dt Time difference (in seconds) between updates.
     * @return The final output of the cascaded controller.
     */
float et_cascade_pos_ff_pid(etk_pos_pid_t *outer_pid, et_ff_pid_t *inner_pid, float outer_feedback, float inner_feedback,
                            float disturbance, float dt);

/**
     * @brief Cascade control: outer adaptive PID and inner integral separation PID.
     * @param outer_pid Pointer to the outer adaptive PID structure.
     * @param inner_pid Pointer to the inner integral separation PID structure.
     * @param outer_feedback Feedback value for the outer loop.
     * @param inner_feedback Feedback value for the inner loop.
     * @param dt Time difference (in seconds) between updates.
     * @return The final output of the cascaded controller.
     */
float et_cascade_adaptive_integral_pid(et_adaptive_pid_t *outer_pid, et_integral_separation_pid_t *inner_pid,
                                       float outer_feedback, float inner_feedback, float dt);

/**
     * @brief Cascade control: outer fuzzy PID and inner incremental PID.
     * @param outer_pid Pointer to the outer fuzzy PID structure.
     * @param inner_pid Pointer to the inner incremental PID structure.
     * @param outer_feedback Feedback value for the outer loop.
     * @param inner_feedback Feedback value for the inner loop.
     * @param dt Time difference (in seconds) between updates.
     * @return The final output of the cascaded controller.
     */
float et_cascade_fuzzy_inc_pid(et_fuzzy_pid_t *outer_pid, et_inc_pid_t *inner_pid, float outer_feedback,
                               float inner_feedback, float dt);

#ifdef __cplusplus
}
#endif

#endif
