12 #include "Components/BoxComponent.h" 13 #include "Runtime/CoreUObject/Public/UObject/ConstructorHelpers.h" 15 #include "UObject/ConstructorHelpers.h" 27 PrimaryActorTick.bCanEverTick =
false;
28 SceneComponent = CreateDefaultSubobject<USceneComponent>(TEXT(
"RootComponent"));
32 static ConstructorHelpers::FClassFinder<AActor> TrafficLightFinder(
33 TEXT(
"/Game/Carla/Blueprints/TrafficLight/BP_TLOpenDrive" ) );
34 if (TrafficLightFinder.Succeeded())
36 TSubclassOf<AActor> Model = TrafficLightFinder.Class;
40 static ConstructorHelpers::FClassFinder<AActor> StopFinder(
41 TEXT(
"/Game/Carla/Static/TrafficSign/BP_Stop" ) );
42 if (StopFinder.Succeeded())
44 TSubclassOf<AActor> StopSignModel = StopFinder.Class;
48 static ConstructorHelpers::FClassFinder<AActor> YieldFinder(
49 TEXT(
"/Game/Carla/Static/TrafficSign/BP_Yield" ) );
50 if (YieldFinder.Succeeded())
52 TSubclassOf<AActor> YieldSignModel = YieldFinder.Class;
56 static ConstructorHelpers::FClassFinder<AActor> SpeedLimit30Finder(
57 TEXT(
"/Game/Carla/Static/TrafficSign/BP_SpeedLimit30" ) );
58 if (SpeedLimit30Finder.Succeeded())
60 TSubclassOf<AActor> SpeedLimitModel = SpeedLimit30Finder.Class;
63 static ConstructorHelpers::FClassFinder<AActor> SpeedLimit40Finder(
64 TEXT(
"/Game/Carla/Static/TrafficSign/BP_SpeedLimit40" ) );
65 if (SpeedLimit40Finder.Succeeded())
67 TSubclassOf<AActor> SpeedLimitModel = SpeedLimit40Finder.Class;
70 static ConstructorHelpers::FClassFinder<AActor> SpeedLimit50Finder(
71 TEXT(
"/Game/Carla/Static/TrafficSign/BP_SpeedLimit50" ) );
72 if (SpeedLimit50Finder.Succeeded())
74 TSubclassOf<AActor> SpeedLimitModel = SpeedLimit50Finder.Class;
77 static ConstructorHelpers::FClassFinder<AActor> SpeedLimit60Finder(
78 TEXT(
"/Game/Carla/Static/TrafficSign/BP_SpeedLimit60" ) );
79 if (SpeedLimit60Finder.Succeeded())
81 TSubclassOf<AActor> SpeedLimitModel = SpeedLimit60Finder.Class;
84 static ConstructorHelpers::FClassFinder<AActor> SpeedLimit70Finder(
85 TEXT(
"/Game/Carla/Static/TrafficSign/BP_SpeedLimit70" ) );
86 if (SpeedLimit70Finder.Succeeded())
88 TSubclassOf<AActor> SpeedLimitModel = SpeedLimit70Finder.Class;
91 static ConstructorHelpers::FClassFinder<AActor> SpeedLimit80Finder(
92 TEXT(
"/Game/Carla/Static/TrafficSign/BP_SpeedLimit80" ) );
93 if (SpeedLimit80Finder.Succeeded())
95 TSubclassOf<AActor> SpeedLimitModel = SpeedLimit80Finder.Class;
98 static ConstructorHelpers::FClassFinder<AActor> SpeedLimit90Finder(
99 TEXT(
"/Game/Carla/Static/TrafficSign/BP_SpeedLimit90" ) );
100 if (SpeedLimit90Finder.Succeeded())
102 TSubclassOf<AActor> SpeedLimitModel = SpeedLimit90Finder.Class;
105 static ConstructorHelpers::FClassFinder<AActor> SpeedLimit100Finder(
106 TEXT(
"/Game/Carla/Static/TrafficSign/BP_SpeedLimit100" ) );
107 if (SpeedLimit100Finder.Succeeded())
109 TSubclassOf<AActor> SpeedLimitModel = SpeedLimit100Finder.Class;
112 static ConstructorHelpers::FClassFinder<AActor> SpeedLimit110Finder(
113 TEXT(
"/Game/Carla/Static/TrafficSign/BP_SpeedLimit110" ) );
114 if (SpeedLimit110Finder.Succeeded())
116 TSubclassOf<AActor> SpeedLimitModel = SpeedLimit110Finder.Class;
119 static ConstructorHelpers::FClassFinder<AActor> SpeedLimit120Finder(
120 TEXT(
"/Game/Carla/Static/TrafficSign/BP_SpeedLimit120" ) );
121 if (SpeedLimit120Finder.Succeeded())
123 TSubclassOf<AActor> SpeedLimitModel = SpeedLimit120Finder.Class;
141 if(Signal->GetControllers().size())
144 auto ControllerId = *(Signal->GetControllers().begin());
147 const auto &Controller =
GetMap()->GetControllers().at(ControllerId);
148 if(Controller->GetJunctions().empty())
150 UE_LOG(LogCarla, Error, TEXT(
"No junctions in controller %d"), *(ControllerId.c_str()) );
154 auto JunctionId = *(Controller->GetJunctions().begin());
159 FActorSpawnParameters SpawnParams;
161 auto * NewTrafficLightGroup =
163 NewTrafficLightGroup->
JunctionId = JunctionId;
171 auto *NewTrafficLightController = NewObject<UTrafficLightController>();
172 NewTrafficLightController->SetControllerId(ControllerId.c_str());
173 TrafficLightGroup->AddController(NewTrafficLightController);
180 FActorSpawnParameters SpawnParams;
182 auto * NewTrafficLightGroup =
185 TrafficGroups.Add(NewTrafficLightGroup->JunctionId, NewTrafficLightGroup);
186 TrafficLightGroup = NewTrafficLightGroup;
188 auto *NewTrafficLightController = NewObject<UTrafficLightController>();
191 NewTrafficLightController->SetRedTime(10);
192 TrafficLightGroup->GetControllers().Add(NewTrafficLightController);
193 TrafficControllers.Add(NewTrafficLightController->GetControllerId(), NewTrafficLightController);
194 TrafficLightController = NewTrafficLightController;
207 TrafficLightGroup->ResetGroup();
213 auto* Controller = TrafficLight->GetController();
214 auto* Group = TrafficLight->GetGroup();
215 if (!Controller || !Group)
217 UE_LOG(LogCarla, Error, TEXT(
"Missing group or controller for traffic light"));
220 if (TrafficLight->GetSignId() ==
"")
225 if (Controller->GetControllerId() ==
"")
230 if (Group->GetJunctionId() == -1)
261 UE_LOG(LogCarla, Error, TEXT(
"Missing TrafficLightModel"));
281 TrafficSigns.Empty();
285 TrafficGroup.Value->Destroy();
287 TrafficGroups.Empty();
296 TArray<AActor*> Actors;
297 UGameplayStatics::GetAllActorsOfClass(GetWorld(), ATrafficLightBase::StaticClass(), Actors);
308 TArray<ATrafficLightBase*> TrafficLights;
315 TrafficLights.Add(TrafficLight);
319 if (!TrafficLights.Num())
325 const auto& Signals = Map->GetSignals();
326 const auto& Controllers = Map->GetControllers();
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() ==
"")
337 float MinDistance = FVector::DistSquaredXY(TrafficLights.Top()->GetActorLocation(),
Location);
340 float Distance = FVector::DistSquaredXY(
Actor->GetActorLocation(),
Location);
341 if (Distance < MinDistance)
343 MinDistance = Distance;
344 ClosestActor =
Actor;
349 if (Component->GetSignId() ==
"")
351 Component->SetSignId(carla::rpc::ToFString(ODSignal->GetSignalId()));
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()));
381 if (ClosestTrafficSign)
457 template<
typename T = ATrafficSignBase>
461 FTransform UETransform(CarlaTransform);
462 FVector
Location = UETransform.GetLocation();
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;
471 float Dist = FVector::DistSquared(
Actor->GetActorLocation(),
Location);
472 T * TrafficSign = Cast<T>(
Actor);
475 ClosestTrafficSign = TrafficSign;
479 return ClosestTrafficSign;
485 const auto& Signals =
GetMap()->GetSignals();
486 std::unordered_set<std::string> SignalsToSpawn;
487 for(
const auto& ControllerPair :
GetMap()->GetControllers())
489 const auto& Controller = ControllerPair.second;
490 for(
const auto& SignalId : Controller->GetSignals())
492 auto& Signal = Signals.at(SignalId);
498 *Signal.get(), GetWorld());
502 TrafficLightComponent->SetSignId(SignalId.c_str());
506 SignalsToSpawn.insert(SignalId);
511 for(
const auto& SignalPair : Signals)
513 const auto& SignalId = SignalPair.first;
514 const auto& Signal = SignalPair.second;
515 if(!Signal->GetControllers().size() &&
516 !
GetMap()->IsJunction(Signal->GetRoadId()) &&
518 !SignalsToSpawn.count(SignalId))
521 *Signal.get(), GetWorld());
525 TrafficLightComponent->SetSignId(SignalId.c_str());
529 SignalsToSpawn.insert(SignalId);
536 for(
auto &SignalId : SignalsToSpawn)
542 if (Signals.count(SignalId) == 0)
544 UE_LOG(LogCarla, Warning,
545 TEXT(
"Possible OpenDRIVE error, reference to nonexistent signal id: %s"),
546 *carla::rpc::ToFString(SignalId));
549 const auto& Signal = Signals.at(SignalId);
550 auto CarlaTransform = Signal->GetTransform();
551 FTransform SpawnTransform(CarlaTransform);
553 FVector SpawnLocation = SpawnTransform.GetLocation();
554 FRotator SpawnRotation(SpawnTransform.GetRotation());
556 SpawnRotation.Yaw += 90;
558 SpawnRotation.Roll = 0;
559 SpawnRotation.Pitch = 0;
561 FActorSpawnParameters SpawnParams;
562 SpawnParams.Owner =
this;
563 SpawnParams.SpawnCollisionHandlingOverride =
564 ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
575 TrafficLightComponent->SetSignId(SignalId.c_str());
577 auto ClosestWaypointToSignal =
578 GetMap()->GetClosestWaypointOnRoad(CarlaTransform.location);
579 if (ClosestWaypointToSignal)
581 auto SignalDistanceToRoad =
582 (
GetMap()->ComputeTransform(ClosestWaypointToSignal.get()).location - CarlaTransform.location).Length();
583 double LaneWidth =
GetMap()->GetLaneWidth(ClosestWaypointToSignal.get());
585 if(SignalDistanceToRoad < LaneWidth * 0.5)
588 TCHAR_TO_UTF8(*TrafficLightComponent->GetSignId()),
589 "overlaps a driving lane. Disabling collision...");
591 TArray<UPrimitiveComponent*> Primitives;
592 TrafficLight->GetComponents(Primitives);
593 for (
auto* Primitive : Primitives)
595 Primitive->SetCollisionProfileName(TEXT(
"NoCollision"));
601 TrafficLightComponent->InitializeSign(
GetMap().
get());
610 const auto &Signals =
GetMap()->GetSignals();
611 for (
auto& SignalPair : Signals)
613 auto &Signal = SignalPair.second;
614 FString SignalType = Signal->GetType().c_str();
617 if (ClosestTrafficSign)
619 USignComponent *SignComponent;
623 NewObject<USignComponent>(
629 NewObject<USignComponent>(
632 SignComponent->SetSignId(Signal->GetSignalId().c_str());
633 SignComponent->RegisterComponent();
634 SignComponent->AttachToComponent(
635 ClosestTrafficSign->GetRootComponent(),
636 FAttachmentTransformRules::KeepRelativeTransform);
643 if (Signal->GetName() ==
"Stencil_STOP")
647 auto CarlaTransform = Signal->GetTransform();
648 FTransform SpawnTransform(CarlaTransform);
649 FVector SpawnLocation = SpawnTransform.GetLocation();
650 FRotator SpawnRotation(SpawnTransform.GetRotation());
651 SpawnRotation.Yaw += 90;
653 SpawnRotation.Roll = 0;
654 SpawnRotation.Pitch = 0;
656 FActorSpawnParameters SpawnParams;
657 SpawnParams.Owner =
this;
658 SpawnParams.SpawnCollisionHandlingOverride =
659 ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
667 USignComponent *SignComponent =
669 SignComponent->SetSignId(Signal->GetSignalId().c_str());
670 SignComponent->RegisterComponent();
671 SignComponent->AttachToComponent(
672 TrafficSign->GetRootComponent(),
673 FAttachmentTransformRules::KeepRelativeTransform);
674 SignComponent->InitializeSign(
GetMap().
get());
676 auto ClosestWaypointToSignal =
677 GetMap()->GetClosestWaypointOnRoad(CarlaTransform.location);
678 if (ClosestWaypointToSignal)
680 auto SignalDistanceToRoad =
681 (
GetMap()->ComputeTransform(ClosestWaypointToSignal.get()).location - CarlaTransform.location).Length();
682 double LaneWidth =
GetMap()->GetLaneWidth(ClosestWaypointToSignal.get());
684 if(SignalDistanceToRoad < LaneWidth * 0.5)
687 TCHAR_TO_UTF8(*SignComponent->GetSignId()),
688 "overlaps a driving lane. Disabling collision...");
690 TArray<UPrimitiveComponent*> Primitives;
691 TrafficSign->GetComponents(Primitives);
692 for (
auto* Primitive : Primitives)
694 Primitive->SetCollisionProfileName(TEXT(
"NoCollision"));
704 auto CarlaTransform = Signal->GetTransform();
705 FTransform SpawnTransform(CarlaTransform);
706 FVector SpawnLocation = SpawnTransform.GetLocation();
707 FRotator SpawnRotation(SpawnTransform.GetRotation());
708 SpawnRotation.Yaw += 90;
710 SpawnRotation.Roll = 0;
711 SpawnRotation.Pitch = 0;
713 FActorSpawnParameters SpawnParams;
714 SpawnParams.Owner =
this;
715 SpawnParams.SpawnCollisionHandlingOverride =
716 ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
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());
734 auto ClosestWaypointToSignal =
735 GetMap()->GetClosestWaypointOnRoad(CarlaTransform.location);
736 if (ClosestWaypointToSignal)
738 auto SignalDistanceToRoad =
739 (
GetMap()->ComputeTransform(ClosestWaypointToSignal.get()).location - CarlaTransform.location).Length();
740 double LaneWidth =
GetMap()->GetLaneWidth(ClosestWaypointToSignal.get());
742 if(SignalDistanceToRoad < LaneWidth * 0.5)
745 TCHAR_TO_UTF8(*SignComponent->GetSignId()),
746 "overlaps a driving lane. Disabling collision...");
748 TArray<UPrimitiveComponent*> Primitives;
749 TrafficSign->GetComponents(Primitives);
750 for (
auto* Primitive : Primitives)
752 Primitive->SetCollisionProfileName(TEXT(
"NoCollision"));
769 auto* TrafficGroup = TrafficGroupPair.Value;
770 TrafficGroup->SetFrozenGroup(
true);
777 auto* TrafficGroup = TrafficGroupPair.Value;
778 TrafficGroup->SetFrozenGroup(
false);
818 TArray<AActor*> Actors;
819 UGameplayStatics::GetAllActorsOfClass(GetWorld(), AActor::StaticClass(), Actors);
822 AActor* PropsNode =
nullptr;
825 const FString Name = UKismetSystemLibrary::GetDisplayName(
Actor);
826 if(Name.Equals(
"PropsNode"))
835 PropsNode->GetAttachedActors(Actors,
true);
837 PropsNode->Destroy();
846 TArray<AActor*> AttachedActors;
847 Actor->GetAttachedActors(AttachedActors,
true);
int TrafficLightGroupMissingId
void SpawnTrafficLights()
void RegisterLightComponentFromOpenDRIVE(UTrafficLightComponent *TrafficLight)
TMap< FString, TSubclassOf< USignComponent > > SignComponentModels
ULevel * GetULevelFromName(FString LevelName)
UTrafficLightComponent * GetTrafficLightComponent()
void RegisterLightComponentGenerated(UTrafficLightComponent *TrafficLight)
const boost::optional< carla::road::Map > & GetMap()
int TrafficLightControllerMissingId
Class which implements the state changing of traffic lights.
TSubclassOf< AActor > TrafficLightModel
T * GetClosestTrafficSignActor(const carla::road::Signal &Signal, UWorld *World)
void MatchTrafficLightActorsWithOpenDriveSignals()
static ACarlaGameModeBase * GetGameMode(const UObject *WorldContextObject)
static boost::optional< road::Map > Load(const std::string &opendrive)
USceneComponent * SceneComponent
void InitializeTrafficLights()
TMap< FString, TSubclassOf< AActor > > TrafficSignsModels
void RemoveRoadrunnerProps() const
TMap< int, ATrafficLightGroup * > TrafficGroups
carla::SharedPtr< cc::Actor > Actor
USignComponent * GetTrafficSign(FString SignId)
const std::string & GetType() const
static const std::string MaximumSpeed()
static const std::string YieldSign()
static const std::string StopSign()
int TrafficLightComponentMissingId
TMap< FString, USignComponent * > TrafficSignComponents
const boost::optional< carla::road::Map > & GetMap() const
void RemoveAttachedProps(TArray< AActor *> Actors) const
ATrafficLightGroup * GetTrafficGroup(int JunctionId)
static FString GetXODR(const UWorld *World)
Return the OpenDrive XML associated to MapName, or empty if the file is not found.
static void log_warning(Args &&... args)
void GenerateSignalsAndTrafficLights()
TMap< FString, TSubclassOf< AActor > > SpeedLimitModels
TMap< FString, UTrafficLightController * > TrafficControllers
void RemoveGeneratedSignalsAndTrafficLights()
const geom::Transform & GetTransform() const
void SetFrozen(bool InFrozen)
const std::string & GetSubtype() const
Base class for the CARLA Game Mode.
static bool IsTrafficLight(const std::string &type)
ETrafficSignState GetTrafficSignState() const
bool MatchSignalAndActor(const carla::road::Signal &Signal, ATrafficSignBase *ClosestTrafficSign)
UTrafficLightController * GetController(FString ControllerId)
Maps a controller from OpenDrive.
bool bTrafficLightsFrozen
geom::Transform Transform
TArray< ATrafficSignBase * > TrafficSigns
void AddTrafficLight(UTrafficLightComponent *TrafficLight)
bool TrafficLightsGenerated