Merge branch 'dev' into xisco

This commit is contained in:
Xisco Bosch 2017-05-24 14:06:32 +02:00
commit e4d55e3464
22 changed files with 361 additions and 83 deletions

View File

@ -1,3 +1,16 @@
## CARLA 0.3.0
* Added basic dynamic weather functionality.
- Weather and sun light can be changed during game.
- Presets stored in config file CarlaWeather.ini.
* Add basic functionality to spawn pedestrians.
* Split road meshes for intersections and turns for better precission of the road map.
* Better debug for road map.
* Implemented collision count for other cars and pedestrians.
* Command line argument -carla-settings now accepts relative paths.
* Improved performance when semantic segmentation is disabled.
* Improved tagger system.
## CARLA 0.2.4
* Fixed serialization of road map resulting in a huge map size.

View File

@ -1,7 +1,7 @@
{
"FileVersion": 3,
"Version": 1,
"VersionName": "0.2.4",
"VersionName": "0.3.0",
"FriendlyName": "CARLA",
"Description": "",
"Category": "Science",

View File

@ -14,6 +14,14 @@ WorldPort=2000
WritePort=2001
ReadPort=2002
[CARLA/LevelSettings]
; Number of NPC vehicles to be spawned into the level.
NumberOfVehicles=5
; Number of NPC pedestrians to be spawned into the level.
NumberOfPedestrians=15
; Index of the weather presets to use. If negative, weather won't be changed.
WeatherId=-1
[CARLA/SceneCapture]
; Names of the scene capture cameras to attach to the player, each of them
; should be defined in its own subsection.

View File

@ -20,3 +20,32 @@ following
[/Script/Engine.RendererSettings]
r.CustomDepth=3
```
Weather presets
---------------
To change the weather and sun light, set `WeatherId` in CarlaSettings.ini
from the following
* 0 - Default
* 1 - ClearNoon
* 2 - CloudyNoon
* 3 - WetNoon
* 4 - WetCloudyNoon
* 5 - MidRainyNoon
* 6 - HardRainNoon
* 7 - SoftRainNoon
* 8 - ClearSunset
* 9 - CloudySunset
* 10 - WetSunset
* 11 - WetCloudySunset
* 12 - MidRainSunset
* 13 - HardRainSunset
* 14 - SoftRainSunset
E.g., to choose the weather to be hard-rain at noon, add to CarlaSettings.ini
```
[CARLA/LevelSettings]
WeatherId=6
```

View File

@ -5,9 +5,25 @@
#include "Engine/TargetPoint.h"
#include "WalkerSpawnPoint.generated.h"
/// Used to set spawner locations for walkers in the level.
UCLASS()
class CARLA_API AWalkerSpawnPoint : public ATargetPoint
/// Base class for spawner locations for walkers.
UCLASS(Abstract)
class CARLA_API AWalkerSpawnPointBase : public ATargetPoint
{
GENERATED_BODY()
};
/// Used to set spawner locations for walkers in the level. These positions will
/// be used solely to spawn walkers at begin play.
UCLASS()
class CARLA_API AWalkerStartSpawnPoint : public AWalkerSpawnPointBase
{
GENERATED_BODY()
};
/// Used to set spawner locations for walkers in the level. These positions will
/// be used as spawn points as well as destination points for walkers.
UCLASS()
class CARLA_API AWalkerSpawnPoint : public AWalkerSpawnPointBase
{
GENERATED_BODY()
};

View File

@ -14,9 +14,24 @@
// -- Static local methods -----------------------------------------------------
// =============================================================================
static bool WalkerIsValid(ACharacter *Walker)
{
return ((Walker != nullptr) && !Walker->IsPendingKill());
}
static AWalkerAIController *GetController(ACharacter *Walker)
{
return (Walker != nullptr ? Cast<AWalkerAIController>(Walker->GetController()) : nullptr);
return (WalkerIsValid(Walker) ? Cast<AWalkerAIController>(Walker->GetController()) : nullptr);
}
static float GetDistance(const FVector &Location0, const FVector &Location1)
{
return FMath::Abs((Location0 - Location1).Size());
}
static float GetDistance(const AActor &Actor0, const AActor &Actor1)
{
return GetDistance(Actor0.GetActorLocation(), Actor1.GetActorLocation());
}
// =============================================================================
@ -39,6 +54,8 @@ void AWalkerSpawnerBase::BeginPlay()
{
Super::BeginPlay();
NumberOfWalkers = FMath::Max(0, NumberOfWalkers);
// Allocate space for walkers.
Walkers.Reserve(NumberOfWalkers);
@ -50,14 +67,32 @@ void AWalkerSpawnerBase::BeginPlay()
}
// Find spawn points present in level.
for (TActorIterator<AWalkerSpawnPoint> It(GetWorld()); It; ++It) {
SpawnPoints.Add(*It);
TArray<AWalkerSpawnPointBase *> BeginSpawnPoints;
for (TActorIterator<AWalkerSpawnPointBase> It(GetWorld()); It; ++It) {
BeginSpawnPoints.Add(*It);
AWalkerSpawnPoint *SpawnPoint = Cast<AWalkerSpawnPoint>(*It);
if (SpawnPoint != nullptr) {
SpawnPoints.Add(SpawnPoint);
}
}
UE_LOG(LogCarla, Log, TEXT("Found %d positions for spawning walkers"), SpawnPoints.Num());
UE_LOG(LogCarla, Log, TEXT("Found %d positions for spawning walkers at begin play."), BeginSpawnPoints.Num());
UE_LOG(LogCarla, Log, TEXT("Found %d positions for spawning walkers during game play."), SpawnPoints.Num());
if (SpawnPoints.Num() < 2) {
bSpawnWalkers = false;
UE_LOG(LogCarla, Error, TEXT("We don't have enough spawn points for walkers!"));
} else if (BeginSpawnPoints.Num() < NumberOfWalkers) {
UE_LOG(LogCarla, Warning, TEXT("Requested %d walkers, but we only have %d spawn points. Some will fail to spawn."), NumberOfWalkers, BeginSpawnPoints.Num());
}
if (bSpawnWalkers) {
uint32 Count = 0u;
for (auto i = 0; i < NumberOfWalkers; ++i) {
if (TryToSpawnWalkerAt(*BeginSpawnPoints[i % BeginSpawnPoints.Num()])) {
++Count;
}
}
UE_LOG(LogCarla, Log, TEXT("Spawned %d walkers at begin play."), Count);
}
}
@ -65,21 +100,39 @@ void AWalkerSpawnerBase::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
if (bSpawnWalkers && (NumberOfWalkers > Walkers.Num())) {
if (bSpawnWalkers && (NumberOfWalkers > GetCurrentNumberOfWalkers())) {
// Try to spawn one walker.
TryToSpawnRandomWalker();
TryToSpawnWalkerAt(GetRandomSpawnPoint());
}
if (WalkersBlackList.Num() > 0) {
// If still stuck in the black list, just kill it.
const int32 Index = (++CurrentIndexToCheck % WalkersBlackList.Num());
auto Walker = WalkersBlackList[Index];
auto Controller = GetController(Walker);
if ((Controller == nullptr) ||
(Controller->GetMoveStatus() != EPathFollowingStatus::Moving)) {
WalkersBlackList.RemoveAtSwap(Index);
if (Walker != nullptr) {
Walker->Destroy();
}
}
}
if (Walkers.Num() > 0) {
// Check one walker and kill it if necessary.
// Check one walker, if fails black-list it or kill it.
const int32 Index = (++CurrentIndexToCheck % Walkers.Num());
auto Walker = Walkers[Index];
auto Controller = GetController(Walker);
if ((Controller == nullptr) || (Controller->GetMoveStatus() != EPathFollowingStatus::Moving)) {
if (Controller == nullptr) {
Walkers.RemoveAtSwap(Index);
if (Walker != nullptr) {
Walker->Destroy();
}
} else if (Controller->GetMoveStatus() != EPathFollowingStatus::Moving) {
TrySetDestination(*Walker);
WalkersBlackList.Add(Walker);
Walkers.RemoveAtSwap(Index);
}
}
}
@ -98,45 +151,64 @@ void AWalkerSpawnerBase::SetNumberOfWalkers(const int32 Count)
}
}
void AWalkerSpawnerBase::TryToSpawnRandomWalker()
const AWalkerSpawnPointBase &AWalkerSpawnerBase::GetRandomSpawnPoint() const
{
auto SpawnPoint = GetRandomSpawnPoint();
auto DestinationPoint = GetRandomSpawnPoint();
if ((SpawnPoint != nullptr) && (DestinationPoint != nullptr)) {
const auto StraightDistance =
DestinationPoint->GetActorLocation() -
SpawnPoint->GetActorLocation();
if (StraightDistance.Size() >= MinimumWalkDistance) {
SpawnWalkerAtSpawnPoint(*SpawnPoint, DestinationPoint->GetActorLocation());
}
} else {
UE_LOG(LogCarla, Error, TEXT("Unable to find spawn point"));
}
check(SpawnPoints.Num() > 0);
return *SpawnPoints[RandomStream.RandRange(0, SpawnPoints.Num() - 1)];
}
void AWalkerSpawnerBase::SpawnWalkerAtSpawnPoint(
const AWalkerSpawnPoint &SpawnPoint,
const FVector &Destination)
bool AWalkerSpawnerBase::TryGetValidDestination(const FVector &Origin, FVector &Destination) const
{
const auto &DestinationPoint = GetRandomSpawnPoint();
Destination = DestinationPoint.GetActorLocation();
return (GetDistance(Origin, Destination) >= MinimumWalkDistance);
}
bool AWalkerSpawnerBase::TryToSpawnWalkerAt(const AWalkerSpawnPointBase &SpawnPoint)
{
// Try find destination.
FVector Destination;
if (!TryGetValidDestination(SpawnPoint.GetActorLocation(), Destination)) {
return false;
}
// Spawn walker.
ACharacter *Walker;
SpawnWalker(SpawnPoint.GetActorTransform(), Walker);
if ((Walker != nullptr) && !Walker->IsPendingKill()) {
Walker->AIControllerClass = AWalkerAIController::StaticClass();
Walker->SpawnDefaultController();
auto Controller = GetController(Walker);
if (Controller != nullptr) { // Sometimes fails...
Controller->MoveToLocation(Destination);
Walkers.Add(Walker);
} else {
UE_LOG(LogCarla, Error, TEXT("Something went wrong creating the controller for the new walker"));
Walker->Destroy();
}
if (!WalkerIsValid(Walker)) {
return false;
}
// Assign controller.
Walker->AIControllerClass = AWalkerAIController::StaticClass();
Walker->SpawnDefaultController();
auto Controller = GetController(Walker);
if (Controller == nullptr) { // Sometimes fails...
UE_LOG(LogCarla, Error, TEXT("Something went wrong creating the controller for the new walker"));
Walker->Destroy();
return false;
}
// Add walker and set destination.
Walkers.Add(Walker);
Controller->MoveToLocation(Destination);
return true;
}
AWalkerSpawnPoint *AWalkerSpawnerBase::GetRandomSpawnPoint() const
bool AWalkerSpawnerBase::TrySetDestination(ACharacter &Walker) const
{
return (SpawnPoints.Num() > 0 ?
SpawnPoints[RandomStream.RandRange(0, SpawnPoints.Num() - 1)] :
nullptr);
// Try to retrieve controller.
auto Controller = GetController(&Walker);
if (Controller == nullptr) {
return false;
}
// Try find destination.
FVector Destination;
if (!TryGetValidDestination(Walker.GetActorLocation(), Destination)) {
return false;
}
Controller->MoveToLocation(Destination);
return true;
}

View File

@ -6,6 +6,7 @@
#include "WalkerSpawnerBase.generated.h"
class AWalkerSpawnPoint;
class AWalkerSpawnPointBase;
class UBoxComponent;
/// Base class for spawning walkers. Implement SpawnWalker in derived
@ -64,13 +65,20 @@ public:
void SetNumberOfWalkers(int32 Count);
int32 GetCurrentNumberOfWalkers() const
{
return Walkers.Num() + WalkersBlackList.Num();
}
private:
void TryToSpawnRandomWalker();
const AWalkerSpawnPointBase &GetRandomSpawnPoint() const;
void SpawnWalkerAtSpawnPoint(const AWalkerSpawnPoint &SpawnPoint, const FVector &Destination);
bool TryGetValidDestination(const FVector &Origin, FVector &Destination) const;
AWalkerSpawnPoint *GetRandomSpawnPoint() const;
bool TryToSpawnWalkerAt(const AWalkerSpawnPointBase &SpawnPoint);
bool TrySetDestination(ACharacter &Walker) const;
/// @}
@ -105,5 +113,8 @@ private:
UPROPERTY(Category = "Walker Spawner", VisibleAnywhere, AdvancedDisplay)
TArray<ACharacter *> Walkers;
UPROPERTY(Category = "Walker Spawner", VisibleAnywhere, AdvancedDisplay)
TArray<ACharacter *> WalkersBlackList;
uint32 CurrentIndexToCheck = 0u;
};

View File

@ -12,7 +12,7 @@ DECLARE_LOG_CATEGORY_EXTERN(LogCarla, Log, All);
DECLARE_LOG_CATEGORY_EXTERN(LogCarlaServer, Log, All);
// Options to compile with extra debug options.
#ifdef WITH_EDITOR
#if WITH_EDITOR
// #define CARLA_ROAD_GENERATOR_EXTRA_LOG /// @todo #1 Crashes in Linux.
// #define CARLA_SERVER_EXTRA_LOG
// #define CARLA_TAGGER_EXTRA_LOG

View File

@ -276,7 +276,7 @@ void ACityMapGenerator::GenerateRoadMap()
}
}
#ifdef WITH_EDITOR
#if WITH_EDITOR
RoadMap->Log();
#endif // WITH_EDITOR
@ -286,7 +286,7 @@ void ACityMapGenerator::GenerateRoadMap()
RoadMap->SaveAsPNG(FilePath);
}
#ifdef WITH_EDITOR
#if WITH_EDITOR
RoadMap->DrawDebugPixelsToLevel(GetWorld(), !bDrawDebugPixelsToLevel);
#endif // WITH_EDITOR
}

View File

@ -71,7 +71,17 @@ ADynamicWeather::ADynamicWeather(const FObjectInitializer& ObjectInitializer)
void ADynamicWeather::OnConstruction(const FTransform &Transform)
{
Super::OnConstruction(Transform);
#if WITH_EDITOR
Update();
#endif // WITH_EDITOR
}
void ADynamicWeather::BeginPlay()
{
Super::BeginPlay();
#if WITH_EDITOR
Update();
#endif // WITH_EDITOR
}
#if WITH_EDITOR
@ -82,6 +92,9 @@ void ADynamicWeather::PostEditChangeProperty(FPropertyChangedEvent &Event)
const FName PropertyName = (Event.Property != NULL ? Event.Property->GetFName() : NAME_None);
if (PropertyName == GET_MEMBER_NAME_CHECKED(ADynamicWeather, Weather)) {
Update();
} else if ((PropertyName == GET_MEMBER_NAME_CHECKED(ADynamicWeather, bSaveToConfigFile)) ||
(PropertyName == GET_MEMBER_NAME_CHECKED(ADynamicWeather, bLoadFromConfigFile))) {
// Do nothing.
} else {
AdjustSunPositionBasedOnActorRotation();
}
@ -97,6 +110,7 @@ void ADynamicWeather::PostEditChangeProperty(FPropertyChangedEvent &Event)
bLoadFromConfigFile = false;
if (LoadFromConfigFile()) {
UE_LOG(LogCarla, Log, TEXT("Weather \"%s\" loaded from config file"), *Weather.Name);
Update();
} else {
UE_LOG(LogCarla, Error, TEXT("Error loading weather from config file"));
}
@ -123,16 +137,6 @@ FVector ADynamicWeather::GetSunDirection() const
return - SphericalCoords.SphericalToUnitCartesian();
}
void ADynamicWeather::Update()
{
// Modify this actor's rotation according to Sun position.
if (!SetActorRotation(FQuat(GetSunDirection().Rotation()), ETeleportType::None)) {
UE_LOG(LogCarla, Warning, TEXT("Unable to rotate actor"));
}
RefreshWeather();
}
void ADynamicWeather::AdjustSunPositionBasedOnActorRotation()
{
const FVector Direction = - GetActorQuat().GetForwardVector();
@ -143,6 +147,18 @@ void ADynamicWeather::AdjustSunPositionBasedOnActorRotation()
#if WITH_EDITOR
void ADynamicWeather::Update()
{
// Modify this actor's rotation according to Sun position.
if (!SetActorRotation(FQuat(GetSunDirection().Rotation()), ETeleportType::None)) {
UE_LOG(LogCarla, Warning, TEXT("Unable to rotate actor"));
}
if (bRefreshAutomatically) {
RefreshWeather();
}
}
bool ADynamicWeather::LoadFromConfigFile()
{
FString FileName;

View File

@ -22,6 +22,8 @@ public:
virtual void OnConstruction(const FTransform &Transform) override;
virtual void BeginPlay() override;
#if WITH_EDITOR
virtual void PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent) override;
@ -49,12 +51,12 @@ public:
private:
void Update();
void AdjustSunPositionBasedOnActorRotation();
#if WITH_EDITOR
void Update();
bool LoadFromConfigFile();
bool SaveToConfigFile() const;
@ -66,9 +68,17 @@ private:
UPROPERTY()
UArrowComponent *ArrowComponent;
/** If true, the weather is refreshed on construction and at begin play.
* Useful for editing the weather (Editor only).
*/
UPROPERTY(Category = "Weather Description", EditAnywhere)
bool bRefreshAutomatically = false;
/** Load the section with the currently set name. */
UPROPERTY(Category = "Weather Description", EditAnywhere)
bool bLoadFromConfigFile = false;
/** Save current settings to disk. */
UPROPERTY(Category = "Weather Description", EditAnywhere)
bool bSaveToConfigFile = false;

View File

@ -16,7 +16,8 @@ UCarlaGameInstance::UCarlaGameInstance() {
UCarlaGameInstance::~UCarlaGameInstance() {}
void UCarlaGameInstance::InitializeGameControllerIfNotPresent()
void UCarlaGameInstance::InitializeGameControllerIfNotPresent(
const FMockGameControllerSettings &MockControllerSettings)
{
if (GameController == nullptr) {
if (CarlaSettings->bUseNetworking) {
@ -25,8 +26,8 @@ void UCarlaGameInstance::InitializeGameControllerIfNotPresent()
CarlaSettings->WritePort,
CarlaSettings->ReadPort);
} else {
GameController = MakeUnique<MockGameController>();
UE_LOG(LogCarla, Warning, TEXT("Using mock CARLA controller"));
GameController = MakeUnique<MockGameController>(MockControllerSettings);
UE_LOG(LogCarla, Log, TEXT("Using mock CARLA controller"));
}
}
}

View File

@ -7,6 +7,7 @@
#include "CarlaGameInstance.generated.h"
class UCarlaSettings;
struct FMockGameControllerSettings;
/// The game instance contains elements that must be kept alive in between
/// levels. It is instantiate once per game.
@ -21,7 +22,8 @@ public:
~UCarlaGameInstance();
void InitializeGameControllerIfNotPresent();
void InitializeGameControllerIfNotPresent(
const FMockGameControllerSettings &MockControllerSettings);
CarlaGameControllerBase &GetGameController()
{

View File

@ -23,6 +23,7 @@ ACarlaGameModeBase::ACarlaGameModeBase(const FObjectInitializer& ObjectInitializ
{
PrimaryActorTick.bCanEverTick = true;
PrimaryActorTick.TickGroup = TG_PrePhysics;
bAllowTickBeforeBeginPlay = false;
PlayerControllerClass = ACarlaVehicleController::StaticClass();
GameStateClass = ACarlaGameState::StaticClass();
@ -43,7 +44,7 @@ void ACarlaGameModeBase::InitGame(
checkf(
GameInstance != nullptr,
TEXT("GameInstance is not a UCarlaGameInstance, did you forget to set it in the project settings?"));
GameInstance->InitializeGameControllerIfNotPresent();
GameInstance->InitializeGameControllerIfNotPresent(MockGameControllerSettings);
GameController = &GameInstance->GetGameController();
GameController->Initialize(GameInstance->GetCarlaSettings());
GameInstance->GetCarlaSettings().LogSettings();
@ -98,14 +99,21 @@ void ACarlaGameModeBase::BeginPlay()
// Change weather.
if (DynamicWeather != nullptr) {
const auto &Weather = CarlaSettings.GetActiveWeatherDescription();
UE_LOG(LogCarla, Log, TEXT("Changing weather settings to \"%s\""), *Weather.Name);
DynamicWeather->SetWeatherDescription(Weather);
const auto *Weather = CarlaSettings.GetActiveWeatherDescription();
if (Weather != nullptr) {
UE_LOG(LogCarla, Log, TEXT("Changing weather settings to \"%s\""), *Weather->Name);
DynamicWeather->SetWeatherDescription(*Weather);
DynamicWeather->RefreshWeather();
}
} else {
UE_LOG(LogCarla, Error, TEXT("Missing dynamic weather actor!"));
}
// Setup walkers.
if (WalkerSpawner != nullptr) {
WalkerSpawner->SetNumberOfWalkers(CarlaSettings.NumberOfPedestrians);
} else {
UE_LOG(LogCarla, Error, TEXT("Missing walker spawner actor!"));
}
GameController->BeginPlay();
@ -164,7 +172,7 @@ APlayerStart *ACarlaGameModeBase::FindUnOccupiedStartPoints(
if (!GetWorld()->EncroachingBlockingGeometry(PawnToFit, ActorLocation, ActorRotation)) {
UnOccupiedStartPoints.Add(PlayerStart);
}
#ifdef WITH_EDITOR
#if WITH_EDITOR
else if (GetWorld()->FindTeleportSpot(PawnToFit, ActorLocation, ActorRotation)) {
UE_LOG(
LogCarla,

View File

@ -6,6 +6,7 @@
#include "AI/WalkerSpawnerBase.h"
#include "CarlaGameControllerBase.h"
#include "DynamicWeather.h"
#include "MockGameControllerSettings.h"
#include "CarlaGameModeBase.generated.h"
class APlayerStart;
@ -15,7 +16,7 @@ class UTaggerDelegate;
/**
*
*/
UCLASS()
UCLASS(HideCategories=(ActorTick))
class CARLA_API ACarlaGameModeBase : public AGameModeBase
{
GENERATED_BODY()
@ -34,6 +35,10 @@ public:
protected:
/** Used only when networking is disabled. */
UPROPERTY(Category = "Mock CARLA Controller", EditAnywhere, BlueprintReadOnly, meta = (ExposeFunctionCategories = "Mock CARLA Controller"))
FMockGameControllerSettings MockGameControllerSettings;
/** The class of DynamicWeather to spawn. */
UPROPERTY(Category = "CARLA Classes", EditAnywhere, BlueprintReadOnly)
TSubclassOf<ADynamicWeather> DynamicWeatherClass;

View File

@ -90,9 +90,9 @@ static void LoadSettingsFromFile(const FString &FileName, UCarlaSettings &Settin
Settings.WeatherDescriptions.Empty();
ADynamicWeather::LoadWeatherDescriptionsFromFile(Settings.WeatherDescriptions);
check(Settings.WeatherDescriptions.Num() > 0);
if (static_cast<int32>(Settings.WeatherId) >= Settings.WeatherDescriptions.Num()) {
if (Settings.WeatherId >= Settings.WeatherDescriptions.Num()) {
UE_LOG(LogCarla, Error, TEXT("Provided weather id %d cannot be found"), Settings.WeatherId);
Settings.WeatherId = 0u;
Settings.WeatherId = -1;
}
// SceneCapture.
FString Cameras;

View File

@ -22,9 +22,12 @@ public:
/** Log settings values. */
void LogSettings() const;
const FWeatherDescription &GetActiveWeatherDescription() const
const FWeatherDescription *GetActiveWeatherDescription() const
{
return WeatherDescriptions[WeatherId];
if ((WeatherId >= 0) && (WeatherId < WeatherDescriptions.Num())) {
return &WeatherDescriptions[WeatherId];
}
return nullptr;
}
private:
@ -70,9 +73,9 @@ public:
UPROPERTY(Category = "Level Settings", EditDefaultsOnly)
uint32 NumberOfPedestrians = 15u;
/** Index of the weather setting to use. */
/** Index of the weather setting to use. If negative, weather won't be changed. */
UPROPERTY(Category = "Level Settings", EditDefaultsOnly)
uint32 WeatherId = 0;
int32 WeatherId = -1;
/** Available weather settings. */
UPROPERTY(Category = "Level Settings", EditDefaultsOnly)

View File

@ -3,15 +3,46 @@
#include "Carla.h"
#include "MockGameController.h"
void MockGameController::Initialize(UCarlaSettings & /*CarlaSettings*/)
{
MockGameController::MockGameController(const FMockGameControllerSettings &InSettings) :
Settings(InSettings) {}
void MockGameController::Initialize(UCarlaSettings & CarlaSettings)
{
#if WITH_EDITOR
if (Settings.bOverrideCarlaSettings) {
CarlaSettings.NumberOfVehicles = Settings.NumberOfVehicles;
CarlaSettings.NumberOfPedestrians = Settings.NumberOfPedestrians;
CarlaSettings.WeatherId = Settings.WeatherId;
}
#endif // WITH_EDITOR
if (Settings.bChangeWeatherOnBeginPlay && (CarlaSettings.WeatherDescriptions.Num() > 0)) {
static uint32 StaticIndex = 0u;
CarlaSettings.WeatherId = StaticIndex % CarlaSettings.WeatherDescriptions.Num();
++StaticIndex;
}
#if WITH_EDITOR
if (Settings.bForceEnableSemanticSegmentation) {
CarlaSettings.bSemanticSegmentationEnabled = true;
}
#endif // WITH_EDITOR
}
APlayerStart *MockGameController::ChoosePlayerStart(
const TArray<APlayerStart *> &AvailableStartSpots)
{
return AvailableStartSpots[FMath::RandRange(0, AvailableStartSpots.Num() - 1)];
check(AvailableStartSpots.Num() > 0);
uint32 Index;
if (Settings.bRandomPlayerStart) {
Index = FMath::RandRange(0, AvailableStartSpots.Num() - 1);
} else {
static uint32 StaticIndex = 0u;
Index = StaticIndex % AvailableStartSpots.Num();
++StaticIndex;
}
UE_LOG(LogCarla, Log, TEXT("Spawning player at player start %d/%d"), Index, AvailableStartSpots.Num());
return AvailableStartSpots[Index];
}
void MockGameController::RegisterPlayer(AController &NewPlayer)

View File

@ -3,12 +3,15 @@
#pragma once
#include "CarlaGameControllerBase.h"
#include "MockGameControllerSettings.h"
/// Mocks the CARLA game controller class for testing purposes.
class CARLA_API MockGameController : public CarlaGameControllerBase
{
public:
explicit MockGameController(const FMockGameControllerSettings &Settings);
virtual void Initialize(UCarlaSettings &CarlaSettings) override;
virtual APlayerStart *ChoosePlayerStart(const TArray<APlayerStart *> &AvailableStartSpots) override;
@ -18,4 +21,8 @@ public:
virtual void BeginPlay() override;
virtual void Tick(float DeltaSeconds) override;
private:
FMockGameControllerSettings Settings;
};

View File

@ -0,0 +1,46 @@
// CARLA, Copyright (C) 2017 Computer Vision Center (CVC)
#pragma once
#include "MockGameControllerSettings.generated.h"
USTRUCT(BlueprintType)
struct FMockGameControllerSettings
{
GENERATED_USTRUCT_BODY()
/** If true, weather will be changed every time we start the level.
*
* Has precedence over options in "Override CARLA Settings".
*/
UPROPERTY(EditAnywhere, Category = "Mock CARLA Controller")
bool bChangeWeatherOnBeginPlay = true;
/** If true, a random player start position will be chosen every time we start the level. */
UPROPERTY(EditAnywhere, Category = "Mock CARLA Controller")
bool bRandomPlayerStart = true;
/** If true, semantic segmentation will be always enabled even if no camera needs it. */
UPROPERTY(EditAnywhere, Category = "Mock CARLA Controller")
bool bForceEnableSemanticSegmentation = false;
#if WITH_EDITORONLY_DATA
/** Override available settings in CARLA Settings (Editor only). */
UPROPERTY(EditAnywhere, Category = "Mock CARLA Controller", meta = (DisplayName = "Override CARLA Settings"))
bool bOverrideCarlaSettings = false;
/** Number of NPC vehicles to be spawned into the level. */
UPROPERTY(EditAnywhere, Category = "Mock CARLA Controller", meta = (EditCondition = "bOverrideCarlaSettings", ClampMin = 0))
int32 NumberOfVehicles = 5;
/** Number of NPC pedestrians to be spawned into the level. */
UPROPERTY(EditAnywhere, Category = "Mock CARLA Controller", meta = (EditCondition = "bOverrideCarlaSettings", ClampMin = 0))
int32 NumberOfPedestrians = 15;
/** Index of the weather setting to use. If negative, weather won't be changed. */
UPROPERTY(EditAnywhere, Category = "Mock CARLA Controller", meta = (EditCondition = "bOverrideCarlaSettings"))
int32 WeatherId = -1;
#endif // WITH_EDITORONLY_DATA
};

View File

@ -5,7 +5,7 @@
#include "HighResScreenshot.h"
#ifdef WITH_EDITOR
#if WITH_EDITOR
#include "DrawDebugHelpers.h"
#endif // WITH_EDITOR
@ -261,7 +261,7 @@ bool URoadMap::SaveAsPNG(const FString &Path) const
return true;
}
#ifdef WITH_EDITOR
#if WITH_EDITOR
void URoadMap::Log() const
{

View File

@ -141,7 +141,7 @@ public:
/// Save the current map as PNG with the pixel data encoded as color.
bool SaveAsPNG(const FString &Path) const;
#ifdef WITH_EDITOR
#if WITH_EDITOR
/// Log status of the map to the console.
void Log() const;