Adding load control on sublevels (#3515)

* Added MapLayer enum

* Added Load/Unload layer functions

* Added calls to register and tag objects on map change

* Added missing file

* Updated MapLayer to support more layers

* Added calls to PythonAPI

* Added default value

* Moved CurrentMapLayer to GI

* Updated manual_control with maplayer handling

* Updated help

* Updated Changelog

* Fixed a missing `;`

* Fixed LoadWorld() API so it works with old code

* Added missing include for shipping builds

* Fixed base enum type of MapLayer

* Removed int number from layer output

* Renamed variables

* MapLayer converted to int32 and added generic enumToString function

* MapLayer back to uint16

Co-authored-by: Marc Garcia Puig <marcgpuig@gmail.com>
This commit is contained in:
doterop 2020-11-02 11:22:49 +01:00 committed by GitHub
parent 7a14a53107
commit 8f1b401e49
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 353 additions and 40 deletions

View File

@ -1,9 +1,9 @@
## Latest
* Updated the bounding box calculation of two wheeled vehicles to include the character inside the bounding box
* Added `load_map_layer` and `unload_map_layer` to control map layers on new maps that support subleveling
* Added `get_environment_objects`call to get all the placed objects in the level
* Added `enable_environment_objects`call to enable/disable objects of the level
* Added fully deterministic option for Traffic Manager, sorting vehicles by ID and avoiding race conditions.
* Fixed RSSSensor python3 build and import of open drive maps by updating to ad-rss v4.2.0 and ad-map-access v2.3.0. Python import of dependent 'ad' python modules reflects now the namespaces of the C++ interface and follow doxygen documentation.
* Added fully deterministic option for Traffic Manager, sorting vehicles by ID and avoiding race conditions
* Fixed RSSSensor python3 build and import of open drive maps by updating to ad-rss v4.2.0 and ad-map-access v2.3.0. Python import of dependent 'ad' python modules reflects now the namespaces of the C++ interface and follow doxygen documentation
* Fixed sensor transformations and sensor data transformations mismatch in IMU and camera-based sensors
* Fixed random dead-lock on synchronous mode at high frame rate
* API extensions:

View File

@ -58,8 +58,10 @@ namespace client {
return World{_simulator->ReloadEpisode()};
}
World LoadWorld(std::string map_name) const {
return World{_simulator->LoadEpisode(std::move(map_name))};
World LoadWorld(
std::string map_name,
rpc::MapLayer map_layers = rpc::MapLayer::All) const {
return World{_simulator->LoadEpisode(std::move(map_name), map_layers)};
}
World GenerateOpenDriveWorld(

View File

@ -22,6 +22,14 @@ namespace client {
return _episode.Lock()->GetCurrentMap();
}
void World::LoadLevelLayer(rpc::MapLayer map_layers) const {
_episode.Lock()->LoadLevelLayer(map_layers);
}
void World::UnloadLevelLayer(rpc::MapLayer map_layers) const {
_episode.Lock()->UnloadLevelLayer(map_layers);
}
SharedPtr<BlueprintLibrary> World::GetBlueprintLibrary() const {
return _episode.Lock()->GetBlueprintLibrary();
}

View File

@ -20,6 +20,7 @@
#include "carla/rpc/EpisodeSettings.h"
#include "carla/rpc/EnvironmentObject.h"
#include "carla/rpc/LabelledPoint.h"
#include "carla/rpc/MapLayer.h"
#include "carla/rpc/VehiclePhysicsControl.h"
#include "carla/rpc/WeatherParameters.h"
#include "carla/rpc/VehicleLightStateList.h"
@ -58,6 +59,10 @@ namespace client {
/// Return the map that describes this world.
SharedPtr<Map> GetMap() const;
void LoadLevelLayer(rpc::MapLayer map_layers) const;
void UnloadLevelLayer(rpc::MapLayer map_layers) const;
/// Return the list of blueprints available in this world. This blueprints
/// can be used to spawning actor into the world.
SharedPtr<BlueprintLibrary> GetBlueprintLibrary() const;

View File

@ -140,9 +140,19 @@ namespace detail {
return _pimpl->CallAndWait<std::string>("version");
}
void Client::LoadEpisode(std::string map_name) {
void Client::LoadEpisode(std::string map_name, rpc::MapLayer map_layer) {
// Await response, we need to be sure in this one.
_pimpl->CallAndWait<void>("load_new_episode", std::move(map_name));
_pimpl->CallAndWait<void>("load_new_episode", std::move(map_name), map_layer);
}
void Client::LoadLevelLayer(rpc::MapLayer map_layer) const {
// Await response, we need to be sure in this one.
_pimpl->CallAndWait<void>("load_map_layer", map_layer);
}
void Client::UnloadLevelLayer(rpc::MapLayer map_layer) const {
// Await response, we need to be sure in this one.
_pimpl->CallAndWait<void>("unload_map_layer", map_layer);
}
void Client::CopyOpenDriveToServer(std::string opendrive, const rpc::OpendriveGenerationParameters & params) {

View File

@ -21,6 +21,7 @@
#include "carla/rpc/LabelledPoint.h"
#include "carla/rpc/LightState.h"
#include "carla/rpc/MapInfo.h"
#include "carla/rpc/MapLayer.h"
#include "carla/rpc/EnvironmentObject.h"
#include "carla/rpc/TrafficLightState.h"
#include "carla/rpc/VehiclePhysicsControl.h"
@ -90,7 +91,11 @@ namespace detail {
std::string GetServerVersion();
void LoadEpisode(std::string map_name);
void LoadEpisode(std::string map_name, rpc::MapLayer map_layer = rpc::MapLayer::All);
void LoadLevelLayer(rpc::MapLayer map_layer) const;
void UnloadLevelLayer(rpc::MapLayer map_layer) const;
void CopyOpenDriveToServer(
std::string opendrive, const rpc::OpendriveGenerationParameters & params);

View File

@ -82,9 +82,9 @@ namespace detail {
// -- Load a new episode -----------------------------------------------------
// ===========================================================================
EpisodeProxy Simulator::LoadEpisode(std::string map_name) {
EpisodeProxy Simulator::LoadEpisode(std::string map_name, rpc::MapLayer map_layers) {
const auto id = GetCurrentEpisode().GetId();
_client.LoadEpisode(std::move(map_name));
_client.LoadEpisode(std::move(map_name), map_layers);
size_t number_of_attempts = _client.GetTimeout().milliseconds() / 10u;
for (auto i = 0u; i < number_of_attempts; ++i) {
using namespace std::literals::chrono_literals;

View File

@ -68,7 +68,15 @@ namespace detail {
return LoadEpisode("");
}
EpisodeProxy LoadEpisode(std::string map_name);
EpisodeProxy LoadEpisode(std::string map_name, rpc::MapLayer map_layers = rpc::MapLayer::All);
void LoadLevelLayer(rpc::MapLayer map_layers) const {
_client.LoadLevelLayer(map_layers);
}
void UnloadLevelLayer(rpc::MapLayer map_layers) const {
_client.UnloadLevelLayer(map_layers);
}
EpisodeProxy LoadOpenDriveEpisode(
std::string opendrive,

View File

@ -0,0 +1,33 @@
// Copyright (c) 2020 Computer Vision Center (CVC) at the Universitat Autonoma
// de Barcelona (UAB).
//
// This work is licensed under the terms of the MIT license.
// For a copy, see <https://opensource.org/licenses/MIT>.
#include "MapLayer.h"
namespace carla {
namespace rpc {
std::string MapLayerToString(MapLayer MapLayerValue)
{
switch(MapLayerValue)
{
case MapLayer::None: return "None";
case MapLayer::Buildings: return "Buildings";
case MapLayer::Decals: return "Decals";
case MapLayer::Foliage: return "Foliage";
case MapLayer::Ground: return "Ground";
case MapLayer::ParkedVehicles: return "Parked_Vehicles";
case MapLayer::Particles: return "Particles";
case MapLayer::Props: return "Props";
case MapLayer::StreetLights: return "StreetLights";
case MapLayer::Walls: return "Walls";
case MapLayer::All: return "All";
default: return "Invalid";
}
}
} // namespace rpc
} // namespace carla

View File

@ -0,0 +1,38 @@
// Copyright (c) 2020 Computer Vision Center (CVC) at the Universitat Autonoma
// de Barcelona (UAB).
//
// This work is licensed under the terms of the MIT license.
// For a copy, see <https://opensource.org/licenses/MIT>.
#pragma once
#include "carla/MsgPack.h"
#include <cstdint>
namespace carla {
namespace rpc {
using MapLayerType = uint16_t;
enum class MapLayer : MapLayerType
{
None = 0,
Buildings = 0x1,
Decals = 0x1 << 1,
Foliage = 0x1 << 2,
Ground = 0x1 << 3,
ParkedVehicles = 0x1 << 4,
Particles = 0x1 << 5,
Props = 0x1 << 6,
StreetLights = 0x1 << 7,
Walls = 0x1 << 8,
All = 0xFFFF,
};
std::string MapLayerToString(MapLayer MapLayerValue);
} // namespace rpc
} // namespace carla
MSGPACK_ADD_ENUM(carla::rpc::MapLayer);

View File

@ -181,7 +181,7 @@ void export_client() {
.def("get_world", &cc::Client::GetWorld)
.def("get_available_maps", &GetAvailableMaps)
.def("reload_world", CONST_CALL_WITHOUT_GIL(cc::Client, ReloadWorld))
.def("load_world", CONST_CALL_WITHOUT_GIL_1(cc::Client, LoadWorld, std::string), (arg("map_name")))
.def("load_world", CONST_CALL_WITHOUT_GIL_2(cc::Client, LoadWorld, std::string, rpc::MapLayer), (arg("map_name"), arg("map_layers")=rpc::MapLayer::All))
.def("generate_opendrive_world", CONST_CALL_WITHOUT_GIL_2(cc::Client, GenerateOpenDriveWorld, std::string,
rpc::OpendriveGenerationParameters), (arg("opendrive"), arg("parameters")=rpc::OpendriveGenerationParameters()))
.def("start_recorder", CALL_WITHOUT_GIL_2(cc::Client, StartRecorder, std::string, bool), (arg("name"), arg("additional_data")=false))

View File

@ -206,6 +206,20 @@ void export_world() {
.def_readonly("label", &cr::LabelledPoint::_label)
;
enum_<cr::MapLayer>("MapLayer")
.value("NONE", cr::MapLayer::None)
.value("Buildings", cr::MapLayer::Buildings)
.value("Decals", cr::MapLayer::Decals)
.value("Foliage", cr::MapLayer::Foliage)
.value("Ground", cr::MapLayer::Ground)
.value("ParkedVehicles", cr::MapLayer::ParkedVehicles)
.value("Particles", cr::MapLayer::Particles)
.value("Props", cr::MapLayer::Props)
.value("StreetLights", cr::MapLayer::StreetLights)
.value("Walls", cr::MapLayer::Walls)
.value("All", cr::MapLayer::All)
;
#define SPAWN_ACTOR_WITHOUT_GIL(fn) +[]( \
cc::World &self, \
const cc::ActorBlueprint &blueprint, \
@ -224,6 +238,8 @@ void export_world() {
class_<cc::World>("World", no_init)
.add_property("id", &cc::World::GetId)
.add_property("debug", &cc::World::MakeDebugHelper)
.def("load_map_layer", CONST_CALL_WITHOUT_GIL_1(cc::World, LoadLevelLayer, cr::MapLayer), arg("map_layers"))
.def("unload_map_layer", CONST_CALL_WITHOUT_GIL_1(cc::World, UnloadLevelLayer, cr::MapLayer), arg("map_layers"))
.def("get_blueprint_library", CONST_CALL_WITHOUT_GIL(cc::World, GetBlueprintLibrary))
.def("get_vehicles_light_states", &GetVehiclesLightStates)
.def("get_map", CONST_CALL_WITHOUT_GIL(cc::World, GetMap))

View File

@ -36,6 +36,9 @@ Use ARROWS or WASD keys for control.
C : change weather (Shift+C reverse)
Backspace : change vehicle
V : Select next map layer (Shift+V reverse)
B : Load current selected map layer (Shift+B to unload)
R : toggle recording images to disk
CTRL + R : toggle recording of simulation (replacing any previous)
@ -107,21 +110,23 @@ try:
from pygame.locals import K_TAB
from pygame.locals import K_UP
from pygame.locals import K_a
from pygame.locals import K_b
from pygame.locals import K_c
from pygame.locals import K_g
from pygame.locals import K_d
from pygame.locals import K_g
from pygame.locals import K_h
from pygame.locals import K_i
from pygame.locals import K_l
from pygame.locals import K_m
from pygame.locals import K_n
from pygame.locals import K_p
from pygame.locals import K_q
from pygame.locals import K_r
from pygame.locals import K_s
from pygame.locals import K_v
from pygame.locals import K_w
from pygame.locals import K_l
from pygame.locals import K_i
from pygame.locals import K_z
from pygame.locals import K_x
from pygame.locals import K_z
from pygame.locals import K_MINUS
from pygame.locals import K_EQUALS
except ImportError:
@ -183,6 +188,20 @@ class World(object):
self.recording_enabled = False
self.recording_start = 0
self.constant_velocity_enabled = False
self.current_map_layer = 0
self.map_layer_names = [
carla.MapLayer.NONE,
carla.MapLayer.Buildings,
carla.MapLayer.Decals,
carla.MapLayer.Foliage,
carla.MapLayer.Ground,
carla.MapLayer.ParkedVehicles,
carla.MapLayer.Particles,
carla.MapLayer.Props,
carla.MapLayer.StreetLights,
carla.MapLayer.Walls,
carla.MapLayer.All
]
def restart(self):
self.player_max_speed = 1.589
@ -241,6 +260,21 @@ class World(object):
self.hud.notification('Weather: %s' % preset[1])
self.player.get_world().set_weather(preset[0])
def next_map_layer(self, reverse=False):
self.current_map_layer += -1 if reverse else 1
self.current_map_layer %= len(self.map_layer_names)
selected = self.map_layer_names[self.current_map_layer]
self.hud.notification('LayerMap selected: %s' % selected)
def load_map_layer(self, unload=False):
selected = self.map_layer_names[self.current_map_layer]
if unload:
self.hud.notification('Unloading map layer: %s' % selected)
self.world.unload_map_layer(selected)
else:
self.hud.notification('Loading map layer: %s' % selected)
self.world.load_map_layer(selected)
def toggle_radar(self):
if self.radar_sensor is None:
self.radar_sensor = RadarSensor(self.player)
@ -318,6 +352,14 @@ class KeyboardControl(object):
world.restart()
elif event.key == K_F1:
world.hud.toggle_info()
elif event.key == K_v and pygame.key.get_mods() & KMOD_SHIFT:
world.next_map_layer(reverse=True)
elif event.key == K_v:
world.next_map_layer()
elif event.key == K_b and pygame.key.get_mods() & KMOD_SHIFT:
world.load_map_layer(unload=True)
elif event.key == K_b:
world.load_map_layer()
elif event.key == K_h or (event.key == K_SLASH and pygame.key.get_mods() & KMOD_SHIFT):
world.hud.help.toggle()
elif event.key == K_TAB:
@ -945,7 +987,6 @@ class CameraManager(object):
if attr_name == 'range':
self.lidar_range = float(attr_value)
item.append(bp)
self.index = None

View File

@ -13,6 +13,7 @@
#include "Carla/Server/CarlaServer.h"
#include <compiler/disable-ue4-macros.h>
#include <carla/rpc/MapLayer.h>
#include <carla/rpc/OpendriveGenerationParameters.h>
#include <compiler/enable-ue4-macros.h>
@ -90,6 +91,18 @@ public:
return GenerationParameters;
}
UFUNCTION(Category = "Carla Game Instance", BlueprintCallable)
void SetMapLayer(int32 MapLayer)
{
CurrentMapLayer = MapLayer;
}
UFUNCTION(Category = "Carla Game Instance", BlueprintCallable)
int32 GetCurrentMapLayer() const
{
return CurrentMapLayer;
}
private:
UPROPERTY(Category = "CARLA Settings", EditAnywhere)
@ -102,4 +115,7 @@ private:
carla::rpc::OpendriveGenerationParameters GenerationParameters;
UPROPERTY(Category = "CARLA Game Instance", EditAnywhere)
int32 CurrentMapLayer = static_cast<int32>(carla::rpc::MapLayer::All);
};

View File

@ -8,12 +8,14 @@
#include "Carla/Game/CarlaGameModeBase.h"
#include "Carla/Game/CarlaHUD.h"
#include "Engine/DecalActor.h"
#include "Engine/LevelStreaming.h"
#include <compiler/disable-ue4-macros.h>
#include "carla/opendrive/OpenDriveParser.h"
#include "carla/road/element/RoadInfoSignal.h"
#include <carla/rpc/EnvironmentObject.h>
#include <carla/rpc/WeatherParameters.h>
#include <carla/rpc/MapLayer.h>
#include <compiler/enable-ue4-macros.h>
#include "Async/ParallelFor.h"
@ -23,6 +25,7 @@
#include "Kismet/KismetSystemLibrary.h"
namespace cr = carla::road;
namespace crp = carla::rpc;
namespace cre = carla::road::element;
ACarlaGameModeBase::ACarlaGameModeBase(const FObjectInitializer& ObjectInitializer)
@ -121,6 +124,9 @@ void ACarlaGameModeBase::BeginPlay()
{
Super::BeginPlay();
LoadMapLayer(GameInstance->GetCurrentMapLayer());
if (true) { /// @todo If semantic segmentation enabled.
check(GetWorld() != nullptr);
ATagger::TagActorsInLevel(*GetWorld(), true);
@ -350,11 +356,6 @@ TArray<FBoundingBox> ACarlaGameModeBase::GetAllBBsOfLevel(uint8 TagQueried)
return BoundingBoxes;
}
TArray<FEnvironmentObject> ACarlaGameModeBase::GetEnvironmentObjects() const
{
return EnvironmentObjects;
}
void ACarlaGameModeBase::RegisterEnvironmentObject()
{
UWorld* World = GetWorld();
@ -403,3 +404,85 @@ void ACarlaGameModeBase::EnableEnvironmentObjects(
}
}
void ACarlaGameModeBase::LoadMapLayer(int32 MapLayers)
{
const UWorld* World = GetWorld();
TArray<FName> LevelsToLoad;
ConvertMapLayerMaskToMapNames(MapLayers, LevelsToLoad);
FLatentActionInfo LatentInfo;
LatentInfo.UUID = 1;
for(FName& LevelName : LevelsToLoad)
{
UGameplayStatics::LoadStreamLevel(World, LevelName, true, true, LatentInfo);
LatentInfo.UUID++;
}
// Register new actors and tag them
RegisterEnvironmentObject();
ATagger::TagActorsInLevel(*GetWorld(), true);
}
void ACarlaGameModeBase::UnLoadMapLayer(int32 MapLayers)
{
const UWorld* World = GetWorld();
TArray<FName> LevelsToLoad;
ConvertMapLayerMaskToMapNames(MapLayers, LevelsToLoad);
FLatentActionInfo LatentInfo;
LatentInfo.UUID = 1;
for(FName& LevelName : LevelsToLoad)
{
UGameplayStatics::UnloadStreamLevel(World, LevelName, LatentInfo, true);
LatentInfo.UUID++;
}
// Update stored registered objects (discarding the deleted objects)
RegisterEnvironmentObject();
}
void ACarlaGameModeBase::ConvertMapLayerMaskToMapNames(int32 MapLayer, TArray<FName>& OutLevelNames)
{
UWorld* World = GetWorld();
const TArray <ULevelStreaming*> Levels = World->GetStreamingLevels();
TArray<FString> LayersToLoad;
// Get all the requested layers
int32 LayerMask = 1;
int32 AllLayersMask = static_cast<crp::MapLayerType>(crp::MapLayer::All);
while(LayerMask > 0)
{
// Convert enum to FString
FString LayerName = UTF8_TO_TCHAR(MapLayerToString(static_cast<crp::MapLayer>(LayerMask)).c_str());
bool included = static_cast<crp::MapLayerType>(MapLayer) & LayerMask;
if(included)
{
LayersToLoad.Emplace(LayerName);
}
LayerMask = (LayerMask << 1) & AllLayersMask;
}
// Get all the requested level maps
for(ULevelStreaming* Level : Levels)
{
TArray<FString> StringArray;
FString FullSubMapName = Level->PackageNameToLoad.ToString();
// Discard full path, we just need the umap name
FullSubMapName.ParseIntoArray(StringArray, TEXT("/"), false);
FString SubMapName = StringArray[StringArray.Num() - 1];
for(FString LayerName : LayersToLoad)
{
if(SubMapName.Contains(LayerName))
{
OutLevelNames.Emplace(FName(*SubMapName));
break;
}
}
}
}

View File

@ -6,19 +6,6 @@
#pragma once
#include "Carla/Actor/CarlaActorFactory.h"
#include "Carla/Game/CarlaEpisode.h"
#include "Carla/Game/CarlaGameInstance.h"
#include "Carla/Recorder/CarlaRecorder.h"
#include "Carla/Game/TaggerDelegate.h"
#include "Carla/OpenDrive/OpenDrive.h"
#include "Carla/Sensor/SceneCaptureSensor.h"
#include "Carla/Settings/CarlaSettingsDelegate.h"
#include "Carla/Weather/Weather.h"
#include "Carla/Traffic/TrafficLightManager.h"
#include "Carla/Util/EnvironmentObject.h"
#include "CoreMinimal.h"
#include "GameFramework/GameModeBase.h"
@ -26,6 +13,18 @@
#include <boost/optional.hpp>
#include <compiler/enable-ue4-macros.h>
#include "Carla/Actor/CarlaActorFactory.h"
#include "Carla/Game/CarlaEpisode.h"
#include "Carla/Game/CarlaGameInstance.h"
#include "Carla/Game/TaggerDelegate.h"
#include "Carla/OpenDrive/OpenDrive.h"
#include "Carla/Recorder/CarlaRecorder.h"
#include "Carla/Sensor/SceneCaptureSensor.h"
#include "Carla/Settings/CarlaSettingsDelegate.h"
#include "Carla/Traffic/TrafficLightManager.h"
#include "Carla/Util/EnvironmentObject.h"
#include "Carla/Weather/Weather.h"
#include "CarlaGameModeBase.generated.h"
/// Base class for the CARLA Game Mode.
@ -58,10 +57,19 @@ public:
TArray<FBoundingBox> GetAllBBsOfLevel(uint8 TagQueried = 0);
UFUNCTION(Category = "Carla Game Mode", BlueprintCallable, CallInEditor, Exec)
TArray<FEnvironmentObject> GetEnvironmentObjects() const;
TArray<FEnvironmentObject> GetEnvironmentObjects() const
{
return EnvironmentObjects;
}
void EnableEnvironmentObjects(const TSet<uint64>& EnvObjectIds, bool Enable);
UFUNCTION(Category = "Carla Game Mode", BlueprintCallable, CallInEditor, Exec)
void LoadMapLayer(int32 MapLayers);
UFUNCTION(Category = "Carla Game Mode", BlueprintCallable, CallInEditor, Exec)
void UnLoadMapLayer(int32 MapLayers);
protected:
void InitGame(const FString &MapName, const FString &Options, FString &ErrorMessage) override;
@ -82,6 +90,8 @@ private:
void RegisterEnvironmentObject();
void ConvertMapLayerMaskToMapNames(int32 MapLayer, TArray<FName>& OutLevelNames);
UPROPERTY()
UCarlaGameInstance *GameInstance = nullptr;

View File

@ -25,12 +25,13 @@
#include <carla/rpc/Command.h>
#include <carla/rpc/CommandResponse.h>
#include <carla/rpc/DebugShape.h>
#include <carla/rpc/EnvironmentObject.h>
#include <carla/rpc/EpisodeInfo.h>
#include <carla/rpc/EpisodeSettings.h>
#include "carla/rpc/LabelledPoint.h"
#include <carla/rpc/LightState.h>
#include <carla/rpc/MapInfo.h>
#include <carla/rpc/EnvironmentObject.h>
#include <carla/rpc/MapLayer.h>
#include <carla/rpc/Response.h>
#include <carla/rpc/Server.h>
#include <carla/rpc/String.h>
@ -237,13 +238,50 @@ void FCarlaServer::FPimpl::BindActions()
return result;
};
BIND_SYNC(load_new_episode) << [this](const std::string &map_name) -> R<void>
BIND_SYNC(load_new_episode) << [this](const std::string &map_name, cr::MapLayer MapLayers) -> R<void>
{
REQUIRE_CARLA_EPISODE();
UCarlaGameInstance* GameInstance = UCarlaStatics::GetGameInstance(Episode->GetWorld());
if (!GameInstance)
{
RESPOND_ERROR("unable to find CARLA game instance");
}
GameInstance->SetMapLayer(static_cast<int32>(MapLayers));
if(!Episode->LoadNewEpisode(cr::ToFString(map_name)))
{
RESPOND_ERROR("map not found");
}
return R<void>::Success();
};
BIND_SYNC(load_map_layer) << [this](cr::MapLayer MapLayers) -> R<void>
{
REQUIRE_CARLA_EPISODE();
ACarlaGameModeBase* GameMode = UCarlaStatics::GetGameMode(Episode->GetWorld());
if (!GameMode)
{
RESPOND_ERROR("unable to find CARLA game mode");
}
GameMode->LoadMapLayer(static_cast<int32>(MapLayers));
return R<void>::Success();
};
BIND_SYNC(unload_map_layer) << [this](cr::MapLayer MapLayers) -> R<void>
{
REQUIRE_CARLA_EPISODE();
ACarlaGameModeBase* GameMode = UCarlaStatics::GetGameMode(Episode->GetWorld());
if (!GameMode)
{
RESPOND_ERROR("unable to find CARLA game mode");
}
GameMode->UnLoadMapLayer(static_cast<int32>(MapLayers));
return R<void>::Success();
};