CARLA
LargeMapManager.cpp
Go to the documentation of this file.
1 // Copyright (c) 2021 Computer Vision Center (CVC) at the Universitat Autonoma de Barcelona (UAB).
2 // This work is licensed under the terms of the MIT license.
3 // For a copy, see <https://opensource.org/licenses/MIT>.
4 
5 #include "LargeMapManager.h"
6 
7 #include "Engine/WorldComposition.h"
8 #include "Engine/ObjectLibrary.h"
9 #include "Game/CarlaStatics.h"
10 #include "Actor/ActorRegistry.h"
11 #include "Game/CarlaEpisode.h"
12 #include "Engine/EngineTypes.h"
13 #include "Components/PrimitiveComponent.h"
14 #include "Landscape.h"
15 #include "LandscapeHeightfieldCollisionComponent.h"
16 #include "LandscapeComponent.h"
17 
19 
20 #include "Walker/WalkerBase.h"
21 #include "Carla/Game/Tagger.h"
23 
24 #include "FileHelper.h"
25 #include "Paths.h"
26 
27 #define LARGEMAP_LOGS 1
28 
29 #if LARGEMAP_LOGS
30 #define LM_LOG(Level, Msg, ...) UE_LOG(LogCarla, Level, TEXT(Msg), ##__VA_ARGS__)
31 #else
32 #define LM_LOG(...)
33 #endif
34 
35 // Sets default values
37 {
38  PrimaryActorTick.bCanEverTick = true;
39  // PrimaryActorTick.TickInterval = TickInterval;
40 }
41 
43 {
44  /// Remove delegates
45  // Origin rebase
46  FCoreDelegates::PreWorldOriginOffset.RemoveAll(this);
47  FCoreDelegates::PostWorldOriginOffset.RemoveAll(this);
48  // Level added/removed from world
49  FWorldDelegates::LevelRemovedFromWorld.RemoveAll(this);
50  FWorldDelegates::LevelAddedToWorld.RemoveAll(this);
51 
52 }
53 
54 // Called when the game starts or when spawned
56 {
57  Super::BeginPlay();
59 
60  UWorld* World = GetWorld();
61  /// Setup delegates
62  // Origin rebase
63  FCoreDelegates::PreWorldOriginOffset.AddUObject(this, &ALargeMapManager::PreWorldOriginOffset);
64  FCoreDelegates::PostWorldOriginOffset.AddUObject(this, &ALargeMapManager::PostWorldOriginOffset);
65  // Level added/removed from world
66  FWorldDelegates::LevelAddedToWorld.AddUObject(this, &ALargeMapManager::OnLevelAddedToWorld);
67  FWorldDelegates::LevelRemovedFromWorld.AddUObject(this, &ALargeMapManager::OnLevelRemovedFromWorld);
68 
69  // Setup Origin rebase settings
70  UWorldComposition* WorldComposition = World->WorldComposition;
71  WorldComposition->bRebaseOriginIn3DSpace = true;
72  WorldComposition->RebaseOriginDistance = RebaseOriginDistance;
73 
77 
78  // Look for terramechanics actor
79  TArray<AActor*> FoundActors;
80  UGameplayStatics::GetAllActorsOfClass(GetWorld(), AActor::StaticClass(), FoundActors);
81  for(auto CurrentActor : FoundActors)
82  {
83  if( CurrentActor->FindComponentByClass( UCustomTerrainPhysicsComponent::StaticClass() ) != nullptr )
84  {
85  bHasTerramechanics = true;
86  break;
87  }
88  }
89 
90  // Get spectator
91  APlayerController* PlayerController = UGameplayStatics::GetPlayerController(GetWorld(), 0);
92  if(PlayerController)
93  {
94  Spectator = PlayerController->GetPawnOrSpectator();
95  }
96 }
97 
98 void ALargeMapManager::PreWorldOriginOffset(UWorld* InWorld, FIntVector InSrcOrigin, FIntVector InDstOrigin)
99 {
100  LM_LOG(Log, "PreWorldOriginOffset Src: %s -> Dst: %s", *InSrcOrigin.ToString(), *InDstOrigin.ToString());
101 }
102 
103 void ALargeMapManager::PostWorldOriginOffset(UWorld* InWorld, FIntVector InSrcOrigin, FIntVector InDstOrigin)
104 {
105  TRACE_CPUPROFILER_EVENT_SCOPE(ALargeMapManager::PostWorldOriginOffset);
106  CurrentOriginInt = InDstOrigin;
107  CurrentOriginD = FDVector(InDstOrigin);
108 
109  UWorld* World = GetWorld();
110  UCarlaEpisode* CarlaEpisode = UCarlaStatics::GetCurrentEpisode(World);
111  CarlaEpisode->SetCurrentMapOrigin(CurrentOriginInt);
112 
113 #if WITH_EDITOR
114  GEngine->AddOnScreenDebugMessage(66, MsgTime, FColor::Yellow,
115  FString::Printf(TEXT("Src: %s -> Dst: %s"), *InSrcOrigin.ToString(), *InDstOrigin.ToString()));
116  LM_LOG(Log, "PostWorldOriginOffset Src: %s -> Dst: %s", *InSrcOrigin.ToString(), *InDstOrigin.ToString());
117 
118  // This is just to update the color of the msg with the same as the closest map
119  const TArray<ULevelStreaming*>& StreamingLevels = World->GetStreamingLevels();
120  FColor LevelColor = FColor::White;
121  float MinDistance = 10000000.0f;
122  for (const auto& TilePair : MapTiles)
123  {
124  const FCarlaMapTile& Tile = TilePair.Value;
125  const ULevelStreaming* Level = Tile.StreamingLevel;
126  FVector LevelLocation = Tile.Location;
127  float Distance = FVector::Dist(LevelLocation, FVector(InDstOrigin));
128  if (Distance < MinDistance)
129  {
130  MinDistance = Distance;
131  PositonMsgColor = Level->LevelColor.ToFColor(false);
132  }
133  }
134 #endif // WITH_EDITOR
135 }
136 
137 void ALargeMapManager::OnLevelAddedToWorld(ULevel* InLevel, UWorld* InWorld)
138 {
139  LM_LOG(Warning, "OnLevelAddedToWorld");
140  ATagger::TagActorsInLevel(*InLevel, true);
141 
142 
143  //FDebug::DumpStackTraceToLog(ELogVerbosity::Log);
144 }
145 
146 void ALargeMapManager::OnLevelRemovedFromWorld(ULevel* InLevel, UWorld* InWorld)
147 {
148  LM_LOG(Warning, "OnLevelRemovedFromWorld");
149  //FDebug::DumpStackTraceToLog(ELogVerbosity::Log);
150  FCarlaMapTile& Tile = GetCarlaMapTile(InLevel);
151  Tile.TilesSpawned = false;
152 }
153 
155 {
156  TRACE_CPUPROFILER_EVENT_SCOPE(ALargeMapManager::RegisterInitialObjects);
157  UWorld* World = GetWorld();
158  UCarlaEpisode* CurrentEpisode = UCarlaStatics::GetCurrentEpisode(World);
159  const FActorRegistry& ActorRegistry = CurrentEpisode->GetActorRegistry();
160  for (const auto& CarlaActorPair : ActorRegistry)
161  {
162  if (CarlaActorPair.Value->GetActorInfo()->Description.Id == "spectator")
163  {
164  continue;
165  }
166  OnActorSpawned(*CarlaActorPair.Value.Get());
167  }
168 }
169 
171  const FCarlaActor& CarlaActor)
172 {
173  TRACE_CPUPROFILER_EVENT_SCOPE(ALargeMapManager::OnActorSpawned);
174  UWorld* World = GetWorld();
175  const FActorInfo* ActorInfo = CarlaActor.GetActorInfo();
176  AActor* Actor = const_cast<AActor*>(CarlaActor.GetActor());
177  bool IsHeroVehicle = false;
178 
179  // LM_LOG(Warning, "ALargeMapManager::OnActorSpawned func %s %s", *Actor->GetName(), *Actor->GetTranslation().ToString());
180 
181  if (Actor)
182  { // Check if is hero vehicle
183 
184  assert(ActorInfo);
185 
186  const FActorDescription& Description = ActorInfo->Description;
187  const FActorAttribute* Attribute = Description.Variations.Find("role_name");
188  // If is the hero vehicle
189  if(Attribute && (Attribute->Value.Contains("hero") || Attribute->Value.Contains("ego_vehicle")))
190  {
191  LM_LOG(Log, "HERO VEHICLE DETECTED");
192 
193  if (ActorsToConsider.Num() == 1 && ActorsToConsider.Contains(Spectator))
194  {
195  ActorsToConsider.Reset();
196  }
197  ActorsToConsider.Add(Actor);
198 
200 
202 
203  // Wait until the pending levels changes are finished to avoid spawning
204  // the car without ground underneath
205  World->FlushLevelStreaming();
206 
207  IsHeroVehicle = true;
208  }
209  }
210 
211  // Any other actor that its role is not "hero"
212  if(!IsHeroVehicle)
213  {
214  UCarlaEpisode* CurrentEpisode = UCarlaStatics::GetCurrentEpisode(World);
215  const FActorRegistry& ActorRegistry = CurrentEpisode->GetActorRegistry();
216 
217  // Any actor that is not the hero vehicle could possible be destroyed at some point
218  // we need to store the CarlaActor information to be able to spawn it again if needed
219 
220  if(IsValid(Actor))
221  { // Actor was spwaned succesfully
222  // TODO: not dormant but not hero => ActiveActor
223  // LM: Map<AActor* FActiveActor> maybe per tile and in a tile sublevel?
224 
225  LM_LOG(Log, "ACTIVE VEHICLE DETECTED");
226  ActiveActors.Add(CarlaActor.GetActorId());
227  }
228  else
229  { // Actor was spawned as dormant
230  // TODO: dormant => no actor so Actorview stored per tile
231  // LM: Map<ActorId, TileID> , Tile: Map<ActorID, FDormantActor>
232  // In case of update: update Tile Map, update LM Map
233  LM_LOG(Log, "DORMANT VEHICLE DETECTED");
234  DormantActors.Add(CarlaActor.GetActorId());
235  }
236  }
237 
238  if (IsValid(Actor)) {
239  Actor->OnDestroyed.AddDynamic(this, &ALargeMapManager::OnActorDestroyed);
240  FVector GlobalPosition = LocalToGlobalLocation(Actor->GetActorLocation());
241  LM_LOG(Warning, "Actor Spawned at %s", *GlobalPosition.ToString());
242  }
243 
244 }
245 
247 {
248  if (ActorsToConsider.Num() > 0)
249  {
250  ACarlaWheeledVehicle* Hero = Cast<ACarlaWheeledVehicle>(ActorsToConsider[0]);
251  if (IsValid(Hero))
252  return Hero;
253  }
254  return nullptr;
255 }
256 
258 {
259  LM_LOG(Warning, "ALargeMapManager::OnActorDestroyed %s", *DestroyedActor->GetName());
260 
261  UWorld* World = GetWorld();
262  UCarlaEpisode* CarlaEpisode = UCarlaStatics::GetCurrentEpisode(World);
263  FCarlaActor* CarlaActor = CarlaEpisode->FindCarlaActor(DestroyedActor);
264  if (CarlaActor)
265  const FActorInfo* ActorInfo = CarlaActor->GetActorInfo();
266 
267  // Hero has been removed?
268  //
269 
270 }
271 
272 void ALargeMapManager::SetTile0Offset(const FVector& Offset)
273 {
274  Tile0Offset = Offset;
275 }
276 
278 {
279  TileSide = Size;
280 }
281 
283 {
284  return TileSide;
285 }
286 
288 {
289  return Tile0Offset;
290 }
291 
293 {
294  LayerStreamingDistance = Distance;
297 }
298 
300 {
301  ActorStreamingDistance = Distance;
304 }
305 
307 {
308  return LayerStreamingDistance;
309 }
310 
312 {
313  return ActorStreamingDistance;
314 }
315 
316 FTransform ALargeMapManager::GlobalToLocalTransform(const FTransform& InTransform) const
317 {
318  return FTransform(
319  InTransform.GetRotation(),
320  InTransform.GetLocation() - CurrentOriginD.ToFVector(),
321  InTransform.GetScale3D());
322 }
323 
324 FVector ALargeMapManager::GlobalToLocalLocation(const FVector& InLocation) const
325 {
326  return InLocation - CurrentOriginD.ToFVector();
327 }
328 
329 FTransform ALargeMapManager::LocalToGlobalTransform(const FTransform& InTransform) const
330 {
331  return FTransform(
332  InTransform.GetRotation(),
333  CurrentOriginD.ToFVector() + InTransform.GetLocation(),
334  InTransform.GetScale3D());
335 }
336 
337 FVector ALargeMapManager::LocalToGlobalLocation(const FVector& InLocation) const
338 {
339  return CurrentOriginD.ToFVector() + InLocation;
340 }
341 
343 uint64_t num_ticks = 0;
344 void ALargeMapManager::Tick(float DeltaTime)
345 {
346  Super::Tick(DeltaTime);
347 
348  // Update map tiles, load/unload based on actors to consider (heros) position
349  // Also, to avoid looping over the heros again, it checks if any actor to consider has been removed
351 
352  // Check if active actors are still in range and inside a loaded tile or have to be converted to dormant
354 
355  // Check if dormant actors have been moved to the load range
357 
358  // Remove the hero actors that doesn't exits any more from the ActorsToConsider vector
360 
362 
364 
366 
367 #if WITH_EDITOR
369 #endif // WITH_EDITOR
370 
371 }
372 
375 }
376 
377 void ALargeMapManager::GenerateMap(FString InAssetsPath)
378 {
379  TRACE_CPUPROFILER_EVENT_SCOPE(ALargeMapManager::GenerateMap);
380  LM_LOG(Warning, "Generating Map %s ...", *InAssetsPath);
382 
383  AssetsPath = InAssetsPath;
384 
385  /// Retrive all the assets in the path
386  TArray<FAssetData> AssetsData;
387  UObjectLibrary* ObjectLibrary = UObjectLibrary::CreateLibrary(UWorld::StaticClass(), true, true);
388  ObjectLibrary->LoadAssetDataFromPath(InAssetsPath);
389  ObjectLibrary->GetAssetDataList(AssetsData);
390 
391  /// Generate tiles based on mesh positions
392  UWorld* World = GetWorld();
393  MapTiles.Reset();
394  for (const FAssetData& AssetData : AssetsData)
395  {
396  #if WITH_EDITOR
397  // LM_LOG(Warning, "Loading asset name: %s", *(AssetData.AssetName.ToString()));
398  // LM_LOG(Warning, "Asset class: %s", *(AssetData.AssetClass.ToString()));
399  #endif
400  FString TileName = AssetData.AssetName.ToString();
401  if (!TileName.Contains("_Tile_"))
402  {
403  continue;
404  }
405  FString TileName_X = "";
406  FString TileName_Y = "";
407  size_t i = TileName.Len()-1;
408  for (; i > 0; i--) {
409  TCHAR character = TileName[i];
410  if (character == '_') {
411  break;
412  }
413  TileName_Y = FString::Chr(character) + TileName_Y;
414  }
415  i--;
416  for (; i > 0; i--) {
417  TCHAR character = TileName[i];
418  if (character == '_') {
419  break;
420  }
421  TileName_X = FString::Chr(character) + TileName_X;
422  }
423  FIntVector TileVectorID = FIntVector(FCString::Atoi(*TileName_X), FCString::Atoi(*TileName_Y), 0);
424  #if WITH_EDITOR
425  // LM_LOG(Warning, "Tile: %d, %d", TileVectorID.X, TileVectorID.Y);
426  #endif
427  TileID TileId = GetTileID(TileVectorID);
428  LoadCarlaMapTile(InAssetsPath + "/" + AssetData.AssetName.ToString(), TileId);
429  }
430  ObjectLibrary->ConditionalBeginDestroy();
431  GEngine->ForceGarbageCollection(true);
432 
433  ActorsToConsider.Reset();
434  if (SpectatorAsEgo && Spectator)
435  {
437  }
438 
439 #if WITH_EDITOR
440  LM_LOG(Warning, "GenerateMap num Tiles generated %d", MapTiles.Num());
441  DumpTilesTable();
442 #endif // WITH_EDITOR
443 }
444 
445 void ALargeMapManager::GenerateMap(TArray<TPair<FString, FIntVector>> MapPathsIds)
446 {
447  TRACE_CPUPROFILER_EVENT_SCOPE(ALargeMapManager::GenerateMap);
448  LM_LOG(Warning, "Generating Large Map");
450 
451  for (TPair<FString, FIntVector>& PathId : MapPathsIds)
452  {
453  FIntVector& TileVectorID = PathId.Value;
454  FString& Path = PathId.Key;
455  TileID TileId = GetTileID(TileVectorID);
456  LoadCarlaMapTile(Path, TileId);
457  }
458 
459  #if WITH_EDITOR
460  LM_LOG(Warning, "GenerateMap num Tiles generated %d", MapTiles.Num());
461  #endif // WITH_EDITOR
462 }
463 
465 {
466  MapTiles.Empty();
467 }
468 
470 {
471  UWorld* World = GetWorld();
472  UWorldComposition* WorldComposition = World->WorldComposition;
473  World->ClearStreamingLevels();
474  WorldComposition->TilesStreaming.Empty();
475  WorldComposition->GetTilesList().Empty();
476 
477  for (auto& It : MapTiles)
478  {
479  ULevelStreamingDynamic* StreamingLevel = It.Value.StreamingLevel;
480  World->AddStreamingLevel(StreamingLevel);
481  WorldComposition->TilesStreaming.Add(StreamingLevel);
482  }
483 }
484 
485 // TODO: maybe remove this, I think I will not need it any more
486 void ALargeMapManager::AddActorToUnloadedList(const FCarlaActor& CarlaActor, const FTransform& Transform)
487 {
488  // ActiveActors.Add(CarlaActor.GetActorId(), {Transform, CarlaActor});
489 }
490 
492 {
493  int32 MinX = 0;
494  int32 MaxX = 0;
495  int32 MinY = 0;
496  int32 MaxY = 0;
497  for (auto& It : MapTiles)
498  {
499  FIntVector TileID = GetTileVectorID(It.Key);
500  MinX = (TileID.X < MinX) ? TileID.X : MinX;
501  MaxX = (TileID.X > MaxX) ? TileID.X : MaxX;
502 
503  MinY = (TileID.Y < MinY) ? TileID.Y : MinY;
504  MaxY = (TileID.Y > MaxY) ? TileID.Y : MaxY;
505  }
506  return { MaxX - MinX + 1, MaxY - MinY + 1, 0 };
507 }
508 
509 bool ALargeMapManager::IsLevelOfTileLoaded(FIntVector InTileID) const
510 {
511  TileID TileID = GetTileID(InTileID);
512 
513  const FCarlaMapTile* Tile = MapTiles.Find(TileID);
514  if (!Tile)
515  {
516  if (bPrintErrors)
517  {
518  LM_LOG(Warning, "IsLevelOfTileLoaded Tile %s does not exist", *InTileID.ToString());
519  }
520  return false;
521  }
522 
523  const ULevelStreamingDynamic* StreamingLevel = Tile->StreamingLevel;
524 
525  return (StreamingLevel && StreamingLevel->GetLoadedLevel());
526 }
527 
528 FIntVector ALargeMapManager::GetTileVectorID(FVector TileLocation) const
529 {
530  FIntVector VectorId = FIntVector(
531  (TileLocation -
532  (Tile0Offset - FVector(0.5f*TileSide,-0.5f*TileSide, 0) + LocalTileOffset))
533  / TileSide);
534  VectorId.Y *= -1;
535  return VectorId;
536 }
537 
538 FIntVector ALargeMapManager::GetTileVectorID(FDVector TileLocation) const
539 {
540  FIntVector VectorId = (
541  (TileLocation -
542  (Tile0Offset - FVector(0.5f*TileSide,-0.5f*TileSide, 0) + LocalTileOffset))
543  / TileSide).ToFIntVector();
544  VectorId.Y *= -1;
545  return VectorId;
546 }
547 
549 {
550  return FIntVector{
551  (int32)(TileID >> 32),
552  (int32)(TileID & (int32)(~0)),
553  0
554  };
555 }
556 
558 {
559  FIntVector VTileId = GetTileVectorID(TileID);
560  return GetTileLocation(VTileId);
561 }
562 
563 FVector ALargeMapManager::GetTileLocation(FIntVector TileVectorID) const
564 {
565  TileVectorID.Y *= -1;
566  return FVector(TileVectorID)* TileSide + Tile0Offset;
567 }
568 
570 {
571  FIntVector VTileId = GetTileVectorID(TileID);
572  return GetTileLocationD(VTileId);
573 }
574 
575 FDVector ALargeMapManager::GetTileLocationD(FIntVector TileVectorID) const
576 {
577  TileVectorID.Y *= -1;
578  return FDVector(TileVectorID) * TileSide + Tile0Offset;
579 }
580 
582 {
583  int64 X = ((int64)(TileVectorID.X) << 32);
584  int64 Y = (int64)(TileVectorID.Y) & 0x00000000FFFFFFFF;
585  return (X | Y);
586 }
587 
589 {
590  FIntVector TileID = GetTileVectorID(TileLocation);
591  return GetTileID(TileID);
592 }
593 
595 {
596  FIntVector TileID = GetTileVectorID(TileLocation);
597  return GetTileID(TileID);
598 }
599 
601 {
602  TileID TileID = GetTileID(Location);
603  return GetCarlaMapTile(TileID);
604 }
605 
607 {
608  FCarlaMapTile* Tile = nullptr;
609  for (auto& It : MapTiles)
610  {
611  ULevelStreamingDynamic* StreamingLevel = It.Value.StreamingLevel;
612  ULevel* Level = StreamingLevel->GetLoadedLevel();
613  if (Level == InLevel)
614  {
615  Tile = &(It.Value);
616  break;
617  }
618  }
619  check(Tile);
620  return *Tile;
621 }
622 
624 {
625  TileID TileID = GetTileID(TileVectorID);
626  FCarlaMapTile* Tile = MapTiles.Find(TileID);
627  return *Tile;
628 }
629 
631 {
632  FCarlaMapTile* Tile = MapTiles.Find(TileID);
633  return Tile;
634 }
635 
637  TRACE_CPUPROFILER_EVENT_SCOPE(ALargeMapManager::LoadCarlaMapTile);
638  // Need to generate a new Tile
639  FCarlaMapTile NewTile;
640  // 1 - Calculate the Tile position
641  FIntVector VTileID = GetTileVectorID(TileId);
642  NewTile.Location = GetTileLocation(TileId);
643  NewTile.Name = TileMapPath;
644 
645  // 3 - Generate the StreamLevel
646  FVector TileLocation = NewTile.Location;
647  FString TileName = NewTile.Name;
648  UWorld* World = GetWorld();
649  UWorldComposition* WorldComposition = World->WorldComposition;
650 
651  FString FullName = TileMapPath;
652  FString PackageFileName = FullName;
653  FString LongLevelPackageName = FPackageName::FilenameToLongPackageName(PackageFileName);
654  FString UniqueLevelPackageName = LongLevelPackageName;
655 
656  ULevelStreamingDynamic* StreamingLevel = NewObject<ULevelStreamingDynamic>(World, *TileName);
657  check(StreamingLevel);
658 
659  StreamingLevel->SetWorldAssetByPackageName(*UniqueLevelPackageName);
660 
661 #if WITH_EDITOR
662  if (World->IsPlayInEditor())
663  {
664  FWorldContext WorldContext = GEngine->GetWorldContextFromWorldChecked(World);
665  StreamingLevel->RenameForPIE(WorldContext.PIEInstance);
666  }
667  StreamingLevel->SetShouldBeVisibleInEditor(true);
668  StreamingLevel->LevelColor = FColor::MakeRandomColor();
669 #endif // WITH_EDITOR
670 
671  StreamingLevel->SetShouldBeLoaded(false);
672  StreamingLevel->SetShouldBeVisible(false);
673  StreamingLevel->bShouldBlockOnLoad = ShouldTilesBlockOnLoad;
674  StreamingLevel->bInitiallyLoaded = false;
675  StreamingLevel->bInitiallyVisible = false;
676  StreamingLevel->LevelTransform = FTransform(TileLocation);
677  StreamingLevel->PackageNameToLoad = *FullName;
678 
679  if (!FPackageName::DoesPackageExist(FullName, NULL, &PackageFileName))
680  {
681  LM_LOG(Error, "Level does not exist in package with FullName variable -> %s", *FullName);
682  }
683 
684  if (!FPackageName::DoesPackageExist(LongLevelPackageName, NULL, &PackageFileName))
685  {
686  LM_LOG(Error, "Level does not exist in package with LongLevelPackageName variable -> %s", *LongLevelPackageName);
687  }
688 
689  //Actual map package to load
690  StreamingLevel->PackageNameToLoad = *LongLevelPackageName;
691 
692  NewTile.StreamingLevel = StreamingLevel;
693 
694  // 4 - Add it to the map
695  return MapTiles.Add(TileId, NewTile);
696 }
697 
699 {
700  TRACE_CPUPROFILER_EVENT_SCOPE(ALargeMapManager::UpdateTilesState);
701  TSet<TileID> TilesToConsider;
702 
703  // Loop over ActorsToConsider to update the state of the map tiles
704  // if the actor is not valid will be removed
705  for (AActor* Actor : ActorsToConsider)
706  {
707  if (IsValid(Actor))
708  {
709  GetTilesToConsider(Actor, TilesToConsider);
710  }
711  else
712  {
713  ActorsToRemove.Add(Actor);
714  }
715  }
716 
717  TSet<TileID> TilesToBeVisible;
718  TSet<TileID> TilesToHidde;
719  GetTilesThatNeedToChangeState(TilesToConsider, TilesToBeVisible, TilesToHidde);
720 
721  UpdateTileState(TilesToBeVisible, true, true, true);
722 
723  UpdateTileState(TilesToHidde, false, false, false);
724 
725  UpdateCurrentTilesLoaded(TilesToBeVisible, TilesToHidde);
726 
727 }
728 
730 {
731  TRACE_CPUPROFILER_EVENT_SCOPE(ALargeMapManager::RemovePendingActorsToRemove);
732  if(ActorsToRemove.Num() > 0 || ActivesToRemove.Num() > 0)
733  {
734  LM_LOG(Log, "ActorsToRemove %d ActivesToRemove %d", ActorsToRemove.Num(), ActivesToRemove.Num());
735  }
736 
737  for (AActor* ActorToRemove : ActorsToRemove)
738  {
739  ActorsToConsider.Remove(ActorToRemove);
740  }
741  if(ActorsToConsider.Num() == 0 && SpectatorAsEgo && Spectator)
742  {
744  }
745  ActorsToRemove.Reset();
746 
747 
748  for (FCarlaActor::IdType ActorToRemove : ActivesToRemove)
749  {
750  ActiveActors.Remove(ActorToRemove);
751  }
752  ActivesToRemove.Reset();
753 
755  {
756  DormantActors.Remove(Id);
757  }
758  DormantsToRemove.Reset();
759 }
760 
762 {
763  TRACE_CPUPROFILER_EVENT_SCOPE(ALargeMapManager::CheckActiveActors);
764  UWorld* World = GetWorld();
765  UCarlaEpisode* CarlaEpisode = UCarlaStatics::GetCurrentEpisode(World);
766  // Check if they have to be destroyed
768  {
769  FCarlaActor* View = CarlaEpisode->FindCarlaActor(Id);
770  if (View)
771  {
772  AActor * Actor = View->GetActor();
773  FVector RelativeLocation = Actor->GetActorLocation();
774  FDVector WorldLocation = CurrentOriginD + RelativeLocation;
775 
776  if(!IsTileLoaded(WorldLocation))
777  {
778  // Save to temporal container. Later will be converted to dormant
779  ActiveToDormantActors.Add(Id);
780  ActivesToRemove.Add(Id);
781  continue;
782  }
783 
784  for(AActor* HeroActor : ActorsToConsider)
785  {
786  FVector HeroLocation = HeroActor->GetActorLocation();
787 
788  float DistanceSquared = (RelativeLocation - HeroLocation).SizeSquared();
789 
791  {
792  // Save to temporal container. Later will be converted to dormant
793  ActiveToDormantActors.Add(Id);
794  ActivesToRemove.Add(Id);
795  }
796  }
797  }
798  else
799  {
800  LM_LOG(Warning, "CheckActiveActors Actor does not exist -> Remove actor");
801  ActivesToRemove.Add(Id);
802  }
803  }
804 }
805 
807 {
808  TRACE_CPUPROFILER_EVENT_SCOPE(ALargeMapManager::ConvertActiveToDormantActors);
809  UWorld* World = GetWorld();
810  UCarlaEpisode* CarlaEpisode = UCarlaStatics::GetCurrentEpisode(World);
811 
812  // These actors are on dormant state so remove them from active actors
813  // But save them on the dormant array first
815  {
816  // To dormant state
817  CarlaEpisode->PutActorToSleep(Id);
818 
819  LM_LOG(Warning, "Converting Active To Dormant... %d", Id);
820 
821  // Need the ID of the dormant actor and save it
822  DormantActors.Add(Id);
823  }
824 
825  ActiveToDormantActors.Reset();
826 }
827 
829 {
830  TRACE_CPUPROFILER_EVENT_SCOPE(ALargeMapManager::CheckDormantActors);
831  UWorld* World = GetWorld();
832  UCarlaEpisode* CarlaEpisode = UCarlaStatics::GetCurrentEpisode(World);
833 
834 
836  {
837  FCarlaActor* CarlaActor = CarlaEpisode->FindCarlaActor(Id);
838 
839  // If the Ids don't match, the actor has been removed
840  if(!CarlaActor)
841  {
842  LM_LOG(Log, "CheckDormantActors Carla Actor %d not found", Id);
843  DormantsToRemove.Add(Id);
844  continue;
845  }
846  if(CarlaActor->GetActorId() != Id)
847  {
848  LM_LOG(Warning, "CheckDormantActors IDs doesn't match!! Wanted = %d Received = %d", Id, CarlaActor->GetActorId());
849  DormantsToRemove.Add(Id);
850  continue;
851  }
852  if (!CarlaActor->IsDormant())
853  {
854  LM_LOG(Warning, "CheckDormantActors Carla Actor %d is not dormant", Id);
855  DormantsToRemove.Add(Id);
856  continue;
857  }
858 
859  const FActorData* ActorData = CarlaActor->GetActorData();
860 
862  {
863  FVector HeroLocation = Actor->GetActorLocation();
864 
865  FDVector WorldLocation = ActorData->Location;
866  FDVector RelativeLocation = WorldLocation - CurrentOriginD;
867 
868  float DistanceSquared = (RelativeLocation - HeroLocation).SizeSquared();
869 
870  if(DistanceSquared < ActorStreamingDistanceSquared && IsTileLoaded(WorldLocation))
871  {
872  DormantToActiveActors.Add(Id);
873  DormantsToRemove.Add(Id);
874  break;
875  }
876  }
877  }
878 }
879 
881 {
882  TRACE_CPUPROFILER_EVENT_SCOPE(ALargeMapManager::ConvertDormantToActiveActors);
883  UWorld* World = GetWorld();
884  UCarlaEpisode* CarlaEpisode = UCarlaStatics::GetCurrentEpisode(World);
885 
887  {
888  LM_LOG(Warning, "Converting %d Dormant To Active", Id);
889 
890  CarlaEpisode->WakeActorUp(Id);
891 
892  FCarlaActor* View = CarlaEpisode->FindCarlaActor(Id);
893 
894  if (View->IsActive()){
895  LM_LOG(Warning, "Spawning dormant at %s\n\tOrigin: %s\n\tRel. location: %s", \
896  *((CurrentOriginD + View->GetActor()->GetActorLocation()).ToString()), \
897  *(CurrentOriginD.ToString()), \
898  *((View->GetActor()->GetActorLocation()).ToString()) \
899  );
900  ActiveActors.Add(Id);
901  }
902  else
903  {
904  LM_LOG(Warning, "Actor %d could not be woken up, keeping sleep state", Id);
905  DormantActors.Add(Id);
906  }
907  }
908  DormantToActiveActors.Reset();
909 }
910 
912 {
913  TRACE_CPUPROFILER_EVENT_SCOPE(ALargeMapManager::CheckIfRebaseIsNeeded);
914  if(ActorsToConsider.Num() > 0)
915  {
916  UWorld* World = GetWorld();
917  UWorldComposition* WorldComposition = World->WorldComposition;
918  // TODO: consider multiple hero vehicles for rebasing
919  AActor* ActorToConsider = ActorsToConsider[0];
920  if( IsValid(ActorToConsider) )
921  {
922  FVector ActorLocation = ActorToConsider->GetActorLocation();
923  FIntVector ILocation = FIntVector(ActorLocation.X, ActorLocation.Y, ActorLocation.Z);
924  if (ActorLocation.SizeSquared() > FMath::Square(RebaseOriginDistance) )
925  {
926  TileID TileId = GetTileID(CurrentOriginD + ActorLocation);
927  FVector NewOrigin = GetTileLocation(TileId);
928  World->SetNewWorldOrigin(FIntVector(NewOrigin));
929  }
930  }
931  }
932 }
933 
934 void ALargeMapManager::GetTilesToConsider(const AActor* ActorToConsider,
935  TSet<TileID>& OutTilesToConsider)
936 {
937  TRACE_CPUPROFILER_EVENT_SCOPE(ALargeMapManager::GetTilesToConsider);
938  check(ActorToConsider);
939  // World location
940  FDVector ActorLocation = CurrentOriginD + ActorToConsider->GetActorLocation();
941 
942  // Calculate Current Tile
943  FIntVector CurrentTile = GetTileVectorID(ActorLocation);
944 
945  // Calculate tile bounds
946  FDVector UpperPos = ActorLocation + FDVector(LayerStreamingDistance,LayerStreamingDistance,0);
947  FDVector LowerPos = ActorLocation + FDVector(-LayerStreamingDistance,-LayerStreamingDistance,0);
948  FIntVector UpperTileId = GetTileVectorID(UpperPos);
949  FIntVector LowerTileId = GetTileVectorID(LowerPos);
950  for (int Y = UpperTileId.Y; Y <= LowerTileId.Y; Y++)
951  {
952  for (int X = LowerTileId.X; X <= UpperTileId.X; X++)
953  {
954  // I don't check the bounds of the Tile map, if the Tile does not exist
955  // I just simply discard it
956  FIntVector TileToCheck = FIntVector(X, Y, 0);
957 
958  TileID TileID = GetTileID(TileToCheck);
959  FCarlaMapTile* Tile = MapTiles.Find(TileID);
960  if (!Tile)
961  {
962  // LM_LOG(Warning, "Requested tile %d, %d but tile was not found", TileToCheck.X, TileToCheck.Y);
963  continue; // Tile does not exist, discard
964  }
965 
966  OutTilesToConsider.Add(TileID);
967  }
968  }
969 }
970 
972  const TSet<TileID>& InTilesToConsider,
973  TSet<TileID>& OutTilesToBeVisible,
974  TSet<TileID>& OutTilesToHidde)
975 {
976  TRACE_CPUPROFILER_EVENT_SCOPE(ALargeMapManager::GetTilesThatNeedToChangeState);
977  OutTilesToBeVisible = InTilesToConsider.Difference(CurrentTilesLoaded);
978  OutTilesToHidde = CurrentTilesLoaded.Difference(InTilesToConsider);
979 }
980 
982  const TSet<TileID>& InTilesToUpdate,
983  bool InShouldBlockOnLoad,
984  bool InShouldBeLoaded,
985  bool InShouldBeVisible)
986 {
987  TRACE_CPUPROFILER_EVENT_SCOPE(ALargeMapManager::UpdateTileState);
988  UWorld* World = GetWorld();
989  UWorldComposition* WorldComposition = World->WorldComposition;
990 
991  // Gather all the locations of the levels to load
992  for (const TileID TileID : InTilesToUpdate)
993  {
994  FCarlaMapTile* CarlaTile = MapTiles.Find(TileID);
995  check(CarlaTile); // If an invalid ID reach here, we did something very wrong
996  ULevelStreamingDynamic* StreamingLevel = CarlaTile->StreamingLevel;
997  StreamingLevel->bShouldBlockOnLoad = InShouldBlockOnLoad;
998  StreamingLevel->SetShouldBeLoaded(InShouldBeLoaded);
999  StreamingLevel->SetShouldBeVisible(InShouldBeVisible);
1000  }
1001 }
1002 
1004  const TSet<TileID>& InTilesToBeVisible,
1005  const TSet<TileID>& InTilesToHidde)
1006 {
1007  TRACE_CPUPROFILER_EVENT_SCOPE(ALargeMapManager::UpdateCurrentTilesLoaded);
1008  for (const TileID TileID : InTilesToHidde)
1009  {
1010  CurrentTilesLoaded.Remove(TileID);
1011  }
1012 
1013  for (const TileID TileID : InTilesToBeVisible)
1014  {
1016  }
1017 }
1018 
1020 {
1021  int32 X = (int32)(TileID >> 32);
1022  int32 Y = (int32)(TileID);
1023  return FString::Printf(TEXT("Tile_%d_%d"), X, Y);
1024 }
1025 
1027 {
1028  int32 X = (int32)(TileID >> 32);
1029  int32 Y = (int32)(TileID);
1030  return FString::Printf(TEXT("%d_%d"), X, Y);
1031 }
1032 
1034 {
1035  FString FileContent = "";
1036  FileContent += FString::Printf(TEXT("LargeMapManager state\n"));
1037 
1038  FileContent += FString::Printf(TEXT("Tile:\n"));
1039  FileContent += FString::Printf(TEXT("ID\tName\tLocation\n"));
1040  for (auto& It : MapTiles)
1041  {
1042  const FCarlaMapTile& Tile = It.Value;
1043  FileContent += FString::Printf(TEXT(" %ld\t%s\t%s\n"), It.Key, *Tile.Name, *Tile.Location.ToString());
1044  }
1045  FileContent += FString::Printf(TEXT("\nNum generated tiles: %d\n"), MapTiles.Num());
1046 
1047  // Generate the map name with the assets folder name
1048  TArray<FString> StringArray;
1049  AssetsPath.ParseIntoArray(StringArray, TEXT("/"), false);
1050 
1051  FString FilePath = FPaths::ProjectSavedDir() + StringArray[StringArray.Num() - 1] + ".txt";
1052  FFileHelper::SaveStringToFile(
1053  FileContent,
1054  *FilePath,
1055  FFileHelper::EEncodingOptions::AutoDetect,
1056  &IFileManager::Get(),
1057  EFileWrite::FILEWRITE_Silent);
1058 }
1059 
1061 {
1062  UWorld* World = GetWorld();
1063 
1064  FDVector CurrentActorPosition;
1065  if (ActorsToConsider.Num() > 0)
1066  CurrentActorPosition = CurrentOriginD + ActorsToConsider[0]->GetActorLocation();
1067 
1068  const TArray<FLevelCollection>& WorldLevelCollections = World->GetLevelCollections();
1069  const FLevelCollection* LevelCollection = World->GetActiveLevelCollection();
1070  const TArray<ULevel*>& Levels = World->GetLevels();
1071  const TArray<ULevelStreaming*>& StreamingLevels = World->GetStreamingLevels();
1072  ULevel* CurrentLevel = World->GetCurrentLevel();
1073 
1074  FString Output = "";
1075  Output += FString::Printf(TEXT("Num levels in world composition: %d\n"), World->WorldComposition->TilesStreaming.Num());
1076  Output += FString::Printf(TEXT("Num levels loaded: %d\n"), Levels.Num() );
1077  Output += FString::Printf(TEXT("Num tiles loaded: %d\n"), CurrentTilesLoaded.Num() );
1078  Output += FString::Printf(TEXT("Tiles loaded: [ "));
1079  for(TileID& TileId : CurrentTilesLoaded)
1080  {
1081  Output += FString::Printf(TEXT("%s, "), *TileIDToString(TileId));
1082  }
1083  Output += FString::Printf(TEXT("]\n"));
1084  GEngine->AddOnScreenDebugMessage(0, MsgTime, FColor::Cyan, Output);
1085 
1086  int LastMsgIndex = TilesDistMsgIndex;
1087  GEngine->AddOnScreenDebugMessage(LastMsgIndex++, MsgTime, FColor::White,
1088  FString::Printf(TEXT("\nActor Global Position: %s km"), *(FDVector(CurrentActorPosition) / (1000.0 * 100.0)).ToString()) );
1089 
1090  FIntVector CurrentTile = GetTileVectorID(CurrentActorPosition);
1091  GEngine->AddOnScreenDebugMessage(LastMsgIndex++, MsgTime, FColor::White,
1092  FString::Printf(TEXT("\nActor Current Tile: %d_%d"), CurrentTile.X, CurrentTile.Y ));
1093 
1094  LastMsgIndex = ClientLocMsgIndex;
1095  GEngine->AddOnScreenDebugMessage(LastMsgIndex++, MsgTime, FColor::White,
1096  FString::Printf(TEXT("\nOrigin: %s km"), *(FDVector(CurrentOriginInt) / (1000.0 * 100.0)).ToString()) );
1097  GEngine->AddOnScreenDebugMessage(LastMsgIndex++, MsgTime, FColor::White,
1098  FString::Printf(TEXT("Num active actors (%d)"), ActiveActors.Num()) );
1099  GEngine->AddOnScreenDebugMessage(LastMsgIndex++, MsgTime, FColor::White,
1100  FString::Printf(TEXT("Num dormant actors (%d)"), DormantActors.Num()));
1101  GEngine->AddOnScreenDebugMessage(LastMsgIndex++, MsgTime, FColor::White,
1102  FString::Printf(TEXT("Actors To Consider (%d)"), ActorsToConsider.Num()));
1103  for (const AActor* Actor : ActorsToConsider)
1104  {
1105  if (IsValid(Actor))
1106  {
1107  Output = "";
1108  float ToKm = 1000.0f * 100.0f;
1109  FVector TileActorLocation = Actor->GetActorLocation();
1110  FDVector ClientActorLocation = CurrentOriginD + FDVector(TileActorLocation);
1111 
1112  Output += FString::Printf(TEXT("Local Loc: %s meters\n"), *(TileActorLocation / ToKm).ToString());
1113  Output += FString::Printf(TEXT("Client Loc: %s km\n"), *(ClientActorLocation / ToKm).ToString());
1114  Output += "---------------";
1115  GEngine->AddOnScreenDebugMessage(LastMsgIndex++, MsgTime, PositonMsgColor, Output);
1116 
1117  if (LastMsgIndex > MaxClientLocMsgIndex) break;
1118  }
1119  }
1120 }
1121 
1123 {
1124  SpectatorAsEgo = _SpectatorAsEgo;
1125  if(SpectatorAsEgo && ActorsToConsider.Num() == 0 && Spectator)
1126  {
1127  // Activating the spectator in an empty world
1129  }
1130  if (!SpectatorAsEgo && ActorsToConsider.Num() == 1 && ActorsToConsider.Contains(Spectator))
1131  {
1132  // Deactivating the spectator in a world with no other egos
1133  ActorsToConsider.Reset();
1134  }
1135 }
FCarlaActor * FindCarlaActor(FCarlaActor::IdType ActorId)
Find a Carla actor by id.
Definition: CarlaEpisode.h:173
TileID GetTileID(FVector TileLocation) const
From a given location it retrieves the TileID that covers that area.
double Y
Definition: DVector.h:14
TSet< uint64 > CurrentTilesLoaded
FString GenerateTileName(TileID TileID)
void UpdateCurrentTilesLoaded(const TSet< TileID > &InTilesToBeVisible, const TSet< TileID > &InTilesToHidde)
A registry of all the Carla actors.
Definition: ActorRegistry.h:20
void GenerateMap(FString InAssetsPath)
TSet< FCarlaActor::IdType > DormantsToRemove
TSet< FCarlaActor::IdType > DormantToActiveActors
void ConvertActiveToDormantActors()
FIntVector GetNumTilesInXY() const
FString ToString() const
Definition: DVector.h:52
void ConsiderSpectatorAsEgo(bool _SpectatorAsEgo)
AActor * GetActor()
Definition: CarlaActor.h:90
FVector GlobalToLocalLocation(const FVector &InLocation) const
void ConvertDormantToActiveActors()
float LayerStreamingDistanceSquared
ACarlaWheeledVehicle * GetHeroVehicle()
void WakeActorUp(carla::rpc::ActorId ActorId)
Definition: CarlaEpisode.h:285
std::vector< cg::Location > Path
void RegisterTilesInWorldComposition()
TSet< FCarlaActor::IdType > ActiveToDormantActors
const int32 TilesDistMsgIndex
FCarlaMapTile & LoadCarlaMapTile(FString TileMapPath, TileID TileId)
FString TileIDToString(TileID TileID)
uint32 IdType
Definition: CarlaActor.h:27
bool IsLevelOfTileLoaded(FIntVector InTileID) const
static bool IsValid(const ACarlaWheeledVehicle *Vehicle)
void PutActorToSleep(carla::rpc::ActorId ActorId)
Definition: CarlaEpisode.h:280
void OnActorSpawned(const FCarlaActor &CarlaActor)
FIntVector CurrentOriginInt
static T Get(carla::rpc::Response< T > &response)
void UpdateTileState(const TSet< TileID > &InTilesToUpdate, bool InShouldBlockOnLoad, bool InShouldBeLoaded, bool InShouldBeVisible)
virtual void BeginPlay() override
uint64_t num_ticks
float ActorStreamingDistanceSquared
FVector ToFVector() const
Definition: DVector.h:47
geom::Location Location
Definition: rpc/Location.h:14
static void TagActorsInLevel(UWorld &World, bool bTagForSemanticSegmentation)
Set the tag of every actor in level.
Definition: Tagger.cpp:222
const FActorRegistry & GetActorRegistry() const
Definition: CarlaEpisode.h:155
TMap< FString, FActorAttribute > Variations
User selected variations of the actor.
FActorData * GetActorData()
Definition: CarlaActor.h:156
carla::SharedPtr< cc::Actor > Actor
A simulation episode.
Definition: CarlaEpisode.h:38
void GetTilesThatNeedToChangeState(const TSet< TileID > &InTilesToConsider, TSet< TileID > &OutTilesToBeVisible, TSet< TileID > &OutTilesToHidde)
float tick_execution_time
const int32 ClientLocMsgIndex
void SetActorStreamingDistance(float Distance)
void PreWorldOriginOffset(UWorld *InWorld, FIntVector InSrcOrigin, FIntVector InDstOrigin)
bool IsActive() const
Definition: CarlaActor.h:65
void SetTileSize(float Size)
void DumpTilesTable() const
A description of a Carla Actor with all its variation.
FActorDescription Description
Definition: ActorInfo.h:26
const FActorInfo * GetActorInfo() const
Definition: CarlaActor.h:100
TMap< uint64, FCarlaMapTile > MapTiles
void SetLayerStreamingDistance(float Distance)
void SetCurrentMapOrigin(const FIntVector &NewOrigin)
Definition: CarlaEpisode.h:324
void GetTilesToConsider(const AActor *ActorToConsider, TSet< TileID > &OutTilesToConsider)
FDVector GetTileLocationD(TileID TileID) const
FTransform LocalToGlobalTransform(const FTransform &InTransform) const
TArray< AActor * > ActorsToConsider
void AddActorToUnloadedList(const FCarlaActor &CarlaActor, const FTransform &Transform)
#define LM_LOG(Level, Msg,...)
float GetActorStreamingDistance() const
float GetLayerStreamingDistance() const
FTransform GlobalToLocalTransform(const FTransform &InTransform) const
void PostWorldOriginOffset(UWorld *InWorld, FIntVector InSrcOrigin, FIntVector InDstOrigin)
static UCarlaEpisode * GetCurrentEpisode(const UObject *WorldContextObject)
Definition: CarlaStatics.h:68
void OnLevelRemovedFromWorld(ULevel *InLevel, UWorld *InWorld)
FCarlaMapTile * GetCarlaMapTile(FVector Location)
A view over an actor and its properties.
Definition: ActorInfo.h:22
bool IsDormant() const
Definition: CarlaActor.h:70
TSet< FCarlaActor::IdType > ActivesToRemove
TSet< AActor * > ActorsToRemove
const int32 MaxClientLocMsgIndex
IdType GetActorId() const
Definition: CarlaActor.h:80
ULevelStreamingDynamic * StreamingLevel
void RemovePendingActorsToRemove()
void SetTile0Offset(const FVector &Offset)
TArray< FCarlaActor::IdType > ActiveActors
Base class for CARLA wheeled vehicles.
void OnActorDestroyed(AActor *DestroyedActor)
An actor attribute, may be an intrinsic (non-modifiable) attribute of the actor or an user-defined ac...
void Tick(float DeltaTime) override
float RebaseOriginDistanceSquared
FVector GetTileLocation(TileID TileID) const
geom::Transform Transform
Definition: rpc/Transform.h:16
FVector LocalToGlobalLocation(const FVector &InLocation) const
bool IsTileLoaded(TileID TileId) const
ActorType GetActorType() const
Definition: CarlaActor.h:85
FIntVector GetTileVectorID(FVector TileLocation) const
A view over an actor and its properties.
Definition: CarlaActor.h:23
TArray< FCarlaActor::IdType > DormantActors
void OnLevelAddedToWorld(ULevel *InLevel, UWorld *InWorld)
FDVector Location
Definition: ActorData.h:32