387 lines
13 KiB
C++
387 lines
13 KiB
C++
#include <gtest/gtest.h>
|
||
#include "detector/CollisionDetector.h"
|
||
#include "spatial/AirportBounds.h"
|
||
#include "types/BasicTypes.h"
|
||
#include "utils/Logger.h"
|
||
|
||
class CollisionDetectorTest : public ::testing::Test {
|
||
protected:
|
||
void SetUp() override {
|
||
bounds = std::make_unique<AirportBounds>("config/airport_bounds.json");
|
||
detector = std::make_unique<CollisionDetector>(*bounds);
|
||
}
|
||
|
||
// 创建一个标准的航空器对象
|
||
Aircraft createAircraft(const Vector2D& pos) {
|
||
Aircraft aircraft;
|
||
aircraft.id = "CES2501";
|
||
aircraft.flightNo = "CES2501";
|
||
aircraft.position = pos;
|
||
aircraft.speed = 55.0; // 标准速度
|
||
aircraft.heading = 90.0; // 向东
|
||
return aircraft;
|
||
}
|
||
|
||
// 创建一个标准的车辆对象
|
||
Vehicle createVehicle(const Vector2D& pos, const std::string& id = "VEH001") {
|
||
Vehicle vehicle;
|
||
vehicle.id = id;
|
||
vehicle.vehicleNo = id; // 使用相同的 ID 作为车牌号
|
||
vehicle.position = pos;
|
||
vehicle.speed = 22.0; // 标准速度
|
||
vehicle.heading = 0.0; // 向北
|
||
return vehicle;
|
||
}
|
||
|
||
std::unique_ptr<AirportBounds> bounds;
|
||
std::unique_ptr<CollisionDetector> detector;
|
||
};
|
||
|
||
// 测试跑道上的碰撞检测
|
||
TEST_F(CollisionDetectorTest, RunwayCollisionDetection) {
|
||
Vector2D runwayPos(2500, 1530); // 跑道中心点
|
||
|
||
std::vector<Aircraft> aircraft = {createAircraft(runwayPos)};
|
||
std::vector<Vehicle> vehicles = {
|
||
createVehicle(Vector2D(2580, 1530)) // 距离80米,小于跑道区域的100米阈值
|
||
};
|
||
|
||
detector->updateTraffic(aircraft, vehicles);
|
||
auto risks = detector->detectCollisions();
|
||
EXPECT_FALSE(risks.empty());
|
||
|
||
if (!risks.empty()) {
|
||
const auto& risk = risks[0];
|
||
EXPECT_EQ(risk.id1, "CES2501");
|
||
EXPECT_EQ(risk.id2, "VEH001");
|
||
EXPECT_EQ(risk.level, RiskLevel::LOW);
|
||
EXPECT_NEAR(risk.distance, 80.0, 0.1);
|
||
}
|
||
}
|
||
|
||
// 测试滑行道上的碰撞检测
|
||
TEST_F(CollisionDetectorTest, TaxiwayCollisionDetection) {
|
||
Vector2D taxiwayPos(2500, 1000); // 滑行道上的位置
|
||
|
||
std::vector<Aircraft> aircraft = {createAircraft(taxiwayPos)};
|
||
std::vector<Vehicle> vehicles = {
|
||
createVehicle(Vector2D(2540, 1000)) // 距离40米,小于滑行道区域的50米阈值
|
||
};
|
||
|
||
detector->updateTraffic(aircraft, vehicles);
|
||
auto risks = detector->detectCollisions();
|
||
EXPECT_FALSE(risks.empty());
|
||
|
||
if (!risks.empty()) {
|
||
const auto& risk = risks[0];
|
||
EXPECT_EQ(risk.id1, "CES2501");
|
||
EXPECT_EQ(risk.id2, "VEH001");
|
||
EXPECT_EQ(risk.level, RiskLevel::LOW);
|
||
EXPECT_NEAR(risk.distance, 40.0, 0.1);
|
||
}
|
||
}
|
||
|
||
// 测试停机位的碰撞检测
|
||
TEST_F(CollisionDetectorTest, GateCollisionDetection) {
|
||
Vector2D gatePos(2500, 2500); // 停机位区域
|
||
|
||
std::vector<Aircraft> aircraft = {createAircraft(gatePos)};
|
||
std::vector<Vehicle> vehicles = {
|
||
createVehicle(Vector2D(2535, 2500)) // 距离35米,小于停机位区域的40米阈值
|
||
};
|
||
|
||
detector->updateTraffic(aircraft, vehicles);
|
||
auto risks = detector->detectCollisions();
|
||
EXPECT_FALSE(risks.empty());
|
||
|
||
if (!risks.empty()) {
|
||
const auto& risk = risks[0];
|
||
EXPECT_EQ(risk.id1, "CES2501");
|
||
EXPECT_EQ(risk.id2, "VEH001");
|
||
EXPECT_EQ(risk.level, RiskLevel::LOW);
|
||
EXPECT_NEAR(risk.distance, 35.0, 0.1);
|
||
}
|
||
}
|
||
|
||
// 测试服务区的碰撞检测
|
||
TEST_F(CollisionDetectorTest, ServiceAreaCollisionDetection) {
|
||
Vector2D servicePos(2500, 3500); // 服务区域
|
||
|
||
std::vector<Aircraft> aircraft = {createAircraft(servicePos)};
|
||
std::vector<Vehicle> vehicles = {
|
||
createVehicle(Vector2D(2525, 3500)) // 距离25米,小于服务区域的30米阈值
|
||
};
|
||
|
||
detector->updateTraffic(aircraft, vehicles);
|
||
auto risks = detector->detectCollisions();
|
||
EXPECT_FALSE(risks.empty());
|
||
|
||
if (!risks.empty()) {
|
||
const auto& risk = risks[0];
|
||
EXPECT_EQ(risk.id1, "CES2501");
|
||
EXPECT_EQ(risk.id2, "VEH001");
|
||
EXPECT_EQ(risk.level, RiskLevel::LOW);
|
||
EXPECT_NEAR(risk.distance, 25.0, 0.1);
|
||
}
|
||
}
|
||
|
||
// 测试车辆之间的碰撞
|
||
TEST_F(CollisionDetectorTest, VehicleToVehicleCollision) {
|
||
Vector2D servicePos(2500, 3500); // 在服务区域内
|
||
|
||
std::vector<Aircraft> aircraft; // 空的航空器列表
|
||
std::vector<Vehicle> vehicles = {
|
||
createVehicle(servicePos, "VEH001"),
|
||
createVehicle(Vector2D(2510, 3500), "VEH002") // 距离10米,小于服务区域的15米车辆碰撞阈值
|
||
};
|
||
|
||
detector->updateTraffic(aircraft, vehicles);
|
||
auto risks = detector->detectCollisions();
|
||
EXPECT_FALSE(risks.empty());
|
||
|
||
if (!risks.empty()) {
|
||
const auto& risk = risks[0];
|
||
EXPECT_EQ(risk.id1, "VEH001");
|
||
EXPECT_EQ(risk.id2, "VEH002");
|
||
EXPECT_EQ(risk.level, RiskLevel::MEDIUM);
|
||
EXPECT_NEAR(risk.distance, 10.0, 0.1);
|
||
}
|
||
}
|
||
|
||
// 测试安全距离外的情况
|
||
TEST_F(CollisionDetectorTest, NoCollisionWhenFarApart) {
|
||
Vector2D runwayPos(2500, 1530); // 跑道位置
|
||
|
||
std::vector<Aircraft> aircraft = {createAircraft(runwayPos)};
|
||
std::vector<Vehicle> vehicles = {
|
||
createVehicle(Vector2D(2650, 1530)) // 距离150米,大于任何区域的阈值
|
||
};
|
||
|
||
detector->updateTraffic(aircraft, vehicles);
|
||
auto risks = detector->detectCollisions();
|
||
EXPECT_TRUE(risks.empty());
|
||
}
|
||
|
||
// 生成随机位置,根据区域类型调整分布
|
||
Vector2D generateRandomPosition(AreaType areaType = AreaType::SERVICE) {
|
||
double x, y;
|
||
|
||
switch (areaType) {
|
||
case AreaType::RUNWAY:
|
||
// 跑道区域 (2000-5600, 1500-1560) - 3600m × 60m
|
||
x = 2000.0 + (std::rand() % 3600);
|
||
y = 1500.0 + (std::rand() % 60);
|
||
break;
|
||
|
||
case AreaType::TAXIWAY:
|
||
// 滑行道区域 (2000-5600, 900-960) - 3600m × 60m
|
||
x = 2000.0 + (std::rand() % 3600);
|
||
y = 900.0 + (std::rand() % 60);
|
||
break;
|
||
|
||
case AreaType::GATE:
|
||
// 停机坪区域 (2000-3500, 2000-3000) - 1500m × 1000m
|
||
x = 2000.0 + (std::rand() % 1500);
|
||
y = 2000.0 + (std::rand() % 1000);
|
||
break;
|
||
|
||
case AreaType::SERVICE:
|
||
default:
|
||
// 服务区域 (2000-4000, 3000-4000) - 2000m × 1000m
|
||
x = 2000.0 + (std::rand() % 2000);
|
||
y = 3000.0 + (std::rand() % 1000);
|
||
break;
|
||
}
|
||
|
||
return {x, y};
|
||
}
|
||
|
||
// 生成随机航向角
|
||
double generateRandomHeading() {
|
||
return std::rand() % 360; // 0-359度
|
||
}
|
||
|
||
// 生成随机速度
|
||
double generateRandomSpeed(bool isAircraft) {
|
||
if (isAircraft) {
|
||
return 40.0 + (std::rand() % 31); // 40-70 m/s
|
||
} else {
|
||
return 5.0 + (std::rand() % 36); // 5-40 m/s
|
||
}
|
||
}
|
||
|
||
// 大规模碰撞检测性能测试
|
||
TEST_F(CollisionDetectorTest, LargeScaleCollisionDetection) {
|
||
std::srand(std::time(nullptr)); // 初始化随机数生成器
|
||
|
||
// 生成150架航空器
|
||
std::vector<Aircraft> aircraft;
|
||
|
||
// 在跑道和滑行道分别安排5架航空器
|
||
for (int i = 0; i < 5; ++i) {
|
||
Aircraft a;
|
||
a.id = "FL_RW" + std::to_string(i + 1);
|
||
a.flightNo = a.id;
|
||
a.position = generateRandomPosition(AreaType::RUNWAY);
|
||
a.speed = generateRandomSpeed(true);
|
||
a.heading = generateRandomHeading();
|
||
aircraft.push_back(a);
|
||
|
||
Aircraft b;
|
||
b.id = "FL_TW" + std::to_string(i + 1);
|
||
b.flightNo = b.id;
|
||
b.position = generateRandomPosition(AreaType::TAXIWAY);
|
||
b.speed = generateRandomSpeed(true);
|
||
b.heading = generateRandomHeading();
|
||
aircraft.push_back(b);
|
||
}
|
||
|
||
// 在停机坪安排100架航空器(对应184个停机位的实际使用率)
|
||
for (int i = 0; i < 100; ++i) {
|
||
Aircraft a;
|
||
a.id = "FL_GT" + std::to_string(i + 1);
|
||
a.flightNo = a.id;
|
||
a.position = generateRandomPosition(AreaType::GATE);
|
||
a.speed = generateRandomSpeed(true);
|
||
a.heading = generateRandomHeading();
|
||
aircraft.push_back(a);
|
||
}
|
||
|
||
// 在服务区安排40架航空器
|
||
for (int i = 0; i < 40; ++i) {
|
||
Aircraft a;
|
||
a.id = "FL_SV" + std::to_string(i + 1);
|
||
a.flightNo = a.id;
|
||
a.position = generateRandomPosition(AreaType::SERVICE);
|
||
a.speed = generateRandomSpeed(true);
|
||
a.heading = generateRandomHeading();
|
||
aircraft.push_back(a);
|
||
}
|
||
|
||
// 生成300辆车,主要在停机坪和服务区分配
|
||
std::vector<Vehicle> vehicles;
|
||
|
||
// 停机坪180辆车(每个停机位约1辆服务车)
|
||
for (int i = 0; i < 180; ++i) {
|
||
Vehicle v;
|
||
v.id = "VH_GT" + std::to_string(i + 1);
|
||
v.vehicleNo = v.id;
|
||
v.position = generateRandomPosition(AreaType::GATE);
|
||
v.speed = generateRandomSpeed(false);
|
||
v.heading = generateRandomHeading();
|
||
vehicles.push_back(v);
|
||
}
|
||
|
||
// 服务区120辆车
|
||
for (int i = 0; i < 120; ++i) {
|
||
Vehicle v;
|
||
v.id = "VH_SV" + std::to_string(i + 1);
|
||
v.vehicleNo = v.id;
|
||
v.position = generateRandomPosition(AreaType::SERVICE);
|
||
v.speed = generateRandomSpeed(false);
|
||
v.heading = generateRandomHeading();
|
||
vehicles.push_back(v);
|
||
}
|
||
|
||
// 记录开始时间
|
||
auto start = std::chrono::high_resolution_clock::now();
|
||
|
||
// 更新交通数据
|
||
detector->updateTraffic(aircraft, vehicles);
|
||
|
||
// 执行碰撞检测
|
||
auto risks = detector->detectCollisions();
|
||
|
||
// 记录结束时间
|
||
auto end = std::chrono::high_resolution_clock::now();
|
||
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
|
||
|
||
// 统计各区域和风险等级的碰撞数量
|
||
int runwayCollisions = 0;
|
||
int taxiwayCollisions = 0;
|
||
int gateCollisions = 0;
|
||
int serviceCollisions = 0;
|
||
|
||
int criticalRisks = 0;
|
||
int highRisks = 0;
|
||
int mediumRisks = 0;
|
||
int lowRisks = 0;
|
||
|
||
for (const auto& risk : risks) {
|
||
// 统计区域分布
|
||
if (risk.id1.find("RW") != std::string::npos || risk.id2.find("RW") != std::string::npos) {
|
||
runwayCollisions++;
|
||
} else if (risk.id1.find("TW") != std::string::npos || risk.id2.find("TW") != std::string::npos) {
|
||
taxiwayCollisions++;
|
||
} else if (risk.id1.find("GT") != std::string::npos || risk.id2.find("GT") != std::string::npos) {
|
||
gateCollisions++;
|
||
} else {
|
||
serviceCollisions++;
|
||
}
|
||
|
||
// 统计风险等级
|
||
switch (risk.level) {
|
||
case RiskLevel::CRITICAL: criticalRisks++; break;
|
||
case RiskLevel::HIGH: highRisks++; break;
|
||
case RiskLevel::MEDIUM: mediumRisks++; break;
|
||
case RiskLevel::LOW: lowRisks++; break;
|
||
}
|
||
}
|
||
|
||
// 输出性能统计
|
||
Logger::info("大规模碰撞检测性能测试:");
|
||
Logger::info(" - 航空器数量: ", aircraft.size());
|
||
Logger::info(" - 车辆数量: ", vehicles.size());
|
||
Logger::info(" - 检测到的碰撞数: ", risks.size());
|
||
Logger::info(" - 区域分布:");
|
||
Logger::info(" * 跑道区域: ", runwayCollisions);
|
||
Logger::info(" * 滑行道区域: ", taxiwayCollisions);
|
||
Logger::info(" * 停机位区域: ", gateCollisions);
|
||
Logger::info(" * 服务区域: ", serviceCollisions);
|
||
Logger::info(" - 风险等级分布:");
|
||
Logger::info(" * 严重风险: ", criticalRisks);
|
||
Logger::info(" * 高风险: ", highRisks);
|
||
Logger::info(" * 中等风险: ", mediumRisks);
|
||
Logger::info(" * 低风险: ", lowRisks);
|
||
Logger::info(" - 处理时间: ", duration.count(), " 微秒");
|
||
|
||
// 验证结果
|
||
for (const auto& risk : risks) {
|
||
// 验证碰撞对是否有效
|
||
bool validCollision = false;
|
||
|
||
// 检查是否为航空器与车辆的碰撞
|
||
for (const auto& a : aircraft) {
|
||
for (const auto& v : vehicles) {
|
||
if ((risk.id1 == a.flightNo && risk.id2 == v.vehicleNo) ||
|
||
(risk.id1 == v.vehicleNo && risk.id2 == a.flightNo)) {
|
||
validCollision = true;
|
||
break;
|
||
}
|
||
}
|
||
if (validCollision) break;
|
||
}
|
||
|
||
// 检查是否为车辆间的碰撞
|
||
if (!validCollision) {
|
||
for (const auto& v1 : vehicles) {
|
||
for (const auto& v2 : vehicles) {
|
||
if (v1.id != v2.id &&
|
||
((risk.id1 == v1.vehicleNo && risk.id2 == v2.vehicleNo) ||
|
||
(risk.id1 == v2.vehicleNo && risk.id2 == v1.vehicleNo))) {
|
||
validCollision = true;
|
||
break;
|
||
}
|
||
}
|
||
if (validCollision) break;
|
||
}
|
||
}
|
||
|
||
EXPECT_TRUE(validCollision) << "无效的碰撞对: " << risk.id1 << " - " << risk.id2;
|
||
EXPECT_GE(risk.distance, 0.0) << "距离不能为负值";
|
||
EXPECT_GE(risk.relativeSpeed, 0.0) << "相对速度不能为负值";
|
||
}
|
||
|
||
// 性能要求:处理时间应在合理范围内
|
||
EXPECT_LT(duration.count(), 1000000) << "碰撞检测时间超过1秒";
|
||
}
|