如何让Python模块中PID控制器的初始化代码仅在首次调用时运行一次?
解决方案
现有实现的核心问题是每次调用函数都会重新实例化PID对象,丢失积分、微分历史状态,且重复执行不必要的初始化操作,按以下方式实现即可满足你的需求:
第一步:编写PID_module.py模块文件
from simple_pid import PID as SimplePID # 以下为仅需执行一次的初始化逻辑,模块首次导入时自动运行 Kp = 80 Ki = 60 Kd = 0.01 pid = SimplePID(Kp, Ki, Kd) pid.sample_time = 0.05 # 缓存变量,用于判断目标速度是否变更 _last_target_speed = None _Kf = 0 def PID(rpm_array1, target_speed): global _last_target_speed, _Kf # 仅目标速度变化时更新设定值和前馈系数 if target_speed != _last_target_speed: _last_target_speed = target_speed _Kf = 180 / target_speed pid.setpoint = target_speed # 每次调用都需要执行的实时运算逻辑 avg_rpm_rear = (rpm_array1[2] + rpm_array1[3]) / 2 speed = (avg_rpm_rear / 60) * 0.355 x = pid(speed) pid_output = x + (target_speed * _Kf) throttle_target = pid_output + 1455 if pid_output > 0 else 1455 # 油门输出限幅 throttle_target = max(1455, min(throttle_target, 2500)) return throttle_target
第二步:主代码调用
你无需修改原有期望的调用逻辑,直接按如下方式使用即可:
import PID_module while True: # 传入实时采集的后轮转速数组和目标速度,直接得到目标油门值 target_throttle = PID_module.PID(rpm_array1, target_speed)
实现说明
- 模块顶层的初始化代码仅在第一次导入
PID_module时执行一次,不会重复创建PID对象,可正确保留PID的积分、微分历史状态,保证控制效果 - 修正了原始代码中PID类和自定义函数重名导致的命名冲突问题
- 仅目标速度发生变化时才更新设定值和前馈系数,减少不必要的重复计算
- 优化了油门限幅逻辑,代码更简洁易维护
内容的提问来源于stack exchange,提问作者SaguaroMaster
相关产品推荐
相关产品推荐

