数学原理图 
C代码实现
akeman.c
//*************************************************
//前轮 单阿卡曼转向
//jsw
//2023-3-30
//思路: 有四个轮胎构成的矩形数据(宽 与 长) 计算出只有前轮的单阿克曼转向 角度与速度 还需要物理车轮的极限最大转角
//in: 1.轮胎矩形的宽与长 2.车辆需要转向的角度(0°-180° 以车辆中轴转向为基准) 0-90 为左转 90-180 为右转
//in: 3.车辆行走的速度(单位 m)
//return: 车轮角度 与 速度的倍数
//**************************************************
#include "math.h"
#include "akeman.h"
Veh vel_str;
//车辆行走的速度
float veh_Speed =0;
//经过计算的 车辆最大转弯角度
float veh_Angle_Max = 0;
//r0r1r2r3r4r5 为辅助线长度 需要翻阅数学原理图
float R0 = 0;
float R1 = 0;
float R2 = 0;
float R3 = 0;
float R4 = 0;
//车辆最大支持转弯角度 注意此值只会为整数
float Mid_Angle = 0;
//R轮需要旋转至的度数
float R_Angle = 0;
//L轮需要旋转至的度数
float L_Angle = 0;
//速度 (单位 速度的倍率)
float R_Speed = 0;
float L_Speed = 0;
//2023/4/1
//jsw
//车辆参数初始化
//in: 1.轮胎最大旋转角度(范围 0 - 90) 2.轮胎矩形宽(单位 米 范围 > 0) 3.轮胎矩形长(单位 米 范围 > 0)
void Vel_AKM_init(float angle_max,float VEHICLE_W,float VEHICLE_H)
{
//轮胎最大旋转角度
vel_str.angle_max = angle_max;
//轮胎矩形 W
vel_str.VEHICLE_W = VEHICLE_W;
//轮胎矩形 H
vel_str.VEHICLE_H = VEHICLE_H;
//先求出车辆最大转弯角度
//R0 = tanα
R1 = vel_str.VEHICLE_H / (float)Angle_To_Tan(vel_str.angle_max);
R0 = R1 + (float)(vel_str.VEHICLE_W / 2);
R2 = R1 + (float)vel_str.VEHICLE_W;
//已知三角形三边 求角度 把度化成弧度的公式 弧度= 度 × π / 180 度 = 弧度 × 180° / π
Mid_Angle = vel_str.VEHICLE_H / R0;
Mid_Angle = (float)Tan_To_Angle(Mid_Angle);
}
//2023/4/1
//jsw
//车辆行走阿克曼
//in: 1.车辆转向角度(中轴转向度数 不是轮胎转向角度) 2.车辆行走的速度
//结果:每一个轮胎的角度 与 速度 会被刷新
void Veh_Walk_AKM(float Angle_data)
{
//代表本次调用函数的方向
int direction = 0;
if (Angle_data > 0)
{
direction = RIGHT;
}
else if (Angle_data < 0)
{
direction = LEFT;
}
else if (Angle_data == 0)
{
direction = STRAIGHT;
}
if (Angle_data < -Mid_Angle && Angle_data > Mid_Angle)
{
//输入角度 超过车辆最大支持转弯角度 变为最大支持角度
Angle_data = Mid_Angle;
}
//需要每次刷新 辅助线的长度
R1 = vel_str.VEHICLE_H / (float)Angle_To_Tan(Angle_data);
R0 = R1 + (float)(vel_str.VEHICLE_W / 2);
R2 = R1 + (float)vel_str.VEHICLE_W;
L_Angle = vel_str.VEHICLE_H / R1;
L_Angle = (float)Tan_To_Angle(L_Angle);
R_Angle = vel_str.VEHICLE_H / R2;
R_Angle = (float)Tan_To_Angle(R_Angle);
//因为接下来要处理速度 此处不可修改 必须修正左右轮角度数据
float temp = 0;
switch (direction)
{
case RIGHT:
//左右轮子的角度应该互换
temp = L_Angle;
L_Angle = R_Angle;
R_Angle = temp;
break;
case LEFT:
//左转角度不需要互换 L就是左轮角度
break;
case STRAIGHT:
//直行不做处理
break;
//case default:
//break;
}
//接下来计算每一个轮胎应该需要多少速度 需要R3 R4
R3 = (float)R1 / Angle_To_Sin(L_Angle);
R4 = (float)R2 / Angle_To_Sin(R_Angle);
//已知 圆的半径 求弧の长 设置内测速度为基准速度
float max_round = 2 * PI * R3;
float min_round = 2 * PI * R4;
//速度倍率为 外侧速度为内测速度的Beilv倍
float Beilv = max_round / min_round;
switch (direction)
{
case RIGHT:
R_Speed = 1;
L_Speed = Beilv;
break;
case LEFT:
R_Speed = Beilv;
L_Speed = 1;
break;
case STRAIGHT:
R_Speed = 1;
L_Speed = 1;
break;
//case default:
// break;
}
}
//2023/4/1
//jsw
//tan值转换为角度值
//in tan值
//return 角度值
double Tan_To_Angle(double tan)
{
return (atan(tan) * 180 / PI);
}
//2023/4/1
//jsw
//角度值转换为tan值
//in 角度值
//return tan值
double Angle_To_Tan(double Angle)
{
return tan(Angle * PI / 180.0);
}
//2023/4/1
//jsw
//sin值转换为角度值
//in 角度值
//return 角度值
double Sin_To_Angle(double sin)
{
return (asin(sin) * 180 / PI);
}
//2023/4/1
//jsw
//角度值转换为sin值
//in 角度值
//return sin值
double Angle_To_Sin(double Angle)
{
return sin(Angle * PI / 180.0);
}
akeman.h
#ifndef _AKM_H
#define _AKM_H
//一弧度相当于180 / PI 度数。
#define PI 3.1415926
//代表方向
#define LEFT 1001
#define RIGHT 1002
#define STRAIGHT 1003
//车辆参数 使用者需要填入参数
typedef struct
{
//轮胎矩形的 宽w 与高h (单位 米)
float VEHICLE_W;
float VEHICLE_H;
//轮胎最大转角 (单位 °)
float angle_max;
}Veh;
//2023/4/1
//jsw
//AKM所需要的车辆参数
//in: 1.轮胎最大旋转角度(范围 0 - 90) 2.轮胎矩形宽(单位 米 范围 > 0) 3.轮胎矩形长(单位 米 范围 > 0)
void Vel_AKM_init(float angle_max, float VEHICLE_W, float VEHICLE_H);
//2023/4/1
//jsw
//车辆行走阿克曼
//in: 1.车辆转向角度(中轴转向度数 不是轮胎转向角度) 2.车辆行走的速度
//结果:每一个轮胎的角度 与 速度 会被刷新
void Veh_Walk_AKM(float Angle_data);
//2023/4/1
//jsw
//角度值转换为tan值
//in 角度值
//return tan值
double Angle_To_Tan(double Angle);
//2023/4/1
//jsw
//tan值转换为角度值
//in tan值
//return 角度值
double Tan_To_Angle(double tan);
//2023/4/1
//jsw
//sin值转换为角度值
//in 角度值
//return 角度值
double Sin_To_Angle(double sin);
//2023/4/1
//jsw
//角度值转换为sin值
//in 角度值
//return sin值
double Angle_To_Sin(double Angle);
#endif // _AKM_H