用Python编程实现龙门吊车重物防摆的鲁棒PID控制方案。
鲁棒 PID 控制是在传统 PID 控制的基础上,增加了一些机制来提高系统对不确定性和干扰的鲁棒性,下面将使用传统的 PID 控制器来进行控制,并通过调整参数来提高系统的鲁棒性。
import numpy as np import matplotlib.pyplot as plt class RobustPIDController: def __init__(self, kp, ki, kd): self.kp = kp self.ki = ki self.kd = kd self.prev_error = 0 self.integral = 0 def update(self, setpoint, current_value, dt): error = setpoint - current_value self.integral += error * dt derivative = (error - self.prev_error) / dt output = self.kp * error + self.ki * self.integral + self.kd * derivative self.prev_error = error return output # 模拟龙门吊车系统 def simulate_crane(pid, setpoint, initial_position, initial_angle, time_steps, dt): position = initial_position angle = initial_angle positions = [position] angles = [angle] for _ in range(time_steps): # 简单的系统模型,这里只是一个示例,实际情况会更复杂 control_output = pid.update(setpoint, position, dt) # 模拟位置和角度的更新 position += control_output * dt # 模拟重物摆动的影响 angle += 0.1 * control_output * dt positions.append(position) angles.append(angle) return positions, angles # 参数设置 kp = 1.0 ki = 0.1 kd = 0.01 setpoint = 10.0 initial_position = 0.0 initial_angle = 0.0 time_steps = 100 dt = 0.1 # 创建PID控制器 pid = RobustPIDController(kp, ki, kd) # 模拟系统 positions, angles = simulate_crane(pid, setpoint, initial_position, initial_angle, time_steps, dt) # 确保 time 数组长度和 positions 一致 time = np.linspace(0, time_steps * dt, len(positions)) # 绘制结果 plt.figure(figsize=(12, 6)) plt.subplot(2, 1, 1) plt.plot(time, positions, label='Position') plt.axhline(y=setpoint, color='r', linestyle='--', label='Setpoint') plt.xlabel('Time (s)') plt.ylabel('Position') plt.legend() plt.subplot(2, 1, 2) plt.plot(time, angles, label='Angle') plt.xlabel('Time (s)') plt.ylabel('Angle') plt.legend() plt.tight_layout() plt.show()
代码解释:
将最后提供的代码解释一下
以下是对最后提供代码的详细解释,该代码实现了龙门吊车重物防摆的鲁棒 PID 控制方案,并对系统运行过程进行模拟和结果可视化:
1. 导入必要的库
python
import numpy as np
import matplotlib.pyplot as plt
numpy
:用于进行数值计算,例如数组操作、生成等差数列等。matplotlib.pyplot
:用于绘制图表,展示模拟结果。
2. 定义鲁棒 PID 控制器类
python
class RobustPIDController:
def __init__(self, kp, ki, kd):
self.kp = kp
self.ki = ki
self.kd = kd
self.prev_error = 0
self.integral = 0
def update(self, setpoint, current_value, dt):
error = setpoint - current_value
self.integral += error * dt
derivative = (error - self.prev_error) / dt
output = self.kp * error + self.ki * self.integral + self.kd * derivative
self.prev_error = error
return output
__init__
方法:初始化 PID 控制器的参数,包括比例系数kp
、积分系数ki
、微分系数kd
,同时初始化上一次的误差prev_error
和积分项integral
为 0。update
方法:根据当前的设定值setpoint
和当前值current_value
计算控制输出。具体步骤如下:- 计算当前误差
error
。 - 更新积分项
integral
,即累加当前误差乘以时间步长dt
。 - 计算误差的微分
derivative
,即当前误差与上一次误差的差值除以时间步长dt
。 - 根据 PID 公式计算控制输出
output
。 - 更新上一次的误差
prev_error
为当前误差。
- 计算当前误差
3. 定义模拟龙门吊车系统的函数
python
def simulate_crane(pid, setpoint, initial_position, initial_angle, time_steps, dt):
position = initial_position
angle = initial_angle
positions = [position]
angles = [angle]
for _ in range(time_steps):
# 简单的系统模型,这里只是一个示例,实际情况会更复杂
control_output = pid.update(setpoint, position, dt)
# 模拟位置和角度的更新
position += control_output * dt
# 模拟重物摆动的影响
angle += 0.1 * control_output * dt
positions.append(position)
angles.append(angle)
return positions, angles
- 该函数接受 PID 控制器对象
pid
、设定值setpoint
、初始位置initial_position
、初始角度initial_angle
、时间步数time_steps
和时间步长dt
作为输入。 - 初始化位置和角度,并创建用于存储位置和角度历史值的列表
positions
和angles
。 - 在每个时间步中:
- 调用 PID 控制器的
update
方法计算控制输出control_output
。 - 根据控制输出更新位置和角度,这里使用了简单的线性模型。
- 将更新后的位置和角度添加到相应的列表中。
- 调用 PID 控制器的
- 最后返回位置和角度的历史值列表。
4. 设置参数
python
# 参数设置
kp = 1.0
ki = 0.1
kd = 0.01
setpoint = 10.0
initial_position = 0.0
initial_angle = 0.0
time_steps = 100
dt = 0.1
kp
、ki
、kd
:分别为 PID 控制器的比例、积分、微分系数。setpoint
:设定的目标位置。initial_position
和initial_angle
:初始位置和初始角度。time_steps
:模拟的时间步数。dt
:时间步长。
5. 创建 PID 控制器并模拟系统
python
# 创建PID控制器
pid = RobustPIDController(kp, ki, kd)
# 模拟系统
positions, angles = simulate_crane(pid, setpoint, initial_position, initial_angle, time_steps, dt)
- 创建一个
RobustPIDController
类的实例pid
。 - 调用
simulate_crane
函数进行系统模拟,得到位置和角度的历史值列表positions
和angles
。
6. 生成时间数组
python
# 确保 time 数组长度和 positions 一致
time = np.linspace(0, time_steps * dt, len(positions))
- 使用
np.linspace
函数生成一个等差数列time
,其长度与positions
列表的长度相同,用于表示时间轴。
7. 绘制结果
python
# 绘制结果
plt.figure(figsize=(12, 6))
plt.subplot(2, 1, 1)
plt.plot(time, positions, label='Position')
plt.axhline(y=setpoint, color='r', linestyle='--', label='Setpoint')
plt.xlabel('Time (s)')
plt.ylabel('Position')
plt.legend()
plt.subplot(2, 1, 2)
plt.plot(time, angles, label='Angle')
plt.xlabel('Time (s)')
plt.ylabel('Angle')
plt.legend()
plt.tight_layout()
plt.show()
- 创建一个大小为
(12, 6)
的图形窗口。 - 使用
plt.subplot
函数将图形窗口划分为 2 行 1 列的子图。 - 在第一个子图中,绘制位置随时间的变化曲线,并添加目标位置的水平线作为参考。
- 在第二个子图中,绘制角度随时间的变化曲线。
- 为每个子图添加坐标轴标签和图例。
- 使用
plt.tight_layout
函数调整子图布局,避免重叠。 - 最后使用
plt.show
函数显示图形。
通过以上步骤,代码实现了龙门吊车重物防摆的鲁棒 PID 控制模拟,并将结果可视化展示。