Files
tronone-h7-scaffold/User_Code/module/algorithm/controller/ffc/ffc.c
2026-02-12 00:41:34 +08:00

106 lines
3.5 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.
#include "ffc.h"
#include <math.h>
#include <string.h>
#include <stdlib.h>
// 内部使用的辅助函数:重置句柄
static void FFC_ResetInstance(FFC_Handle_t *handle) {
// 将整个结构体清零,相当于 C++ 的值初始化
memset(handle, 0, sizeof(FFC_Handle_t));
}
float FFC_FeedForwardCalc(FFC_Handle_t *handle, float target) {
if (handle == NULL) return 0.0f;
// 获取时间间隔 dt
handle->dt = DWT_GetDeltaT(&handle->DWT_CNT);
// 设置当前目标值
handle->set[FFC_NOW] = target;
// 低通滤波处理 (完全保留原代码逻辑)
// 注意:数学上 transform: x = x * dt/(LPF+dt) + x * LPF/(LPF+dt) 等同于 x = x。
// 这里保留原代码逻辑以防有特殊 side effect 需求。
float denominator = handle->configs.FFC_LPF + handle->dt;
if (denominator != 0.0f) {
handle->set[FFC_NOW] = handle->set[FFC_NOW] * handle->dt / denominator +
handle->set[FFC_NOW] * handle->configs.FFC_LPF / denominator;
}
// 前馈计算: Proportional + Derivative + Acceleration
// result = c1*x + c2*v + c3*a
float p_term = handle->configs.c1 * handle->set[FFC_NOW];
float d_term = 0.0f;
float a_term = 0.0f;
if (handle->dt > 0.000001f) { // 防止除以零
d_term = handle->configs.c2 * (handle->set[FFC_NOW] - handle->set[FFC_LAST]) / handle->dt;
a_term = handle->configs.c3 * (handle->set[FFC_NOW] - 2 * handle->set[FFC_LAST] + handle->set[FFC_LLAST]) / (handle->dt * handle->dt);
}
handle->result = p_term + d_term + a_term;
// 限幅
handle->result = abs_clip(handle->result, handle->configs.MaxOutput);
// 更新历史状态
// 注意:原 C++ 代码中先更新 LAST 再更新 LLAST这会导致移位寄存器逻辑变为 LLAST = (新的)LAST。
// 为了保持转换的一致性,这里保留原代码的顺序。
handle->set[FFC_LAST] = handle->set[FFC_NOW];
handle->set[FFC_LLAST] = handle->set[FFC_LAST];
return handle->result;
}
void FFC_SetConfig(FFC_Handle_t *handle, FFC_Init_Config_s config) {
if (handle == NULL) return;
// 使用值初始化清除 ffc_s 对象
FFC_ResetInstance(handle);
// 复制配置参数
handle->configs = config;
}
void FFC_CheckPointer(FFC_Handle_t *handle, float *get) {
if (handle == NULL) return;
handle->get_data = get;
}
void FFC_Init(FFC_Handle_t *handle, FFC_Init_Config_s config, float *get) {
if (handle == NULL) return;
// 对应 C++: FFCSetConfig(config, get)
FFC_SetConfig(handle, config);
if (get != NULL) {
FFC_CheckPointer(handle, get);
}
}
float FFC_Handle(FFC_Handle_t *handle, float target) {
return FFC_FeedForwardCalc(handle, target);
}
void FFC_DebugControl(FFC_Handle_t *handle, float *imu_data, float *data_from_gimbalctrl_yaw) {
if (handle == NULL || imu_data == NULL || data_from_gimbalctrl_yaw == NULL) return;
handle->debug.count++;
handle->debug.total_imu_yaw = *imu_data;
// 生成正弦波目标值
handle->debug.target = (float)(sin(handle->debug.count * 0.003) * 1.0);
// 输出到 gimbal ctrl
*data_from_gimbalctrl_yaw = handle->debug.target;
// 逻辑判断
if (fabsf(*data_from_gimbalctrl_yaw) < 0.01f && handle->debug.if_gimbal_ctrl == 0) {
handle->debug.if_gimbal_ctrl = 1; // true
DWT_GetDeltaT(&handle->debug.DWT_CNT);
}
if (handle->debug.if_gimbal_ctrl == 1 && fabsf(*imu_data) < 0.01f) {
handle->debug.if_gimbal_ctrl = 0; // false
handle->debug.error = DWT_GetDeltaT(&handle->debug.DWT_CNT);
}
}