CARLA
 
载入中...
搜索中...
未找到
TrafficLightManager.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
8#include "Game/CarlaStatics.h"
9#include "StopSignComponent.h"
10#include "YieldSignComponent.h"
11#include "SpeedLimitComponent.h"
12#include "Components/BoxComponent.h"
13#include "Runtime/CoreUObject/Public/UObject/ConstructorHelpers.h"
14
15#include "UObject/ConstructorHelpers.h"
16
18#include <carla/rpc/String.h>
22
23#include <string>
24
26{
27 PrimaryActorTick.bCanEverTick = false;
28 SceneComponent = CreateDefaultSubobject<USceneComponent>(TEXT("RootComponent"));
29 RootComponent = SceneComponent;
30
31 // Hard codded default traffic light blueprint
32 static ConstructorHelpers::FClassFinder<AActor> TrafficLightFinder(
33 TEXT( "/Game/Carla/Blueprints/TrafficLight/BP_TLOpenDrive" ) );
34 if (TrafficLightFinder.Succeeded())
35 {
36 TSubclassOf<AActor> Model = TrafficLightFinder.Class;
37 TrafficLightModel = Model;
38 }
39 // Default traffic signs models
40 static ConstructorHelpers::FClassFinder<AActor> StopFinder(
41 TEXT( "/Game/Carla/Static/TrafficSign/BP_Stop" ) );
42 if (StopFinder.Succeeded())
43 {
44 TSubclassOf<AActor> StopSignModel = StopFinder.Class;
45 TrafficSignsModels.Add(carla::road::SignalType::StopSign().c_str(), StopSignModel);
46 SignComponentModels.Add(carla::road::SignalType::StopSign().c_str(), UStopSignComponent::StaticClass());
47 }
48 static ConstructorHelpers::FClassFinder<AActor> YieldFinder(
49 TEXT( "/Game/Carla/Static/TrafficSign/BP_Yield" ) );
50 if (YieldFinder.Succeeded())
51 {
52 TSubclassOf<AActor> YieldSignModel = YieldFinder.Class;
53 TrafficSignsModels.Add(carla::road::SignalType::YieldSign().c_str(), YieldSignModel);
54 SignComponentModels.Add(carla::road::SignalType::YieldSign().c_str(), UYieldSignComponent::StaticClass());
55 }
56 static ConstructorHelpers::FClassFinder<AActor> SpeedLimit30Finder(
57 TEXT( "/Game/Carla/Static/TrafficSign/BP_SpeedLimit30" ) );
58 if (SpeedLimit30Finder.Succeeded())
59 {
60 TSubclassOf<AActor> SpeedLimitModel = SpeedLimit30Finder.Class;
61 SpeedLimitModels.Add("30", SpeedLimitModel);
62 }
63 static ConstructorHelpers::FClassFinder<AActor> SpeedLimit40Finder(
64 TEXT( "/Game/Carla/Static/TrafficSign/BP_SpeedLimit40" ) );
65 if (SpeedLimit40Finder.Succeeded())
66 {
67 TSubclassOf<AActor> SpeedLimitModel = SpeedLimit40Finder.Class;
68 SpeedLimitModels.Add("40", SpeedLimitModel);
69 }
70 static ConstructorHelpers::FClassFinder<AActor> SpeedLimit50Finder(
71 TEXT( "/Game/Carla/Static/TrafficSign/BP_SpeedLimit50" ) );
72 if (SpeedLimit50Finder.Succeeded())
73 {
74 TSubclassOf<AActor> SpeedLimitModel = SpeedLimit50Finder.Class;
75 SpeedLimitModels.Add("50", SpeedLimitModel);
76 }
77 static ConstructorHelpers::FClassFinder<AActor> SpeedLimit60Finder(
78 TEXT( "/Game/Carla/Static/TrafficSign/BP_SpeedLimit60" ) );
79 if (SpeedLimit60Finder.Succeeded())
80 {
81 TSubclassOf<AActor> SpeedLimitModel = SpeedLimit60Finder.Class;
82 SpeedLimitModels.Add("60", SpeedLimitModel);
83 }
84 static ConstructorHelpers::FClassFinder<AActor> SpeedLimit70Finder(
85 TEXT( "/Game/Carla/Static/TrafficSign/BP_SpeedLimit70" ) );
86 if (SpeedLimit70Finder.Succeeded())
87 {
88 TSubclassOf<AActor> SpeedLimitModel = SpeedLimit70Finder.Class;
89 SpeedLimitModels.Add("70", SpeedLimitModel);
90 }
91 static ConstructorHelpers::FClassFinder<AActor> SpeedLimit80Finder(
92 TEXT( "/Game/Carla/Static/TrafficSign/BP_SpeedLimit80" ) );
93 if (SpeedLimit80Finder.Succeeded())
94 {
95 TSubclassOf<AActor> SpeedLimitModel = SpeedLimit80Finder.Class;
96 SpeedLimitModels.Add("80", SpeedLimitModel);
97 }
98 static ConstructorHelpers::FClassFinder<AActor> SpeedLimit90Finder(
99 TEXT( "/Game/Carla/Static/TrafficSign/BP_SpeedLimit90" ) );
100 if (SpeedLimit90Finder.Succeeded())
101 {
102 TSubclassOf<AActor> SpeedLimitModel = SpeedLimit90Finder.Class;
103 SpeedLimitModels.Add("90", SpeedLimitModel);
104 }
105 static ConstructorHelpers::FClassFinder<AActor> SpeedLimit100Finder(
106 TEXT( "/Game/Carla/Static/TrafficSign/BP_SpeedLimit100" ) );
107 if (SpeedLimit100Finder.Succeeded())
108 {
109 TSubclassOf<AActor> SpeedLimitModel = SpeedLimit100Finder.Class;
110 SpeedLimitModels.Add("100", SpeedLimitModel);
111 }
112 static ConstructorHelpers::FClassFinder<AActor> SpeedLimit110Finder(
113 TEXT( "/Game/Carla/Static/TrafficSign/BP_SpeedLimit110" ) );
114 if (SpeedLimit110Finder.Succeeded())
115 {
116 TSubclassOf<AActor> SpeedLimitModel = SpeedLimit110Finder.Class;
117 SpeedLimitModels.Add("110", SpeedLimitModel);
118 }
119 static ConstructorHelpers::FClassFinder<AActor> SpeedLimit120Finder(
120 TEXT( "/Game/Carla/Static/TrafficSign/BP_SpeedLimit120" ) );
121 if (SpeedLimit120Finder.Succeeded())
122 {
123 TSubclassOf<AActor> SpeedLimitModel = SpeedLimit120Finder.Class;
124 SpeedLimitModels.Add("120", SpeedLimitModel);
125 }
127}
128
129void ATrafficLightManager::RegisterLightComponentFromOpenDRIVE(UTrafficLightComponent * TrafficLightComponent)
130{
132 check(GM);
133
134 // Cast to std::string
135 carla::road::SignId SignId(TCHAR_TO_UTF8(*(TrafficLightComponent->GetSignId())));
136
137 ATrafficLightGroup* TrafficLightGroup;
138 UTrafficLightController* TrafficLightController;
139
140 const auto &Signal = GetMap()->GetSignals().at(SignId);
141 if(Signal->GetControllers().size())
142 {
143 // Only one controller per signal
144 auto ControllerId = *(Signal->GetControllers().begin());
145
146 // Get controller
147 const auto &Controller = GetMap()->GetControllers().at(ControllerId);
148 if(Controller->GetJunctions().empty())
149 {
150 UE_LOG(LogCarla, Error, TEXT("No junctions in controller %d"), *(ControllerId.c_str()) );
151 return;
152 }
153 // Get junction of the controller
154 auto JunctionId = *(Controller->GetJunctions().begin());
155
156 // Search/create TrafficGroup (junction traffic light manager)
157 if(!TrafficGroups.Contains(JunctionId))
158 {
159 FActorSpawnParameters SpawnParams;
160 SpawnParams.OverrideLevel = GM->GetULevelFromName("TrafficLights");
161 auto * NewTrafficLightGroup =
162 GetWorld()->SpawnActor<ATrafficLightGroup>(SpawnParams);
163 NewTrafficLightGroup->JunctionId = JunctionId;
164 TrafficGroups.Add(JunctionId, NewTrafficLightGroup);
165 }
166 TrafficLightGroup = TrafficGroups[JunctionId];
167
168 // Search/create controller in the junction
169 if(!TrafficControllers.Contains(ControllerId.c_str()))
170 {
171 auto *NewTrafficLightController = NewObject<UTrafficLightController>();
172 NewTrafficLightController->SetControllerId(ControllerId.c_str());
173 TrafficLightGroup->AddController(NewTrafficLightController);
174 TrafficControllers.Add(ControllerId.c_str(), NewTrafficLightController);
175 }
176 TrafficLightController = TrafficControllers[ControllerId.c_str()];
177 }
178 else
179 {
180 FActorSpawnParameters SpawnParams;
181 SpawnParams.OverrideLevel = GM->GetULevelFromName("TrafficLights");
182 auto * NewTrafficLightGroup =
183 GetWorld()->SpawnActor<ATrafficLightGroup>(SpawnParams);
184 NewTrafficLightGroup->JunctionId = TrafficLightGroupMissingId;
185 TrafficGroups.Add(NewTrafficLightGroup->JunctionId, NewTrafficLightGroup);
186 TrafficLightGroup = NewTrafficLightGroup;
187
188 auto *NewTrafficLightController = NewObject<UTrafficLightController>();
189 NewTrafficLightController->SetControllerId(FString::FromInt(TrafficLightControllerMissingId));
190 // Set red time longer than the default 2s
191 NewTrafficLightController->SetRedTime(10);
192 TrafficLightGroup->GetControllers().Add(NewTrafficLightController);
193 TrafficControllers.Add(NewTrafficLightController->GetControllerId(), NewTrafficLightController);
194 TrafficLightController = NewTrafficLightController;
195
198 }
199
200 // Add signal to controller
201 TrafficLightController->AddTrafficLight(TrafficLightComponent);
202 TrafficLightController->ResetState();
203
204 // Add signal to map
205 TrafficSignComponents.Add(TrafficLightComponent->GetSignId(), TrafficLightComponent);
206
207 TrafficLightGroup->ResetGroup();
208
209}
210
212{
213 auto* Controller = TrafficLight->GetController();
214 auto* Group = TrafficLight->GetGroup();
215 if (!Controller || !Group)
216 {
217 UE_LOG(LogCarla, Error, TEXT("Missing group or controller for traffic light"));
218 return;
219 }
220 if (TrafficLight->GetSignId() == "")
221 {
222 TrafficLight->SetSignId(FString::FromInt(TrafficLightComponentMissingId));
224 }
225 if (Controller->GetControllerId() == "")
226 {
227 Controller->SetControllerId(FString::FromInt(TrafficLightControllerMissingId));
229 }
230 if (Group->GetJunctionId() == -1)
231 {
232 Group->JunctionId = TrafficLightGroupMissingId;
234 }
235
236 if (!TrafficControllers.Contains(Controller->GetControllerId()))
237 {
238 TrafficControllers.Add(Controller->GetControllerId(), Controller);
239 }
240 if (!TrafficGroups.Contains(Group->GetJunctionId()))
241 {
242 TrafficGroups.Add(Group->GetJunctionId(), Group);
243 }
244 if (!TrafficSignComponents.Contains(TrafficLight->GetSignId()))
245 {
247 }
248}
249
250const boost::optional<carla::road::Map>& ATrafficLightManager::GetMap()
251{
252 return UCarlaStatics::GetGameMode(GetWorld())->GetMap();
253}
254
256{
258 {
260 {
261 UE_LOG(LogCarla, Error, TEXT("Missing TrafficLightModel"));
262 return;
263 }
264
266
268
269 SpawnSignals();
270
272 }
273}
274
276{
277 for(auto& Sign : TrafficSigns)
278 {
279 Sign->Destroy();
280 }
281 TrafficSigns.Empty();
282
283 for(auto& TrafficGroup : TrafficGroups)
284 {
285 TrafficGroup.Value->Destroy();
286 }
287 TrafficGroups.Empty();
288
289 TrafficControllers.Empty();
290
292}
293
295{
296 TArray<AActor*> Actors;
297 UGameplayStatics::GetAllActorsOfClass(GetWorld(), ATrafficLightBase::StaticClass(), Actors);
298
299 std::string opendrive_xml = carla::rpc::FromFString(UOpenDrive::GetXODR(GetWorld()));
300 auto Map = carla::opendrive::OpenDriveParser::Load(opendrive_xml);
301
302 if (!Map)
303 {
304 carla::log_warning("Map not found");
305 return;
306 }
307
308 TArray<ATrafficLightBase*> TrafficLights;
309 for (AActor* Actor : Actors)
310 {
311 ATrafficLightBase* TrafficLight = Cast<ATrafficLightBase>(Actor);
312 if (TrafficLight)
313 {
314 TrafficLight->GetTrafficLightComponent()->SetSignId("");
315 TrafficLights.Add(TrafficLight);
316 }
317 }
318
319 if (!TrafficLights.Num())
320 {
321 carla::log_warning("No actors in the map");
322 return;
323 }
324
325 const auto& Signals = Map->GetSignals();
326 const auto& Controllers = Map->GetControllers();
327
328 for(const auto& Signal : Signals) {
329 const auto& ODSignal = Signal.second;
330 const FTransform Transform = ODSignal->GetTransform();
331 const FVector Location = Transform.GetLocation();
332 if (ODSignal->GetName() == "")
333 {
334 continue;
335 }
336 ATrafficLightBase* ClosestActor = TrafficLights.Top();
337 float MinDistance = FVector::DistSquaredXY(TrafficLights.Top()->GetActorLocation(), Location);
338 for (ATrafficLightBase* Actor : TrafficLights)
339 {
340 float Distance = FVector::DistSquaredXY(Actor->GetActorLocation(), Location);
341 if (Distance < MinDistance)
342 {
343 MinDistance = Distance;
344 ClosestActor = Actor;
345 }
346 }
347 ATrafficLightBase* TrafficLight = ClosestActor;
348 auto* Component = TrafficLight->GetTrafficLightComponent();
349 if (Component->GetSignId() == "")
350 {
351 Component->SetSignId(carla::rpc::ToFString(ODSignal->GetSignalId()));
352 }
353 else
354 {
355 carla::log_warning("Could not find a suitable traffic light for signal", ODSignal->GetSignalId(),
356 "Closest traffic light has id", carla::rpc::FromFString(Component->GetSignId()));
357 }
358
359 }
360}
361
363{
364
365 // Should not run in empty maps
366 if (!GetMap())
367 {
368 carla::log_warning("Coud not generate traffic lights: missing map.");
369 return;
370 }
371
373 {
375 }
376}
377
378bool MatchSignalAndActor(const carla::road::Signal &Signal, ATrafficSignBase* ClosestTrafficSign)
379{
380 namespace cr = carla::road;
381 if (ClosestTrafficSign)
382 {
383 if ((Signal.GetType() == cr::SignalType::StopSign()) &&
384 ClosestTrafficSign->GetTrafficSignState() == ETrafficSignState::StopSign)
385 {
386 return true;
387 }
388 else if ((Signal.GetType() == cr::SignalType::YieldSign()) &&
389 ClosestTrafficSign->GetTrafficSignState() == ETrafficSignState::YieldSign)
390 {
391 return true;
392 }
393 else if (cr::SignalType::IsTrafficLight(Signal.GetType()))
394 {
395 if (ClosestTrafficSign->GetTrafficSignState() == ETrafficSignState::TrafficLightRed ||
398 return true;
399 }
400 else if (Signal.GetType() == cr::SignalType::MaximumSpeed())
401 {
402 if (Signal.GetSubtype() == "30" &&
403 ClosestTrafficSign->GetTrafficSignState() == ETrafficSignState::SpeedLimit_30)
404 {
405 return true;
406 }
407 else if (Signal.GetSubtype() == "40" &&
408 ClosestTrafficSign->GetTrafficSignState() == ETrafficSignState::SpeedLimit_40)
409 {
410 return true;
411 }
412 else if (Signal.GetSubtype() == "50" &&
413 ClosestTrafficSign->GetTrafficSignState() == ETrafficSignState::SpeedLimit_50)
414 {
415 return true;
416 }
417 else if (Signal.GetSubtype() == "60" &&
418 ClosestTrafficSign->GetTrafficSignState() == ETrafficSignState::SpeedLimit_60)
419 {
420 return true;
421 }
422 else if (Signal.GetSubtype() == "70" &&
423 ClosestTrafficSign->GetTrafficSignState() == ETrafficSignState::SpeedLimit_60)
424 {
425 return true;
426 }
427 else if (Signal.GetSubtype() == "80" &&
428 ClosestTrafficSign->GetTrafficSignState() == ETrafficSignState::SpeedLimit_90)
429 {
430 return true;
431 }
432 else if (Signal.GetSubtype() == "90" &&
433 ClosestTrafficSign->GetTrafficSignState() == ETrafficSignState::SpeedLimit_90)
434 {
435 return true;
436 }
437 else if (Signal.GetSubtype() == "100" &&
438 ClosestTrafficSign->GetTrafficSignState() == ETrafficSignState::SpeedLimit_100)
439 {
440 return true;
441 }
442 else if (Signal.GetSubtype() == "120" &&
443 ClosestTrafficSign->GetTrafficSignState() == ETrafficSignState::SpeedLimit_120)
444 {
445 return true;
446 }
447 else if (Signal.GetSubtype() == "130" &&
448 ClosestTrafficSign->GetTrafficSignState() == ETrafficSignState::SpeedLimit_130)
449 {
450 return true;
451 }
452 }
453 }
454 return false;
455}
456
457template<typename T = ATrafficSignBase>
458T * GetClosestTrafficSignActor(const carla::road::Signal &Signal, UWorld* World)
459{
460 auto CarlaTransform = Signal.GetTransform();
461 FTransform UETransform(CarlaTransform);
462 FVector Location = UETransform.GetLocation();
463 // max distance to match 500cm
464 constexpr float MaxDistanceMatchSqr = 250000.0;
465 T * ClosestTrafficSign = nullptr;
466 TArray<AActor*> Actors;
467 UGameplayStatics::GetAllActorsOfClass(World, T::StaticClass(), Actors);
468 float MinDistance = MaxDistanceMatchSqr;
469 for (AActor* Actor : Actors)
470 {
471 float Dist = FVector::DistSquared(Actor->GetActorLocation(), Location);
472 T * TrafficSign = Cast<T>(Actor);
473 if (Dist < MinDistance && MatchSignalAndActor(Signal, TrafficSign))
474 {
475 ClosestTrafficSign = TrafficSign;
476 MinDistance = Dist;
477 }
478 }
479 return ClosestTrafficSign;
480}
481
483{
484 namespace cr = carla::road;
485 const auto& Signals = GetMap()->GetSignals();
486 std::unordered_set<std::string> SignalsToSpawn;
487 for(const auto& ControllerPair : GetMap()->GetControllers())
488 {
489 const auto& Controller = ControllerPair.second;
490 for(const auto& SignalId : Controller->GetSignals())
491 {
492 auto& Signal = Signals.at(SignalId);
493 if (!cr::SignalType::IsTrafficLight(Signal->GetType()))
494 {
495 continue;
496 }
497 ATrafficLightBase * TrafficLight = GetClosestTrafficSignActor<ATrafficLightBase>(
498 *Signal.get(), GetWorld());
499 if (TrafficLight)
500 {
501 UTrafficLightComponent *TrafficLightComponent = TrafficLight->GetTrafficLightComponent();
502 TrafficLightComponent->SetSignId(SignalId.c_str());
503 }
504 else
505 {
506 SignalsToSpawn.insert(SignalId);
507 }
508 }
509 }
510
511 for(const auto& SignalPair : Signals)
512 {
513 const auto& SignalId = SignalPair.first;
514 const auto& Signal = SignalPair.second;
515 if(!Signal->GetControllers().size() &&
516 !GetMap()->IsJunction(Signal->GetRoadId()) &&
517 carla::road::SignalType::IsTrafficLight(Signal->GetType()) &&
518 !SignalsToSpawn.count(SignalId))
519 {
520 ATrafficLightBase * TrafficLight = GetClosestTrafficSignActor<ATrafficLightBase>(
521 *Signal.get(), GetWorld());
522 if (TrafficLight)
523 {
524 UTrafficLightComponent *TrafficLightComponent = TrafficLight->GetTrafficLightComponent();
525 TrafficLightComponent->SetSignId(SignalId.c_str());
526 }
527 else
528 {
529 SignalsToSpawn.insert(SignalId);
530 }
531 }
532 }
533
535 check(GM);
536 for(auto &SignalId : SignalsToSpawn)
537 {
538 // TODO: should this be an assert?
539 // RELEASE_ASSERT(
540 // Signals.count(SignalId) > 0,
541 // "Reference to inexistent signal. Possible OpenDRIVE error.");
542 if (Signals.count(SignalId) == 0)
543 {
544 UE_LOG(LogCarla, Warning,
545 TEXT("Possible OpenDRIVE error, reference to nonexistent signal id: %s"),
546 *carla::rpc::ToFString(SignalId));
547 continue;
548 }
549 const auto& Signal = Signals.at(SignalId);
550 auto CarlaTransform = Signal->GetTransform();
551 FTransform SpawnTransform(CarlaTransform);
552
553 FVector SpawnLocation = SpawnTransform.GetLocation();
554 FRotator SpawnRotation(SpawnTransform.GetRotation());
555 // Blueprints are all rotated by 90 degrees
556 SpawnRotation.Yaw += 90;
557 // Remove road inclination
558 SpawnRotation.Roll = 0;
559 SpawnRotation.Pitch = 0;
560
561 FActorSpawnParameters SpawnParams;
562 SpawnParams.Owner = this;
563 SpawnParams.SpawnCollisionHandlingOverride =
564 ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
565 SpawnParams.OverrideLevel = GM->GetULevelFromName("TrafficLights");
566 ATrafficLightBase * TrafficLight = GetWorld()->SpawnActor<ATrafficLightBase>(
568 SpawnLocation,
569 SpawnRotation,
570 SpawnParams);
571
573
574 UTrafficLightComponent *TrafficLightComponent = TrafficLight->GetTrafficLightComponent();
575 TrafficLightComponent->SetSignId(SignalId.c_str());
576
577 auto ClosestWaypointToSignal =
578 GetMap()->GetClosestWaypointOnRoad(CarlaTransform.location);
579 if (ClosestWaypointToSignal)
580 {
581 auto SignalDistanceToRoad =
582 (GetMap()->ComputeTransform(ClosestWaypointToSignal.get()).location - CarlaTransform.location).Length();
583 double LaneWidth = GetMap()->GetLaneWidth(ClosestWaypointToSignal.get());
584
585 if(SignalDistanceToRoad < LaneWidth * 0.5)
586 {
587 carla::log_warning("Traffic light",
588 TCHAR_TO_UTF8(*TrafficLightComponent->GetSignId()),
589 "overlaps a driving lane. Disabling collision...");
590
591 TArray<UPrimitiveComponent*> Primitives;
592 TrafficLight->GetComponents(Primitives);
593 for (auto* Primitive : Primitives)
594 {
595 Primitive->SetCollisionProfileName(TEXT("NoCollision"));
596 }
597 }
598 }
599
600 RegisterLightComponentFromOpenDRIVE(TrafficLightComponent);
601 TrafficLightComponent->InitializeSign(GetMap().get());
602 }
603}
604
606{
608 check(GM);
609
610 const auto &Signals = GetMap()->GetSignals();
611 for (auto& SignalPair : Signals)
612 {
613 auto &Signal = SignalPair.second;
614 FString SignalType = Signal->GetType().c_str();
615
616 ATrafficSignBase * ClosestTrafficSign = GetClosestTrafficSignActor(*Signal.get(), GetWorld());
617 if (ClosestTrafficSign)
618 {
619 USignComponent *SignComponent;
620 if (SignComponentModels.Contains(SignalType))
621 {
622 SignComponent =
623 NewObject<USignComponent>(
624 ClosestTrafficSign, SignComponentModels[SignalType]);
625 }
626 else
627 {
628 SignComponent =
629 NewObject<USignComponent>(
630 ClosestTrafficSign);
631 }
632 SignComponent->SetSignId(Signal->GetSignalId().c_str());
633 SignComponent->RegisterComponent();
634 SignComponent->AttachToComponent(
635 ClosestTrafficSign->GetRootComponent(),
636 FAttachmentTransformRules::KeepRelativeTransform);
637 TrafficSignComponents.Add(SignComponent->GetSignId(), SignComponent);
638 TrafficSigns.Add(ClosestTrafficSign);
639 }
640 else if (TrafficSignsModels.Contains(SignalType))
641 {
642 // We do not spawn stops painted in the ground
643 if (Signal->GetName() == "Stencil_STOP")
644 {
645 continue;
646 }
647 auto CarlaTransform = Signal->GetTransform();
648 FTransform SpawnTransform(CarlaTransform);
649 FVector SpawnLocation = SpawnTransform.GetLocation();
650 FRotator SpawnRotation(SpawnTransform.GetRotation());
651 SpawnRotation.Yaw += 90;
652 // Remove road inclination
653 SpawnRotation.Roll = 0;
654 SpawnRotation.Pitch = 0;
655
656 FActorSpawnParameters SpawnParams;
657 SpawnParams.Owner = this;
658 SpawnParams.SpawnCollisionHandlingOverride =
659 ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
660 SpawnParams.OverrideLevel = GM->GetULevelFromName("TrafficSigns");
661 ATrafficSignBase * TrafficSign = GetWorld()->SpawnActor<ATrafficSignBase>(
662 TrafficSignsModels[SignalType],
663 SpawnLocation,
664 SpawnRotation,
665 SpawnParams);
666
667 USignComponent *SignComponent =
668 NewObject<USignComponent>(TrafficSign, SignComponentModels[SignalType]);
669 SignComponent->SetSignId(Signal->GetSignalId().c_str());
670 SignComponent->RegisterComponent();
671 SignComponent->AttachToComponent(
672 TrafficSign->GetRootComponent(),
673 FAttachmentTransformRules::KeepRelativeTransform);
674 SignComponent->InitializeSign(GetMap().get());
675
676 auto ClosestWaypointToSignal =
677 GetMap()->GetClosestWaypointOnRoad(CarlaTransform.location);
678 if (ClosestWaypointToSignal)
679 {
680 auto SignalDistanceToRoad =
681 (GetMap()->ComputeTransform(ClosestWaypointToSignal.get()).location - CarlaTransform.location).Length();
682 double LaneWidth = GetMap()->GetLaneWidth(ClosestWaypointToSignal.get());
683
684 if(SignalDistanceToRoad < LaneWidth * 0.5)
685 {
686 carla::log_warning("Traffic sign",
687 TCHAR_TO_UTF8(*SignComponent->GetSignId()),
688 "overlaps a driving lane. Disabling collision...");
689
690 TArray<UPrimitiveComponent*> Primitives;
691 TrafficSign->GetComponents(Primitives);
692 for (auto* Primitive : Primitives)
693 {
694 Primitive->SetCollisionProfileName(TEXT("NoCollision"));
695 }
696 }
697 }
698 TrafficSignComponents.Add(SignComponent->GetSignId(), SignComponent);
699 TrafficSigns.Add(TrafficSign);
700 }
701 else if (Signal->GetType() == carla::road::SignalType::MaximumSpeed() &&
702 SpeedLimitModels.Contains(Signal->GetSubtype().c_str()))
703 {
704 auto CarlaTransform = Signal->GetTransform();
705 FTransform SpawnTransform(CarlaTransform);
706 FVector SpawnLocation = SpawnTransform.GetLocation();
707 FRotator SpawnRotation(SpawnTransform.GetRotation());
708 SpawnRotation.Yaw += 90;
709 // Remove road inclination
710 SpawnRotation.Roll = 0;
711 SpawnRotation.Pitch = 0;
712
713 FActorSpawnParameters SpawnParams;
714 SpawnParams.Owner = this;
715 SpawnParams.SpawnCollisionHandlingOverride =
716 ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
717 SpawnParams.OverrideLevel = GM->GetULevelFromName("TrafficSigns");
718 ATrafficSignBase * TrafficSign = GetWorld()->SpawnActor<ATrafficSignBase>(
719 SpeedLimitModels[Signal->GetSubtype().c_str()],
720 SpawnLocation,
721 SpawnRotation,
722 SpawnParams);
723
724 USpeedLimitComponent *SignComponent =
725 NewObject<USpeedLimitComponent>(TrafficSign);
726 SignComponent->SetSignId(Signal->GetSignalId().c_str());
727 SignComponent->RegisterComponent();
728 SignComponent->AttachToComponent(
729 TrafficSign->GetRootComponent(),
730 FAttachmentTransformRules::KeepRelativeTransform);
731 SignComponent->InitializeSign(GetMap().get());
732 SignComponent->SetSpeedLimit(Signal->GetValue());
733
734 auto ClosestWaypointToSignal =
735 GetMap()->GetClosestWaypointOnRoad(CarlaTransform.location);
736 if (ClosestWaypointToSignal)
737 {
738 auto SignalDistanceToRoad =
739 (GetMap()->ComputeTransform(ClosestWaypointToSignal.get()).location - CarlaTransform.location).Length();
740 double LaneWidth = GetMap()->GetLaneWidth(ClosestWaypointToSignal.get());
741
742 if(SignalDistanceToRoad < LaneWidth * 0.5)
743 {
744 carla::log_warning("Traffic sign",
745 TCHAR_TO_UTF8(*SignComponent->GetSignId()),
746 "overlaps a driving lane. Disabling collision...");
747
748 TArray<UPrimitiveComponent*> Primitives;
749 TrafficSign->GetComponents(Primitives);
750 for (auto* Primitive : Primitives)
751 {
752 Primitive->SetCollisionProfileName(TEXT("NoCollision"));
753 }
754 }
755 }
756 TrafficSignComponents.Add(SignComponent->GetSignId(), SignComponent);
757 TrafficSigns.Add(TrafficSign);
758 }
759 }
760}
761
763{
764 bTrafficLightsFrozen = InFrozen;
766 {
767 for (auto& TrafficGroupPair : TrafficGroups)
768 {
769 auto* TrafficGroup = TrafficGroupPair.Value;
770 TrafficGroup->SetFrozenGroup(true);
771 }
772 }
773 else
774 {
775 for (auto& TrafficGroupPair : TrafficGroups)
776 {
777 auto* TrafficGroup = TrafficGroupPair.Value;
778 TrafficGroup->SetFrozenGroup(false);
779 }
780 }
781}
782
787
789{
790 if (TrafficGroups.Contains(JunctionId))
791 {
792 return TrafficGroups[JunctionId];
793 }
794 return nullptr;
795}
796
797
799{
800 if (TrafficControllers.Contains(ControllerId))
801 {
802 return TrafficControllers[ControllerId];
803 }
804 return nullptr;
805}
806
807USignComponent* ATrafficLightManager::GetTrafficSign(FString SignId)
808{
809 if (!TrafficSignComponents.Contains(SignId))
810 {
811 return nullptr;
812 }
813 return TrafficSignComponents[SignId];
814}
815
817{
818 TArray<AActor*> Actors;
819 UGameplayStatics::GetAllActorsOfClass(GetWorld(), AActor::StaticClass(), Actors);
820
821 // Detect PropsNode Actor which is the father of all the Props imported from Roadrunner
822 AActor* PropsNode = nullptr;
823 for(AActor* Actor : Actors)
824 {
825 const FString Name = UKismetSystemLibrary::GetDisplayName(Actor);
826 if(Name.Equals("PropsNode"))
827 {
828 PropsNode = Actor;
829 break;
830 }
831 }
832
833 if(PropsNode)
834 {
835 PropsNode->GetAttachedActors(Actors, true);
836 RemoveAttachedProps(Actors);
837 PropsNode->Destroy();
838 }
839
840}
841
842void ATrafficLightManager::RemoveAttachedProps(TArray<AActor*> Actors) const
843{
844 for(AActor* Actor : Actors)
845 {
846 TArray<AActor*> AttachedActors;
847 Actor->GetAttachedActors(AttachedActors, true);
848 RemoveAttachedProps(AttachedActors);
849 Actor->Destroy();
850 }
851}
bool MatchSignalAndActor(const carla::road::Signal &Signal, ATrafficSignBase *ClosestTrafficSign)
T * GetClosestTrafficSignActor(const carla::road::Signal &Signal, UWorld *World)
Base class for the CARLA Game Mode.
ULevel * GetULevelFromName(FString LevelName)
const boost::optional< carla::road::Map > & GetMap() const
UTrafficLightComponent * GetTrafficLightComponent()
Class which implements the state changing of traffic lights
TArray< UTrafficLightController * > & GetControllers()
void AddController(UTrafficLightController *Controller)
TMap< FString, USignComponent * > TrafficSignComponents
void RegisterLightComponentFromOpenDRIVE(UTrafficLightComponent *TrafficLight)
void SetFrozen(bool InFrozen)
TMap< FString, TSubclassOf< AActor > > SpeedLimitModels
TMap< FString, TSubclassOf< USignComponent > > SignComponentModels
ATrafficLightGroup * GetTrafficGroup(int JunctionId)
USignComponent * GetTrafficSign(FString SignId)
TMap< FString, TSubclassOf< AActor > > TrafficSignsModels
const boost::optional< carla::road::Map > & GetMap()
TSubclassOf< AActor > TrafficLightModel
void RegisterLightComponentGenerated(UTrafficLightComponent *TrafficLight)
TMap< FString, UTrafficLightController * > TrafficControllers
UTrafficLightController * GetController(FString ControllerId)
TArray< ATrafficSignBase * > TrafficSigns
void RemoveAttachedProps(TArray< AActor * > Actors) const
TMap< int, ATrafficLightGroup * > TrafficGroups
USceneComponent * SceneComponent
ETrafficSignState GetTrafficSignState() const
static ACarlaGameModeBase * GetGameMode(const UObject *WorldContextObject)
static FString GetXODR(const UWorld *World)
Return the OpenDrive XML associated to MapName, or empty if the file is not found.
Maps a controller from OpenDrive.
void AddTrafficLight(UTrafficLightComponent *TrafficLight)
static boost::optional< road::Map > Load(const std::string &opendrive)
static const std::string YieldSign()
static bool IsTrafficLight(const std::string &type)
static const std::string MaximumSpeed()
static const std::string StopSign()
const std::string & GetSubtype() const
Definition Signal.h:131
const geom::Transform & GetTransform() const
Definition Signal.h:172
const std::string & GetType() const
Definition Signal.h:127
int32_t JuncId
Definition RoadTypes.h:17
std::string SignId
Definition RoadTypes.h:25
static void log_warning(Args &&... args)
Definition Logging.h:96