rm_balance/User/component/kinematics.c
2025-09-02 20:25:52 +08:00

113 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 "component/kinematics.h"
#include "component/user_math.h"
/*串联腿单腿转摆动杆正运动学*/
/*大腿小腿均按照水平为0点向下为正方向*/
/**
* @brief 串联腿单腿转摆动杆正运动学
* @param param 腿部长度参数
* @param hip_angle 髋关节角度(弧度)
* @param knee_angle 膝关节角度(弧度)
* @param angle 计算到的等效摆动杆角度
* @param heigh 计算到的等效摆动杆高度
* @return
*/
int8_t KIN_SerialLeg_FK(const KIN_SerialLeg_Param_t *param, const float *hip_angle,const float *knee_angle, float *angle, float *height) {
if (param == NULL || hip_angle == NULL || knee_angle == NULL || angle == NULL || height == NULL) {
return -1; // 参数错误
}
float L1 = param->thigh_length;
float L2 = param->calf_length;
float q1 = *hip_angle; // 髋关节角度
float q2 = *knee_angle; // 膝关节角度
float q4 = (M_PI - q1 - q2)/2;
// 使用余弦定理求解等效摆动杆长度
// L2*L2 = L1*L1 + L3*L3 - 2*L1*L3*cosf(q4);
// 整理得L3*L3 - 2*L1*cosf(q4)*L3 + (L1*L1 - L2*L2) = 0
float a = 1.0f;
float b = -2.0f * L1 * cosf(q4);
float c = L1*L1 - L2*L2;
float discriminant = b*b - 4*a*c;
// 检查判别式,确保有实数解
if (discriminant < 0) {
return -2; // 无实数解,配置不可达
}
float sqrt_discriminant = sqrtf(discriminant);
float L3_1 = (-b + sqrt_discriminant) / (2*a);
float L3_2 = (-b - sqrt_discriminant) / (2*a);
// 选择正的解(物理意义上的长度)
float L3;
if (L3_1 > 0 && L3_2 > 0) {
// 两个正解,选择较小的(通常对应机构的正常工作姿态)
L3 = (L3_1 < L3_2) ? L3_1 : L3_2;
} else if (L3_1 > 0) {
L3 = L3_1;
} else if (L3_2 > 0) {
L3 = L3_2;
} else {
return -3; // 无正解
}
*angle = q1 + q4;
*height = L3;
return 0; // 成功
}
/*串联腿单腿转摆动杆逆运动学*/
/*大腿小腿均按照水平为0点向下为正方向*/
/**
* @brief 串联腿单腿转摆动杆逆运动学
* @param param 腿部长度参数
* @param angle 输入的等效摆动杆角度
* @param height 输入的等效摆动杆高度
* @param hip_angle 计算到的髋关节角度(弧度)
* @param knee_angle 计算到的膝关节角度(弧度)
* @return
*/
int8_t KIN_SerialLeg_IK(const KIN_SerialLeg_Param_t *param, const float *angle,const float *height, float *hip_angle, float *knee_angle) {
if (param == NULL || angle == NULL || height == NULL || hip_angle == NULL || knee_angle == NULL) {
return -1; // 参数错误
}
float L1 = param->thigh_length;
float L2 = param->calf_length;
float q = *angle; // 摆动杆角度
float h = *height; // 摆动杆长度
// 由正解可知q = q1 + q4h = L3
// 由余弦定理L2^2 = L1^2 + h^2 - 2*L1*h*cos(q4)
// 整理得cos(q4) = (L1^2 + h^2 - L2^2) / (2*L1*h)
float cos_q4 = (L1*L1 + h*h - L2*L2) / (2.0f * L1 * h);
// 检查 cos_q4 是否在 [-1, 1] 范围内
if (cos_q4 < -1.0f || cos_q4 > 1.0f) {
return -2; // 不可达
}
float q4 = acosf(cos_q4);
// 由正解q = q1 + q4且 q4 = (PI - q1 - q2)/2
// 整理得q1 = q - q4
float q1 = q - q4;
// 再由 q4 = (PI - q1 - q2)/2整理得q2 = PI - 2*q4 - q1
float q2 = M_PI - 2.0f * q4 - q1;
*hip_angle = q1;
*knee_angle = q2;
return 0; // 成功
}