
#include "chassis.h"

#include "can.h"
#include "device/at9s_pro.h"
#include "component/pid.h"
#include "device/motor_rm.h"
#include <math.h>
#include "bsp/time.h"

KPID_t pid_wheel[4];
KPID_Params_t pid_wheel_params={1, 0.8, 0.0, 0.0, 0.0, 0.8,-1.0,-1.0};

KPID_t pid_lockagl[4];
KPID_Params_t pid_lockagl_params={1, 0.8, 0.05, 0.0, 0.1, 0.8,-1.0,M_2PI};

KPID_t pid_lockomg[4];
KPID_Params_t pid_lockomg_params={2, 1, 0.0, 0.01, 0.0, 0.8,-1.0,-1.0};


KPID_t pid_follow;
KPID_Params_t pid_follow_params={0.5, 1, 0, 0.0, 0, 0.0, -1.0, -1};

MOTOR_RM_Param_t motor1to4_param[4]={
    {.can=BSP_CAN_1,.id=0x201,.module=MOTOR_M3508,.reverse=false,.gear=true,},
    {.can=BSP_CAN_1,.id=0x202,.module=MOTOR_M3508,.reverse=false,.gear=true,},
    {.can=BSP_CAN_1,.id=0x203,.module=MOTOR_M3508,.reverse=false,.gear=true,},
    {.can=BSP_CAN_1,.id=0x204,.module=MOTOR_M3508,.reverse=false,.gear=true,}
};

MOTOR_Feedback_t motor1to4_measure[4];
float lockagl_out[4];
float chassis_out[4];
float Wheel_status[4];
void Inverse_resolve(float vx,float vy,float w)
{
    Wheel_status[0]=vx-vy+w;
    Wheel_status[1]=vx+vy+w;
    Wheel_status[2]=-vx+vy+w;
    Wheel_status[3]=-vx-vy+w;
}

void Motor_Init(float freq)
{	for(int i=0;i<4;i++)
	{
	PID_Init(&pid_wheel[i], KPID_MODE_CALC_D, freq,&pid_wheel_params);
		PID_Init(&pid_lockagl[i], KPID_MODE_CALC_D, freq,&pid_lockagl_params);
	PID_Init(&pid_lockomg[i], KPID_MODE_CALC_D, freq,&pid_lockomg_params);

	}
	
		
	PID_Init(&pid_follow, KPID_MODE_NO_D, freq,&pid_follow_params);
    BSP_CAN_Init();
    for(int i=0;i<4;i++){
	MOTOR_RM_Register(&motor1to4_param[i]);
    }
}
int64_t now,last_wakeup;
float dt;
float vx,vy,w;float chassis_yaw;
float speed[4];
float lockagl[4]={0,0,0,0};
void chassis_control(chassis_ctrl_eulr_t eulr, COMP_AT9S_CMD_t cmd_rc)//k:ת���޷�
{
	//float vx,vy,w;
	now 		=BSP_TIME_Get_us() / 1000000.0f;
    dt 			=(BSP_TIME_Get_us() - last_wakeup) / 1000000.0f;
    last_wakeup	=BSP_TIME_Get_us();
	float delta_angle;
	float cos_delta_angle;
	float sin_delta_angle;
    for(int i=0;i<4;i++){
	MOTOR_RM_Update(&motor1to4_param[i]);
    MOTOR_RM_t *motor_fed = MOTOR_RM_GetMotor(&motor1to4_param[i]);
		if(motor_fed!=NULL)
		{
			motor1to4_measure[i]=motor_fed->motor.feedback;
		}
    }
	switch(cmd_rc.mode){
		case 0:
	vx=0;vy=0;w=0;
		break;
		case 1:
	delta_angle = eulr.chassis_encoder_yaw - eulr.chassis_mech_zero_yaw;
      cos_delta_angle = cosf(delta_angle);
      sin_delta_angle = sinf(delta_angle);
      vx =cos_delta_angle * cmd_rc.chassis_ctrl_vec.x - sin_delta_angle * cmd_rc.chassis_ctrl_vec.y;
      vy =sin_delta_angle * cmd_rc.chassis_ctrl_vec.x + cos_delta_angle * cmd_rc.chassis_ctrl_vec.y;
		w=PID_Calc(&pid_follow, eulr.chassis_mech_zero_yaw,
                  eulr.chassis_encoder_yaw, 0.0f, dt);
		break;
		case 2:
	PID_ResetIntegral(&pid_follow);
		
	  delta_angle = eulr.chassis_encoder_yaw - eulr.chassis_mech_zero_yaw;
      cos_delta_angle = cosf(delta_angle);
      sin_delta_angle = sinf(delta_angle);
      vx =cos_delta_angle * cmd_rc.chassis_ctrl_vec.x - sin_delta_angle * cmd_rc.chassis_ctrl_vec.y;
      vy =sin_delta_angle * cmd_rc.chassis_ctrl_vec.x + cos_delta_angle * cmd_rc.chassis_ctrl_vec.y;
		
	w=PID_Calc(&pid_follow, eulr.chassis_mech_zero_yaw,
                  eulr.chassis_encoder_yaw, 0.0f, dt);
		break;
		case 3:
	  delta_angle = eulr.chassis_encoder_yaw - eulr.chassis_mech_zero_yaw;
      cos_delta_angle = cosf(delta_angle);
      sin_delta_angle = sinf(delta_angle);
      vx =cos_delta_angle * cmd_rc.chassis_ctrl_vec.x - sin_delta_angle * cmd_rc.chassis_ctrl_vec.y;
      vy =sin_delta_angle * cmd_rc.chassis_ctrl_vec.x + cos_delta_angle * cmd_rc.chassis_ctrl_vec.y;
		
	  w=0.6f; 
		break;
		default :
			break;
	}
	
	
    Inverse_resolve(vx, vy, w);
	float abs_max = 0.0f;
	for (int8_t i = 0; i < 4; i++) {
		const float abs_val = fabsf(Wheel_status[i]);
		abs_max = (abs_val > abs_max) ? abs_val : abs_max;
	}
	if (abs_max > 1.0f) {
		for (int8_t i = 0; i < 4; i++) {
			Wheel_status[i] /= abs_max;
		}
	}
	
//	if(vx==0&&vy==0)PID_ResetIntegral(&pid_wheel);
	switch(cmd_rc.mode){
		case 0:
			PID_ResetIntegral(&pid_wheel[0]);
			PID_ResetIntegral(&pid_wheel[1]);
			PID_ResetIntegral(&pid_wheel[2]);
			PID_ResetIntegral(&pid_wheel[3]);
	chassis_out[0] = 0;
    chassis_out[1] = 0;
    chassis_out[2] = 0;
    chassis_out[3] = 0;
		break;
		case 1:
			PID_ResetIntegral(&pid_wheel[0]);
			PID_ResetIntegral(&pid_wheel[1]);
			PID_ResetIntegral(&pid_wheel[2]);
			PID_ResetIntegral(&pid_wheel[3]);
//	chassis_out[0] = 0;
//    chassis_out[1] = 0;
//    chassis_out[2] = 0;
//    chassis_out[3] = 0;
		for(int i=0;i<4;i++){
				speed[i]=motor1to4_measure[i].rotor_speed*19.2032/7000.0f;
			
				if(speed[i]>1)speed[i]=1;
		else if(speed[i]<-1)speed[i]=-1;
				lockagl_out[i] = PID_Calc(&pid_lockagl[i],lockagl[i],motor1to4_measure[i].rotor_abs_angle, 0,dt);
				chassis_out[i] = PID_Calc(&pid_lockomg[i],lockagl_out[i],speed[i], 0,dt);
				if(chassis_out[i]>0.8f)chassis_out[i]=0.8f;
			}
		break;
		case 2:
			for(int i=0;i<4;i++){
				
				lockagl[i]=motor1to4_measure[i].rotor_abs_angle;
				
				speed[i]=motor1to4_measure[i].rotor_speed*19.2032/7000.0f;
				if(speed[i]>1)speed[i]=1;
		else if(speed[i]<-1)speed[i]=-1;
				chassis_out[i] = PID_Calc(&pid_wheel[i],Wheel_status[i],speed[i], 0,dt);
				if(chassis_out[i]>0.8f)chassis_out[i]=0.8f;
			}
			
		break;                                                                            
		case 3:                                                                           
		for(int i=0;i<4;i++){
			
				lockagl[i]=motor1to4_measure[i].rotor_abs_angle;
			
				speed[i]=motor1to4_measure[i].rotor_speed*19.2032/7000.0f;
				if(speed[i]>1)speed[i]=1;
		else if(speed[i]<-1)speed[i]=-1;
				chassis_out[i] = PID_Calc(&pid_wheel[i],Wheel_status[i],speed[i], 0,dt);
			if(chassis_out[i]>0.8f)chassis_out[i]=0.8f;
			}
		break;
		default :
			break;
	}

//	for(int i;i<4;i++){
//		chassis_out[i]*=0.6;
//	}
    MOTOR_RM_SetOutput(&motor1to4_param[0], chassis_out[0]);
    MOTOR_RM_SetOutput(&motor1to4_param[1], chassis_out[1]);
    MOTOR_RM_SetOutput(&motor1to4_param[2], chassis_out[2]);
    MOTOR_RM_SetOutput(&motor1to4_param[3], chassis_out[3]);
//MOTOR_RM_SetOutput(&motor1to4_param[1], 0);
//    MOTOR_RM_SetOutput(&motor1to4_param[2], 0);
    MOTOR_RM_Ctrl(&motor1to4_param[0]);
}






