#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; PID_t Acc_front_speed_pid; PID_t Dec_front_speed_pid; /** * @brief 根据挡位和输入转矩计算输出转矩值 * @param gear 挡位状态(STATE_FORWARD/STATE_BACKWARD/其他) * @param input_torque 输入转矩值 * @return 处理后的转矩值(已包含偏移量和系数) */ float calculateTorqueOutput(uint8_t gear, float input_torque) { const float OFFSET = 300.0f; // 偏移量常量 const float SCALE_FACTOR = 100.0f; // 缩放系数 const float DEFAULT_VALUE = 30000.0f; // 默认输出值 float output_torque; if (gear == STATE_FORWARD) { output_torque = (input_torque + OFFSET) * SCALE_FACTOR; } else if (gear == STATE_BACKWARD) { output_torque = (-input_torque + OFFSET) * SCALE_FACTOR; } else { output_torque = DEFAULT_VALUE; } return output_torque; } /** * @brief 车辆状态控制状态机 * @note 根据车速和扭矩方向切换前进/后退状态,带扭矩回滞保护 * @param ctx 状态机上下文,包含当前状态(STATE_INIT/FORWARD/BACKWARD) * @param speed 当前车速(单位:km/h),0表示静止状态 * @param torque 当前扭矩(单位:Nm),正数表示前进方向,负数表示后退方向 */ void handleVehicleState(MotorState *ctx, float speed, float torque) { switch (*ctx) { // 初始状态:根据扭矩方向初始化 case STATE_INIT: { if (torque >= 0.0f) { *ctx = STATE_FORWARD; // 正扭矩进前进档 } else { *ctx = STATE_BACKWARD; // 负扭矩进倒档 } break; } // 前进状态:零速且反向扭矩超阈值切倒档 case STATE_FORWARD: { if ( (speed == 0.0f) && (torque <= -TORQUE_HYSTERESIS_THRESHOLD) ) { *ctx = STATE_BACKWARD; // 满足条件切换 } else { *ctx = STATE_FORWARD; // 否则保持 } break; } // 倒车状态:零速且正向扭矩超阈值切前进 case STATE_BACKWARD: { if ( (speed == 0.0f) && (torque >= TORQUE_HYSTERESIS_THRESHOLD) ) { *ctx = STATE_FORWARD; // 满足条件切换 } else { *ctx = STATE_BACKWARD; // 否则保持 } break; } default:; // 异常处理 } } // 设置电机输出 void setMotorOutput(float *out_torq, float max_torque, uint16_t feed_power, uint16_t discharge_power) { float abs_left_front_speed = 0; float abs_right_front_speed = 0; float abs_left_rear_speed = 0; float abs_right_rear_speed = 0; // 档位 abs_left_front_speed = calculateTorqueOutput(diff_data.motor_state[0], out_torq[0]); //根据挡位增加转矩方向 abs_right_front_speed = calculateTorqueOutput(diff_data.motor_state[1], out_torq[1]); abs_left_rear_speed = calculateTorqueOutput(diff_data.motor_state[2], out_torq[2]); abs_right_rear_speed = calculateTorqueOutput(diff_data.motor_state[3], out_torq[3]); un_motor_output1.bit_data.gear = diff_data.motor_state[0]; un_motor_output2.bit_data.gear = diff_data.motor_state[1]; if(STATE_FORWARD == diff_data.motor_state[2])//把后两台电机反相 { un_motor_output3.bit_data.gear = STATE_BACKWARD; } else if(STATE_BACKWARD == diff_data.motor_state[2]) { un_motor_output3.bit_data.gear = STATE_FORWARD; } else { un_motor_output3.bit_data.gear = STATE_INIT; } if(STATE_FORWARD == diff_data.motor_state[3]) { un_motor_output4.bit_data.gear = STATE_BACKWARD; } else if(STATE_BACKWARD == diff_data.motor_state[3]) { un_motor_output4.bit_data.gear = STATE_FORWARD; } else { un_motor_output4.bit_data.gear = STATE_INIT; } // 设置左右电机期望转速 // un_motor_output1.bit_data.set_rotation_speed = ((uint16_t)roundf(abs_left_speed) + 30000); // 20240921 增加偏移量 30000 // un_motor_output2.bit_data.set_rotation_speed = ((uint16_t)roundf(abs_right_speed) + 30000); // 20240921 增加偏移量 30000 // 设置模式为扭矩模式 un_motor_output1.bit_data.mode = MOTOR_MODE; un_motor_output2.bit_data.mode = MOTOR_MODE; un_motor_output3.bit_data.mode = MOTOR_MODE; un_motor_output4.bit_data.mode = MOTOR_MODE; // 设置扭矩 un_motor_output1.bit_data.set_torque = (uint16_t)( (int16_t)abs_left_front_speed ); un_motor_output2.bit_data.set_torque = (uint16_t)( (int16_t)abs_right_front_speed ); un_motor_output3.bit_data.set_torque = (uint16_t)( (int16_t)abs_left_rear_speed ); un_motor_output4.bit_data.set_torque = (uint16_t)( (int16_t)abs_right_rear_speed ); //设定转速 un_motor_output1.bit_data.set_rotation_speed = 30000; un_motor_output2.bit_data.set_rotation_speed = 30000; un_motor_output3.bit_data.set_rotation_speed = 30000; un_motor_output4.bit_data.set_rotation_speed = 30000; // 设置馈电功率 un_motor_output1.bit_data.feed_power = feed_power; un_motor_output2.bit_data.feed_power = feed_power; un_motor_output3.bit_data.feed_power = feed_power; un_motor_output4.bit_data.feed_power = feed_power; // 设置放电功率 un_motor_output1.bit_data.discharge_power = discharge_power; un_motor_output2.bit_data.discharge_power = discharge_power; un_motor_output3.bit_data.discharge_power = discharge_power; un_motor_output4.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 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 left_speed_mps = 0.0f; float right_speed_mps = 0.0f; float max_torque = diff_data.max_Torq; linear_velocity_x = constrain(linear_velocity_x, -max_torque, max_torque); yaw_rate = constrain(yaw_rate, -2*max_torque, 2*max_torque); left_speed_mps = linear_velocity_x + yaw_rate; 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); // 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); motor_speed[0] = left_speed_mps;//加速状态,没有负扭矩,要么前进加速要么后退加速 motor_speed[2] = left_speed_mps; motor_speed[1] = right_speed_mps; motor_speed[3] = right_speed_mps; handleVehicleState(&diff_data.motor_state[0], diff_data.left_front_motor_speed, motor_speed[0]); //通过扭矩以及速度来判断挡位 handleVehicleState(&diff_data.motor_state[1], diff_data.right_front_motor_speed, motor_speed[1]); handleVehicleState(&diff_data.motor_state[2], diff_data.left_rear_motor_speed, motor_speed[2]); handleVehicleState(&diff_data.motor_state[3], diff_data.right_rear_motor_speed, motor_speed[3]); // 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); #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; } // 使用差速车辆动力学模型计算左右电机的期望速度 float out_torque[4] = {0,0,0,0}; // 使用差速车辆动力学模型计算左右电机的期望速度 computeInverseKinematics(output_speed, output_yaw_rate, diff_data.max_speed, out_torque); if( ( (diff_data.left_front_motor_speed / diff_data.left_rear_motor_speed) >= diff_data.diff_dead_zone ) || ( (diff_data.left_front_motor_speed / diff_data.left_rear_motor_speed) <= (1/diff_data.diff_dead_zone) ) )//如果超过2倍,或者小于2倍 { diff_data.left_speed_diff = diff_data.left_front_motor_speed - diff_data.left_rear_motor_speed; diff_data.left_diff_touue = calculatePidOutput(&Acc_front_speed_pid, 0.0f, diff_data.left_speed_diff, 0.0f, dt); //左侧转速差PID } else { diff_data.left_speed_diff = 0; Acc_front_speed_pid.integral = 0; diff_data.left_diff_touue = 0; } if( ( (diff_data.right_front_motor_speed / diff_data.right_rear_motor_speed) >= diff_data.diff_dead_zone ) || ( (diff_data.right_front_motor_speed / diff_data.right_rear_motor_speed) <= (1/diff_data.diff_dead_zone) ) )//如果超过2倍,或者小于2倍 { diff_data.right_speed_diff = diff_data.right_front_motor_speed - diff_data.right_rear_motor_speed; diff_data.right_diff_touue = calculatePidOutput(&Dec_front_speed_pid, 0.0f, diff_data.right_speed_diff, 0.0f, dt); //左侧转速差PID } else { diff_data.right_speed_diff = 0; Dec_front_speed_pid.integral = 0; diff_data.right_diff_touue = 0; } if(out_torque[0] > 0) { diff_data.left_diff_touue = constrain(diff_data.left_diff_touue, -2*out_torque[0], 2*out_torque[0]); } else { diff_data.left_diff_touue = constrain(diff_data.left_diff_touue, 2*out_torque[0], -2*out_torque[0]); } if(out_torque[1] > 0) { diff_data.right_diff_touue = constrain(diff_data.right_diff_touue, -2*out_torque[1], 2*out_torque[1]); } else { diff_data.right_diff_touue = constrain(diff_data.right_diff_touue, 2*out_torque[1], -2*out_torque[1]); } diff_data.out_torq[0] = (2*out_torque[0] + diff_data.left_diff_touue)/2.0f;//因为每一个电机都是相同的扭矩,所以扭矩和为2倍。 diff_data.out_torq[2] = (2*out_torque[0] - diff_data.left_diff_touue)/2.0f; diff_data.out_torq[1] = (2*out_torque[1] + diff_data.right_diff_touue)/2.0f; diff_data.out_torq[3] = (2*out_torque[1] - diff_data.right_diff_touue)/2.0f; // printf("output_speed: %f, output_yaw: %f, integral: %f\n", output_speed, output_yaw_rate,speed_pid.integral); // 设置电机输出 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); publishMessage(&un_motor_output3, 1); publishMessage(&un_motor_output4, 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_speed_diff); un_can_debug_output.bit_data.set_right_out = (uint16_t)(int16_t)(diff_data.right_speed_diff); 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*(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) { 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, 1, 20, 5, 5, 0.5); diff_data.desired_curvature = mapRemoteControlSpeed(diff_data.desired_curvature, 0.1, 2, 2, 1, 0.5); diff_data.desired_curvature = -diff_data.desired_curvature; 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) || (signal_id == &un_motor_input3) )// 处理第一个电机速度信号(左电机) { diff_data.left_front_motor_speed = (float)((int16_t)(un_motor_input1.bit_data.speed - 30000));//20240921 增加偏移量 diff_data.left_rear_motor_speed = (float)((int16_t)(un_motor_input3.bit_data.speed - 30000));//20240921 增加偏移量 diff_data.left_rear_motor_speed = - diff_data.left_rear_motor_speed;//20250708 增加反相 if(fabs(diff_data.left_rear_motor_speed) > fabs(diff_data.left_front_motor_speed))//取速度较小的轮速 { motor_speed_temp = diff_data.left_front_motor_speed; } else { motor_speed_temp = diff_data.left_rear_motor_speed; } diff_data.left_motor_speed = motor_speed_temp; } else if( (signal_id == &un_motor_input2) || (signal_id == &un_motor_input4) )// 处理第二个电机速度信号(右电机) { diff_data.right_front_motor_speed = (float)((int16_t)(un_motor_input2.bit_data.speed - 30000)); // 20250502 1号控制器增加反相 diff_data.right_rear_motor_speed = (float)((int16_t)(un_motor_input4.bit_data.speed - 30000)); diff_data.right_rear_motor_speed = - diff_data.right_rear_motor_speed;//20250708 增加反相 if(fabs(diff_data.right_front_motor_speed) > fabs(diff_data.right_rear_motor_speed))//取速度较小的轮速 { motor_speed_temp = diff_data.right_rear_motor_speed; } else { motor_speed_temp = diff_data.right_front_motor_speed; } diff_data.right_motor_speed = motor_speed_temp; } // 急停开关 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");//参数读取设定最大扭矩 // } if((power_data.current_state == POWER_WORKING))//电机上电才运行 { diffProcess(&diff_data);//计算左右电机期望转速 } else { resetPidIntegral(&speed_pid); resetPidIntegral(&yaw_rate_pid); diff_data.motor_state[0] = STATE_INIT; diff_data.motor_state[1] = STATE_INIT; diff_data.motor_state[2] = STATE_INIT; diff_data.motor_state[3] = STATE_INIT; } } // 预充完成处理函数 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; un_motor_output3.bit_data.gear = 0; // 0表示空挡 un_motor_output4.bit_data.gear = 0; publishMessage(&un_motor_output1, 1); publishMessage(&un_motor_output2, 1); publishMessage(&un_motor_output3, 1); publishMessage(&un_motor_output4, 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") ); } // 设置曲率 PID 控制器的参数 setPidParameters(&Dec_front_speed_pid, getParam("mot_kp"), getParam("mot_ki"), getParam("mot_kd"), getParam("mot_il"), getParam("mot_ol") ); // 设置曲率 PID 控制器的参数 setPidParameters(&Acc_front_speed_pid, Dec_front_speed_pid.kp, Dec_front_speed_pid.ki, Dec_front_speed_pid.kd, Dec_front_speed_pid.integral_limit, Dec_front_speed_pid.output_limit ); diff_data.min_Torq = (uint16_t)getParam("minTorq");//参数读取设定最大扭矩 diff_data.max_Torq = (float)getParam("maxTorq"); if(0 == (float)getParam("diff_sp"))//20250711 防止参数为0,影响计算。 { diff_data.diff_dead_zone = 2; } else { diff_data.diff_dead_zone = (float)getParam("diff_sp");//参数读取设定最大扭矩 } 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("LF_speed = %f,RF_speed = %f,LR_speed = %f,RR_speed = %f\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("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_yaw_rate: %f\n", deffspeed, deffcurvature); printf(" car state = %d,%d,%d,%d\n", diff_data.motor_state[0],diff_data.motor_state[1],diff_data.motor_state[2],diff_data.motor_state[3]); 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") ); // 初始化减速 PID 控制器 initializePid(&Dec_front_speed_pid, PID_MODE_DERIVATIVE_CALC, 0.0001f); // 设置 PID 控制器的参数 setPidParameters(&Dec_front_speed_pid, getParam("mot_kp"), getParam("mot_ki"), getParam("mot_kd"), getParam("mot_il"), getParam("mot_ol") ); // 初始化加速 PID 控制器 initializePid(&Acc_front_speed_pid, PID_MODE_DERIVATIVE_CALC, 0.0001f); // 设置 PID 控制器的参数 setPidParameters(&Acc_front_speed_pid, Dec_front_speed_pid.kp, Dec_front_speed_pid.ki, Dec_front_speed_pid.kd, Dec_front_speed_pid.integral_limit, Dec_front_speed_pid.output_limit ); subscribe(&diff_app_timer, diffParametersInit); timerStart(&diff_app_timer,1000,1);//1s调用一次 printf("diffControl: diffAppInit OK \n"); }