358 lines
12 KiB
C++
358 lines
12 KiB
C++
#include "detector/CollisionDetector.h"
|
||
#include "vehicle/ControllableVehicles.h"
|
||
#include "spatial/AirportBounds.h"
|
||
#include <gtest/gtest.h>
|
||
#include <gmock/gmock.h>
|
||
#include "utils/Logger.h"
|
||
#include <chrono>
|
||
|
||
// Mock ControllableVehicles 类
|
||
class MockControllableVehicles : public ControllableVehicles {
|
||
public:
|
||
MockControllableVehicles() : ControllableVehicles("") {} // 使用空字符串,避免加载实际配置
|
||
MOCK_METHOD(bool, isControllable, (const std::string& vehicleNo), (const));
|
||
};
|
||
|
||
// Mock AirportBounds 类
|
||
class MockAirportBounds : public AirportBounds {
|
||
public:
|
||
MockAirportBounds() : AirportBounds("") {
|
||
// 设置更大的测试边界,以包含所有测试数据
|
||
airportBounds_ = Bounds(0, 0, 4000, 2000); // 4000x2000 的测试区域
|
||
Logger::info("MockAirportBounds initialized with bounds: ",
|
||
"x=", airportBounds_.x, ", y=", airportBounds_.y,
|
||
", width=", airportBounds_.width, ", height=", airportBounds_.height);
|
||
}
|
||
|
||
// 覆盖原有方法,返回测试用的配置
|
||
AreaType getAreaType(const Vector2D& position) const override {
|
||
return AreaType::RUNWAY; // 简化测试,总是返回跑道区域
|
||
}
|
||
|
||
const AreaConfig& getAreaConfig(AreaType type) const override {
|
||
static const AreaConfig config{50.0, 100.0, 15.0};
|
||
return config;
|
||
}
|
||
|
||
const Bounds& getAirportBounds() const override {
|
||
return airportBounds_;
|
||
}
|
||
};
|
||
|
||
class CollisionDetectorTest : public ::testing::Test {
|
||
protected:
|
||
void SetUp() override {
|
||
// 创建 Mock 对象
|
||
airportBounds_ = std::make_unique<MockAirportBounds>();
|
||
mockControllableVehicles_ = std::make_unique<MockControllableVehicles>();
|
||
|
||
// 创建碰撞检测器
|
||
detector_ = std::make_unique<CollisionDetector>(*airportBounds_, *mockControllableVehicles_);
|
||
}
|
||
|
||
std::unique_ptr<MockAirportBounds> airportBounds_;
|
||
std::unique_ptr<MockControllableVehicles> mockControllableVehicles_;
|
||
std::unique_ptr<CollisionDetector> detector_;
|
||
};
|
||
|
||
// 测试可控车辆与航空器的碰撞检测
|
||
TEST_F(CollisionDetectorTest, DetectControllableVehicleAircraftCollision) {
|
||
// 设置 Mock 期望 - 在创建数据之前设置
|
||
EXPECT_CALL(*mockControllableVehicles_, isControllable("VEH001"))
|
||
.WillRepeatedly(testing::Return(true));
|
||
Logger::info("Set mock expectation: VEH001 is controllable");
|
||
|
||
// 设置测试数据
|
||
Aircraft aircraft;
|
||
aircraft.flightNo = "TEST001";
|
||
aircraft.position = {100, 100};
|
||
aircraft.speed = 10;
|
||
aircraft.heading = 90;
|
||
Logger::info("Created aircraft: flightNo=", aircraft.flightNo,
|
||
", position=(", aircraft.position.x, ", ", aircraft.position.y, ")");
|
||
|
||
Vehicle vehicle;
|
||
vehicle.vehicleNo = "VEH001";
|
||
vehicle.position = {120, 100}; // 距离航空器20米
|
||
vehicle.speed = 5;
|
||
vehicle.heading = 270;
|
||
Logger::info("Created vehicle: vehicleNo=", vehicle.vehicleNo,
|
||
", position=(", vehicle.position.x, ", ", vehicle.position.y, ")");
|
||
|
||
// 更新交通数据
|
||
detector_->updateTraffic({aircraft}, {vehicle});
|
||
Logger::info("Updated traffic data");
|
||
|
||
// 执行碰撞检测
|
||
auto risks = detector_->detectCollisions();
|
||
Logger::info("Collision detection completed, found ", risks.size(), " risks");
|
||
|
||
// 验证结果
|
||
ASSERT_EQ(risks.size(), 1); // 应该检测到一个碰撞风险
|
||
if (!risks.empty()) {
|
||
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::EMERGENCY); // 20米距离应该是严重风险
|
||
}
|
||
}
|
||
|
||
// 测试可控车辆与其他车辆的碰撞检测
|
||
TEST_F(CollisionDetectorTest, DetectControllableVehicleOtherVehicleCollision) {
|
||
// 设置 Mock 期望
|
||
EXPECT_CALL(*mockControllableVehicles_, isControllable("VEH001"))
|
||
.WillRepeatedly(testing::Return(true));
|
||
EXPECT_CALL(*mockControllableVehicles_, isControllable("VEH002"))
|
||
.WillRepeatedly(testing::Return(false));
|
||
|
||
// 设置测试数据
|
||
Vehicle controlVehicle;
|
||
controlVehicle.vehicleNo = "VEH001";
|
||
controlVehicle.position = {100, 100};
|
||
controlVehicle.speed = 5;
|
||
controlVehicle.heading = 90;
|
||
|
||
Vehicle otherVehicle;
|
||
otherVehicle.vehicleNo = "VEH002";
|
||
otherVehicle.position = {120, 100}; // 距离可控车辆20米
|
||
otherVehicle.speed = 5;
|
||
otherVehicle.heading = 270;
|
||
|
||
// 更新交通数据
|
||
detector_->updateTraffic({}, {controlVehicle, otherVehicle});
|
||
|
||
// 执行碰撞检测
|
||
auto risks = detector_->detectCollisions();
|
||
|
||
// 验证结果
|
||
ASSERT_EQ(risks.size(), 1); // 应该检测到一个碰撞风险
|
||
if (!risks.empty()) {
|
||
EXPECT_EQ(risks[0].id1, "VEH001"); // 可控车辆ID
|
||
EXPECT_EQ(risks[0].id2, "VEH002"); // 其他车辆ID
|
||
EXPECT_EQ(risks[0].distance, 20); // 距离应该是20米
|
||
EXPECT_EQ(risks[0].level, RiskLevel::CRITICAL); // 20米距离应该是严重风险
|
||
}
|
||
}
|
||
|
||
// 测试非可控车辆的碰撞检测(不应该产生碰撞风险)
|
||
TEST_F(CollisionDetectorTest, NonControllableVehicleCollision) {
|
||
// 设置测试数据
|
||
Vehicle vehicle1;
|
||
vehicle1.vehicleNo = "VEH001";
|
||
vehicle1.position = {100, 100};
|
||
vehicle1.speed = 5;
|
||
vehicle1.heading = 90;
|
||
|
||
Vehicle vehicle2;
|
||
vehicle2.vehicleNo = "VEH002";
|
||
vehicle2.position = {120, 100}; // 距离20米
|
||
vehicle2.speed = 5;
|
||
vehicle2.heading = 270;
|
||
|
||
// 设置 Mock 期望
|
||
EXPECT_CALL(*mockControllableVehicles_, isControllable(testing::_))
|
||
.WillRepeatedly(testing::Return(false));
|
||
|
||
// 更新交通数据
|
||
detector_->updateTraffic({}, {vehicle1, vehicle2});
|
||
|
||
// 执行碰撞检测
|
||
auto risks = detector_->detectCollisions();
|
||
|
||
// 验证结果
|
||
EXPECT_EQ(risks.size(), 0); // 非可控车辆之间的碰撞不应该被检测
|
||
}
|
||
|
||
// 测试多个可控车辆之间的碰撞检测
|
||
TEST_F(CollisionDetectorTest, MultipleControllableVehiclesCollision) {
|
||
// 设置 Mock 期望 - 所有车辆都是可控的
|
||
ON_CALL(*mockControllableVehicles_, isControllable(testing::_))
|
||
.WillByDefault(testing::Return(true));
|
||
EXPECT_CALL(*mockControllableVehicles_, isControllable(testing::_))
|
||
.Times(testing::AtLeast(3)); // 至少调用3次,因为有3辆车
|
||
Logger::info("Set mock expectation: all vehicles are controllable");
|
||
|
||
// 设置测试数据
|
||
std::vector<Vehicle> vehicles;
|
||
|
||
// 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);
|
||
|
||
// 执行碰撞检测
|
||
auto risks = detector_->detectCollisions();
|
||
|
||
// 验证结果
|
||
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米应该是危险级别
|
||
}
|
||
}
|
||
|
||
// 性能测试:模拟真实机场场景
|
||
TEST_F(CollisionDetectorTest, PerformanceTest) {
|
||
// 设置 Mock 期望 - 默认车辆不可控
|
||
EXPECT_CALL(*mockControllableVehicles_, isControllable(testing::_))
|
||
.WillRepeatedly(testing::Return(false));
|
||
|
||
// 设置3辆可控车辆
|
||
std::vector<std::string> controlVehicleNos = {
|
||
"VEH001", // 滑行道上的可控车辆
|
||
"VEH002", // 停机位的可控车辆
|
||
"VEH003" // 服务区的可控车辆
|
||
};
|
||
|
||
for (const auto& vehicleNo : controlVehicleNos) {
|
||
EXPECT_CALL(*mockControllableVehicles_, isControllable(vehicleNo))
|
||
.WillRepeatedly(testing::Return(true));
|
||
}
|
||
Logger::info("Set mock expectations for controllable vehicles");
|
||
|
||
// 创建测试数据
|
||
std::vector<Aircraft> aircraft;
|
||
std::vector<Vehicle> vehicles;
|
||
|
||
// 跑道区域:5架航空器
|
||
for (int i = 0; i < 5; ++i) {
|
||
Aircraft a;
|
||
a.flightNo = "RW" + std::to_string(i + 1);
|
||
a.position = {1800.0 + i * 500, 30.0}; // 跑道上等间距分布
|
||
a.speed = 30; // 较快速度
|
||
a.heading = 90;
|
||
aircraft.push_back(a);
|
||
}
|
||
|
||
// 滑行道区域:5架航空器
|
||
for (int i = 0; i < 5; ++i) {
|
||
Aircraft a;
|
||
a.flightNo = "TW" + std::to_string(i + 1);
|
||
a.position = {1800.0 + i * 500, 90.0}; // 滑行道上等间距分布
|
||
a.speed = 10; // 中等速度
|
||
a.heading = 90;
|
||
aircraft.push_back(a);
|
||
}
|
||
|
||
// 停机位区域:100架航空器,180辆车辆
|
||
for (int i = 0; i < 100; ++i) {
|
||
Aircraft a;
|
||
a.flightNo = "GT" + std::to_string(i + 1);
|
||
a.position = {
|
||
750.0 + (i % 10) * 150, // 10列
|
||
500.0 + (i / 10) * 100 // 10行
|
||
};
|
||
a.speed = 0; // 静止
|
||
a.heading = 180;
|
||
aircraft.push_back(a);
|
||
}
|
||
|
||
for (int i = 0; i < 180; ++i) {
|
||
Vehicle v;
|
||
v.vehicleNo = "GV" + std::to_string(i + 1);
|
||
v.position = {
|
||
750.0 + (i % 12) * 125, // 12列
|
||
500.0 + (i / 12) * 83 // 15行
|
||
};
|
||
v.speed = 5; // 低速
|
||
v.heading = (i % 4) * 90; // 4个方向
|
||
vehicles.push_back(v);
|
||
}
|
||
|
||
// 服务区:40架航空器,120辆车辆
|
||
for (int i = 0; i < 40; ++i) {
|
||
Aircraft a;
|
||
a.flightNo = "SA" + std::to_string(i + 1);
|
||
a.position = {
|
||
1000.0 + (i % 8) * 250, // 8列
|
||
500.0 + (i / 8) * 200 // 5行
|
||
};
|
||
a.speed = 0; // 静止
|
||
a.heading = 180;
|
||
aircraft.push_back(a);
|
||
}
|
||
|
||
for (int i = 0; i < 120; ++i) {
|
||
Vehicle v;
|
||
v.vehicleNo = "SV" + std::to_string(i + 1);
|
||
v.position = {
|
||
1000.0 + (i % 10) * 200, // 10列
|
||
500.0 + (i / 10) * 100 // 12行
|
||
};
|
||
v.speed = 8; // 中等速度
|
||
v.heading = (i % 8) * 45; // 8个方向
|
||
vehicles.push_back(v);
|
||
}
|
||
|
||
// 添加3辆可控车辆
|
||
// 1. 滑行道上的可控车辆
|
||
Vehicle taxiwayVehicle;
|
||
taxiwayVehicle.vehicleNo = "VEH001";
|
||
taxiwayVehicle.position = {1800.0, 90.0}; // 在滑行道上
|
||
taxiwayVehicle.speed = 10;
|
||
taxiwayVehicle.heading = 90;
|
||
vehicles.push_back(taxiwayVehicle);
|
||
|
||
// 2. 停机位的可控车辆
|
||
Vehicle gateVehicle;
|
||
gateVehicle.vehicleNo = "VEH002";
|
||
gateVehicle.position = {750.0, 500.0}; // 在停机位区域
|
||
gateVehicle.speed = 5;
|
||
gateVehicle.heading = 180;
|
||
vehicles.push_back(gateVehicle);
|
||
|
||
// 3. 服务区的可控车辆
|
||
Vehicle serviceVehicle;
|
||
serviceVehicle.vehicleNo = "VEH003";
|
||
serviceVehicle.position = {1000.0, 500.0}; // 在服务区
|
||
serviceVehicle.speed = 8;
|
||
serviceVehicle.heading = 270;
|
||
vehicles.push_back(serviceVehicle);
|
||
|
||
// 更新交通数据
|
||
detector_->updateTraffic(aircraft, vehicles);
|
||
Logger::info("Updated traffic data with ", aircraft.size(), " aircraft and ",
|
||
vehicles.size(), " vehicles (including 3 controllable vehicles)");
|
||
|
||
// 执行碰撞检测并记录时间
|
||
auto start = std::chrono::high_resolution_clock::now();
|
||
|
||
auto risks = detector_->detectCollisions();
|
||
|
||
auto end = std::chrono::high_resolution_clock::now();
|
||
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
|
||
Logger::info("Collision detection completed in ", duration.count(), " microseconds");
|
||
Logger::info("Found ", risks.size(), " risks");
|
||
|
||
// 验证结果
|
||
ASSERT_GT(risks.size(), 0); // 应该检测到一些碰撞风险
|
||
|
||
// 验证性能要求
|
||
EXPECT_LT(duration.count(), 100000); // 期望处理时间小于100ms
|
||
}
|