// 文件编码: GB18030
/*
 * pid.c
 *
 *  Created on: 2025年3月25日
 *      Author: LHYe200
 */

#include "pid.h"
#include "math.h"


void PID_Init(PID *pid, float kp, float ki, float kd, float integral_max, float output_max, float output_min)
{
    pid->kp = kp;
    pid->ki = ki;
    pid->kd = kd;

    pid->integral_max = integral_max;

    pid->output_max = output_max;
    pid->output_min = output_min;

    pid->p_output = 0;
    pid->i_output = 0;
    pid->d_output = 0;
    pid->output = 0;

    pid->err = 0;
    pid->err_last = 0;
    pid->last_derivative = 0;
    pid->integral = 0;
}

/*************************************************************************
*  函数名称：float constrain_float(float amt, float low, float high)
*  功能说明：限幅函数
*  参数说明：
* @param    amt   ： 参数
* @param    low   ： 最低值
* @param    high  ： 最高值
*  函数返回：限幅结果
*************************************************************************/
float constrain_float(float amt, float low, float high)
{
    return ((amt)<(low)?(low):((amt)>(high)?(high):(amt)));
}


void PID_Reset(PID *pid)
{
    pid->p_output = 0;
    pid->i_output = 0;
    pid->d_output = 0;
    pid->output = 0;

    pid->err = 0;
    pid->err_last = 0;
    pid->last_derivative = 0;
    pid->integral = 0;
}

/*************************************************************************
*  函数名称：float PidLocCtrl(pid_param_t * pid, float err)
*  功能说明：pid位置式控制器输出
*  参数说明：
* @param    pid     pid参数
* @param    err   pid输入误差
*  函数返回：PID输出结果
*************************************************************************/

float PID_Loc_Ctrl(PID * pid, float err)
{
    /* 累积误差 */
    pid->err = err;
    pid->integral += pid->err;

    /* 误差限幅 */

    pid->integral=constrain_float(pid->integral, -pid->integral_max, pid->integral_max);
    pid->p_output = pid->kp * pid->err;
    pid->i_output = pid->ki * pid->integral;
    pid->d_output = pid->kd * (pid->err - pid->err_last);

    pid->err_last = pid->err;

    pid->output = constrain_float(pid->p_output + pid->i_output + pid->d_output,pid->output_min,pid->output_max);

    return pid->output;
}


/*************************************************************************
*  函数名称：PidIncCtrl(pid_param_t * pid, float err)
*  功能说明：pid增量式控制器输出
*  参数说明：
* @param    pid     pid参数
* @param    err   pid输入误差
*  函数返回：PID输出结果   注意输出结果已经包涵了上次结果
*************************************************************************/
float PID_Inc_Ctrl(PID * pid, float err)
{
    pid->p_output = pid->kp * (err - pid->err_last);
    // pid->i_output = pid->ki * err;
    pid->i_output = pid->ki * constrain_float(err, -pid->integral_max, pid->integral_max);
    pid->d_output = pid->kd * ((err - pid->err_last) - pid->last_derivative);

    pid->last_derivative = err - pid->err_last;
    pid->err_last = err;

    pid->output += pid->p_output + pid->i_output + pid->d_output;
    pid->output = constrain_float(pid->output,pid->output_min,pid->output_max);
    return pid->output;
}


float PID_ChangeIntegral_Inc_Ctrl(PID * pid, float err, float change_integral_b, float change_integral_k)
{
    pid->p_output = pid->kp * (err - pid->err_last);
    // pid->i_output = pid->ki * err;
    float ki_c = pid->ki;
    if(err + pid->err_last > 0)
    {
        ki_c = pid->ki - pid->ki / (1 + expf(change_integral_b - fabsf(err) * change_integral_k));
    }
    pid->i_output = ki_c * constrain_float(err, -pid->integral_max, pid->integral_max);
    pid->d_output = pid->kd * ((err - pid->err_last) - pid->last_derivative);

    pid->last_derivative = err - pid->err_last;
    pid->err_last = err;

    pid->output += pid->p_output + pid->i_output + pid->d_output;
    pid->output = constrain_float(pid->output,pid->output_min,pid->output_max);
    return pid->output;
}

