214 lines
7.4 KiB
C
214 lines
7.4 KiB
C
//
|
|
// Created by SJQ on 2023/12/25.
|
|
//
|
|
|
|
#include "leg.h"
|
|
#include "math.h"
|
|
#include "main.h"
|
|
#include "arm_math.h"
|
|
|
|
#include "cal_phi0_dot.h"
|
|
|
|
|
|
static const float l[5]={0.15f,0.27f,0.27f,0.15f,0.15f};
|
|
static void calculate_leg_pos(Leg_State_t* leg_state);
|
|
static void VMC_jacobian(float L0, float phi0, float phi1, float phi2, float phi3,
|
|
float phi4, float F, float Tp, float T12[2]);
|
|
void VMC_getT(LegInstance* legInstance);
|
|
|
|
void Leg_Init(LegInstance* legInstance, Leg_init_config_s* legInitConfig)
|
|
{
|
|
PIDInit(&legInstance->Length_PID,&legInitConfig->length_PID_conf);
|
|
PIDInit(&legInstance->Phi0_PID,&legInitConfig->phi0_PID_conf);
|
|
legInstance->target_L0 = legInitConfig->init_target_L0;
|
|
legInstance->F_feedforward = legInitConfig->F_feedforward;
|
|
|
|
arm_mat_init_f32(&legInstance->VMC_Jacobi,2,2,legInstance->VMC_Jacobi_data);
|
|
arm_mat_init_f32(&legInstance->inv_VMC_Jacobi,2,2,legInstance->inv_VMC_Jacobi_data);
|
|
// set rest of memory to 0
|
|
DWT_GetDeltaT(&legInstance->legState.DWT_CNT);
|
|
}
|
|
|
|
void Leg_length_control_loop(LegInstance* legInstance)
|
|
{
|
|
float F_pid_out = PIDCalculate(&legInstance->Length_PID,legInstance->legState.L0,legInstance->target_L0);
|
|
float Tp_pid_out = PIDCalculate(&legInstance->Phi0_PID,legInstance->legState.phi0,legInstance->target_phi0);
|
|
Leg_Input_update(&legInstance->legInput,F_pid_out-2.73f,Tp_pid_out);
|
|
//Leg_calc_output(&legInstance->legState,&legInstance->legInput,&legInstance->legOutput);
|
|
VMC_getT(legInstance);
|
|
}
|
|
void Leg_State_update(LegInstance* legInstance, float phi1,float phi4 ,float phi1_dot,float phi4_dot)
|
|
{
|
|
Leg_State_t* leg_state = &legInstance->legState;
|
|
if(phi1<=PI/2)
|
|
phi1 = PI/2;
|
|
if(phi4>=PI/2)
|
|
phi4 = PI/2;
|
|
|
|
leg_state->phi1 = phi1;
|
|
leg_state->phi4 = phi4;
|
|
float leg_pos[4];
|
|
|
|
//calculate_leg_pos(leg_state->phi1,leg_state->phi4,leg_pos);
|
|
calculate_leg_pos(leg_state);
|
|
|
|
leg_state->phi0_dot = get_dphi0(phi1,phi4,phi1_dot,phi4_dot);
|
|
leg_state->L0_dot = get_dL0(phi1,phi4,phi1_dot,phi4_dot);
|
|
|
|
//对dPhi0 dL0求导(二阶导)
|
|
leg_state->dt = DWT_GetDeltaT(&leg_state->DWT_CNT);
|
|
// //if(leg_state->last_phi0>=0)
|
|
// leg_state->phi0_dot2 = (leg_state->phi0_dot-leg_state->last_dPhi0)/leg_state->dt;
|
|
// //else
|
|
// //leg_state->phi0_dot_num = 0;
|
|
// leg_state->last_dPhi0 = leg_state->phi0_dot;
|
|
//
|
|
//if(leg_state->last_phi0>=0)
|
|
leg_state->L0_dot2 = (leg_state->L0_dot-leg_state->last_dL0)/leg_state->dt;
|
|
//else
|
|
//leg_state->phi0_dot_num = 0;
|
|
leg_state->last_dL0 = leg_state->L0_dot;
|
|
}
|
|
|
|
void Leg_Input_update(Leg_Input_t* leg_Input, float F,float Tp)
|
|
{
|
|
leg_Input->F = F;
|
|
leg_Input->Tp = Tp;
|
|
}
|
|
|
|
void Leg_calc_output(Leg_State_t* leg_state,Leg_Input_t* leg_input,Leg_Output_t* leg_output)
|
|
{
|
|
// float T12[2] = {0,0};
|
|
// vmcJacobian(leg_state->L0,leg_state->phi0,leg_state->phi1,
|
|
// leg_state->phi2,leg_state->phi3,leg_state->phi4,
|
|
// leg_input->F,leg_input->Tp,T12);
|
|
// leg_output->T1 = T12[0];
|
|
// leg_output->T2 = T12[1];
|
|
}
|
|
|
|
|
|
void calculate_leg_pos(Leg_State_t* leg_state)
|
|
{
|
|
//以机体中点建立坐标系
|
|
float xb = -l[4]/2+l[0]* arm_cos_f32(leg_state->phi1);
|
|
float yb = l[0]* arm_sin_f32(leg_state->phi1);
|
|
|
|
float xd = l[4]/2+l[3]* arm_cos_f32(leg_state->phi4);
|
|
float yd = l[3]* arm_sin_f32(leg_state->phi4);
|
|
|
|
float A0 = 2*l[1]*(xd-xb);
|
|
float B0 = 2*l[1]*(yd-yb);
|
|
|
|
float lbd2 = (xd-xb)*(xd-xb)+(yd-yb)*(yd-yb);
|
|
float C0 = l[1]*l[1]+lbd2-l[2]*l[2];
|
|
|
|
float tanPhi = 0;
|
|
|
|
arm_sqrt_f32((A0*A0 + B0*B0 - C0*C0),&tanPhi);
|
|
//tanPhi = (B0+tanPhi)/(A0+C0);
|
|
|
|
float phi2 = 2* atan2f(B0+tanPhi,A0+C0);
|
|
float xc = xb + l[1] * arm_cos_f32(phi2);
|
|
float yc = yb + l[1] * arm_sin_f32(phi2);
|
|
|
|
float phi3 = acosf(xc-xd/l[2]);
|
|
float L0 = 0;
|
|
arm_sqrt_f32((xc*xc + yc*yc),&L0);
|
|
float phi0 = atan2f(yc,xc);
|
|
|
|
//赋值
|
|
leg_state->L0 = L0;
|
|
leg_state->phi0 = phi0;
|
|
leg_state->phi2 = phi2;
|
|
leg_state->phi3 = phi3;
|
|
|
|
leg_state->position[0] = xb; leg_state->position[1] = yb;
|
|
leg_state->position[2] = xc; leg_state->position[3] = yc;
|
|
leg_state->position[4] = xd; leg_state->position[5] = yd;
|
|
}
|
|
|
|
void VMC_getT(LegInstance* legInstance)
|
|
{
|
|
//arm_matrix_instance_f32 T_matrix;
|
|
arm_matrix_instance_f32 F_Tp_matrix;
|
|
// float T_array[4] = {0};
|
|
float F_Tp_array[2] = {0};
|
|
|
|
F_Tp_array[0] = legInstance->legInput.F;
|
|
F_Tp_array[1] = legInstance->legInput.Tp;
|
|
|
|
float sinPhi23 = arm_sin_f32(legInstance->legState.phi2 - legInstance->legState.phi3);
|
|
float sinPhi12 = arm_sin_f32(legInstance->legState.phi1 - legInstance->legState.phi2);
|
|
float sinPhi34 = arm_sin_f32(legInstance->legState.phi3 - legInstance->legState.phi4);
|
|
|
|
float sinPhi03 = arm_sin_f32(legInstance->legState.phi0 - legInstance->legState.phi3);
|
|
float sinPhi02 = arm_sin_f32(legInstance->legState.phi0 - legInstance->legState.phi2);
|
|
float cosPhi03 = arm_cos_f32(legInstance->legState.phi0 - legInstance->legState.phi3);
|
|
float cosPhi02 = arm_cos_f32(legInstance->legState.phi0 - legInstance->legState.phi2);
|
|
|
|
// T_array[0] = -(l[0]* sinPhi03*sinPhi12)/sinPhi23;
|
|
// T_array[1] = -(l[0]* cosPhi03*sinPhi12)/(legInstance->legState.L0 * sinPhi23);
|
|
//
|
|
// T_array[2] = -(l[3]* sinPhi02*sinPhi34)/sinPhi23;
|
|
// T_array[3] = -(l[3]* cosPhi02*sinPhi34)/(legInstance->legState.L0 * sinPhi23);
|
|
legInstance->VMC_Jacobi_data[0] = -(l[0]* sinPhi03*sinPhi12)/sinPhi23;
|
|
legInstance->VMC_Jacobi_data[1] = -(l[0]* cosPhi03*sinPhi12)/(legInstance->legState.L0 * sinPhi23);
|
|
|
|
legInstance->VMC_Jacobi_data[2] = -(l[3]* sinPhi02*sinPhi34)/sinPhi23;
|
|
legInstance->VMC_Jacobi_data[3] = -(l[3]* cosPhi02*sinPhi34)/(legInstance->legState.L0 * sinPhi23);
|
|
|
|
//arm_mat_init_f32(&T_matrix,2,2,T_array);
|
|
arm_mat_init_f32(&F_Tp_matrix,2,1,F_Tp_array);
|
|
|
|
arm_matrix_instance_f32 T12_matrix;
|
|
float T12[2] = {0};
|
|
arm_mat_init_f32(&T12_matrix,2,1,T12);
|
|
|
|
arm_mat_mult_f32(&legInstance->VMC_Jacobi,&F_Tp_matrix,&T12_matrix);
|
|
legInstance->legOutput.T1 = T12_matrix.pData[0];
|
|
legInstance->legOutput.T2 = T12_matrix.pData[1];
|
|
}
|
|
|
|
void Leg_feedback_update(LegInstance* legInstance,float T1_fb,float T2_fb)
|
|
{
|
|
arm_mat_inverse_f32(&legInstance->VMC_Jacobi,&legInstance->inv_VMC_Jacobi);
|
|
|
|
arm_matrix_instance_f32 F_Tp_matrix;
|
|
float F_Tp_array[2] = {0};
|
|
arm_mat_init_f32(&F_Tp_matrix,2,1,F_Tp_array);
|
|
|
|
arm_matrix_instance_f32 T12_matrix;
|
|
float T12[2] = {0};
|
|
arm_mat_init_f32(&T12_matrix,2,1,T12);
|
|
|
|
T12[0] = T1_fb; T12[1] = T2_fb;
|
|
arm_mat_mult_f32(&legInstance->inv_VMC_Jacobi,&T12_matrix,&F_Tp_matrix);
|
|
|
|
legInstance->legFeedback.F = F_Tp_array[0];
|
|
legInstance->legFeedback.Tp = F_Tp_array[1];
|
|
}
|
|
|
|
void VMC_jacobian(float L0, float phi0, float phi1, float phi2, float phi3,
|
|
float phi4, float F, float Tp, float T12[2])
|
|
{
|
|
float T_tmp;
|
|
float b_T_tmp;
|
|
float c_T_tmp;
|
|
float d_T_tmp;
|
|
float e_T_tmp;
|
|
float f_T_tmp;
|
|
T_tmp = phi0 - phi3;
|
|
b_T_tmp = arm_sin_f32(phi1 - phi2);
|
|
c_T_tmp = arm_sin_f32(phi2 - phi3);
|
|
d_T_tmp = phi0 - phi2;
|
|
e_T_tmp = arm_sin_f32(phi3 - phi4);
|
|
f_T_tmp = L0 * c_T_tmp;
|
|
T12[0] = -(0.15F * arm_sin_f32(T_tmp) * b_T_tmp) / c_T_tmp * F +
|
|
-(0.15F * arm_cos_f32(T_tmp) * b_T_tmp) / f_T_tmp * Tp;
|
|
T12[1] = -(0.15F * arm_sin_f32(d_T_tmp) * e_T_tmp) / c_T_tmp * F +
|
|
-(0.15F * arm_cos_f32(d_T_tmp) * e_T_tmp) / f_T_tmp * Tp;
|
|
}
|
|
|
|
|
|
|