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;
|
|||
|
}
|