Files
1CAR/app/app_differential_drive.c

858 lines
33 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 "app_config.h"
#include "interface.h"
#include "app_frm_monitor.h"
#include "app_frm_signal.h"
#include "app_frm_timer.h"
#include "app_param_manage.h"
#include "app_pid.h"
#include "app_differential_drive.h"
#include "app_brake.h"
#include "app_power.h"
Timer diff_app_timer;
// 定义全局变量
DiffData diff_data;
PID_t speed_pid;
PID_t yaw_rate_pid;
// 设置电机输出
void setMotorOutput(float *out_torq, float max_torque, uint16_t feed_power, uint16_t discharge_power)
{
// // 档位
// un_motor_output1.bit_data.gear = (left_speed >= 0) ? 1 : 2; // 1 表示前进2 表示后退
// un_motor_output2.bit_data.gear = (right_speed >= 0) ? 1 : 2;
// // 计算绝对值并转换
int16_t abs_left_front_speed = (int16_t)(out_torq[0]);
int16_t abs_right_front_speed = (int16_t)(out_torq[1]);
int16_t abs_left_rear_speed = (int16_t)(out_torq[2]);
int16_t abs_right_rear_speed = (int16_t)(out_torq[3]);
// 设置左右电机期望转速
un_motor_output1.bit_data.MotCon_1Signal3 = (uint16_t)(-abs_right_front_speed);//20250502方向原因需要把1号电机控制器的左右电机反相
un_motor_output2.bit_data.MotCon_1Signal4 = (uint16_t)abs_right_rear_speed;
un_motor_output1.bit_data.MotCon_1Signal4 = (uint16_t)(-abs_left_front_speed);
un_motor_output2.bit_data.MotCon_1Signal3 = (uint16_t)abs_left_rear_speed;
// // 设置模式为恒速模式
// un_motor_output1.bit_data.mode = 0x01;
// un_motor_output2.bit_data.mode = 0x01;
//
// // 设置最大扭矩
// un_motor_output1.bit_data.set_torque = (max_torque + 300) * 100; // 20240921 增加偏移量
// un_motor_output2.bit_data.set_torque = (max_torque + 300) * 100; // 20240921 增加偏移量
//
// // 设置馈电功率
// un_motor_output1.bit_data.feed_power = feed_power;
// un_motor_output2.bit_data.feed_power = feed_power;
//
// // 设置放电功率
// un_motor_output1.bit_data.discharge_power = discharge_power;
// un_motor_output2.bit_data.discharge_power = discharge_power;
}
// 限制值在最小值和最大值之间
float constrain(float value, float min_val, float max_val)
{
if (value < min_val)
{
return min_val;
}
else if (value > max_val)
{
return max_val;
}
else
{
return value;
}
}
// 计算当前速度、角速度
uint8_t calculateCurrentSpeedYawRate(void)
{
// 获取轮子周长
float wheel_circumference = (float)getParam("whl_dia") * M_PI;
// 获取减速比
float gear_ratio = (float)getParam("gRatio");
if (fabsf(gear_ratio) < EPSILON)
{
return 0; // 避免除以0的情况
}
// 将电机转速 (RPM) 转换为线速度 (m/s),考虑减速比
float left_speed_mps = (diff_data.left_motor_speed * wheel_circumference) / (60.0f * gear_ratio);
float right_speed_mps = (diff_data.right_motor_speed * wheel_circumference) / (60.0f * gear_ratio);
// float left_speed_mps = 0;
// float right_speed_mps = 0;
// float left_speed_mps = 0;
// float right_speed_mps = 0;
// 计算当前速度
diff_data.speed = (left_speed_mps + right_speed_mps) / 2.0f;
// 计算速度差
float speed_diff = left_speed_mps - right_speed_mps;
// 计算角速度
float wheel_base = (float)getParam("whl_bas");
if (fabsf(wheel_base) < EPSILON)
{
return 0; // 避免除以0的情况
}
diff_data.yaw_rate = speed_diff / wheel_base;
return 0;
}
// 计算加速度
float calculateAcceleration(float speed, float previous_speed, float dt)
{
if (fabs(dt) < EPSILON)
{
return 0; // 避免除以0的情况
}
float acceleration = (speed - previous_speed) / dt;
return acceleration;
}
// 计算减速度
float calculateDeceleration(float speed, float previous_speed, float dt)
{
if (fabs(dt) < EPSILON)
{
return 0; // 避免除以0的情况
}
float deceleration = calculateAcceleration(previous_speed, speed, dt); // 减速度就是负的加速度
return deceleration;
}
// 计算最大速度
float calculateMaxSpeed()
{
// 获取最大电机转速 (RPM)
float max_rpm = (float)getParam("max_rpm");
// 获取轮子周长
float wheel_circumference = (float)getParam("whl_dia") * M_PI;
// 获取减速比
float gear_ratio = (float)getParam("gRatio");
if (fabsf(gear_ratio) < EPSILON)
{
return 0; // 避免除以0的情况
}
// 将最大电机转速 (RPM) 转换为线速度 (m/s),考虑减速比
float max_speed = (max_rpm * wheel_circumference) / (60.0f * gear_ratio);
return max_speed;
}
// 计算最大加速度
float calculateMaxAcceleration(void)
{
// 获取车辆参数
float max_motor_torque = (float)getParam("maxTorq"); // 最大电机扭矩
float vehicle_mass = (float)getParam("VehMass"); // 车辆质量
float wheel_radius = (float)getParam("whl_dia") / 2.0f; // 轮子半径
float gear_ratio = (float)getParam("gRatio"); // 减速比
if (fabsf(wheel_radius) < EPSILON || fabsf(vehicle_mass) < EPSILON )
{
return 0; // 避免除以0的情况
}
// 减速比计算扭矩
float effective_torque = max_motor_torque * gear_ratio;
// 计算最大加速度
float max_acceleration = (effective_torque / wheel_radius) / vehicle_mass;
return max_acceleration;
}
// 计算当前状态,包括当前速度、角速度、加速度、减速度、最大速度
void calculateCurrentState(float dt)
{
static float previous_speed = 0.0f;
// 更新当前速度和当前角速度
calculateCurrentSpeedYawRate();
// 更新加速度、减速度等,根据需要计算
diff_data.acceleration = calculateAcceleration(diff_data.speed, previous_speed, dt);
diff_data.deceleration = calculateDeceleration(diff_data.speed, previous_speed, dt);
diff_data.max_speed = calculateMaxSpeed();
previous_speed = diff_data.speed;
}
/**
* @brief 基于转速反比的双电机扭矩分配函数
* @param rpm1 电机1当前转速单位rpm
* @param rpm2 电机2当前转速单位rpm
* @param total_torque 系统总需求扭矩单位Nm
* @param torque1 [out] 电机1分配到的扭矩单位Nm
* @param torque2 [out] 电机2分配到的扭矩单位Nm
* @note 分配原则:转速越高的电机分配扭矩越小,确保负载均衡
*/
void distributeTorque(float rpm1, float rpm2, float total_torque, float* torque1, float* torque2, float max_torque, float min_torque)
{
// 总扭矩为0时快速返回
if (fabs(total_torque) < 0.001f) {
*torque1 = 0.0f;
*torque2 = 0.0f;
return;
}
// // 保护条件:当两电机均静止时采用平均分配策略
// if (fabs(rpm1) < 0.001f && fabs(rpm2) < 0.001f) {
// *torque1 = total_torque / 2.0f;
// *torque2 = total_torque / 2.0f;
// return;
// }
// 计算权重因子(与转速成反比关系)
// 注添加0.001f防止零转速时除零错误fabs确保负转速正确处理
float weight1 = 1.0f / (fabs(rpm1) + 0.001f);
float weight2 = 1.0f / (fabs(rpm2) + 0.001f);
// 归一化计算分配比例
float total_weight = weight1 + weight2;
*torque1 = total_torque * (weight1 / total_weight);
*torque2 = total_torque * (weight2 / total_weight);
// 独立限制单侧扭矩(修改核心逻辑)
if (fabs(*torque1) > max_torque) {
*torque1 = copysignf(max_torque, *torque1);
}
if (fabs(*torque2) > max_torque) {
*torque2 = copysignf(max_torque, *torque2);
}
// 仅对非零扭矩应用下限限制
if (fabs(*torque1) < min_torque) {
*torque1 = copysignf(min_torque, *torque1);
}
if ( fabs(*torque2) < min_torque) {
*torque2 = copysignf(min_torque, *torque2);
}
}
/**
* @brief 根据轮速差动态调整电机扭矩(带非负限制)
* @param speed_left 左轮速度单位rpm或自定义
* @param speed_right 右轮速度单位rpm或自定义
* @param torque_left 左轮扭矩指针单位Nm或自定义
* @param torque_right 右轮扭矩指针单位Nm或自定义
* @param threshold 触发调整的速差阈值(单位同轮速)
* @param k 扭矩调整系数无量纲建议0<k<1
* @note 函数会直接修改传入的扭矩值并确保扭矩不小于0
*/
void adjust_torque_by_speed_diff(float speed_left, float speed_right,
float* torque_left, float* torque_right,
float threshold, float k) {
// 计算轮速差绝对值
float speed_diff = fabsf(speed_left - speed_right);
if (speed_diff > threshold) {
// 计算需要减少的扭矩量(速差超出阈值部分×系数)
float torque_reduction = (speed_diff - threshold) * k;
if (speed_left > speed_right) {
// 左轮过快时减少左扭矩并限制最小值为0
*torque_left = fmaxf(*torque_left - torque_reduction, 0.0f);
} else {
// 右轮过快时减少右扭矩并限制最小值为0
*torque_right = fmaxf(*torque_right - torque_reduction, 0.0f);
}
}
}
// 计算左右电机速度
void computeInverseKinematics(float linear_velocity_x, float yaw_rate, float max_speed, float *motor_speed)
{
// 防止速度过低导致不必要的计算
if (fabs(max_speed) < EPSILON)
{
motor_speed[0] = 0.0f;
motor_speed[1] = 0.0f;
motor_speed[2] = 0.0f;
motor_speed[3] = 0.0f;
return;
}
#if THROTTLE_PID_MODE
float max_torque = (float)getParam("maxTorq");
linear_velocity_x = constrain(linear_velocity_x, -max_torque, max_torque);
yaw_rate = constrain(yaw_rate, -2*max_torque, 2*max_torque);
float left_speed_mps = linear_velocity_x + yaw_rate;
float right_speed_mps = linear_velocity_x - yaw_rate;
//扭矩分配
if(max_torque < left_speed_mps)
{
right_speed_mps = right_speed_mps - (left_speed_mps - max_torque);//多减去超出限值得部分,保证转矩差
left_speed_mps = max_torque;
}
else if(-max_torque > left_speed_mps)
{
right_speed_mps = right_speed_mps - (left_speed_mps + max_torque);//多减去超出限值得部分,保证转矩差
left_speed_mps = -max_torque;
}
else if(max_torque < right_speed_mps)
{
left_speed_mps = left_speed_mps - (right_speed_mps - max_torque);//多减去超出限值得部分,保证转矩差
right_speed_mps = max_torque;
}
else if(-max_torque > right_speed_mps)
{
left_speed_mps = left_speed_mps - (right_speed_mps + max_torque);//多减去超出限值得部分,保证转矩差
right_speed_mps = -max_torque;
}
else{}
printf("input_torq: left=%.1f right=%.1f yaw_rate=%.1f\n", left_speed_mps, right_speed_mps, yaw_rate);
motor_speed[0] = left_speed_mps;
motor_speed[2] = left_speed_mps;
motor_speed[1] = right_speed_mps;
motor_speed[3] = right_speed_mps;
adjust_torque_by_speed_diff( diff_data.left_front_motor_speed,diff_data.left_rear_motor_speed, &motor_speed[0], &motor_speed[2],100, 5);
adjust_torque_by_speed_diff( diff_data.right_front_motor_speed,diff_data.right_rear_motor_speed, &motor_speed[1], &motor_speed[3],100, 5);
// printf("speed: FL=%.1f FR=%.1f RL=%.1f RR=%.1f\n", diff_data.left_front_motor_speed, diff_data.right_front_motor_speed, diff_data.left_rear_motor_speed, diff_data.right_rear_motor_speed);
// distributeTorque(diff_data.left_front_motor_speed,diff_data.left_rear_motor_speed,2*left_speed_mps,&motor_speed[0],&motor_speed[2],diff_data.max_Torq,diff_data.min_Torq);
// distributeTorque(diff_data.right_front_motor_speed,diff_data.right_rear_motor_speed,2*right_speed_mps,&motor_speed[1],&motor_speed[3],diff_data.max_Torq,diff_data.min_Torq);
// printf("torq: FL=%.1fNm FR=%.1fNm RL=%.1fNm RR=%.1fNm\n", motor_speed[0], motor_speed[1], motor_speed[2], motor_speed[3]);
// // 返回计算结果
// *left_motor_speed = left_speed_mps;
// *right_motor_speed = right_speed_mps;
#else
// 限制线速度和偏航率
linear_velocity_x = constrain(linear_velocity_x, -max_speed, max_speed);
float max_yaw_rate = max_speed / ((float)getParam("whl_bas") / 2.0f);
yaw_rate = constrain(yaw_rate, -max_yaw_rate, max_yaw_rate);
// 计算旋转速度
float rotational_velocity = ((float)getParam("whl_bas") / 2.0f) * yaw_rate;
// 计算车辆左右线速度 (m/s)
float left_speed_mps = linear_velocity_x - rotational_velocity; //20250316 为解决原地转向和直行转向相同,所以把左右输出的速度交换
float right_speed_mps = linear_velocity_x + rotational_velocity;
// 计算轮子周长
float wheel_circumference = (float)getParam("whl_dia") * M_PI;
// 将车辆左右线速度转换为轮子转速 (RPM)
float left_wheel_rpm = (left_speed_mps * 60.0f) / wheel_circumference;
float right_wheel_rpm = (right_speed_mps * 60.0f) / wheel_circumference;
// 获取减速比
float gear_ratio = (float)getParam("gRatio");
// 将轮子转速转换为电机转速,考虑减速比
float left_motor_rpm = left_wheel_rpm * gear_ratio;
float right_motor_rpm = right_wheel_rpm * gear_ratio;
// 限制电机的最大和最小转速
float max_motor_rpm = (float)getParam("max_rpm");
left_motor_rpm = constrain(left_motor_rpm, -max_motor_rpm, max_motor_rpm);
right_motor_rpm = constrain(right_motor_rpm, -max_motor_rpm, max_motor_rpm);
// 当电机转速小于50转时设置为0
if (fabsf(left_motor_rpm) < 50)//速度慢所以设置位10转
{
left_motor_rpm = 0;
}
if (fabsf(right_motor_rpm) < 50)//速度慢所以设置位10转
{
right_motor_rpm = 0;
}
// 左边电机方向反一下,因为电机安装反了,返回来的数据也要反一下
// left_motor_rpm = -left_motor_rpm;
// 返回计算结果
*left_motor_speed = left_motor_rpm;
*right_motor_speed = right_motor_rpm;
#endif
}
// 映射遥控器速度,分为死区、低速区和高速区。
float mapRemoteControlSpeed(
float input_speed,
float deadzone_limit,
float input_max,
float output_max,
float input_slow,
float output_slow
)
{
float output_speed = 0.0f;
// 获取输入速度的绝对值
float abs_input = fabsf(input_speed);
//diff_data.desired_speed, 0.1, 2, 10, 1, 5
// diff_data.desired_speed = mapRemoteControlSpeed(diff_data.desired_speed, 0.1, 20, 5, 5, 0.5);
if (abs_input < deadzone_limit + EPSILON)
{
output_speed = 0.0f;// 死区
}
else if (abs_input < input_slow + EPSILON)// 低速区
{
output_speed = (abs_input - deadzone_limit) * output_slow / (input_slow - deadzone_limit);//
}
else if (abs_input <= input_max + EPSILON)// 高速区
{
output_speed = output_slow + (abs_input - input_slow) * (output_max - output_slow) / (input_max - input_slow);// 0.2 + 3 - 0.5* 15-0.2 / 17 - 0.5
}
else // 超出范围
{
output_speed = output_max;
}
// 根据原始输入速度的符号恢复方向
if (input_speed < 0)
{
output_speed = -output_speed;
}
return output_speed;
}
// 差速处理函数
static void diffProcess(void *signal_id)
{
(void)signal_id;
static float previous_time1 = 0.0f;
float time1 = (float)getCurrentTime();
float dt = (time1 - previous_time1) / PERIOD_TICK;
previous_time1 = time1;
// 计算当前状态,包括当前速度、角速度、加速度、减速度、最大速度
calculateCurrentState(dt);
// 当速度小于1时设定为原地转向 20250321 修改为考虑负号
if( (diff_data.desired_speed >= 0) && (diff_data.desired_speed <= 1.0f) )
{
diff_data.desired_yaw_rate = diff_data.desired_curvature * 1.0f;
}
else if( (diff_data.desired_speed < 0) && (diff_data.desired_speed >= -1.0f) )
{
diff_data.desired_yaw_rate = diff_data.desired_curvature * -1.0f;
}
else
{
diff_data.desired_yaw_rate = diff_data.desired_curvature * diff_data.desired_speed;
}
// printf("desired_speed: %f, desired_yaw: %f\n", diff_data.desired_speed, diff_data.desired_yaw_rate);
// 使用 PID 控制器计算输出速度和曲率
float output_speed = calculatePidOutput(&speed_pid, diff_data.desired_speed, diff_data.speed, 0.0f, dt);
float output_yaw_rate = calculatePidOutput(&yaw_rate_pid, diff_data.desired_yaw_rate, diff_data.yaw_rate, 0.0f, dt);
// 计算最大加速度,用函数计算
float max_acceleration = calculateMaxAcceleration();
// 限制输出速度在当前速度和最大加速度计算出来的速度之间
// output_speed = constrain(output_speed, diff_data.speed - max_acceleration * dt, diff_data.speed + max_acceleration * dt);
if( (0 == diff_data.desired_yaw_rate) && (0 == diff_data.desired_speed) )//手柄回中速度小的时候清0
{
resetPidIntegral(&speed_pid);
resetPidIntegral(&yaw_rate_pid);
output_speed = 0;
output_yaw_rate = 0;
}
// printf("output_speed: %f, output_yaw: %f, integral: %f\n", output_speed, output_yaw_rate,speed_pid.integral);
// if(diff_data.desired_yaw_rate != 0)//有转向的情况下下
// {
// if( (output_yaw_rate > -500) && (output_yaw_rate < 500) )//如果是转向输出在-500~500之间那么开始原地转向扭矩太小所以设定最小扭矩。
// {
// output_yaw_rate = 500;
// }
// }
// 使用差速车辆动力学模型计算左右电机的期望速度
computeInverseKinematics(output_speed, output_yaw_rate, diff_data.max_speed, &diff_data.out_torq[0]);
// if( (left_speed < 200) && (left_speed > -200) )
// {
// left_speed = 0;
// }
//
// if( (right_speed < 200) && (right_speed > -200) )
// {
// right_speed = 0;
// }
// 设置电机输出
setMotorOutput(&diff_data.out_torq[0],
diff_data.max_Torq,//
(uint16_t)getParam("feedPwr"),
(uint16_t)getParam("dispPwr"));
// 发布左右电机期望转速,电源在工作状态才能发送
if (power_data.current_state == POWER_WORKING)
{
publishMessage(&un_motor_output1, 1);
publishMessage(&un_motor_output2, 1);
}
un_can_debug_output.bit_data.speed = (uint8_t)(int8_t)(diff_data.speed*10);
un_can_debug_output.bit_data.desired_speed = (uint8_t)(int8_t)(diff_data.desired_speed*10);
un_can_debug_output.bit_data.curvature = (uint8_t)(int8_t)(diff_data.yaw_rate*10);
un_can_debug_output.bit_data.desired_curvature = (uint8_t)(int8_t)(diff_data.desired_yaw_rate*10);
un_can_debug_output.bit_data.set_left_out = (uint16_t)(int16_t)(diff_data.left_motor_speed);
un_can_debug_output.bit_data.set_right_out = (uint16_t)(int16_t)(diff_data.right_motor_speed);
publishMessage(&diff_data, 1);
}
/******************************************************************************
Filter(); N个数中取两个
******************************************************************************/
int16_t Filter(int16_t *s,uint8_t Len)
{
uint8_t i,j;
int16_t temp;
//降序排序
for(i=0;i<Len-1;i++)
for(j=i+1;j<Len;j++)
{
if(*(s+i)>*(s+j))
{
*(s+i)=*(s+i)^*(s+j);
*(s+j)=*(s+j)^*(s+i);
*(s+i)=*(s+i)^*(s+j);
}
}
temp=(*(s+Len/2)+*(s+(Len/2-1)))/2;//20210225修改为除以2负数不能够右移
return(temp);
}
// 差速输入处理函数
static void diffInput(void *signal_id)
{
static float left_speed_fiter[SPEED_FITER_NUM] = {0};
// static uint8_t left_speed_cnt = 0;
static float right_speed_fiter[SPEED_FITER_NUM] = {0};
// static uint8_t right_speed_cnt = 0;
float motor_speed_temp = 0.0f;
if (signal_id == &un_sw_sample)
{
diff_data.emergency_stop_switch = (uint8_t)un_sw_sample.bit_data.emergency_stop_switch;
}
else if ( (signal_id == &un_remote_control_input) && (1 == un_remote_control_input.bit_data.enable) )// 遥控器断线,不更新数据
{
diff_data.remote_emergency_stop = !(uint8_t)un_remote_control_input.bit_data.switch_b;
diff_data.mode = un_remote_control_input.bit_data.switch_c == 1 ? MODE_AUTO : MODE_MANUAL;
if (diff_data.mode == MODE_MANUAL)
{
diff_data.desired_speed = (float)((int16_t)(un_remote_control_input.bit_data.speed));
diff_data.desired_curvature = (float)((int16_t)(un_remote_control_input.bit_data.curvature));
// 单位转换
diff_data.desired_speed = diff_data.desired_speed * 0.01f;
diff_data.desired_curvature = diff_data.desired_curvature * 0.0001f;
// 遥控器速度映射,参数含义为:输入速度,死区,最大输入,最大输出,低速输入,低速输出
diff_data.desired_speed = mapRemoteControlSpeed(diff_data.desired_speed, 0.1, 20, 5, 5, 0.5);
diff_data.desired_curvature = mapRemoteControlSpeed(diff_data.desired_curvature, 0.1, 2, 2, 1, 0.5);
if(diff_data.desired_speed >= 0)//20250320 增加根据速度大小来决定方向,解决后退时转弯反向的问题
{
diff_data.desired_curvature = diff_data.desired_curvature;
}
else
{
diff_data.desired_curvature = -diff_data.desired_curvature;
}
}
}
else if ( (signal_id == &un_manual_computer_input) && (diff_data.mode == MODE_AUTO) )
{
diff_data.desired_speed = (float)((int16_t)(un_manual_computer_input.bit_data.set_speed));
diff_data.desired_curvature = (float)((int16_t)(un_manual_computer_input.bit_data.set_curvature));
// 单位转换
diff_data.desired_speed = diff_data.desired_speed * 0.01f;
diff_data.desired_curvature = diff_data.desired_curvature * 0.0001f;
// 遥控器速度映射,参数含义为:输入速度,死区,最大输入,最大输出,低速输入,低速输出
diff_data.desired_speed = mapRemoteControlSpeed(diff_data.desired_speed, 0.2, 2, 10, 1, 5);//20250320 修改死区为0.2解决停不住的问题
diff_data.desired_curvature = mapRemoteControlSpeed(diff_data.desired_curvature, 0, 2, 2, 1, 1);
}
else if ( (signal_id == &un_auto_computer_input) && (diff_data.mode == MODE_AUTO) )
{
diff_data.desired_speed = (float)((int16_t)(un_auto_computer_input.bit_data.set_speed));
diff_data.desired_curvature = (float)((int16_t)(un_auto_computer_input.bit_data.set_curvature));
// 单位转换
diff_data.desired_speed = diff_data.desired_speed * 0.01f;
diff_data.desired_curvature = - diff_data.desired_curvature * 0.0001f;// 20241016 增加转弯反相
// 遥控器速度映射,参数含义为:输入速度,死区,最大输入,最大输出,低速输入,低速输出
diff_data.desired_speed = mapRemoteControlSpeed(diff_data.desired_speed, 0, 5, 10, 2.5, 5);
diff_data.desired_curvature = mapRemoteControlSpeed(diff_data.desired_curvature, 0, 2, 2, 1, 1);
}
else if (signal_id == &un_motor_input1)// 处理第一个电机速度信号(左电机)
{
diff_data.right_front_motor_speed = -(float)( (int16_t)(un_motor_input1.bit_data.MotCon_1Signal3) ) / 6.0; // 20250502 1号控制器增加反相
diff_data.right_rear_motor_speed = (float)( (int16_t)(un_motor_input2.bit_data.MotCon_1Signal4) ) /6.0;
// motor_speed_temp = (motor_speed_temp + (int16_t)un_motor_input2.bit_data.MotCon_1Signal4)/2/6;
if(fabs(diff_data.right_rear_motor_speed) > fabs(diff_data.right_front_motor_speed))//取速度较小的轮速
{
motor_speed_temp = diff_data.right_front_motor_speed;
}
else
{
motor_speed_temp = diff_data.right_rear_motor_speed;
}
// diff_data.right_motor_speed = LOWPASS_FILTER(motor_speed_temp,right_speed_fiter[0]);
diff_data.right_motor_speed = motor_speed_temp;
right_speed_fiter[0] = diff_data.right_motor_speed;
// if(SPEED_FITER_NUM == right_speed_cnt)//取样4次后滤波
// {
// right_speed_cnt = 0;
// diff_data.right_motor_speed = (float)Filter(right_speed_fiter,SPEED_FITER_NUM)/6.0f;
// }
// printf("right_motor_speed = %f, motor_speed_temp = %d\n",diff_data.right_motor_speed,motor_speed_temp);
}
else if (signal_id == &un_motor_input2)// 处理第二个电机速度信号(右电机)
{
diff_data.left_front_motor_speed = -(float)( (int16_t)(un_motor_input1.bit_data.MotCon_1Signal4) ) /6.0; // 20250502 1号控制器增加反相
diff_data.left_rear_motor_speed = (float)( (int16_t)un_motor_input2.bit_data.MotCon_1Signal3 ) / 6.0;
if(fabs(diff_data.left_front_motor_speed) > fabs(diff_data.left_rear_motor_speed))//取速度较小的轮速
{
motor_speed_temp = diff_data.left_rear_motor_speed;
}
else
{
motor_speed_temp = diff_data.left_front_motor_speed;
}
diff_data.left_motor_speed = motor_speed_temp;
// diff_data.left_motor_speed = LOWPASS_FILTER(motor_speed_temp,left_speed_fiter[0]);//低通滤波器
left_speed_fiter[0] = diff_data.left_motor_speed;
// left_speed_fiter[left_speed_cnt] = motor_speed_temp;
// left_speed_cnt ++;
// if(SPEED_FITER_NUM == left_speed_cnt)//取样4次后滤波
// {
// left_speed_cnt = 0;
// diff_data.left_motor_speed = (float)Filter(left_speed_fiter,SPEED_FITER_NUM)/6.0f;
// }
}
// 急停开关
diff_data.emergency_stop_state = (uint8_t)(diff_data.emergency_stop_switch == app_close() || diff_data.remote_emergency_stop == app_close());
// 如果急停被激活,强制设定速度为0,急停包括车上急停开关和遥控器急停开关
if (diff_data.emergency_stop_state == 1)
{
diff_data.desired_speed = 0.0;
diff_data.desired_curvature = 0.0;
}
// 遥控器断线而且是在手动模式期望值清0
if ( (diff_data.mode == MODE_MANUAL) && (0 == un_remote_control_input.bit_data.enable) )
{
diff_data.desired_speed = 0.0;
diff_data.desired_curvature = 0.0;
}
if (diff_data.emergency_stop_state == 1)//刹车 20241017 增加的扭矩限制
{
diff_data.max_Torq = 5;//20240403修改。刹车就是5N
}
else if ((0 == diff_data.desired_speed) && (0 == diff_data.desired_curvature) && (diff_data.left_motor_speed > -100) && (diff_data.left_motor_speed < 100)&& (((diff_data.right_motor_speed > -100) && (diff_data.right_motor_speed < 100))))//20240330只有当手柄回中然后当前已经停止的状态才设置为最小停车扭矩
{
diff_data.max_Torq = 5;//停车 就为0 20250425 修改为5解决手柄回中震荡问题
}
else
{
diff_data.max_Torq = (uint16_t)getParam("maxTorq");//参数读取设定最大扭矩
}
diffProcess(&diff_data);//计算左右电机期望转速
}
// 预充完成处理函数
void preChargeFinish(void *signal_id)
{
(void)signal_id;
float out_torq[4] = {0.0f,0.0f,0.0f,0.0f};
setMotorOutput(out_torq, (uint16_t)getParam("maxTorq"), (uint16_t)getParam("feedPwr"), (uint16_t)getParam("dispPwr"));
// 档位
// un_motor_output1.bit_data.gear = 0; // 0表示空挡
// un_motor_output2.bit_data.gear = 0;
publishMessage(&un_motor_output1, 1);
publishMessage(&un_motor_output2, 1);
}
void diffParametersInit(void *signal_id)
{
(void)signal_id; // 标记变量为已使用,避免编译器警告
if(diff_data.mode == MODE_AUTO)//20250504 自动模式PID
{
setPidParameters(&speed_pid,
getParam("Ospd_kp"),
getParam("Ospd_ki"),
getParam("Ospd_kd"),
getParam("Ospd_il"),
getParam("Ospd_ol")
);
setPidParameters(&yaw_rate_pid,
getParam("Ocrv_kp"),
getParam("Ocrv_ki"),
getParam("Ocrv_kd"),
getParam("Ocrv_il"),
getParam("Ocrv_ol")
);
}
else//手动模式
{
setPidParameters(&speed_pid,
getParam("spd_kp"),
getParam("spd_ki"),
getParam("spd_kd"),
getParam("spd_il"),
getParam("spd_ol")
);
setPidParameters(&yaw_rate_pid,
getParam("crv_kp"),
getParam("crv_ki"),
getParam("crv_kd"),
getParam("crv_il"),
getParam("crv_ol")
);
}
diff_data.min_Torq = (uint16_t)getParam("minTorq");//参数读取设定最大扭矩
printf("desired_speed: %f, desired_yaw_rate: %f\n", diff_data.desired_speed, diff_data.desired_yaw_rate);
printf("speed: %f, yaw_rate: %f\n", diff_data.speed, diff_data.yaw_rate);
// printf("speed: %f, yaw_rate: %f\n", diff_data.speed, diff_data.yaw_rate);
printf("left_motor_speed = %f\n",diff_data.left_motor_speed);
printf("right_motor_speed = %f\n",diff_data.right_motor_speed);
// printf("speed: FL=%.1f FR=%.1f RL=%.1f RR=%.1f\n", diff_data.left_front_motor_speed, diff_data.right_front_motor_speed, diff_data.left_rear_motor_speed, diff_data.right_rear_motor_speed);
// printf("torq: FL=%.1fNm FR=%.1fNm RL=%.1fNm RR=%.1fNm\n", diff_data.out_torq[0], diff_data.out_torq[1], diff_data.out_torq[2], diff_data.out_torq[3]);
float deffspeed = (float)((int16_t)(un_remote_control_input.bit_data.speed));
float deffcurvature = (float)((int16_t)(un_remote_control_input.bit_data.curvature));
// 单位转换
deffspeed = deffspeed * 0.01f;
deffcurvature = deffcurvature * 0.0001f;
printf("remote speed = %f, remote curvature = %f\n", deffspeed, deffcurvature);
timerStart(&diff_app_timer,1000,1);//1s调用一次
}
// 差速初始化函数
void diffAppInit(void)
{
// 初始化 diff_data
memset(&diff_data, 0, sizeof(DiffData));
// 订阅相关信号
subscribe(&un_sw_sample, diffInput); // 急停开关、高压开关
subscribe(&un_motor_input1, diffInput);
subscribe(&un_motor_input2, diffInput);
subscribe(&un_auto_computer_input, diffInput);
subscribe(&un_manual_computer_input, diffInput);
subscribe(&un_remote_control_input, diffInput);
subscribe(&power_data.pre_charge_finish, preChargeFinish);
// 初始化速度 PID 控制器
initializePid(&speed_pid, PID_MODE_DERIVATIVE_CALC, 0.0001f);
// 设置速度 PID 控制器的参数
setPidParameters(&speed_pid,
getParam("spd_kp"),
getParam("spd_ki"),
getParam("spd_kd"),
getParam("spd_il"),
getParam("spd_ol")
);
// 初始化曲率 PID 控制器
initializePid(&yaw_rate_pid, PID_MODE_DERIVATIVE_CALC, 0.0001f);
// 设置曲率 PID 控制器的参数
setPidParameters(&yaw_rate_pid,
getParam("crv_kp"),
getParam("crv_ki"),
getParam("crv_kd"),
getParam("crv_il"),
getParam("crv_ol")
);
subscribe(&diff_app_timer, diffParametersInit);
timerStart(&diff_app_timer,1000,1);//1s调用一次
printf("diffControl: diffAppInit OK \n");
}