CARLA
 
载入中...
搜索中...
未找到
StopSignComponent.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 "StopSignComponent.h"
8#include "TrafficLightState.h"
10
11#include <queue>
12
19
20void UStopSignComponent::InitializeSign(const carla::road::Map &Map)
21{
22
23 const double epsilon = 0.00001;
24
25 auto References = GetAllReferencesToThisSignal(Map);
26
27 for (auto& Reference : References)
28 {
29 auto RoadId = Reference.first;
30 const auto* SignalReference = Reference.second;
31 TSet<carla::road::RoadId> SignalPredecessors;
32 // 停车标志边界框
33 for(auto &validity : SignalReference->GetValidities())
34 {
35 for(auto lane : carla::geom::Math::GenerateRange(validity._from_lane, validity._to_lane))
36 {
37 if(lane == 0)
38 continue;
39
40 auto signal_waypoint = Map.GetWaypoint(
41 RoadId, lane, SignalReference->GetS()).get();
42
43 if(Map.GetLane(signal_waypoint).GetType() != cr::Lane::LaneType::Driving)
44 continue;
45
46 auto box_waypoint = signal_waypoint;
47 // 防止在交叉路口内添加边界框
48 if (Map.IsJunction(RoadId)) {
49 auto predecessors = Map.GetPredecessors(box_waypoint);
50 if (predecessors.size() == 1) {
51 auto predecessor = predecessors.front();
52 if (!Map.IsJunction(predecessor.road_id)) {
53 box_waypoint = predecessor;
54 }
55 }
56 }
57
58 // 获得车道宽度一半的 50%
59 float BoxWidth = static_cast<float>(
60 0.5f*Map.GetLaneWidth(box_waypoint)*0.5);
61 float BoxLength = 1.5f;
62 float BoxHeight = 1.0f;
63 // 防止出现道路宽度为 0 的情况,这种情况可能发生在刚刚出现的车道上
64 BoxWidth = std::max(0.01f, BoxWidth);
65 // Get min and max
66 double LaneLength = Map.GetLane(box_waypoint).GetLength();
67 double LaneDistance = Map.GetLane(box_waypoint).GetDistance();
68 // 避免边界框与交叉路口重叠的安全距离
69 float AdditionalDistance = 1.5f;
70 if(lane < 0)
71 {
72 box_waypoint.s = FMath::Clamp(box_waypoint.s - (BoxLength + AdditionalDistance),
73 LaneDistance + epsilon, LaneDistance + LaneLength - epsilon);
74 }
75 else
76 {
77 box_waypoint.s = FMath::Clamp(box_waypoint.s + (BoxLength + AdditionalDistance),
78 LaneDistance + epsilon, LaneDistance + LaneLength - epsilon);
79 }
80 FTransform BoxTransform = Map.ComputeTransform(box_waypoint);
81 ALargeMapManager* LargeMapManager = UCarlaStatics::GetLargeMapManager(GetWorld());
82 if (LargeMapManager)
83 {
84 BoxTransform = LargeMapManager->GlobalToLocalTransform(BoxTransform);
85 }
86 GenerateStopBox(BoxTransform, FVector(100*BoxLength, 100*BoxWidth, 100*BoxHeight));
87
88 auto Predecessors = Map.GetPredecessors(signal_waypoint);
89 for(auto &Prev : Predecessors)
90 {
91 if(!SignalPredecessors.Contains(Prev.road_id))
92 {
93 SignalPredecessors.Add(Prev.road_id);
94 }
95 }
96 }
97 }
98
99 //Check boxes
100 if(Map.IsJunction(RoadId))
101 {
102 auto JuncId = Map.GetJunctionId(RoadId);
103 const auto * Junction = Map.GetJunction(JuncId);
104 if(Junction->RoadHasConflicts(RoadId))
105 {
106 const auto &ConflictingRoads = Junction->GetConflictsOfRoad(RoadId);
107 for(const auto &Conflict : ConflictingRoads)
108 {
109 auto Waypoints = Map.GenerateWaypointsInRoad(Conflict);
110 for(auto& Waypoint : Waypoints)
111 {
112 // Skip roads that share the same previous road
113 bool bHasSamePredecessor = false;
114 auto Predecessors = Map.GetPredecessors(Waypoint);
115 for(auto &Prev : Predecessors)
116 {
117 if(SignalPredecessors.Contains(Prev.road_id))
118 {
119 bHasSamePredecessor = true;
120 }
121 }
122 if(bHasSamePredecessor)
123 {
124 continue;
125 }
126 if(Map.GetLane(Waypoint).GetType() != cr::Lane::LaneType::Driving)
127 continue;
128
129 // Cover the road within the junction
130 auto CurrentWaypoint = Waypoint;
131 auto NextWaypoint = CurrentWaypoint;
132 float BoxSize = static_cast<float>(
133 0.9*Map.GetLaneWidth(NextWaypoint)*0.5);
134 // Prevent a situation where the road width is 0
135 // This could happen in a lane that is just appearing
136 BoxSize = std::max(0.01f, BoxSize);
137 float UEBoxSize = 100*BoxSize;
138
139 FTransform BoxTransform = Map.ComputeTransform(NextWaypoint);
140 ALargeMapManager* LargeMapManager = UCarlaStatics::GetLargeMapManager(GetWorld());
141 if (LargeMapManager)
142 {
143 BoxTransform = LargeMapManager->GlobalToLocalTransform(BoxTransform);
144 }
145 GenerateCheckBox(BoxTransform, UEBoxSize);
146 while (true)
147 {
148 auto Next = Map.GetNext(NextWaypoint, 2*BoxSize);
149 if (Next.size() != 1)
150 {
151 break;
152 }
153 NextWaypoint = Next.front();
154 if(NextWaypoint.road_id != Waypoint.road_id)
155 {
156 break;
157 }
158 BoxTransform = Map.ComputeTransform(NextWaypoint);
159 if (LargeMapManager)
160 {
161 BoxTransform = LargeMapManager->GlobalToLocalTransform(BoxTransform);
162 }
163 GenerateCheckBox(BoxTransform, UEBoxSize);
164 }
165 // Cover the road before the junction
166 // Hard coded anticipation time (boxes placed prior to the junction)
167 double AnticipationTime = 0.1;
168 auto Previous = Map.GetPrevious(Waypoint, 2*BoxSize);
169 std::queue<std::pair<float, carla::road::element::Waypoint>>
170 WaypointQueue;
171 for (auto & Prev : Previous)
172 {
173 WaypointQueue.push({AnticipationTime, Prev});
174 }
175 while (!WaypointQueue.empty())
176 {
177 auto CurrentElement = WaypointQueue.front();
178 WaypointQueue.pop();
179 GenerateCheckBox(Map.ComputeTransform(CurrentElement.second), UEBoxSize);
180
181 float Speed = 40;
182 auto* InfoSpeed = Map.GetLane(CurrentElement.second).GetRoad()->GetInfo<carla::road::element::RoadInfoSpeed>(CurrentElement.second.s);
183 if(InfoSpeed)
184 {
185 Speed = InfoSpeed->GetSpeed();
186 }
187 float RemainingTime = CurrentElement.first - BoxSize/Speed;
188 if(RemainingTime > 0)
189 {
190 Previous = Map.GetPrevious(CurrentElement.second, 2*BoxSize);
191 for (auto & Prev : Previous)
192 {
193 WaypointQueue.push({RemainingTime, Prev});
194 }
195 }
196 }
197 }
198 }
199 }
200 }
201 }
202}
203
204void UStopSignComponent::GenerateStopBox(const FTransform BoxTransform,
205 const FVector BoxSize)
206{
207 UBoxComponent* BoxComponent = GenerateTriggerBox(BoxTransform, BoxSize);
208 BoxComponent->OnComponentBeginOverlap.AddDynamic(this, &UStopSignComponent::OnOverlapBeginStopEffectBox);
209 BoxComponent->OnComponentEndOverlap.AddDynamic(this, &UStopSignComponent::OnOverlapEndStopEffectBox);
210 AddEffectTriggerVolume(BoxComponent);
211}
212
213void UStopSignComponent::GenerateCheckBox(const FTransform BoxTransform,
214 float BoxSize)
215{
216 UBoxComponent* BoxComponent = GenerateTriggerBox(BoxTransform, BoxSize);
217 BoxComponent->OnComponentBeginOverlap.AddDynamic(this, &UStopSignComponent::OnOverlapBeginStopCheckBox);
218 BoxComponent->OnComponentEndOverlap.AddDynamic(this, &UStopSignComponent::OnOverlapEndStopCheckBox);
219}
220
221void UStopSignComponent::GiveWayIfPossible()
222{
223 if (VehiclesToCheck.Num() == 0)
224 {
225 for (auto Vehicle : VehiclesInStop)
226 {
227 AWheeledVehicleAIController* VehicleController =
228 Cast<AWheeledVehicleAIController>(Vehicle->GetController());
229 VehicleController->SetTrafficLightState(ETrafficLightState::Green);
230 }
231 }
232 else
233 {
234 if(VehiclesInStop.Num())
235 {
236 for (auto Vehicle : VehiclesInStop)
237 {
238 AWheeledVehicleAIController* VehicleController =
239 Cast<AWheeledVehicleAIController>(Vehicle->GetController());
240 VehicleController->SetTrafficLightState(ETrafficLightState::Red);
241 }
242 // 1 second delay
243 DelayedGiveWay(1.0f);
244 }
245 }
246}
247
248void UStopSignComponent::DelayedGiveWay(float Delay)
249{
250 FTimerHandle TimerHandler;
251 GetWorld()->GetTimerManager().
252 SetTimer(TimerHandler, this, &UStopSignComponent::GiveWayIfPossible, Delay);
253}
254
255void UStopSignComponent::OnOverlapBeginStopEffectBox(UPrimitiveComponent *OverlappedComp,
256 AActor *OtherActor,
257 UPrimitiveComponent *OtherComp,
258 int32 OtherBodyIndex,
259 bool bFromSweep,
260 const FHitResult &SweepResult)
261{
262 ACarlaWheeledVehicle * Vehicle = Cast<ACarlaWheeledVehicle>(OtherActor);
263 if (Vehicle)
264 {
265 AWheeledVehicleAIController* VehicleController =
266 Cast<AWheeledVehicleAIController>(Vehicle->GetController());
267 if (VehicleController)
268 {
269 VehicleController->SetTrafficLightState(ETrafficLightState::Red);
270 VehiclesInStop.Add(Vehicle);
271
272 // 2 second delay for stop
273 DelayedGiveWay(2.0f);
274 }
275 }
276 RemoveSameVehicleInBothLists();
277}
278
279void UStopSignComponent::OnOverlapEndStopEffectBox(UPrimitiveComponent *OverlappedComp,
280 AActor *OtherActor,
281 UPrimitiveComponent *OtherComp,
282 int32 OtherBodyIndex)
283{
284 ACarlaWheeledVehicle * Vehicle = Cast<ACarlaWheeledVehicle>(OtherActor);
285 if (Vehicle)
286 {
287 VehiclesInStop.Remove(Vehicle);
288 }
289}
290
291void UStopSignComponent::OnOverlapBeginStopCheckBox(UPrimitiveComponent *OverlappedComp,
292 AActor *OtherActor,
293 UPrimitiveComponent *OtherComp,
294 int32 OtherBodyIndex,
295 bool bFromSweep,
296 const FHitResult &SweepResult)
297{
298 ACarlaWheeledVehicle * Vehicle = Cast<ACarlaWheeledVehicle>(OtherActor);
299 if (Vehicle)
300 {
301 if(!VehiclesInStop.Contains(Vehicle))
302 {
303 if (!VehiclesToCheck.Contains(Vehicle))
304 {
305 VehiclesToCheck.Add(Vehicle, 0);
306 }
307 VehiclesToCheck[Vehicle]++;
308 }
309 GiveWayIfPossible();
310 }
311}
312
313void UStopSignComponent::OnOverlapEndStopCheckBox(UPrimitiveComponent *OverlappedComp,
314 AActor *OtherActor,
315 UPrimitiveComponent *OtherComp,
316 int32 OtherBodyIndex)
317{
318 ACarlaWheeledVehicle * Vehicle = Cast<ACarlaWheeledVehicle>(OtherActor);
319 if (Vehicle)
320 {
321 if(VehiclesToCheck.Contains(Vehicle))
322 {
323 VehiclesToCheck[Vehicle]--;
324 if(VehiclesToCheck[Vehicle] <= 0)
325 {
326 VehiclesToCheck.Remove(Vehicle);
327 }
328 }
329 // 0.5s delay
330 DelayedGiveWay(0.5f);
331 }
332}
333void UStopSignComponent::RemoveSameVehicleInBothLists()
334{
335 for(auto* Vehicle : VehiclesInStop)
336 {
337 if(VehiclesToCheck.Contains(Vehicle))
338 {
339 VehiclesToCheck.Remove(Vehicle);
340 }
341 }
342}
Base class for CARLA wheeled vehicles.
FTransform GlobalToLocalTransform(const FTransform &InTransform) const
带可选 AI 的轮式车辆控制器。
void SetTrafficLightState(ETrafficLightState InTrafficLightState)
设置当前影响此车辆的红绿灯状态。
地图类的前向声明,用于在LaneInvasionSensor类中可能的引用。
static ALargeMapManager * GetLargeMapManager(const UObject *WorldContextObject)
carla::SharedPtr< carla::client::Junction > Junction
CARLA模拟器的主命名空间。
Definition Carla.cpp:139