44 PrimaryActorTick.bCanEverTick =
true;
45 PrimaryActorTick.bStartWithTickEnabled =
false;
46 SceneComponent = CreateDefaultSubobject<USceneComponent>(TEXT(
"RootComponent"));
50 static ConstructorHelpers::FClassFinder<AActor> TrafficLightRHTFinder(
51 TEXT(
"/Game/Carla/Blueprints/TrafficLight/BP_TLOpenDrive_RHT" ) );
52 if (TrafficLightRHTFinder.Succeeded())
54 TSubclassOf<AActor> Model = TrafficLightRHTFinder.Class;
59 static ConstructorHelpers::FClassFinder<AActor> TrafficLightLHTFinder(
60 TEXT(
"/Game/Carla/Blueprints/TrafficLight/BP_TLOpenDrive_LHT" ) );
61 if (TrafficLightLHTFinder.Succeeded())
63 TSubclassOf<AActor> Model = TrafficLightLHTFinder.Class;
67 static ConstructorHelpers::FClassFinder<AActor> StopFinder(
68 TEXT(
"/Game/Carla/Static/TrafficSign/BP_Stop01" ) );
69 if (StopFinder.Succeeded())
71 TSubclassOf<AActor> StopSignModel = StopFinder.Class;
75 static ConstructorHelpers::FClassFinder<AActor> YieldFinder(
76 TEXT(
"/Game/Carla/Static/TrafficSign/BP_Yield01" ) );
77 if (YieldFinder.Succeeded())
79 TSubclassOf<AActor> YieldSignModel = YieldFinder.Class;
83 static ConstructorHelpers::FClassFinder<AActor> SpeedLimit30Finder(
84 TEXT(
"/Game/Carla/Static/TrafficSign/BP_SpeedLimit30" ) );
85 if (SpeedLimit30Finder.Succeeded())
87 TSubclassOf<AActor> SpeedLimitModel = SpeedLimit30Finder.Class;
90 static ConstructorHelpers::FClassFinder<AActor> SpeedLimit40Finder(
91 TEXT(
"/Game/Carla/Static/TrafficSign/BP_SpeedLimit40" ) );
92 if (SpeedLimit40Finder.Succeeded())
94 TSubclassOf<AActor> SpeedLimitModel = SpeedLimit40Finder.Class;
97 static ConstructorHelpers::FClassFinder<AActor> SpeedLimit50Finder(
98 TEXT(
"/Game/Carla/Static/TrafficSign/BP_SpeedLimit50" ) );
99 if (SpeedLimit50Finder.Succeeded())
101 TSubclassOf<AActor> SpeedLimitModel = SpeedLimit50Finder.Class;
104 static ConstructorHelpers::FClassFinder<AActor> SpeedLimit60Finder(
105 TEXT(
"/Game/Carla/Static/TrafficSign/BP_SpeedLimit60" ) );
106 if (SpeedLimit60Finder.Succeeded())
108 TSubclassOf<AActor> SpeedLimitModel = SpeedLimit60Finder.Class;
111 static ConstructorHelpers::FClassFinder<AActor> SpeedLimit70Finder(
112 TEXT(
"/Game/Carla/Static/TrafficSign/BP_SpeedLimit70" ) );
113 if (SpeedLimit70Finder.Succeeded())
115 TSubclassOf<AActor> SpeedLimitModel = SpeedLimit70Finder.Class;
118 static ConstructorHelpers::FClassFinder<AActor> SpeedLimit80Finder(
119 TEXT(
"/Game/Carla/Static/TrafficSign/BP_SpeedLimit80" ) );
120 if (SpeedLimit80Finder.Succeeded())
122 TSubclassOf<AActor> SpeedLimitModel = SpeedLimit80Finder.Class;
125 static ConstructorHelpers::FClassFinder<AActor> SpeedLimit90Finder(
126 TEXT(
"/Game/Carla/Static/TrafficSign/BP_SpeedLimit90" ) );
127 if (SpeedLimit90Finder.Succeeded())
129 TSubclassOf<AActor> SpeedLimitModel = SpeedLimit90Finder.Class;
132 static ConstructorHelpers::FClassFinder<AActor> SpeedLimit100Finder(
133 TEXT(
"/Game/Carla/Static/TrafficSign/BP_SpeedLimit100" ) );
134 if (SpeedLimit100Finder.Succeeded())
136 TSubclassOf<AActor> SpeedLimitModel = SpeedLimit100Finder.Class;
139 static ConstructorHelpers::FClassFinder<AActor> SpeedLimit110Finder(
140 TEXT(
"/Game/Carla/Static/TrafficSign/BP_SpeedLimit110" ) );
141 if (SpeedLimit110Finder.Succeeded())
143 TSubclassOf<AActor> SpeedLimitModel = SpeedLimit110Finder.Class;
146 static ConstructorHelpers::FClassFinder<AActor> SpeedLimit120Finder(
147 TEXT(
"/Game/Carla/Static/TrafficSign/BP_SpeedLimit120" ) );
148 if (SpeedLimit120Finder.Succeeded())
150 TSubclassOf<AActor> SpeedLimitModel = SpeedLimit120Finder.Class;
155 struct FUSPlate {
const TCHAR *Key;
const TCHAR *Path; };
156 const FUSPlate USPlates[] = {
157 {TEXT(
"20"), TEXT(
"/Game/Carla/Static/TrafficSign/BP_SpeedLimit20_15")},
158 {TEXT(
"25"), TEXT(
"/Game/Carla/Static/TrafficSign/BP_SpeedLimit25_15")},
159 {TEXT(
"30"), TEXT(
"/Game/Carla/Static/TrafficSign/BP_SpeedLimit30_15")},
160 {TEXT(
"50"), TEXT(
"/Game/Carla/Static/TrafficSign/BP_SpeedLimit50_40")},
161 {TEXT(
"55"), TEXT(
"/Game/Carla/Static/TrafficSign/BP_SpeedLimit55_40")},
162 {TEXT(
"75"), TEXT(
"/Game/Carla/Static/TrafficSign/BP_SpeedLimit75_45")},
164 for (
const FUSPlate &Plate : USPlates)
166 ConstructorHelpers::FClassFinder<AActor> Finder(Plate.Path);
167 if (Finder.Succeeded())
187 const auto &Signal =
GetMap()->GetSignals().at(SignId);
188 if(Signal->GetControllers().size())
191 auto ControllerId = *(Signal->GetControllers().begin());
194 const auto &Controller =
GetMap()->GetControllers().at(ControllerId);
195 if(Controller->GetJunctions().empty())
197 UE_LOG(LogCarla, Error, TEXT(
"No junctions in controller %d"), *(ControllerId.c_str()) );
201 auto JunctionId = *(Controller->GetJunctions().begin());
206 FActorSpawnParameters SpawnParams;
208 auto * NewTrafficLightGroup =
210 NewTrafficLightGroup->
JunctionId = JunctionId;
218 auto *NewTrafficLightController = NewObject<UTrafficLightController>();
219 NewTrafficLightController->SetControllerId(ControllerId.c_str());
227 FActorSpawnParameters SpawnParams;
229 auto * NewTrafficLightGroup =
232 TrafficGroups.Add(NewTrafficLightGroup->JunctionId, NewTrafficLightGroup);
233 TrafficLightGroup = NewTrafficLightGroup;
235 auto *NewTrafficLightController = NewObject<UTrafficLightController>();
237 NewTrafficLightController->SetRedTime(10);
239 TrafficControllers.Add(NewTrafficLightController->GetControllerId(), NewTrafficLightController);
240 TrafficLightController = NewTrafficLightController;
412 TArray<AActor*> Actors;
413 UGameplayStatics::GetAllActorsOfClass(GetWorld(), ATrafficLightBase::StaticClass(), Actors);
424 TArray<ATrafficLightBase*> TrafficLights;
425 for (
AActor* Actor : Actors)
430 TrafficLight->GetTrafficLightComponent()->SetSignId(
"");
435 if (!TrafficLights.Num())
441 const auto& Signals = Map->GetSignals();
442 const auto& Controllers = Map->GetControllers();
444 for(
const auto& Signal : Signals) {
445 const auto& ODSignal = Signal.second;
446 const FTransform Transform = ODSignal->GetTransform();
447 const FVector Location = Transform.GetLocation();
448 if (ODSignal->GetName() ==
"")
453 float MinDistance = FVector::DistSquaredXY(TrafficLights.Top()->GetActorLocation(), Location);
456 float Distance = FVector::DistSquaredXY(Actor->GetActorLocation(), Location);
457 if (Distance < MinDistance)
459 MinDistance = Distance;
460 ClosestActor = Actor;
465 if (Component->GetSignId() ==
"")
467 Component->SetSignId(carla::rpc::ToFString(ODSignal->GetSignalId()));
471 carla::log_warning(
"Could not find a suitable traffic light for signal", ODSignal->GetSignalId(),
472 "Closest traffic light has id", carla::rpc::FromFString(Component->GetSignId()));
621 UWorld *World = GetWorld();
628 const TArray<AActor*> IgnoredActors =
630 const TArray<UPrimitiveComponent*> NoIgnoredComponents;
631 bool bSweepWrapped =
false;
633 for (int32 i = 0; i < Checks; ++i)
647 const FVector Origin = Sign->GetActorLocation();
648 FCollisionQueryParams Params(SCENE_QUERY_STAT(SignalGroundDormancy),
false, Sign);
650 const bool bGroundResident = World->LineTraceSingleByChannel(
652 Origin + FVector(0.0f, 0.0f, 50.0f),
656 if (Sign->IsHidden() == bGroundResident)
658 Sign->SetActorHiddenInGame(!bGroundResident);
660 if (bSnapToGround && bGroundResident &&
662 World, Sign, IgnoredActors, NoIgnoredComponents))
675 GameMode->RegisterEnvironmentObjects();
760 const auto& Signals =
GetMap()->GetSignals();
761 std::unordered_set<std::string> SignalsToSpawn;
762 for(
const auto& ControllerPair :
GetMap()->GetControllers())
764 const auto& Controller = ControllerPair.second;
765 for(
const auto& SignalId : Controller->GetSignals())
767 auto& Signal = Signals.at(SignalId);
768 if (!cr::SignalType::IsTrafficLight(Signal->GetType()))
775 UTrafficLightComponent *TrafficLightComponent =
TrafficLight->GetTrafficLightComponent();
776 TrafficLightComponent->SetSignId(SignalId.c_str());
780 SignalsToSpawn.insert(SignalId);
785 for(
const auto& SignalPair : Signals)
787 const auto& SignalId = SignalPair.first;
788 const auto& Signal = SignalPair.second;
789 if(!Signal->GetControllers().size() &&
790 !
GetMap()->IsJunction(Signal->GetRoadId()) &&
792 !SignalsToSpawn.count(SignalId))
797 UTrafficLightComponent *TrafficLightComponent =
TrafficLight->GetTrafficLightComponent();
798 TrafficLightComponent->SetSignId(SignalId.c_str());
802 SignalsToSpawn.insert(SignalId);
809 for(
auto &SignalId : SignalsToSpawn)
815 if (Signals.count(SignalId) == 0)
817 UE_LOG(LogCarla, Warning,
818 TEXT(
"Possible OpenDRIVE error, reference to nonexistent signal id: %s"),
819 *carla::rpc::ToFString(SignalId));
822 const auto& Signal = Signals.at(SignalId);
823 auto CarlaTransform = Signal->GetTransform();
827 CarlaTransform.location.z -=
static_cast<float>(Signal->GetZOffset());
828 auto ClosestWaypointToSignal =
829 GetMap()->GetClosestWaypointOnRoad(CarlaTransform.location);
831 const bool IsRHT =
GetMap()->GetLane(ClosestWaypointToSignal.value()).GetRoad()->IsRHT();
833 FTransform SpawnTransform(CarlaTransform);
835 FVector SpawnLocation = SpawnTransform.GetLocation();
836 FRotator SpawnRotation(SpawnTransform.GetRotation());
838 SpawnRotation.Yaw += 90;
840 SpawnRotation.Roll = 0;
841 SpawnRotation.Pitch = 0;
843 FActorSpawnParameters SpawnParams;
844 SpawnParams.Owner =
this;
845 SpawnParams.SpawnCollisionHandlingOverride =
846 ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
862 UTrafficLightComponent *TrafficLightComponent =
TrafficLight->GetTrafficLightComponent();
863 TrafficLightComponent->SetSignId(SignalId.c_str());
865 if (ClosestWaypointToSignal)
867 auto SignalDistanceToRoad =
868 (
GetMap()->ComputeTransform(ClosestWaypointToSignal.value()).location - CarlaTransform.location).Length();
869 double LaneWidth =
GetMap()->GetLaneWidth(ClosestWaypointToSignal.value());
871 if(SignalDistanceToRoad < LaneWidth * 0.5)
874 TCHAR_TO_UTF8(*TrafficLightComponent->GetSignId()),
875 "overlaps a driving lane. Disabling collision...");
877 TArray<UPrimitiveComponent*> Primitives;
879 for (
auto* Primitive : Primitives)
881 Primitive->SetCollisionProfileName(TEXT(
"NoCollision"));
887 TrafficLightComponent->InitializeSign(
GetMap().value());
896 const auto &Signals =
GetMap()->GetSignals();
897 for (
auto& SignalPair : Signals)
899 auto &Signal = SignalPair.second;
900 FString SignalType = Signal->GetType().c_str();
903 if (ClosestTrafficSign)
905 USignComponent *SignComponent;
909 NewObject<USignComponent>(
915 NewObject<USignComponent>(
918 SignComponent->SetSignId(Signal->GetSignalId().c_str());
919 SignComponent->RegisterComponent();
920 SignComponent->AttachToComponent(
921 ClosestTrafficSign->GetRootComponent(),
922 FAttachmentTransformRules::KeepRelativeTransform);
929 if (Signal->GetName() ==
"Stencil_STOP")
933 auto CarlaTransform = Signal->GetTransform();
938 CarlaTransform.location.z -=
static_cast<float>(Signal->GetZOffset());
939 FTransform SpawnTransform(CarlaTransform);
940 FVector SpawnLocation = SpawnTransform.GetLocation();
941 FRotator SpawnRotation(SpawnTransform.GetRotation());
942 SpawnRotation.Yaw += 90;
944 SpawnRotation.Roll = 0;
945 SpawnRotation.Pitch = 0;
947 FActorSpawnParameters SpawnParams;
948 SpawnParams.Owner =
this;
949 SpawnParams.SpawnCollisionHandlingOverride =
950 ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
958 USignComponent *SignComponent =
960 SignComponent->SetSignId(Signal->GetSignalId().c_str());
961 SignComponent->RegisterComponent();
962 SignComponent->AttachToComponent(
963 TrafficSign->GetRootComponent(),
964 FAttachmentTransformRules::KeepRelativeTransform);
965 SignComponent->InitializeSign(
GetMap().value());
967 auto ClosestWaypointToSignal =
968 GetMap()->GetClosestWaypointOnRoad(CarlaTransform.location);
969 if (ClosestWaypointToSignal)
971 auto SignalDistanceToRoad =
972 (
GetMap()->ComputeTransform(ClosestWaypointToSignal.value()).location - CarlaTransform.location).Length();
973 double LaneWidth =
GetMap()->GetLaneWidth(ClosestWaypointToSignal.value());
975 if(SignalDistanceToRoad < LaneWidth * 0.5)
978 TCHAR_TO_UTF8(*SignComponent->GetSignId()),
979 "overlaps a driving lane. Disabling collision...");
981 TArray<UPrimitiveComponent*> Primitives;
982 TrafficSign->GetComponents(Primitives);
983 for (
auto* Primitive : Primitives)
985 Primitive->SetCollisionProfileName(TEXT(
"NoCollision"));
1003 TSubclassOf<AActor> SpeedModel =
SpeedLimitModels[Signal->GetSubtype().c_str()];
1006 const float Kmh = FCString::Atof(*FString(Signal->GetSubtype().c_str()));
1007 const float Mph = Kmh / 1.60934f;
1009 float BestDiff = TNumericLimits<float>::Max();
1012 const float Diff = FMath::Abs(FCString::Atof(*Pair.Key) - Mph);
1013 if (Diff < BestDiff)
1019 if (!BestKey.IsEmpty())
1024 auto CarlaTransform = Signal->GetTransform();
1027 CarlaTransform.location.z -=
static_cast<float>(Signal->GetZOffset());
1028 FTransform SpawnTransform(CarlaTransform);
1029 FVector SpawnLocation = SpawnTransform.GetLocation();
1030 FRotator SpawnRotation(SpawnTransform.GetRotation());
1031 SpawnRotation.Yaw += 90;
1033 SpawnRotation.Roll = 0;
1034 SpawnRotation.Pitch = 0;
1036 FActorSpawnParameters SpawnParams;
1037 SpawnParams.Owner =
this;
1038 SpawnParams.SpawnCollisionHandlingOverride =
1039 ESpawnActorCollisionHandlingMethod::AlwaysSpawn;
1047 USpeedLimitComponent *SignComponent =
1048 NewObject<USpeedLimitComponent>(TrafficSign);
1049 SignComponent->SetSignId(Signal->GetSignalId().c_str());
1050 SignComponent->RegisterComponent();
1051 SignComponent->AttachToComponent(
1052 TrafficSign->GetRootComponent(),
1053 FAttachmentTransformRules::KeepRelativeTransform);
1054 SignComponent->InitializeSign(
GetMap().value());
1055 SignComponent->SetSpeedLimit(Signal->GetValue());
1057 auto ClosestWaypointToSignal =
1058 GetMap()->GetClosestWaypointOnRoad(CarlaTransform.location);
1059 if (ClosestWaypointToSignal)
1061 auto SignalDistanceToRoad =
1062 (
GetMap()->ComputeTransform(ClosestWaypointToSignal.value()).location - CarlaTransform.location).Length();
1063 double LaneWidth =
GetMap()->GetLaneWidth(ClosestWaypointToSignal.value());
1065 if(SignalDistanceToRoad < LaneWidth * 0.5)
1068 TCHAR_TO_UTF8(*SignComponent->GetSignId()),
1069 "overlaps a driving lane. Disabling collision...");
1071 TArray<UPrimitiveComponent*> Primitives;
1072 TrafficSign->GetComponents(Primitives);
1073 for (
auto* Primitive : Primitives)
1075 Primitive->SetCollisionProfileName(TEXT(
"NoCollision"));