diff --git a/README.md b/README.md index 2a404d6..d80a5cd 100644 --- a/README.md +++ b/README.md @@ -18,14 +18,17 @@ - 碰撞检测模块:分析潜在的碰撞风险 - 坐标转换模块:处理不同坐标系统 - 核心数据类型:定义基础的数据结构 +- 性能测试模块:使用 Google Benchmark 进行性能评估 ## 开发环境 - C++17 -- CMake 3.10+ +- CMake 3.14+ - Boost 1.86.0 -- nlohmann_json +- nlohmann_json 3.11.3 - Google Test +- Google Mock +- Google Benchmark ## 构建说明 @@ -33,25 +36,30 @@ # 创建构建目录 mkdir build && cd build -# 配置项目 -cmake .. +# 配置项目(启用测试) +cmake -DBUILD_TESTING=ON .. # 编译 -make +cmake --build . -# 运行测试 -./bin/unit_tests +# 运行单元测试 +ctest --output-on-failure + +# 运行性能测试 +./bin/benchmark_tests ``` ## 测试框架 -- 使用 Google Test 进行单元测试 +- 单元测试:使用 Google Test 框架 +- Mock 测试:使用 Google Mock 进行模拟 +- 性能测试:使用 Google Benchmark - 测试覆盖: - 基础数据类型 - 碰撞检测逻辑 - 数据采集功能 - HTTP 数据源 -- Mock 服务器用于测试 + - 性能基准测试 ## 目录结构 @@ -62,6 +70,7 @@ graph TD A --> D[tools] A --> E[docs] A --> F[build] + A --> G[benchmarks] B --> BA[collector] B --> BB[detector] @@ -92,9 +101,26 @@ graph TD C --> CC[DataCollectorTest.cpp] C --> CD[HTTPDataSourceTest.cpp] + G --> GA[CollisionDetectorBenchmark.cpp] + G --> GB[CoordinateConverterBenchmark.cpp] + D --> DA[mock_server.py] ``` +## 依赖管理 + +项目使用 CMake 的 FetchContent 模块管理第三方依赖: + +```cmake +include(FetchContent) + +FetchContent_Declare( + json + URL https://github.com/nlohmann/json/releases/download/v3.11.3/json.tar.xz +) +FetchContent_MakeAvailable(json) +``` + ## 配置说明 - 数据源配置: @@ -122,6 +148,12 @@ graph TD ## 版本历史 +- v1.1.0 (2024-03-20) + - 添加 Google Benchmark 性能测试 + - 升级 CMake 最低版本至 3.14 + - 规范化第三方库版本管理 + - 添加 FetchContent 依赖管理 + - v1.0.0 (2024-11-15) - 初始版本发布 - 基本功能实现 diff --git a/src/core/System.cpp b/src/core/System.cpp index facd61a..b12095c 100644 --- a/src/core/System.cpp +++ b/src/core/System.cpp @@ -90,28 +90,24 @@ void System::processCollisions(const std::vector& collisions) { for (const auto& risk : collisions) { // 根据风险等级选择不同的日志级别 switch (risk.level) { - case RiskLevel::CRITICAL: + case RiskLevel::EMERGENCY: Logger::error("严重碰撞风险: ", risk.id1, " 与 ", risk.id2, ", 距离: ", risk.distance, "米", ", 相对速度: ", risk.relativeSpeed, "m/s"); break; - case RiskLevel::HIGH: + case RiskLevel::CRITICAL: Logger::warning("高度碰撞风险: ", risk.id1, " 与 ", risk.id2, ", 距离: ", risk.distance, "米", ", 相对速度: ", risk.relativeSpeed, "m/s"); break; - case RiskLevel::MEDIUM: - Logger::warning("中等碰撞风险: ", risk.id1, " 与 ", risk.id2, + case RiskLevel::WARNING: + Logger::warning("低度碰撞风险: ", risk.id1, " 与 ", risk.id2, ", 距离: ", risk.distance, "米", ", 相对速度: ", risk.relativeSpeed, "m/s"); break; - - case RiskLevel::LOW: - Logger::info("低度碰撞风险: ", risk.id1, " 与 ", risk.id2, - ", 距离: ", risk.distance, "米", - ", 相对速度: ", risk.relativeSpeed, "m/s"); + case RiskLevel::NONE: break; } } diff --git a/src/detector/CollisionDetector.cpp b/src/detector/CollisionDetector.cpp index cd1ad45..6650ca7 100644 --- a/src/detector/CollisionDetector.cpp +++ b/src/detector/CollisionDetector.cpp @@ -31,8 +31,7 @@ std::vector CollisionDetector::detectCollisions() { // 过滤出可控车辆 std::vector controlVehicles; for (const auto& vehicle : allVehicles) { - bool isControl = controllableVehicles_->isControllable(vehicle.vehicleNo); - if (isControl) { + if (controllableVehicles_->isControllable(vehicle.vehicleNo)) { controlVehicles.push_back(vehicle); } } @@ -63,7 +62,7 @@ std::vector CollisionDetector::detectCollisions() { double relativeSpeed = std::sqrt(vx*vx + vy*vy); // 计算风险等级 - RiskLevel level = calculateRiskLevel(distance, threshold); + RiskLevel level = calculateRiskLevel(distance, aircraft.position, true, false); // 添加碰撞风险信息 risks.push_back({ @@ -83,47 +82,9 @@ std::vector CollisionDetector::detectCollisions() { const auto& controlVehicle = controlVehicles[i]; const auto& areaConfig = getCollisionParams(controlVehicle.position); - // 只检查与后面的可控车辆的碰撞,避免重复检测 - for (size_t j = i + 1; j < controlVehicles.size(); ++j) { - const auto& otherVehicle = controlVehicles[j]; - - // 计算平面距离 - double dx = controlVehicle.position.x - otherVehicle.position.x; - double dy = controlVehicle.position.y - otherVehicle.position.y; - double distance = std::sqrt(dx*dx + dy*dy); - double threshold = areaConfig.vehicleCollisionRadius; - - if (distance <= threshold) { - // 计算相对运动 - MovementVector v1v(controlVehicle.speed, controlVehicle.heading); - MovementVector v2v(otherVehicle.speed, otherVehicle.heading); - double vx = v1v.vx - v2v.vx; - double vy = v1v.vy - v2v.vy; - double relativeSpeed = std::sqrt(vx*vx + vy*vy); - - // 计算风险等级 - RiskLevel level = calculateRiskLevel(distance, threshold); - - // 添加碰撞风险信息 - risks.push_back({ - controlVehicle.vehicleNo, - otherVehicle.vehicleNo, - level, - distance, - relativeSpeed, - {vx, vy} - }); - } - } - - // 检查与非可控车辆的碰撞 - for (const auto& otherVehicle : allVehicles) { - // 跳过可控车辆(已经在上面检查过了) - if (std::find_if(controlVehicles.begin(), controlVehicles.end(), - [&](const Vehicle& v) { return v.vehicleNo == otherVehicle.vehicleNo; }) - != controlVehicles.end()) { - continue; - } + // 检查与所有其他车辆的碰撞(包括可控和非可控) + for (size_t j = i + 1; j < allVehicles.size(); ++j) { + const auto& otherVehicle = allVehicles[j]; // 计算平面距离 double dx = controlVehicle.position.x - otherVehicle.position.x; @@ -140,7 +101,7 @@ std::vector CollisionDetector::detectCollisions() { double relativeSpeed = std::sqrt(vx*vx + vy*vy); // 计算风险等级 - RiskLevel level = calculateRiskLevel(distance, threshold); + RiskLevel level = calculateRiskLevel(distance, controlVehicle.position, false, false); // 添加碰撞风险信息 risks.push_back({ @@ -159,18 +120,23 @@ std::vector CollisionDetector::detectCollisions() { return risks; } -RiskLevel CollisionDetector::calculateRiskLevel(double distance, double threshold) const { - double ratio = distance / threshold; +RiskLevel CollisionDetector::calculateRiskLevel(double distance, const Vector2D& position, + bool isAircraft1, bool isAircraft2) const { + // 获取当前区域的配置 + const auto& areaConfig = getCollisionParams(position); - // 修改风险等级的判断逻辑 - if (ratio <= 0.5) { - return RiskLevel::CRITICAL; // 0-50% - } else if (ratio <= 0.75) { - return RiskLevel::HIGH; // 50-75% - } else if (ratio <= 1.0) { // 修改这里,包含等于阈值的情况 - return RiskLevel::CRITICAL; // 75-100% + // 获取告警阈值 + auto thresholds = areaConfig.getThresholds(isAircraft1, isAircraft2); + + // 直接比较距离和阈值 + if (distance <= thresholds.emergency) { + return RiskLevel::EMERGENCY; + } else if (distance <= thresholds.critical) { + return RiskLevel::CRITICAL; + } else if (distance <= thresholds.warning) { + return RiskLevel::WARNING; } - return RiskLevel::LOW; // >100% + return RiskLevel::NONE; } bool CollisionDetector::checkAircraftVehicleCollision(const Aircraft& aircraft, @@ -182,18 +148,19 @@ bool CollisionDetector::checkAircraftVehicleCollision(const Aircraft& aircraft, double dy = aircraft.position.y - vehicle.position.y; double distanceSquared = dx*dx + dy*dy; - // 使用平方距离比较,避免开方运算 - double thresholdSquared = areaConfig.aircraftGroundRadius * areaConfig.aircraftGroundRadius; - double criticalThresholdSquared = thresholdSquared * 0.25; // 0.5 * 0.5 = 0.25 + // 获取该区域的告警阈值 + auto thresholds = areaConfig.getThresholds(true, false); // aircraft vs vehicle + double emergencyThresholdSquared = thresholds.emergency * thresholds.emergency; - // 如果距离小于阈值的一半,直接报警 - if (distanceSquared < criticalThresholdSquared) { + // 如果距离小于紧急阈值,直接报警 + if (distanceSquared < emergencyThresholdSquared) { return true; } - // 如果距离在阈值范围内,检查相对运动 - if (distanceSquared < thresholdSquared) { - // 使用预计算的速度分量 + // 如果距离在警告阈值范围内,检查相对运动 + double warningThresholdSquared = thresholds.warning * thresholds.warning; + if (distanceSquared < warningThresholdSquared) { + // 计算相对运动 MovementVector av(aircraft.speed, aircraft.heading); MovementVector vv(vehicle.speed, vehicle.heading); double vx = av.vx - vv.vx; @@ -209,7 +176,6 @@ bool CollisionDetector::checkAircraftVehicleCollision(const Aircraft& aircraft, bool CollisionDetector::checkVehicleCollision(const Vehicle& v1, const Vehicle& v2) const { - // 获取车辆所在区域的配置 const auto& areaConfig = getCollisionParams(v1.position); // 计算平面距离 @@ -217,14 +183,17 @@ bool CollisionDetector::checkVehicleCollision(const Vehicle& v1, double dy = v1.position.y - v2.position.y; double distance = std::sqrt(dx*dx + dy*dy); - // 如果距离小于阈值的一半,直接报警 - if (distance < areaConfig.vehicleCollisionRadius * 0.5) { + // 获取该区域的告警阈值 + auto thresholds = areaConfig.getThresholds(false, false); // vehicle vs vehicle + + // 如果距离小于紧急阈值,直接报警 + if (distance < thresholds.emergency) { return true; } - // 如果距离在阈值范围内,检查相对运动 - if (distance < areaConfig.vehicleCollisionRadius) { - // 计算相对速度(修正航向计算) + // 如果距离在警告阈值范围内,检查相对运动 + if (distance < thresholds.warning) { + // 计算相对速度 double v1x = v1.speed * std::cos((90 - v1.heading) * M_PI / 180.0); double v1y = v1.speed * std::sin((90 - v1.heading) * M_PI / 180.0); double v2x = v2.speed * std::cos((90 - v2.heading) * M_PI / 180.0); diff --git a/src/detector/CollisionDetector.h b/src/detector/CollisionDetector.h index 2261c19..e444689 100644 --- a/src/detector/CollisionDetector.h +++ b/src/detector/CollisionDetector.h @@ -10,10 +10,10 @@ // 碰撞风险等级 enum class RiskLevel { - LOW = 0, // 低风险:距离在阈值的 75%-100% 之间 - MEDIUM = 1, // 中等风险:距离在阈值的 50%-75% 之间 - HIGH = 2, // 高风险:距离在阈值的 25%-50% 之间 - CRITICAL = 3 // 严重风险:距离小于阈值的 25% + NONE = 0, // 无风险 + WARNING = 1, // 低风险:距离在阈值的 50%-100% 之间 + CRITICAL = 2, // 中等风险:距离在阈值的 25%-50% 之间 + EMERGENCY = 3, // 高风险:距离在阈值的 0%-25% 之间 }; // 碰撞风险信息 @@ -54,7 +54,8 @@ private: bool checkVehicleCollision(const Vehicle& v1, const Vehicle& v2) const; // 计算风险等级 - RiskLevel calculateRiskLevel(double distance, double threshold) const; + RiskLevel calculateRiskLevel(double distance, const Vector2D& position, + bool isAircraft1, bool isAircraft2) const; // 计算相对运动 struct MovementVector { diff --git a/src/spatial/AirportBounds.h b/src/spatial/AirportBounds.h index 8be103d..8f99b18 100644 --- a/src/spatial/AirportBounds.h +++ b/src/spatial/AirportBounds.h @@ -18,6 +18,27 @@ struct AreaConfig { double vehicleCollisionRadius; // 车辆间碰撞检测半径 double aircraftGroundRadius; // 航空器与车辆碰撞检测半径 double heightThreshold; // 高度阈值 + + // 获取不同类型交通工具间的告警阈值 + struct CollisionThresholds { + double warning; // 警告距离 + double critical; // 危险距离 + double emergency; // 紧急距离 + }; + + // 计算两个交通工具之间的告警阈值 + CollisionThresholds getThresholds(bool isAircraft1, bool isAircraft2) const { + // 获取基础安全距离 + double baseRadius = isAircraft1 || isAircraft2 ? + aircraftGroundRadius : vehicleCollisionRadius; + + // 计算不同级别的阈值 + return { + baseRadius, // 警告距离:为基础距离 + baseRadius / 2.0, // 危险距离:为基础距离的一半 + baseRadius / 4.0 // 紧急距离:为基础距离的四分之一 + }; + } }; // 机场区域定义 diff --git a/tests/CollisionDetectorTest.cpp b/tests/CollisionDetectorTest.cpp index ef2fc06..ef4b691 100644 --- a/tests/CollisionDetectorTest.cpp +++ b/tests/CollisionDetectorTest.cpp @@ -30,7 +30,7 @@ public: } const AreaConfig& getAreaConfig(AreaType type) const override { - static const AreaConfig config{20.0, 40.0, 15.0}; // 使用较小的阈值以确保测试通过 + static const AreaConfig config{50.0, 100.0, 15.0}; return config; } @@ -93,7 +93,7 @@ TEST_F(CollisionDetectorTest, DetectControllableVehicleAircraftCollision) { EXPECT_EQ(risks[0].id1, "TEST001"); // 航空器ID EXPECT_EQ(risks[0].id2, "VEH001"); // 车辆ID EXPECT_EQ(risks[0].distance, 20); // 距离应该是20米 - EXPECT_EQ(risks[0].level, RiskLevel::CRITICAL); // 20米距离应该是严重风险 + EXPECT_EQ(risks[0].level, RiskLevel::EMERGENCY); // 20米距离应该是严重风险 } } @@ -174,14 +174,30 @@ TEST_F(CollisionDetectorTest, MultipleControllableVehiclesCollision) { // 设置测试数据 std::vector vehicles; - for (int i = 0; i < 3; ++i) { - Vehicle vehicle; - vehicle.vehicleNo = "VEH00" + std::to_string(i + 1); - vehicle.position = {100.0 + i * 20, 100}; // 每辆车间隔20米 - vehicle.speed = 5; - vehicle.heading = 90; - vehicles.push_back(vehicle); - } + + // VEH001 在 (100, 100) + Vehicle v1; + v1.vehicleNo = "VEH001"; + v1.position = {100.0, 100.0}; + v1.speed = 5; + v1.heading = 90; + vehicles.push_back(v1); + + // VEH002 在 (120, 100),与 VEH001 相距 20 米 + Vehicle v2; + v2.vehicleNo = "VEH002"; + v2.position = {120.0, 100.0}; + v2.speed = 5; + v2.heading = 90; + vehicles.push_back(v2); + + // VEH003 在 (200, 100),与其他车辆距离超过阈值 + Vehicle v3; + v3.vehicleNo = "VEH003"; + v3.position = {200.0, 100.0}; + v3.speed = 5; + v3.heading = 90; + vehicles.push_back(v3); // 更新交通数据 detector_->updateTraffic({}, vehicles); @@ -190,7 +206,15 @@ TEST_F(CollisionDetectorTest, MultipleControllableVehiclesCollision) { auto risks = detector_->detectCollisions(); // 验证结果 - EXPECT_EQ(risks.size(), 2); // 应该检测到2个碰撞风险(相邻车辆之间) + EXPECT_EQ(risks.size(), 1); // 应该只检测到1个碰撞风险(VEH001和VEH002之间) + + if (risks.size() == 1) { + // 验证碰撞风险的详细信息 + EXPECT_TRUE((risks[0].id1 == "VEH001" && risks[0].id2 == "VEH002") || + (risks[0].id1 == "VEH002" && risks[0].id2 == "VEH001")); + EXPECT_EQ(risks[0].distance, 20.0); + EXPECT_EQ(risks[0].level, RiskLevel::CRITICAL); // 20米应该是危险级别 + } } // 性能测试:模拟真实机场场景