基于ROS和Python的两轮滑差转向UGV直线行驶PID自动整定咨询
两轮滑差转向UGV直线行驶PID自动整定实现方案
核心实现方法
- 齐格勒-尼科尔斯继电器整定法:无模型整定,不需要提前做系统辨识,最适合小型移动机器人场景。触发整定流程后,先给固定油门,将PID的I、D设为0,逐步增大P值直到yaw偏差出现等幅振荡,记录此时的临界增益
Ku和振荡周期Tu,代入公式直接计算最优参数:- P = 0.6 * Ku
- I = 1.2 * Ku / Tu
- D = 0.075 * Ku * Tu
- 适配现有代码的修改点:你当前的ROS+simple_pid框架已经覆盖了信号接收、PID控制、参数重置的基础能力,只需新增3个逻辑模块即可实现自动整定:
- 整定状态机:分为空闲、振荡触发、数据采集、参数计算、效果验证5个状态,绑定闲置RC通道作为整定触发开关
- 峰值检测逻辑:在振荡触发阶段持续采集yaw偏差值,自动识别波峰波谷,统计平均振荡周期,避免单次采样误差
- 参数自动写入逻辑:计算完成后直接调用你现有代码中的PID重置接口,自动将新参数写入PID实例,无需手动调整dynamic_reconfigure
- 优化适配方案:针对地面摩擦变化、负载波动的场景,可在整定完成后增加效果校验环节,控制小车跑10米固定距离,记录路径偏差的RMSE值,若偏差超过预设阈值则自动重新触发整定流程。
调参注意事项
- 整定操作需要在实际使用的地面环境下执行,不同摩擦系数的地面(水泥地、草地、地毯)适配的参数差异较大
- 你当前设置的PID输出限幅
(-300,300)刚好匹配SBUS转向行程,无需修改,可避免整定阶段转向输出过大导致小车翻车 - 差速转向UGV容易出现积分饱和问题,建议整定得到I参数后再手动缩小30%使用,避免纠偏过度
- simple_pid的
sample_time建议改为0.01s,和你的ROS节点刷新频率30Hz匹配,避免PID计算出现时序偏差
可复用代码片段
你可以直接把以下逻辑插入到现有代码的对应位置:
# 类__init__中新增属性 self.tune_state = "idle" self.ku = 0 self.tu = 0 self.peak_times = [] self.last_diff = 0 # cmd_callback中新增整定触发通道绑定,可自行修改对应通道号 self.tune_trigger = data.data[9] # loop循环的auto模式分支下新增整定逻辑 if self.tune_trigger > 1900 and self.tune_state == "idle": self.tune_state = "oscillate" self.pid.tunings = (2, 0, 0) # 初始设置偏大的P值触发振荡 self.peak_times = [] self.last_diff = 0 rospy.loginfo("开始PID自动整定") if self.tune_state == "oscillate": current_diff = self.diff # 检测峰值:偏差由正转负时为波峰 if self.last_diff > 0 and current_diff < 0: self.peak_times.append(time.time()) self.last_diff = current_diff # 采集4个波峰即可计算平均周期 if len(self.peak_times) >= 4: self.tu = (self.peak_times[-1] - self.peak_times[0]) / (len(self.peak_times)-1) self.ku = 2 # 对应之前设置的临界P值 # 计算最优参数 p_auto = 0.6 * self.ku i_auto = 1.2 * self.ku / self.tu d_auto = 0.075 * self.ku * self.tu # 写入PID参数 self.pid.tunings = (p_auto, i_auto, d_auto) self.tune_state = "idle" rospy.loginfo(f"自动整定完成,参数:P={p_auto:.2f}, I={i_auto:.2f}, D={d_auto:.2f}")
内容的提问来源于stack exchange,提问作者Akshay Acharya
相关产品推荐
相关产品推荐

