#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 osThreadId_t thread_alert;

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 ShootGame_FlagSet(void)
//{
//  osThreadFlagsSet(thread_alert, SIGNAL_NUC_RAW_REDY);
//  
//}
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; //没使用原值
//    }
		c->sick_cali.sick_dis[0]=(fp32)(can->sickfed.raw_dis[0]) ;
		c->sick_cali.sick_dis[1]=(fp32)(can->sickfed.raw_dis[1]+26) ;  //有点误差，手动补偿
		c->sick_cali.sick_dis[2]=(fp32)(can->sickfed.raw_dis[2] );
		
//		c->vofa_send[7] =c->sick_cali.sick_dis[0]-c->sick_cali.sick_dis[1];
//		c->vofa_send[6] = c->sick_cali.sick_dis[0];
//		c->vofa_send[5] =c->sick_cali.sick_dis[1];
//		c->vofa_send[4] =c->sick_cali.sick_dis[2];
    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;
	  if ((thread_alert = osThreadGetId()) == 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));
    /*sick*/
    PID_init(&(c->pid.SickCaliWzInPID), PID_POSITION, &(c->param->SickCali_WInparam));
    PID_init(&(c->pid.SickCaliWzOutPID), PID_POSITION, &(c->param->SickCali_WOutparam));
    PID_init(&(c->pid.SickCaliVxInPID), PID_POSITION, &(c->param->SickCali_XInparam));
    PID_init(&(c->pid.SickCaliVxOutPID), PID_POSITION, &(c->param->SickCali_XOutparam));
    PID_init(&(c->pid.SickCaliVyInPID), PID_POSITION, &(c->param->SickCali_YInparam));
    PID_init(&(c->pid.SickCaliVyOutPID), PID_POSITION, &(c->param->SickCali_YOutparam));
    /*修正 */
    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); 
    LowPassFilter2p_Init(&(c->filled[4]), target_freq, 80.0f); 
    LowPassFilter2p_Init(&(c->filled[5]), target_freq, 80.0f);
    LowPassFilter2p_Init(&(c->filled[6]), target_freq, 80.0f);
    LowPassFilter2p_Init(&(c->filled[7]), target_freq, 80.0f); 
		
		c->sick_cali .sickparam=c->param ->sickparam ;

    return CHASSIS_OK;
}

fp32 pian_yaw;

fp32 qian_Nor_Vx;
fp32 hou_Nor_Vx;

void Chassis_speed_calculate(Chassis_t *c, fp32 Vx, fp32 Vy, fp32 Vw) {

    fp32 Nor_Vx, Nor_Vy;
    
    normalize_vector(Vx, Vy, &Nor_Vx, &Nor_Vy);  //速度归一，防止斜跑速度最快
	  qian_Nor_Vx=Nor_Vx;
   	ChassisHeadlessMode(&Nor_Vx,&Nor_Vy,c->pos088.imu_eulr.yaw);
    hou_Nor_Vx=Nor_Vx;


    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);

}
int i=0;
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->NUC_send.send[0] = 0;
//    c->sick_cali.is_reach = 0;
	
    switch (c->chassis_ctrl.ctrl) {
			case ShootGame_Mode:  //投球赛模式
				i=(osThreadFlagsWait(SHOOT_GAME_FLAG, osFlagsWaitAny, 0)==SHOOT_GAME_FLAG);
		if (ctrl->Vw != 0 || ctrl->Vy != 0 || ctrl->Vx != 0) {
        // 有遥控器输出，设置标志位1
        osThreadFlagsSet(thread_alert, SHOOT_GAME_FLAG);
			
    } else {
        // 无输出，清除标志位1
        osThreadFlagsClear( SHOOT_GAME_FLAG);
    }
			
		if(osThreadFlagsWait(SHOOT_GAME_FLAG, osFlagsWaitAny, 0)==SHOOT_GAME_FLAG) 
		{
				c->move_vec.Vw = ctrl->Vw * 8000;
				c->move_vec.Vx = ctrl->Vy * 8000;
				c->move_vec.Vy = ctrl->Vx * 8000;			
	  }else {
				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;		
     		
			case RCcontrol:
			
				c->move_vec.Vw = ctrl->Vw * 8000;
				c->move_vec.Vx = ctrl->Vy * 8000;
				c->move_vec.Vy = ctrl->Vx * 8000;				
			
			
			break;
			default:
			c->move_vec.Vw = 0;
			c->move_vec.Vx = 0;
			c->move_vec.Vy = 0;					
			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];
    }


		
    return CHASSIS_OK;
		
		
		
}



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


*/
fp32 diff_yaw,diff_y,diff_x;
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 delta_w,delta_x,delta_y; 
     
    fp32 sick0 =LowPassFilter2p_Apply( &(c->filled[5]),c->sick_cali.sick_dis[0]) ;
    fp32 sick1 =LowPassFilter2p_Apply( &(c->filled[6]), c->sick_cali.sick_dis[1]) ;
    fp32 sick2 = LowPassFilter2p_Apply( &(c->filled[7]),c->sick_cali.sick_dis[2] );
    const   sickparam_t *param = &c->sick_cali.sickparam;

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

    delta_w=PID_calc(&c->pid.SickCaliWzOutPID, diff_yaw, 0);
    delta_x=PID_calc(&c->pid.SickCaliVxOutPID, diff_x, 0);
    delta_y=PID_calc(&c->pid.SickCaliVyOutPID, diff_y,0);
	
	if(fabs(diff_yaw)>5){
	  c->move_vec.Vw=PID_calc(&c->pid.SickCaliWzInPID,-delta_w,0);
//	c->move_vec.Vw=delta_w;
//	  c->move_vec.Vx=PID_calc(&c->pid.SickCaliVxInPID,delta_x,0);
//	  c->move_vec.Vx=PID_calc(&c->pid.SickCaliVyInPID,delta_y,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 >= 20) {
            
            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);
}


