你好!看到你在做巡线避障时遇到了控制策略的难题。这是智能车竞赛中最经典的问题,你的困惑(开环难调参、规划易冲线)非常典型。
结合社区已有的成熟方案,给你三个层级的解决思路,建议根据你的基础选择:
核心结论:推荐「视觉感知 + PID闭环 + 状态机」方案
不要做开环控制(定时转弯),也不要做复杂的路径规划(容易冲出赛道)。最佳实践是:
- 视觉实时检测赛道中心点和障碍物位置
- PID闭环控制巡线(稳定、易调参)
- 状态机切换巡线/避障模式(逻辑清晰)
方案一:快速上手(推荐新手)
使用社区已验证的 NodeHub 功能包,1小时内可跑通:
步骤 1:部署视觉感知节点
# 安装赛道检测(ResNet18)
sudo apt update
sudo apt install -y tros-racing-track-detection-resnet
# 安装障碍物检测(YOLOv5s)
sudo apt install -y tros-racing-obstacle-detection-yolo
# 安装巡线控制节点
sudo apt install -y tros-racing-control
步骤 2:启动系统
# 终端1:摄像头
ros2 launch mipi_cam mipi_cam_640x480_nv12_hbmem.launch.py
# 终端2:视觉感知
ros2 launch racing_track_detection_resnet racing_track_detection_resnet.launch.py
ros2 launch racing_obstacle_detection_yolo racing_obstacle_detection_yolo.launch.py
# 终端3:控制
ros2 launch racing_control racing_control.launch.py
步骤 3:关键参数调优
编辑 racing_control.launch.py:
parameters=[
{"follow_linear_speed": 0.3}, # 巡线速度(先调低)
{"follow_angular_ratio": 1.2}, # 转向灵敏度
{"bottom_threshold": 400}, # 避障触发距离(像素)
{"obstacle_avoidance_speed": 0.2}, # 避障时减速
]
优势:无需自己写算法,社区已调优好,参考教程
方案二:自主开发(适合想深入理解)
如果你希望自己写控制逻辑,核心是状态机 + PID:
控制逻辑框架
// 伪代码示例
enum State { LINE_FOLLOWING, OBSTACLE_AVOIDING };
State current_state = LINE_FOLLOWING;
void timer_callback() {
// 1. 读取视觉数据
auto track_center = get_track_center(); // 赛道中心点
auto obstacles = get_obstacles(); // 障碍物列表
// 2. 状态切换
if (has_nearby_obstacle(obstacles)) {
current_state = OBSTACLE_AVOIDING;
} else {
current_state = LINE_FOLLOWING;
}
// 3. 执行控制
if (current_state == LINE_FOLLOWING) {
pid_follow_line(track_center);
} else {
avoid_obstacle(obstacles);
}
}
PID巡线核心代码
void pid_follow_line(Point track_center) {
int error = track_center.x - image_center_x; // 偏差
integral += error * dt;
derivative = (error - last_error) / dt;
float angular_velocity = Kp * error + Ki * integral + Kd * derivative;
publish_velocity(linear_speed, angular_velocity);
last_error = error;
}
避障策略(简单有效)
void avoid_obstacle(vector<Obstacle> obstacles) {
// 找最近的障碍物
Obstacle nearest = find_nearest(obstacles);
// 判断障碍物在左侧还是右侧
int obs_center_x = nearest.x + nearest.width / 2;
if (obs_center_x < image_center_x) {
// 障碍物在左,向右转
publish_velocity(0.2, -1.5); // 减速 + 右转
} else {
// 障碍物在右,向左转
publish_velocity(0.2, 1.5);
}
}
调参技巧:
- 先调巡线:直线速度 0.3m/s,角速度系数从 0.5 开始逐步增加
- 再调避障:触发距离设为图像高度的 2/3 处(约 400 像素)
- 最后调切换:确保避障后能平滑回到巡线
方案三:进阶优化(适合冲奖)
参考 20届智能车备赛指南,核心优化点:
1. 统一模型检测
用 YOLOv5s 同时检测:赛道线 + 障碍物 + 二维码
- 单一模型,帧率更高(X3可达30fps)
- 减少模型切换开销
2. 预测性避障
// 结合赛道中心点预判
int track_direction = track_center.x - image_center_x;
int obstacle_direction = obs_center_x - image_center_x;
// 如果障碍物阻挡预期路径,提前避障
if ((track_direction > 0 && obstacle_direction > 0) ||
(track_direction < 0 && obstacle_direction < 0)) {
early_avoidance = true;
}
3. 渐进式转向
根据障碍物距离动态调整转向强度:
float distance_ratio = bottom_y / image_height;
float dynamic_angular_speed = base_speed * (1.0 + distance_ratio);
针对你的问题
问题1:开环参数难调
原因:开环控制无法适应赛道变化(弯道曲率、速度波动)
解决:必须用闭环PID,根据实时偏差调整转向
问题2:规划后找不到线
原因:避障时转向过大/时间过长,导致赛道线移出视野
解决:
- 避障时减速(线速度降到 0.2m/s)
- 避障角度不要超过 45 度
- 避障后立即恢复巡线,让PID把车拉回赛道
推荐学习路径
- 先跑通方案一:理解数据流(摄像头→检测→控制)
- 阅读源码:学习
racing_control节点的状态机实现 - 自己改写:加入自己的避障逻辑
- 优化调参:根据实际赛道调整 PID 参数
关键资源:
最后建议
- 先用低速测试(0.2m/s),稳定后再加速
- Web界面实时监控:访问
http://[设备IP]:8000查看检测效果 - 记录日志:用
ros2 topic echo /cmd_vel观察控制指令 - 社区提问:遇到具体报错时,带上日志和代码片段再问
需要我帮你分析具体的代码实现或参数配置吗?