# 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& key_points, int num_points = 100, double tension = 0.5); ``` 同时在文件开头添加 string 头文件: ```cpp #include ``` ### 第二步:添加实现文件到编译 在 `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 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 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 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路径跟踪!