312 lines
6.6 KiB
C
312 lines
6.6 KiB
C
/*
|
||
自定义的数学运算。
|
||
*/
|
||
|
||
#include "user_math.h"
|
||
#include "math.h"
|
||
#include <string.h>
|
||
|
||
|
||
/**
|
||
* \brief 映射函数
|
||
*
|
||
* \param x 输入值
|
||
* \param in_min 输入最小值
|
||
* \param in_min 输入最大值
|
||
* \param in_min 输出最小值
|
||
* \param in_min 输出最大值
|
||
*
|
||
* \return 映射完成后的数
|
||
*/
|
||
int map_int(int x, int in_min, int in_max, int out_min, int out_max)
|
||
{
|
||
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
|
||
}
|
||
|
||
fp32 map_fp32(fp32 x, fp32 in_min, fp32 in_max, fp32 out_min, fp32 out_max)
|
||
{
|
||
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
|
||
}
|
||
|
||
int Setint_Deadzone(int value,int deadzone)
|
||
{
|
||
if(value>=-deadzone&&value<=deadzone)
|
||
{
|
||
value =0;
|
||
}
|
||
return 1;
|
||
}
|
||
|
||
|
||
float abs_float_double(float a,float b){
|
||
|
||
if((a-b)<0){return (b-a);}
|
||
else if((a>b)>0){return (a-b);}
|
||
else return 0;
|
||
|
||
}
|
||
|
||
float abs_float_single (float a){
|
||
if(a<0) return -a;
|
||
else if(a>0) return a;
|
||
else return 0;
|
||
}
|
||
|
||
|
||
// 归一化角度到 [0,2PI]
|
||
float _normalizeAngle(float angle)
|
||
{
|
||
float a = fmod(angle, 2*M_PI); //取余运算可以用于归一化,列出特殊值例子算便知
|
||
return a >= 0 ? a : (a + 2*M_PI);
|
||
}
|
||
//归一化角度到 [0,360]
|
||
float _normalizeTo360(float angle)
|
||
{
|
||
// 使用 fmod 函数取 angle 除以 360 的余数
|
||
float a = fmod(angle, 360.0f);
|
||
|
||
// 如果余数小于 0,则加上 360 再返回
|
||
return a < 0 ? (a + 360.0f) : a;
|
||
}
|
||
|
||
|
||
//角度量纲的转换
|
||
fp32 AngleChange(Angle_e hopetype,fp32 angle)
|
||
{
|
||
fp32 hope_angle;
|
||
if(hopetype==DEGREE)
|
||
{
|
||
hope_angle = angle*180/M_PI; //弧度制转角度制
|
||
}
|
||
else if(hopetype ==RADIAN)
|
||
{
|
||
hope_angle = angle*M_PI/180; //角度值转弧度制
|
||
}
|
||
return hope_angle;
|
||
|
||
}
|
||
//获取角度的函数
|
||
/*
|
||
|
||
param in type:获取角度的类型 RELATIVE ABSOLUTE
|
||
abs_angle:绝对角度的获取 注意是指针类型
|
||
zero_point:零点值 用于计算相对角度
|
||
param out final_angle: 用于输出最后期望的角度值
|
||
|
||
|
||
*/
|
||
fp32 AngleCalc(AngleType_e type, fp32 abs_angle,fp32 zero_point)
|
||
{
|
||
fp32 final_angle=0;
|
||
if(type==RELATIVE)
|
||
{
|
||
if(abs_angle - zero_point >=0.0f)
|
||
{
|
||
final_angle = abs_angle - zero_point;
|
||
}
|
||
else final_angle = M_2PI +(abs_angle -zero_point);
|
||
}
|
||
else if(type ==ABSOLUTE)
|
||
{
|
||
final_angle = abs_angle;
|
||
}
|
||
return final_angle;
|
||
|
||
}
|
||
// 函数:计算最短路径需要转动的角度
|
||
float calculate_rotation(float current_angle, float target_angle) {
|
||
float diff = target_angle - current_angle;
|
||
|
||
// 将差值调整到-180到180之间
|
||
if (diff > 180.0f) {
|
||
diff -= 360.0f;
|
||
} else if (diff < -180.0f) {
|
||
diff += 360.0f;
|
||
}
|
||
|
||
return diff;
|
||
}
|
||
|
||
//相加两个极坐标向量并返回结果
|
||
PolarCoordinate_t addPolarVectors(PolarCoordinate_t v1, PolarCoordinate_t v2) {
|
||
// 将极坐标转换为直角坐标
|
||
double x1, y1, x2, y2;
|
||
x1 = v1.r * cos(v1.theta);
|
||
y1 = v1.r * sin(v1.theta);
|
||
x2 = v2.r * cos(v2.theta);
|
||
y2 = v2.r * sin(v2.theta);
|
||
|
||
// 直角坐标相加
|
||
double x_sum = x1 + x2;
|
||
double y_sum = y1 + y2;
|
||
|
||
// 将直角坐标结果转换回极坐标
|
||
PolarCoordinate_t sum;
|
||
sum.r = sqrt(x_sum * x_sum + y_sum * y_sum);
|
||
sum.theta = atan2(y_sum, x_sum);
|
||
|
||
return sum;
|
||
}
|
||
|
||
|
||
//函数用于将直角坐标转换为极坐标
|
||
PolarCoordinate_t cartesianToPolar(fp32 x, fp32 y) {
|
||
PolarCoordinate_t polar;
|
||
|
||
// 计算极径
|
||
polar.r = sqrt(x * x + y * y);
|
||
|
||
// 计算极角
|
||
if (x == 0) {
|
||
if (y > 0) {
|
||
polar.theta = M_PI / 2.0f;
|
||
} else if (y < 0) {
|
||
polar.theta = -M_PI / 2.0f;
|
||
} else {
|
||
polar.theta = 0; // 任何角度都可以表示为0
|
||
}
|
||
} else {
|
||
polar.theta = atan2(y, x);
|
||
}
|
||
|
||
return polar;
|
||
}
|
||
|
||
|
||
//循环限幅
|
||
|
||
fp32 loop_fp32_constrain(fp32 Input, fp32 minValue, fp32 maxValue)
|
||
{
|
||
if (maxValue < minValue)
|
||
{
|
||
return Input;
|
||
}
|
||
|
||
if (Input > maxValue)
|
||
{
|
||
fp32 len = maxValue - minValue;
|
||
while (Input > maxValue)
|
||
{
|
||
Input -= len;
|
||
}
|
||
}
|
||
else if (Input < minValue)
|
||
{
|
||
fp32 len = maxValue - minValue;
|
||
while (Input < minValue)
|
||
{
|
||
Input += len;
|
||
}
|
||
}
|
||
return Input;
|
||
}
|
||
|
||
//限幅
|
||
void abs_limit_fp(fp32 *num, fp32 Limit)
|
||
{
|
||
if (*num > Limit)
|
||
{
|
||
*num = Limit;
|
||
}
|
||
else if (*num < -Limit)
|
||
{
|
||
*num = -Limit;
|
||
}
|
||
}
|
||
|
||
|
||
/* 移动向量 */
|
||
MoveVector_t *mv;
|
||
inline float InvSqrt(float x) {
|
||
#if 0
|
||
/* Fast inverse square-root */
|
||
/* See: http://en.wikipedia.org/wiki/Fast_inverse_square_root */
|
||
float halfx = 0.5f * x;
|
||
float y = x;
|
||
long i = *(long*)&y;
|
||
i = 0x5f3759df - (i>>1);
|
||
y = *(float*)&i;
|
||
y = y * (1.5f - (halfx * y * y));
|
||
y = y * (1.5f - (halfx * y * y));
|
||
return y;
|
||
#else
|
||
return 1.0f / sqrtf(x);
|
||
#endif
|
||
}
|
||
|
||
inline float AbsClip(float in, float limit) {
|
||
return (in < -limit) ? -limit : ((in > limit) ? limit : in);
|
||
}
|
||
|
||
inline void Clip(float *origin, float min, float max) {
|
||
if (*origin > max) *origin = max;
|
||
if (*origin < min) *origin = min;
|
||
}
|
||
|
||
inline float Sign(float in) { return (in > 0) ? 1.0f : 0.0f; }
|
||
/**
|
||
* \brief 将运动向量置零
|
||
*
|
||
* \param mv 被操作的值
|
||
*/
|
||
inline void ResetMoveVector(MoveVector_t *mv) { memset(mv, 0, sizeof(*mv)); }
|
||
/**
|
||
* \brief 计算循环值的误差,用于没有负数值,并在一定范围内变化的值
|
||
* 例如编码器:相差1.5PI其实等于相差-0.5PI
|
||
*
|
||
* \param sp 被操作的值
|
||
* \param fb 变化量
|
||
* \param range 被操作的值变化范围,正数时起效
|
||
*
|
||
* \return 函数运行结果
|
||
*/
|
||
inline float CircleError(float sp, float fb, float range) {
|
||
float error = sp - fb;
|
||
if (range > 0.0f) {
|
||
float half_range = range / 2.0f;
|
||
|
||
if (error > half_range)
|
||
error -= range;
|
||
else if (error < -half_range)
|
||
error += range;
|
||
}
|
||
return error;
|
||
}
|
||
|
||
/**
|
||
* \brief 循环加法,用于没有负数值,并在一定范围内变化的值
|
||
* 例如编码器,在0-2PI内变化,1.5PI + 1.5PI = 1PI
|
||
*
|
||
* \param origin 被操作的值
|
||
* \param delta 变化量
|
||
* \param range 被操作的值变化范围,正数时起效
|
||
*/
|
||
inline void CircleAdd(float *origin, float delta, float range) {
|
||
float out = *origin + delta;
|
||
if (range > 0.0f) {
|
||
if (out >= range)
|
||
out -= range;
|
||
else if (out < 0.0f)
|
||
out += range;
|
||
}
|
||
*origin = out;
|
||
}
|
||
|
||
/**
|
||
* @brief 循环值取反
|
||
*
|
||
* @param origin 被操作的值
|
||
*/
|
||
inline void CircleReverse(float *origin) { *origin = -(*origin) + M_2PI; }
|
||
/// @brief
|
||
/// @param arr 数组
|
||
/// @param n 元素数
|
||
/// @return 平均值
|
||
uint8_t average(uint8_t arr[], uint8_t n) {
|
||
int sum = 0;
|
||
for (int i = 0; i < n; i++) {
|
||
sum += arr[i];
|
||
}
|
||
return (float) sum / n;
|
||
}
|