CARLA
 
载入中...
搜索中...
未找到
RssCheck.cpp
浏览该文件的文档.
1// Copyright (c) 2019-2020 Intel Corporation
2//
3// This work is licensed under the terms of the MIT license.
4// For a copy, see <https://opensource.org/licenses/MIT>.
5
7
8#include <spdlog/sinks/stdout_color_sinks.h>
9#ifdef RSS_USE_TBB
10#include <tbb/tbb.h>
11#endif
12// 包含与地图访问相关的日志记录功能的头文件,用于在地图操作等过程中记录日志
13#include <ad/map/access/Logging.hpp>
14// 包含地图访问操作相关的头文件,定义了一些对地图进行查询、修改等操作的函数或类
15#include <ad/map/access/Operation.hpp>
16// 包含与地图中交叉路口相关操作的头文件
17#include <ad/map/intersection/Intersection.hpp>
18// 包含与地图中车道相关操作的头文件,例如车道信息查询、车道变换等操作的实现可能在这里面
19#include <ad/map/lane/Operation.hpp>
20// 包含地图匹配相关功能的头文件,用于将车辆等对象与地图中的位置进行匹配等操作
21#include <ad/map/match/AdMapMatching.hpp>
22// 包含地图匹配操作相关的头文件,对地图匹配结果进一步处理等操作的定义所在
23#include <ad/map/match/MapMatchedOperation.hpp>
24// 包含与路线中车道区间操作相关的头文件,用于处理路线上车道区间相关的逻辑,比如获取区间信息等
25#include <ad/map/route/LaneIntervalOperation.hpp>
26// 包含与路线操作相关的头文件
27#include <ad/map/route/Operation.hpp>
28// 包含与路线规划相关的头文件,涉及根据一些条件规划路线的功能实现
29#include <ad/map/route/Planning.hpp>
30// 包含 RSS 相关的地图日志记录功能的头文件,用于在 RSS 模块涉及地图操作时记录日志
31#include <ad/rss/map/Logging.hpp>
32// 包含 RSS 中对象转换相关的头文件,用于将不同格式或类型的对象进行转换以适配 RSS 相关处理逻辑
33#include <ad/rss/map/RssObjectConversion.hpp>
34// 包含 RSS 中对象数据相关的头文件,定义了表示 RSS 场景中对象的数据结构及相关操作
35#include <ad/rss/map/RssObjectData.hpp>
36// 包含 RSS 场景创建相关的头文件,用于创建 RSS 场景,组合各种对象及其关系等
37#include <ad/rss/map/RssSceneCreator.hpp>
38// 包含 RSS 状态操作相关的头文件
39#include <ad/rss/state/RssStateOperation.hpp>
40// 包含时间相关的头文件,用于处理时间戳、时间间隔等时间相关的操作
41#include <chrono>
42#include <tuple>
43
44#include "carla/client/Map.h"
47#include "carla/client/Walker.h"
49
50#define DEBUG_TIMING 0
51// 定义在carla命名空间的rss子命名空间中
52namespace carla {
53namespace rss {
54 // 定义一个函数printRoute,用于打印路由信息
55 // 参数包括一个描述路由的字符串route_descr和一个FullRoute类型的常量引用route
56void printRoute(std::string const &route_descr, ::ad::map::route::FullRoute const &route) {
57 // 首先打印出路由的描述信息
58 std::cout << route_descr << std::endl;
59 // 遍历路由中的每一个路段(road segment)
60 for (auto road_segment : route.roadSegments) {
61 // 对于每一个路段,遍历其所有可驾驶的车道段(lane segment)
62 for (auto lane_segment : road_segment.drivableLaneSegments) {
63 // 打印出车道段的详细信息,包括:
64 // 车道ID(laneId),转换为uint64_t类型
65 // 车道段的起始位置(start)和结束位置(end),转换为double类型,并保留两位小数
66 // 输出格式为:(车道ID | 起始位置:结束位置)
67 std::cout << "(" << static_cast<uint64_t>(lane_segment.laneInterval.laneId) << " | " << std::setprecision(2)
68 << static_cast<double>(lane_segment.laneInterval.start) << ":"
69 << static_cast<double>(lane_segment.laneInterval.end) << ") ";
70 }
71 // 每个路段的车道段信息打印完毕后,输出一个换行符,以便于区分不同的路段
72 std::cout << std::endl;
73 }
74}
75
76// 度到弧度转换常数 PI / 180
77constexpr float to_radians = static_cast<float>(M_PI) / 180.0f;
78// 定义了一个名为EgoDynamicsOnRoute的类
79// 在构造函数中初始化了多个成员变量
81 : time_since_epoch_check_start_ms(0.),
82 time_since_epoch_check_end_ms(0.),
83 ego_speed(0.),// 速度
84 min_stopping_distance(0.),// 停止距离
85 ego_center({0., 0., 0.}),// 中心位置
86 ego_heading(0.),//航向
87 ego_heading_change(0.),// 航向变化
88 ego_steering_angle(0.),// 转向角度
89 ego_center_within_route(false),
90 crossing_border(false),
91 route_heading(0.),
92 route_nominal_center({0., 0., 0.}),
93 heading_diff(0.),
94 route_speed_lat(0.),
95 route_speed_lon(0.),
96 route_accel_lat(0.),
97 route_accel_lon(0.),
98 avg_route_accel_lat(0.),
99 avg_route_accel_lon(0.) {
100 // 初始化时间戳对象中的已流逝秒数为 0
101 timestamp.elapsed_seconds = 0.;
102}
103// 获取一个指向 spdlog::logger 的共享指针,用于记录日志信息。这里创建了一个名为 "RssCheck" 的日志记录器,并且是线程安全的(通过 stdout_color_mt 函数创建),每次调用都会返回同一个静态实例
104std::shared_ptr<spdlog::logger> getLogger() {
105 static auto logger = spdlog::stdout_color_mt("RssCheck");
106 return logger;
107}
108// 获取一个指向 spdlog::logger 的共享指针,用于记录计时相关的日志信息。创建了一个名为 "RssCheckTiming" 的日志记录器,同样是线程安全的,每次调用返回同一个静态实例,用于记录特定的计时相关内容
109std::shared_ptr<spdlog::logger> getTimingLogger() {
110 static auto logger = spdlog::stdout_color_mt("RssCheckTiming");
111 return logger;
112}
113// RssCheck 类的成员函数,用于获取默认的车辆动力学参数配置,返回一个 ::ad::rss::world::RssDynamics 类型的对象,包含了车辆在纵向、横向等方向的加速度、刹车等参数设置
114::ad::rss::world::RssDynamics RssCheck::GetDefaultVehicleDynamics() {
115 ::ad::rss::world::RssDynamics default_ego_vehicle_dynamics;
116 // 设置纵向最大加速度,单位可能与具体的物理模拟相关,这里设置为 3.5(具体单位需结合项目其他部分确定)
117 default_ego_vehicle_dynamics.alphaLon.accelMax = ::ad::physics::Acceleration(3.5);
118 // 设置纵向最大刹车加速度,为负值表示减速,这里设置为 -8.
119 default_ego_vehicle_dynamics.alphaLon.brakeMax = ::ad::physics::Acceleration(-8.);
120 // 设置纵向最小刹车加速度,同样为负值,这里设置为 -4.
121 default_ego_vehicle_dynamics.alphaLon.brakeMin = ::ad::physics::Acceleration(-4.);
122 // 设置纵向最小修正刹车加速度,这里设置为 -3
123 default_ego_vehicle_dynamics.alphaLon.brakeMinCorrect = ::ad::physics::Acceleration(-3);
124 // 设置横向最大加速度,这里设置为 0.2
125 default_ego_vehicle_dynamics.alphaLat.accelMax = ::ad::physics::Acceleration(0.2);
126 // 设置横向最小刹车加速度,这里设置为 -0.8
127 default_ego_vehicle_dynamics.alphaLat.brakeMin = ::ad::physics::Acceleration(-0.8);
128 // 设置横向波动余量,单位为距离相关,这里设置为 0.1(具体单位结合项目确定)
129 default_ego_vehicle_dynamics.lateralFluctuationMargin = ::ad::physics::Distance(0.1);
130 // 设置响应时间,单位为时间相关,这里设置为 1.0(具体单位结合项目确定),表示车辆对外部情况做出反应的时间
131 default_ego_vehicle_dynamics.responseTime = ::ad::physics::Duration(1.0);
132 // 设置加速时的最大速度,这里设置为 100.(具体单位结合项目确定)
133 default_ego_vehicle_dynamics.maxSpeedOnAcceleration = ::ad::physics::Speed(100.);
134 // 设置行人转弯半径,单位为距离相关,这里设置为 2.0
135 default_ego_vehicle_dynamics.unstructuredSettings.pedestrianTurningRadius = ad::physics::Distance(2.0);
136 // 设置驶离最大角度,单位为角度相关,这里设置为 2.4(具体角度单位结合项目确定)
137 default_ego_vehicle_dynamics.unstructuredSettings.driveAwayMaxAngle = ad::physics::Angle(2.4);
138 // 设置车辆偏航角速度变化率,单位为角加速度相关,这里设置为 0.3(具体单位结合项目确定)
139 default_ego_vehicle_dynamics.unstructuredSettings.vehicleYawRateChange = ad::physics::AngularAcceleration(0.3);
140 // 设置车辆最小转弯半径,单位为距离相关,这里设置为 3.5
141 default_ego_vehicle_dynamics.unstructuredSettings.vehicleMinRadius = ad::physics::Distance(3.5);
142 // 设置车辆轨迹计算步长,单位为时间相关,这里设置为 0.2
143 default_ego_vehicle_dynamics.unstructuredSettings.vehicleTrajectoryCalculationStep = ad::physics::Duration(0.2);
144 return default_ego_vehicle_dynamics;
145}
146// RssCheck 类的成员函数,用于获取默认的行人动力学参数配置,返回一个 ::ad::rss::world::RssDynamics 类型的对象,同样包含了行人在不同方向的加速度、刹车等相关参数设置
147::ad::rss::world::RssDynamics RssCheck::GetDefaultPedestrianDynamics() {
148 ::ad::rss::world::RssDynamics default_pedestrian_dynamics;
149 // 设置行人纵向最大加速度,这里设置为 2.0
150 default_pedestrian_dynamics.alphaLon.accelMax = ::ad::physics::Acceleration(2.0);
151 // 设置行人纵向最大刹车加速度,这里设置为 -4.
152 default_pedestrian_dynamics.alphaLon.brakeMax = ::ad::physics::Acceleration(-4.);
153 // 设置行人纵向最小刹车加速度,这里设置为 -2.
154 default_pedestrian_dynamics.alphaLon.brakeMin = ::ad::physics::Acceleration(-2.);
155 // 设置行人纵向最小修正刹车加速度,这里设置为 -2.
156 default_pedestrian_dynamics.alphaLon.brakeMinCorrect = ::ad::physics::Acceleration(-2.);
157 // 设置行人横向最大加速度,这里设置为 0.001,数值较小符合行人横向移动相对缓慢的特点
158 default_pedestrian_dynamics.alphaLat.accelMax = ::ad::physics::Acceleration(0.001);
159 / 设置行人横向最小刹车加速度,这里设置为 -0.001
160 default_pedestrian_dynamics.alphaLat.brakeMin = ::ad::physics::Acceleration(-0.001);
161 // 设置行人横向波动余量,这里设置为 0.1
162 default_pedestrian_dynamics.lateralFluctuationMargin = ::ad::physics::Distance(0.1);
163 // 设置行人响应时间,这里设置为 0.5,通常行人反应时间相对车辆可能较短一些(具体取决于模拟设定)
164 default_pedestrian_dynamics.responseTime = ::ad::physics::Duration(0.5);
165 // 设置行人加速时的最大速度,这里设置为 10.
166 default_pedestrian_dynamics.maxSpeedOnAcceleration = ::ad::physics::Speed(10.);
167 // 设置行人转弯半径,这里设置为 2.0
168 default_pedestrian_dynamics.unstructuredSettings.pedestrianTurningRadius = ad::physics::Distance(2.0);
169 // 设置行人驶离最大角度,这里设置为 2.4
170 default_pedestrian_dynamics.unstructuredSettings.driveAwayMaxAngle = ad::physics::Angle(2.4);
171 // 设置行人相关的车辆偏航角速度变化率(虽然对于行人来说这个概念有点不太常规,但可能在统一的模拟框架中有相关用途),这里设置为 0.3
172 default_pedestrian_dynamics.unstructuredSettings.vehicleYawRateChange = ad::physics::AngularAcceleration(0.3);
173 // 设置行人相关的车辆最小转弯半径(同样,可能是在统一框架下的一种设定),这里设置为 3.5
174 default_pedestrian_dynamics.unstructuredSettings.vehicleMinRadius = ad::physics::Distance(3.5);
175 // 设置行人相关的车辆轨迹计算步长,这里设置为 0.2
176 default_pedestrian_dynamics.unstructuredSettings.vehicleTrajectoryCalculationStep = ad::physics::Duration(0.2);
177
178 return default_pedestrian_dynamics;
179}
180
181RssCheck::RssCheck(float maximum_steering_angle)// 设置允许的最大转向角度
182// 初始化成员变量
183 : _maximum_steering_angle(maximum_steering_angle), _road_boundaries_mode(GetDefaultRoadBoundariesMode()) {
184 // 获取标准的日志记录器
185 _logger = getLogger();
186 // 获取专门用于计时的日志记录器
188 // 将计时日志记录器的级别设置为关闭
189 _timing_logger->set_level(spdlog::level::off);
190// 设置全局和地图相关的日志级别为警告
191 SetLogLevel(spdlog::level::warn);
192 SetMapLogLevel(spdlog::level::warn);
193// 获取并设置行人的自我车辆动态回调
195 //获取并设置其他车辆的默认动态回调
197 // 将其他车辆的响应时间设置为 2 秒;其余保持不变
198 _default_actor_constellation_callback_other_vehicle_dynamics.responseTime = ::ad::physics::Duration(2.0);
199 // 获取行人的默认动态回调
201
202 //创建一个默认回调.
203 // 回调函数
205 [this](carla::SharedPtr<::carla::rss::ActorConstellationData> actor_constellation_data)
207 ::carla::rss::ActorConstellationResult actor_constellation_result;
208
209 actor_constellation_result.rss_calculation_mode = ::ad::rss::map::RssMode::NotRelevant;
210 actor_constellation_result.restrict_speed_limit_mode =
211 ::ad::rss::map::RssSceneCreation::RestrictSpeedLimitMode::IncreasedSpeedLimit10;
212 actor_constellation_result.actor_object_type = ad::rss::world::ObjectType::Invalid;
215
216 if (actor_constellation_data->other_actor != nullptr) {
217 if (boost::dynamic_pointer_cast<carla::client::Walker>(actor_constellation_data->other_actor) != nullptr) {
218 actor_constellation_result.rss_calculation_mode = ::ad::rss::map::RssMode::Unstructured;
219 actor_constellation_result.actor_object_type = ad::rss::world::ObjectType::Pedestrian;
221 } else if (boost::dynamic_pointer_cast<carla::client::Vehicle>(actor_constellation_data->other_actor) !=
222 nullptr) {
223 actor_constellation_result.rss_calculation_mode = ::ad::rss::map::RssMode::Structured;
224 actor_constellation_result.actor_object_type = ad::rss::world::ObjectType::OtherVehicle;
225
226 if (GetSpeed(*actor_constellation_data->other_actor) == ::ad::physics::Speed(0.)) {
227 /*
228 对静止不动的车辆进行特殊处理,以应对核心 RSS 实现中尚未实现的横向交叉路口检查。
229 如果另一个待着不动,我们就不会假设他会加速;
230 否则,如果待在十字路口,反应时间内的加速度将使车进入十字路口,当前的 RSS 实现将会立即认为这是危险的。
231
232 */
233 actor_constellation_result.actor_dynamics.alphaLon.accelMax = ::ad::physics::Acceleration(0.);
234 }
235 }
236 }
237
238 /*
239 由于 Ego 车辆是手动控制的,因此 Ego 车辆在横向加速度很可能远高于自动控制时的加速度
240 在自动驾驶汽车中,当合理利用 RSS 实现时,会考虑到低级控制器
241 但是 CARLA 中的简单 RSS 限制器无法做到这一点...
242 因此,我们至少应该告诉 RSS 我们的加速度超过这个数值时,及时对此做出反应。
243
244 */
245 auto const abs_avg_route_accel_lat = std::fabs(actor_constellation_data->ego_dynamics_on_route.avg_route_accel_lat);
246 if (abs_avg_route_accel_lat > actor_constellation_result.ego_vehicle_dynamics.alphaLat.accelMax) {
247 actor_constellation_result.ego_vehicle_dynamics.alphaLat.accelMax =
248 std::min(ad::physics::Acceleration(20.), abs_avg_route_accel_lat);
249 }
250 return actor_constellation_result;
251 };
252
253 // 设置默认动态
255
256 _logger->debug("RssCheck with default actor constellation callback created");
257}
258// RssCheck类的构造函数
259// 参数:
260// - maximum_steering_angle:最大转向角度
261// - rss_actor_constellation_callback:参与者星座回调函数类型,用于获取参与者星座相关信息
262// - carla_ego_actor:指向CARLA中自车参与者的共享指针
263RssCheck::RssCheck(float maximum_steering_angle,
264 ActorConstellationCallbackFunctionType rss_actor_constellation_callback,
265 carla::SharedPtr<carla::client::Actor> const &carla_ego_actor)
266 : _maximum_steering_angle(maximum_steering_angle),
267 _actor_constellation_callback(rss_actor_constellation_callback),
268 _road_boundaries_mode(GetDefaultRoadBoundariesMode()) {
269 // 获取日志记录器实例,用于记录各类日志信息
270 _logger = getLogger();
271 // 获取计时日志记录器实例,用于记录时间相关的日志信息
273 // 将计时日志记录器的日志级别设置为关闭(不记录)
274 _timing_logger->set_level(spdlog::level::off);
275// 设置整体的日志级别为警告级别
276 SetLogLevel(spdlog::level::warn);
277 // 设置地图相关的日志级别为警告级别
278 SetMapLogLevel(spdlog::level::warn);
279 // 获取与自车参与者匹配的对象,允许车辆距离路线至少2.0米,以免丧失与路线的接触
280 _carla_rss_state.ego_match_object = GetMatchObject(carla_ego_actor, ::ad::physics::Distance(2.0));
281 // 更新默认的RSS动力学相关信息
283 // 在日志中输出调试信息,表示RssCheck对象已创建
284 _logger->debug("RssCheck created");
285}
286// RssCheck类的析构函数,这里为空实现,可能在子类中会有具体的资源释放等操作
288// 设置日志级别,对spdlog库和RssCheck类的内部_logger都生效
289void RssCheck::SetLogLevel(const spdlog::level::level_enum &log_level) {
290 spdlog::set_level(log_level); // 设置全局spdlog日志级别
291 _logger->set_level(log_level); // 设置RssCheck类内部_logger的日志级别
292}
293// 设置地图日志级别,对ad::map和ad::rss::map模块的日志器生效
294void RssCheck::SetMapLogLevel(const spdlog::level::level_enum &map_log_level) {
295 ::ad::map::access::getLogger()->set_level(map_log_level); // 设置ad::map模块的日志级别
296 ::ad::rss::map::getLogger()->set_level(map_log_level); // 设置ad::rss::map模块的日志级别
297}
298// 获取默认的自我车辆动态参数,这些参数用于RSS检查回调
302// 设置默认的自我车辆动态参数
304 const ::ad::rss::world::RssDynamics &ego_vehicle_dynamics) {
306}
307// 获取默认的其他车辆动态参数,这些参数用于RSS检查回调
311// 设置默认的其他车辆动态参数
313 const ::ad::rss::world::RssDynamics &other_vehicle_dynamics) {
315}
316// 获取默认的行人动态参数
320// 设置默认的行人动态参数
322 const ::ad::rss::world::RssDynamics &pedestrian_dynamics) {
324}
325// 获取道路边界模式
326const ::carla::rss::RoadBoundariesMode &RssCheck::GetRoadBoundariesMode() const {
328}
329// 设置道路边界模式
330void RssCheck::SetRoadBoundariesMode(const ::carla::rss::RoadBoundariesMode &road_boundaries_mode) {
331 _road_boundaries_mode = road_boundaries_mode;
332}
333// 向RssCheck类添加路由目标,这些目标用于RSS检查
336 ::ad::map::point::createENUPoint(routing_target.location.x, -1. * routing_target.location.y, 0.));
337}
338// 获取路由目标列表信息(常量函数)
339// 返回值:包含路由目标坐标变换信息的向量
340const std::vector<::carla::geom::Transform> RssCheck::GetRoutingTargets() const {
341 std::vector<::carla::geom::Transform> routing_targets;
342 // 判断输入范围是否有效,如果有效则进行后续处理
343 if (withinValidInputRange(_routing_targets)) {
344 for (auto const &target : _routing_targets) {
345 ::carla::geom::Transform routing_target;
346 routing_target.location.x = static_cast<float>(target.x);
347 routing_target.location.y = static_cast<float>(-target.y);
348 routing_target.location.z = 0.f;
349 routing_targets.push_back(routing_target);
350 }
351 }
352 return routing_targets;
353}
354// 重置路由目标,清空已有的路由目标列表和待添加的路由目标列表
359// 放弃当前路线,在日志中输出相关调试信息,并将自车的路线设置为空路线
361 _logger->debug("Dropping Route:: {}", _carla_rss_state.ego_route);
362 _carla_rss_state.ego_route = ::ad::map::route::FullRoute();
363}
364// 检查对象相关信息,进行一系列的逻辑判断和操作
365// 参数:
366// - timestamp:时间戳信息
367// - actors:指向参与者列表的共享指针
368// - carla_ego_actor:指向自车参与者的共享指针
369// - output_response:用于输出合适响应的对象
370// - output_rss_state_snapshot:用于输出RSS状态快照的对象
371// - output_situation_snapshot:用于输出情况快照的对象
372// - output_world_model:用于输出世界模型的对象
373// - output_rss_ego_dynamics_on_route:用于输出自车在路线上的RSS动力学信息的对象
374// 返回值:表示检查结果的布尔值,成功为true,失败为false
377 carla::SharedPtr<carla::client::Actor> const &carla_ego_actor,
378 ::ad::rss::state::ProperResponse &output_response,
379 ::ad::rss::state::RssStateSnapshot &output_rss_state_snapshot,
380 ::ad::rss::situation::SituationSnapshot &output_situation_snapshot,
381 ::ad::rss::world::WorldModel &output_world_model,
382 EgoDynamicsOnRoute &output_rss_ego_dynamics_on_route) {
383 bool result = false;
384 try {
385 // 获取从纪元开始到当前检查开始的时间(以毫秒为单位)
386 double const time_since_epoch_check_start_ms =
387 std::chrono::duration<double, std::milli>(std::chrono::system_clock::now().time_since_epoch()).count();
388#if DEBUG_TIMING
389 // 在调试模式下,输出时间相关信息以及开始检查对象的提示信息
390 std::cout << "--- time: " << timestamp.frame << ", " << timestamp.elapsed_seconds << std::endl;
391 auto t_start = std::chrono::high_resolution_clock::now();
392 auto t_end = std::chrono::high_resolution_clock::now();
393 std::cout << "-> SC " << std::chrono::duration<double, std::milli>(t_end - t_start).count() << " start checkObjects"
394 << std::endl;
395#endif
396// 将传入的自车参与者指针转换为车辆类型的共享指针,如果转换失败则返回nullptr
397 const auto carla_ego_vehicle = boost::dynamic_pointer_cast<carla::client::Vehicle>(carla_ego_actor);
398 if (carla_ego_vehicle == nullptr) {
399 // 如果自车不是车辆类型,则在日志中输出错误信息,提示RSS传感器仅支持车辆作为自车
400 _logger->error("RSS Sensor only support vehicles as ego.");
401 }
402
403#if DEBUG_TIMING
404 t_end = std::chrono::high_resolution_clock::now();
405 std::cout << "-> ME " << std::chrono::duration<double, std::milli>(t_end - t_start).count()
406 << " before MapMatching" << std::endl;
407#endif
408
409 //允许车辆距离路线至少 2.0 米,以免丧失
410 //与路线的接触
411 auto const ego_match_object = GetMatchObject(carla_ego_actor, ::ad::physics::Distance(2.0));
412
413 if (::ad::map::point::isValid(_carla_rss_state.ego_match_object.enuPosition.centerPoint, false)) {
414 // check for bigger position jumps of the ego vehicle
415 auto const travelled_distance = ::ad::map::point::distance(
416 _carla_rss_state.ego_match_object.enuPosition.centerPoint, ego_match_object.enuPosition.centerPoint);
417 if (travelled_distance > ::ad::physics::Distance(10.)) {
418 // 如果距离大于设定值(10.),则在日志中输出警告信息,提示检测到自车位置跳跃,并强制重新规划路线
419 _logger->warn("Jump in ego vehicle position detected {} -> {}! Force reroute!",
420 _carla_rss_state.ego_match_object.enuPosition.centerPoint,
421 ego_match_object.enuPosition.centerPoint);
422 DropRoute();
423 }
424 }
425// 将计算得到的与自车匹配的对象赋值给_carla_rss_state中的对应成员变量
426 _carla_rss_state.ego_match_object = ego_match_object;
427// 在日志中以跟踪级别(trace)输出自车匹配对象的相关信息,方便调试查看具体匹配情况
428 _logger->trace("MapMatch:: {}", _carla_rss_state.ego_match_object);
429
430#if DEBUG_TIMING
431 // 获取当前时间,用于记录时间相关的调试信息,此处表示地图匹配自车部分结束的时间记录
432 t_end = std::chrono::high_resolution_clock::now();
433 std::cout << "-> ME " << std::chrono::duration<double, std::milli>(t_end - t_start).count()
434 << " after ego MapMatching" << std::endl;
435#endif
436// 根据当前状态更新路线信息,可能涉及根据匹配对象等重新规划、调整自车的行驶路线等操作
438
439#if DEBUG_TIMING
440 t_end = std::chrono::high_resolution_clock::now();
441 std::cout << "-> RU " << std::chrono::duration<double, std::milli>(t_end - t_start).count()
442 << " after route update " << std::endl;
443#endif
444// 计算自车在路线上的动力学信息,传入多个相关参数,包括时间戳、起始检查时间、自车车辆信息、自车匹配对象、自车路线以及默认的自车动力学信息等,并结合之前的动力学信息进行更新计算
446 timestamp, time_since_epoch_check_start_ms, *carla_ego_vehicle, _carla_rss_state.ego_match_object,
449// 根据当前的_carla_rss_state状态更新默认的RSS动力学相关信息,可能涉及根据自车当前状态调整一些默认的动力学参数等
451// 根据传入的时间戳、参与者列表、自车车辆信息以及当前的_carla_rss_state状态来创建世界模型,这个世界模型应该包含了整个场景中相关对象的信息等
452 CreateWorldModel(timestamp, *actors, *carla_ego_vehicle, _carla_rss_state);
453
454#if DEBUG_TIMING
455 t_end = std::chrono::high_resolution_clock::now();
456 std::cout << "-> WM " << std::chrono::duration<double, std::milli>(t_end - t_start).count()
457 << " after create world model " << std::endl;
458#endif
459// 执行实际的检查操作,根据当前的_carla_rss_state状态来判断是否存在某些情况(比如安全风险等),返回检查结果(布尔值),并将结果赋值给result变量
460 result = PerformCheck(_carla_rss_state);
461
462#if DEBUG_TIMING
463 t_end = std::chrono::high_resolution_clock::now();
464 std::cout << "-> CH " << std::chrono::duration<double, std::milli>(t_end - t_start).count() << " end RSS check"
465 << std::endl;
466#endif
467// 对检查结果进行分析,可能涉及更深入地查看结果中的各项指标、状态等,以便后续进一步处理或者记录相关信息
468 AnalyseCheckResults(_carla_rss_state);
469
470#if DEBUG_TIMING
471 t_end = std::chrono::high_resolution_clock::now();
472 std::cout << "-> AN " << std::chrono::duration<double, std::milli>(t_end - t_start).count()
473 << " end analyze results" << std::endl;
474#endif
475// 记录自车动力学在检查结束时的时间戳(从纪元开始到当前的时间,以毫秒为单位),用于后续统计或者记录整个检查过程的时间相关信息
477 std::chrono::duration<double, std::milli>(std::chrono::system_clock::now().time_since_epoch()).count();
478// 将检查过程中得到的相关结果存储到输出参数中,方便外部调用者获取此次检查的各项信息,例如合适的响应、RSS状态快照、情况快照、世界模型以及自车在路线上的动力学信息等
479// 存储合适响应信息
480 // 存储结果
481 output_response = _carla_rss_state.proper_response;
482 // 存储RSS状态快照信息
483 output_rss_state_snapshot = _carla_rss_state.rss_state_snapshot;
484 // 存储情况快照信息
485 output_situation_snapshot = _carla_rss_state.situation_snapshot;
486 // 存储世界模型信息
487 output_world_model = _carla_rss_state.world_model;
488 output_rss_ego_dynamics_on_route = _carla_rss_state.ego_dynamics_on_route;
489 // 存储自车在路线上的动力学信息
491 _logger->debug("===== ROUTE NOT SAFE =====");
492 } else {
493 _logger->debug("===== ROUTE SAFE =====");
494 }
495
496#if DEBUG_TIMING
497 t_end = std::chrono::high_resolution_clock::now();
498 std::cout << "-> EC " << std::chrono::duration<double, std::milli>(t_end - t_start).count() << " end check objects"
499 << std::endl;
500#endif
501 } catch (...) {
502 // 如果在检查过程中出现任何异常,在日志中记录错误信息,表示检查失败
503 _logger->error("Exception -> Check failed");
504 }
505 // 返回最终的检查结果(布尔值),外部调用者可根据此结果判断整体检查情况
506 return result;
507}
508// 获取与给定参与者(actor)匹配的对象信息,传入参与者指针以及采样距离作为参数,返回匹配后的对象信息
510 ::ad::physics::Distance const &sampling_distance) const {
511 // 创建一个待返回的匹配对象实例
512 ::ad::map::match::Object match_object;
513// 获取参与者(actor)的坐标变换信息,可能包含位置、旋转等信息
514 auto const vehicle_transform = actor->GetTransform();
515 // 将参与者在世界坐标系中的x坐标转换为ENU坐标格式,并赋值给匹配对象的中心坐标x分量
516 match_object.enuPosition.centerPoint.x = ::ad::map::point::ENUCoordinate(vehicle_transform.location.x);
517 // 将参与者在世界坐标系中的y坐标取反后转换为ENU坐标格式,并赋值给匹配对象的中心坐标y分量
518 match_object.enuPosition.centerPoint.y = ::ad::map::point::ENUCoordinate(-1. * vehicle_transform.location.y);
519 // 将参与者在世界坐标系中的z坐标转换为ENU坐标格式(此处原代码注释掉了直接使用vehicle_transform.location.z的部分,可能存在特殊考虑),并赋值给匹配对象的中心坐标z分量
520 match_object.enuPosition.centerPoint.z = ::ad::map::point::ENUCoordinate(0.); // vehicle_transform.location.z;
521 // 根据参与者的旋转角度(yaw,偏航角)创建ENU坐标下的朝向信息,并赋值给匹配对象的朝向属性,这里进行了角度单位转换(可能是转换为弧度制,假设to_radians是角度转弧度的常量或者函数)
522 match_object.enuPosition.heading =
523 ::ad::map::point::createENUHeading(-1 * vehicle_transform.rotation.yaw * to_radians);
524 // 将参与者指针尝试转换为车辆类型的共享指针,如果转换成功,表示参与者是车辆类型
525 auto const vehicle = boost::dynamic_pointer_cast<carla::client::Vehicle>(actor);
526 // 将参与者指针尝试转换为行人类型的共享指针,如果转换成功,表示参与者是行人类型
527 auto const walker = boost::dynamic_pointer_cast<carla::client::Walker>(actor);
528 if (vehicle != nullptr) {
529 // 如果参与者是车辆类型,获取车辆的包围盒信息(bounding box),通常包含车辆在各个方向上的尺寸范围
530 const auto &bounding_box = vehicle->GetBoundingBox();
531 // 根据包围盒在x方向上的尺寸(extent.x)计算并设置匹配对象在ENU坐标下的长度属性,乘以2可能是考虑包围盒尺寸是从中心到边缘的距离,这里获取整体长度
532 match_object.enuPosition.dimension.length = ::ad::physics::Distance(2 * bounding_box.extent.x);
533 // 同理,根据包围盒在y方向上的尺寸计算并设置匹配对象在ENU坐标下的宽度属性
534 match_object.enuPosition.dimension.width = ::ad::physics::Distance(2 * bounding_box.extent.y);
535 // 根据包围盒在z方向上的尺寸计算并设置匹配对象在ENU坐标下的高度属性
536 match_object.enuPosition.dimension.height = ::ad::physics::Distance(2 * bounding_box.extent.z);
537 } else if (walker != nullptr) {
538 // 如果参与者是行人类型,获取行人的包围盒信息
539 const auto &bounding_box = walker->GetBoundingBox();
540 // 按照与车辆类似的方式,根据行人包围盒在各个方向上的尺寸设置匹配对象相应的长度、宽度、高度属性
541 match_object.enuPosition.dimension.length = ::ad::physics::Distance(2 * bounding_box.extent.x);
542 match_object.enuPosition.dimension.width = ::ad::physics::Distance(2 * bounding_box.extent.y);
543 match_object.enuPosition.dimension.height = ::ad::physics::Distance(2 * bounding_box.extent.z);
544 } else {
545 // 如果参与者既不是车辆也不是行人类型,在日志中记录错误信息,提示无法获取该参与者的包围盒信息,并输出参与者的ID,方便排查问题
546 _logger->error("Could not get bounding box of actor {}", actor->GetId());
547 }
548 // 获取ENU坐标参考点信息,并赋值给匹配对象的ENU参考点属性,这个参考点可能用于后续的坐标转换、匹配等相关操作的基准
549 match_object.enuPosition.enuReferencePoint = ::ad::map::access::getENUReferencePoint();
550// 创建地图匹配相关的实例,用于执行地图匹配操作,获取匹配后的包围盒信息
551 ::ad::map::match::AdMapMatching map_matching;
552 // 通过地图匹配实例,根据匹配对象的ENU位置信息以及给定的采样距离,获取地图匹配后的包围盒信息,并赋值给匹配对象的相应属性
553 match_object.mapMatchedBoundingBox =
554 map_matching.getMapMatchedBoundingBox(match_object.enuPosition, sampling_distance);
555 // 返回最终构建好的匹配对象信息,包含了坐标、尺寸、朝向以及地图匹配后的包围盒等相关信息
556 return match_object;
557}
558// 根据给定的参与者(actor)获取其速度信息,返回对应的物理速度(Speed)类型的数值
559::ad::physics::Speed RssCheck::GetSpeed(carla::client::Actor const &actor) const {
560 // 获取参与者的速度向量信息,通常包含在各个坐标轴方向上的速度分量
561 auto velocity = actor.GetVelocity();
562 // 获取参与者的坐标变换信息(可能包含旋转等信息),用于后续对速度向量进行旋转操作
563 auto const actor_transform = actor.GetTransform();
564 // 根据参与者的旋转信息对速度向量进行反向旋转操作,可能是为了将速度转换到某个特定的参考坐标系下
565 actor_transform.rotation.InverseRotateVector(velocity);
566 // 根据旋转后的速度向量在x和y方向上的分量计算速度的大小(二维平面上的速度大小),通过勾股定理计算,创建一个物理速度类型(::ad::physics::Speed)的实例
567 ::ad::physics::Speed speed(std::sqrt(velocity.x * velocity.x + velocity.y * velocity.y));
568 // 如果速度在x方向上的分量小于0,表示速度方向与设定的正方向相反,将速度取反,以符合特定的速度正负表示规则
569 if (velocity.x < 0.) {
570 speed = -speed;
571 }
572 // 返回最终计算得到的参与者的速度信息,以符合要求的物理速度类型返回
573 return speed;
574}
575
576::ad::physics::AngularVelocity RssCheck::GetHeadingChange(carla::client::Actor const &actor) const {
577 auto const angular_velocity = actor.GetAngularVelocity();
578 ::ad::physics::AngularVelocity heading_change(-1. * angular_velocity.z * to_radians);
579 return heading_change;
580}
581
582::ad::physics::Angle RssCheck::GetSteeringAngle(carla::client::Vehicle const &actor) const {
583 auto const steer_ratio = actor.GetControl().steer;
584 ::ad::physics::Angle steering_angle(-1 * _maximum_steering_angle * steer_ratio);
585 return steering_angle;
586}
587
588void RssCheck::UpdateRoute(CarlaRssState &carla_rss_state) {
589 _logger->trace("Update route start: {}", carla_rss_state.ego_route);
590
591 // 移除已走过的路线部分,尝试将路线段前置
592 // (i.e. when driving backwards)
593 // 尽量确保车辆的后部仍在路线范围内
594 // 支持方向计算
595 ::ad::map::point::ParaPointList all_lane_matches;
596 for (auto reference_point :
597 {::ad::map::match::ObjectReferencePoints::RearRight, ::ad::map::match::ObjectReferencePoints::RearLeft}) {
598 auto const &reference_position =
599 carla_rss_state.ego_match_object.mapMatchedBoundingBox.referencePointPositions[size_t(reference_point)];
600 auto const para_points = ::ad::map::match::getParaPoints(reference_position);
601 all_lane_matches.insert(all_lane_matches.end(), para_points.begin(), para_points.end());
602 }
603
604 auto shorten_route_result = ::ad::map::route::shortenRoute(
605 all_lane_matches, carla_rss_state.ego_route,
606 ::ad::map::route::ShortenRouteMode::DontCutIntersectionAndPrependIfSucceededBeforeRoute);
607 if (shorten_route_result == ::ad::map::route::ShortenRouteResult::SucceededIntersectionNotCut) {
608 shorten_route_result = ::ad::map::route::ShortenRouteResult::Succeeded;
609 }
610
611 bool routing_target_check_finished = false;
612 while ((!_routing_targets.empty()) && (!routing_target_check_finished)) {
613 auto const next_target = _routing_targets.front();
614 auto const &distance_to_next_target =
615 ::ad::map::point::distance(next_target, carla_rss_state.ego_match_object.enuPosition.centerPoint);
616 if (distance_to_next_target < ::ad::physics::Distance(3.)) {
617 _routing_targets.erase(_routing_targets.begin());
618 _logger->debug("Next target reached: {}; remaining targets: {}", next_target, _routing_targets);
619 } else {
620 routing_target_check_finished = true;
621 }
622 }
623
624 bool reroute_required = false;
625 if (!_routing_targets_to_append.empty()) {
626 reroute_required = true;
629 _logger->debug("Appending new routing targets: {}; resulting targets: {}", _routing_targets_to_append,
632 }
633
634 ::ad::physics::Distance const route_target_length(50.);
635
636 if ((!reroute_required) && (shorten_route_result == ::ad::map::route::ShortenRouteResult::Succeeded)) {
637 std::vector<::ad::map::route::FullRoute> additional_routes;
638 auto const route_valid =
639 ::ad::map::route::extendRouteToDistance(carla_rss_state.ego_route, route_target_length, additional_routes);
640
641 if (route_valid) {
642 if (additional_routes.size() > 0u) {
643 // 对路由进行随机扩展
644 std::size_t route_index = static_cast<std::size_t>(std::rand()) % (additional_routes.size() + 1);
645 if (route_index < additional_routes.size()) {
646 // 我们决定选择其中一条额外的路线
647 _logger->debug("Additional Routes: {}->{}", additional_routes.size(), route_index);
648 carla_rss_state.ego_route = additional_routes[route_index];
649 } else {
650 // 我们决定在路线内进行扩展,不进行任何改动
651 _logger->debug("Additional Routes: expand current");
652 }
653 }
654 } else {
655 reroute_required = true;
656 }
657 } else {
658 // 对于所有其他结果,我们重新创建路线
659 reroute_required = true;
660 }
661
662 // 如有需要,创建路线
663 if (reroute_required) {
664 // try to create routes
665 // 创建一个用于存储所有新路线的向量,每条路线的类型为::ad::map::route::FullRoute
666 std::vector<::ad::map::route::FullRoute> all_new_routes;
667 // 遍历自车匹配对象的地图匹配包围盒中的参考点位置(这里取的是中心位置对应的参考点集合)
668 for (const auto &position :
669 carla_rss_state.ego_match_object.mapMatchedBoundingBox
670 .referencePointPositions[int32_t(::ad::map::match::ObjectReferencePoints::Center)]) {
671 // 获取起始点信息,这里是从参考点位置中的车道点(lanePoint)里获取参数化点(paraPoint)作为起始点
672 auto start_point = position.lanePoint.paraPoint;
673 // 初始化一个投影后的起始点,初始值与原始起始点相同,后续可能根据一些条件进行更新
674 auto projected_start_point = start_point;
675 if (!::ad::map::lane::isHeadingInLaneDirection(start_point,
676 carla_rss_state.ego_match_object.enuPosition.heading)) {
677 // 如果自车朝向与车道方向相反,在日志中输出调试信息提示
678 _logger->debug("EgoVehicle heading in opposite lane direction");
679 // 尝试将起始点投影到与自车朝向一致的车道方向上,若投影成功
680 if (::ad::map::lane::projectPositionToLaneInHeadingDirection(
681 start_point, carla_rss_state.ego_match_object.enuPosition.heading, projected_start_point)) {
682 // 在日志中输出调试信息,显示投影后的车道ID,方便调试查看具体投影情况
683 _logger->debug("Projected to lane {}", projected_start_point.laneId);
684 }
685 }
686 // 在日志中输出调试信息,显示原始起始点和投影后的起始点信息,方便对比查看
687 _logger->debug("Route start_point: {}, projected_start_point: {}", start_point, projected_start_point);
688 // 根据投影后的起始点和自车的朝向信息创建一个用于路径规划的起始点(routing_start_point),用于后续生成路线
689 auto routing_start_point = ::ad::map::route::planning::createRoutingPoint(
690 projected_start_point, carla_rss_state.ego_match_object.enuPosition.heading);
691 // 判断是否存在目标路由点(_routing_targets)且其是有效的
692 if (!_routing_targets.empty() && ::ad::map::point::isValid(_routing_targets)) {
693 // 根据起始点和目标路由点规划一条新的路线,使用指定的路线创建模式(AllRoutableLanes,可能表示可通行的所有车道)
694 auto new_route = ::ad::map::route::planning::planRoute(routing_start_point, _routing_targets,
695 ::ad::map::route::RouteCreationMode::AllRoutableLanes);
696 // 将新规划的路线添加到所有新路线的向量中
697 all_new_routes.push_back(new_route);
698 } else {
699 // 如果没有指定目标路由点,则根据起始点、预设的路线目标长度以及指定的路线创建模式预测生成一系列路线(可能是基于一定距离延伸的多条路线)
700 auto new_routes = ::ad::map::route::planning::predictRoutesOnDistance(
701 routing_start_point, route_target_length, ::ad::map::route::RouteCreationMode::AllRoutableLanes);
702// 遍历预测生成的每条新路线,并将它们都添加到所有新路线的向量中
703 for (const auto &new_route : new_routes) {
704 // 延长所有车道的路线
705 all_new_routes.push_back(new_route);
706 }
707 }
708 }
709 // 在日志中输出调试信息,显示新生成的路线数量,方便查看规划情况
710 _logger->debug("New routes: {}", all_new_routes.size());
711// 判断是否成功生成了新的路线
712 if (!all_new_routes.empty()) {
713 // take a random route
714 // 如果有新路线,随机选择一条路线作为最终采用的路线
715 // 通过生成一个随机数作为索引来选择路线,将随机数转换为合适的size_t类型,确保索引在有效范围内(取模运算保证不会越界)
716 std::size_t route_index = static_cast<std::size_t>(std::rand()) % (all_new_routes.size());
717 // 将随机选择的路线赋值给自车的路线(carla_rss_state.ego_route),更新自车的行驶路线
718 carla_rss_state.ego_route = all_new_routes[route_index];
719 }
720 }
721 // 在日志中以跟踪级别(trace)输出更新路线后的结果信息,方便调试查看具体的路线情况
722 _logger->trace("Update route result: {}", carla_rss_state.ego_route);
723}
724// 定义函数CalculateEgoDynamicsOnRoute,用于计算自车在路线上的动力学信息
725// 参数包括当前时间戳、从纪元开始到检查开始的时间(以毫秒为单位)、自车车辆信息、自车匹配对象、完整的路线信息、默认的自车动力学信息以及上一次的自车动力学信息
727 carla::client::Timestamp const &current_timestamp, double const &time_since_epoch_check_start_ms,
728 carla::client::Vehicle const &carla_vehicle, ::ad::map::match::Object match_object,
729 ::ad::map::route::FullRoute const &route, ::ad::rss::world::RssDynamics const &default_ego_vehicle_dynamics,
730 EgoDynamicsOnRoute const &last_dynamics) const {
731 // 创建一个新的自车动力学信息结构体实例,用于存储本次计算得到的动力学信息
732 EgoDynamicsOnRoute new_dynamics;
733 // 将传入的当前时间戳赋值给新的动力学信息结构体中的时间戳成员变量
734 new_dynamics.timestamp = current_timestamp;
735 // 将传入的从纪元开始到检查开始的时间赋值给新的动力学信息结构体中的对应成员变量
736 new_dynamics.time_since_epoch_check_start_ms = time_since_epoch_check_start_ms;
737 // 调用GetSpeed函数获取自车的速度信息,并赋值给新的动力学信息结构体中的速度成员变量
738 new_dynamics.ego_speed = GetSpeed(carla_vehicle);
739 // 将自车匹配对象的中心坐标赋值给新的动力学信息结构体中的自车中心坐标成员变量
740 new_dynamics.ego_center = match_object.enuPosition.centerPoint;
741 // 将自车匹配对象的朝向信息赋值给新的动力学信息结构体中的自车朝向成员变量
742 new_dynamics.ego_heading = match_object.enuPosition.heading;
743 // 调用GetHeadingChange函数获取自车的航向变化信息,并赋值给新的动力学信息结构体中的相应成员变量
744 new_dynamics.ego_heading_change = GetHeadingChange(carla_vehicle);
745 // 调用GetSteeringAngle函数获取自车的转向角度信息,并赋值给新的动力学信息结构体中的相应成员变量
746 new_dynamics.ego_steering_angle = GetSteeringAngle(carla_vehicle);
747// 根据自车匹配对象和完整路线信息获取与自车相关的路线区间信息,使用指定的路线区间创建模式(AllRouteLanes,可能表示所有车道相关的路线区间)
748 auto object_route =
749 ::ad::map::route::getRouteSection(match_object, route, ::ad::map::route::RouteSectionCreationMode::AllRouteLanes);
750 // 获取该路线区间对应的ENU边界信息(可能是用于后续判断位置、方向等相关操作的边界数据)
751 auto border = ::ad::map::route::getENUBorderOfRoute(object_route);
752 new_dynamics.route_heading = ::ad::map::lane::getENUHeading(border, match_object.enuPosition.centerPoint);
753
754// 根据自车匹配对象和相关路线区间查找路线的中心点信息(可能是车道中心等相关的点)
755 auto const object_center = ::ad::map::route::findCenterWaypoint(match_object, object_route);
756 if (object_center.isValid()) {
757 // 如果找到的中心点信息是有效的
758 // 获取中心点对应的位置信息(可能是车道上的某个位置点)
759 auto lane_center_point = object_center.queryPosition;
760 // 将该位置点转换为ENU坐标下的车道点信息
761 auto lane_center_point_enu = ::ad::map::lane::getENULanePoint(lane_center_point);
762 // 将该位置点转换为ENU坐标下的车道点信息
763 if (std::fabs(new_dynamics.route_heading) > ::ad::map::point::ENUHeading(M_PI)) {
764 // 如果实际中心点已经在外部,尝试使用这个扩展
765 // 路线航向计算的物体中心
766 new_dynamics.route_heading = ::ad::map::lane::getENUHeading(border, lane_center_point_enu);
767 }
768
769 if (object_center.laneSegmentIterator->laneInterval.wrongWay) {
770 // 行驶在错误的车道上,因此我们必须投影到标准路线
771 // 方向
772 ::ad::map::lane::projectPositionToLaneInHeadingDirection(lane_center_point, new_dynamics.route_heading,
773 lane_center_point);
774 lane_center_point_enu = ::ad::map::lane::getENULanePoint(lane_center_point);
775 }
776 new_dynamics.route_nominal_center = lane_center_point_enu;
777
778 } else {
779 // 自车完全偏离了路线,因此我们无法更新
780 // 数值
781 new_dynamics.route_nominal_center = last_dynamics.route_nominal_center;
782 new_dynamics.route_heading = last_dynamics.route_heading;
783 }
784// 计算自车航向与路线航向的差值,并进行归一化处理(可能是将角度差值限制在一定范围内,比如 -π 到 π 之间),将结果赋值给新的动力学信息结构体中的航向差值成员变量
785 new_dynamics.heading_diff =
786 ::ad::map::point::normalizeENUHeading(new_dynamics.route_heading - new_dynamics.ego_heading);
787 // 计算自车航向与路线航向的差值,并进行归一化处理(可能是将角度差值限制在一定范围内,比如 -π 到 π 之间),将结果赋值给新的动力学信息结构体中的航向差值成员变量
788 new_dynamics.route_speed_lon =
789 std::fabs(std::cos(static_cast<double>(new_dynamics.heading_diff))) * new_dynamics.ego_speed;
790 // 根据航向差值和自车速度计算路线横向速度(通过三角函数,横向速度是速度在垂直于路线方向上的分量),并赋值给相应成员变量
791 new_dynamics.route_speed_lat = std::sin(static_cast<double>(new_dynamics.heading_diff)) * new_dynamics.ego_speed;
792
793 // 初始化一个标志变量,用于表示是否保留上一次的加速度信息,初始值设为true,表示默认保留
794 bool keep_last_acceleration = true;
795 // 判断上一次动力学信息中的时间戳的经过秒数是否大于0,即上一次记录是否有时间间隔
796 if (last_dynamics.timestamp.elapsed_seconds > 0.) {
797 // 计算本次时间戳与上一次时间戳之间的时间间隔,创建一个时间间隔类型(::ad::physics::Duration)的实例
798 ::ad::physics::Duration const delta_time(current_timestamp.elapsed_seconds -
799 last_dynamics.timestamp.elapsed_seconds);
800 // 判断时间间隔是否大于一个极小值(0.0001,可能是为了避免除以极小时间间隔导致数值异常等情况)
801 if (delta_time > ::ad::physics::Duration(0.0001)) {
802 try {
803 // 根据本次和上一次的横向路线速度以及时间间隔计算横向路线加速度,并赋值给相应成员变量
804 new_dynamics.route_accel_lat = (new_dynamics.route_speed_lat - last_dynamics.route_speed_lat) / delta_time;
805 // 计算横向路线平均加速度(可能是一种平滑处理方式,结合了上一次平均加速度和本次计算的加速度),并赋值给相应成员变量
806 new_dynamics.avg_route_accel_lat =
807 ((last_dynamics.avg_route_accel_lat * 2.) + new_dynamics.route_accel_lat) / 3.;
808 // 同理,根据纵向路线速度计算纵向路线加速度,并赋值给相应成员变量
809 new_dynamics.route_accel_lon = (new_dynamics.route_speed_lon - last_dynamics.route_speed_lon) / delta_time;
810 // 计算纵向路线平均加速度,并赋值给相应成员变量
811 new_dynamics.avg_route_accel_lon =
812 ((last_dynamics.avg_route_accel_lon * 2.) + new_dynamics.route_accel_lon) / 3.;
813 // 判断横向路线平均加速度是否等于0,如果等于0,为了防止出现数值下溢等问题,将其设置为0(可能是在特定的逻辑处理中避免出现意外情况)
814 if (new_dynamics.avg_route_accel_lat == ::ad::physics::Acceleration(0.)) {
815 // prevent from underrun
816 new_dynamics.avg_route_accel_lat = ::ad::physics::Acceleration(0.);
817 }
818 // 同样地,判断纵向路线平均加速度是否等于0,如果等于0,进行相应的处理,将其设置为0
819 if (new_dynamics.avg_route_accel_lon == ::ad::physics::Acceleration(0.)) {
820 // prevent from underrun
821 new_dynamics.avg_route_accel_lon = ::ad::physics::Acceleration(0.);
822 }
823 // 如果成功计算了加速度相关信息,将标志变量设为false,表示不需要保留上一次的加速度信息了
824 keep_last_acceleration = false;
825 } catch (...) {
826 }
827 }
828 }
829
830 if (keep_last_acceleration) {
831 new_dynamics.route_accel_lat = last_dynamics.route_accel_lat;
832 new_dynamics.avg_route_accel_lat = last_dynamics.avg_route_accel_lat;
833 new_dynamics.route_accel_lon = last_dynamics.route_accel_lon;
834 new_dynamics.avg_route_accel_lon = last_dynamics.avg_route_accel_lon;
835 }
836
837 // check if the center point (and only the center point) is still found on the
838 // route
839 ::ad::map::point::ParaPointList in_lane_matches;
840 for (auto &match_position : match_object.mapMatchedBoundingBox
841 .referencePointPositions[int32_t(::ad::map::match::ObjectReferencePoints::Center)]) {
842 if (match_position.type == ::ad::map::match::MapMatchedPositionType::LANE_IN) {
843 in_lane_matches.push_back(match_position.lanePoint.paraPoint);
844 }
845 }
846 auto const object_in_lane_center = ::ad::map::route::findNearestWaypoint(in_lane_matches, route);
847 new_dynamics.ego_center_within_route = object_in_lane_center.isValid();
848 // evaluated by AnalyseResults
849 new_dynamics.crossing_border = false;
850
851 // calculate the ego stopping distance, to be able to reduce the effort
852
853 ::ad::rss::map::RssObjectData ego_object_data;
854 ego_object_data.id = ::ad::rss::world::ObjectId(0u);
855 ego_object_data.type = ::ad::rss::world::ObjectType::EgoVehicle;
856 ego_object_data.matchObject = match_object;
857 ego_object_data.speed = new_dynamics.ego_speed;
858 ego_object_data.yawRate = new_dynamics.ego_heading_change;
859 ego_object_data.steeringAngle = new_dynamics.ego_steering_angle;
860 ego_object_data.rssDynamics = default_ego_vehicle_dynamics;
861
862 ad::rss::map::RssObjectConversion object_conversion(ego_object_data);
863 if (!object_conversion.calculateMinStoppingDistance(new_dynamics.min_stopping_distance)) {
864 _logger->error(
865 "CalculateEgoDynamicsOnRoute: calculation of min stopping distance "
866 "failed. Setting to 100. ({} {} {} {})",
867 match_object, new_dynamics.ego_speed, new_dynamics.ego_speed, new_dynamics.ego_heading_change,
868 default_ego_vehicle_dynamics);
869 new_dynamics.min_stopping_distance = ::ad::physics::Distance(100.);
870 }
871
872 _logger->trace("CalculateEgoDynamicsOnRoute: route-section {} -> dynamics: {}", object_route, new_dynamics);
873 return new_dynamics;
874}
875
877 ::ad::map::match::Object other_match_object;
878 carla::SharedPtr<ActorConstellationData> default_constellation_data{
879 new ActorConstellationData{carla_rss_state.ego_match_object, carla_rss_state.ego_route,
880 carla_rss_state.ego_dynamics_on_route, other_match_object, nullptr}};
881 auto const default_constellation_result = _actor_constellation_callback(default_constellation_data);
882 carla_rss_state.default_ego_vehicle_dynamics = default_constellation_result.ego_vehicle_dynamics;
883}
884
885::ad::map::landmark::LandmarkIdSet RssCheck::GetGreenTrafficLightsOnRoute(
886 std::vector<SharedPtr<carla::client::TrafficLight>> const &traffic_lights,
887 ::ad::map::route::FullRoute const &route) const {
888 ::ad::map::landmark::LandmarkIdSet green_traffic_lights;
889
890 auto next_intersection = ::ad::map::intersection::Intersection::getNextIntersectionOnRoute(route);
891 if (next_intersection &&
892 (next_intersection->intersectionType() == ::ad::map::intersection::IntersectionType::TrafficLight)) {
893 // try to guess the the relevant traffic light with the rule: nearest
894 // traffic light in respect to the incoming lane.
895 // @todo: when OpenDrive maps have the traffic lights incorporated, we only
896 // have to fill all green traffic lights into the green_traffic_lights list
897 auto incoming_lanes = next_intersection->incomingLanesOnRoute();
898 // since our route spans the whole street, we have to filter out the
899 // incoming lanes with wrong way flag
900 auto incoming_lanes_iter = incoming_lanes.begin();
901 while (incoming_lanes_iter != incoming_lanes.end()) {
902 auto find_waypoint = ::ad::map::route::findWaypoint(*incoming_lanes_iter, route);
903 if (find_waypoint.isValid() && find_waypoint.laneSegmentIterator->laneInterval.wrongWay) {
904 incoming_lanes_iter = incoming_lanes.erase(incoming_lanes_iter);
905 } else {
906 incoming_lanes_iter++;
907 }
908 }
909
910 ::ad::map::match::AdMapMatching traffic_light_map_matching;
911 bool found_relevant_traffic_light = false;
912 for (const auto &traffic_light : traffic_lights) {
913 auto traffic_light_state = traffic_light->GetState();
914 carla::geom::BoundingBox trigger_bounding_box = traffic_light->GetTriggerVolume();
915
916 auto traffic_light_transform = traffic_light->GetTransform();
917 auto trigger_box_location = trigger_bounding_box.location;
918 traffic_light_transform.TransformPoint(trigger_box_location);
919
920 ::ad::map::point::ENUPoint trigger_box_position;
921 trigger_box_position.x = ::ad::map::point::ENUCoordinate(trigger_box_location.x);
922 trigger_box_position.y = ::ad::map::point::ENUCoordinate(-1 * trigger_box_location.y);
923 trigger_box_position.z = ::ad::map::point::ENUCoordinate(0.);
924
925 _logger->trace("traffic light[{}] Position: {}", traffic_light->GetId(), trigger_box_position);
926 auto traffic_light_map_matched_positions = traffic_light_map_matching.getMapMatchedPositions(
927 trigger_box_position, ::ad::physics::Distance(0.25), ::ad::physics::Probability(0.1));
928
929 _logger->trace("traffic light[{}] Map Matched Position: {}", traffic_light->GetId(),
930 traffic_light_map_matched_positions);
931
932 for (auto matched_position : traffic_light_map_matched_positions) {
933 if (incoming_lanes.find(matched_position.lanePoint.paraPoint.laneId) != incoming_lanes.end()) {
934 if (found_relevant_traffic_light &&
935 (green_traffic_lights.empty() && (traffic_light_state == carla::rpc::TrafficLightState::Green))) {
936 _logger->warn("found another relevant traffic light on lane {}; {} state {}",
937 matched_position.lanePoint.paraPoint.laneId, traffic_light->GetId(),
938 (traffic_light_state == carla::rpc::TrafficLightState::Green) ? "green" : "not green");
939 } else {
940 _logger->debug("found relevant traffic light on lane {}; {} state {}",
941 matched_position.lanePoint.paraPoint.laneId, traffic_light->GetId(),
942 (traffic_light_state == carla::rpc::TrafficLightState::Green) ? "green" : "not green");
943 }
944
945 found_relevant_traffic_light = true;
946
947 // found matching traffic light
948 if (traffic_light_state == carla::rpc::TrafficLightState::Green) {
949 // @todo: currently there is only this workaround because of missign
950 // OpenDrive map support for actual traffic light ids
951 green_traffic_lights.insert(::ad::map::landmark::LandmarkId::getMax());
952 } else {
953 // if the light is not green, we don't have priority
954 green_traffic_lights.clear();
955 }
956 break;
957 }
958 }
959 }
960 }
961 return green_traffic_lights;
962}
963
965 ::ad::rss::map::RssSceneCreation &scene_creation,
966 carla::client::Vehicle const &carla_ego_vehicle,
967 CarlaRssState const &carla_rss_state,
968 ::ad::map::landmark::LandmarkIdSet const &green_traffic_lights)
969 : _rss_check(rss_check),
970 _scene_creation(scene_creation),
971 _carla_ego_vehicle(carla_ego_vehicle),
972 _carla_rss_state(carla_rss_state),
973 _green_traffic_lights(green_traffic_lights) {}
974
976 const carla::SharedPtr<carla::client::Actor> other_traffic_participant) const {
977 try {
978 auto other_match_object = _rss_check.GetMatchObject(other_traffic_participant, ::ad::physics::Distance(2.0));
979
980 _rss_check._logger->trace("OtherVehicleMapMatching: {} {}", other_traffic_participant->GetId(),
981 other_match_object.mapMatchedBoundingBox);
982
985 other_match_object, other_traffic_participant}};
986 auto const actor_constellation_result = _rss_check._actor_constellation_callback(actor_constellation_data);
987
988 auto other_speed = _rss_check.GetSpeed(*other_traffic_participant);
989 auto other_heading_change = _rss_check.GetHeadingChange(*other_traffic_participant);
990 auto other_steering_angle = ::ad::physics::Angle(0.);
991
992 ::ad::rss::map::RssObjectData ego_object_data;
993 ego_object_data.id = _carla_ego_vehicle.GetId();
994 ego_object_data.type = ::ad::rss::world::ObjectType::EgoVehicle;
995 ego_object_data.matchObject = _carla_rss_state.ego_match_object;
996 ego_object_data.speed = _carla_rss_state.ego_dynamics_on_route.ego_speed;
998 ego_object_data.steeringAngle = _carla_rss_state.ego_dynamics_on_route.ego_steering_angle;
999 ego_object_data.rssDynamics = actor_constellation_result.ego_vehicle_dynamics;
1000
1001 ::ad::rss::map::RssObjectData other_object_data;
1002 other_object_data.id = ::ad::rss::world::ObjectId(other_traffic_participant->GetId());
1003 other_object_data.type = actor_constellation_result.actor_object_type;
1004 other_object_data.matchObject = other_match_object;
1005 other_object_data.speed = other_speed;
1006 other_object_data.yawRate = other_heading_change;
1007 other_object_data.steeringAngle = other_steering_angle;
1008 other_object_data.rssDynamics = actor_constellation_result.actor_dynamics;
1009
1010 _scene_creation.appendScenes(ego_object_data, _carla_rss_state.ego_route, other_object_data,
1011 actor_constellation_result.restrict_speed_limit_mode, _green_traffic_lights,
1012 actor_constellation_result.rss_calculation_mode);
1013
1014 } catch (...) {
1015 _rss_check._logger->error("Exception processing other traffic participant {} -> Ignoring it",
1016 other_traffic_participant->GetId());
1017 }
1018}
1019
1020void RssCheck::CreateWorldModel(carla::client::Timestamp const &timestamp, carla::client::ActorList const &actors,
1021 carla::client::Vehicle const &carla_ego_vehicle, CarlaRssState &carla_rss_state) const {
1022 // only loop once over the actors since always the respective objects are created
1023 std::vector<SharedPtr<carla::client::TrafficLight>> traffic_lights;
1024 std::vector<SharedPtr<carla::client::Actor>> other_traffic_participants;
1025 for (const auto &actor : actors) {
1026 const auto traffic_light = boost::dynamic_pointer_cast<carla::client::TrafficLight>(actor);
1027 if (traffic_light != nullptr) {
1028 traffic_lights.push_back(traffic_light);
1029 continue;
1030 }
1031
1032 if ((boost::dynamic_pointer_cast<carla::client::Vehicle>(actor) != nullptr) ||
1033 (boost::dynamic_pointer_cast<carla::client::Walker>(actor) != nullptr)) {
1034 if (actor->GetId() == carla_ego_vehicle.GetId()) {
1035 continue;
1036 }
1037 auto const relevant_distance =
1038 std::max(static_cast<double>(carla_rss_state.ego_dynamics_on_route.min_stopping_distance), 100.);
1039 if (actor->GetTransform().location.Distance(carla_ego_vehicle.GetTransform().location) < relevant_distance) {
1040 other_traffic_participants.push_back(actor);
1041 }
1042 }
1043 }
1044
1045 ::ad::map::landmark::LandmarkIdSet green_traffic_lights =
1046 GetGreenTrafficLightsOnRoute(traffic_lights, carla_rss_state.ego_route);
1047
1048 ::ad::rss::map::RssSceneCreation scene_creation(timestamp.frame, carla_rss_state.default_ego_vehicle_dynamics);
1049
1050#ifdef RSS_USE_TBB
1051 tbb::parallel_for_each(
1052 other_traffic_participants.begin(), other_traffic_participants.end(),
1053 RssObjectChecker(*this, scene_creation, carla_ego_vehicle, carla_rss_state, green_traffic_lights));
1054#else
1055 for (auto const traffic_participant : other_traffic_participants) {
1056 auto checker = RssObjectChecker(*this, scene_creation, carla_ego_vehicle, carla_rss_state, green_traffic_lights);
1057 checker(traffic_participant);
1058 }
1059#endif
1060
1062 // add artifical objects on the road boundaries for "stay-on-road" feature
1063 // use 'smart' dynamics
1064 auto ego_vehicle_dynamics = carla_rss_state.default_ego_vehicle_dynamics;
1065 ego_vehicle_dynamics.alphaLat.accelMax = ::ad::physics::Acceleration(0.);
1066
1067 ::ad::rss::map::RssObjectData ego_object_data;
1068 ego_object_data.id = carla_ego_vehicle.GetId();
1069 ego_object_data.type = ::ad::rss::world::ObjectType::EgoVehicle;
1070 ego_object_data.matchObject = _carla_rss_state.ego_match_object;
1071 ego_object_data.speed = _carla_rss_state.ego_dynamics_on_route.ego_speed;
1073 ego_object_data.steeringAngle = _carla_rss_state.ego_dynamics_on_route.ego_steering_angle;
1074 ego_object_data.rssDynamics = ego_vehicle_dynamics;
1075 scene_creation.appendRoadBoundaries(ego_object_data, carla_rss_state.ego_route,
1076 // since the route always expanded, route isn't required to expand any
1077 // more
1078 ::ad::rss::map::RssSceneCreation::AppendRoadBoundariesMode::RouteOnly);
1079 }
1080
1081 carla_rss_state.world_model = scene_creation.getWorldModel();
1082}
1083
1084bool RssCheck::PerformCheck(CarlaRssState &carla_rss_state) const {
1085 // 调用carla_rss_state中的rss_check对象的calculateProperResponse函数(具体功能依赖其实现),传入世界模型、情况快照、RSS 状态快照以及用于存储最终合适响应的对象等参数
1086 // 执行相应的计算和判断,获取检查结果(布尔值,表示是否成功进行了合适响应的计算等)
1087 bool result = carla_rss_state.rss_check.calculateProperResponse(
1088 carla_rss_state.world_model, carla_rss_state.situation_snapshot, carla_rss_state.rss_state_snapshot,
1089 carla_rss_state.proper_response);
1090
1091// 如果检查结果为false,即计算合适响应失败,记录警告日志,提示calculateProperResponse失败的情况
1092 if (!result) {
1093 _logger->warn("calculateProperResponse failed!");
1094 }
1095 // 如果检查结果为true,但是最终的合适响应表示当前路线不安全(isSafe为false)
1096 else if (!carla_rss_state.proper_response.isSafe) {
1097 // 记录信息日志,输出当前不安全的路线对应的响应信息,提示当前情况不安全
1098 _logger->info("Unsafe route: {}", carla_rss_state.proper_response);
1099 }
1100 // 返回检查结果(布尔值),用于告知调用者此次 RSS 检查的执行情况
1101 return result;
1102}
1103
1104// RssCheck类中的函数,用于分析 RSS 检查的结果,根据各种响应状态等信息判断不同的危险情况,并更新CarlaRssState对象中的相关危险状态标志等内容
1105void RssCheck::AnalyseCheckResults(CarlaRssState &carla_rss_state) const {
1106 // 初始将CarlaRssState对象中的表示整体危险状态的标志设为false,后续根据具体情况判断是否变为true
1107 carla_rss_state.dangerous_state = false;
1108 // 初始将CarlaRssState对象中的表示有危险车辆的标志设为false,后续根据具体情况判断是否变为true
1109 carla_rss_state.dangerous_vehicle = false;
1110 // 将CarlaRssState对象中表示存在相反方向危险情况的标志初始化为false,同样后续依据具体情况判断是否出现此类危险
1111 carla_rss_state.dangerous_opposite_state = false;
1112 // 初始化一个标志变量,表示左侧道路边界是否处于危险状态,初始为false,后续在分析过程中更新
1113 bool left_border_is_dangerous = false;
1114 // 初始化一个标志变量,表示右侧道路边界是否处于危险状态,初始为false,后续根据分析情况改变其值
1115 bool right_border_is_dangerous = false;
1116 // 初始化一个标志变量,用于表示是否是车辆触发了左侧响应,初始为false,会根据具体的响应状态来确定
1117 bool vehicle_triggered_left_response = false;
1118 // 初始化一个标志变量,用于表示是否是车辆触发了右侧响应,初始设为false,后续根据分析情况更新
1119 bool vehicle_triggered_right_response = false;
1120 // 初始化一个标志变量,用于表示是否是车辆触发了纵向响应,初始为false,在遍历分析响应状态时会改变其值
1121 bool vehicle_triggered_longitudinal_response = false;
1122 // 遍历CarlaRssState对象中RSS状态快照里的每个单独响应状态
1123 for (auto const state : carla_rss_state.rss_state_snapshot.individualResponses) {
1124 // 调用::ad::rss::state::isDangerous函数(其具体实现应该是判断给定的状态是否处于危险情况)来检查当前响应状态是否危险
1125 if (::ad::rss::state::isDangerous(state)) {
1126 // 如果当前响应状态是危险的,将CarlaRssState对象中的表示整体危险状态的标志设为true
1127 carla_rss_state.dangerous_state = true;
1128 // 记录跟踪日志,输出当前处于危险的状态信息(可能用于调试、查看具体危险情况等目的)
1129 _logger->trace("DangerousState: {}", state);
1130 // 在情况快照(situation_snapshot)中的所有情况里查找与当前危险状态对应的情况信息
1131 // 使用std::find_if算法结合lambda表达式来查找,lambda表达式的逻辑是比较情况的ID与当前危险状态的情况ID是否相等
1132 auto dangerous_sitation_iter = std::find_if(carla_rss_state.situation_snapshot.situations.begin(),
1133 carla_rss_state.situation_snapshot.situations.end(),
1134 [&state](::ad::rss::situation::Situation const &situation) {
1135 return situation.situationId == state.situationId;
1136 });
1137 // 如果找到了对应的情况信息(即迭代器不等于结束迭代器)
1138 if (dangerous_sitation_iter != carla_rss_state.situation_snapshot.situations.end()) {
1139 // 记录跟踪日志,输出找到的对应情况信息(可能用于进一步查看相关情况细节)
1140 _logger->trace("Situation: {}", *dangerous_sitation_iter);
1141 // 如果该情况对应的对象ID与右侧道路边界对象的ID相等(通过::ad::rss::map::RssSceneCreator::getRightBorderObjectId获取右侧边界对象ID)
1142 if (dangerous_sitation_iter->objectId == ::ad::rss::map::RssSceneCreator::getRightBorderObjectId()) {
1143 // 则将右侧道路边界处于危险状态的标志设为true,表示右侧边界存在危险情况
1144 right_border_is_dangerous = true;
1145 // 如果该情况对应的对象ID与左侧道路边界对象的ID相等(通过::ad::rss::map::RssSceneCreator::getLeftBorderObjectId获取左侧边界对象ID)
1146 } else if (dangerous_sitation_iter->objectId == ::ad::rss::map::RssSceneCreator::getLeftBorderObjectId()) {
1147 // 则将左侧道路边界处于危险状态的标志设为true,意味着左侧边界有危险情况
1148 left_border_is_dangerous = true;
1149 // 如果情况对应的对象不是道路边界(即可能是其他交通参与者等情况)
1150 } else {
1151 // 将表示存在危险车辆的标志设为true,说明有车辆相关的危险情况存在
1152 carla_rss_state.dangerous_vehicle = true;
1153 // 如果当前危险状态中的纵向状态响应不是无响应(::ad::rss::state::LongitudinalResponse::None表示无响应)
1154 if (state.longitudinalState.response != ::ad::rss::state::LongitudinalResponse::None) {
1155 // 将表示车辆触发纵向响应的标志设为true,说明车辆的纵向运动情况触发了相应响应
1156 vehicle_triggered_longitudinal_response = true;
1157 }
1158 // 如果当前危险状态中的左侧横向状态响应不是无响应
1159 if (state.lateralStateLeft.response != ::ad::rss::state::LateralResponse::None) {
1160 // 将表示车辆触发左侧响应的标志设为true,意味着车辆的左侧横向运动情况触发了响应
1161 vehicle_triggered_left_response = true;
1162 }
1163 // 如果当前危险状态中的右侧横向状态响应不是无响应
1164 if (state.lateralStateRight.response != ::ad::rss::state::LateralResponse::None) {
1165 // 将表示车辆触发右侧响应的标志设为true,表明车辆的右侧横向运动情况触发了响应
1166 vehicle_triggered_right_response = true;
1167 }
1168 }
1169 // 如果该情况的类型是相反方向情况(::ad::rss::situation::SituationType::OppositeDirection表示相反方向情况类型)
1170 if (dangerous_sitation_iter->situationType == ::ad::rss::situation::SituationType::OppositeDirection) {
1171 // 将表示存在相反方向危险情况的标志设为true,提示有来自相反方向的危险情况出现
1172 carla_rss_state.dangerous_opposite_state = true;
1173 }
1174 }
1175 }
1176 }
1177
1178 // border are restricting potentially too much, fix this
1179 // 如果不是车辆触发纵向响应(vehicle_triggered_longitudinal_response为false),并且最终合适响应中的纵向响应不是无响应(即有纵向响应限制)
1180 if (!vehicle_triggered_longitudinal_response &&
1181 (carla_rss_state.proper_response.longitudinalResponse != ::ad::rss::state::LongitudinalResponse::None)) {
1182 // 记录调试日志,提示纵向响应只是由边界触发的情况,这种情况需要忽略该纵向响应(可能因为不符合预期的合理触发条件等原因)
1183 _logger->debug("!! longitudinalResponse only triggered by borders: ignore !!");
1184 // 将最终合适响应中的纵向响应设为无响应,即去除不合理的纵向响应限制
1185 carla_rss_state.proper_response.longitudinalResponse = ::ad::rss::state::LongitudinalResponse::None;
1186 // 将最终合适响应中的纵向加速度限制范围的最大值设为默认自身车辆动力学参数中的纵向最大加速度值
1187 // 这样就恢复到默认的纵向加速度可允许的最大值,避免了过度限制
1188 carla_rss_state.proper_response.accelerationRestrictions.longitudinalRange.maximum =
1189 carla_rss_state.default_ego_vehicle_dynamics.alphaLon.accelMax;
1190 }
1191 // 如果不是车辆触发左侧响应(vehicle_triggered_left_response为false),并且左侧边界不是处于危险状态(left_border_is_dangerous为false),同时最终合适响应中的左侧横向响应不是无响应(即有左侧横向响应限制)
1192 if (!vehicle_triggered_left_response && !left_border_is_dangerous &&
1193 (carla_rss_state.proper_response.lateralResponseLeft != ::ad::rss::state::LateralResponse::None)) {
1194 // 记录调试日志,提示左侧横向响应只是由右侧边界触发的情况,需要忽略该左侧横向响应(可能是不合理的触发导致的限制)
1195 _logger->debug("!! lateralResponseLeft only triggered by right border: ignore !!");
1196 // 将最终合适响应中的左侧横向响应设为无响应,去除该不合理的左侧横向响应限制
1197 carla_rss_state.proper_response.lateralResponseLeft = ::ad::rss::state::LateralResponse::None;
1198 // 将最终合适响应中的左侧横向加速度限制范围的最大值设为默认自身车辆动力学参数中的横向最大加速度值
1199 // 恢复到默认的横向加速度可允许的最大值,避免因不合理触发导致的过度限制
1200 carla_rss_state.proper_response.accelerationRestrictions.lateralLeftRange.maximum =
1201 carla_rss_state.default_ego_vehicle_dynamics.alphaLat.accelMax;
1202 // 将车辆在路线上的动力学参数中的跨越边界标志设为true,表示出现了可能跨越边界相关的不合理情况(具体含义需结合整体关于边界跨越的逻辑来看)
1203 carla_rss_state.ego_dynamics_on_route.crossing_border = true;
1204 }
1205 // 如果不是车辆触发右侧响应(vehicle_triggered_right_response为false),并且右侧边界不是处于危险状态(right_border_is_dangerous为false),同时最终合适响应中的右侧横向响应不是无响应(即有右侧横向响应限制)
1206 if (!vehicle_triggered_right_response && !right_border_is_dangerous &&
1207 (carla_rss_state.proper_response.lateralResponseRight != ::ad::rss::state::LateralResponse::None)) {
1208 // 记录调试日志,提示右侧横向响应只是由左侧边界触发的情况,需要忽略该右侧横向响应(同样是因为可能是不合理触发导致的限制)
1209 _logger->debug("!! lateralResponseRight only triggered by left border: ignore !!");
1210 // 将最终合适响应中的右侧横向响应设为无响应,去除不合理的右侧横向响应限制
1211 carla_rss_state.proper_response.lateralResponseRight = ::ad::rss::state::LateralResponse::None;
1212 // 将最终合适响应中的右侧横向加速度限制范围的最大值设为默认自身车辆动力学参数中的横向最大加速度值
1213 // 恢复到默认的横向加速度可允许的最大值,避免过度限制
1214 carla_rss_state.proper_response.accelerationRestrictions.lateralRightRange.maximum =
1215 carla_rss_state.default_ego_vehicle_dynamics.alphaLat.accelMax;
1216 // 将车辆在路线上的动力学参数中的跨越边界标志设为true,意味着出现了可能跨越边界相关的不合理情况
1217 carla_rss_state.ego_dynamics_on_route.crossing_border = true;
1218 }
1219// 记录跟踪日志,输出最终的路线响应信息(可能用于查看最终整体的响应情况,方便调试、分析等)
1220 _logger->trace("RouteResponse: {}", carla_rss_state.proper_response);
1221}
1222
1223
1224} // namespace rss
1225} // namespace carla
Traits::size_t size_t
表示模拟中的一个行为体(Actor)。
geom::Vector3D GetVelocity() const
返回行为体的当前3D速度。
geom::Vector3D GetAngularVelocity() const
返回行为体的当前3D角速度。
geom::Transform GetTransform() const
返回行为体的当前变换(位置和方向)。
std::size_t frame
自模拟器启动以来经过的帧数。
Definition Timestamp.h:37
double elapsed_seconds
模拟自当前情境开始以来经过的秒数。
Definition Timestamp.h:40
车辆类的前向声明,用于在LaneInvasionSensor类中可能的引用。
Definition Vehicle.h:76
Control GetControl() const
返回最后应用于车辆的控制.
Definition Vehicle.cpp:119
Location location
边界框的中心位置(本地坐标系下)
void InverseRotateVector(Vector3D &in_point) const
Definition Rotation.h:124
RssObjectChecker(RssCheck const &rss_check, ::ad::rss::map::RssSceneCreation &scene_creation, carla::client::Vehicle const &carla_ego_vehicle, CarlaRssState const &carla_rss_state, ::ad::map::landmark::LandmarkIdSet const &green_traffic_lights)
Definition RssCheck.cpp:964
void operator()(const carla::SharedPtr< carla::client::Actor > other_traffic_participant) const
Definition RssCheck.cpp:975
class implementing the actual RSS checks based on CARLA world description
Definition RssCheck.h:152
::ad::physics::Speed GetSpeed(carla::client::Actor const &actor) const
calculate the speed from the actor
Definition RssCheck.cpp:559
::ad::rss::world::RssDynamics GetDefaultVehicleDynamics()
Definition RssCheck.cpp:114
::ad::physics::AngularVelocity GetHeadingChange(carla::client::Actor const &actor) const
calculate the heading change from the actor
Definition RssCheck.cpp:576
const ::carla::rss::RoadBoundariesMode & GetRoadBoundariesMode() const
Definition RssCheck.cpp:326
const std::vector<::carla::geom::Transform > GetRoutingTargets() const
Definition RssCheck.cpp:340
::ad::rss::world::RssDynamics _default_actor_constellation_callback_ego_vehicle_dynamics
current used vehicle dynamics for ego vehicle by the default actor constellation callback
Definition RssCheck.h:271
float _maximum_steering_angle
maximum steering angle
Definition RssCheck.h:266
::ad::physics::Angle GetSteeringAngle(carla::client::Vehicle const &actor) const
calculate the steering angle from the actor
Definition RssCheck.cpp:582
RssCheck(float max_steering_angle)
default constructor with default internal default actor constellation callback
Definition RssCheck.cpp:181
const ::ad::rss::world::RssDynamics & GetDefaultActorConstellationCallbackOtherVehicleDynamics() const
Definition RssCheck.cpp:308
::carla::rss::RoadBoundariesMode _road_boundaries_mode
current used road boundaries mode
Definition RssCheck.h:286
friend class RssObjectChecker
Definition RssCheck.h:366
bool CheckObjects(carla::client::Timestamp const &timestamp, carla::SharedPtr< carla::client::ActorList > const &actors, carla::SharedPtr< carla::client::Actor > const &carla_ego_actor, ::ad::rss::state::ProperResponse &output_response, ::ad::rss::state::RssStateSnapshot &output_rss_state_snapshot, ::ad::rss::situation::SituationSnapshot &output_situation_snapshot, ::ad::rss::world::WorldModel &output_world_model, EgoDynamicsOnRoute &output_rss_ego_dynamics_on_route)
main function to trigger the RSS check at a certain point in time
Definition RssCheck.cpp:375
::ad::rss::world::RssDynamics _default_actor_constellation_callback_other_vehicle_dynamics
current used vehicle dynamics for other vehicle by the default actor constellation callback
Definition RssCheck.h:273
const ::ad::rss::world::RssDynamics & GetDefaultActorConstellationCallbackEgoVehicleDynamics() const
Definition RssCheck.cpp:299
std::vector<::ad::map::point::ENUPoint > _routing_targets
current used routing targets
Definition RssCheck.h:288
void SetLogLevel(const spdlog::level::level_enum &log_level)
sets the current log level
Definition RssCheck.cpp:289
void AppendRoutingTarget(const ::carla::geom::Transform &routing_target)
appends a routing target to the current routing target list (
Definition RssCheck.cpp:334
void SetDefaultActorConstellationCallbackEgoVehicleDynamics(const ::ad::rss::world::RssDynamics &ego_vehicle_dynamics)
sets the vehicle dynamics to be used for the ego vehicle
Definition RssCheck.cpp:303
void UpdateRoute(CarlaRssState &carla_rss_state)
update the desired ego vehicle route
Definition RssCheck.cpp:588
::ad::rss::world::RssDynamics _default_actor_constellation_callback_pedestrian_dynamics
current used vehicle dynamics for pedestrians by the default actor constellation callback
Definition RssCheck.h:275
EgoDynamicsOnRoute CalculateEgoDynamicsOnRoute(carla::client::Timestamp const &current_timestamp, double const &time_since_epoch_check_start_ms, carla::client::Vehicle const &carla_vehicle, ::ad::map::match::Object match_object, ::ad::map::route::FullRoute const &route, ::ad::rss::world::RssDynamics const &default_ego_vehicle_dynamics, EgoDynamicsOnRoute const &last_dynamics) const
calculate ego vehicle dynamics on the route
Definition RssCheck.cpp:726
void SetDefaultActorConstellationCallbackOtherVehicleDynamics(const ::ad::rss::world::RssDynamics &other_vehicle_dynamics)
sets the vehicle dynamics to be used for other vehicles
Definition RssCheck.cpp:312
std::function<::carla::rss::ActorConstellationResult(carla::SharedPtr< ActorConstellationData >)> ActorConstellationCallbackFunctionType
Definition RssCheck.h:154
::ad::rss::world::RssDynamics GetDefaultPedestrianDynamics()
Definition RssCheck.cpp:147
const ::ad::rss::world::RssDynamics & GetDefaultActorConstellationCallbackPedestrianDynamics() const
Definition RssCheck.cpp:317
void ResetRoutingTargets()
resets the current routing targets (
Definition RssCheck.cpp:355
ActorConstellationCallbackFunctionType _actor_constellation_callback
the current actor constellation callback
Definition RssCheck.h:281
void SetMapLogLevel(const spdlog::level::level_enum &map_log_level)
sets the current log level
Definition RssCheck.cpp:294
~RssCheck()
destructor
Definition RssCheck.cpp:287
CarlaRssState _carla_rss_state
the current state of the ego vehicle
Definition RssCheck.h:370
void DropRoute()
drop the current route
Definition RssCheck.cpp:360
std::shared_ptr< spdlog::logger > _timing_logger
logger for timing log messages
Definition RssCheck.h:261
::ad::map::match::Object GetMatchObject(carla::SharedPtr< carla::client::Actor > const &actor, ::ad::physics::Distance const &sampling_distance) const
calculate the map matched object from the actor
Definition RssCheck.cpp:509
void SetRoadBoundariesMode(const ::carla::rss::RoadBoundariesMode &road_boundaries_mode)
sets the current mode for respecting the road boundaries (
Definition RssCheck.cpp:330
std::vector<::ad::map::point::ENUPoint > _routing_targets_to_append
routing targets to be appended next run
Definition RssCheck.h:292
std::shared_ptr< spdlog::logger > _logger
standard logger
Definition RssCheck.h:257
void UpdateDefaultRssDynamics(CarlaRssState &carla_rss_state)
Definition RssCheck.cpp:876
void SetDefaultActorConstellationCallbackPedestrianDynamics(const ::ad::rss::world::RssDynamics &pedestrian_dynamics)
sets the dynamics to be used for pedestrians
Definition RssCheck.cpp:321
std::shared_ptr< spdlog::logger > getLogger()
Definition RssCheck.cpp:104
std::shared_ptr< spdlog::logger > getTimingLogger()
Definition RssCheck.cpp:109
void printRoute(std::string const &route_descr, ::ad::map::route::FullRoute const &route)
Definition RssCheck.cpp:56
constexpr float to_radians
Definition RssCheck.cpp:77
CARLA模拟器的主命名空间。
Definition Carla.cpp:139
boost::shared_ptr< T > SharedPtr
使用这个SharedPtr(boost::shared_ptr)以保持与boost::python的兼容性, 但未来如果可能的话,我们希望能为std::shared_ptr制作一个Python适配器。
Definition Memory.h:19
Struct defining the configuration for RSS processing of a given actor
Definition RssCheck.h:112
::ad::rss::map::RssSceneCreation::RestrictSpeedLimitMode restrict_speed_limit_mode
限速模式
Definition RssCheck.h:117
::ad::rss::world::RssDynamics ego_vehicle_dynamics
应用于ego车辆的Rss动态
Definition RssCheck.h:121
::ad::rss::world::ObjectType actor_object_type
要用于参与者的Rss对象类型
Definition RssCheck.h:124
::ad::rss::map::RssMode rss_calculation_mode
要应用于参与者的计算模式
Definition RssCheck.h:114
::ad::rss::world::RssDynamics actor_dynamics
应用于参与者的Rss动态
Definition RssCheck.h:127
struct defining the ego vehicles current dynamics in respect to the current route
Definition RssCheck.h:46
::ad::physics::Acceleration route_accel_lat
the ego acceleration component lat in respect to a route
Definition RssCheck.h:93
::ad::physics::Distance min_stopping_distance
当前最小停止距离
Definition RssCheck.h:59
::ad::map::point::ENUPoint route_nominal_center
the considered nominal center of the current route
Definition RssCheck.h:81
::ad::map::point::ENUPoint ego_center
考虑自主车辆的位置
Definition RssCheck.h:61
bool crossing_border
flag indicating if the current state is already crossing one of the borders this is only evaluated if...
Definition RssCheck.h:74
::ad::physics::Acceleration route_accel_lon
the ego acceleration component lon in respect to a route
Definition RssCheck.h:95
::ad::physics::Angle ego_steering_angle
考虑自主车辆的转向角度
Definition RssCheck.h:67
::ad::physics::Acceleration avg_route_accel_lon
the ego acceleration component lon in respect to a route smoothened by an average filter
Definition RssCheck.h:103
::ad::physics::Acceleration avg_route_accel_lat
the ego acceleration component lat in respect to a route smoothened by an average filter
Definition RssCheck.h:98
::ad::map::point::ENUHeading route_heading
the considered heading of the route
Definition RssCheck.h:78
double time_since_epoch_check_start_ms
在checkObjects调用开始时,从epoch开始的时间,单位为毫秒
Definition RssCheck.h:53
::ad::map::point::ENUHeading ego_heading
考虑自主车辆的航向
Definition RssCheck.h:63
::ad::map::point::ENUHeading heading_diff
the considered heading diff towards the route
Definition RssCheck.h:83
bool ego_center_within_route
检查自我中心是否在路线内
Definition RssCheck.h:69
::ad::physics::Speed route_speed_lon
the ego speed component lon in respect to a route
Definition RssCheck.h:90
double time_since_epoch_check_end_ms
在checkObjects调用结束时,从epoch开始的时间,单位为毫秒
Definition RssCheck.h:55
carla::client::Timestamp timestamp
最后一次计算的Carla时间戳
Definition RssCheck.h:51
::ad::physics::Speed ego_speed
自主车辆的速度
Definition RssCheck.h:57
::ad::physics::AngularVelocity ego_heading_change
考虑自主车辆的方向变化
Definition RssCheck.h:65
::ad::physics::Speed route_speed_lat
the ego speed component lat in respect to a route
Definition RssCheck.h:87
struct collecting the rss states required
Definition RssCheck.h:295
EgoDynamicsOnRoute ego_dynamics_on_route
the ego dynamics on the route
Definition RssCheck.h:312
::ad::map::route::FullRoute ego_route
the ego route
Definition RssCheck.h:307
::ad::rss::world::RssDynamics default_ego_vehicle_dynamics
current used default vehicle dynamics for ego vehicle
Definition RssCheck.h:317
::ad::map::match::Object ego_match_object
the ego map matched information
Definition RssCheck.h:304
bool dangerous_state
flag indicating if the current state is overall dangerous
Definition RssCheck.h:332
::ad::rss::state::ProperResponse proper_response
check result: the proper response
Definition RssCheck.h:329
::ad::rss::world::WorldModel world_model
check input: the RSS world model
Definition RssCheck.h:320
::ad::rss::situation::SituationSnapshot situation_snapshot
check result: the situation snapshot
Definition RssCheck.h:323
::ad::rss::state::RssStateSnapshot rss_state_snapshot
check result: the rss state snapshot
Definition RssCheck.h:325