rm_chassis/User/module/chassis.c
2025-10-28 21:51:19 +08:00

298 lines
8.8 KiB
C

/*
µ×ÅÌÄ£×é
*/
#include "cmsis_os2.h"
#include <stdlib.h>
#include "bsp/mm.h"
#include "bsp/can.h"
#include "component/ahrs.h"
#include "device/motor_rm.h"
#include "device/motor.h"
#include "module/chassis.h"
#define CHASSIS_ROTOR_WZ_MIN 0.6f
#define CHASSIS_ROTOR_WZ_MAX 0.8f
#define M_7OVER72PI (M_2PI * 7.0f / 72.0f)
#define CHASSIS_ROTOR_OMEGA 0.001f
static int8_t Chassis_SetMode(Chassis_t *c, Chassis_Mode_t mode, uint32_t now) {
if (!c)
return CHASSIS_ERR_NULL;
if (mode == c->mode)
return CHASSIS_OK;
if (mode == CHASSIS_MODE_ROTOR && c->mode != CHASSIS_MODE_ROTOR) {
srand(now);
c->wz_multi = (rand() % 2) ? -1 : 1;
}
for (uint8_t i = 0; i < c->num_wheel; i++) {
PID_Reset(&c->pid.motor[i]);
LowPassFilter2p_Reset(&c->filter.in[i], 0.0f);
LowPassFilter2p_Reset(&c->filter.out[i], 0.0f);
}
c->mode = mode;
return CHASSIS_OK;
}
static float Chassis_CalcWz(const float min, const float max, uint32_t now) {
float wz_vary = fabsf(0.2f * sinf(CHASSIS_ROTOR_OMEGA * (float)now)) + min;
return (wz_vary > max) ? max : wz_vary;
}
int8_t Chassis_Init(Chassis_t *c, const Chassis_Params_t *param,
AHRS_Eulr_t *mech_zero, float target_freq) {
if (!c) return CHASSIS_ERR_NULL;
<<<<<<< HEAD
BSP_CAN_Init();
=======
>>>>>>> fc2ac5c99d3c57c83c4929b0969c6dc753eef3ac
c->param = param;
c->mode = CHASSIS_MODE_RELAX;
c->mech_zero = *mech_zero;
c->feedback.imu.eulr = *mech_zero;
if (param->reverse.yaw) {
CircleReverse(&(c->mech_zero.yaw));
c->feedback.imu.eulr.yaw = -c->feedback.imu.eulr.yaw + M_2PI;
}
c->limit.vx.max = param->limit.max_vx;
c->limit.vx.min = -param->limit.max_vx;
c->limit.vy.max = param->limit.max_vy;
c->limit.vy.min = -param->limit.max_vy;
c->limit.wz.max = param->limit.max_wz;
c->limit.wz.min = -param->limit.max_wz;
Mixer_Mode_t mixer_mode;
switch (param->type) {
case CHASSIS_TYPE_MECANUM:
c->num_wheel = 4;
mixer_mode = MIXER_MECANUM;
break;
case CHASSIS_TYPE_PARLFIX4:
c->num_wheel = 4;
mixer_mode = MIXER_PARLFIX4;
break;
case CHASSIS_TYPE_PARLFIX2:
c->num_wheel = 2;
mixer_mode = MIXER_PARLFIX2;
break;
case CHASSIS_TYPE_OMNI_CROSS:
c->num_wheel = 4;
mixer_mode = MIXER_OMNICROSS;
break;
case CHASSIS_TYPE_OMNI_PLUS:
c->num_wheel = 4;
mixer_mode = MIXER_OMNIPLUS;
break;
case CHASSIS_TYPE_SINGLE:
c->num_wheel = 1;
mixer_mode = MIXER_SINGLE;
break;
default:
return CHASSIS_ERR_TYPE;
}
c->last_wakeup = 0;
c->dt = 0.0f;
for (uint8_t i = 0; i < c->num_wheel; i++) {
PID_Init(&c->pid.motor[i], KPID_MODE_NO_D, target_freq, &param->pid.motor_pid_param);
LowPassFilter2p_Init(&c->filter.in[i], target_freq, param->low_pass_cutoff_freq.in);
LowPassFilter2p_Init(&c->filter.out[i], target_freq, param->low_pass_cutoff_freq.out);
c->feedback.motor[i].rotor_speed = 0;
c->feedback.motor[i].torque_current = 0;
c->feedback.motor[i].rotor_abs_angle = 0;
c->feedback.motor[i].temp = 0;
}
PID_Init(&c->pid.follow, KPID_MODE_NO_D, target_freq, &param->pid.follow_pid_param);
Mixer_Init(&c->mixer, mixer_mode);
c->move_vec.vx = c->move_vec.vy = c->move_vec.wz = 0.0f;
for (uint8_t i = 0; i < c->num_wheel; i++) {
c->out.motor[i] = 0.0f;
}
for (int i = 0; i < c->num_wheel; i++) {
MOTOR_RM_Register(&(c->param->motor_param[i]));
}
return CHASSIS_OK;
}
int8_t Chassis_UpdateFeedback(Chassis_t *c, const Chassis_Feedback_t *feedback) {
if (!c || !feedback) return CHASSIS_ERR_NULL;
float yaw = c->param->reverse.yaw ? -feedback->imu.eulr.yaw : feedback->imu.eulr.yaw;
while (yaw > M_PI) yaw -= M_2PI;
while (yaw < -M_PI) yaw += M_2PI;
c->feedback.imu.eulr.yaw = yaw;
for (uint8_t i = 0; i < c->num_wheel; i++) {
MOTOR_RM_Update(&(c->param->motor_param[i]));
<<<<<<< HEAD
MOTOR_RM_t *rm_motor = MOTOR_RM_GetMotor(&(c->param->motor_param[i]));
c->motors[i] = rm_motor;
MOTOR_RM_t *rm = c->motors[i];
if (rm_motor != NULL) {
c->feedback.motor[i] = rm_motor->feedback;
}else
{
return CHASSIS_ERR_NULL;
}
=======
// MOTOR_RM_t *rm_motor = c->motors[i];
// if (rm_motor) {
// c->feedback.motor[i] = rm_motor->feedback;
// }
// else
// {
// return CHASSIS_ERR_NULL;
// }
MOTOR_RM_t *rm_motor = MOTOR_RM_GetMotor(&(c->param->motor_param[i]));
if (rm_motor != NULL) {
c->feedback.motor[i] = rm_motor->feedback;
}
>>>>>>> fc2ac5c99d3c57c83c4929b0969c6dc753eef3ac
}
return CHASSIS_OK;
}
int8_t Chassis_Control(Chassis_t *c, const ChassisCmd_t *c_cmd, uint32_t now) {
if (!c || !c_cmd) return CHASSIS_ERR_NULL;
c->dt = (float)(now - c->last_wakeup) / 1000.0f;
c->last_wakeup = now;
if (!isfinite(c->dt) || c->dt <= 0.0f) {
c->dt = 0.001f;
}
if (c->dt < 0.0005f) c->dt = 0.0005f;
if (c->dt > 0.050f) c->dt = 0.050f;
Chassis_SetMode(c, c_cmd->mode, now);
Clip(&c->move_vec.vx, c->limit.vx.min, c->limit.vx.max);
Clip(&c->move_vec.vy, c->limit.vy.min, c->limit.vy.max);
Clip(&c->move_vec.wz, c->limit.wz.min, c->limit.wz.max);
switch (c->mode) {
case CHASSIS_MODE_BREAK:
c->move_vec.vx = c->move_vec.vy = 0.0f;
break;
case CHASSIS_MODE_INDEPENDENT:
c->move_vec.vx = c_cmd->ctrl_vec.vx;
c->move_vec.vy = c_cmd->ctrl_vec.vy;
break;
default: {
float beta = c->feedback.imu.eulr.yaw - c->mech_zero.yaw;
float cosb = cosf(beta);
float sinb = sinf(beta);
c->move_vec.vx = cosb * c_cmd->ctrl_vec.vx - sinb * c_cmd->ctrl_vec.vy;
c->move_vec.vy = sinb * c_cmd->ctrl_vec.vx + cosb * c_cmd->ctrl_vec.vy;
break;
}
}
switch (c->mode) {
case CHASSIS_MODE_RELAX:
case CHASSIS_MODE_BREAK:
case CHASSIS_MODE_INDEPENDENT:
c->move_vec.wz = 0.0f;
break;
case CHASSIS_MODE_OPEN:
c->move_vec.wz = c_cmd->ctrl_vec.wz;
<<<<<<< HEAD
break;
=======
>>>>>>> fc2ac5c99d3c57c83c4929b0969c6dc753eef3ac
case CHASSIS_MODE_FOLLOW_GIMBAL:
c->move_vec.wz = PID_Calc(&c->pid.follow, c->mech_zero.yaw, c->feedback.imu.eulr.yaw, 0.0f, c->dt);
break;
case CHASSIS_MODE_FOLLOW_GIMBAL_35:
c->move_vec.wz = PID_Calc(&c->pid.follow,c->mech_zero.yaw +M_7OVER72PI, c->feedback.imu.eulr.yaw, 0.0f, c->dt);
break;
case CHASSIS_MODE_ROTOR:
c->move_vec.wz = c->wz_multi * Chassis_CalcWz(CHASSIS_ROTOR_WZ_MIN,
CHASSIS_ROTOR_WZ_MAX, now);
break;
}
Mixer_Apply(&c->mixer, &c->move_vec, c->setpoint.motor_rpm, c->num_wheel, 3000.0f);
for (uint8_t i = 0; i < c->num_wheel; i++) {
float rf = c->setpoint.motor_rpm[i];
float fb = LowPassFilter2p_Apply(&c->filter.in[i], (float)c->feedback.motor[i].rotor_speed);
<<<<<<< HEAD
=======
//float out_current = 0.0f;
>>>>>>> fc2ac5c99d3c57c83c4929b0969c6dc753eef3ac
float out_current = PID_Calc(&c->pid.motor[i], rf, fb, 0.0f, c->dt);
switch (c->mode) {
case CHASSIS_MODE_BREAK:
case CHASSIS_MODE_FOLLOW_GIMBAL:
case CHASSIS_MODE_FOLLOW_GIMBAL_35:
case CHASSIS_MODE_ROTOR:
case CHASSIS_MODE_INDEPENDENT:
out_current = PID_Calc(&c->pid.motor[i], c->setpoint.motor_rpm[i], fb, 0.0f, c->dt);
break;
case CHASSIS_MODE_OPEN:
<<<<<<< HEAD
out_current = c->setpoint.motor_rpm[i] / 3000.0f;
=======
out_current = c->setpoint.motor_rpm[i] / 7000.0f;
>>>>>>> fc2ac5c99d3c57c83c4929b0969c6dc753eef3ac
break;
case CHASSIS_MODE_RELAX:
out_current = 0.0f;
break;
}
c->out.motor[i] = LowPassFilter2p_Apply(&c->filter.out[i], out_current);
Clip(&c->out.motor[i], -c->param->limit.max_current, c->param->limit.max_current);
}
return CHASSIS_OK;
}
void Chassis_Output(Chassis_t *c) {
if (!c)
return;
//ÿ¸öµç»úÄ¿±êÊä³ö
for (uint8_t i = 0; i < c->num_wheel; i++) {
MOTOR_RM_t *rm = c->motors[i];
if (!rm) continue;
MOTOR_RM_SetOutput(&rm->param, c->out.motor[i]);
}
//µ÷ÓÃctrl
for (uint8_t i = 0; i < c->num_wheel; i++) {
MOTOR_RM_t *rm = c->motors[i];
if (rm) {
MOTOR_RM_Ctrl(&rm->param);
}
}
}
void Chassis_ResetOutput(Chassis_t *c) {
if (!c) return;
for (uint8_t i = 0; i < c->num_wheel; i++) {
MOTOR_RM_t *m = c->motors[i];
if (m) {
MOTOR_RM_Relax(&(m->param));
}
}
}