增加红绿灯的两个方向的信号状态处理和前端页面显示
This commit is contained in:
parent
d645dbc486
commit
5f2c0e4d86
@ -9,6 +9,8 @@
|
||||
#include "network/TrafficLightHttpServer.h"
|
||||
#include "config/SystemConfig.h"
|
||||
#include "types/TrafficLightTypes.h"
|
||||
#include "network/WebSocketServer.h"
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
System* System::instance_ = nullptr;
|
||||
|
||||
@ -494,6 +496,16 @@ void System::broadcastPositionUpdate(const MovingObject& obj) {
|
||||
" timestamp=", msg.timestamp);
|
||||
}
|
||||
|
||||
// 新增辅助函数:将 SignalStatus 转换为字符串
|
||||
std::string signalStatusToString(SignalStatus status) {
|
||||
switch (status) {
|
||||
case SignalStatus::RED: return "RED";
|
||||
case SignalStatus::GREEN: return "GREEN";
|
||||
case SignalStatus::YELLOW: return "YELLOW";
|
||||
default: return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
void System::broadcastTrafficLightStatus(const TrafficLightSignal& signal) {
|
||||
if (!ws_server_) {
|
||||
return;
|
||||
@ -505,8 +517,13 @@ void System::broadcastTrafficLightStatus(const TrafficLightSignal& signal) {
|
||||
nlohmann::json j = {
|
||||
{"type", "traffic_light_status"},
|
||||
{"id", signal.trafficLightId},
|
||||
{"status", static_cast<int>(signal.status)},
|
||||
{"timestamp", signal.timestamp} };
|
||||
// 修改: 将 status 改为一个包含 ns 和 ew 状态的对象
|
||||
{"status", {
|
||||
{"ns", signalStatusToString(signal.ns_status)},
|
||||
{"ew", signalStatusToString(signal.ew_status)}
|
||||
}},
|
||||
{"timestamp", signal.timestamp}
|
||||
};
|
||||
|
||||
// 添加路口信息
|
||||
if (intersection) {
|
||||
@ -517,12 +534,13 @@ void System::broadcastTrafficLightStatus(const TrafficLightSignal& signal) {
|
||||
}
|
||||
|
||||
ws_server_->broadcast(j.dump());
|
||||
|
||||
// 修改日志记录
|
||||
Logger::debug("广播红绿灯状态: id=", signal.trafficLightId,
|
||||
" status=", static_cast<int>(signal.status),
|
||||
" intersection=", intersection ? intersection->id : "",
|
||||
" position=(", intersection ? intersection->position.longitude : 0.0, ",",
|
||||
intersection ? intersection->position.latitude : 0.0, ")",
|
||||
" timestamp=", signal.timestamp);
|
||||
", NS_Status=", signalStatusToString(signal.ns_status),
|
||||
", EW_Status=", signalStatusToString(signal.ew_status),
|
||||
", intersection=", intersection ? intersection->id : "",
|
||||
", timestamp=", signal.timestamp);
|
||||
}
|
||||
|
||||
std::string getRiskLevelString(RiskLevel level) {
|
||||
@ -774,61 +792,65 @@ bool System::handleSafetyZoneRisk(const Vehicle& vehicle,
|
||||
}
|
||||
|
||||
void System::processPushedTrafficLightData(const nlohmann::json& di_data) {
|
||||
const auto& config = SystemConfig::instance();
|
||||
const std::string target_id = config.simulated_mobile_light_target_intersection_id;
|
||||
|
||||
if (target_id.empty()) {
|
||||
Logger::warning("Target intersection ID for pushed traffic light data is not configured.");
|
||||
return;
|
||||
}
|
||||
|
||||
// 使用配置的 ID 查找路口信息
|
||||
const Intersection* intersection = intersection_config_.findById(target_id);
|
||||
if (!intersection) {
|
||||
Logger::warning("Configured target intersection ID ", target_id, " not found.");
|
||||
return;
|
||||
}
|
||||
|
||||
// 解析 DI 数据获取当前状态 (简化: 只处理南北向)
|
||||
SignalStatus current_status = SignalStatus::UNKNOWN;
|
||||
try {
|
||||
// DI-13: 北绿 (NS Green)
|
||||
if (di_data.contains("DI-13") && di_data.at("DI-13").get<int>() == 1) {
|
||||
current_status = SignalStatus::GREEN;
|
||||
}
|
||||
// DI-12: 北黄 (NS Yellow)
|
||||
else if (di_data.contains("DI-12") && di_data.at("DI-12").get<int>() == 1) {
|
||||
current_status = SignalStatus::YELLOW;
|
||||
}
|
||||
// DI-11: 北红 (NS Red)
|
||||
else if (di_data.contains("DI-11") && di_data.at("DI-11").get<int>() == 1) {
|
||||
current_status = SignalStatus::RED;
|
||||
}
|
||||
// 可以添加东西向 DI-14 (E/W Red), DI-15 (E/W Yellow), DI-16 (E/W Green) 的解析逻辑
|
||||
else {
|
||||
Logger::warning("Received DI data has unknown or invalid N/S state: ", di_data.dump());
|
||||
// 可以选择不广播或广播 UNKNOWN
|
||||
// return; // 如果状态无效则不广播
|
||||
}
|
||||
} catch (const json::exception& e) {
|
||||
Logger::error("Error parsing DI data JSON: ", e.what(), ", Data: ", di_data.dump());
|
||||
const auto& config = SystemConfig::instance();
|
||||
const std::string targetIntersectionId = config.simulated_mobile_light_target_intersection_id;
|
||||
const Intersection* targetIntersection = intersection_config_.findById(targetIntersectionId);
|
||||
|
||||
if (!targetIntersection) {
|
||||
Logger::warning("Configured target intersection ID not found in intersection config: ", targetIntersectionId);
|
||||
return;
|
||||
}
|
||||
|
||||
// 创建 TrafficLightSignal 结构体
|
||||
TrafficLightSignal signal;
|
||||
signal.trafficLightId = intersection->trafficLightId; // 使用找到的路口的红绿灯 ID
|
||||
signal.status = current_status;
|
||||
signal.timestamp = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
std::chrono::system_clock::now().time_since_epoch())
|
||||
.count();
|
||||
signal.intersectionId = intersection->id;
|
||||
signal.latitude = intersection->position.latitude;
|
||||
signal.longitude = intersection->position.longitude;
|
||||
SignalStatus ns_status = SignalStatus::UNKNOWN;
|
||||
SignalStatus ew_status = SignalStatus::UNKNOWN;
|
||||
|
||||
Logger::debug("Processing pushed traffic light data for intersection: ", intersection->id,
|
||||
", status: ", static_cast<int>(signal.status));
|
||||
|
||||
// 广播信号状态
|
||||
broadcastTrafficLightStatus(signal);
|
||||
if (di_data.contains("DI-13") && di_data.at("DI-13").get<int>() == 1) {
|
||||
ns_status = SignalStatus::GREEN;
|
||||
} else if (di_data.contains("DI-12") && di_data.at("DI-12").get<int>() == 1) {
|
||||
ns_status = SignalStatus::YELLOW;
|
||||
} else if (di_data.contains("DI-11") && di_data.at("DI-11").get<int>() == 1) {
|
||||
ns_status = SignalStatus::RED;
|
||||
} else {
|
||||
Logger::warning("Received DI data has unknown or invalid N/S state: ", di_data.dump());
|
||||
}
|
||||
|
||||
if (di_data.contains("DI-16") && di_data.at("DI-16").get<int>() == 1) {
|
||||
ew_status = SignalStatus::GREEN;
|
||||
} else if (di_data.contains("DI-15") && di_data.at("DI-15").get<int>() == 1) {
|
||||
ew_status = SignalStatus::YELLOW;
|
||||
} else if (di_data.contains("DI-14") && di_data.at("DI-14").get<int>() == 1) {
|
||||
ew_status = SignalStatus::RED;
|
||||
} else {
|
||||
Logger::warning("Received DI data has unknown or invalid E/W state: ", di_data.dump());
|
||||
}
|
||||
|
||||
TrafficLightSignal signal;
|
||||
signal.trafficLightId = "DI_PUSHED_" + targetIntersectionId;
|
||||
signal.ns_status = ns_status;
|
||||
signal.ew_status = ew_status;
|
||||
signal.timestamp = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
std::chrono::system_clock::now().time_since_epoch()).count();
|
||||
|
||||
if (ws_server_) {
|
||||
nlohmann::json messageJson;
|
||||
messageJson["type"] = "intersection_traffic_light_status";
|
||||
messageJson["intersection_id"] = targetIntersection->id;
|
||||
messageJson["position"] = {
|
||||
{"latitude", targetIntersection->position.latitude},
|
||||
{"longitude", targetIntersection->position.longitude}
|
||||
};
|
||||
messageJson["ns_status"] = static_cast<int>(signal.ns_status);
|
||||
messageJson["ew_status"] = static_cast<int>(signal.ew_status);
|
||||
messageJson["timestamp"] = signal.timestamp;
|
||||
|
||||
ws_server_->broadcast(messageJson.dump());
|
||||
Logger::debug("广播路口交通灯状态: ", messageJson.dump());
|
||||
} else {
|
||||
Logger::warning("WebSocket server is not available, cannot broadcast intersection status.");
|
||||
}
|
||||
|
||||
} catch (const std::exception& e) {
|
||||
Logger::error("处理推送的交通信号灯数据时出错: ", e.what());
|
||||
}
|
||||
}
|
||||
@ -16,6 +16,7 @@
|
||||
#include "network/MessageTypes.h"
|
||||
#include "config/IntersectionConfig.h"
|
||||
#include "network/TrafficLightHttpServer.h"
|
||||
#include <nlohmann/json_fwd.hpp>
|
||||
|
||||
// 前向声明
|
||||
class DataCollector;
|
||||
@ -43,9 +44,12 @@ public:
|
||||
const SystemConfig& getSystemConfig() const { return SystemConfig::instance(); }
|
||||
const IntersectionConfig& getIntersectionConfig() const { return intersection_config_; }
|
||||
|
||||
// 新增: 处理推送的红绿灯数据
|
||||
// 新增: 处理推送的红绿灯数据 (改回接收 json 对象)
|
||||
void processPushedTrafficLightData(const nlohmann::json& di_data);
|
||||
|
||||
// 处理来自数据源的交通信号灯状态
|
||||
void processTrafficLightStatus(const TrafficLightSignal& signal);
|
||||
|
||||
private:
|
||||
void processLoop();
|
||||
void processCollisions(const std::vector<CollisionRisk>& detectedRisks,
|
||||
|
||||
@ -27,7 +27,9 @@ void TrafficLightDetector::processSignal(const TrafficLightSignal& signal,
|
||||
for (const auto& vehicle : vehicles) {
|
||||
if (controllable_vehicles_.isControllable(vehicle.vehicleNo)) {
|
||||
// 根据信号灯状态发送指令
|
||||
switch (signal.status) {
|
||||
// FIXME: 临时修改 - 仅根据南北向状态发送指令,未考虑车辆方向和东西向状态。
|
||||
// 需要根据车辆行驶方向判断应该参考 ns_status 还是 ew_status。
|
||||
switch (signal.ns_status) {
|
||||
case SignalStatus::RED:
|
||||
sendSignalCommand(vehicle.vehicleNo, SignalState::RED);
|
||||
break;
|
||||
|
||||
@ -582,8 +582,8 @@ bool HTTPDataSource::parseTrafficLightResponse(const std::string& response, std:
|
||||
for (const auto& item : data) {
|
||||
TrafficLightSignal signal;
|
||||
signal.trafficLightId = item["id"].get<std::string>();
|
||||
signal.status = [&]() {
|
||||
int state = item["state"].get<int>();
|
||||
signal.ns_status = [&]() {
|
||||
int state = item["ns_status"].get<int>();
|
||||
switch (state) {
|
||||
case 0: return SignalStatus::RED;
|
||||
case 1: return SignalStatus::GREEN;
|
||||
|
||||
@ -12,16 +12,10 @@ enum class SignalStatus {
|
||||
|
||||
struct TrafficLightSignal {
|
||||
std::string trafficLightId; // 红绿灯设备 ID
|
||||
SignalStatus status; // 信号灯状态
|
||||
SignalStatus ns_status = SignalStatus::UNKNOWN; // 南北向状态
|
||||
SignalStatus ew_status = SignalStatus::UNKNOWN; // 东西向状态
|
||||
uint64_t timestamp; // 时间戳
|
||||
std::string intersectionId; // 路口编号
|
||||
double latitude; // 路口纬度
|
||||
double longitude; // 路口经度
|
||||
|
||||
static SignalStatus parseStatus(const std::string& status) {
|
||||
if (status == "red") return SignalStatus::RED;
|
||||
if (status == "green") return SignalStatus::GREEN;
|
||||
if (status == "yellow") return SignalStatus::YELLOW;
|
||||
return SignalStatus::UNKNOWN;
|
||||
}
|
||||
};
|
||||
@ -118,7 +118,8 @@ protected:
|
||||
TrafficLightSignal createTestTrafficLight(const std::string& id, int state) {
|
||||
TrafficLightSignal signal;
|
||||
signal.trafficLightId = id;
|
||||
signal.status = static_cast<SignalStatus>(state);
|
||||
signal.ns_status = static_cast<SignalStatus>(state);
|
||||
signal.ew_status = static_cast<SignalStatus>(state);
|
||||
signal.timestamp = std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||
std::chrono::system_clock::now().time_since_epoch()).count();
|
||||
return signal;
|
||||
@ -379,9 +380,9 @@ TEST_F(DataCollectorTest, TrafficLightSignalsTest) {
|
||||
EXPECT_EQ(signals.size(), 3);
|
||||
if (signals.size() >= 3) {
|
||||
EXPECT_EQ(signals[0].trafficLightId, "TL001");
|
||||
EXPECT_EQ(signals[0].status, SignalStatus::RED); // RED = 0
|
||||
EXPECT_EQ(signals[0].ns_status, SignalStatus::RED); // RED = 0
|
||||
EXPECT_EQ(signals[1].trafficLightId, "TL002");
|
||||
EXPECT_EQ(signals[1].status, SignalStatus::GREEN); // GREEN = 1
|
||||
EXPECT_EQ(signals[1].ns_status, SignalStatus::GREEN); // GREEN = 1
|
||||
}
|
||||
|
||||
// 停止数据采集
|
||||
|
||||
@ -76,7 +76,8 @@ protected:
|
||||
TrafficLightSignal createTestSignal(const std::string& id, SignalStatus status) {
|
||||
TrafficLightSignal signal;
|
||||
signal.trafficLightId = id;
|
||||
signal.status = status;
|
||||
signal.ns_status = status;
|
||||
signal.ew_status = status;
|
||||
signal.timestamp = std::chrono::system_clock::now().time_since_epoch().count();
|
||||
return signal;
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<title>机场车辆监控</title>
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" />
|
||||
@ -11,15 +12,18 @@
|
||||
padding: 20px;
|
||||
font-family: Arial, sans-serif;
|
||||
}
|
||||
|
||||
.container {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
#map {
|
||||
height: 800px;
|
||||
width: 60%;
|
||||
border: 1px solid #ccc;
|
||||
}
|
||||
|
||||
#messages {
|
||||
width: 40%;
|
||||
height: 800px;
|
||||
@ -28,15 +32,35 @@
|
||||
padding: 10px;
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
.controls {
|
||||
margin-top: 10px;
|
||||
}
|
||||
.error { color: red; }
|
||||
.success { color: green; }
|
||||
.info { color: blue; }
|
||||
.position { color: #666; }
|
||||
.warning { color: #f90; }
|
||||
.command { color: #800080; }
|
||||
|
||||
.error {
|
||||
color: red;
|
||||
}
|
||||
|
||||
.success {
|
||||
color: green;
|
||||
}
|
||||
|
||||
.info {
|
||||
color: blue;
|
||||
}
|
||||
|
||||
.position {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.warning {
|
||||
color: #f90;
|
||||
}
|
||||
|
||||
.command {
|
||||
color: #800080;
|
||||
}
|
||||
|
||||
.vehicle-icon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
@ -44,6 +68,7 @@
|
||||
clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%);
|
||||
border: 2px solid white;
|
||||
}
|
||||
|
||||
.aircraft-icon {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
@ -52,6 +77,7 @@
|
||||
border: 2px solid white;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.aircraft-icon::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
@ -63,6 +89,7 @@
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
|
||||
.special-vehicle-icon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
@ -70,6 +97,7 @@
|
||||
clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%);
|
||||
border: 2px solid white;
|
||||
}
|
||||
|
||||
.intersection-icon {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
@ -77,6 +105,7 @@
|
||||
clip-path: polygon(40% 0%, 60% 0%, 60% 40%, 100% 40%, 100% 60%, 60% 60%, 60% 100%, 40% 100%, 40% 60%, 0% 60%, 0% 40%, 40% 40%);
|
||||
border: 2px solid white;
|
||||
}
|
||||
|
||||
.traffic-light {
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
@ -84,15 +113,19 @@
|
||||
border: 2px solid white;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.traffic-light-red {
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
.traffic-light-green {
|
||||
background-color: green;
|
||||
}
|
||||
|
||||
.traffic-light-yellow {
|
||||
background-color: yellow;
|
||||
}
|
||||
|
||||
.countdown-label {
|
||||
background: #000;
|
||||
border: 1px solid #666;
|
||||
@ -111,15 +144,19 @@
|
||||
justify-content: center;
|
||||
height: 14px;
|
||||
}
|
||||
|
||||
.countdown-red {
|
||||
color: #ff3333;
|
||||
}
|
||||
|
||||
.countdown-green {
|
||||
color: #33ff33;
|
||||
}
|
||||
|
||||
.countdown-yellow {
|
||||
color: #ffff33;
|
||||
}
|
||||
|
||||
.distance-label {
|
||||
background: none;
|
||||
border: none;
|
||||
@ -128,6 +165,7 @@
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.command-text {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
@ -143,23 +181,28 @@
|
||||
pointer-events: none;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.safety-border {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 2px solid;
|
||||
background: none;
|
||||
}
|
||||
|
||||
.emergency-border {
|
||||
border-color: rgba(255, 0, 0, 0.8);
|
||||
}
|
||||
|
||||
.core-border {
|
||||
border-color: rgba(255, 165, 0, 0.6);
|
||||
}
|
||||
|
||||
.warning-border {
|
||||
border-color: rgba(255, 255, 0, 0.4);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h2>机场车辆监控系统</h2>
|
||||
<div class="container">
|
||||
@ -231,7 +274,7 @@
|
||||
|
||||
// 存储所有标记
|
||||
const markers = new Map();
|
||||
const trafficLights = new Map();
|
||||
const intersectionMarkers = new Map();
|
||||
const intersections = new Map();
|
||||
|
||||
// 创建自定义图标
|
||||
@ -349,84 +392,46 @@
|
||||
}
|
||||
|
||||
// 添加红绿灯状态和倒计时变量
|
||||
let lastTrafficLightState = null;
|
||||
let countdownInterval = null;
|
||||
let countdown = 10; // 10秒倒计时
|
||||
// let lastTrafficLightState = null;
|
||||
// let countdownInterval = null;
|
||||
// let countdown = 10;
|
||||
|
||||
function updateTrafficLight(data) {
|
||||
const id = data.id;
|
||||
// New function to update intersection traffic lights
|
||||
function updateIntersectionTrafficLights(data) {
|
||||
const intersectionId = data.intersection_id;
|
||||
const position = [data.position.latitude, data.position.longitude];
|
||||
const state = data.status === 0 ? 'red' : data.status === 1 ? 'green' : 'yellow';
|
||||
const nsStatus = data.ns_status; // 0: red, 1: green, 2: yellow
|
||||
const ewStatus = data.ew_status; // 0: red, 1: green, 2: yellow
|
||||
|
||||
// 检查是否是西路口(TL001)的红绿灯状态变化
|
||||
if (id === 'TL001' && lastTrafficLightState !== state) {
|
||||
lastTrafficLightState = state;
|
||||
// 重置倒计时
|
||||
countdown = 10;
|
||||
// 清除现有的倒计时
|
||||
if (countdownInterval) {
|
||||
clearInterval(countdownInterval);
|
||||
}
|
||||
// 启动新的倒计时
|
||||
countdownInterval = setInterval(() => {
|
||||
countdown = Math.max(0, countdown - 1);
|
||||
// 更新红绿灯标签显示
|
||||
const light = trafficLights.get(id);
|
||||
if (light) {
|
||||
// 格式化倒计时为 0:SS 格式
|
||||
const countdownStr = `0:${countdown.toString().padStart(2, '0')}`;
|
||||
const label = L.divIcon({
|
||||
className: `countdown-label countdown-${state}`,
|
||||
html: countdownStr,
|
||||
iconSize: [32, 16],
|
||||
iconAnchor: [16, 30]
|
||||
});
|
||||
// 更新或创建倒计时标签
|
||||
if (!light.countdownMarker) {
|
||||
light.countdownMarker = L.marker(position, {
|
||||
icon: label,
|
||||
interactive: false
|
||||
}).addTo(map);
|
||||
} else {
|
||||
light.countdownMarker.setIcon(label);
|
||||
}
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
const nsColor = nsStatus === 0 ? 'red' : nsStatus === 1 ? 'green' : 'yellow';
|
||||
const ewColor = ewStatus === 0 ? 'red' : ewStatus === 1 ? 'green' : 'yellow';
|
||||
|
||||
let light = trafficLights.get(id);
|
||||
if (!light) {
|
||||
light = L.marker(position, {
|
||||
icon: createIcon(`traffic-light traffic-light-${state}`)
|
||||
}).addTo(map);
|
||||
// 为西路口添加倒计时显示
|
||||
if (id === 'TL001') {
|
||||
const countdownStr = `0:${countdown.toString().padStart(2, '0')}`;
|
||||
const label = L.divIcon({
|
||||
className: `countdown-label countdown-${state}`,
|
||||
html: countdownStr,
|
||||
iconSize: [32, 16],
|
||||
iconAnchor: [16, 30]
|
||||
});
|
||||
light.countdownMarker = L.marker(position, {
|
||||
icon: label,
|
||||
interactive: false
|
||||
}).addTo(map);
|
||||
}
|
||||
trafficLights.set(id, light);
|
||||
// Calculate offset positions for NS and EW lights
|
||||
const nsPositionOffset = [position[0] + 0.00003, position[1]]; // Slightly north
|
||||
const ewPositionOffset = [position[0], position[1] + 0.00003]; // Slightly east
|
||||
|
||||
let currentMarkers = intersectionMarkers.get(intersectionId);
|
||||
if (!currentMarkers) {
|
||||
// Create new marker group
|
||||
currentMarkers = {};
|
||||
currentMarkers.nsMarker = L.marker(nsPositionOffset, {
|
||||
icon: createIcon(`traffic-light traffic-light-${nsColor}`),
|
||||
pane: 'markerPane' // Ensure lights are above roads
|
||||
}).addTo(map).bindTooltip(`Intersection ${intersectionId} (NS)`);
|
||||
|
||||
currentMarkers.ewMarker = L.marker(ewPositionOffset, {
|
||||
icon: createIcon(`traffic-light traffic-light-${ewColor}`),
|
||||
pane: 'markerPane'
|
||||
}).addTo(map).bindTooltip(`Intersection ${intersectionId} (EW)`);
|
||||
|
||||
intersectionMarkers.set(intersectionId, currentMarkers);
|
||||
} else {
|
||||
light.setIcon(createIcon(`traffic-light traffic-light-${state}`));
|
||||
// 更新西路口的倒计时显示
|
||||
if (id === 'TL001' && light.countdownMarker) {
|
||||
const countdownStr = `0:${countdown.toString().padStart(2, '0')}`;
|
||||
const label = L.divIcon({
|
||||
className: `countdown-label countdown-${state}`,
|
||||
html: countdownStr,
|
||||
iconSize: [32, 16],
|
||||
iconAnchor: [16, 30]
|
||||
});
|
||||
light.countdownMarker.setIcon(label);
|
||||
}
|
||||
// Update existing markers
|
||||
currentMarkers.nsMarker.setLatLng(nsPositionOffset);
|
||||
currentMarkers.nsMarker.setIcon(createIcon(`traffic-light traffic-light-${nsColor}`));
|
||||
|
||||
currentMarkers.ewMarker.setLatLng(ewPositionOffset);
|
||||
currentMarkers.ewMarker.setIcon(createIcon(`traffic-light traffic-light-${ewColor}`));
|
||||
}
|
||||
}
|
||||
|
||||
@ -514,10 +519,13 @@
|
||||
`航向: ${data.heading !== undefined ? data.heading.toFixed(2) + '°' : 'N/A'}\n` +
|
||||
`速度: ${data.speed !== undefined ? data.speed.toFixed(2) + ' m/s' : 'N/A'}`;
|
||||
break;
|
||||
case 'traffic_light_status':
|
||||
case 'intersection_traffic_light_status':
|
||||
type = 'info';
|
||||
updateTrafficLight(data);
|
||||
message = `红绿灯状态更新:\n信号灯: ${data.id}\n状态: ${data.status === 0 ? '红灯' : data.status === 1 ? '绿灯' : '黄灯'}`;
|
||||
updateIntersectionTrafficLights(data);
|
||||
message = `路口交通灯状态更新:\n` +
|
||||
`路口 ID: ${data.intersection_id}\n` +
|
||||
`南北状态: ${data.ns_status === 0 ? '红' : data.ns_status === 1 ? '绿' : '黄'}\n` +
|
||||
`东西状态: ${data.ew_status === 0 ? '红' : data.ew_status === 1 ? '绿' : '黄'}`;
|
||||
break;
|
||||
case 'collision_warning':
|
||||
type = 'warning';
|
||||
@ -572,32 +580,40 @@
|
||||
}
|
||||
|
||||
// 清除倒计时
|
||||
if (countdownInterval) {
|
||||
clearInterval(countdownInterval);
|
||||
countdownInterval = null;
|
||||
}
|
||||
lastTrafficLightState = null;
|
||||
countdown = 10;
|
||||
// if (countdownInterval) {
|
||||
// clearInterval(countdownInterval);
|
||||
// countdownInterval = null;
|
||||
// }
|
||||
// lastTrafficLightState = null;
|
||||
// countdown = 10;
|
||||
|
||||
// 清除倒计时标记
|
||||
trafficLights.forEach(light => {
|
||||
if (light.countdownMarker) {
|
||||
map.removeLayer(light.countdownMarker);
|
||||
light.countdownMarker = null;
|
||||
}
|
||||
});
|
||||
// trafficLights.forEach(light => {
|
||||
// if (light.countdownMarker) {
|
||||
// map.removeLayer(light.countdownMarker);
|
||||
// light.countdownMarker = null;
|
||||
// }
|
||||
// });
|
||||
|
||||
ws.close();
|
||||
ws = null;
|
||||
|
||||
// 清除所有标记(包括边框标记)
|
||||
// 清除所有车辆和安全边框标记
|
||||
markers.forEach((marker, key) => {
|
||||
map.removeLayer(marker);
|
||||
});
|
||||
markers.clear();
|
||||
|
||||
trafficLights.forEach(light => map.removeLayer(light));
|
||||
trafficLights.clear();
|
||||
// 清除旧的红绿灯标记
|
||||
// trafficLights.forEach(light => map.removeLayer(light));
|
||||
// trafficLights.clear();
|
||||
|
||||
// 清除路口红绿灯标记
|
||||
intersectionMarkers.forEach((markers, id) => {
|
||||
if (markers.nsMarker) map.removeLayer(markers.nsMarker);
|
||||
if (markers.ewMarker) map.removeLayer(markers.ewMarker);
|
||||
});
|
||||
intersectionMarkers.clear();
|
||||
}
|
||||
|
||||
// 添加道路刻度标记函数
|
||||
@ -720,4 +736,5 @@
|
||||
);
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Loading…
Reference in New Issue
Block a user