#include "Chassis.h"
#include "gpio.h"
#include "user_math.h"
#include "bsp_buzzer.h"
#include "bsp_delay.h"

/*
机器人坐标系，向前x，右y，上yaw
不同于nuc (前x，左y，上yaw)
            x
            |
              --y
*/

static int8_t Chassis_SetCtrl(Chassis_t *c, CMD_t *ctrl) {
    if (c == NULL) return CHASSIS_ERR_NULL;
    if (ctrl->CMD_CtrlType == c->chassis_ctrl.ctrl && ctrl->CMD_mode == c->chassis_ctrl.mode)
        return CHASSIS_OK;
    c->chassis_ctrl.ctrl = ctrl->CMD_CtrlType;
    c->chassis_ctrl.mode = ctrl->CMD_mode;
    return CHASSIS_OK;
}

int8_t Chassis_UpdateFeedback(Chassis_t *c, const CAN_t *can) {
    if (c == NULL) return CHASSIS_ERR_NULL;
    if (can == NULL) return CHASSIS_ERR_NULL;
    for (uint8_t i = 0; i < 4; i++) {
        c->motorfeedback.rotor_rpm3508[i] = can->motor.chassis_motor3508.as_array[i].rotor_speed;
        c->motorfeedback.rotor_current3508[i] = can->motor.chassis_motor3508.as_array[i].torque_current;
    }
    for (uint8_t i = 0; i < 4; i++) {
		
		c->sick_cali.sick_dis[i]=can->sickfed.raw_dis[i] / 10; //没使用原值
    }
			
    return CHASSIS_OK;
}

int8_t Chassis_init(Chassis_t *c, const Chassis_Param_t *param, float target_freq) {
    if (c == NULL) return CHASSIS_ERR_NULL;
    c->param = param;

    for (int i = 0; i < 4; i++) {
        PID_init(&(c->pid.chassis_3508VecPID[i]), PID_POSITION_D, &(c->param->M3508_param));
    }
    PID_init(&(c->pid.chassis_PICKWzPID_HIGN), PID_POSITION, &(c->param->chassis_PICKWzPID_HIGN_param));
    PID_init(&(c->pid.chassis_PICKWzPID_LOW), PID_POSITION, &(c->param->chassis_PICKWzPID_LOW_param));
    PID_init(&(c->pid.SickCaliWzPID), PID_POSITION, &(c->param->Sick_CaliWparam));
    PID_init(&(c->pid.SickCaliVxPID), PID_POSITION, &(c->param->Sick_CaliXparam));
    PID_init(&(c->pid.SickCaliVyPID), PID_POSITION, &(c->param->Sick_CaliYparam));
    PID_init(&(c->pid.Chassis_AngleAdjust), PID_POSITION, &(c->param->Chassis_AngleAdjust_param));	

    LowPassFilter2p_Init(&(c->filled[0]), target_freq, 80.0f); // 角加速度滤波
    LowPassFilter2p_Init(&(c->filled[1]), target_freq, 80.0f); // w滤波
    LowPassFilter2p_Init(&(c->filled[2]), target_freq, 80.0f); // y滤波
    LowPassFilter2p_Init(&(c->filled[3]), target_freq, 80.0f); // x滤波
		
		c->sick_cali .sickparam=c->param ->sickparam ;

    return CHASSIS_OK;
}

fp32 pian_yaw;
void Chassis_speed_calculate(Chassis_t *c, fp32 Vx, fp32 Vy, fp32 Vw) {
    fp64 Nor_Vx, Nor_Vy;
    normalize_vector(Vx, Vy, &Nor_Vx, &Nor_Vy);

    c->hopemotorout.OmniSpeedOut[0] = -Nor_Vx + Nor_Vy + Vw+pian_yaw; // 右前
    c->hopemotorout.OmniSpeedOut[1] = -Nor_Vx - Nor_Vy + Vw+pian_yaw; // 右后
    c->hopemotorout.OmniSpeedOut[2] = Nor_Vx - Nor_Vy + Vw +pian_yaw;  // 左后
    c->hopemotorout.OmniSpeedOut[3] = Nor_Vx + Nor_Vy + Vw +pian_yaw;  // 左前
	
		Chassis_AngleCompensate(c);

}
int8_t Chassis_Control(Chassis_t *c, CMD_t *ctrl, CAN_Output_t *out) {
    if (c == NULL) return CHASSIS_ERR_NULL;
    if (ctrl == NULL) return CHASSIS_ERR_NULL;

    Chassis_SetCtrl(c, ctrl);
    // IMU加滤波修正
    c->pos088.bmi088.filtered_gyro.z = LowPassFilter2p_Apply(&(c->filled[0]), c->pos088.bmi088.gyro.z);

    /*初始数据*/
    c->move_vec.Vw = 0;
    c->move_vec.Vx = 0;
    c->move_vec.Vy = 0;
    c->NUC_send.send[0] = 0;
    c->sick_cali.is_reach = 0;
	
    switch (c->chassis_ctrl.ctrl) {
        case RCcontrol:
            switch (c->chassis_ctrl.mode) {
                case Normal:
                    c->move_vec.Vw = ctrl->Vw * 8000;
                    c->move_vec.Vx = ctrl->Vy * 8000;
                    c->move_vec.Vy = ctrl->Vx * 8000;
                    break;
                case Pitch:
                     c->move_vec.Vw = ctrl->Vw * 6000;
                    c->move_vec.Vx = ctrl->Vy * 6000;
                    c->move_vec.Vy = ctrl->Vx * 6000;                  
                    break;
                case UP_Adjust:
                    c->move_vec.Vw = ctrl->Vw * 6000;
                    
                    break;
                case Chassis_Adjust_Sick:
									
                    sick_calibration(c, ctrl, out);
                    c->NUC_send.send[0] = (c->sick_cali.is_reach == 1) ? 1 : 0;
                    break;
                default:
                    
                    break;
            }
            break;

        case AUTO:
            switch (c->chassis_ctrl.mode) {
                case AUTO_MID360:
                    c->move_vec.Vw = ctrl->cmd_MID360.posw * 1000;
                    c->move_vec.Vy = -ctrl->cmd_MID360.posy * 1000;
                    c->move_vec.Vx = -ctrl->cmd_MID360.posx * 1000;
                    abs_limit_fp(&c->move_vec.Vx, 5000.0f);
                    abs_limit_fp(&c->move_vec.Vy, 5000.0f);
                    abs_limit_fp(&c->move_vec.Vw, 5000.0f);
								   // c->NUC_send.send[0] = 1;
                    break;
                case AUTO_MID360_Pitch:
                    
                    break;
                case AUTO_MID360_Adjust:
                    c->move_vec.Vw = ctrl->Vw * 6000;
                    c->move_vec.Vx = ctrl->Vy * 6000;
                    c->move_vec.Vy = ctrl->Vx * 6000;
                    
                    break;
								case PassBall:   //
                    c->move_vec.Vw = ctrl->cmd_MID360.posw * 1000;
                    c->move_vec.Vy = -ctrl->cmd_MID360.posy * 1000;
                    c->move_vec.Vx = -ctrl->cmd_MID360.posx * 1000;
                    abs_limit_fp(&c->move_vec.Vx, 5000.0f);
                    abs_limit_fp(&c->move_vec.Vy, 5000.0f);
                    abs_limit_fp(&c->move_vec.Vw, 5000.0f);									
								    break ;
                default:
                    
                    break;
            }
            break;

        default:
            
            break;
    }

    // 电机速度限幅
    abs_limit_fp(&c->move_vec.Vx, 6000.0f);
    abs_limit_fp(&c->move_vec.Vy, 6000.0f);
    abs_limit_fp(&c->move_vec.Vw, 6000.0f);

    Chassis_speed_calculate(c, c->move_vec.Vx, c->move_vec.Vy, c->move_vec.Vw);

    for (uint8_t i = 0; i < 4; i++) {
        c->final_out.final_3508out[i] = PID_calc(&(c->pid.chassis_3508VecPID[i]),
                                                 c->motorfeedback.rotor_rpm3508[i],
                                                 c->hopemotorout.OmniSpeedOut[i]);
        out->motor_CHASSIS3508.as_array[i] = c->final_out.final_3508out[i];
    }

    c->vofa_send[0] = (fp32)c->sick_cali.sick_dis[1] - c->sick_cali.sick_dis[2];
		
    return CHASSIS_OK;
		
		
		
}



/*
sick0,下
sick1,左2
sick2,左1


*/

int8_t sick_calibration(Chassis_t *c, CMD_t *ctrl, CAN_Output_t *out) 
{
    if (c == NULL) return CHASSIS_ERR_NULL;
    if (ctrl == NULL) return CHASSIS_ERR_NULL;

    
    fp32 sick0 = c->sick_cali.sick_dis[0] ;
    fp32 sick1 = c->sick_cali.sick_dis[1];
    fp32 sick2 = c->sick_cali.sick_dis[2];
    const   sickparam_t *param = &c->sick_cali.sickparam;

    fp32 diff_yaw = -(fp32)(sick1 - sick2);
    fp32 diff_y  = -(fp32)(sick1 - c->sick_cali.sickparam.y_set);
    fp32 diff_x  =  (fp32)(sick0 - c->sick_cali.sickparam.x_set);


    c->move_vec.Vw = (fabsf(diff_yaw) > param->w_error) ? PID_calc(&(c->pid.SickCaliWzPID), diff_yaw, 0) : 0;
    c->move_vec.Vx = (fabsf(diff_x)   > param->xy_error) ? PID_calc(&(c->pid.SickCaliVxPID), diff_x, 0) : 0;
    c->move_vec.Vy = (fabsf(diff_y)   > param->xy_error) ? PID_calc(&(c->pid.SickCaliVyPID), diff_y, 0) : 0;
		
    static uint16_t reach_cnt = 0;
    if (fabsf(diff_yaw) <= param->w_error &&
        fabsf(diff_x)   <= param->xy_error &&
        fabsf(diff_y)   <= param->xy_error) {
        reach_cnt++;
        if (reach_cnt >= 50) {
            
            c->sick_cali.is_reach = 1;
            
        }
    } else {
        reach_cnt = 0;
			  c->sick_cali.is_reach = 0;
    }	
		
    return CHASSIS_OK;
}

int8_t Chassis_AngleCompensate(Chassis_t *c) 
{
	  if (c == NULL) return CHASSIS_ERR_NULL;
    static fp32 pian_angel,cur_angle;
	  if((c->move_vec.Vx || c->move_vec.Vy) && (c->move_vec.Vw== 0))
    {
		   pian_angel=cur_angle-AngleChange(DEGREE,c->pos088.imu_eulr.yaw);		
		}

		else	{
			 cur_angle=AngleChange(DEGREE,c->pos088.imu_eulr.yaw);			
       pian_angel=0;
		}
    pian_yaw = PID_calc(&c->pid.Chassis_AngleAdjust,pian_angel,0);
}


