This commit is contained in:
CaiXiang
2025-11-27 15:20:21 +08:00
parent 3e2884ea53
commit 7b6c956b6a
49 changed files with 2042 additions and 10294 deletions

614
docs/DEVELOPMENT.md Normal file
View File

@@ -0,0 +1,614 @@
# 开发指南
本文档提供 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 <cassert>
#include <iostream>
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 <iostream>
#include <iomanip>
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<double> 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