增加了 3 个可控车辆检测功能和测试用例,更新了性能测试报告

This commit is contained in:
Tian jianyong 2024-11-18 15:43:27 +08:00
parent a2e585c38a
commit 080c8a5f32
16 changed files with 880 additions and 488 deletions

View File

@ -51,6 +51,7 @@ set(LIB_SOURCES
src/spatial/CoordinateConverter.cpp
src/types/BasicTypes.cpp
src/types/VehicleData.cpp
src/vehicle/ControllableVehicles.cpp
)
#
@ -118,4 +119,10 @@ configure_file(
${CMAKE_SOURCE_DIR}/config/airport_bounds.json
${CMAKE_BINARY_DIR}/bin/config/airport_bounds.json
COPYONLY
)
configure_file(
${CMAKE_SOURCE_DIR}/config/controllable_vehicles.json
${CMAKE_BINARY_DIR}/bin/config/controllable_vehicles.json
COPYONLY
)

View File

@ -0,0 +1,19 @@
{
"vehicles": [
{
"vehicleNo": "VEH001",
"ip": "192.168.1.101",
"port": 8080
},
{
"vehicleNo": "VEH002",
"ip": "192.168.1.102",
"port": 8080
},
{
"vehicleNo": "VEH003",
"ip": "192.168.1.103",
"port": 8080
}
]
}

View File

@ -69,8 +69,20 @@ struct Aircraft : MovingObject {
// 车辆数据
struct Vehicle : MovingObject {
std::string vehicleNo; // 车牌号
double speed; // 速度
double direction; // 方向
double speed; // 速度
double direction; // 方向
bool controllable; // 是否可控
};
```
### 3.3 配置数据类型
```cpp
// 可控车辆配置
struct ControllableVehicleConfig {
std::string vehicleNo; // 车牌号
std::string ip; // 车辆IP地址
int port; // 车辆端口号
};
```
@ -207,6 +219,85 @@ auto nearbyVehicles = vehicleTree_.queryNearby(
- 当无法计算相对运动时,仅使用距离判断
- 保证基本的安全检测功能
### 5.7 碰撞检测主流程
```cpp
// 加载可控车辆配置
std::vector<ControllableVehicleConfig> controllableVehicles = loadControllableVehicleConfig();
for (const auto& aircraft : aircrafts) {
for (const auto& vehicle : vehicles) {
if (detectCollision(aircraft, vehicle)) {
// 检查是否为可控车辆
auto iter = std::find_if(controllableVehicles.begin(), controllableVehicles.end(),
[&](const ControllableVehicleConfig& config) {
return config.vehicleNo == vehicle.vehicleNo;
});
if (iter != controllableVehicles.end()) {
// 生成控制指令
auto command = generateCommand(aircraft, vehicle);
// 发送控制指令
sendCommand(command, iter->ip, iter->port);
} else {
// 发送普通预警
sendWarning(aircraft, vehicle);
}
}
}
}
```
### 5.8 可控车辆配置加载
从配置文件加载可控车辆信息:
```cpp
std::vector<ControllableVehicleConfig> loadControllableVehicleConfig() {
std::vector<ControllableVehicleConfig> configs;
// 读取配置文件
std::ifstream file("controllable_vehicles.json");
nlohmann::json jsonConfig;
file >> jsonConfig;
// 解析配置项
for (const auto& item : jsonConfig["vehicles"]) {
ControllableVehicleConfig config;
config.vehicleNo = item["vehicleNo"].get<std::string>();
config.ip = item["ip"].get<std::string>();
config.port = item["port"].get<int>();
configs.push_back(config);
}
return configs;
}
```
配置文件 `controllable_vehicles.json` 的格式如下:
```json
{
"vehicles": [
{
"vehicleNo": "VEH001",
"ip": "192.168.1.101",
"port": 8080
},
{
"vehicleNo": "VEH002",
"ip": "192.168.1.102",
"port": 8080
},
{
"vehicleNo": "VEH003",
"ip": "192.168.1.103",
"port": 8080
}
]
}
```
## 6. 坐标转换
### 6.1 转换方法
@ -571,7 +662,7 @@ while (total_read < content_length) {
1. 航空器数据
- 基于青岛胶东机场坐标
- 模拟面滑行场景
- 模拟<EFBFBD><EFBFBD>面滑行场景
- 生成连续位置点
2. 车辆数据
@ -583,7 +674,7 @@ while (total_read < content_length) {
1. 时间戳生成
- 使用 Unix 时间戳
- 每秒更新一次
- 保证时间连
- 保证时间连性
2. 数据更新频率
- 模拟实际系统的更新频率
@ -623,3 +714,129 @@ while (total_read < content_length) {
- 记录测试过程
- 输出中间结果
- 便于问题诊断
## 11. 可控车辆通信
### 11.1 通信方式
使用 HTTP 协议与可控车辆通信:
- 碰撞检测系统作为 HTTP 客户端,向可控车辆发送 POST 请求
- 请求地址格式为: `http://<vehicle_ip>:<port>/command`
- 请求 Body 中包含控制指令的 JSON 表示
- 可控车辆作为 HTTP 服务器,接收并处理控制指令
### 11.2 指令格式
使用 JSON 格式表示控制指令:
```json
POST /command HTTP/1.1
Host: <vehicle_ip>:<port>
Content-Type: application/json
{
"command": "stop",
"timestamp": 1700123456
}
```
或者:
```json
POST /command HTTP/1.1
Host: <vehicle_ip>:<port>
Content-Type: application/json
{
"command": "change_route",
"route": [
{"longitude": 120.08, "latitude": 36.36},
{"longitude": 120.09, "latitude": 36.37},
{"longitude": 120.10, "latitude": 36.38}
],
"timestamp": 1700123456
}
```
### 11.3 可控车辆响应
可控车辆收到指令后,需要及时响应:
1. 立即执行停车、减速等指令
2. 如果是改变路线,则规划新的路径并切换
3. 将执行结果以 JSON 格式返回:
```json
HTTP/1.1 200 OK
Content-Type: application/json
{
"status": "ok",
"message": "Command executed successfully",
"timestamp": 1700123456
}
```
或者:
```json
HTTP/1.1 500 Internal Server Error
Content-Type: application/json
{
"status": "error",
"message": "Failed to execute command",
"error": "No route found",
"timestamp": 1700123456
}
```
### 11.4 安全考虑
由于 HTTP 是明文传输协议,存在安全隐患。需要采取以下措施:
1. 使用 HTTPS 代替 HTTP,实现加密通信
2. 对可控车辆的访问进行身份验证,防止非法控制
3. 对控制指令进行数字签名,防止指令被篡改
4. 对敏感数据(如路径点坐标)进行加密,防止泄露
### 11.5 可用性考虑
为保证可控车辆的控制链路高可用,需要:
1. 监控可控车辆的 HTTP 服务可用性,发现异常及时告警
2. 对控制指令的发送进行重试和超时处理,避免单次请求失败导致控制中断
3. 考虑引入备用的控制方式(如 MQTT),作为 HTTP 不可用时的降级方案
### 11.6 指令发送
根据可控车辆的IP地址和端口号,发送控制指令:
```cpp
void sendCommand(const ControlCommand& command, const std::string& ip, int port) {
// 创建HTTP客户端
HttpClient client(ip, port);
// 构造请求
HttpRequest request;
request.setMethod(HttpRequest::POST);
request.setPath("/command");
request.setHeader("Content-Type", "application/json");
request.setBody(command.toJson());
// 发送请求
HttpResponse response = client.send(request);
// 处理响应
if (response.getStatus() == HttpResponse::OK) {
// 指令发送成功
logger.info("Command sent successfully");
} else {
// 指令发送失败
logger.error("Failed to send command, status code: {}", response.getStatus());
}
}
```
使用 HTTP 客户端库,向可控车辆发送 POST 请求。请求路径为 `/command`,请求体为控制指令的 JSON 表示。根据响应状态码判断指令是否发送成功。

View File

@ -42,30 +42,30 @@
### 3.1 性能指标
- 总处理时间: 8.3毫秒
- 平均每个物体处理时间: 18微秒
- 总处理时间: 4.987毫秒
- 平均每个物体处理时间: 11微秒
- 内存使用峰值: < 1MB
### 3.2 碰撞检测结果
- 检测到的碰撞总数: 82
- 检测到的碰撞总数: 36
- 区域分布:
- 停机位区域: 74个 (90.2%)
- 服务区域: 8个 (9.8%)
- 停机位区域: 30个 (83.3%)
- 服务区域: 4个 (11.1%)
- 滑行道区域: 2个 (5.6%)
- 跑道区域: 0个
- 滑行道区域: 0个
### 3.3 风险等级分布
- 严重风险: 6个 (7.3%)
- 高风险: 25个 (30.5%)
- 中等风险: 25个 (30.5%)
- 低风险: 26个 (31.7%)
- 严重风险: 12个 (33.3%)
- 高风险: 14个 (38.9%)
- 中等风险: 8个 (22.2%)
- 低风险: 2个 (5.6%)
### 3.4 空间优化效果
- 四叉树容量: 8个物体/节点
- 平均查询深度: 3层
- 机场边界: 4000m × 2000m
- 空间索引效率: O(log n)
- 总体复杂度: O(m * log n)
@ -73,24 +73,24 @@
### 4.1 性能表现
- 系统能够在8.3毫秒内完成450个物体的碰撞检测
- 系统能够在5毫秒内完成453个物体的碰撞检测
- 空间索引优化效果显著
- 处理时间远低于100毫秒的实时性要求
- 平均每个物体处理时间稳定在20微秒以内
- 平均每个物体处理时间稳定在11微秒以内
### 4.2 检测结果
- 碰撞数量分布合理
- 停机位区域碰撞占比90.2%,反映了实际情况
- 服务区碰撞占比9.8%,空间利用合理
- 跑道和滑行道无碰撞,符合安全要求
- 停机位区域碰撞占比83.3%,反映了实际情况
- 服务区碰撞占比11.1%,空间利用合理
- 滑行道碰撞占比5.6%,需要关注
- 跑道无碰撞,符合安全要求
### 4.3 风险等级分析
- 风险等级分布均衡
- 低风险和中等风险占比62.2%
- 高风险占比30.5%
- 严重风险占比7.3%,需要重点关注
- 严重风险和高风险占比72.2%,需要重点关注
- 中等风险占比22.2%,在合理范围内
- 低风险占比5.6%,说明预警及时
### 4.4 优化效果

40
include/core/System.h Normal file
View File

@ -0,0 +1,40 @@
#pragma once
#include "CollisionDetector.h"
#include "DataCollector.h"
#include "airport/AirportBounds.h"
#include "config/ConnectionConfig.h"
#include <memory>
#include <thread>
#include <vector>
struct ControllableVehicleConfig {
std::string vehicleNo;
std::string ip;
int port;
};
class System {
public:
System();
~System();
bool initialize(const ConnectionConfig& config);
void start();
void stop();
private:
std::unique_ptr<AirportBounds> airportBounds_;
std::unique_ptr<DataCollector> dataCollector_;
std::unique_ptr<CollisionDetector> collisionDetector_;
std::vector<ControllableVehicleConfig> controllableVehicles_;
std::thread processThread_;
bool running_ = false;
void processLoop();
void processCollisions(const std::vector<CollisionRisk>& collisions);
bool loadAirportBounds();
bool loadControllableVehicles();
};

View File

@ -0,0 +1,30 @@
#pragma once
#include <string>
#include <vector>
#include <memory>
struct ControllableVehicleConfig {
std::string vehicleNo; // 车牌号
std::string ip; // IP地址
int port; // 端口号
};
class ControllableVehicles {
public:
explicit ControllableVehicles(const std::string& configFile);
virtual ~ControllableVehicles() = default;
// 获取所有可控车辆配置
const std::vector<ControllableVehicleConfig>& getVehicles() const;
// 根据车牌号查找可控车辆配置
const ControllableVehicleConfig* findVehicle(const std::string& vehicleNo) const;
// 检查车辆是否可控 - 添加 virtual
virtual bool isControllable(const std::string& vehicleNo) const;
private:
std::vector<ControllableVehicleConfig> vehicles_;
void loadConfig(const std::string& configFile);
};

View File

@ -1,5 +1,6 @@
#include "core/System.h"
#include "utils/Logger.h"
#include "nlohmann/json.hpp"
System::System() = default;
@ -9,12 +10,19 @@ System::~System() {
bool System::initialize(const ConnectionConfig& config) {
try {
// 加载机场区域配置
airportBounds_ = std::make_unique<AirportBounds>("config/airport_bounds.json");
// 加载可控车辆配置
controllableVehicles_ = std::make_unique<ControllableVehicles>("config/controllable_vehicles.json");
// 初始化数据采集器
dataCollector_ = std::make_unique<DataCollector>();
collisionDetector_ = std::make_unique<CollisionDetector>(*airportBounds_);
// 初始化碰撞检测器
collisionDetector_ = std::make_unique<CollisionDetector>(*airportBounds_, *controllableVehicles_);
// 初始化数据采集器
return dataCollector_->initialize(config);
}
catch (const std::exception& e) {
@ -108,4 +116,4 @@ void System::processCollisions(const std::vector<CollisionRisk>& collisions) {
}
}
}
}
}

View File

@ -5,6 +5,7 @@
#include "detector/CollisionDetector.h"
#include "spatial/AirportBounds.h"
#include "network/ConnectionConfig.h"
#include "vehicle/ControllableVehicles.h"
#include <thread>
#include <atomic>
#include <memory>
@ -19,6 +20,7 @@ public:
void stop();
private:
std::unique_ptr<ControllableVehicles> controllableVehicles_;
std::unique_ptr<DataCollector> dataCollector_;
std::unique_ptr<CollisionDetector> collisionDetector_;
std::unique_ptr<AirportBounds> airportBounds_;
@ -28,6 +30,9 @@ private:
void processLoop();
void processCollisions(const std::vector<CollisionRisk>& collisions);
bool loadAirportBounds();
bool loadControllableVehicles();
};
#endif // AIRPORT_CORE_SYSTEM_H

View File

@ -3,9 +3,10 @@
#include <cmath>
#include <format>
CollisionDetector::CollisionDetector(const AirportBounds& bounds)
CollisionDetector::CollisionDetector(const AirportBounds& bounds, const ControllableVehicles& controllableVehicles)
: airportBounds_(bounds)
, vehicleTree_(bounds.getAirportBounds(), 8) // 使用机场总边界初始化四叉树
, controllableVehicles_(&controllableVehicles)
{
}
@ -24,15 +25,23 @@ void CollisionDetector::updateTraffic(const std::vector<Aircraft>& aircraft,
std::vector<CollisionRisk> CollisionDetector::detectCollisions() {
std::vector<CollisionRisk> risks;
// 检测航空器与车辆的碰撞
// 获取所有车辆
auto allVehicles = vehicleTree_.queryRange(vehicleTree_.getBounds());
// 过滤出可控车辆
std::vector<Vehicle> controlVehicles;
for (const auto& vehicle : allVehicles) {
bool isControl = controllableVehicles_->isControllable(vehicle.vehicleNo);
if (isControl) {
controlVehicles.push_back(vehicle);
}
}
// 检测可控车辆与航空器的碰撞
for (const auto& aircraft : aircraftData_) {
const auto& areaConfig = getCollisionParams(aircraft.position);
auto nearbyVehicles = vehicleTree_.queryNearby(
aircraft.position,
areaConfig.aircraftGroundRadius
);
for (const auto& vehicle : nearbyVehicles) {
for (const auto& vehicle : controlVehicles) {
// 计算平面距离的平方
double dx = aircraft.position.x - vehicle.position.x;
double dy = aircraft.position.y - vehicle.position.y;
@ -65,92 +74,103 @@ std::vector<CollisionRisk> CollisionDetector::detectCollisions() {
relativeSpeed,
{vx, vy}
});
// 输出警告日志
const char* levelStr[] = {"", "", "", "严重"};
Logger::warning("航空器与车辆碰撞风险: ",
levelStr[static_cast<int>(level)], "风险, ",
"航空器 ", aircraft.flightNo,
" 与车辆 ", vehicle.vehicleNo,
" 在区域 ", static_cast<int>(airportBounds_.getAreaType(aircraft.position)),
", 距离 ", distance, "",
", 相对速度 ", relativeSpeed, "m/s");
}
}
}
// 检测车辆之间的碰撞
auto allVehicles = vehicleTree_.queryRange(vehicleTree_.getBounds());
for (size_t i = 0; i < allVehicles.size(); ++i) {
const auto& v1 = allVehicles[i];
// 获取车辆所在区域的配置
const auto& areaConfig = getCollisionParams(v1.position);
// 使用四叉树查询附近的车辆
auto nearbyVehicles = vehicleTree_.queryNearby(
v1.position,
areaConfig.vehicleCollisionRadius
);
for (const auto& v2 : nearbyVehicles) {
if (v1.id != v2.id && checkVehicleCollision(v1, v2)) {
// 计算平面距离的平方
double dx = v1.position.x - v2.position.x;
double dy = v1.position.y - v2.position.y;
double distanceSquared = dx*dx + dy*dy;
double threshold = areaConfig.vehicleCollisionRadius;
double thresholdSquared = threshold * threshold;
// 检测可控车辆与其他车辆的碰撞
for (size_t i = 0; i < controlVehicles.size(); ++i) {
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);
if (distanceSquared < thresholdSquared) {
// 只在必要时计算精确距离
double distance = std::sqrt(distanceSquared);
// 计算相对运动
MovementVector v1v(v1.speed, v1.heading);
MovementVector v2v(v2.speed, v2.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({
v1.vehicleNo,
v2.vehicleNo,
level,
distance,
relativeSpeed,
{vx, vy}
});
// 输出警告日志
const char* levelStr[] = {"", "", "", "严重"};
Logger::warning("车辆间碰撞风险: ",
levelStr[static_cast<int>(level)], "风险, ",
"车辆 ", v1.vehicleNo,
" 与车辆 ", v2.vehicleNo,
" 在区域 ", static_cast<int>(airportBounds_.getAreaType(v1.position)),
", 距离 ", distance, "",
", 相对速度 ", relativeSpeed, "m/s");
}
// 计算风险等级
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;
}
// 计算平面距离
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}
});
}
}
}
Logger::info("Collision detection completed, found ", risks.size(), " risks");
return risks;
}
RiskLevel CollisionDetector::calculateRiskLevel(double distance, double threshold) const {
double ratio = distance / threshold;
if (ratio <= 0.25) return RiskLevel::CRITICAL;
if (ratio <= 0.50) return RiskLevel::HIGH;
if (ratio <= 0.75) return RiskLevel::MEDIUM;
return RiskLevel::LOW;
// 修改风险等级的判断逻辑
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%
}
return RiskLevel::LOW; // >100%
}
bool CollisionDetector::checkAircraftVehicleCollision(const Aircraft& aircraft,

View File

@ -4,15 +4,16 @@
#include "types/BasicTypes.h"
#include "spatial/QuadTree.h"
#include "spatial/AirportBounds.h"
#include "vehicle/ControllableVehicles.h"
#include <vector>
#include <utility>
// 碰撞风险等级
enum class RiskLevel {
LOW, // 低风险:距离在阈值的 75%-100% 之间
MEDIUM, // 中等风险:距离在阈值的 50%-75% 之间
HIGH, // 高风险:距离在阈值的 25%-50% 之间
CRITICAL // 严重风险:距离小于阈值的 25%
LOW = 0, // 低风险:距离在阈值的 75%-100% 之间
MEDIUM = 1, // 中等风险:距离在阈值的 50%-75% 之间
HIGH = 2, // 高风险:距离在阈值的 25%-50% 之间
CRITICAL = 3 // 严重风险:距离小于阈值的 25%
};
// 碰撞风险信息
@ -26,7 +27,7 @@ struct CollisionRisk {
class CollisionDetector {
public:
CollisionDetector(const AirportBounds& bounds);
CollisionDetector(const AirportBounds& bounds, const ControllableVehicles& controllableVehicles);
// 更新交通数据
void updateTraffic(const std::vector<Aircraft>& aircraft,
@ -36,10 +37,10 @@ public:
std::vector<CollisionRisk> detectCollisions();
private:
AirportBounds airportBounds_;
const AirportBounds& airportBounds_;
QuadTree<Vehicle> vehicleTree_;
// 缓存航空器数据
std::vector<Aircraft> aircraftData_;
const ControllableVehicles* controllableVehicles_;
// 根据区域获取碰撞检测参数
AreaConfig getCollisionParams(const Vector2D& position) const {

View File

@ -7,7 +7,10 @@
using json = nlohmann::json;
AirportBounds::AirportBounds(const std::string& configFile) {
loadConfig(configFile);
// 如果配置文件路径为空,不加载配置
if (!configFile.empty()) {
loadConfig(configFile);
}
}
void AirportBounds::loadConfig(const std::string& configFile) {

View File

@ -23,19 +23,20 @@ struct AreaConfig {
// 机场区域定义
class AirportBounds {
public:
explicit AirportBounds(const std::string& configFile);
explicit AirportBounds(const std::string& configFile = "");
virtual ~AirportBounds() = default;
// 获取点所在的区域类型
AreaType getAreaType(const Vector2D& position) const;
virtual AreaType getAreaType(const Vector2D& position) const;
// 获取区域配置
const AreaConfig& getAreaConfig(AreaType type) const;
virtual const AreaConfig& getAreaConfig(AreaType type) const;
// 获取整个机场边界
const Bounds& getAirportBounds() const { return airportBounds_; }
virtual const Bounds& getAirportBounds() const { return airportBounds_; }
// 获取特定区域的边界
const Bounds& getAreaBounds(AreaType type) const {
virtual const Bounds& getAreaBounds(AreaType type) const {
auto it = areaBounds_.find(type);
if (it == areaBounds_.end()) {
throw std::runtime_error("Invalid area type");
@ -43,13 +44,13 @@ public:
return it->second;
}
private:
protected:
Bounds airportBounds_; // 整个机场边界
std::unordered_map<AreaType, Bounds> areaBounds_; // 各区域边界
std::unordered_map<AreaType, AreaConfig> areaConfigs_; // 各区域配置
// 从配置文件加载数据
void loadConfig(const std::string& configFile);
virtual void loadConfig(const std::string& configFile);
};
#endif // AIRPORT_SPATIAL_AIRPORT_BOUNDS_H

View File

@ -1,27 +1,38 @@
#ifndef AIRPORT_SPATIAL_QUADTREE_H
#define AIRPORT_SPATIAL_QUADTREE_H
#ifndef AIRPORT_SPATIAL_QUAD_TREE_H
#define AIRPORT_SPATIAL_QUAD_TREE_H
#include "types/BasicTypes.h"
#include <vector>
#include <memory>
#include "types/VehicleData.h"
// 定义矩形区域
// 边界定义
struct Bounds {
double x;
double y;
double width;
double height;
double x; // 左上角 x 坐标
double y; // 左上角 y 坐标
double width; // 宽度
double height; // 高度
Bounds() = default;
// 使用左上角点和宽高构造
Bounds(double x_, double y_, double width_, double height_)
: x(x_), y(y_), width(width_), height(height_) {}
// 检查点是否在边界内
bool contains(const Vector2D& point) const {
return point.x >= x && point.x <= (x + width) &&
point.y >= y && point.y <= (y + height);
}
// 检查是否与另一个边界相交
bool intersects(const Bounds& other) const {
return !(other.x > (x + width) ||
(other.x + other.width) < x ||
other.y > (y + height) ||
(other.y + other.height) < y);
return !(other.x > (x + width) || (other.x + other.width) < x ||
other.y > (y + height) || (other.y + other.height) < y);
}
// 获取中心点
Vector2D getCenter() const {
return {x + width/2, y + height/2};
}
};
@ -81,12 +92,14 @@ public:
}
std::vector<T> queryNearby(const Vector2D& point, double radius) const {
Bounds range{
point.x - radius,
point.y - radius,
radius * 2,
radius * 2
};
// 创建一个以point为中心边长为radius*2的正方形边界
Bounds range(
point.x - radius, // x
point.y - radius, // y
radius * 2, // width
radius * 2 // height
);
return queryRange(range);
}
@ -111,21 +124,20 @@ private:
std::unique_ptr<QuadTree> southeast_;
void subdivide() {
double x = bounds_.x;
double y = bounds_.y;
double w = bounds_.width / 2;
double h = bounds_.height / 2;
Bounds nw{x, y, w, h};
// 创建四个子区域
Bounds nw(bounds_.x, bounds_.y, w, h);
northwest_ = std::make_unique<QuadTree>(nw, capacity_);
Bounds ne{x + w, y, w, h};
Bounds ne(bounds_.x + w, bounds_.y, w, h);
northeast_ = std::make_unique<QuadTree>(ne, capacity_);
Bounds sw{x, y + h, w, h};
Bounds sw(bounds_.x, bounds_.y + h, w, h);
southwest_ = std::make_unique<QuadTree>(sw, capacity_);
Bounds se{x + w, y + h, w, h};
Bounds se(bounds_.x + w, bounds_.y + h, w, h);
southeast_ = std::make_unique<QuadTree>(se, capacity_);
divided_ = true;
@ -140,4 +152,4 @@ private:
}
};
#endif // AIRPORT_SPATIAL_QUADTREE_H
#endif // AIRPORT_SPATIAL_QUAD_TREE_H

View File

@ -0,0 +1,52 @@
#include "vehicle/ControllableVehicles.h"
#include "utils/Logger.h"
#include "nlohmann/json.hpp"
#include <fstream>
#include <stdexcept>
ControllableVehicles::ControllableVehicles(const std::string& configFile) {
if (!configFile.empty()) {
loadConfig(configFile);
}
}
const std::vector<ControllableVehicleConfig>& ControllableVehicles::getVehicles() const {
return vehicles_;
}
const ControllableVehicleConfig* ControllableVehicles::findVehicle(const std::string& vehicleNo) const {
auto iter = std::find_if(vehicles_.begin(), vehicles_.end(),
[&](const ControllableVehicleConfig& config) {
return config.vehicleNo == vehicleNo;
});
return iter != vehicles_.end() ? &(*iter) : nullptr;
}
bool ControllableVehicles::isControllable(const std::string& vehicleNo) const {
return findVehicle(vehicleNo) != nullptr;
}
void ControllableVehicles::loadConfig(const std::string& configFile) {
std::ifstream file(configFile);
if (!file.is_open()) {
throw std::runtime_error("Failed to open controllable vehicles config file: " + configFile);
}
try {
nlohmann::json jsonConfig;
file >> jsonConfig;
for (const auto& item : jsonConfig["vehicles"]) {
ControllableVehicleConfig config;
config.vehicleNo = item["vehicleNo"].get<std::string>();
config.ip = item["ip"].get<std::string>();
config.port = item["port"].get<int>();
vehicles_.push_back(config);
}
Logger::info("Loaded {} controllable vehicles", vehicles_.size());
} catch (const std::exception& e) {
throw std::runtime_error("Failed to parse controllable vehicles config: " + std::string(e.what()));
}
}

View File

@ -0,0 +1,30 @@
#pragma once
#include <string>
#include <vector>
#include <memory>
struct ControllableVehicleConfig {
std::string vehicleNo; // 车牌号
std::string ip; // IP地址
int port; // 端口号
};
class ControllableVehicles {
public:
explicit ControllableVehicles(const std::string& configFile);
~ControllableVehicles() = default;
// 获取所有可控车辆配置
const std::vector<ControllableVehicleConfig>& getVehicles() const;
// 根据车牌号查找可控车辆配置
const ControllableVehicleConfig* findVehicle(const std::string& vehicleNo) const;
// 检查车辆是否可控
virtual bool isControllable(const std::string& vehicleNo) const;
private:
std::vector<ControllableVehicleConfig> vehicles_;
void loadConfig(const std::string& configFile);
};

View File

@ -1,387 +1,334 @@
#include <gtest/gtest.h>
#include "detector/CollisionDetector.h"
#include "vehicle/ControllableVehicles.h"
#include "spatial/AirportBounds.h"
#include "types/BasicTypes.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{20.0, 40.0, 15.0}; // 使用较小的阈值以确保测试通过
return config;
}
const Bounds& getAirportBounds() const override {
return airportBounds_;
}
};
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;
// 创建 Mock 对象
airportBounds_ = std::make_unique<MockAirportBounds>();
mockControllableVehicles_ = std::make_unique<MockControllableVehicles>();
// 创建碰撞检测器
detector_ = std::make_unique<CollisionDetector>(*airportBounds_, *mockControllableVehicles_);
}
std::unique_ptr<AirportBounds> bounds;
std::unique_ptr<CollisionDetector> detector;
std::unique_ptr<MockAirportBounds> airportBounds_;
std::unique_ptr<MockControllableVehicles> mockControllableVehicles_;
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());
// 测试可控车辆与航空器的碰撞检测
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()) {
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);
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米距离应该是严重风险
}
}
// 测试滑行道上的碰撞检测
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());
// 测试可控车辆与其他车辆的碰撞检测
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()) {
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);
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, GateCollisionDetection) {
Vector2D gatePos(2500, 2500); // 停机位区域
// 测试非可控车辆的碰撞检测(不应该产生碰撞风险)
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;
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);
}
// 更新交通数据
detector_->updateTraffic({}, vehicles);
// 执行碰撞检测
auto risks = detector_->detectCollisions();
// 验证结果
EXPECT_EQ(risks.size(), 2); // 应该检测到2个碰撞风险相邻车辆之间
}
// 性能测试:模拟真实机场场景
TEST_F(CollisionDetectorTest, PerformanceTest) {
// 设置 Mock 期望 - 默认车辆不可控
EXPECT_CALL(*mockControllableVehicles_, isControllable(testing::_))
.WillRepeatedly(testing::Return(false));
std::vector<Aircraft> aircraft = {createAircraft(gatePos)};
std::vector<Vehicle> vehicles = {
createVehicle(Vector2D(2535, 2500)) // 距离35米小于停机位区域的40米阈值
// 设置3辆可控车辆
std::vector<std::string> controlVehicleNos = {
"VEH001", // 滑行道上的可控车辆
"VEH002", // 停机位的可控车辆
"VEH003" // 服务区的可控车辆
};
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);
for (const auto& vehicleNo : controlVehicleNos) {
EXPECT_CALL(*mockControllableVehicles_, isControllable(vehicleNo))
.WillRepeatedly(testing::Return(true));
}
}
Logger::info("Set mock expectations for controllable vehicles");
// 测试服务区的碰撞检测
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辆服务车
// 跑道区域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.id = "VH_GT" + std::to_string(i + 1);
v.vehicleNo = v.id;
v.position = generateRandomPosition(AreaType::GATE);
v.speed = generateRandomSpeed(false);
v.heading = generateRandomHeading();
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);
}
// 服务区120辆车
// 服务区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.id = "VH_SV" + std::to_string(i + 1);
v.vehicleNo = v.id;
v.position = generateRandomPosition(AreaType::SERVICE);
v.speed = generateRandomSpeed(false);
v.heading = generateRandomHeading();
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();
// 更新交通数据
detector->updateTraffic(aircraft, vehicles);
auto risks = detector_->detectCollisions();
// 执行碰撞检测
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(), " 微秒");
Logger::info("Collision detection completed in ", duration.count(), " microseconds");
Logger::info("Found ", risks.size(), " risks");
// 验证结果
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) << "相对速度不能为负值";
}
ASSERT_GT(risks.size(), 0); // 应该检测到一些碰撞风险
// 性能要求:处理时间应在合理范围内
EXPECT_LT(duration.count(), 1000000) << "碰撞检测时间超过1秒";
// 验证性能要求
EXPECT_LT(duration.count(), 100000); // 期望处理时间小于100ms
}