修改了 CPP 文件的格式化,使用 K&R 代码风格
This commit is contained in:
parent
81fcd1f438
commit
90b372f659
14
.clang-format
Normal file
14
.clang-format
Normal file
@ -0,0 +1,14 @@
|
||||
# 精简版 K&R 风格配置
|
||||
BasedOnStyle: LLVM
|
||||
BreakBeforeBraces: Linux
|
||||
IndentWidth: 4
|
||||
AllowShortFunctionsOnASingleLine: Empty
|
||||
|
||||
# 显式禁用所有大括号换行
|
||||
BraceWrapping:
|
||||
AfterClass: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
AfterFunction: false
|
||||
AfterNamespace: false
|
||||
AfterControlStatement: Never
|
||||
19
.cursorrules
19
.cursorrules
@ -1,14 +1,5 @@
|
||||
请遵循:
|
||||
- 最小化修改代码,不要修改任何与解决当前问题无关的代码(包括注释),一定不能删除任何其他的代码
|
||||
- 使用 C++20 标准
|
||||
- 使用 CMake 3.14 及以上版本
|
||||
- 使用 nlohmann_json 3.11.3 版本
|
||||
- 使用 FetchContent 管理第三方库
|
||||
- 使用 Google Test 进行单元测试
|
||||
- 使用 Google Mock 进行单元测试
|
||||
- 使用 Google Benchmark 进行性能测试
|
||||
- 在头文件中定义函数,在源文件中实现函数
|
||||
- 在头文件中定义类,在源文件中实现类
|
||||
- 使用源代码中的格式化方式和注释风格
|
||||
- 日志的字符串格式采用拼接方式,不要使用{}占位符
|
||||
|
||||
@ -23,7 +14,6 @@
|
||||
|
||||
2. 列表格式
|
||||
- 无序列表统一使用 -
|
||||
- 有序列表使用 1. 2. 3.
|
||||
- 列表项前后空一行
|
||||
- 列表嵌套使用两个空格缩进
|
||||
|
||||
@ -44,7 +34,7 @@
|
||||
- 格式统一一致
|
||||
|
||||
请遵循如下 C++ 规范:
|
||||
- 使用 C++20 标准
|
||||
- 使用 C++17 标准
|
||||
- 使用 CMake 3.14 及以上版本
|
||||
- 使用 nlohmann_json 3.11.3 版本
|
||||
- 使用 FetchContent 管理第三方库
|
||||
@ -52,10 +42,3 @@
|
||||
- 使用 Google Mock 进行单元测试
|
||||
- 使用 Google Benchmark 进行性能测试
|
||||
- 在头文件中定义函数,在源文件中实现函数
|
||||
|
||||
修改代码原则:
|
||||
- 先询问代码的用途
|
||||
- 理解代码的功能和作用
|
||||
- 确认是否可以修改或删除
|
||||
- 如果不确定就直接问我
|
||||
- 不要随便修改原有代码中的中文注释
|
||||
@ -81,6 +81,7 @@ endif()
|
||||
# 源文件列表
|
||||
set(LIB_SOURCES
|
||||
src/collector/DataCollector.cpp
|
||||
src/collector/DataSourceConfig.cpp
|
||||
src/core/System.cpp
|
||||
src/detector/CollisionDetector.cpp
|
||||
src/detector/SafetyZone.cpp
|
||||
|
||||
@ -1,12 +0,0 @@
|
||||
std::string getSignalStateString(SignalState state) {
|
||||
switch (state) {
|
||||
case SignalState::RED:
|
||||
return "RED";
|
||||
case SignalState::YELLOW:
|
||||
return "YELLOW";
|
||||
case SignalState::GREEN:
|
||||
return "GREEN";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
@ -2,23 +2,23 @@
|
||||
#include "network/HTTPDataSource.h"
|
||||
#include "utils/Logger.h"
|
||||
#include <chrono>
|
||||
#include <mutex>
|
||||
#include <fstream>
|
||||
#include <mutex>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
DataCollector::DataCollector(const AirportBounds& bounds)
|
||||
: last_position_fetch_(std::chrono::steady_clock::now())
|
||||
, last_unmanned_fetch_(std::chrono::steady_clock::now())
|
||||
, last_traffic_light_fetch_(std::chrono::steady_clock::now())
|
||||
, last_warning_time_(std::chrono::steady_clock::now())
|
||||
, airportBounds_(bounds) {
|
||||
}
|
||||
: last_position_fetch_(std::chrono::steady_clock::now()),
|
||||
last_unmanned_fetch_(std::chrono::steady_clock::now()),
|
||||
last_traffic_light_fetch_(std::chrono::steady_clock::now()),
|
||||
last_warning_time_(std::chrono::steady_clock::now()),
|
||||
airportBounds_(bounds) {}
|
||||
|
||||
DataCollector::~DataCollector() {
|
||||
stop();
|
||||
}
|
||||
|
||||
bool DataCollector::initialize(const DataSourceConfig& dataSourceConfig, const WarnConfig& warnConfig) {
|
||||
bool DataCollector::initialize(const DataSourceConfig& dataSourceConfig,
|
||||
const WarnConfig& warnConfig) {
|
||||
if (!dataSource_) {
|
||||
dataSourceConfig_ = dataSourceConfig;
|
||||
dataSource_ = std::make_shared<HTTPDataSource>(dataSourceConfig_);
|
||||
@ -83,7 +83,8 @@ void DataCollector::stop() {
|
||||
}
|
||||
|
||||
void DataCollector::positionLoop() {
|
||||
Logger::debug("位置数据采集循环启动,刷新间隔: ", dataSourceConfig_.position.refresh_interval_ms, "ms");
|
||||
Logger::debug("位置数据采集循环启动,刷新间隔: ",
|
||||
dataSourceConfig_.position.refresh_interval_ms, "ms");
|
||||
auto next_collection_time = std::chrono::steady_clock::now();
|
||||
|
||||
while (running_) {
|
||||
@ -94,14 +95,18 @@ void DataCollector::positionLoop() {
|
||||
}
|
||||
|
||||
// 计算下一次采集时间
|
||||
next_collection_time += std::chrono::milliseconds(dataSourceConfig_.position.refresh_interval_ms);
|
||||
next_collection_time += std::chrono::milliseconds(
|
||||
dataSourceConfig_.position.refresh_interval_ms);
|
||||
auto now = std::chrono::steady_clock::now();
|
||||
|
||||
if (next_collection_time > now) {
|
||||
auto wait_time = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
next_collection_time - now).count();
|
||||
auto wait_time =
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
next_collection_time - now)
|
||||
.count();
|
||||
if (wait_time > 0) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(wait_time));
|
||||
std::this_thread::sleep_for(
|
||||
std::chrono::milliseconds(wait_time));
|
||||
}
|
||||
} else {
|
||||
// 如果已经超过了下一次采集时间,立即重置
|
||||
@ -111,7 +116,8 @@ void DataCollector::positionLoop() {
|
||||
}
|
||||
|
||||
void DataCollector::unmannedLoop() {
|
||||
Logger::debug("无人车状态采集循环启动,刷新间隔: ", dataSourceConfig_.vehicle.refresh_interval_ms, "ms");
|
||||
Logger::debug("无人车状态采集循环启动,刷新间隔: ",
|
||||
dataSourceConfig_.vehicle.refresh_interval_ms, "ms");
|
||||
auto next_collection_time = std::chrono::steady_clock::now();
|
||||
|
||||
while (running_) {
|
||||
@ -122,14 +128,18 @@ void DataCollector::unmannedLoop() {
|
||||
}
|
||||
|
||||
// 计算下一次采集时间
|
||||
next_collection_time += std::chrono::milliseconds(dataSourceConfig_.vehicle.refresh_interval_ms);
|
||||
next_collection_time += std::chrono::milliseconds(
|
||||
dataSourceConfig_.vehicle.refresh_interval_ms);
|
||||
auto now = std::chrono::steady_clock::now();
|
||||
|
||||
if (next_collection_time > now) {
|
||||
auto wait_time = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
next_collection_time - now).count();
|
||||
auto wait_time =
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
next_collection_time - now)
|
||||
.count();
|
||||
if (wait_time > 0) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(wait_time));
|
||||
std::this_thread::sleep_for(
|
||||
std::chrono::milliseconds(wait_time));
|
||||
}
|
||||
} else {
|
||||
// 如果已经超过了下一次采集时间,立即重置
|
||||
@ -139,7 +149,8 @@ void DataCollector::unmannedLoop() {
|
||||
}
|
||||
|
||||
void DataCollector::trafficLightLoop() {
|
||||
Logger::debug("红绿灯数据采集循环启动,刷新间隔: ", dataSourceConfig_.traffic_light.refresh_interval_ms, "ms");
|
||||
Logger::debug("红绿灯数据采集循环启动,刷新间隔: ",
|
||||
dataSourceConfig_.traffic_light.refresh_interval_ms, "ms");
|
||||
auto next_collection_time = std::chrono::steady_clock::now();
|
||||
|
||||
while (running_) {
|
||||
@ -150,14 +161,18 @@ void DataCollector::trafficLightLoop() {
|
||||
}
|
||||
|
||||
// 计算下一次采集时间
|
||||
next_collection_time += std::chrono::milliseconds(dataSourceConfig_.traffic_light.refresh_interval_ms);
|
||||
next_collection_time += std::chrono::milliseconds(
|
||||
dataSourceConfig_.traffic_light.refresh_interval_ms);
|
||||
auto now = std::chrono::steady_clock::now();
|
||||
|
||||
if (next_collection_time > now) {
|
||||
auto wait_time = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
next_collection_time - now).count();
|
||||
auto wait_time =
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
next_collection_time - now)
|
||||
.count();
|
||||
if (wait_time > 0) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(wait_time));
|
||||
std::this_thread::sleep_for(
|
||||
std::chrono::milliseconds(wait_time));
|
||||
}
|
||||
} else {
|
||||
// 如果已经超过了下一次采集时间,立即重置
|
||||
@ -170,22 +185,28 @@ void DataCollector::checkTimeout() {
|
||||
auto now = std::chrono::steady_clock::now();
|
||||
|
||||
// 检查位置数据超时
|
||||
auto position_elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
now - last_position_fetch_).count();
|
||||
auto position_elapsed =
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
now - last_position_fetch_)
|
||||
.count();
|
||||
if (position_elapsed > dataSourceConfig_.position.timeout_ms) {
|
||||
sendTimeoutWarning("position", position_elapsed);
|
||||
}
|
||||
|
||||
// 检查无人车数据超时
|
||||
auto unmanned_elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
now - last_unmanned_fetch_).count();
|
||||
auto unmanned_elapsed =
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
now - last_unmanned_fetch_)
|
||||
.count();
|
||||
if (unmanned_elapsed > dataSourceConfig_.vehicle.timeout_ms) {
|
||||
sendTimeoutWarning("unmanned", unmanned_elapsed);
|
||||
}
|
||||
|
||||
// 检查红绿灯数据超时
|
||||
auto traffic_light_elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
now - last_traffic_light_fetch_).count();
|
||||
auto traffic_light_elapsed =
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
now - last_traffic_light_fetch_)
|
||||
.count();
|
||||
if (traffic_light_elapsed > dataSourceConfig_.traffic_light.timeout_ms) {
|
||||
sendTimeoutWarning("traffic_light", traffic_light_elapsed);
|
||||
}
|
||||
@ -196,34 +217,42 @@ void DataCollector::resetTimeout(const std::string& source) {
|
||||
|
||||
if (source == "position") {
|
||||
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
now - last_position_fetch_).count();
|
||||
now - last_position_fetch_)
|
||||
.count();
|
||||
if (elapsed > dataSourceConfig_.position.timeout_ms) {
|
||||
Logger::info("Position data source connection restored after ", elapsed, "ms timeout");
|
||||
Logger::info("Position data source connection restored after ",
|
||||
elapsed, "ms timeout");
|
||||
}
|
||||
last_position_fetch_ = now;
|
||||
}
|
||||
else if (source == "unmanned") {
|
||||
} else if (source == "unmanned") {
|
||||
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
now - last_unmanned_fetch_).count();
|
||||
now - last_unmanned_fetch_)
|
||||
.count();
|
||||
if (elapsed > dataSourceConfig_.vehicle.timeout_ms) {
|
||||
Logger::info("Unmanned vehicle data source connection restored after ", elapsed, "ms timeout");
|
||||
Logger::info(
|
||||
"Unmanned vehicle data source connection restored after ",
|
||||
elapsed, "ms timeout");
|
||||
}
|
||||
last_unmanned_fetch_ = now;
|
||||
}
|
||||
else if (source == "traffic_light") {
|
||||
} else if (source == "traffic_light") {
|
||||
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
now - last_traffic_light_fetch_).count();
|
||||
now - last_traffic_light_fetch_)
|
||||
.count();
|
||||
if (elapsed > dataSourceConfig_.traffic_light.timeout_ms) {
|
||||
Logger::info("Traffic light data source connection restored after ", elapsed, "ms timeout");
|
||||
Logger::info("Traffic light data source connection restored after ",
|
||||
elapsed, "ms timeout");
|
||||
}
|
||||
last_traffic_light_fetch_ = now;
|
||||
}
|
||||
}
|
||||
|
||||
void DataCollector::sendTimeoutWarning(const std::string& source, int64_t elapsed_ms) {
|
||||
void DataCollector::sendTimeoutWarning(const std::string& source,
|
||||
int64_t elapsed_ms) {
|
||||
auto now = std::chrono::steady_clock::now();
|
||||
auto warning_elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
now - last_warning_time_).count();
|
||||
auto warning_elapsed =
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
now - last_warning_time_)
|
||||
.count();
|
||||
|
||||
if (warning_elapsed >= warnConfig_.warning_interval_ms) {
|
||||
if (!system_) {
|
||||
@ -239,11 +268,9 @@ void DataCollector::sendTimeoutWarning(const std::string& source, int64_t elapse
|
||||
int64_t timeout_ms = 0;
|
||||
if (source == "position") {
|
||||
timeout_ms = dataSourceConfig_.position.timeout_ms;
|
||||
}
|
||||
else if (source == "unmanned") {
|
||||
} else if (source == "unmanned") {
|
||||
timeout_ms = dataSourceConfig_.vehicle.timeout_ms;
|
||||
}
|
||||
else if (source == "traffic_light") {
|
||||
} else if (source == "traffic_light") {
|
||||
timeout_ms = dataSourceConfig_.traffic_light.timeout_ms;
|
||||
}
|
||||
|
||||
@ -254,20 +281,21 @@ void DataCollector::sendTimeoutWarning(const std::string& source, int64_t elapse
|
||||
}
|
||||
}
|
||||
|
||||
void DataCollector::filterPositionData(std::vector<Aircraft>& aircraft, std::vector<Vehicle>& vehicles) {
|
||||
void DataCollector::filterPositionData(std::vector<Aircraft>& aircraft,
|
||||
std::vector<Vehicle>& vehicles) {
|
||||
size_t originalAircraftCount = aircraft.size();
|
||||
size_t originalVehicleCount = vehicles.size();
|
||||
|
||||
// 过滤航空器数据
|
||||
auto aircraftIt = std::remove_if(aircraft.begin(), aircraft.end(),
|
||||
[this](const Aircraft& a) {
|
||||
// 过滤掉不在机场区域内的航空器数据
|
||||
auto aircraftIt = std::remove_if(
|
||||
aircraft.begin(), aircraft.end(), [this](const Aircraft& a) {
|
||||
return !airportBounds_.isPointInBounds(a.position);
|
||||
});
|
||||
aircraft.erase(aircraftIt, aircraft.end());
|
||||
|
||||
// 过滤车辆数据
|
||||
auto vehicleIt = std::remove_if(vehicles.begin(), vehicles.end(),
|
||||
[this](const Vehicle& v) {
|
||||
// 过滤掉不在机场区域内的车辆数据
|
||||
auto vehicleIt = std::remove_if(
|
||||
vehicles.begin(), vehicles.end(), [this](const Vehicle& v) {
|
||||
return !airportBounds_.isPointInBounds(v.position);
|
||||
});
|
||||
vehicles.erase(vehicleIt, vehicles.end());
|
||||
@ -277,10 +305,8 @@ void DataCollector::filterPositionData(std::vector<Aircraft>& aircraft, std::vec
|
||||
size_t filteredVehicleCount = originalVehicleCount - vehicles.size();
|
||||
|
||||
if (filteredAircraftCount > 0 || filteredVehicleCount > 0) {
|
||||
Logger::info(
|
||||
"数据过滤结果: 过滤掉 ", filteredAircraftCount, " 架航空器, ",
|
||||
filteredVehicleCount, " 辆车辆"
|
||||
);
|
||||
Logger::info("数据过滤结果: 过滤掉 ", filteredAircraftCount,
|
||||
" 架航空器, ", filteredVehicleCount, " 辆车辆");
|
||||
}
|
||||
}
|
||||
|
||||
@ -330,14 +356,16 @@ bool DataCollector::fetchPositionData() {
|
||||
// 转换坐标系
|
||||
for (auto& a : newAircraft) {
|
||||
// 1. 先转换为世界坐标
|
||||
a.position = CoordinateConverter::instance().toLocalXY(a.geo.latitude, a.geo.longitude);
|
||||
a.position = CoordinateConverter::instance().toLocalXY(
|
||||
a.geo.latitude, a.geo.longitude);
|
||||
// 2. 再转换为机场坐标
|
||||
a.position = airportBounds_.toAirportCoordinate(a.position);
|
||||
}
|
||||
|
||||
for (auto& v : newVehicles) {
|
||||
// 1. 先转换为世界坐标
|
||||
v.position = CoordinateConverter::instance().toLocalXY(v.geo.latitude, v.geo.longitude);
|
||||
v.position = CoordinateConverter::instance().toLocalXY(
|
||||
v.geo.latitude, v.geo.longitude);
|
||||
// 2. 再转换为机场坐标
|
||||
v.position = airportBounds_.toAirportCoordinate(v.position);
|
||||
}
|
||||
@ -366,11 +394,13 @@ bool DataCollector::fetchUnmannedVehicleData() {
|
||||
for (const auto& vehicle : vehicles) {
|
||||
if (vehicle.type == "UNMANNED") {
|
||||
std::string status;
|
||||
if (dataSource_->fetchUnmannedVehicleStatus(vehicle.vehicleNo, status)) {
|
||||
if (dataSource_->fetchUnmannedVehicleStatus(vehicle.vehicleNo,
|
||||
status)) {
|
||||
any_success = true;
|
||||
} else {
|
||||
any_failure = true;
|
||||
Logger::error("获取无人车状态失败, vehicleNo: " + vehicle.vehicleNo);
|
||||
Logger::error("获取无人车状态失败, vehicleNo: " +
|
||||
vehicle.vehicleNo);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -413,7 +443,8 @@ std::vector<TrafficLightSignal> DataCollector::getTrafficLightSignals() {
|
||||
return trafficLightCache_;
|
||||
}
|
||||
|
||||
bool DataCollector::fetchTrafficLightSignals(std::vector<TrafficLightSignal>& signals) {
|
||||
bool DataCollector::fetchTrafficLightSignals(
|
||||
std::vector<TrafficLightSignal>& signals) {
|
||||
if (!dataSource_) {
|
||||
return false;
|
||||
}
|
||||
@ -430,7 +461,8 @@ std::vector<Vehicle> DataCollector::getVehicleData() {
|
||||
return vehicleCache_;
|
||||
}
|
||||
|
||||
bool DataCollector::fetchUnmannedVehicleStatus(const std::string& vehicle_id, std::string& status) {
|
||||
bool DataCollector::fetchUnmannedVehicleStatus(const std::string& vehicle_id,
|
||||
std::string& status) {
|
||||
if (!dataSource_) {
|
||||
Logger::error("No data source available");
|
||||
return false;
|
||||
|
||||
@ -8,40 +8,65 @@ DataSourceConfig DataSourceConfig::fromSystemConfig(const SystemConfig& config)
|
||||
// 转换位置数据源配置
|
||||
dataSourceConfig.position.host = config.data_source.position.host;
|
||||
dataSourceConfig.position.port = config.data_source.position.port;
|
||||
dataSourceConfig.position.aircraft_path = config.data_source.position.aircraft_path;
|
||||
dataSourceConfig.position.vehicle_path = config.data_source.position.vehicle_path;
|
||||
dataSourceConfig.position.refresh_interval_ms = config.data_source.position.refresh_interval_ms;
|
||||
dataSourceConfig.position.timeout_ms = config.data_source.position.timeout_ms;
|
||||
dataSourceConfig.position.read_timeout_ms = config.data_source.position.read_timeout_ms;
|
||||
dataSourceConfig.position.auth.username = config.data_source.position.auth.username;
|
||||
dataSourceConfig.position.auth.password = config.data_source.position.auth.password;
|
||||
dataSourceConfig.position.auth.auth_path = config.data_source.position.auth.auth_path;
|
||||
dataSourceConfig.position.auth.auth_required = config.data_source.position.auth.auth_required;
|
||||
dataSourceConfig.position.aircraft_path =
|
||||
config.data_source.position.aircraft_path;
|
||||
dataSourceConfig.position.vehicle_path =
|
||||
config.data_source.position.vehicle_path;
|
||||
dataSourceConfig.position.refresh_interval_ms =
|
||||
config.data_source.position.refresh_interval_ms;
|
||||
dataSourceConfig.position.timeout_ms =
|
||||
config.data_source.position.timeout_ms;
|
||||
dataSourceConfig.position.read_timeout_ms =
|
||||
config.data_source.position.read_timeout_ms;
|
||||
dataSourceConfig.position.auth.username =
|
||||
config.data_source.position.auth.username;
|
||||
dataSourceConfig.position.auth.password =
|
||||
config.data_source.position.auth.password;
|
||||
dataSourceConfig.position.auth.auth_path =
|
||||
config.data_source.position.auth.auth_path;
|
||||
dataSourceConfig.position.auth.auth_required =
|
||||
config.data_source.position.auth.auth_required;
|
||||
|
||||
// 转换无人车数据源配置
|
||||
dataSourceConfig.vehicle.host = config.data_source.vehicle.host;
|
||||
dataSourceConfig.vehicle.port = config.data_source.vehicle.port;
|
||||
dataSourceConfig.vehicle.status_path = config.data_source.vehicle.status_path;
|
||||
dataSourceConfig.vehicle.command_path = config.data_source.vehicle.command_path;
|
||||
dataSourceConfig.vehicle.refresh_interval_ms = config.data_source.vehicle.refresh_interval_ms;
|
||||
dataSourceConfig.vehicle.status_path =
|
||||
config.data_source.vehicle.status_path;
|
||||
dataSourceConfig.vehicle.command_path =
|
||||
config.data_source.vehicle.command_path;
|
||||
dataSourceConfig.vehicle.refresh_interval_ms =
|
||||
config.data_source.vehicle.refresh_interval_ms;
|
||||
dataSourceConfig.vehicle.timeout_ms = config.data_source.vehicle.timeout_ms;
|
||||
dataSourceConfig.vehicle.read_timeout_ms = config.data_source.vehicle.read_timeout_ms;
|
||||
dataSourceConfig.vehicle.auth.username = config.data_source.vehicle.auth.username;
|
||||
dataSourceConfig.vehicle.auth.password = config.data_source.vehicle.auth.password;
|
||||
dataSourceConfig.vehicle.auth.auth_path = config.data_source.vehicle.auth.auth_path;
|
||||
dataSourceConfig.vehicle.auth.auth_required = config.data_source.vehicle.auth.auth_required;
|
||||
dataSourceConfig.vehicle.read_timeout_ms =
|
||||
config.data_source.vehicle.read_timeout_ms;
|
||||
dataSourceConfig.vehicle.auth.username =
|
||||
config.data_source.vehicle.auth.username;
|
||||
dataSourceConfig.vehicle.auth.password =
|
||||
config.data_source.vehicle.auth.password;
|
||||
dataSourceConfig.vehicle.auth.auth_path =
|
||||
config.data_source.vehicle.auth.auth_path;
|
||||
dataSourceConfig.vehicle.auth.auth_required =
|
||||
config.data_source.vehicle.auth.auth_required;
|
||||
|
||||
// 转换红绿灯数据源配置
|
||||
dataSourceConfig.traffic_light.host = config.data_source.traffic_light.host;
|
||||
dataSourceConfig.traffic_light.port = config.data_source.traffic_light.port;
|
||||
dataSourceConfig.traffic_light.signal_path = config.data_source.traffic_light.signal_path;
|
||||
dataSourceConfig.traffic_light.refresh_interval_ms = config.data_source.traffic_light.refresh_interval_ms;
|
||||
dataSourceConfig.traffic_light.timeout_ms = config.data_source.traffic_light.timeout_ms;
|
||||
dataSourceConfig.traffic_light.read_timeout_ms = config.data_source.traffic_light.read_timeout_ms;
|
||||
dataSourceConfig.traffic_light.auth.username = config.data_source.traffic_light.auth.username;
|
||||
dataSourceConfig.traffic_light.auth.password = config.data_source.traffic_light.auth.password;
|
||||
dataSourceConfig.traffic_light.auth.auth_path = config.data_source.traffic_light.auth.auth_path;
|
||||
dataSourceConfig.traffic_light.auth.auth_required = config.data_source.traffic_light.auth.auth_required;
|
||||
dataSourceConfig.traffic_light.signal_path =
|
||||
config.data_source.traffic_light.signal_path;
|
||||
dataSourceConfig.traffic_light.refresh_interval_ms =
|
||||
config.data_source.traffic_light.refresh_interval_ms;
|
||||
dataSourceConfig.traffic_light.timeout_ms =
|
||||
config.data_source.traffic_light.timeout_ms;
|
||||
dataSourceConfig.traffic_light.read_timeout_ms =
|
||||
config.data_source.traffic_light.read_timeout_ms;
|
||||
dataSourceConfig.traffic_light.auth.username =
|
||||
config.data_source.traffic_light.auth.username;
|
||||
dataSourceConfig.traffic_light.auth.password =
|
||||
config.data_source.traffic_light.auth.password;
|
||||
dataSourceConfig.traffic_light.auth.auth_path =
|
||||
config.data_source.traffic_light.auth.auth_path;
|
||||
dataSourceConfig.traffic_light.auth.auth_required =
|
||||
config.data_source.traffic_light.auth.auth_required;
|
||||
|
||||
return dataSourceConfig;
|
||||
}
|
||||
@ -1,9 +1,9 @@
|
||||
#include "AirportBounds.h"
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <fstream>
|
||||
#include <filesystem>
|
||||
#include "utils/Logger.h"
|
||||
#include <cmath>
|
||||
#include <filesystem>
|
||||
#include <fstream>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
using json = nlohmann::json;
|
||||
|
||||
@ -18,7 +18,8 @@ void AirportBounds::loadConfig(const std::string& configFile) {
|
||||
// 检查文件是否存在
|
||||
if (!std::filesystem::exists(configFile)) {
|
||||
Logger::error("配置文件不存在: ", configFile);
|
||||
Logger::error("当前工作目录: ", std::filesystem::current_path().string());
|
||||
Logger::error("当前工作目录: ",
|
||||
std::filesystem::current_path().string());
|
||||
throw std::runtime_error("配置文件不存在: " + configFile);
|
||||
}
|
||||
|
||||
@ -40,7 +41,8 @@ void AirportBounds::loadConfig(const std::string& configFile) {
|
||||
auto& airport = j["airport"];
|
||||
if (airport.contains("rotation_angle")) {
|
||||
// 将角度转换为弧度
|
||||
rotationAngle_ = airport["rotation_angle"].get<double>() * M_PI / 180.0;
|
||||
rotationAngle_ =
|
||||
airport["rotation_angle"].get<double>() * M_PI / 180.0;
|
||||
}
|
||||
|
||||
if (airport.contains("reference_point")) {
|
||||
@ -50,12 +52,10 @@ void AirportBounds::loadConfig(const std::string& configFile) {
|
||||
|
||||
// 加载机场边界
|
||||
auto& airportBounds = j["airport"]["bounds"];
|
||||
airportBounds_ = {
|
||||
airportBounds["x"].get<double>(),
|
||||
airportBounds_ = { airportBounds["x"].get<double>(),
|
||||
airportBounds["y"].get<double>(),
|
||||
airportBounds["width"].get<double>(),
|
||||
airportBounds["height"].get<double>()
|
||||
};
|
||||
airportBounds["height"].get<double>() };
|
||||
|
||||
// 检查 areas 字段
|
||||
if (!j.contains("areas")) {
|
||||
@ -65,12 +65,18 @@ void AirportBounds::loadConfig(const std::string& configFile) {
|
||||
// 加载各区域配置
|
||||
for (const auto& [key, value] : j["areas"].items()) {
|
||||
AreaType type;
|
||||
if (key == "runway") type = AreaType::RUNWAY;
|
||||
else if (key == "taxiway") type = AreaType::TAXIWAY;
|
||||
else if (key == "gate") type = AreaType::GATE;
|
||||
else if (key == "service") type = AreaType::SERVICE;
|
||||
else if (key == "test_zone") type = AreaType::TEST_ZONE;
|
||||
else continue;
|
||||
if (key == "runway")
|
||||
type = AreaType::RUNWAY;
|
||||
else if (key == "taxiway")
|
||||
type = AreaType::TAXIWAY;
|
||||
else if (key == "gate")
|
||||
type = AreaType::GATE;
|
||||
else if (key == "service")
|
||||
type = AreaType::SERVICE;
|
||||
else if (key == "test_zone")
|
||||
type = AreaType::TEST_ZONE;
|
||||
else
|
||||
continue;
|
||||
|
||||
// 检查必要的字段
|
||||
if (!value.contains("bounds") || !value.contains("config")) {
|
||||
@ -80,11 +86,8 @@ void AirportBounds::loadConfig(const std::string& configFile) {
|
||||
// 加载区域边界
|
||||
auto& bounds = value["bounds"];
|
||||
areaBounds_[type] = {
|
||||
bounds["x"].get<double>(),
|
||||
bounds["y"].get<double>(),
|
||||
bounds["width"].get<double>(),
|
||||
bounds["height"].get<double>()
|
||||
};
|
||||
bounds["x"].get<double>(), bounds["y"].get<double>(),
|
||||
bounds["width"].get<double>(), bounds["height"].get<double>() };
|
||||
|
||||
// 加载区域配置
|
||||
auto& config = value["config"];
|
||||
@ -95,34 +98,26 @@ void AirportBounds::loadConfig(const std::string& configFile) {
|
||||
RadiusConfig collision_config = {
|
||||
collision_radius["aircraft"].get<double>(),
|
||||
collision_radius["special"].get<double>(),
|
||||
collision_radius["unmanned"].get<double>()
|
||||
};
|
||||
collision_radius["unmanned"].get<double>() };
|
||||
|
||||
RadiusConfig warning_config = {
|
||||
warning_zone_radius["aircraft"].get<double>(),
|
||||
warning_zone_radius["special"].get<double>(),
|
||||
warning_zone_radius["unmanned"].get<double>()
|
||||
};
|
||||
warning_zone_radius["unmanned"].get<double>() };
|
||||
|
||||
RadiusConfig alert_config = {
|
||||
alert_zone_radius["aircraft"].get<double>(),
|
||||
alert_zone_radius["special"].get<double>(),
|
||||
alert_zone_radius["unmanned"].get<double>()
|
||||
};
|
||||
alert_zone_radius["unmanned"].get<double>() };
|
||||
|
||||
areaConfigs_[type] = {
|
||||
collision_config,
|
||||
areaConfigs_[type] = { collision_config,
|
||||
config["height_threshold"].get<double>(),
|
||||
warning_config,
|
||||
alert_config
|
||||
};
|
||||
warning_config, alert_config };
|
||||
}
|
||||
}
|
||||
catch (const json::exception& e) {
|
||||
} catch (const json::exception& e) {
|
||||
Logger::error("JSON解析错误: ", e.what());
|
||||
throw;
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
} catch (const std::exception& e) {
|
||||
Logger::error("加载配置文件失败: ", e.what());
|
||||
throw;
|
||||
}
|
||||
@ -138,10 +133,8 @@ Vector2D AirportBounds::toAirportCoordinate(const Vector2D& point) const {
|
||||
double sin_angle = std::sin(rotationAngle_);
|
||||
|
||||
// 3. 返回机场坐标系中的坐标(逆时针旋转)
|
||||
Vector2D result{
|
||||
dx * cos_angle - dy * sin_angle,
|
||||
dx * sin_angle + dy * cos_angle
|
||||
};
|
||||
Vector2D result{ dx * cos_angle - dy * sin_angle,
|
||||
dx * sin_angle + dy * cos_angle };
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -173,7 +166,8 @@ bool AirportBounds::isPointInBounds(const Vector2D& position) const {
|
||||
return result;
|
||||
}
|
||||
|
||||
bool AirportBounds::isPointInArea(const Vector2D& position, AreaType areaType) const {
|
||||
bool AirportBounds::isPointInArea(const Vector2D& position,
|
||||
AreaType areaType) const {
|
||||
// 获取区域定义
|
||||
auto it = areaBounds_.find(areaType);
|
||||
if (it == areaBounds_.end()) {
|
||||
|
||||
@ -14,8 +14,8 @@ void SystemConfig::load(const std::string& filename) {
|
||||
nlohmann::from_json(j, *this);
|
||||
|
||||
Logger::info("Loaded system configuration from ", filename);
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
throw std::runtime_error("Failed to load config: " + std::string(e.what()));
|
||||
} catch (const std::exception& e) {
|
||||
throw std::runtime_error("Failed to load config: " +
|
||||
std::string(e.what()));
|
||||
}
|
||||
}
|
||||
@ -40,8 +40,7 @@ bool System::initialize() {
|
||||
// 初始化全局坐标转换器
|
||||
CoordinateConverter::instance().setReferencePoint(
|
||||
system_config.airport.reference_point.latitude,
|
||||
system_config.airport.reference_point.longitude
|
||||
);
|
||||
system_config.airport.reference_point.longitude);
|
||||
|
||||
// 加载路口配置
|
||||
intersection_config_ = IntersectionConfig::load("config/intersections.json");
|
||||
@ -49,9 +48,7 @@ bool System::initialize() {
|
||||
|
||||
// 初始化 WebSocket 服务器
|
||||
ws_server_ = std::make_unique<network::WebSocketServer>(system_config.websocket.port);
|
||||
ws_thread_ = std::thread([this]() {
|
||||
ws_server_->start();
|
||||
});
|
||||
ws_thread_ = std::thread([this]() { ws_server_->start(); });
|
||||
|
||||
// 加载机场区域配置
|
||||
airportBounds_ = std::make_unique<AirportBounds>("config/airport_bounds.json");
|
||||
@ -68,14 +65,12 @@ bool System::initialize() {
|
||||
// 加载告警配置
|
||||
WarnConfig warnConfig{
|
||||
system_config.warning.warning_interval_ms,
|
||||
system_config.warning.log_interval_ms
|
||||
};
|
||||
system_config.warning.log_interval_ms };
|
||||
|
||||
// 创建数据采集器并初始化
|
||||
dataCollector_ = std::make_unique<DataCollector>(*airportBounds_);
|
||||
return dataCollector_->initialize(system_config.data_source, warnConfig);
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
} catch (const std::exception& e) {
|
||||
Logger::error("Failed to initialize system: ", e.what());
|
||||
return false;
|
||||
}
|
||||
@ -93,8 +88,7 @@ void System::initializeSafetyZones() {
|
||||
// 获取路口中心点的地理坐标
|
||||
Vector2D center = CoordinateConverter::instance().toLocalXY(
|
||||
intersection.position.latitude,
|
||||
intersection.position.longitude
|
||||
);
|
||||
intersection.position.longitude);
|
||||
|
||||
// 创建安全区
|
||||
auto safetyZone = std::make_unique<SafetyZone>(
|
||||
@ -203,7 +197,8 @@ void System::processLoop() {
|
||||
|
||||
// 检查安全区更新
|
||||
auto safety_zone_elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
now - last_safety_zone_update).count();
|
||||
now - last_safety_zone_update)
|
||||
.count();
|
||||
|
||||
if (safety_zone_elapsed >= SystemConfig::instance().collision_detection.update_interval_ms) {
|
||||
updateSafetyZoneStates(objects);
|
||||
@ -255,8 +250,7 @@ void System::processLoop() {
|
||||
// 等待下一次处理
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(
|
||||
SystemConfig::instance().collision_detection.update_interval_ms));
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
} catch (const std::exception& e) {
|
||||
Logger::error("处理循环发生错误: ", e.what());
|
||||
}
|
||||
}
|
||||
@ -308,14 +302,14 @@ void System::checkUnmannedVehicleSafetyZones(
|
||||
risk.minDistance = distance;
|
||||
risk.relativeSpeed = std::sqrt(
|
||||
std::pow(obj->speed * std::cos(obj->heading) -
|
||||
vehicle.speed * std::cos(vehicle.heading), 2) +
|
||||
vehicle.speed * std::cos(vehicle.heading),
|
||||
2) +
|
||||
std::pow(obj->speed * std::sin(obj->heading) -
|
||||
vehicle.speed * std::sin(vehicle.heading), 2)
|
||||
);
|
||||
vehicle.speed * std::sin(vehicle.heading),
|
||||
2));
|
||||
risk.relativeMotion = {
|
||||
obj->position.x - vehicle.position.x,
|
||||
obj->position.y - vehicle.position.y
|
||||
};
|
||||
obj->position.y - vehicle.position.y };
|
||||
|
||||
detectedRisks.push_back(risk);
|
||||
|
||||
@ -364,11 +358,10 @@ void System::processCollisions(
|
||||
VehicleCommand cmd;
|
||||
cmd.vehicleId = vehicleId;
|
||||
cmd.type = risk.level == RiskLevel::CRITICAL ? CommandType::ALERT : CommandType::WARNING;
|
||||
cmd.reason = otherId.substr(0, 2) == "AC" ?
|
||||
CommandReason::AIRCRAFT_CROSSING :
|
||||
CommandReason::SPECIAL_VEHICLE;
|
||||
cmd.reason = otherId.substr(0, 2) == "AC" ? CommandReason::AIRCRAFT_CROSSING : CommandReason::SPECIAL_VEHICLE;
|
||||
cmd.timestamp = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
std::chrono::system_clock::now().time_since_epoch()).count();
|
||||
std::chrono::system_clock::now().time_since_epoch())
|
||||
.count();
|
||||
|
||||
// 设置目标位置
|
||||
const MovingObject* target = findVehicle(otherId);
|
||||
@ -423,7 +416,8 @@ void System::processCollisions(
|
||||
cmd.type = CommandType::RESUME;
|
||||
cmd.reason = CommandReason::RESUME_TRAFFIC;
|
||||
cmd.timestamp = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
std::chrono::system_clock::now().time_since_epoch()).count();
|
||||
std::chrono::system_clock::now().time_since_epoch())
|
||||
.count();
|
||||
|
||||
broadcastVehicleCommand(cmd);
|
||||
controllableVehicles_.sendCommand(vehicleId, cmd);
|
||||
@ -455,13 +449,9 @@ void System::broadcastPositionUpdate(const MovingObject& obj) {
|
||||
{"object_id", msg.objectId},
|
||||
{"object_type", msg.objectType},
|
||||
{"timestamp", msg.timestamp},
|
||||
{"position", {
|
||||
{"longitude", msg.longitude},
|
||||
{"latitude", msg.latitude}
|
||||
}},
|
||||
{"position", {{"longitude", msg.longitude}, {"latitude", msg.latitude}}},
|
||||
{"heading", msg.heading},
|
||||
{"speed", msg.speed}
|
||||
};
|
||||
{"speed", msg.speed} };
|
||||
|
||||
ws_server_->broadcast(j.dump());
|
||||
Logger::debug("广播位置更新: id=", msg.objectId,
|
||||
@ -484,16 +474,14 @@ void System::broadcastTrafficLightStatus(const TrafficLightSignal& signal) {
|
||||
{"type", "traffic_light_status"},
|
||||
{"id", signal.trafficLightId},
|
||||
{"status", static_cast<int>(signal.status)},
|
||||
{"timestamp", signal.timestamp}
|
||||
};
|
||||
{"timestamp", signal.timestamp} };
|
||||
|
||||
// 添加路口信息
|
||||
if (intersection) {
|
||||
j["intersection"] = intersection->id;
|
||||
j["position"] = {
|
||||
{"longitude", intersection->position.longitude},
|
||||
{"latitude", intersection->position.latitude}
|
||||
};
|
||||
{"latitude", intersection->position.latitude} };
|
||||
}
|
||||
|
||||
ws_server_->broadcast(j.dump());
|
||||
@ -507,9 +495,12 @@ void System::broadcastTrafficLightStatus(const TrafficLightSignal& signal) {
|
||||
|
||||
std::string getRiskLevelString(RiskLevel level) {
|
||||
switch (level) {
|
||||
case RiskLevel::CRITICAL: return "critical";
|
||||
case RiskLevel::WARNING: return "warning";
|
||||
default: return "none";
|
||||
case RiskLevel::CRITICAL:
|
||||
return "critical";
|
||||
case RiskLevel::WARNING:
|
||||
return "warning";
|
||||
default:
|
||||
return "none";
|
||||
}
|
||||
}
|
||||
|
||||
@ -527,8 +518,8 @@ void System::broadcastCollisionWarning(const CollisionRisk& risk) {
|
||||
{"relativeSpeed", risk.relativeSpeed},
|
||||
{"warningLevel", getRiskLevelString(risk.level)},
|
||||
{"timestamp", std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
std::chrono::system_clock::now().time_since_epoch()).count()}
|
||||
};
|
||||
std::chrono::system_clock::now().time_since_epoch())
|
||||
.count()} };
|
||||
|
||||
// 广播冲突预警消息
|
||||
ws_server_->broadcast(j.dump());
|
||||
@ -563,27 +554,39 @@ void System::broadcastVehicleCommand(const VehicleCommand& cmd) {
|
||||
{"vehicleId", cmd.vehicleId},
|
||||
{"commandType", [&]() {
|
||||
switch (cmd.type) {
|
||||
case CommandType::SIGNAL: return "SIGNAL";
|
||||
case CommandType::ALERT: return "ALERT";
|
||||
case CommandType::WARNING: return "WARNING";
|
||||
case CommandType::RESUME: return "RESUME";
|
||||
case CommandType::PARKING: return "PARKING";
|
||||
default: return "UNKNOWN";
|
||||
case CommandType::SIGNAL:
|
||||
return "SIGNAL";
|
||||
case CommandType::ALERT:
|
||||
return "ALERT";
|
||||
case CommandType::WARNING:
|
||||
return "WARNING";
|
||||
case CommandType::RESUME:
|
||||
return "RESUME";
|
||||
case CommandType::PARKING:
|
||||
return "PARKING";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}()},
|
||||
{"reason", [&]() {
|
||||
switch (cmd.reason) {
|
||||
case CommandReason::TRAFFIC_LIGHT: return "TRAFFIC_LIGHT";
|
||||
case CommandReason::AIRCRAFT_CROSSING: return "AIRCRAFT_CROSSING";
|
||||
case CommandReason::SPECIAL_VEHICLE: return "SPECIAL_VEHICLE";
|
||||
case CommandReason::AIRCRAFT_PUSH: return "AIRCRAFT_PUSH";
|
||||
case CommandReason::RESUME_TRAFFIC: return "RESUME_TRAFFIC";
|
||||
case CommandReason::PARKING_SIDE: return "PARKING_SIDE";
|
||||
default: return "UNKNOWN";
|
||||
case CommandReason::TRAFFIC_LIGHT:
|
||||
return "TRAFFIC_LIGHT";
|
||||
case CommandReason::AIRCRAFT_CROSSING:
|
||||
return "AIRCRAFT_CROSSING";
|
||||
case CommandReason::SPECIAL_VEHICLE:
|
||||
return "SPECIAL_VEHICLE";
|
||||
case CommandReason::AIRCRAFT_PUSH:
|
||||
return "AIRCRAFT_PUSH";
|
||||
case CommandReason::RESUME_TRAFFIC:
|
||||
return "RESUME_TRAFFIC";
|
||||
case CommandReason::PARKING_SIDE:
|
||||
return "PARKING_SIDE";
|
||||
default:
|
||||
return "UNKNOWN";
|
||||
}
|
||||
}()},
|
||||
{"timestamp", cmd.timestamp}
|
||||
};
|
||||
{"timestamp", cmd.timestamp} };
|
||||
|
||||
// 添加可选字段
|
||||
if (cmd.type == CommandType::SIGNAL) {
|
||||
@ -636,8 +639,7 @@ void System::updateSafetyZoneStates(const std::vector<MovingObject*>& objects) {
|
||||
// 检查所有移动物体
|
||||
for (const auto& obj : objects) {
|
||||
Logger::debug("检查移动物体: id=", obj->id,
|
||||
", type=", obj->type == MovingObjectType::UNMANNED ? "无人车" :
|
||||
(obj->type == MovingObjectType::SPECIAL ? "特勤车" : "飞机"),
|
||||
", type=", obj->type == MovingObjectType::UNMANNED ? "无人车" : (obj->type == MovingObjectType::SPECIAL ? "特勤车" : "飞机"),
|
||||
", isAircraft=", obj->isAircraft(),
|
||||
", isSpecialVehicle=", obj->isSpecialVehicle(),
|
||||
", isUnmannedVehicle=", obj->isUnmannedVehicle());
|
||||
@ -684,11 +686,10 @@ bool System::handleSafetyZoneRisk(const Vehicle& vehicle,
|
||||
VehicleCommand cmd;
|
||||
cmd.vehicleId = vehicle.id;
|
||||
cmd.type = cmdType;
|
||||
cmd.reason = zone->getType() == SafetyZoneType::AIRCRAFT ?
|
||||
CommandReason::AIRCRAFT_CROSSING :
|
||||
CommandReason::SPECIAL_VEHICLE;
|
||||
cmd.reason = zone->getType() == SafetyZoneType::AIRCRAFT ? CommandReason::AIRCRAFT_CROSSING : CommandReason::SPECIAL_VEHICLE;
|
||||
cmd.timestamp = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
std::chrono::system_clock::now().time_since_epoch()).count();
|
||||
std::chrono::system_clock::now().time_since_epoch())
|
||||
.count();
|
||||
|
||||
// 查找触发安全区的目标物体
|
||||
const MovingObject* target = nullptr;
|
||||
@ -712,8 +713,7 @@ bool System::handleSafetyZoneRisk(const Vehicle& vehicle,
|
||||
// 计算相对速度
|
||||
cmd.relativeSpeed = std::sqrt(
|
||||
(target->position.x - vehicle.position.x) * (target->position.x - vehicle.position.x) +
|
||||
(target->position.y - vehicle.position.y) * (target->position.y - vehicle.position.y)
|
||||
);
|
||||
(target->position.y - vehicle.position.y) * (target->position.y - vehicle.position.y));
|
||||
cmd.relativeMotionX = rel_dx;
|
||||
cmd.relativeMotionY = rel_dy;
|
||||
cmd.minDistance = distance;
|
||||
|
||||
@ -1,15 +1,14 @@
|
||||
#include "CollisionDetector.h"
|
||||
|
||||
#include "utils/Logger.h"
|
||||
#include "config/SystemConfig.h"
|
||||
#include "utils/Logger.h"
|
||||
#include <cmath>
|
||||
#include <unordered_set>
|
||||
|
||||
CollisionDetector::CollisionDetector(const AirportBounds& bounds, const ControllableVehicles& controllableVehicles)
|
||||
: airportBounds_(bounds)
|
||||
, vehicleTree_(bounds.getAirportBounds(), 8) // 使用机场总边界初始化四叉树
|
||||
, controllableVehicles_(&controllableVehicles) {
|
||||
|
||||
: airportBounds_(bounds),
|
||||
vehicleTree_(bounds.getAirportBounds(), 8), // 使用机场总边界初始化四叉树
|
||||
controllableVehicles_(&controllableVehicles) {
|
||||
// 记录初始化信息
|
||||
const auto& airportBounds = bounds.getAirportBounds();
|
||||
}
|
||||
@ -29,15 +28,15 @@ void CollisionDetector::updateTraffic(const std::vector<Aircraft>& aircraft,
|
||||
for (const auto& vehicle : vehicles) {
|
||||
// 首先检查车辆是否在机场边界内
|
||||
if (!airportBounds_.isPointInBounds(vehicle.position)) {
|
||||
Logger::error("车辆在机场边界外: id=", vehicle.id,
|
||||
", position=(", vehicle.position.x,
|
||||
",", vehicle.position.y, ")");
|
||||
Logger::error("车辆在机场边界外: id=", vehicle.id, ", position=(",
|
||||
vehicle.position.x, ",", vehicle.position.y, ")");
|
||||
continue; // 跳过边界外的车辆
|
||||
}
|
||||
|
||||
// 根据配置设置车辆类型
|
||||
Vehicle updatedVehicle = vehicle;
|
||||
const auto* config = controllableVehicles_->findVehicle(vehicle.vehicleNo);
|
||||
const auto* config =
|
||||
controllableVehicles_->findVehicle(vehicle.vehicleNo);
|
||||
if (config) {
|
||||
if (config->type == "UNMANNED") {
|
||||
updatedVehicle.type = MovingObjectType::UNMANNED;
|
||||
@ -54,24 +53,28 @@ void CollisionDetector::updateTraffic(const std::vector<Aircraft>& aircraft,
|
||||
// 插入四叉树
|
||||
try {
|
||||
Logger::debug("尝试插入车辆: id=", updatedVehicle.id,
|
||||
", position=(", updatedVehicle.position.x, ",", updatedVehicle.position.y, ")",
|
||||
", type=", updatedVehicle.isControllable ? "UNMANNED" : "SPECIAL");
|
||||
", position=(", updatedVehicle.position.x, ",",
|
||||
updatedVehicle.position.y, ")", ", type=",
|
||||
updatedVehicle.isControllable ? "UNMANNED"
|
||||
: "SPECIAL");
|
||||
vehicleTree_.insert(updatedVehicle);
|
||||
++validVehicles;
|
||||
Logger::debug("成功插入车辆: id=", updatedVehicle.id);
|
||||
} catch (const std::exception& e) {
|
||||
Logger::error("无法插入车辆到四叉树: id=", updatedVehicle.id, ", error=", e.what());
|
||||
Logger::error("无法插入车辆到四叉树: id=", updatedVehicle.id,
|
||||
", error=", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
// 记录更新后的状态
|
||||
auto bounds = vehicleTree_.getBounds();
|
||||
Logger::debug("四叉树边界: min=(", bounds.x, ",", bounds.y,
|
||||
"), max=(", bounds.x + bounds.width, ",", bounds.y + bounds.height, ")");
|
||||
Logger::debug("四叉树边界: min=(", bounds.x, ",", bounds.y, "), max=(",
|
||||
bounds.x + bounds.width, ",", bounds.y + bounds.height, ")");
|
||||
auto allVehicles = vehicleTree_.queryRange(bounds);
|
||||
for (const auto& vehicle : allVehicles) {
|
||||
Logger::debug("查询到车辆: id=", vehicle.id,
|
||||
", position=(", vehicle.position.x, ",", vehicle.position.y, ")",
|
||||
Logger::debug(
|
||||
"查询到车辆: id=", vehicle.id, ", position=(", vehicle.position.x,
|
||||
",", vehicle.position.y, ")",
|
||||
", type=", vehicle.isControllable ? "UNMANNED" : "SPECIAL");
|
||||
}
|
||||
Logger::debug("交通数据更新完成: 有效车辆数量=", validVehicles,
|
||||
@ -82,7 +85,8 @@ std::vector<CollisionRisk> CollisionDetector::detectCollisions() {
|
||||
std::vector<CollisionRisk> risks;
|
||||
|
||||
// 获取配置参数
|
||||
const auto& predictionConfig = SystemConfig::instance().collision_detection.prediction;
|
||||
const auto& predictionConfig =
|
||||
SystemConfig::instance().collision_detection.prediction;
|
||||
|
||||
// 获取所有车辆
|
||||
auto allVehicles = vehicleTree_.queryRange(vehicleTree_.getBounds());
|
||||
@ -96,7 +100,8 @@ std::vector<CollisionRisk> CollisionDetector::detectCollisions() {
|
||||
}
|
||||
|
||||
// 记录当前检测到的冲突对
|
||||
std::unordered_set<std::pair<std::string, std::string>, CollisionPairHash> currentCollisions;
|
||||
std::unordered_set<std::pair<std::string, std::string>, CollisionPairHash>
|
||||
currentCollisions;
|
||||
|
||||
// 检测可控车辆与航空器的碰撞
|
||||
for (const auto& aircraft : aircraftData_) {
|
||||
@ -111,19 +116,20 @@ std::vector<CollisionRisk> CollisionDetector::detectCollisions() {
|
||||
|
||||
// 检查是否存在未解除的冲突记录
|
||||
auto it = collisionRecords_.find(collisionKey);
|
||||
bool hasUnresolvedConflict = (it != collisionRecords_.end() && !it->second.resolved);
|
||||
bool hasUnresolvedConflict =
|
||||
(it != collisionRecords_.end() && !it->second.resolved);
|
||||
|
||||
if (hasUnresolvedConflict) {
|
||||
Logger::debug("存在未解除的冲突记录: obj1=", aircraft.id,
|
||||
", obj2=", vehicle.id,
|
||||
", maxLevel=", static_cast<int>(it->second.maxLevel),
|
||||
", obj2=", vehicle.id, ", maxLevel=",
|
||||
static_cast<int>(it->second.maxLevel),
|
||||
", collisionPoint=(", it->second.collisionPoint.x,
|
||||
",", it->second.collisionPoint.y, ")");
|
||||
}
|
||||
|
||||
// 检测碰撞
|
||||
auto collisionResult = checkCollision(
|
||||
aircraft, vehicle, predictionConfig.time_window);
|
||||
auto collisionResult =
|
||||
checkCollision(aircraft, vehicle, predictionConfig.time_window);
|
||||
|
||||
// 计算相对运动
|
||||
MovementVector av(aircraft.speed, aircraft.heading);
|
||||
@ -138,12 +144,9 @@ std::vector<CollisionRisk> CollisionDetector::detectCollisions() {
|
||||
}
|
||||
|
||||
// 评估风险等级
|
||||
auto [level, zoneType] = evaluateRisk(
|
||||
collisionResult,
|
||||
aircraft.position,
|
||||
aircraft.type,
|
||||
vehicle.type
|
||||
);
|
||||
auto [level, zoneType] =
|
||||
evaluateRisk(collisionResult, aircraft.position, aircraft.type,
|
||||
vehicle.type);
|
||||
|
||||
if (level != RiskLevel::NONE) {
|
||||
// 记录或更新冲突信息
|
||||
@ -151,33 +154,34 @@ std::vector<CollisionRisk> CollisionDetector::detectCollisions() {
|
||||
if (!record.resolved) {
|
||||
// 更新已存在的冲突记录
|
||||
record.maxLevel = std::max(record.maxLevel, level);
|
||||
record.collisionPoint = collisionResult.collisionPoint; // 更新冲突点
|
||||
record.collisionPoint =
|
||||
collisionResult.collisionPoint; // 更新冲突点
|
||||
Logger::debug("更新冲突记录: obj1=", aircraft.id,
|
||||
", obj2=", vehicle.id,
|
||||
", maxLevel=", static_cast<int>(record.maxLevel),
|
||||
", obj2=", vehicle.id, ", maxLevel=",
|
||||
static_cast<int>(record.maxLevel),
|
||||
", collisionPoint=(", record.collisionPoint.x,
|
||||
",", record.collisionPoint.y, ")");
|
||||
} else {
|
||||
// 创建新的冲突记录
|
||||
record = {
|
||||
collisionResult.collisionPoint, // 使用当前检测到的冲突点
|
||||
std::chrono::system_clock::now().time_since_epoch().count(),
|
||||
level,
|
||||
false
|
||||
};
|
||||
record = { collisionResult
|
||||
.collisionPoint, // 使用当前检测到的冲突点
|
||||
std::chrono::system_clock::now()
|
||||
.time_since_epoch()
|
||||
.count(),
|
||||
level, false };
|
||||
Logger::debug("创建新的冲突记录: obj1=", aircraft.id,
|
||||
", obj2=", vehicle.id,
|
||||
", level=", static_cast<int>(level),
|
||||
", collisionPoint=(", collisionResult.collisionPoint.x,
|
||||
",", collisionResult.collisionPoint.y, ")");
|
||||
", collisionPoint=(",
|
||||
collisionResult.collisionPoint.x, ",",
|
||||
collisionResult.collisionPoint.y, ")");
|
||||
}
|
||||
|
||||
// 添加到当前冲突集合
|
||||
currentCollisions.insert(collisionKey);
|
||||
|
||||
// 添加到风险列表
|
||||
risks.push_back({
|
||||
aircraft.id,
|
||||
risks.push_back({ aircraft.id,
|
||||
vehicle.id,
|
||||
level,
|
||||
collisionResult.minDistance,
|
||||
@ -186,25 +190,24 @@ std::vector<CollisionRisk> CollisionDetector::detectCollisions() {
|
||||
{vx, vy},
|
||||
zoneType,
|
||||
collisionResult.timeToCollision,
|
||||
collisionResult.collisionPoint
|
||||
});
|
||||
collisionResult.collisionPoint });
|
||||
|
||||
Logger::debug("检测到碰撞风险: obj1=", aircraft.id,
|
||||
", obj2=", vehicle.id,
|
||||
Logger::debug(
|
||||
"检测到碰撞风险: obj1=", aircraft.id, ", obj2=", vehicle.id,
|
||||
", minDistance=", collisionResult.minDistance, "m",
|
||||
", timeToCollision=", collisionResult.timeToCollision, "s",
|
||||
", level=", static_cast<int>(level));
|
||||
} else if (hasUnresolvedConflict) {
|
||||
// 检查是否满足解除条件
|
||||
if (checkCollisionResolved(aircraft, vehicle, it->second, safeDistance)) {
|
||||
if (checkCollisionResolved(aircraft, vehicle, it->second,
|
||||
safeDistance)) {
|
||||
it->second.resolved = true;
|
||||
Logger::debug("冲突已解除: obj1=", aircraft.id,
|
||||
", obj2=", vehicle.id);
|
||||
} else {
|
||||
// 虽然当前没有检测到风险,但由于未满足解除条件,继续保持原有风险等级
|
||||
currentCollisions.insert(collisionKey);
|
||||
risks.push_back({
|
||||
aircraft.id,
|
||||
risks.push_back({ aircraft.id,
|
||||
vehicle.id,
|
||||
it->second.maxLevel,
|
||||
collisionResult.minDistance,
|
||||
@ -213,13 +216,14 @@ std::vector<CollisionRisk> CollisionDetector::detectCollisions() {
|
||||
{vx, vy},
|
||||
zoneType,
|
||||
collisionResult.timeToCollision,
|
||||
it->second.collisionPoint
|
||||
});
|
||||
Logger::debug("保持原有风险等级: obj1=", aircraft.id,
|
||||
it->second.collisionPoint });
|
||||
Logger::debug(
|
||||
"保持原有风险等级: obj1=", aircraft.id,
|
||||
", obj2=", vehicle.id,
|
||||
", maxLevel=", static_cast<int>(it->second.maxLevel),
|
||||
", minDistance=", collisionResult.minDistance, "m",
|
||||
", timeToCollision=", collisionResult.timeToCollision, "s");
|
||||
", timeToCollision=", collisionResult.timeToCollision,
|
||||
"s");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -242,42 +246,45 @@ bool CollisionDetector::checkCollisionResolved(const MovingObject& obj1,
|
||||
const CollisionRecord& record,
|
||||
double safeDistance) const {
|
||||
// 计算航空器与冲突点的距离
|
||||
double dist1 = std::sqrt(
|
||||
std::pow(obj1.position.x - record.collisionPoint.x, 2) +
|
||||
std::pow(obj1.position.y - record.collisionPoint.y, 2)
|
||||
);
|
||||
double dist1 =
|
||||
std::sqrt(std::pow(obj1.position.x - record.collisionPoint.x, 2) +
|
||||
std::pow(obj1.position.y - record.collisionPoint.y, 2));
|
||||
|
||||
double dist2 = std::sqrt(
|
||||
std::pow(obj2.position.x - record.collisionPoint.x, 2) +
|
||||
std::pow(obj2.position.y - record.collisionPoint.y, 2)
|
||||
);
|
||||
double dist2 =
|
||||
std::sqrt(std::pow(obj2.position.x - record.collisionPoint.x, 2) +
|
||||
std::pow(obj2.position.y - record.collisionPoint.y, 2));
|
||||
|
||||
// 计算冲突点相对于航空器的位置向量与航空器航向的夹角
|
||||
double dx = record.collisionPoint.x - obj1.position.x; // 冲突点相对于航空器的向量
|
||||
double dx =
|
||||
record.collisionPoint.x - obj1.position.x; // 冲突点相对于航空器的向量
|
||||
double dy = record.collisionPoint.y - obj1.position.y;
|
||||
double pointAngle = std::atan2(dy, dx) * 180.0 / M_PI; // 冲突点相对于航空器的角度
|
||||
double angleDiff = normalizeAngle(pointAngle - (90.0 - obj1.heading)); // 修正航向角
|
||||
double pointAngle =
|
||||
std::atan2(dy, dx) * 180.0 / M_PI; // 冲突点相对于航空器的角度
|
||||
double angleDiff =
|
||||
normalizeAngle(pointAngle - (90.0 - obj1.heading)); // 修正航向角
|
||||
|
||||
Logger::debug("检查冲突解除条件: 航空器位置=(", obj1.position.x, ",", obj1.position.y,
|
||||
"), 冲突点=(", record.collisionPoint.x, ",", record.collisionPoint.y,
|
||||
"), 航向=", obj1.heading,
|
||||
", 冲突点角度=", pointAngle,
|
||||
", 角度差=", angleDiff,
|
||||
Logger::debug("检查冲突解除条件: 航空器位置=(", obj1.position.x, ",",
|
||||
obj1.position.y, "), 冲突点=(", record.collisionPoint.x, ",",
|
||||
record.collisionPoint.y, "), 航向=", obj1.heading,
|
||||
", 冲突点角度=", pointAngle, ", 角度差=", angleDiff,
|
||||
", 距离=", dist1);
|
||||
|
||||
// 判断航空器是否已经通过交叉点
|
||||
if (angleDiff > 90 && angleDiff < 270) {
|
||||
// 航空器已经通过交叉点,只要航空器离开冲突点的距离大于安全距离就可以解除
|
||||
Logger::debug("航空器已通过交叉点,航空器距离=", dist1, "m, 安全距离=", safeDistance, "m");
|
||||
Logger::debug("航空器已通过交叉点,航空器距离=", dist1,
|
||||
"m, 安全距离=", safeDistance, "m");
|
||||
return dist1 >= safeDistance;
|
||||
} else {
|
||||
// 航空器还未通过交叉点,需要两者都在安全距离外且预计不会碰撞
|
||||
auto collisionResult = checkCollision(obj1, obj2, 30.0); // 使用30秒的预测窗口
|
||||
auto collisionResult =
|
||||
checkCollision(obj1, obj2, 30.0); // 使用30秒的预测窗口
|
||||
bool willCollide = collisionResult.willCollide;
|
||||
bool bothOutside = (dist1 >= safeDistance && dist2 >= safeDistance);
|
||||
|
||||
Logger::debug("航空器未通过交叉点,航空器距离=", dist1, "m, 无人车距离=", dist2,
|
||||
"m, 安全距离=", safeDistance, "m, 预测碰撞=", willCollide ? "是" : "否");
|
||||
Logger::debug("航空器未通过交叉点,航空器距离=", dist1,
|
||||
"m, 无人车距离=", dist2, "m, 安全距离=", safeDistance,
|
||||
"m, 预测碰撞=", willCollide ? "是" : "否");
|
||||
|
||||
return !willCollide && bothOutside;
|
||||
}
|
||||
@ -285,10 +292,8 @@ bool CollisionDetector::checkCollisionResolved(const MovingObject& obj1,
|
||||
|
||||
// 统一的风险评估函数
|
||||
std::pair<RiskLevel, WarningZoneType> CollisionDetector::evaluateRisk(
|
||||
const CollisionResult& collisionResult,
|
||||
const Vector2D& position,
|
||||
MovingObjectType type1,
|
||||
MovingObjectType type2) const {
|
||||
const CollisionResult& collisionResult, const Vector2D& position,
|
||||
MovingObjectType type1, MovingObjectType type2) const {
|
||||
|
||||
// 取区域配置
|
||||
const auto& areaConfig = getCollisionParams(position);
|
||||
@ -312,8 +317,7 @@ std::pair<RiskLevel, WarningZoneType> CollisionDetector::evaluateRisk(
|
||||
}
|
||||
|
||||
// 修改日志,添加物体类型信息
|
||||
Logger::debug(
|
||||
"风险评估: 物体1类型=", static_cast<int>(type1),
|
||||
Logger::debug("风险评估: 物体1类型=", static_cast<int>(type1),
|
||||
", 物体2类型=", static_cast<int>(type2),
|
||||
", 当前距离=", collisionResult.distance,
|
||||
"m, 预测最小距离=", collisionResult.minDistance,
|
||||
@ -321,23 +325,20 @@ std::pair<RiskLevel, WarningZoneType> CollisionDetector::evaluateRisk(
|
||||
"m, 警报阈值=", thresholds.critical,
|
||||
"m, 预测碰撞=", collisionResult.willCollide ? "是" : "否",
|
||||
", 风险等级=", static_cast<int>(level),
|
||||
", 区域类型=", static_cast<int>(zoneType)
|
||||
);
|
||||
", 区域类型=", static_cast<int>(zoneType));
|
||||
|
||||
return { level, zoneType };
|
||||
}
|
||||
|
||||
// 统一的碰撞检测函数
|
||||
CollisionResult CollisionDetector::checkCollision(
|
||||
const MovingObject& obj1,
|
||||
CollisionResult CollisionDetector::checkCollision(const MovingObject& obj1,
|
||||
const MovingObject& obj2,
|
||||
double timeWindow) const {
|
||||
|
||||
// 添加物体信息日志
|
||||
Logger::debug(
|
||||
"检查碰撞: obj1[", obj1.id, "]=(", obj1.position.x, ",", obj1.position.y,
|
||||
"), obj2[", obj2.id, "]=(", obj2.position.x, ",", obj2.position.y, ")"
|
||||
);
|
||||
Logger::debug("检查碰撞: obj1[", obj1.id, "]=(", obj1.position.x, ",",
|
||||
obj1.position.y, "), obj2[", obj2.id, "]=(", obj2.position.x,
|
||||
",", obj2.position.y, ")");
|
||||
|
||||
// 获取区域配置
|
||||
const auto& areaConfig = getCollisionParams(obj1.position);
|
||||
@ -345,8 +346,10 @@ CollisionResult CollisionDetector::checkCollision(
|
||||
// 获取各自的碰撞半径和警告半径
|
||||
double radius1 = areaConfig.collision_radius.getRadius(obj1.type);
|
||||
double radius2 = areaConfig.collision_radius.getRadius(obj2.type);
|
||||
double warning_radius1 = areaConfig.warning_zone_radius.getRadius(obj1.type);
|
||||
double warning_radius2 = areaConfig.warning_zone_radius.getRadius(obj2.type);
|
||||
double warning_radius1 =
|
||||
areaConfig.warning_zone_radius.getRadius(obj1.type);
|
||||
double warning_radius2 =
|
||||
areaConfig.warning_zone_radius.getRadius(obj2.type);
|
||||
|
||||
// 计算当前距离
|
||||
double dx = obj2.position.x - obj1.position.x;
|
||||
@ -358,15 +361,21 @@ CollisionResult CollisionDetector::checkCollision(
|
||||
double speed2_calc = obj2.speed;
|
||||
|
||||
if (obj1.type == MovingObjectType::UNMANNED && speed1_calc < 0.1) {
|
||||
speed1_calc = SystemConfig::instance().collision_detection.prediction.min_unmanned_speed; // 使用配置的最低速度
|
||||
speed1_calc = SystemConfig::instance()
|
||||
.collision_detection.prediction
|
||||
.min_unmanned_speed; // 使用配置的最低速度
|
||||
}
|
||||
if (obj2.type == MovingObjectType::UNMANNED && speed2_calc < 0.1) {
|
||||
speed2_calc = SystemConfig::instance().collision_detection.prediction.min_unmanned_speed; // 使用配置的最低速度
|
||||
speed2_calc = SystemConfig::instance()
|
||||
.collision_detection.prediction
|
||||
.min_unmanned_speed; // 使用配置的最低速度
|
||||
}
|
||||
|
||||
// 计算速度分量
|
||||
double vx1 = speed1_calc * std::cos((90.0 - obj1.heading) * M_PI / 180.0); // x 方向
|
||||
double vy1 = speed1_calc * std::sin((90.0 - obj1.heading) * M_PI / 180.0); // y 方向
|
||||
double vx1 =
|
||||
speed1_calc * std::cos((90.0 - obj1.heading) * M_PI / 180.0); // x 方向
|
||||
double vy1 =
|
||||
speed1_calc * std::sin((90.0 - obj1.heading) * M_PI / 180.0); // y 方向
|
||||
double vx2 = speed2_calc * std::cos((90.0 - obj2.heading) * M_PI / 180.0);
|
||||
double vy2 = speed2_calc * std::sin((90.0 - obj2.heading) * M_PI / 180.0);
|
||||
|
||||
@ -380,11 +389,9 @@ CollisionResult CollisionDetector::checkCollision(
|
||||
}
|
||||
|
||||
// 否则进行碰撞检测
|
||||
return predictCircleBasedCollision(
|
||||
obj1.position, radius1, obj1.speed, obj1.heading,
|
||||
obj2.position, radius2, obj2.speed, obj2.heading,
|
||||
timeWindow
|
||||
);
|
||||
return predictCircleBasedCollision(obj1.position, radius1, obj1.speed,
|
||||
obj1.heading, obj2.position, radius2,
|
||||
obj2.speed, obj2.heading, timeWindow);
|
||||
}
|
||||
|
||||
CollisionResult CollisionDetector::predictCircleBasedCollision(
|
||||
@ -434,10 +441,8 @@ CollisionResult CollisionDetector::predictCircleBasedCollision(
|
||||
result.timeToCollision = 0.0;
|
||||
result.minDistance = current_distance;
|
||||
result.timeToMinDistance = 0.0;
|
||||
result.collisionPoint = {
|
||||
(pos1.x + pos2.x) / 2.0,
|
||||
(pos1.y + pos2.y) / 2.0
|
||||
};
|
||||
result.collisionPoint = { (pos1.x + pos2.x) / 2.0,
|
||||
(pos1.y + pos2.y) / 2.0 };
|
||||
result.object1State = CollisionObjectState(pos1, speed1, heading1);
|
||||
result.object2State = CollisionObjectState(pos2, speed2, heading2);
|
||||
}
|
||||
@ -456,12 +461,12 @@ CollisionResult CollisionDetector::predictCircleBasedCollision(
|
||||
result.timeToCollision = 0.0;
|
||||
result.minDistance = current_distance;
|
||||
result.timeToMinDistance = 0.0;
|
||||
result.collisionPoint = {
|
||||
(pos1.x + pos2.x) / 2.0,
|
||||
(pos1.y + pos2.y) / 2.0
|
||||
};
|
||||
result.object1State = CollisionObjectState(pos1, speed1, heading1);
|
||||
result.object2State = CollisionObjectState(pos2, speed2, heading2);
|
||||
result.collisionPoint = { (pos1.x + pos2.x) / 2.0,
|
||||
(pos1.y + pos2.y) / 2.0 };
|
||||
result.object1State =
|
||||
CollisionObjectState(pos1, speed1, heading1);
|
||||
result.object2State =
|
||||
CollisionObjectState(pos2, speed2, heading2);
|
||||
} else {
|
||||
result.timeToCollision = collision_distance / closing_speed;
|
||||
result.willCollide = result.timeToCollision <= timeWindow;
|
||||
@ -476,40 +481,40 @@ CollisionResult CollisionDetector::predictCircleBasedCollision(
|
||||
|
||||
// 计算物体1的碰撞位置(向前移动到碰撞点前方)
|
||||
Vector2D collision1 = {
|
||||
pos1.x + move_distance1 * std::sin(heading1 * M_PI / 180.0),
|
||||
pos1.y + move_distance1 * std::cos(heading1 * M_PI / 180.0)
|
||||
};
|
||||
pos1.x +
|
||||
move_distance1 * std::sin(heading1 * M_PI / 180.0),
|
||||
pos1.y +
|
||||
move_distance1 * std::cos(heading1 * M_PI / 180.0) };
|
||||
|
||||
// 计算物体2的碰撞位置(也是向前移动)
|
||||
Vector2D collision2 = {
|
||||
pos2.x + move_distance2 * std::sin(heading2 * M_PI / 180.0),
|
||||
pos2.y + move_distance2 * std::cos(heading2 * M_PI / 180.0)
|
||||
};
|
||||
pos2.x +
|
||||
move_distance2 * std::sin(heading2 * M_PI / 180.0),
|
||||
pos2.y +
|
||||
move_distance2 * std::cos(heading2 * M_PI / 180.0) };
|
||||
|
||||
// 碰撞点两个物体的中点
|
||||
result.collisionPoint = {
|
||||
(collision1.x + collision2.x) / 2.0,
|
||||
(collision1.y + collision2.y) / 2.0
|
||||
};
|
||||
(collision1.y + collision2.y) / 2.0 };
|
||||
|
||||
result.object1State = CollisionObjectState(collision1, speed1, heading1);
|
||||
result.object2State = CollisionObjectState(collision2, speed2, heading2);
|
||||
result.object1State =
|
||||
CollisionObjectState(collision1, speed1, heading1);
|
||||
result.object2State =
|
||||
CollisionObjectState(collision2, speed2, heading2);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
} else if (angle_diff > 15.0 && angle_diff < 165.0) { // 放宽交叉路径的角度范围
|
||||
} else if (angle_diff > 15.0 &&
|
||||
angle_diff < 165.0) { // 放宽交叉路径的角度范围
|
||||
result.type = CollisionType::CROSSING;
|
||||
|
||||
Logger::debug(
|
||||
"交叉路径检测: angle_diff=", angle_diff,
|
||||
", pos1=(", pos1.x, ",", pos1.y, ")",
|
||||
", pos2=(", pos2.x, ",", pos2.y, ")",
|
||||
", v1=(", vx1, ",", vy1, ")",
|
||||
", v2=(", vx2, ",", vy2, ")",
|
||||
", current_distance=", current_distance,
|
||||
", safe_distance=", safe_distance
|
||||
);
|
||||
Logger::debug("交叉路径检测: angle_diff=", angle_diff, ", pos1=(",
|
||||
pos1.x, ",", pos1.y, ")", ", pos2=(", pos2.x, ",", pos2.y,
|
||||
")", ", v1=(", vx1, ",", vy1, ")", ", v2=(", vx2, ",",
|
||||
vy2, ")", ", current_distance=", current_distance,
|
||||
", safe_distance=", safe_distance);
|
||||
|
||||
// 计算行列式 (v1 x v2)
|
||||
double det = vx1 * (-vy2) - (-vx2) * vy1;
|
||||
@ -524,67 +529,50 @@ CollisionResult CollisionDetector::predictCircleBasedCollision(
|
||||
double t1 = det1 / det; // 物体1的时间
|
||||
double t2 = det2 / det; // 物体2的时间
|
||||
|
||||
Logger::debug(
|
||||
"交叉路径检测: det1=", det1,
|
||||
", det2=", det2,
|
||||
", det=", det,
|
||||
", t1=", t1,
|
||||
", t2=", t2
|
||||
);
|
||||
Logger::debug("交叉路径检测: det1=", det1, ", det2=", det2,
|
||||
", det=", det, ", t1=", t1, ", t2=", t2);
|
||||
|
||||
// 计算相交点
|
||||
Vector2D intersection = {
|
||||
pos1.x + vx1 * t1,
|
||||
pos1.y + vy1 * t1
|
||||
};
|
||||
Vector2D intersection = { pos1.x + vx1 * t1, pos1.y + vy1 * t1 };
|
||||
|
||||
Logger::debug(
|
||||
"交叉路径检测: intersection=(", intersection.x, ",", intersection.y, ")",
|
||||
", t1=", t1,
|
||||
", t2=", t2
|
||||
);
|
||||
Logger::debug("交叉路径检测: intersection=(", intersection.x, ",",
|
||||
intersection.y, ")", ", t1=", t1, ", t2=", t2);
|
||||
|
||||
// 检查时间条件
|
||||
double first_arrival_time = std::min(t1, t2);
|
||||
double first_arrival_speed = (t1 < t2) ? speed1 : speed2;
|
||||
double time_threshold = safe_distance / first_arrival_speed;
|
||||
bool valid_time = (t1 >= 0 && t2 >= 0 &&
|
||||
std::max(t1, t2) <= timeWindow &&
|
||||
bool valid_time =
|
||||
(t1 >= 0 && t2 >= 0 && std::max(t1, t2) <= timeWindow &&
|
||||
std::abs(t1 - t2) <= time_threshold);
|
||||
|
||||
// 如果满足所有条件,则预测为碰撞
|
||||
if (valid_time) {
|
||||
// 计算实际碰撞点(在交点之前)
|
||||
double collision_distance = safe_distance;
|
||||
double collision_time = first_arrival_time - collision_distance / first_arrival_speed;
|
||||
double collision_time =
|
||||
first_arrival_time - collision_distance / first_arrival_speed;
|
||||
|
||||
if (collision_time < 0) {
|
||||
collision_time = 0;
|
||||
}
|
||||
|
||||
// 根据碰撞时间计算两个物体的位置
|
||||
Vector2D pos1_at_collision = {
|
||||
pos1.x + vx1 * collision_time,
|
||||
pos1.y + vy1 * collision_time
|
||||
};
|
||||
Vector2D pos1_at_collision = { pos1.x + vx1 * collision_time,
|
||||
pos1.y + vy1 * collision_time };
|
||||
|
||||
Vector2D pos2_at_collision = {
|
||||
pos2.x + vx2 * collision_time,
|
||||
pos2.y + vy2 * collision_time
|
||||
};
|
||||
Vector2D pos2_at_collision = { pos2.x + vx2 * collision_time,
|
||||
pos2.y + vy2 * collision_time };
|
||||
|
||||
// 碰撞点在两个物体位置的中点
|
||||
result.collisionPoint = {
|
||||
(pos1_at_collision.x + pos2_at_collision.x) / 2.0,
|
||||
(pos1_at_collision.y + pos2_at_collision.y) / 2.0
|
||||
};
|
||||
(pos1_at_collision.y + pos2_at_collision.y) / 2.0 };
|
||||
|
||||
Logger::debug(
|
||||
"碰撞时间计算: first_arrival_time=", first_arrival_time,
|
||||
", safe_distance=", safe_distance,
|
||||
Logger::debug("碰撞时间计算: first_arrival_time=",
|
||||
first_arrival_time, ", safe_distance=", safe_distance,
|
||||
", collision_distance=", collision_distance,
|
||||
", collision_time=", collision_time
|
||||
);
|
||||
", collision_time=", collision_time);
|
||||
|
||||
result.willCollide = true;
|
||||
result.timeToCollision = collision_time;
|
||||
@ -592,18 +580,17 @@ CollisionResult CollisionDetector::predictCircleBasedCollision(
|
||||
result.minDistance = safe_distance;
|
||||
|
||||
// 更新物体状态
|
||||
result.object1State = CollisionObjectState(
|
||||
pos1_at_collision, speed1, heading1);
|
||||
result.object2State = CollisionObjectState(
|
||||
pos2_at_collision, speed2, heading2);
|
||||
result.object1State =
|
||||
CollisionObjectState(pos1_at_collision, speed1, heading1);
|
||||
result.object2State =
|
||||
CollisionObjectState(pos2_at_collision, speed2, heading2);
|
||||
|
||||
Logger::debug(
|
||||
"交叉路径碰撞: collision_time=", collision_time,
|
||||
", collision1=(", pos1_at_collision.x, ",", pos1_at_collision.y, ")",
|
||||
", collision2=(", pos2_at_collision.x, ",", pos2_at_collision.y, ")",
|
||||
", collision_point=(", result.collisionPoint.x,
|
||||
",", result.collisionPoint.y, ")"
|
||||
);
|
||||
Logger::debug("交叉路径碰撞: collision_time=", collision_time,
|
||||
", collision1=(", pos1_at_collision.x, ",",
|
||||
pos1_at_collision.y, ")", ", collision2=(",
|
||||
pos2_at_collision.x, ",", pos2_at_collision.y, ")",
|
||||
", collision_point=(", result.collisionPoint.x, ",",
|
||||
result.collisionPoint.y, ")");
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -619,24 +606,22 @@ CollisionResult CollisionDetector::predictCircleBasedCollision(
|
||||
double rotation_angle = (90.0 - heading1) * M_PI / 180.0;
|
||||
|
||||
// 使用标准的二维坐标旋转式
|
||||
double dx_rotated = dx * std::cos(rotation_angle) - dy * std::sin(rotation_angle);
|
||||
double dy_rotated = dx * std::sin(rotation_angle) + dy * std::cos(rotation_angle);
|
||||
double dx_rotated =
|
||||
dx * std::cos(rotation_angle) - dy * std::sin(rotation_angle);
|
||||
double dy_rotated =
|
||||
dx * std::sin(rotation_angle) + dy * std::cos(rotation_angle);
|
||||
|
||||
// 横向距离就是旋转后的y坐标的绝对值
|
||||
double lateral_distance = std::abs(dy_rotated);
|
||||
|
||||
Logger::debug(
|
||||
"平行运动检测: angle_diff=", angle_diff,
|
||||
Logger::debug("平行运动检测: angle_diff=", angle_diff,
|
||||
", heading1=", heading1,
|
||||
", rotation_angle=", rotation_angle * 180.0 / M_PI,
|
||||
", dx=", dx,
|
||||
", dy=", dy,
|
||||
", dx_rotated=", dx_rotated,
|
||||
", dx=", dx, ", dy=", dy, ", dx_rotated=", dx_rotated,
|
||||
", dy_rotated=", dy_rotated,
|
||||
", lateral_distance=", lateral_distance,
|
||||
", safe_distance=", safe_distance,
|
||||
", rel_speed=", rel_speed
|
||||
);
|
||||
", rel_speed=", rel_speed);
|
||||
|
||||
// 如果横向距离大于等于安全距离,且相对速度很小,则不会碰撞
|
||||
if (lateral_distance >= safe_distance && rel_speed < 1.0) {
|
||||
@ -651,8 +636,10 @@ CollisionResult CollisionDetector::predictCircleBasedCollision(
|
||||
double dt = timeWindow / STEPS; // 时间步长
|
||||
|
||||
// 新计算速度分量(修正计算方式)
|
||||
double vx1_sample = speed1 * std::cos((90.0 - heading1) * M_PI / 180.0); // x 方向
|
||||
double vy1_sample = speed1 * std::sin((90.0 - heading1) * M_PI / 180.0); // y 方向
|
||||
double vx1_sample =
|
||||
speed1 * std::cos((90.0 - heading1) * M_PI / 180.0); // x 方向
|
||||
double vy1_sample =
|
||||
speed1 * std::sin((90.0 - heading1) * M_PI / 180.0); // y 方向
|
||||
double vx2_sample = speed2 * std::cos((90.0 - heading2) * M_PI / 180.0);
|
||||
double vy2_sample = speed2 * std::sin((90.0 - heading2) * M_PI / 180.0);
|
||||
|
||||
@ -662,10 +649,8 @@ CollisionResult CollisionDetector::predictCircleBasedCollision(
|
||||
result.timeToCollision = 0.0;
|
||||
result.minDistance = current_distance;
|
||||
result.timeToMinDistance = 0.0;
|
||||
result.collisionPoint = {
|
||||
(pos1.x + pos2.x) / 2.0,
|
||||
(pos1.y + pos2.y) / 2.0
|
||||
};
|
||||
result.collisionPoint = { (pos1.x + pos2.x) / 2.0,
|
||||
(pos1.y + pos2.y) / 2.0 };
|
||||
result.object1State = CollisionObjectState(pos1, speed1, heading1);
|
||||
result.object2State = CollisionObjectState(pos2, speed2, heading2);
|
||||
return result;
|
||||
@ -673,31 +658,23 @@ CollisionResult CollisionDetector::predictCircleBasedCollision(
|
||||
|
||||
// 在时间窗口内采样检查
|
||||
double prev_distance = current_distance;
|
||||
Logger::debug(
|
||||
"开始时间窗口采样: STEPS=", STEPS,
|
||||
", dt=", dt,
|
||||
Logger::debug("开始时间窗口采样: STEPS=", STEPS, ", dt=", dt,
|
||||
", timeWindow=", timeWindow,
|
||||
", safe_distance=", safe_distance,
|
||||
", current_distance=", current_distance
|
||||
);
|
||||
", current_distance=", current_distance);
|
||||
for (int i = 1; i <= STEPS; ++i) {
|
||||
double t = i * dt;
|
||||
|
||||
// 计算t时的位置(使用修正后的速度分量)
|
||||
Vector2D future1 = {
|
||||
pos1.x + vx1_sample * t,
|
||||
pos1.y + vy1_sample * t
|
||||
};
|
||||
Vector2D future1 = { pos1.x + vx1_sample * t, pos1.y + vy1_sample * t };
|
||||
|
||||
Vector2D future2 = {
|
||||
pos2.x + vx2_sample * t,
|
||||
pos2.y + vy2_sample * t
|
||||
};
|
||||
Vector2D future2 = { pos2.x + vx2_sample * t, pos2.y + vy2_sample * t };
|
||||
|
||||
// 计算t时的距离
|
||||
double dx_t = future2.x - future1.x;
|
||||
double dy_t = future2.y - future1.y;
|
||||
double distance = std::sqrt(dx_t*dx_t + dy_t*dy_t); // 统一使用实际距离
|
||||
double distance =
|
||||
std::sqrt(dx_t * dx_t + dy_t * dy_t); // 统一使用实际距离
|
||||
|
||||
// 更新小距离
|
||||
if (distance < result.minDistance) {
|
||||
@ -713,35 +690,28 @@ CollisionResult CollisionDetector::predictCircleBasedCollision(
|
||||
if (distance <= safe_distance) {
|
||||
result.willCollide = true;
|
||||
// 使用当前距离和安全距离做插值,提高精确度
|
||||
double progress = (distance - safe_distance) / (prev_distance - safe_distance);
|
||||
double progress =
|
||||
(distance - safe_distance) / (prev_distance - safe_distance);
|
||||
double t_interp = t - dt * progress;
|
||||
result.timeToCollision = t_interp;
|
||||
|
||||
Logger::debug(
|
||||
"找到碰撞: t=", t,
|
||||
", distance=", distance,
|
||||
", prev_distance=", prev_distance,
|
||||
", dt=", dt,
|
||||
", t_interp=", t_interp,
|
||||
", future1=(", future1.x, ",", future1.y, ")",
|
||||
", future2=(", future2.x, ",", future2.y, ")"
|
||||
);
|
||||
Logger::debug("找到碰撞: t=", t, ", distance=", distance,
|
||||
", prev_distance=", prev_distance, ", dt=", dt,
|
||||
", t_interp=", t_interp, ", future1=(", future1.x,
|
||||
",", future1.y, ")", ", future2=(", future2.x, ",",
|
||||
future2.y, ")");
|
||||
|
||||
// 使用插值时间计算更精确的碰撞点
|
||||
Vector2D interp1 = {
|
||||
pos1.x + vx1_sample * t_interp,
|
||||
pos1.y + vy1_sample * t_interp
|
||||
};
|
||||
Vector2D interp2 = {
|
||||
pos2.x + vx2_sample * t_interp,
|
||||
pos2.y + vy2_sample * t_interp
|
||||
};
|
||||
result.collisionPoint = {
|
||||
(interp1.x + interp2.x) / 2.0,
|
||||
(interp1.y + interp2.y) / 2.0
|
||||
};
|
||||
result.object1State = CollisionObjectState(interp1, speed1, heading1);
|
||||
result.object2State = CollisionObjectState(interp2, speed2, heading2);
|
||||
Vector2D interp1 = { pos1.x + vx1_sample * t_interp,
|
||||
pos1.y + vy1_sample * t_interp };
|
||||
Vector2D interp2 = { pos2.x + vx2_sample * t_interp,
|
||||
pos2.y + vy2_sample * t_interp };
|
||||
result.collisionPoint = { (interp1.x + interp2.x) / 2.0,
|
||||
(interp1.y + interp2.y) / 2.0 };
|
||||
result.object1State =
|
||||
CollisionObjectState(interp1, speed1, heading1);
|
||||
result.object2State =
|
||||
CollisionObjectState(interp2, speed2, heading2);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@ -9,8 +9,7 @@ TrafficLightDetector::TrafficLightDetector(const IntersectionConfig& intersectio
|
||||
System& system)
|
||||
: intersection_config_(intersectionConfig)
|
||||
, controllable_vehicles_(controllableVehicles)
|
||||
, system_(system) {
|
||||
}
|
||||
, system_(system) {}
|
||||
|
||||
void TrafficLightDetector::processSignal(const TrafficLightSignal& signal,
|
||||
const std::vector<Vehicle>& vehicles) {
|
||||
|
||||
@ -88,8 +88,7 @@ bool HTTPDataSource::tryReconnect() {
|
||||
Logger::error("Failed to reconnect after ", MAX_RETRIES, " attempts");
|
||||
is_reconnecting_ = false;
|
||||
return false;
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
} catch (const std::exception& e) {
|
||||
Logger::error("Error during reconnection: ", e.what());
|
||||
is_reconnecting_ = false;
|
||||
return false;
|
||||
@ -354,8 +353,7 @@ bool HTTPDataSource::sendUnmannedVehicleCommand(const std::string& vehicle_id, c
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
} catch (const std::exception& e) {
|
||||
Logger::error("Failed to parse command response: ", e.what());
|
||||
return false;
|
||||
}
|
||||
@ -399,8 +397,7 @@ bool HTTPDataSource::fetchUnmannedVehicleStatus(const std::string& vehicle_id, s
|
||||
|
||||
status = j["data"].dump();
|
||||
return true;
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
} catch (const std::exception& e) {
|
||||
Logger::error("Failed to parse vehicle status response: ", e.what());
|
||||
return false;
|
||||
}
|
||||
@ -451,8 +448,7 @@ bool HTTPDataSource::authenticatePosition(const AuthConfig& auth_config,
|
||||
auth_state.last_auth_time = std::chrono::steady_clock::now();
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
} catch (const std::exception& e) {
|
||||
Logger::error("解析认证响应失败: ", e.what(), ", 响应内容: ", response);
|
||||
return false;
|
||||
}
|
||||
@ -524,8 +520,7 @@ bool HTTPDataSource::parsePositionAircraftResponse(const std::string& response,
|
||||
aircraft.push_back(ac);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
} catch (const std::exception& e) {
|
||||
Logger::error("Failed to parse aircraft response: ", e.what());
|
||||
return false;
|
||||
}
|
||||
@ -563,8 +558,7 @@ bool HTTPDataSource::parsePositionVehicleResponse(const std::string& response, s
|
||||
vehicles.push_back(vehicle);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
} catch (const std::exception& e) {
|
||||
Logger::error("Failed to parse vehicle response: ", e.what());
|
||||
return false;
|
||||
}
|
||||
@ -604,8 +598,7 @@ bool HTTPDataSource::parseTrafficLightResponse(const std::string& response, std:
|
||||
signals.push_back(signal);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (const std::exception& e) {
|
||||
} catch (const std::exception& e) {
|
||||
Logger::error("Failed to parse traffic light response: ", e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -8,8 +8,7 @@
|
||||
namespace network {
|
||||
|
||||
WebSocketServer::WebSocketServer(uint16_t port)
|
||||
: acceptor_(ioc_, {boost::asio::ip::tcp::v4(), port}) {
|
||||
}
|
||||
: acceptor_(ioc_, { boost::asio::ip::tcp::v4(), port }) {}
|
||||
|
||||
WebSocketServer::~WebSocketServer() {
|
||||
// 关闭所有连接
|
||||
|
||||
Loading…
Reference in New Issue
Block a user