#include "detector/CollisionDetector.h" #include "vehicle/ControllableVehicles.h" #include "spatial/AirportBounds.h" #include #include #include "utils/Logger.h" #include // 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(); mockControllableVehicles_ = std::make_unique(); // 创建冲突检测器 detector_ = std::make_unique(*airportBounds_, *mockControllableVehicles_); } std::unique_ptr airportBounds_; std::unique_ptr mockControllableVehicles_; std::unique_ptr 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(); // 验证结果 ASSERT_EQ(risks.size(), 1); // 应该检测到一个冲突风险 if (!risks.empty()) { const auto& risk = risks[0]; EXPECT_EQ(risk.id1, "TEST001"); // 航空器ID EXPECT_EQ(risk.id2, "VEH001"); // 车辆ID EXPECT_EQ(risk.distance, 20); // 距离应该是20米 EXPECT_EQ(risk.level, RiskLevel::CRITICAL); // 20米距离应该是严重风险 EXPECT_GT(risk.relativeSpeed, 0); // 相对速度应该大于0 } } // 测试可控车辆与其他车辆的冲突检测 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 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 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; std::vector 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(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 } // 测试轨迹预测的准确性 TEST_F(CollisionDetectorTest, TrajectoryPredictionAccuracy) { // 设置 Mock 期望 EXPECT_CALL(*mockControllableVehicles_, isControllable(testing::_)) .WillRepeatedly(testing::Return(true)); // 测试场景1:正面相遇碰撞 { Vector2D pos1{100, 100}; // 第一个物体的位置 double speed1 = 10; // 第一个物体的速度 (m/s) double heading1 = 90; // 第一个物体的航向(正东,90度) Vector2D pos2{300, 100}; // 第二个物体的位置 double speed2 = 10; // 第二个物体的速度 (m/s) double heading2 = 270; // 第二个物体的航向(正西,270度) double size1 = 5; // 第一个物体的尺寸 double size2 = 5; // 第二个物体的尺寸 double timeWindow = 30; // 预测时间窗口 auto prediction = detector_->predictTrajectoryCollision( pos1, speed1, heading1, pos2, speed2, heading2, size1, size2, timeWindow ); // 验证结果:首先验证是否检测到碰撞 EXPECT_TRUE(prediction.willCollide) << "应该检测到碰撞"; if (prediction.willCollide) { // 验证碰撞点位置(允许1米的误差) EXPECT_NEAR(prediction.collisionPoint.x, 200.0, 1.0) << "碰撞点x坐标应该在中点附近"; EXPECT_NEAR(prediction.collisionPoint.y, 100.0, 1.0) << "碰撞点y坐标应该保持不变"; } } // 测试场景2:平行路径,不会碰撞 { Vector2D pos1{100, 100}; double speed1 = 10; double heading1 = 90; // 正东(90度) Vector2D pos2{100, 120}; // 平行路径,距20米 double speed2 = 10; double heading2 = 90; // 正东(90度) double size1 = 5; double size2 = 5; double timeWindow = 30; auto prediction = detector_->predictTrajectoryCollision( pos1, speed1, heading1, pos2, speed2, heading2, size1, size2, timeWindow ); // 验证结果:不应该检测到碰撞 EXPECT_FALSE(prediction.willCollide) << "平行路径不应该碰撞"; // 验证最小距离(允许1米的误差) EXPECT_NEAR(prediction.minDistance, 20.0, 1.0) << "平行路径应该保持20米的距离"; } // 测试场景3:垂直相交路径 { Vector2D pos1{0, 100}; // 第一个物体从左开始 double speed1 = 10; double heading1 = 90; // 正东(90度) Vector2D pos2{200, 300}; // 第二个物体从上开始 double speed2 = 10; double heading2 = 180; // 正南(180度) double size1 = 5; double size2 = 5; double timeWindow = 30; // 30秒的预测窗口 Logger::info("垂直路径测试参数:"); Logger::info(" 物体1: 位置=(" + std::to_string(pos1.x) + ", " + std::to_string(pos1.y) + "), 速度=" + std::to_string(speed1) + ", 航向=" + std::to_string(heading1)); Logger::info(" 物体2: 位置=(" + std::to_string(pos2.x) + ", " + std::to_string(pos2.y) + "), 速度=" + std::to_string(speed2) + ", 航向=" + std::to_string(heading2)); // 计算速度分量用于调试 double heading1Rad = heading1 * M_PI / 180.0; double heading2Rad = heading2 * M_PI / 180.0; double v1x = speed1 * std::sin(heading1Rad); // 东向为x轴正方向 double v1y = speed1 * std::cos(heading1Rad); // 北向为y轴正方向 double v2x = speed2 * std::sin(heading2Rad); double v2y = speed2 * std::cos(heading2Rad); Logger::info("速度分量:"); Logger::info(" 物体1: vx=" + std::to_string(v1x) + ", vy=" + std::to_string(v1y)); Logger::info(" 物体2: vx=" + std::to_string(v2x) + ", vy=" + std::to_string(v2y)); auto prediction = detector_->predictTrajectoryCollision( pos1, speed1, heading1, pos2, speed2, heading2, size1, size2, timeWindow ); Logger::info("预测结果:"); Logger::info(" willCollide=" + std::to_string(prediction.willCollide)); Logger::info(" minDistance=" + std::to_string(prediction.minDistance)); if (prediction.willCollide) { Logger::info(" 碰撞点=(" + std::to_string(prediction.collisionPoint.x) + ", " + std::to_string(prediction.collisionPoint.y) + ")"); Logger::info(" 碰撞时间=" + std::to_string(prediction.timeToCollision)); // 计算理论碰撞点 // 物体1:x = 0 + 10t, y = 100 // 物体2:x = 200, y = 300 - 10t // 碰撞时:x1 = x2 = 200, y1 = y2 double collisionTime = 20.0; // t = 200/10 = 20秒 double expectedX = 200.0; // x = 0 + 10*20 = 200 double expectedY = 100.0; // y = 100 (物体1的y保持不变) // 验证碰撞点位置(允许5米的误差,考虑到物体尺寸) EXPECT_NEAR(prediction.collisionPoint.x, expectedX, 5.0) << "碰撞点x坐标应该在交叉点附近"; EXPECT_NEAR(prediction.collisionPoint.y, expectedY, 5.0) << "碰撞点y坐标应该在交叉点附近"; // 验证碰撞时间(允许1秒的误差) EXPECT_NEAR(prediction.timeToCollision, collisionTime, 1.0) << "碰撞时间应该接近20秒"; } } // 测试场景4:静止物体 { Vector2D pos1{0, 100}; // 第一个物体从远处开始 double speed1 = 10; double heading1 = 90; // 正东(90度) Vector2D pos2{200, 100}; // 静止物体在目标位置 double speed2 = 0; // 静止物体 double heading2 = 0; // 航向无关紧要,因为是静止的 double size1 = 5; double size2 = 5; double timeWindow = 30; // 30秒的预测窗口 Logger::info("静止物体测试参数:"); Logger::info(" 物体1: 位置=(" + std::to_string(pos1.x) + ", " + std::to_string(pos1.y) + "), 速度=" + std::to_string(speed1) + ", 航向=" + std::to_string(heading1)); Logger::info(" 物体2: 位置=(" + std::to_string(pos2.x) + ", " + std::to_string(pos2.y) + "), 速度=" + std::to_string(speed2) + ", 航向=" + std::to_string(heading2)); // 计算速度分量用于调试 double heading1Rad = heading1 * M_PI / 180.0; double heading2Rad = heading2 * M_PI / 180.0; double v1x = speed1 * std::sin(heading1Rad); // 东向为x轴正方向 double v1y = speed1 * std::cos(heading1Rad); // 北向为y轴正方向 double v2x = speed2 * std::sin(heading2Rad); double v2y = speed2 * std::cos(heading2Rad); Logger::info("速度分量:"); Logger::info(" 物体1: vx=" + std::to_string(v1x) + ", vy=" + std::to_string(v1y)); Logger::info(" 物体2: vx=" + std::to_string(v2x) + ", vy=" + std::to_string(v2y)); auto prediction = detector_->predictTrajectoryCollision( pos1, speed1, heading1, pos2, speed2, heading2, size1, size2, timeWindow ); Logger::info("预测结果:"); Logger::info(" willCollide=" + std::to_string(prediction.willCollide)); Logger::info(" minDistance=" + std::to_string(prediction.minDistance)); if (prediction.willCollide) { Logger::info(" 碰撞点=(" + std::to_string(prediction.collisionPoint.x) + ", " + std::to_string(prediction.collisionPoint.y) + ")"); Logger::info(" 碰撞时间=" + std::to_string(prediction.timeToCollision)); // 计算理论碰撞点 // 考虑物体尺寸:当两个物体中心点距离等于它们尺寸之和时就发生碰撞 double safeDistance = size1 + size2; // 10米 double expectedX = pos2.x - safeDistance; // 200 - 10 = 190米 double expectedY = pos2.y; // 100米 double collisionTime = expectedX / speed1; // 19秒 // 验证碰撞点位置(允许5米的误差,考虑到数值计算的精度) EXPECT_NEAR(prediction.collisionPoint.x, expectedX, 5.0) << "碰撞点应该在考虑物体尺寸后的位置"; EXPECT_NEAR(prediction.collisionPoint.y, expectedY, 5.0) << "碰撞点y坐标应该保持不变"; // 验证碰撞时间(允许1秒的误差) EXPECT_NEAR(prediction.timeToCollision, collisionTime, 1.0) << "碰撞时间应该接近19秒"; } } // 测试场景5:超出时间窗口的碰撞 { Vector2D pos1{100, 100}; double speed1 = 10; double heading1 = 90; // 向东 Vector2D pos2{400, 100}; double speed2 = 0; double heading2 = 0; // 静止物体的航向可以是任意值 double size1 = 5; double size2 = 5; double timeWindow = 20; // 20秒的时间窗口(不足以到达碰撞点) auto prediction = detector_->predictTrajectoryCollision( pos1, speed1, heading1, pos2, speed2, heading2, size1, size2, timeWindow ); // 验证结果:不应该检测到碰撞(因为超出时间窗口) EXPECT_FALSE(prediction.willCollide) << "超出时间窗口应该报告碰撞"; EXPECT_GT(prediction.minDistance, 0) << "最小距离该大于0"; } // 测试场景6:飞机和车辆垂直相交 { // 飞机尺寸:波音737-800,翼展35.8米,长度39.5米 double aircraftSize = 40.0; // 使用较大的值以确保安全 // 车辆尺寸:标准摆渡车,长度12米,宽度2.5米 double vehicleSize = 12.0; // 飞机从西向东,车辆从南向北 Vector2D aircraftPos{0, 200}; // 飞机初始位置 double aircraftSpeed = 12; // 飞机速度 double aircraftHeading = 90; // 向东飞行 Vector2D vehiclePos{200, 100}; // 修改车辆初始位置,使其能与飞机相遇 double vehicleSpeed = 6; // 车辆速度 double vehicleHeading = 0; // 向北行驶 double timeWindow = 60; // 60秒的预测窗口,考虑到较低的速度 Logger::info("飞机和车辆垂直相交测试参数:"); Logger::info(" 飞机: 位置=(" + std::to_string(aircraftPos.x) + ", " + std::to_string(aircraftPos.y) + "), 速度=" + std::to_string(aircraftSpeed) + ", 航向=" + std::to_string(aircraftHeading)); Logger::info(" 车辆: 位置=(" + std::to_string(vehiclePos.x) + ", " + std::to_string(vehiclePos.y) + "), 速度=" + std::to_string(vehicleSpeed) + ", 航向=" + std::to_string(vehicleHeading)); // 计算速度分量 double aircraftHeadingRad = aircraftHeading * M_PI / 180.0; double vehicleHeadingRad = vehicleHeading * M_PI / 180.0; double vax = aircraftSpeed * std::sin(aircraftHeadingRad); // 东向为x轴正方向 double vay = aircraftSpeed * std::cos(aircraftHeadingRad); // 北向为y轴正方向 double vvx = vehicleSpeed * std::sin(vehicleHeadingRad); double vvy = vehicleSpeed * std::cos(vehicleHeadingRad); Logger::info("速度分量:"); Logger::info(" 飞机: vx=" + std::to_string(vax) + ", vy=" + std::to_string(vay)); Logger::info(" 车辆: vx=" + std::to_string(vvx) + ", vy=" + std::to_string(vvy)); // 计算相对运动方程的系数 double dx = aircraftPos.x - vehiclePos.x; double dy = aircraftPos.y - vehiclePos.y; double dvx = vax - vvx; double dvy = vay - vvy; double safeDistance = aircraftSize + vehicleSize; double a = dvx * dvx + dvy * dvy; double b = 2.0 * (dx * dvx + dy * dvy); double c = dx * dx + dy * dy - safeDistance * safeDistance; Logger::info("二次方程系数:"); Logger::info(" 相对位置: dx=" + std::to_string(dx) + ", dy=" + std::to_string(dy)); Logger::info(" 相对速度: dvx=" + std::to_string(dvx) + ", dvy=" + std::to_string(dvy)); Logger::info(" 安全距离=" + std::to_string(safeDistance)); Logger::info(" a=" + std::to_string(a) + ", b=" + std::to_string(b) + ", c=" + std::to_string(c)); auto prediction = detector_->predictTrajectoryCollision( aircraftPos, aircraftSpeed, aircraftHeading, vehiclePos, vehicleSpeed, vehicleHeading, aircraftSize, vehicleSize, timeWindow ); Logger::info("预测结果:"); Logger::info(" willCollide=" + std::to_string(prediction.willCollide)); Logger::info(" minDistance=" + std::to_string(prediction.minDistance)); if (prediction.willCollide) { Logger::info(" 碰撞点=(" + std::to_string(prediction.collisionPoint.x) + ", " + std::to_string(prediction.collisionPoint.y) + ")"); Logger::info(" 碰撞时间=" + std::to_string(prediction.timeToCollision)); } // 验证结果 EXPECT_TRUE(prediction.willCollide) << "应该检测到飞机和车的潜在碰撞"; if (prediction.willCollide) { // 考虑安全距离的影响,碰撞点会在实际交叉点之前 // 飞机从(0,200)出发,速度12m/s,12.79秒到达x=164.22 // 车辆从(200,100)出发,速度6m/s,12.79秒到达y=194.63 EXPECT_NEAR(prediction.collisionPoint.x, 164.22, 5.0) << "碰撞点x坐标应该考虑安全距离的影响"; EXPECT_NEAR(prediction.collisionPoint.y, 194.63, 5.0) << "碰撞点y坐标应该考虑安全距离的影响"; // 碰撞时间应该是12.79秒左右 double expectedTime = 12.79; // 考虑安全距离后的预期碰撞时间 EXPECT_NEAR(prediction.timeToCollision, expectedTime, 2.0) << "碰撞时间应该接近预期值"; } } // 测试场景7:斜向相交路径 { // 第一个物体从西南向东北运动 Vector2D pos1{0, 0}; double speed1 = 10; double heading1 = 45; // 东北方向(45度) // 第二个物体从东南向西北运动 Vector2D pos2{200, 0}; double speed2 = 10; double heading2 = 315; // 西北方向(315度) double size1 = 5; double size2 = 5; double timeWindow = 30; Logger::info("斜向相交路径测试参数:"); Logger::info(" 物体1: 位置=(" + std::to_string(pos1.x) + ", " + std::to_string(pos1.y) + "), 速度=" + std::to_string(speed1) + ", 航向=" + std::to_string(heading1)); Logger::info(" 物体2: 位置=(" + std::to_string(pos2.x) + ", " + std::to_string(pos2.y) + "), 速度=" + std::to_string(speed2) + ", 航向=" + std::to_string(heading2)); // 计算速度分量 double heading1Rad = heading1 * M_PI / 180.0; double heading2Rad = heading2 * M_PI / 180.0; double v1x = speed1 * std::sin(heading1Rad); // 东向为x轴正方向 double v1y = speed1 * std::cos(heading1Rad); // 北向为y轴正方向 double v2x = speed2 * std::sin(heading2Rad); double v2y = speed2 * std::cos(heading2Rad); Logger::info("速度分量:"); Logger::info(" 物体1: vx=" + std::to_string(v1x) + ", vy=" + std::to_string(v1y)); Logger::info(" 物体2: vx=" + std::to_string(v2x) + ", vy=" + std::to_string(v2y)); auto prediction = detector_->predictTrajectoryCollision( pos1, speed1, heading1, pos2, speed2, heading2, size1, size2, timeWindow ); // 验证结果 EXPECT_TRUE(prediction.willCollide) << "斜向相交路径应该检测到碰撞"; if (prediction.willCollide) { // 考虑安全距离(两个物体各5米),碰撞检测会在实际交叉点之前触发 // 由于两个物体速度相同且对称,碰撞点应该在中点附近,但会略低于理想位置 EXPECT_NEAR(prediction.collisionPoint.x, 100.0, 5.0) << "碰撞点x坐标应该在预期位置"; EXPECT_NEAR(prediction.collisionPoint.y, 95.0, 5.0) << "碰撞点y坐标应该考虑安全距离的影响"; // 到达碰撞点的时间 // 物体1需要移动:√((100-0)² + (95-0)²) ≈ 137.8米 // 速度为10m/s,所以时间应该约为13.78秒 double expectedTime = 13.78; EXPECT_NEAR(prediction.timeToCollision, expectedTime, 2.0) << "碰撞时间应该接近预期值"; } } }