initial
This commit is contained in:
303
docs/custom_path/QT_GUI_CUSTOM_PATH_GUIDE.md
Normal file
303
docs/custom_path/QT_GUI_CUSTOM_PATH_GUIDE.md
Normal file
@@ -0,0 +1,303 @@
|
||||
# QT GUI 添加自定义路径功能 - 修改指南
|
||||
|
||||
## 概述
|
||||
|
||||
本指南将教你如何在现有的 QT GUI (`qt_gui_demo.cpp`) 中添加自定义路径选择功能。
|
||||
|
||||
## 修改步骤
|
||||
|
||||
### 步骤 1: 添加必要的头文件
|
||||
|
||||
在文件开头添加以下头文件(第16行之后):
|
||||
|
||||
```cpp
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
```
|
||||
|
||||
### 步骤 2: 在 Path Type 下拉框中添加选项
|
||||
|
||||
找到 `path_combo_` 的初始化部分(约第275-279行),修改为:
|
||||
|
||||
```cpp
|
||||
path_combo_ = new QComboBox(this);
|
||||
path_combo_->addItem("Circle Arc");
|
||||
path_combo_->addItem("Straight Line");
|
||||
path_combo_->addItem("S-Curve");
|
||||
path_combo_->addItem("Load from CSV"); // 新增
|
||||
path_combo_->addItem("Custom Spline"); // 新增
|
||||
```
|
||||
|
||||
### 步骤 3: 添加按钮和路径信息标签
|
||||
|
||||
在 path_combo_ 初始化后,添加以下代码(约第280行):
|
||||
|
||||
```cpp
|
||||
control_layout->addLayout(path_layout);
|
||||
|
||||
// 添加自定义路径按钮
|
||||
QHBoxLayout* custom_btn_layout = new QHBoxLayout();
|
||||
|
||||
QPushButton* load_csv_btn = new QPushButton("Browse CSV...", this);
|
||||
connect(load_csv_btn, &QPushButton::clicked, [this]() {
|
||||
QString filename = QFileDialog::getOpenFileName(
|
||||
this, "Open CSV Path File", "", "CSV Files (*.csv)");
|
||||
if (!filename.isEmpty()) {
|
||||
if (custom_path_.loadFromCSV(filename.toStdString(), true)) {
|
||||
custom_path_loaded_ = true;
|
||||
QMessageBox::information(this, "Success",
|
||||
QString("Loaded %1 points from CSV!").arg(
|
||||
custom_path_.getPathPoints().size()));
|
||||
} else {
|
||||
QMessageBox::warning(this, "Error", "Failed to load CSV file!");
|
||||
}
|
||||
}
|
||||
});
|
||||
custom_btn_layout->addWidget(load_csv_btn);
|
||||
|
||||
QPushButton* save_csv_btn = new QPushButton("Save Path...", this);
|
||||
connect(save_csv_btn, &QPushButton::clicked, [this]() {
|
||||
QString filename = QFileDialog::getSaveFileName(
|
||||
this, "Save Path as CSV", "my_path.csv", "CSV Files (*.csv)");
|
||||
if (!filename.isEmpty() && custom_path_loaded_) {
|
||||
if (custom_path_.saveToCSV(filename.toStdString())) {
|
||||
QMessageBox::information(this, "Success", "Path saved!");
|
||||
}
|
||||
}
|
||||
});
|
||||
custom_btn_layout->addWidget(save_csv_btn);
|
||||
|
||||
control_layout->addLayout(custom_btn_layout);
|
||||
```
|
||||
|
||||
### 步骤 4: 添加成员变量
|
||||
|
||||
在 MainWindow 类的 private 部分(约第522-529行),添加:
|
||||
|
||||
```cpp
|
||||
// 在 animation_running_ 之后添加:
|
||||
PathCurve custom_path_;
|
||||
bool custom_path_loaded_ = false;
|
||||
```
|
||||
|
||||
### 步骤 5: 修改 generateControl() 方法
|
||||
|
||||
找到 `generateControl()` 方法(约第330行),修改路径创建部分:
|
||||
|
||||
```cpp
|
||||
void generateControl() {
|
||||
updateAGVModel();
|
||||
|
||||
PathCurve path;
|
||||
QString path_type = path_combo_->currentText();
|
||||
|
||||
if (path_type == "Load from CSV") {
|
||||
if (!custom_path_loaded_) {
|
||||
QMessageBox::warning(this, "Warning",
|
||||
"Please load a CSV file first using 'Browse CSV...' button!");
|
||||
return;
|
||||
}
|
||||
path = custom_path_;
|
||||
}
|
||||
else if (path_type == "Custom Spline") {
|
||||
if (!custom_path_loaded_) {
|
||||
// 如果没有预加载,让用户输入关键点
|
||||
bool ok;
|
||||
int num_points = QInputDialog::getInt(this, "Spline Input",
|
||||
"Number of key points (2-10):", 4, 2, 10, 1, &ok);
|
||||
if (!ok) return;
|
||||
|
||||
std::vector<PathPoint> key_points;
|
||||
for (int i = 0; i < num_points; ++i) {
|
||||
double x = QInputDialog::getDouble(this, "Key Point",
|
||||
QString("Point %1 - X coordinate:").arg(i+1),
|
||||
i * 3.0, -100, 100, 2, &ok);
|
||||
if (!ok) return;
|
||||
|
||||
double y = QInputDialog::getDouble(this, "Key Point",
|
||||
QString("Point %1 - Y coordinate:").arg(i+1),
|
||||
(i % 2) * 3.0, -100, 100, 2, &ok);
|
||||
if (!ok) return;
|
||||
|
||||
key_points.push_back(PathPoint(x, y));
|
||||
}
|
||||
|
||||
path.generateSpline(key_points, 200, 0.5);
|
||||
custom_path_ = path;
|
||||
custom_path_loaded_ = true;
|
||||
} else {
|
||||
path = custom_path_;
|
||||
}
|
||||
}
|
||||
else if (path_type == "Circle Arc") {
|
||||
path.generateCircleArc(5.0, 0.0, 5.0, M_PI, M_PI / 2, 100);
|
||||
} else if (path_type == "Straight Line") {
|
||||
PathPoint start(0, 0, 0, 0);
|
||||
PathPoint end(10, 0, 0, 0);
|
||||
path.generateLine(start, end, 100);
|
||||
} else if (path_type == "S-Curve") {
|
||||
PathPoint p0(0, 0, 0, 0);
|
||||
PathPoint p1(3, 2, 0, 0);
|
||||
PathPoint p2(7, 2, 0, 0);
|
||||
PathPoint p3(10, 0, 0, 0);
|
||||
path.generateCubicBezier(p0, p1, p2, p3, 100);
|
||||
}
|
||||
|
||||
// 验证路径
|
||||
if (path.getPathPoints().empty()) {
|
||||
QMessageBox::warning(this, "Error", "Invalid path!");
|
||||
return;
|
||||
}
|
||||
|
||||
// 其余代码保持不变...
|
||||
tracker_->setReferencePath(path);
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
### 步骤 6: 添加 QInputDialog 头文件(可选,用于简单输入)
|
||||
|
||||
如果使用 QInputDialog,在文件开头添加:
|
||||
|
||||
```cpp
|
||||
#include <QInputDialog>
|
||||
```
|
||||
|
||||
## 完整修改示例(精简版)
|
||||
|
||||
如果你想要最简单的实现,只需做以下 3 处修改:
|
||||
|
||||
### 修改 1: 头文件(第1行附近)
|
||||
|
||||
```cpp
|
||||
#include "path_tracker.h"
|
||||
#include <QApplication>
|
||||
// ... 现有的 includes ...
|
||||
#include <QFileDialog> // 添加
|
||||
#include <QMessageBox> // 添加
|
||||
```
|
||||
|
||||
### 修改 2: 添加成员变量(MainWindow 类 private 部分)
|
||||
|
||||
```cpp
|
||||
private:
|
||||
// ... 现有成员 ...
|
||||
bool animation_running_ = false;
|
||||
|
||||
// 添加以下两行:
|
||||
PathCurve custom_path_;
|
||||
bool custom_path_loaded_ = false;
|
||||
};
|
||||
```
|
||||
|
||||
### 修改 3: 修改路径类型选择和控制生成
|
||||
|
||||
在 path_combo_ 添加项后(约第279行):
|
||||
|
||||
```cpp
|
||||
path_combo_->addItem("Load from CSV");
|
||||
```
|
||||
|
||||
在 generateControl() 中添加(约第336行):
|
||||
|
||||
```cpp
|
||||
if (path_type == "Load from CSV") {
|
||||
QString filename = QFileDialog::getOpenFileName(
|
||||
this, "Open CSV", "", "CSV Files (*.csv)");
|
||||
if (filename.isEmpty()) return;
|
||||
|
||||
if (!path.loadFromCSV(filename.toStdString(), true)) {
|
||||
QMessageBox::warning(this, "Error", "Failed to load CSV!");
|
||||
return;
|
||||
}
|
||||
} else if (path_type == "Circle Arc") {
|
||||
// 原有代码...
|
||||
```
|
||||
|
||||
## 编译
|
||||
|
||||
修改完成后重新编译:
|
||||
|
||||
```bash
|
||||
cd build
|
||||
cmake ..
|
||||
cmake --build .
|
||||
```
|
||||
|
||||
运行增强版 GUI:
|
||||
|
||||
```bash
|
||||
./agv_qt_gui
|
||||
```
|
||||
|
||||
## 使用方法
|
||||
|
||||
1. 启动程序
|
||||
2. 在 "Path Type" 下拉框中选择 "Load from CSV"
|
||||
3. 点击 "Generate Control" 会弹出文件选择对话框
|
||||
4. 选择你的 CSV 文件(例如 `examples/custom_path.csv`)
|
||||
5. 程序会加载路径并显示可视化
|
||||
6. 点击 "Start Animation" 查看 AGV 跟踪效果
|
||||
|
||||
## CSV 文件格式示例
|
||||
|
||||
创建一个 `my_path.csv` 文件:
|
||||
|
||||
```csv
|
||||
# My custom path
|
||||
# x, y
|
||||
0, 0
|
||||
2, 1
|
||||
4, 3
|
||||
6, 4
|
||||
8, 4
|
||||
10, 3
|
||||
12, 1
|
||||
14, 0
|
||||
```
|
||||
|
||||
## 高级功能(可选)
|
||||
|
||||
如果需要更完整的功能(样条插值对话框、保存路径等),可以参考已创建的完整版本:
|
||||
|
||||
```
|
||||
examples/qt_gui_enhanced.cpp
|
||||
```
|
||||
|
||||
该文件包含:
|
||||
- 完整的样条插值对话框
|
||||
- CSV 加载和保存功能
|
||||
- 路径信息显示
|
||||
- 更好的用户界面
|
||||
|
||||
## 故障排除
|
||||
|
||||
### 问题 1: 编译错误 "loadFromCSV 未定义"
|
||||
|
||||
**解决方案:** 确保已经:
|
||||
1. 修改了 `include/path_curve.h` 添加方法声明
|
||||
2. 在 `CMakeLists.txt` 中添加了 `src/path_curve_custom.cpp`
|
||||
3. 重新运行 cmake 和编译
|
||||
|
||||
### 问题 2: CSV 文件加载失败
|
||||
|
||||
**解决方案:**
|
||||
- 检查 CSV 格式是否正确
|
||||
- 确保文件路径正确
|
||||
- 尝试使用绝对路径
|
||||
|
||||
### 问题 3: QT5 未找到
|
||||
|
||||
**解决方案:**
|
||||
- 安装 QT5: `sudo apt-get install qt5-default` (Linux)
|
||||
- 或下载 QT5 并设置环境变量
|
||||
|
||||
## 总结
|
||||
|
||||
通过以上修改,你的 QT GUI 现在支持:
|
||||
- ✅ 从 CSV 文件加载自定义路径
|
||||
- ✅ 使用样条插值创建平滑路径
|
||||
- ✅ 保存路径到 CSV
|
||||
- ✅ 所有原有的预设路径类型
|
||||
|
||||
Enjoy your enhanced AGV path tracking GUI! 🚀
|
||||
Reference in New Issue
Block a user