CARLA
 
载入中...
搜索中...
未找到
TrafficManager.cpp
浏览该文件的文档.
1// Copyright (c) 2020 Computer Vision Center (CVC) at the Universitat Autonoma
2// de Barcelona (UAB).
3//
4// This work is licensed under the terms of the MIT license.
5// For a copy, see <https://opensource.org/licenses/MIT>.
6
7//#include "carla/client/Client.h"
8
9
10#include "carla/Sockets.h"
12
18
19#define DEBUG_PRINT_TM 0
20#define IP_DATA_BUFFER_SIZE 80
21
22namespace carla {
23namespace traffic_manager {
24
25// 使用速度阈值和PID常量
26using namespace constants::SpeedThreshold;
27using namespace constants::PID;
28
29// 定义一个映射,存储TrafficManagerBase指针
30std::map<uint16_t, TrafficManagerBase*> TrafficManager::_tm_map;
31// 定义互斥锁,用于多线程安全
32std::mutex TrafficManager::_mutex;
33
34// TrafficManager构造函数
37 uint16_t port)
38 : _port(port) {
39
40 // 检查是否能获取当前端口的交通管理器
41 if(!GetTM(_port)){
42 // 如果没有获取到,尝试连接已存在的TM服务器
43 if(!CreateTrafficManagerClient(episode_proxy, port)) {
44 // 如果TM服务器没有运行,创建一个新的TM服务器
45 CreateTrafficManagerServer(episode_proxy, port);
46 }
47 }
48}
49
50// 释放资源
52 std::lock_guard<std::mutex> lock(_mutex); // 锁定互斥锁以保证线程安全
53 for(auto& tm : _tm_map) { // 遍历所有交通管理器
54 tm.second->Release(); // 调用释放方法
55 TrafficManagerBase *base_ptr = tm.second; // 获取指针
56 delete base_ptr; // 删除指针,释放内存
57 }
58 _tm_map.clear(); // 清空映射
59}
60
61// 重置所有交通管理器
63 std::lock_guard<std::mutex> lock(_mutex); // 锁定互斥锁
64 for(auto& tm : _tm_map) { // 遍历所有交通管理器
65 tm.second->Reset(); // 调用重置方法
66 }
67}
68
69// 执行每个交通管理器的Tick操作
71 std::lock_guard<std::mutex> lock(_mutex); // 锁定互斥锁
72 for(auto& tm : _tm_map) { // 遍历所有交通管理器
73 tm.second->SynchronousTick(); // 调用同步Tick方法
74 }
75}
76
77// 关闭交通管理器
79 TrafficManagerBase* tm_ptr = GetTM(_port); // 获取指定端口的交通管理器
80 std::lock_guard<std::mutex> lock(_mutex); // 锁定互斥锁
81 auto it = _tm_map.find(_port); // 查找端口对应的交通管理器
82 if (it != _tm_map.end()) {
83 _tm_map.erase(it); // 删除映射中的交通管理器
84 }
85 if(tm_ptr != nullptr) {
86 tm_ptr->ShutDown(); // 调用关闭方法
87 delete tm_ptr; // 删除指针,释放内存
88 }
89}
90
91// 创建交通管理器服务器
94 uint16_t port) {
95
96 // 获取本地IP地址
97 auto GetLocalIP = [=](const uint16_t sport)-> std::pair<std::string, uint16_t> {
98 std::pair<std::string, uint16_t> localIP; // 存储本地IP和端口对
99 int sock = socket(AF_INET, SOCK_DGRAM, 0); // 创建UDP socket
100 if(sock == SOCK_INVALID_INDEX) {
101 #if DEBUG_PRINT_TM
102 std::cout << "Error number 1: " << errno << std::endl; // 打印错误号
103 std::cout << "Error message: " << strerror(errno) << std::endl; // 打印错误信息
104 #endif
105 } else {
106 int err;
107 sockaddr_in loopback; // 定义回环地址结构
108 std::memset(&loopback, 0, sizeof(loopback)); // 清零结构体
109 loopback.sin_family = AF_INET; // 设置地址族为IPv4
110 loopback.sin_addr.s_addr = INADDR_LOOPBACK; // 设置为回环地址
111 loopback.sin_port = htons(9); // 设置端口为9(任意端口)
112 err = connect(sock, reinterpret_cast<sockaddr*>(&loopback), sizeof(loopback)); // 尝试连接
113 if(err == SOCK_INVALID_INDEX) {
114 #if DEBUG_PRINT_TM
115 std::cout << "Error number 2: " << errno << std::endl; // 打印连接错误号
116 std::cout << "Error message: " << strerror(errno) << std::endl; // 打印连接错误信息
117 #endif
118 } else {
119 socklen_t addrlen = sizeof(loopback);
120 err = getsockname(sock, reinterpret_cast<struct sockaddr*> (&loopback), &addrlen); // 获取socket名称
121 if(err == SOCK_INVALID_INDEX) {
122 #if DEBUG_PRINT_TM
123 std::cout << "Error number 3: " << errno << std::endl; // 打印获取socket名称错误号
124 std::cout << "Error message: " << strerror(errno) << std::endl; // 打印获取socket名称错误信息
125 #endif
126 } else {
127 char buffer[IP_DATA_BUFFER_SIZE]; // 定义缓冲区存储IP
128 const char* p = inet_ntop(AF_INET, &loopback.sin_addr, buffer, IP_DATA_BUFFER_SIZE); // 转换IP地址
129 if(p != NULL) {
130 localIP = std::pair<std::string, uint16_t>(std::string(buffer), sport); // 保存本地IP和端口
131 } else {
132 #if DEBUG_PRINT_TM
133 std::cout << "Error number 4: " << errno << std::endl; // 打印转换IP地址错误号
134 std::cout << "Error message: " << strerror(errno) << std::endl; // 打印转换IP地址错误信息
135 #endif
136 }
137 }
138 }
139 #ifdef _WIN32
140 closesocket(sock); // 在Windows上关闭socket
141#else
142 close(sock); // 在非Windows系统上关闭socket
143#endif
144 }
145 return localIP; // 返回本地IP和端口的对
146 };
147
148 /// 定义局部常量
149 const std::vector<float> longitudinal_param = LONGITUDIAL_PARAM; // 纵向参数
150 const std::vector<float> longitudinal_highway_param = LONGITUDIAL_HIGHWAY_PARAM; // 纵向高速公路参数
151 const std::vector<float> lateral_param = LATERAL_PARAM; // 横向参数
152 const std::vector<float> lateral_highway_param = LATERAL_HIGHWAY_PARAM; // 横向高速公路参数
153 const float perc_difference_from_limit = INITIAL_PERCENTAGE_SPEED_DIFFERENCE; // 初始速度差百分比
154
155 std::pair<std::string, uint16_t> serverTM; // 存储服务器IP和端口的对
156
157 /// 创建交通管理器的本地实例
159 longitudinal_param, // 传入纵向参数
160 longitudinal_highway_param, // 传入纵向高速公路参数
161 lateral_param, // 传入横向参数
162 lateral_highway_param, // 传入横向高速公路参数
163 perc_difference_from_limit, // 传入初始速度差百分比
164 episode_proxy, // 传入剧集代理
165 port); // 传入端口
166
167 /// 获取TM服务器信息(本地IP和端口)
168 serverTM = GetLocalIP(port);
169
170 /// 将此客户端设置为TM服务器
171 episode_proxy.Lock()->AddTrafficManagerRunning(serverTM); // 向剧集代理添加正在运行的交通管理器
172
173 #if DEBUG_PRINT_TM
174 /// 打印状态信息
175 std::cout << "NEW@: Registered TM at "
176 << serverTM.first << ":"
177 << serverTM.second << " ..... SUCCESS." // 打印成功注册的消息
178 << std::endl;
179 #endif
180
181 /// 设置实例指针
182 _tm_map.insert(std::make_pair(port, tm_ptr)); // 将交通管理器的指针存入映射
183
184}
185
188 uint16_t port) {
189
190 bool result = false; // 初始化结果为false
191
192 if(episode_proxy.Lock()->IsTrafficManagerRunning(port)) { // 检查指定端口的交通管理器是否正在运行
193
194 /// 获取TM服务器信息(远程IP和端口)
195 std::pair<std::string, uint16_t> serverTM =
196 episode_proxy.Lock()->GetTrafficManagerRunning(port);
197
198 /// 设置远程TM服务器的IP和端口
199 TrafficManagerRemote* tm_ptr = new(std::nothrow)
200 TrafficManagerRemote(serverTM, episode_proxy); // 创建远程交通管理器实例
201
202 /// 尝试连接到远程TM服务器
203 try {
204
205 /// 检查内存是否分配成功
206 if(tm_ptr != nullptr) {
207
208 #if DEBUG_PRINT_TM
209 // 测试打印
210 std::cout << "OLD@: Registered TM at "
211 << serverTM.first << ":"
212 << serverTM.second << " ..... TRY " // 打印尝试连接的消息
213 << std::endl;
214 #endif
215 /// 尝试重置所有交通信号灯
216 tm_ptr->HealthCheckRemoteTM(); // 进行健康检查
217
218 /// 设置实例指针
219 _tm_map.insert(std::make_pair(port, tm_ptr)); // 将远程交通管理器的指针存入映射
220
221 result = true; // 更新结果为true,表示连接成功
222 }
223 }
224
225 /// 如果发生连接错误
226 catch (...) {
227
228 /// 清除之前分配的内存
229 delete tm_ptr; // 删除远程交通管理器实例
230
231 #if DEBUG_PRINT_TM
232 /// 测试打印
233 std::cout << "OLD@: Registered TM at "
234 << serverTM.first << ":"
235 << serverTM.second << " ..... FAILED " // 打印连接失败的消息
236 << std::endl;
237 #endif
238 }
239
240 }
241
242 return result; // 返回连接结果
243}
244
245} // namespace traffic_manager
246} // namespace carla
#define SOCK_INVALID_INDEX
Definition Sockets.h:19
#define IP_DATA_BUFFER_SIZE
SharedPtrType Lock() const
与 TryLock 相同,但永远不会返回 nullptr。
virtual void ShutDown()=0
关闭系统。
交通管理器本地类,通过消息传递机制整合交通管理器的各个阶段。 @inherits TrafficManagerBase
远程交通管理器类,通过消息传递机制整合交通管理的各个阶段。
void HealthCheckRemoteTM()
检查服务器是否存活。
static std::map< uint16_t, TrafficManagerBase * > _tm_map
存储交通管理器实例的静态映射表。
void ShutDown()
关闭交通管理器服务或客户端。
static std::mutex _mutex
用于保护_tm_map的静态互斥锁。
TrafficManagerBase * GetTM(uint16_t port) const
根据端口号获取交通管理器实例。
TrafficManager()
默认构造函数,不执行任何操作。
static void Tick()
执行TrafficManager的Tick操作,通常用于周期性地更新状态
static void Release()
释放TrafficManager对象,用于单例模式的清理工作
void CreateTrafficManagerServer(carla::client::detail::EpisodeProxy episode_proxy, uint16_t port)
创建交通管理器服务器。
bool CreateTrafficManagerClient(carla::client::detail::EpisodeProxy episode_proxy, uint16_t port)
创建交通管理器客户端。
static void Reset()
重置TrafficManager对象,用于单例模式的重置操作
uint16_t _port
当前交通管理器实例使用的端口号。
static const std::vector< float > LATERAL_HIGHWAY_PARAM
Definition Constants.h:154
static const std::vector< float > LONGITUDIAL_PARAM
Definition Constants.h:151
static const std::vector< float > LONGITUDIAL_HIGHWAY_PARAM
Definition Constants.h:152
static const std::vector< float > LATERAL_PARAM
Definition Constants.h:153
CARLA模拟器的主命名空间。
Definition Carla.cpp:139