CollisionAvoidance/src/config/AirportBounds.cpp

135 lines
4.5 KiB
C++

#include "AirportBounds.h"
#include <nlohmann/json.hpp>
#include <fstream>
#include <filesystem>
#include "utils/Logger.h"
using json = nlohmann::json;
AirportBounds::AirportBounds(const std::string& configFile) {
// 如果配置文件路径为空,不加载配置
if (!configFile.empty()) {
loadConfig(configFile);
}
}
void AirportBounds::loadConfig(const std::string& configFile) {
// 检查文件是否存在
if (!std::filesystem::exists(configFile)) {
Logger::error("配置文件不存在: ", configFile);
Logger::error("当前工作目录: ", std::filesystem::current_path().string());
throw std::runtime_error("配置文件不存在: " + configFile);
}
std::ifstream file(configFile);
if (!file.is_open()) {
throw std::runtime_error("无法打开配置文件: " + configFile);
}
try {
json j;
file >> j;
// 检查必要的字段是否存在
if (!j.contains("airport") || !j["airport"].contains("bounds")) {
throw std::runtime_error("配置文件缺少 airport.bounds 字段");
}
// 加载机场边界
auto& airport = j["airport"]["bounds"];
airportBounds_ = {
airport["x"].get<double>(),
airport["y"].get<double>(),
airport["width"].get<double>(),
airport["height"].get<double>()
};
// 检查 areas 字段
if (!j.contains("areas")) {
throw std::runtime_error("配置文件缺少 areas 字段");
}
// 加载各区域配置
for (const auto& [key, value] : j["areas"].items()) {
AreaType type;
if (key == "runway") type = AreaType::RUNWAY;
else if (key == "taxiway") type = AreaType::TAXIWAY;
else if (key == "gate") type = AreaType::GATE;
else if (key == "service") type = AreaType::SERVICE;
else if (key == "test_zone") type = AreaType::TEST_ZONE;
else continue;
// 检查必要的字段
if (!value.contains("bounds") || !value.contains("config")) {
throw std::runtime_error("区域 " + key + " 缺少必要的字段");
}
// 加载区域边界
auto& bounds = value["bounds"];
areaBounds_[type] = {
bounds["x"].get<double>(),
bounds["y"].get<double>(),
bounds["width"].get<double>(),
bounds["height"].get<double>()
};
// 加载区域配置
auto& config = value["config"];
auto& collision_radius = config["collision_radius"];
auto& warning_zone_radius = config["warning_zone_radius"];
auto& alert_zone_radius = config["alert_zone_radius"];
RadiusConfig collision_config = {
collision_radius["aircraft"].get<double>(),
collision_radius["special"].get<double>(),
collision_radius["unmanned"].get<double>()
};
RadiusConfig warning_config = {
warning_zone_radius["aircraft"].get<double>(),
warning_zone_radius["special"].get<double>(),
warning_zone_radius["unmanned"].get<double>()
};
RadiusConfig alert_config = {
alert_zone_radius["aircraft"].get<double>(),
alert_zone_radius["special"].get<double>(),
alert_zone_radius["unmanned"].get<double>()
};
areaConfigs_[type] = {
collision_config,
config["height_threshold"].get<double>(),
warning_config,
alert_config
};
}
}
catch (const json::exception& e) {
Logger::error("JSON解析错误: ", e.what());
throw;
}
catch (const std::exception& e) {
Logger::error("加载配置文件失败: ", e.what());
throw;
}
}
AreaType AirportBounds::getAreaType(const Vector2D& position) const {
// 按优先级检查位置所在区域
for (const auto& [type, bounds] : areaBounds_) {
if (bounds.contains(position)) {
return type;
}
}
// 默认返回测试区
return AreaType::TEST_ZONE;
}
const AreaConfig& AirportBounds::getAreaConfig(AreaType type) const {
auto it = areaConfigs_.find(type);
if (it == areaConfigs_.end()) {
throw std::runtime_error("Invalid area type");
}
return it->second;
}