CollisionAvoidance/tests/CollisionDetectorTest.cpp

387 lines
13 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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秒";
}