第6周:闭环控制初探

课时: 6小时(第一次课3小时 + 第二次课3小时)


📋 本周课程表

次序 时间 主题 内容
第1次 3小时 闭环控制原理 什么是闭环控制、反馈原理
第2次 3小时 避障逻辑实现 简单避障编程、实验

第一次课:闭环控制原理(3小时)

⏱️ 时间分配

环节 时间 内容
复习 20分钟 上周内容回顾
讲解 60分钟 开环vs闭环
讲解 60分钟 反馈控制原理
茶歇 10分钟 休息
演示 30分钟 演示简单闭环

2.3.1 什么是闭环控制(60分钟)

开环控制系统

开环 = 只管发送命令,不管结果

开环控制:

┌──────────┐      命令       ┌──────────┐
│ 控制器   │ ─────────────► │ 执行器   │ ──────► 机器人
└──────────┘                └──────────┘
        ▲                         │
        │                         │
        │   结果如何?不知道!    │
        │                         │
        └─────────────────────────┘

特点:
• 简单
• 不管结果
• 适用于精度要求不高的场景

闭环控制系统

闭环 = 发送命令后,检查结果,根据误差调整

闭环控制(反馈控制):

┌──────────┐      命令       ┌──────────┐
│ 控制器   │ ─────────────► │ 执行器   │ ──────► 机器人
└──────────┘                └──────────┘
        ▲                         │
        │                         ▼
        │                   ┌──────────┐
        │                   │ 传感器   │
        │                   └────┬─────┘
        │                        │
        │                   测量位置/速度
        │                        │
        │                        ▼
        │                   ┌──────────┐
        └─────────────────── │ 比较器   │ ◄── 期望值
                             └──────────┘
                                      ▲
                                      │
                                 设定目标
                                      │

特点:
• 精确
• 能纠正误差
• 复杂但可靠

生活中的闭环控制

开环例子 闭环例子
洗衣机定时洗涤 空调恒温
风扇档位 电饭煲保温
手动灌溉 自动驾驶

2.3.2 传感器数据与控制结合(60分钟)

机器人闭环控制流程

机器人闭环控制流程:

┌─────────────────────────────────────────────────────────────┐
│                                                             │
│    设定目标                                                 │
│    (如:前进2米)                                            │
│         │                                                   │
│         ▼                                                   │
│    ┌─────────────┐                                          │
│    │  控制器     │ ← 计算误差                               │
│    │ (PID等)    │   误差 = 目标 - 实际                     │
│    └──────┬──────┘                                          │
│             │                                                │
│             ▼ 命令                                           │
│    ┌─────────────┐                                          │
│    │   执行器    │ → 发送速度命令                           │
│    │ (电机驱动) │                                            │
│    └──────┬──────┘                                          │
│             │                                                │
│             ▼                                               │
│    ┌─────────────┐                                          │
│    │   机器人    │ ← 执行运动                               │
│    └──────┬──────┘                                          │
│             │                                                │
│             ▼ 测量                                          │
│    ┌─────────────┐                                          │
│    │   传感器    │ → 读取里程计/编码器                      │
│    │ (里程计)   │                                            │
│    └─────────────┘                                          │
│             │                                                │
│             └──────► 返回"误差计算" ◄── 反馈              │
│                                                             │
└─────────────────────────────────────────────────────────────┘

PID控制器的LaTeX表示

$$u(t) = K_p e(t) + K_i \int_0^t e(\tau) d\tau + K_d \frac{de}{dt}$$

其中:

  • $u(t)$ = 控制器输出
  • $e(t)$ = 误差 (目标值 - 实际值)
  • $K_p$ = 比例增益
  • $K_i$ = 积分增益
  • $K_d$ = 微分增益

PID控制器简介

PID = Proportional(比例)+ Integral(积分)+ Derivative(微分)

# PID控制公式

# 输出 = Kp * e + Ki * ∫e dt + Kd * de/dt

# 其中:
# e = 误差(目标值 - 实际值)
# Kp = 比例系数(响应速度)
# Ki = 积分系数(消除稳态误差)
# Kd = 微分系数(抑制振荡)

class PIDController:
    def __init__(self, kp, ki, kd):
        self.kp = kp
        self.ki = ki
        self.kd = kd
        self.error = 0
        self.integral = 0
        self.derivative = 0
        self.last_error = 0

    def compute(self, target, actual, dt):
        # 计算误差
        self.error = target - actual

        # 积分项
        self.integral += self.error * dt

        # 微分项
        self.derivative = (self.error - self.last_error) / dt
        self.last_error = self.error

        # PID输出
        output = (self.kp * self.error + 
                  self.ki * self.integral + 
                  self.kd * self.derivative)

        return output

第二次课:避障逻辑实现(3小时)

⏱️ 时间分配

环节 时间 内容
复习 20分钟 闭环控制概念
讲解 40分钟 避障逻辑原理
演示 30分钟 演示避障
实践 80分钟 编程实验
茶歇 10分钟 休息
实践 60分钟 综合练习

2.3.3 简单避障逻辑(40分钟)

避障原理

避障流程:

    ┌─────────────────┐
    │ 开始            │
    └────────┬────────┘
             │
             ▼
    ┌─────────────────┐
    │ 读取前方距离    │ ← 传感器测量
    └────────┬────────┘
             │
             ▼
    ┌─────────────────┐
    │ 距离 < 阈值?    │ ← 判断
    └────────┬────────┘
             │
      ┌──────┴──────┐
      │ 是           │ 否
      ▼              ▼
┌───────────┐  ┌───────────┐
│  停止     │  │  继续前进  │
│  后退     │  └───────────┘
│  转向     │
└─────┬─────┘
      │
      ▼
┌───────────┐
│ 重新检测  │
└───────────┘

伪代码

伪代码:简单避障

while True:
    distance = read_sensor()  # 读取传感器

    if distance < THRESHOLD:  # 如果距离太近
        stop()                 # 停止
        backward(0.5)         # 后退
        turn(90)              # 转弯
    else:                     # 否则
        forward(1.0)         # 继续前进

    sleep(0.1)

2.3.4 实现"撞不到墙"(80分钟)

完整避障代码

#!/usr/bin/env python3
"""
简单避障机器人
"""

import rclpy
from rclpy.node import Node
from geometry_msgs.msg import Twist
from sensor_msgs.msg import LaserScan


class BumperRobot(Node):
    """简单避障机器人"""

    def __init__(self):
        super().__init__('bumper_robot')

        # 速度发布者
        self.cmd_pub = self.create_publisher(Twist, '/cmd_vel', 10)

        # 激光雷达订阅者
        self.scan_sub = self.create_subscription(
            LaserScan,
            '/scan',
            self.scan_callback,
            10
        )

        # 参数
        self.SAFE_DISTANCE = 0.3  # 安全距离 0.3米
        self.FORWARD_SPEED = 0.2   # 前进速度
        self.BACK_SPEED = -0.1     # 后退速度
        self.TURN_SPEED = 0.5      # 转向速度

        # 标志位
        self.obstacle_detected = False

        # 定时器
        self.timer = self.create_timer(0.1, self.control_loop)

        self.get_logger().info('避障机器人启动!')

    def scan_callback(self, msg):
        """激光雷达回调"""
        # 获取前方距离
        # 激光雷达前方大约在0度附近
        min_distance = min(msg.ranges)

        if min_distance < self.SAFE_DISTANCE:
            self.obstacle_detected = True
            self.get_logger().warn(f'检测到障碍物!距离: {min_distance:.2f}m')
        else:
            self.obstacle_detected = False

    def control_loop(self):
        """控制循环"""
        msg = Twist()

        if self.obstacle_detected:
            # 有障碍物:后退+转向
            msg.linear.x = self.BACK_SPEED
            msg.angular.z = self.TURN_SPEED
            self.get_logger().info('障碍物!后退并转向...')
        else:
            # 无障碍物:前进
            msg.linear.x = self.FORWARD_SPEED
            msg.angular.z = 0.0

        self.cmd_pub.publish(msg)


def main(args=None):
    rclpy.init(args=args)
    node = BumperRobot()

    try:
        rclpy.spin(node)
    except KeyboardInterrupt:
        pass
    finally:
        # 停止机器人
        msg = Twist()
        node.cmd_pub.publish(msg)
        node.destroy_node()
        rclpy.shutdown()


if __name__ == '__main__':
    main()

2.3.5 实验(60分钟)

实验1:测试避障

# 启动Gazebo仿真
ros2 launch turtlebot3_gazebo turtlebot3_world.launch.py

# 运行避障节点
python3 bumper_robot.py

实验2:调整参数

# 调整安全距离
self.SAFE_DISTANCE = 0.5  # 原来是0.3

# 调整速度
self.FORWARD_SPEED = 0.3  # 原来是0.2

实验3:改进避障

# 改进:区分左转还是右转
def control_loop(self):
    msg = Twist()

    # 获取左右方向的距离
    left_dist = min(self.scan_msg.ranges[0:180])
    right_dist = min(self.scan_msg.ranges[180:360])

    if self.obstacle_detected:
        # 向障碍物少的方向转
        if left_dist > right_dist:
            msg.angular.z = self.TURN_SPEED  # 左转
        else:
            msg.angular.z = -self.TURN_SPEED # 右转

本周实验报告

✅ 验收清单

序号 实验 要求 完成
1 理解开环vs闭环 能解释区别
2 理解PID控制 能说各部分作用
3 运行避障代码 能看到效果
4 调整安全距离 观察行为变化
5 改进避障逻辑 区分左右转

本周作业

📝 理论题

  1. 解释什么是闭环控制
  2. PID控制器各部分的作用是什么?

💻 实践题

  1. 修改代码,实现遇到障碍物时三次后退+左转

知识点速查表

┌─────────────────────────────────────────────────────────────┐
│                    第6周知识点速查                           │
├─────────────────────────────────────────────────────────────┤
│  概念                                                          │
│  ├── 开环 = 发送命令不管结果                                │
│  ├── 闭环 = 反馈控制,根据误差调整                         │
│  ├── PID = 比例+积分+微分                                   │
│  └── 避障 = 检测障碍物 → 停止/转向                        │
├─────────────────────────────────────────────────────────────┤
│  公式                                                          │
│  └── PID输出 = Kp*e + Ki*∫e*dt + Kd*de/dt               │
└─────────────────────────────────────────────────────────────┘


参考文献

[1] Åström, K. J., & Hägglund, T. (2006). Advanced PID Control. ISA - The Instrumentation, Systems, and Automation Society. ISBN: 978-1556179426

[2] Ogata, K. (2010). Modern Control Engineering (5th ed.). Prentice Hall. ISBN: 978-0136156734

[3] Levine, W. S. (1996). The Control Handbook. CRC Press. ISBN: 978-0849345960

[4] Franklin, G. F., Powell, J. D., & Emami-Naeini, A. (2015). Feedback Control of Dynamic Systems (7th ed.). Pearson. ISBN: 978-0133496598

📚 课后阅读


下周预告

第7周:复习与实操演练

  • 前半学期知识总复习
  • 模拟练习

第6周结束!

results matching ""

    No results matching ""