# CSV加载闪退问题修复方案 ## 问题分析 经过代码审查,发现"Load from CSV"功能闪退的可能原因: 1. **Windows路径编码问题**(最可能的原因) - 在`examples/qt_gui_demo.cpp`第309行和326行使用了`QString::toStdString()` - 在Windows MINGW环境下,当文件路径包含中文字符或特殊字符时,这种转换可能产生错误的编码 - 导致文件路径无法正确打开,或在某些情况下导致程序崩溃 2. **单点路径处理问题** - 在`src/path_curve.cpp`的`setPathPoints`函数中,当CSV文件只包含1个数据点时,该点的theta和kappa不会被正确初始化 3. **潜在的异常处理不完整** - CSV解析过程中的某些异常可能未被完全捕获 ## 修复方案 ### 修复1: 更正文件路径编码(重要) **文件**: `examples/qt_gui_demo.cpp` **第309行** 需要修改为: ```cpp // 原代码 (第308-317行): 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!"); } } // 修改为: if (!filename.isEmpty()) { // 使用toLocal8Bit以正确处理Windows路径(包括中文路径) std::string filepath = filename.toLocal8Bit().constData(); if (custom_path_.loadFromCSV(filepath, 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!"); } } ``` **第326行** 需要修改为: ```cpp // 原代码 (第325-329行): if (!filename.isEmpty() && custom_path_loaded_) { if (custom_path_.saveToCSV(filename.toStdString())) { QMessageBox::information(this, "Success", "Path saved!"); } } // 修改为: if (!filename.isEmpty() && custom_path_loaded_) { // 使用toLocal8Bit以正确处理Windows路径(包括中文路径) std::string filepath = filename.toLocal8Bit().constData(); if (custom_path_.saveToCSV(filepath)) { QMessageBox::information(this, "Success", "Path saved!"); } } ``` ### 修复2: 改进单点路径处理 **文件**: `src/path_curve.cpp` 在`setPathPoints`函数(第106-134行)中,添加单点处理逻辑: ```cpp void PathCurve::setPathPoints(const std::vector& points) { path_points_ = points; // 计算每个点的切线方向和曲率 for (size_t i = 0; i < path_points_.size(); ++i) { if (i == 0 && path_points_.size() > 1) { // 第一个点 double dx = path_points_[i + 1].x - path_points_[i].x; double dy = path_points_[i + 1].y - path_points_[i].y; path_points_[i].theta = std::atan2(dy, dx); } else if (i == path_points_.size() - 1 && path_points_.size() > 1) { // 最后一个点 double dx = path_points_[i].x - path_points_[i - 1].x; double dy = path_points_[i].y - path_points_[i - 1].y; path_points_[i].theta = std::atan2(dy, dx); } else if (path_points_.size() > 2) { // 中间点 double dx = path_points_[i + 1].x - path_points_[i - 1].x; double dy = path_points_[i + 1].y - path_points_[i - 1].y; path_points_[i].theta = std::atan2(dy, dx); // 计算曲率(使用三点法) if (i > 0 && i < path_points_.size() - 1) { path_points_[i].kappa = computeCurvature( path_points_[i - 1], path_points_[i], path_points_[i + 1]); } } // 添加: 处理只有单个点的情况 else if (path_points_.size() == 1) { // 单个点保持其原有的theta和kappa值(通常为0) // 不需要额外计算 } } } ``` ### 修复3: 添加更完善的异常处理 **文件**: `src/path_curve_custom.cpp` 在`loadFromCSV`函数中添加更完善的错误处理: ```cpp bool PathCurve::loadFromCSV(const std::string& filename, bool has_header) { try { std::ifstream file(filename); if (!file.is_open()) { std::cerr << "Error: Cannot open file " << filename << std::endl; return false; } std::vector points; std::string line; int line_num = 0; // 跳过表头 if (has_header && std::getline(file, line)) { line_num++; } while (std::getline(file, line)) { line_num++; // 跳过空行和注释行 if (line.empty() || line[0] == '#') { continue; } std::stringstream ss(line); std::string token; std::vector values; bool parse_error = false; // 解析CSV行 while (std::getline(ss, token, ',')) { try { // 去除前后空格 size_t start = token.find_first_not_of(" \t\r\n"); size_t end = token.find_last_not_of(" \t\r\n"); if (start == std::string::npos) { // 空token,跳过整行 parse_error = true; break; } std::string trimmed = token.substr(start, end - start + 1); values.push_back(std::stod(trimmed)); } catch (const std::exception& e) { std::cerr << "Error parsing line " << line_num << ": " << line << " (reason: " << e.what() << ")" << std::endl; parse_error = true; break; } } // 如果解析出错或值数量不足,跳过整行 if (parse_error) { continue; } // 根据列数创建路径点 if (values.size() >= 2) { PathPoint p; p.x = values[0]; p.y = values[1]; p.theta = (values.size() >= 3) ? values[2] : 0.0; p.kappa = (values.size() >= 4) ? values[3] : 0.0; points.push_back(p); } } file.close(); if (points.empty()) { std::cerr << "Error: No valid path points loaded from " << filename << std::endl; return false; } // 设置路径点(会自动计算theta和kappa) setPathPoints(points); std::cout << "Successfully loaded " << points.size() << " points from " << filename << std::endl; return true; } catch (const std::exception& e) { std::cerr << "Exception in loadFromCSV: " << e.what() << std::endl; return false; } } ``` ## 测试建议 修复后,建议测试以下场景: 1. 加载包含中文路径的CSV文件 2. 加载只有2列(x, y)的CSV文件 3. 加载完整4列(x, y, theta, kappa)的CSV文件 4. 加载只有1个数据点的CSV文件 5. 加载空的CSV文件(只有header) ## 编译和重新生成 修改完成后,需要重新编译项目: ```bash cd build cmake --build . --config Release # 或 cmake --build . --config Debug ``` 编译完成后,运行 `agv_qt_gui.exe` 并测试CSV加载功能。