# 开发指南 本文档提供 AGV 路径跟踪与控制系统的开发指南,包括代码结构、开发流程和最佳实践。 ## 目录 - [开发环境设置](#开发环境设置) - [代码结构](#代码结构) - [开发流程](#开发流程) - [编码规范](#编码规范) - [测试指南](#测试指南) - [调试技巧](#调试技巧) --- ## 开发环境设置 ### Windows 开发环境(推荐) #### 1. 安装 MSYS2 从 [msys2.org](https://www.msys2.org/) 下载并安装 MSYS2。 #### 2. 安装开发工具 ```bash # 打开 MSYS2 MinGW 64-bit 终端 pacman -Syu # 更新包数据库 # 安装基础开发工具 pacman -S mingw-w64-x86_64-gcc pacman -S mingw-w64-x86_64-cmake pacman -S mingw-w64-x86_64-make # 安装 Qt6 pacman -S mingw-w64-x86_64-qt6-base pacman -S mingw-w64-x86_64-qt6-tools ``` #### 3. 配置 PATH ```bash export PATH="/c/Qt/Tools/mingw1310_64/bin:$PATH" export PATH="/c/Qt/6.10.1/mingw_64/bin:$PATH" ``` ### Linux 开发环境 #### Ubuntu/Debian ```bash sudo apt-get update sudo apt-get install build-essential cmake sudo apt-get install qt6-base-dev qt6-tools-dev sudo apt-get install python3 python3-matplotlib ``` #### Fedora/RHEL ```bash sudo dnf install gcc gcc-c++ cmake sudo dnf install qt6-qtbase-devel sudo dnf install python3 python3-matplotlib ``` ### IDE 推荐 - **Visual Studio Code**: 轻量级,插件丰富 - C/C++ 插件 - CMake Tools 插件 - Qt tools 插件 - **Qt Creator**: Qt 开发首选 - **CLion**: 强大的 C++ IDE --- ## 代码结构 ### 目录组织 ``` agv-control-slam/ ├── include/ # 公共头文件 │ ├── agv_model.h │ ├── path_curve.h │ ├── path_tracker.h │ ├── control_generator.h │ └── can/ │ ├── CANController.h │ └── CurtisMotorController.h ├── src/ # 源文件实现 │ └── control/ │ ├── agv_model.cpp │ ├── path_curve.cpp │ ├── path_curve_custom.cpp │ ├── path_tracker.cpp │ ├── control_generator.cpp │ └── can/ │ ├── CANController.cpp │ └── CurtisMotorController.cpp ├── examples/ # 示例程序 │ ├── demo.cpp │ ├── qt_gui_demo.cpp │ ├── curtis_demo.cpp │ └── ... ├── lib/ # 第三方库 │ ├── ControlCAN.dll │ └── ControlCAN.lib ├── scripts/ # 工具脚本 ├── docs/ # 文档 └── CMakeLists.txt # CMake 配置 ``` ### 模块划分 #### 1. 核心模块 (`agv_model`, `path_curve`) 负责基础的运动学模型和路径表示。 - **职责**:提供 AGV 运动学仿真和路径数据结构 - **依赖**:C++ 标准库 - **接口**:清晰的类接口,便于单元测试 #### 2. 控制模块 (`control_generator`, `path_tracker`) 实现路径跟踪算法。 - **职责**:Pure Pursuit、Stanley 等算法实现 - **依赖**:核心模块 - **接口**:算法参数可配置 #### 3. CAN 通信模块 (`can/`) 处理硬件通信。 - **职责**:CAN 设备初始化、数据收发 - **依赖**:ControlCAN 库 - **接口**:硬件抽象层 #### 4. 界面模块 (`examples/qt_gui_demo.cpp`) 提供可视化界面。 - **职责**:路径显示、参数调整、数据导出 - **依赖**:Qt6、核心模块、控制模块 - **接口**:用户友好的 GUI --- ## 开发流程 ### 1. 功能开发流程 ``` 需求分析 → 设计 → 实现 → 测试 → 文档 → 代码审查 ``` #### 需求分析 - 明确功能需求和性能要求 - 确定接口设计 - 评估技术可行性 #### 设计 - 设计类结构和接口 - 确定数据结构 - 规划测试用例 #### 实现 - 遵循编码规范 - 编写清晰的注释 - 逐步实现功能 #### 测试 - 单元测试 - 集成测试 - 性能测试 #### 文档 - 更新 API 文档 - 编写使用示例 - 更新 README ### 2. 添加新算法 假设要添加一个新的路径跟踪算法 "LQR": #### Step 1: 在 `control_generator.h` 中声明 ```cpp class ControlGenerator { public: // 现有算法... /** * @brief LQR 算法 * @param state 当前状态 * @param path 参考路径 * @param Q 状态权重矩阵 * @param R 控制权重 * @return 转向角 */ static double lqr( const AGVModel::State& state, const PathCurve& path, const Eigen::Matrix2d& Q, double R ); }; ``` #### Step 2: 在 `control_generator.cpp` 中实现 ```cpp double ControlGenerator::lqr( const AGVModel::State& state, const PathCurve& path, const Eigen::Matrix2d& Q, double R ) { // 实现 LQR 算法 // ... return steering_angle; } ``` #### Step 3: 在 `path_tracker.cpp` 中集成 ```cpp bool PathTracker::generateControlSequence(..., const std::string& algorithm) { // ... if (algorithm == "lqr") { delta = ControlGenerator::lqr(current_state, path_, Q, R); } // ... } ``` #### Step 4: 编写测试 ```cpp // examples/test_lqr.cpp #include "path_tracker.h" int main() { AGVModel model(2.0, 1.0); PathTracker tracker(model); PathCurve path = PathCurve::generateCircularPath(5.0, 100); tracker.setReferencePath(path); tracker.generateControlSequence("lqr", 0.1, 10.0, 1.0); // 验证结果... } ``` ### 3. 添加新的硬件接口 假设要添加对新电机控制器的支持: #### Step 1: 创建新的控制器类 ```cpp // include/can/NewMotorController.h class NewMotorController { public: bool initialize(...); void setSpeed(double speed); void setSteering(double angle); // ... }; ``` #### Step 2: 实现接口 ```cpp // src/control/can/NewMotorController.cpp #include "can/NewMotorController.h" bool NewMotorController::initialize(...) { // 初始化硬件 } void NewMotorController::setSpeed(double speed) { // 发送速度命令 } ``` #### Step 3: 创建示例程序 ```cpp // examples/new_motor_demo.cpp #include "can/NewMotorController.h" int main() { NewMotorController controller; controller.initialize(...); controller.setSpeed(1.0); // ... } ``` --- ## 编码规范 ### 命名约定 - **类名**:大驼峰(PascalCase) ```cpp class PathTracker { }; ``` - **函数名**:小驼峰(camelCase) ```cpp void setReferencePath(...); ``` - **变量名**:下划线分隔(snake_case) ```cpp double lookahead_distance; ``` - **常量**:全大写加下划线 ```cpp const double MAX_SPEED = 10.0; ``` - **成员变量**:后缀下划线 ```cpp class MyClass { private: int value_; }; ``` ### 注释规范 #### 头文件注释 ```cpp /** * @file path_tracker.h * @brief 路径跟踪器类定义 * @author Your Name * @date 2025-11-27 */ ``` #### 类注释 ```cpp /** * @brief 路径跟踪器 * * 整合 AGV 模型、路径和控制算法,提供完整的路径跟踪功能。 * 支持多种算法:Pure Pursuit、Stanley 等。 */ class PathTracker { // ... }; ``` #### 函数注释 ```cpp /** * @brief 生成控制序列 * @param algorithm 算法类型("pure_pursuit" 或 "stanley") * @param dt 时间步长(秒) * @param horizon 时域(秒) * @param desired_velocity 期望速度(m/s) * @return 成功返回 true,失败返回 false */ bool generateControlSequence( const std::string& algorithm, double dt, double horizon, double desired_velocity ); ``` ### 代码风格 #### 缩进和空格 - 使用 4 个空格缩进 - 运算符两侧加空格 - 逗号后加空格 ```cpp // 好的风格 int result = a + b * c; function(arg1, arg2, arg3); // 不好的风格 int result=a+b*c; function(arg1,arg2,arg3); ``` #### 大括号 ```cpp // 推荐:K&R 风格 if (condition) { // code } else { // code } // 或 Allman 风格(保持一致即可) if (condition) { // code } else { // code } ``` --- ## 测试指南 ### 单元测试 创建测试文件 `src/control/tests/test_path_tracker.cpp`: ```cpp #include "path_tracker.h" #include #include void test_circular_path_tracking() { AGVModel model(2.0, 1.0); PathTracker tracker(model); PathCurve path = PathCurve::generateCircularPath(5.0, 100); tracker.setReferencePath(path); AGVModel::State initial(0, -5, M_PI/2, 0); tracker.setInitialState(initial); bool success = tracker.generateControlSequence("pure_pursuit", 0.1, 10.0, 1.0); assert(success && "Failed to generate control sequence"); const auto& sequence = tracker.getControlSequence(); assert(!sequence.predicted_states.empty() && "Empty control sequence"); std::cout << "✓ Circular path tracking test passed" << std::endl; } int main() { test_circular_path_tracking(); // 更多测试... return 0; } ``` ### 集成测试 测试完整的系统流程: ```cpp void test_full_system() { // 1. 创建模型 AGVModel model(2.0, 1.0); PathTracker tracker(model); // 2. 加载路径 PathCurve path = PathCurve::loadFromCSV("test_path.csv"); tracker.setReferencePath(path); // 3. 生成控制 tracker.generateControlSequence("stanley", 0.1, 10.0, 1.0); // 4. 导出结果 tracker.exportToCSV("test_output.csv"); // 5. 验证结果 // ... } ``` --- ## 调试技巧 ### 1. 日志输出 在关键位置添加日志: ```cpp #include #include void PathTracker::generateControlSequence(...) { std::cout << "[DEBUG] Starting control generation" << std::endl; std::cout << " Algorithm: " << algorithm << std::endl; std::cout << " dt: " << dt << ", horizon: " << horizon << std::endl; // ... std::cout << "[DEBUG] Generated " << steps << " control steps" << std::endl; } ``` ### 2. 数据可视化 使用 Python 脚本可视化结果: ```python import pandas as pd import matplotlib.pyplot as plt data = pd.read_csv('output.csv') plt.figure(figsize=(10, 10)) plt.plot(data['ref_x'], data['ref_y'], 'b-', label='Reference') plt.plot(data['x'], data['y'], 'r--', label='Trajectory') plt.legend() plt.axis('equal') plt.savefig('debug_plot.png') ``` ### 3. GDB 调试 ```bash # 编译时添加调试符号 cmake -DCMAKE_BUILD_TYPE=Debug .. make # 使用 GDB gdb ./agv_demo (gdb) break path_tracker.cpp:50 (gdb) run (gdb) print current_state ``` ### 4. Valgrind 内存检查(Linux) ```bash valgrind --leak-check=full ./agv_demo ``` --- ## 性能优化 ### 1. 编译优化 ```cmake # CMakeLists.txt set(CMAKE_CXX_FLAGS_RELEASE "-O3 -march=native") ``` ### 2. 代码优化 - 避免不必要的拷贝,使用引用 - 预分配内存 - 使用合适的数据结构 ```cpp // 好的实践 void processPath(const PathCurve& path) { // 使用引用 std::vector results; results.reserve(path.size()); // 预分配 // ... } ``` --- ## 常见问题 ### Q: 编译时找不到 Qt **A**: 设置 CMAKE_PREFIX_PATH: ```bash cmake -DCMAKE_PREFIX_PATH=/path/to/Qt/6.10.1/mingw_64 .. ``` ### Q: CAN 通信失败 **A**: 检查: 1. ControlCAN.dll 是否在 PATH 中 2. 硬件是否正确连接 3. 波特率是否匹配 ### Q: 路径跟踪精度不够 **A**: 尝试: 1. 减小时间步长 dt 2. 调整算法参数(lookahead_distance、k 等) 3. 增加路径点密度 --- ## 贡献指南 1. Fork 项目 2. 创建功能分支 (`git checkout -b feature/new-feature`) 3. 提交更改 (`git commit -am 'Add new feature'`) 4. 推送到分支 (`git push origin feature/new-feature`) 5. 创建 Pull Request --- **最后更新**: 2025-11-27