CARLA
 
载入中...
搜索中...
未找到
LargeMapManager.cpp
浏览该文件的文档.
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
98void ALargeMapManager::PreWorldOriginOffset(UWorld* InWorld, FIntVector InSrcOrigin, FIntVector InDstOrigin)
99{
100 LM_LOG(Log, "PreWorldOriginOffset Src: %s -> Dst: %s", *InSrcOrigin.ToString(), *InDstOrigin.ToString());
101}
102
103void 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);
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
137void 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
146void 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
272void 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
298
305
310
315
316FTransform ALargeMapManager::GlobalToLocalTransform(const FTransform& InTransform) const
317{
318 return FTransform(
319 InTransform.GetRotation(),
320 InTransform.GetLocation() - CurrentOriginD.ToFVector(),
321 InTransform.GetScale3D());
322}
323
324FVector ALargeMapManager::GlobalToLocalLocation(const FVector& InLocation) const
325{
326 return InLocation - CurrentOriginD.ToFVector();
327}
328
329FTransform ALargeMapManager::LocalToGlobalTransform(const FTransform& InTransform) const
330{
331 return FTransform(
332 InTransform.GetRotation(),
333 CurrentOriginD.ToFVector() + InTransform.GetLocation(),
334 InTransform.GetScale3D());
335}
336
337FVector ALargeMapManager::LocalToGlobalLocation(const FVector& InLocation) const
338{
339 return CurrentOriginD.ToFVector() + InLocation;
340}
341
343uint64_t num_ticks = 0;
344void 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
376
377void 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();
435 {
437 }
438
439#if WITH_EDITOR
440 LM_LOG(Warning, "GenerateMap num Tiles generated %d", MapTiles.Num());
442#endif // WITH_EDITOR
443}
444
445void 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
486void 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
509bool 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
528FIntVector 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
538FIntVector 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
563FVector 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
575FDVector 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
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
861 for(AActor* Actor : ActorsToConsider)
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()), \
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
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
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}
float tick_execution_time
#define LM_LOG(...)
uint64_t num_ticks
static bool IsValid(const ACarlaWheeledVehicle *Vehicle)
Base class for CARLA wheeled vehicles.
void ConvertDormantToActiveActors()
FCarlaMapTile & LoadCarlaMapTile(FString TileMapPath, TileID TileId)
virtual void BeginPlay() override
FString TileIDToString(TileID TileID)
void UpdateCurrentTilesLoaded(const TSet< TileID > &InTilesToBeVisible, const TSet< TileID > &InTilesToHidde)
TSet< FCarlaActor::IdType > DormantToActiveActors
FTransform GlobalToLocalTransform(const FTransform &InTransform) const
float RebaseOriginDistanceSquared
float ActorStreamingDistanceSquared
ACarlaWheeledVehicle * GetHeroVehicle()
void PreWorldOriginOffset(UWorld *InWorld, FIntVector InSrcOrigin, FIntVector InDstOrigin)
void GetTilesToConsider(const AActor *ActorToConsider, TSet< TileID > &OutTilesToConsider)
void ConvertActiveToDormantActors()
float GetLayerStreamingDistance() const
void ConsiderSpectatorAsEgo(bool _SpectatorAsEgo)
void SetActorStreamingDistance(float Distance)
TSet< FCarlaActor::IdType > ActiveToDormantActors
FIntVector GetNumTilesInXY() const
void DumpTilesTable() const
FIntVector CurrentOriginInt
void OnActorSpawned(const FCarlaActor &CarlaActor)
FString GenerateTileName(TileID TileID)
FIntVector GetTileVectorID(FVector TileLocation) const
FVector GlobalToLocalLocation(const FVector &InLocation) const
void OnActorDestroyed(AActor *DestroyedActor)
TSet< AActor * > ActorsToRemove
const int32 ClientLocMsgIndex
FTransform LocalToGlobalTransform(const FTransform &InTransform) const
TSet< uint64 > CurrentTilesLoaded
TileID GetTileID(FVector TileLocation) const
From a given location it retrieves the TileID that covers that area
FCarlaMapTile * GetCarlaMapTile(FVector Location)
TArray< FCarlaActor::IdType > ActiveActors
bool IsTileLoaded(TileID TileId) const
void GetTilesThatNeedToChangeState(const TSet< TileID > &InTilesToConsider, TSet< TileID > &OutTilesToBeVisible, TSet< TileID > &OutTilesToHidde)
void OnLevelRemovedFromWorld(ULevel *InLevel, UWorld *InWorld)
FDVector GetTileLocationD(TileID TileID) const
void SetTile0Offset(const FVector &Offset)
void Tick(float DeltaTime) override
void RegisterTilesInWorldComposition()
void SetLayerStreamingDistance(float Distance)
const int32 MaxClientLocMsgIndex
float LayerStreamingDistanceSquared
FVector GetTileLocation(TileID TileID) const
void PostWorldOriginOffset(UWorld *InWorld, FIntVector InSrcOrigin, FIntVector InDstOrigin)
float GetActorStreamingDistance() const
TSet< FCarlaActor::IdType > DormantsToRemove
TArray< AActor * > ActorsToConsider
bool IsLevelOfTileLoaded(FIntVector InTileID) const
void SetTileSize(float Size)
void UpdateTileState(const TSet< TileID > &InTilesToUpdate, bool InShouldBlockOnLoad, bool InShouldBeLoaded, bool InShouldBeVisible)
void GenerateMap(FString InAssetsPath)
TArray< FCarlaActor::IdType > DormantActors
TSet< FCarlaActor::IdType > ActivesToRemove
FVector LocalToGlobalLocation(const FVector &InLocation) const
void OnLevelAddedToWorld(ULevel *InLevel, UWorld *InWorld)
const int32 TilesDistMsgIndex
void AddActorToUnloadedList(const FCarlaActor &CarlaActor, const FTransform &Transform)
TMap< uint64, FCarlaMapTile > MapTiles
static void TagActorsInLevel(UWorld &World, bool bTagForSemanticSegmentation)
Set the tag of every actor in level.
Definition Tagger.cpp:223
FDVector Location
Definition ActorData.h:32
A registry of all the Carla actors.
A view over an actor and its properties.
Definition CarlaActor.h:25
ActorType GetActorType() const
Definition CarlaActor.h:86
bool IsDormant() const
Definition CarlaActor.h:71
AActor * GetActor()
Definition CarlaActor.h:91
uint32 IdType
Definition CarlaActor.h:28
FActorData * GetActorData()
Definition CarlaActor.h:157
bool IsActive() const
Definition CarlaActor.h:66
const FActorInfo * GetActorInfo() const
Definition CarlaActor.h:101
IdType GetActorId() const
Definition CarlaActor.h:81
A simulation episode.
void PutActorToSleep(carla::rpc::ActorId ActorId)
void SetCurrentMapOrigin(const FIntVector &NewOrigin)
FCarlaActor * FindCarlaActor(FCarlaActor::IdType ActorId)
Find a Carla actor by id.
const FActorRegistry & GetActorRegistry() const
void WakeActorUp(carla::rpc::ActorId ActorId)
static UCarlaEpisode * GetCurrentEpisode(const UObject *WorldContextObject)
An actor attribute, may be an intrinsic (non-modifiable) attribute of the actor or an user-defined ac...
A description of a Carla Actor with all its variation.
TMap< FString, FActorAttribute > Variations
User selected variations of the actor.
A view over an actor and its properties.
Definition ActorInfo.h:23
FActorDescription Description
Definition ActorInfo.h:26
ULevelStreamingDynamic * StreamingLevel
FString ToString() const
Definition DVector.h:52
FVector ToFVector() const
Definition DVector.h:47