rm_balance/User/task/atti_esit.c
2026-02-04 14:32:14 +08:00

205 lines
6.9 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
atti_esit Task
*/
/* Includes ----------------------------------------------------------------- */
#include "task/user_task.h"
/* USER INCLUDE BEGIN */
#include "bsp/gpio.h"
#include "bsp/mm.h"
#include "bsp/pwm.h"
#include "component/ahrs.h"
#include "component/QuaternionEKF.h"
#include "component/pid.h"
#include "device/bmi088.h"
#include "device/mrobot.h"
#include "device/device.h"
#include "module/balance_chassis.h"
#include "task/user_task.h"
#include <stdio.h>
/* USER INCLUDE END */
/* Private typedef ---------------------------------------------------------- */
/* 自定义 IMU 数据结构 */
typedef struct {
DEVICE_Header_t header;
AHRS_Accl_t accl; /* 加速度 m/s² */
AHRS_Gyro_t gyro; /* 角速度 rad/s */
AHRS_Eulr_t euler; /* 欧拉角 rad */
AHRS_Quaternion_t quat; /* 四元数 */
float temp; /* 温度 °C */
} MyIMU_Data_t;
/* Private define ----------------------------------------------------------- */
/* Private macro ------------------------------------------------------------ */
/* Private variables -------------------------------------------------------- */
/* USER STRUCT BEGIN */
BMI088_t bmi088;
MyIMU_Data_t imu_device; /* 使用自定义结构 */
#ifndef USE_QEKF
AHRS_t gimbal_ahrs;
AHRS_Magn_t magn;
#endif
AHRS_Eulr_t eulr_to_send;
Chassis_IMU_t imu_for_chassis;
KPID_t imu_temp_ctrl_pid;
/*默认校准参数*/
BMI088_Cali_t cali_bmi088 = {
.gyro_offset = {-0.00147764047f, -0.00273479894f, 0.00154074503f},
};
static const KPID_Params_t imu_temp_ctrl_pid_param = {
.k = 0.1f,
.p = 0.15f,
.i = 0.01f,
.d = 0.02f,
.i_limit = 1.0f,
.out_limit = 1.0f,
};
/* USER STRUCT END */
/* Private function --------------------------------------------------------- */
/**
* @brief IMU 设备打印回调函数(用户自定义格式)
*/
static int print_imu_callback(const void *data, char *buffer, size_t size) {
const MyIMU_Data_t *imu = (const MyIMU_Data_t *)data;
/* 弧度转角度 */
#define RAD2DEG 57.2957795131f
/* 使用 MRobot 提供的工具函数格式化浮点数 */
char ax[16], ay[16], az[16];
char gx[16], gy[16], gz[16];
char roll[16], pitch[16], yaw[16];
char q0[16], q1[16], q2[16], q3[16];
char temp[16];
MRobot_FormatFloat(ax, sizeof(ax), imu->accl.x, 3);
MRobot_FormatFloat(ay, sizeof(ay), imu->accl.y, 3);
MRobot_FormatFloat(az, sizeof(az), imu->accl.z, 3);
MRobot_FormatFloat(gx, sizeof(gx), imu->gyro.x, 3);
MRobot_FormatFloat(gy, sizeof(gy), imu->gyro.y, 3);
MRobot_FormatFloat(gz, sizeof(gz), imu->gyro.z, 3);
MRobot_FormatFloat(roll, sizeof(roll), imu->euler.rol * RAD2DEG, 2);
MRobot_FormatFloat(pitch, sizeof(pitch), imu->euler.pit * RAD2DEG, 2);
MRobot_FormatFloat(yaw, sizeof(yaw), imu->euler.yaw * RAD2DEG, 2);
MRobot_FormatFloat(q0, sizeof(q0), imu->quat.q0, 4);
MRobot_FormatFloat(q1, sizeof(q1), imu->quat.q1, 4);
MRobot_FormatFloat(q2, sizeof(q2), imu->quat.q2, 4);
MRobot_FormatFloat(q3, sizeof(q3), imu->quat.q3, 4);
MRobot_FormatFloat(temp, sizeof(temp), imu->temp, 1);
return snprintf(buffer, size,
" Status : %s\r\n"
" Accel : X=%s Y=%s Z=%s (m/s^2)\r\n"
" Gyro : X=%s Y=%s Z=%s (rad/s)\r\n"
" Euler : R=%s P=%s Y=%s (deg)\r\n"
" Quat : q0=%s q1=%s q2=%s q3=%s\r\n"
" Temp : %s C\r\n",
imu->header.online ? "Online" : "Offline",
ax, ay, az,
gx, gy, gz,
roll, pitch, yaw,
q0, q1, q2, q3,
temp);
}
/* Exported functions ------------------------------------------------------- */
void Task_atti_esit(void *argument) {
(void)argument; /* 未使用argument消除警告 */
osDelay(ATTI_ESIT_INIT_DELAY); /* 延时一段时间再开启任务 */
/* USER CODE INIT BEGIN */
BMI088_Init(&bmi088, &cali_bmi088);
#ifdef USE_QEKF
QEKF_Init(10.0f, 0.001f, 1000000.0f, 0.9996f, 0.0f);
#else
AHRS_Init(&gimbal_ahrs, &magn, BMI088_GetUpdateFreq(&bmi088));
#endif
PID_Init(&imu_temp_ctrl_pid, KPID_MODE_NO_D,
1.0f / BMI088_GetUpdateFreq(&bmi088), &imu_temp_ctrl_pid_param);
BSP_PWM_Start(BSP_PWM_IMU_HEAT);
/* 注册 IMU 设备到 MRobot只需名称、数据、打印回调 */
MRobot_RegisterDevice("bmi088", &imu_device, print_imu_callback);
/* USER CODE INIT END */
while (1) {
/* USER CODE BEGIN */
BMI088_WaitNew();
BMI088_AcclStartDmaRecv();
BMI088_AcclWaitDmaCplt();
BMI088_GyroStartDmaRecv();
BMI088_GyroWaitDmaCplt();
/* 锁住RTOS内核防止数据解析过程中断造成错误 */
osKernelLock();
/* 接收完所有数据后,把数据从原始字节加工成方便计算的数据 */
BMI088_ParseAccl(&bmi088);
BMI088_ParseGyro(&bmi088);
// IST8310_Parse(&ist8310);
/* 根据设备接收到的数据进行姿态解析 */
#ifdef USE_QEKF
QEKF_Update(bmi088.gyro.x, bmi088.gyro.y, bmi088.gyro.z,
bmi088.accl.x, bmi088.accl.y, bmi088.accl.z,
1.0f / BMI088_GetUpdateFreq(&bmi088));
/* 从EKF获取欧拉角 */
eulr_to_send.rol = QEKF_INS.roll;
eulr_to_send.pit = QEKF_INS.pitch;
eulr_to_send.yaw = QEKF_INS.yaw;
#else
AHRS_Update(&gimbal_ahrs, &bmi088.accl, &bmi088.gyro, &magn);
/* 根据解析出来的四元数计算欧拉角 */
AHRS_GetEulr(&eulr_to_send, &gimbal_ahrs);
#endif
/* 加速度计数据绕z轴旋转270度: (x,y,z) -> (y,-x,z) */
imu_for_chassis.accl.x = bmi088.accl.y;
imu_for_chassis.accl.y = -bmi088.accl.x;
imu_for_chassis.accl.z = bmi088.accl.z;
/* 陀螺仪数据绕z轴旋转270度: (x,y,z) -> (y,-x,z) */
imu_for_chassis.gyro.x = bmi088.gyro.y;
imu_for_chassis.gyro.y = -bmi088.gyro.x;
imu_for_chassis.gyro.z = bmi088.gyro.z;
/* 欧拉角绕z轴旋转270度 */
imu_for_chassis.euler.rol = eulr_to_send.pit;
imu_for_chassis.euler.pit = -eulr_to_send.rol;
imu_for_chassis.euler.yaw = eulr_to_send.yaw - 1.57079632679f; // -90度
osMessageQueueReset(
task_runtime.msgq.chassis.imu); // 重置消息队列,防止阻塞
osMessageQueuePut(task_runtime.msgq.chassis.imu, &imu_for_chassis, 0,
0); // 非阻塞发送底盘IMU数据
BSP_PWM_SetComp(BSP_PWM_IMU_HEAT, PID_Calc(&imu_temp_ctrl_pid, 40.5f,
bmi088.temp, 0.0f, 0.0f));
/* 直接赋值 AHRS 结构体 - 完美兼容 */
imu_device.accl = bmi088.accl;
imu_device.gyro = bmi088.gyro;
imu_device.euler = eulr_to_send;
#ifdef USE_QEKF
imu_device.quat.q0 = QEKF_INS.q[0];
imu_device.quat.q1 = QEKF_INS.q[1];
imu_device.quat.q2 = QEKF_INS.q[2];
imu_device.quat.q3 = QEKF_INS.q[3];
#else
imu_device.quat = gimbal_ahrs.quat;
#endif
imu_device.temp = bmi088.temp;
imu_device.header = bmi088.header;
osKernelUnlock();
/* USER CODE END */
}
}