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