Files
agv-control-slam/docs/custom_path/CUSTOM_PATH_GUIDE.md
CaiXiang af65c2425d initial
2025-11-14 16:09:58 +08:00

328 lines
8.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# AGV 自定义路径功能使用指南
## 概述
本指南介绍如何使用新增的自定义路径功能,包括:
1. **从CSV文件加载路径**
2. **保存路径到CSV文件**
3. **样条插值生成平滑曲线**
## 功能特性
### 1. CSV 文件加载/保存
支持两种CSV格式
- **完整格式**`x, y, theta, kappa`
- **简化格式**`x, y` theta和kappa会自动计算
### 2. 样条插值
使用 Catmull-Rom 样条插值,只需提供少量关键点,自动生成平滑的路径曲线。
## 安装步骤
### 第一步:修改头文件
`include/path_curve.h` 中添加以下方法声明(在 `setPathPoints` 方法之后):
```cpp
// 在第77行之后添加
/**
* @brief 从CSV文件加载路径点
* @param filename CSV文件路径
* @param has_header 是否包含表头默认true
* @return 是否加载成功
*
* CSV格式支持以下两种
* 1. 完整格式x, y, theta, kappa
* 2. 简化格式x, y theta和kappa将自动计算
*/
bool loadFromCSV(const std::string& filename, bool has_header = true);
/**
* @brief 将路径点保存到CSV文件
* @param filename CSV文件路径
* @return 是否保存成功
*/
bool saveToCSV(const std::string& filename) const;
/**
* @brief 使用样条插值生成路径
* @param key_points 关键路径点只需指定x和y
* @param num_points 生成的路径点总数
* @param tension 张力参数0.0-1.0控制曲线平滑度默认0.5
*
* 使用 Catmull-Rom 样条插值,生成经过所有关键点的平滑曲线
*/
void generateSpline(const std::vector<PathPoint>& key_points,
int num_points = 100,
double tension = 0.5);
```
同时在文件开头添加 string 头文件:
```cpp
#include <string>
```
### 第二步:添加实现文件到编译
`src/CMakeLists.txt` 或主 `CMakeLists.txt` 中添加:
```cmake
add_library(path_curve_lib
src/path_curve.cpp
src/path_curve_custom.cpp # 新增
# ... 其他文件
)
```
### 第三步:重新编译
```bash
cd build
cmake ..
cmake --build .
```
## 使用示例
### 示例 1从CSV加载路径
```cpp
#include "path_curve.h"
#include "path_tracker.h"
int main() {
// 创建路径对象
PathCurve path;
// 从CSV文件加载
if (path.loadFromCSV("custom_path.csv", true)) {
std::cout << "路径加载成功!" << std::endl;
std::cout << "路径点数量: " << path.getPathPoints().size() << std::endl;
std::cout << "路径长度: " << path.getPathLength() << " m" << std::endl;
// 使用加载的路径进行跟踪
AGVModel agv(2.0, 1.0, M_PI/4);
PathTracker tracker(agv);
tracker.setReferencePath(path);
// 设置初始状态并生成控制序列
const auto& points = path.getPathPoints();
AGVModel::State initial(points[0].x, points[0].y, points[0].theta);
tracker.setInitialState(initial);
tracker.generateControlSequence("pure_pursuit", 0.1, 20.0);
// 保存结果
tracker.saveTrajectory("output_trajectory.csv");
}
return 0;
}
```
### 示例 2使用样条插值
```cpp
#include "path_curve.h"
int main() {
PathCurve path;
// 定义关键点
std::vector<PathPoint> key_points;
key_points.push_back(PathPoint(0.0, 0.0));
key_points.push_back(PathPoint(5.0, 2.0));
key_points.push_back(PathPoint(10.0, 5.0));
key_points.push_back(PathPoint(15.0, 3.0));
key_points.push_back(PathPoint(20.0, 0.0));
// 生成样条曲线200个点
path.generateSpline(key_points, 200, 0.5);
std::cout << "样条曲线生成完成" << std::endl;
std::cout << "路径长度: " << path.getPathLength() << " m" << std::endl;
// 保存到文件
path.saveToCSV("spline_path.csv");
return 0;
}
```
### 示例 3手动创建并保存路径
```cpp
#include "path_curve.h"
int main() {
PathCurve path;
// 创建路径(例如:贝塞尔曲线)
PathPoint p0(0, 0), p1(5, 10), p2(15, 10), p3(20, 0);
path.generateCubicBezier(p0, p1, p2, p3, 150);
// 保存到CSV
if (path.saveToCSV("my_custom_path.csv")) {
std::cout << "路径已保存" << std::endl;
}
return 0;
}
```
## CSV 文件格式
### 完整格式示例
```csv
# Custom Path Data
# x(m), y(m), theta(rad), kappa(1/m)
0.0, 0.0, 0.0, 0.0
1.0, 0.5, 0.1, 0.05
2.0, 1.2, 0.15, 0.03
```
### 简化格式示例
```csv
# Custom Path - Simple Format
# x(m), y(m)
0.0, 0.0
2.0, 1.0
4.0, 3.0
6.0, 4.0
```
## 参数说明
### loadFromCSV 参数
- `filename`: CSV文件路径相对或绝对路径
- `has_header`: 是否包含注释/表头行默认true
### generateSpline 参数
- `key_points`: 关键点数组最少2个点
- `num_points`: 生成的总点数推荐100-500
- `tension`: 张力系数0.0 = 最平滑1.0 = 最紧密推荐0.5
## 常见用例
### 用例 1地图路径规划
从地图软件导出路径点CSV格式直接加载使用
```cpp
PathCurve map_path;
map_path.loadFromCSV("map_waypoints.csv");
```
### 用例 2平滑路径优化
将粗糙的路径点用样条插值平滑化:
```cpp
// 加载原始路径
PathCurve rough_path;
rough_path.loadFromCSV("raw_path.csv");
// 提取关键点每隔10个点取一个
std::vector<PathPoint> key_points;
const auto& points = rough_path.getPathPoints();
for (size_t i = 0; i < points.size(); i += 10) {
key_points.push_back(points[i]);
}
// 生成平滑路径
PathCurve smooth_path;
smooth_path.generateSpline(key_points, 300, 0.3);
smooth_path.saveToCSV("smooth_path.csv");
```
### 用例 3交互式路径定义
通过用户输入定义路径:
```cpp
std::vector<PathPoint> user_points;
int n;
std::cout << "输入路径点数量: ";
std::cin >> n;
for (int i = 0; i < n; i++) {
double x, y;
std::cout << "点" << (i+1) << " x: "; std::cin >> x;
std::cout << "点" << (i+1) << " y: "; std::cin >> y;
user_points.push_back(PathPoint(x, y));
}
PathCurve user_path;
user_path.generateSpline(user_points, 200);
user_path.saveToCSV("user_defined_path.csv");
```
## 与现有路径类型的对比
| 路径类型 | 定义方式 | 灵活性 | 适用场景 |
|---------|---------|--------|---------|
| **直线** | 起点+终点 | 低 | 简单直线移动 |
| **圆弧** | 圆心+半径+角度 | 低 | 固定半径转弯 |
| **贝塞尔曲线** | 4个控制点 | 中 | S型曲线 |
| **CSV加载** | 外部文件 | 高 | 复杂预定义路径 |
| **样条插值** | 关键点数组 | 极高 | 任意平滑曲线 |
## 调试技巧
### 1. 验证加载的路径
```cpp
const auto& points = path.getPathPoints();
for (size_t i = 0; i < points.size(); i += 10) {
std::cout << "Point " << i << ": ("
<< points[i].x << ", " << points[i].y << ")" << std::endl;
}
```
### 2. 检查路径连续性
```cpp
double max_distance = 0.0;
for (size_t i = 1; i < points.size(); i++) {
double dx = points[i].x - points[i-1].x;
double dy = points[i].y - points[i-1].y;
double dist = sqrt(dx*dx + dy*dy);
max_distance = std::max(max_distance, dist);
}
std::cout << "最大点间距: " << max_distance << " m" << std::endl;
```
## 常见问题
**Q: CSV文件格式不正确怎么办**
A: 确保每行格式为 `数字, 数字, ...`,使用逗号分隔,可以有注释行(以#开头)。
**Q: 样条插值生成的路径不平滑?**
A: 尝试增加点数num_points或减小tension参数。
**Q: 路径跟踪效果不理想?**
A: 检查路径曲率kappa值确保不超过AGV的最大转向能力。
## 完整示例程序
项目中提供了完整的示例:
- `examples/custom_path.csv` - 示例CSV路径文件
- `src/path_curve_custom.cpp` - 实现代码
## 总结
使用自定义路径功能的基本步骤:
1. **准备路径数据** - CSV文件或关键点数组
2. **创建PathCurve对象** - 使用loadFromCSV或generateSpline
3. **验证路径** - 检查点数和长度
4. **应用到跟踪器** - 使用tracker.setReferencePath()
5. **运行仿真** - 生成控制序列并保存结果
现在你可以摆脱预设曲线的限制使用任意自定义路径进行AGV路径跟踪