Full pipeline for spawning actors from Python
This commit is contained in:
parent
03c5ccc9d2
commit
0f636e84fd
|
@ -86,11 +86,11 @@ namespace client {
|
|||
|
||||
void ActorAttribute::Validate() const {
|
||||
switch (_attribute.type) {
|
||||
case rpc::ActorAttributeType::Bool: As<rpc::ActorAttributeType::Bool>();
|
||||
case rpc::ActorAttributeType::Int: As<rpc::ActorAttributeType::Int>();
|
||||
case rpc::ActorAttributeType::Float: As<rpc::ActorAttributeType::Float>();
|
||||
case rpc::ActorAttributeType::String: As<rpc::ActorAttributeType::String>();
|
||||
case rpc::ActorAttributeType::RGBColor: As<rpc::ActorAttributeType::RGBColor>();
|
||||
case rpc::ActorAttributeType::Bool: As<rpc::ActorAttributeType::Bool>(); break;
|
||||
case rpc::ActorAttributeType::Int: As<rpc::ActorAttributeType::Int>(); break;
|
||||
case rpc::ActorAttributeType::Float: As<rpc::ActorAttributeType::Float>(); break;
|
||||
case rpc::ActorAttributeType::String: As<rpc::ActorAttributeType::String>(); break;
|
||||
case rpc::ActorAttributeType::RGBColor: As<rpc::ActorAttributeType::RGBColor>(); break;
|
||||
default:
|
||||
LIBCARLA_THROW_INVALID_VALUE("invalid value type");
|
||||
}
|
||||
|
|
|
@ -58,10 +58,13 @@ namespace client {
|
|||
SharedPtr<World> GetWorld();
|
||||
|
||||
SharedPtr<BlueprintLibrary> GetBlueprintLibrary() {
|
||||
return MakeShared<BlueprintLibrary>(Call<std::vector<carla::rpc::ActorDefinition>>("get_blueprints"));
|
||||
return MakeShared<BlueprintLibrary>(
|
||||
Call<std::vector<carla::rpc::ActorDefinition>>("get_actor_definitions"));
|
||||
}
|
||||
|
||||
SharedPtr<Actor> SpawnActor(const ActorBlueprint &blueprint, const Transform &transform);
|
||||
SharedPtr<Actor> SpawnActor(
|
||||
const ActorBlueprint &blueprint,
|
||||
const Transform &transform);
|
||||
|
||||
void ApplyControlToActor(
|
||||
const Actor &actor,
|
||||
|
|
|
@ -29,7 +29,7 @@ namespace rpc {
|
|||
#ifdef LIBCARLA_INCLUDED_FROM_UE4
|
||||
|
||||
operator FActorDescription() const {
|
||||
FActorVariation Description;
|
||||
FActorDescription Description;
|
||||
Description.UId = uid;
|
||||
Description.Id = ToFString(id);
|
||||
Description.Variations.Reserve(attributes.size());
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include <boost/asio/io_service.hpp>
|
||||
|
||||
#include <rpc/server.h>
|
||||
#include <rpc/this_handler.h>
|
||||
|
||||
#include <future>
|
||||
|
||||
|
@ -108,6 +109,11 @@ namespace detail {
|
|||
_server.stop();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void RespondError(T &&error_object) {
|
||||
::rpc::this_handler().respond_error(std::forward<T>(error_object));
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
boost::asio::io_service _sync_io_service;
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
// Copyright (c) 2017 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 <rpc/rpc_error.h>
|
||||
|
||||
#include <boost/python.hpp>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
void translator(rpc::rpc_error e) {
|
||||
std::stringstream ss;
|
||||
ss << e.what()
|
||||
<< " in function " << e.get_function_name()
|
||||
<< ": " << e.get_error().as<std::string>();
|
||||
PyErr_SetString(PyExc_RuntimeError, ss.str().c_str());
|
||||
}
|
||||
|
||||
void export_exception() {
|
||||
using namespace boost::python;
|
||||
namespace cc = carla::client;
|
||||
|
||||
register_exception_translator<rpc::rpc_error>(translator);
|
||||
}
|
|
@ -10,6 +10,7 @@
|
|||
#include "Blueprint.cpp"
|
||||
#include "Client.cpp"
|
||||
#include "Control.cpp"
|
||||
#include "Exception.cpp"
|
||||
#include "Transform.cpp"
|
||||
#include "World.cpp"
|
||||
|
||||
|
@ -22,4 +23,5 @@ BOOST_PYTHON_MODULE(libcarla) {
|
|||
export_actor();
|
||||
export_world();
|
||||
export_client();
|
||||
export_exception();
|
||||
}
|
||||
|
|
|
@ -34,21 +34,18 @@ void FActorDispatcher::Bind(IActorSpawner &ActorSpawner)
|
|||
}
|
||||
}
|
||||
|
||||
AActor *FActorDispatcher::SpawnActor(
|
||||
TPair<EActorSpawnResultStatus, FActorView> FActorDispatcher::SpawnActor(
|
||||
const FTransform &Transform,
|
||||
const FActorDescription &Description)
|
||||
{
|
||||
if ((Description.UId == 0) || (Description.UId > SpawnFunctions.Num()))
|
||||
{
|
||||
UE_LOG(LogCarla, Error, TEXT("Invalid ActorDescription \"%s\" (UId=%d)"), *Description.Id, Description.UId);
|
||||
return nullptr;
|
||||
return MakeTuple(EActorSpawnResultStatus::InvalidDescription, FActorView());
|
||||
}
|
||||
auto *Actor = SpawnFunctions[Description.UId](Transform, Description);
|
||||
if (Actor != nullptr)
|
||||
{
|
||||
Registry.Register(*Actor);
|
||||
}
|
||||
return Actor;
|
||||
auto Result = SpawnFunctions[Description.UId - 1](Transform, Description);
|
||||
auto View = Result.IsValid() ? Registry.Register(*Result.Actor) : FActorView();
|
||||
return MakeTuple(Result.Status, View);
|
||||
}
|
||||
|
||||
void FActorDispatcher::DestroyActor(AActor *Actor)
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include "Carla/Actor/ActorDefinition.h"
|
||||
#include "Carla/Actor/ActorDescription.h"
|
||||
#include "Carla/Actor/ActorRegistry.h"
|
||||
#include "Carla/Actor/ActorSpawnResult.h"
|
||||
|
||||
#include "Containers/Array.h"
|
||||
#include "Templates/Function.h"
|
||||
|
@ -21,7 +22,7 @@ class FActorDispatcher
|
|||
{
|
||||
public:
|
||||
|
||||
using SpawnFunctionType = TFunction<AActor*(const FTransform &, const FActorDescription &)>;
|
||||
using SpawnFunctionType = TFunction<FActorSpawnResult(const FTransform &, const FActorDescription &)>;
|
||||
|
||||
/// Bind a definition to a spawn function. When SpawnActor is called with a
|
||||
/// matching description @a Functor is called.
|
||||
|
@ -37,8 +38,10 @@ public:
|
|||
/// Spawns an actor based on @a ActorDescription at @a Transform. To properly
|
||||
/// despawn an actor created with this function call DestroyActor.
|
||||
///
|
||||
/// Return nullptr on failure.
|
||||
AActor *SpawnActor(
|
||||
/// @return A pair containing the result of the spawn function and a view over
|
||||
/// the actor and its properties. If the status is different of Success the
|
||||
/// view is invalid.
|
||||
TPair<EActorSpawnResultStatus, FActorView> SpawnActor(
|
||||
const FTransform &Transform,
|
||||
const FActorDescription &ActorDescription);
|
||||
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
// Copyright (c) 2017 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.h"
|
||||
#include "Carla/Actor/ActorSpawnResult.h"
|
||||
|
||||
FString FActorSpawnResult::StatusToString(EActorSpawnResultStatus InStatus)
|
||||
{
|
||||
static_assert(
|
||||
static_cast<uint8>(EActorSpawnResultStatus::SIZE) == 4u,
|
||||
"If you add a new status, please update this function.");
|
||||
|
||||
switch (InStatus)
|
||||
{
|
||||
case EActorSpawnResultStatus::Success:
|
||||
return TEXT("Success");
|
||||
case EActorSpawnResultStatus::InvalidDescription:
|
||||
return TEXT("Spawn failed because of invalid actor description");
|
||||
case EActorSpawnResultStatus::Collision:
|
||||
return TEXT("Spawn failed because due to a collision at spawn position");
|
||||
case EActorSpawnResultStatus::UnknownError:
|
||||
default:
|
||||
return TEXT("Unknown error while trying to spawn actor");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
// Copyright (c) 2017 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 "ActorSpawnResult.generated.h"
|
||||
|
||||
/// List of valid types for actor attributes.
|
||||
UENUM(BlueprintType)
|
||||
enum class EActorSpawnResultStatus : uint8
|
||||
{
|
||||
Success UMETA(DisplayName = "Success"),
|
||||
InvalidDescription UMETA(DisplayName = "Invalid actor description"),
|
||||
Collision UMETA(DisplayName = "Failed because collision at spawn position"),
|
||||
UnknownError UMETA(DisplayName = "Unknown Error"),
|
||||
|
||||
SIZE UMETA(Hidden)
|
||||
};
|
||||
|
||||
/// Result of an actor spawn function.
|
||||
USTRUCT(BlueprintType)
|
||||
struct FActorSpawnResult
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
static FString StatusToString(EActorSpawnResultStatus Status);
|
||||
|
||||
bool IsValid() const
|
||||
{
|
||||
return (Actor != nullptr) && (Status == EActorSpawnResultStatus::Success);
|
||||
}
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
AActor *Actor = nullptr;
|
||||
|
||||
UPROPERTY(EditAnywhere, BlueprintReadWrite)
|
||||
EActorSpawnResultStatus Status = EActorSpawnResultStatus::UnknownError;
|
||||
};
|
|
@ -8,6 +8,7 @@
|
|||
|
||||
#include "Carla/Actor/ActorDefinition.h"
|
||||
#include "Carla/Actor/ActorDescription.h"
|
||||
#include "Carla/Actor/ActorSpawnResult.h"
|
||||
|
||||
#include "Containers/Array.h"
|
||||
#include "GameFramework/Actor.h"
|
||||
|
@ -26,7 +27,7 @@ public:
|
|||
///
|
||||
/// @pre ActorDescription is expected to be derived from one of the
|
||||
/// definitions retrieved with MakeDefinitions.
|
||||
virtual AActor *SpawnActor(
|
||||
virtual FActorSpawnResult SpawnActor(
|
||||
const FTransform &SpawnAtTransform,
|
||||
const FActorDescription &ActorDescription) = 0;
|
||||
};
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#pragma once
|
||||
|
||||
#include "Carla/Actor/ActorSpawner.h"
|
||||
#include "Carla/Actor/ActorSpawnResult.h"
|
||||
|
||||
#include "ActorSpawnerBlueprintBase.generated.h"
|
||||
|
||||
|
@ -28,13 +29,13 @@ public:
|
|||
return GenerateDefinitions();
|
||||
}
|
||||
|
||||
virtual AActor *SpawnActor(
|
||||
virtual FActorSpawnResult SpawnActor(
|
||||
const FTransform &SpawnAtTransform,
|
||||
const FActorDescription &ActorDescription) final
|
||||
{
|
||||
AActor *Actor = nullptr;
|
||||
SpawnActor(SpawnAtTransform, ActorDescription, Actor);
|
||||
return Actor;
|
||||
FActorSpawnResult Result;
|
||||
SpawnActor(SpawnAtTransform, ActorDescription, Result);
|
||||
return Result;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
@ -46,5 +47,5 @@ protected:
|
|||
void SpawnActor(
|
||||
const FTransform &SpawnAtTransform,
|
||||
const FActorDescription &ActorDescription,
|
||||
AActor *&Actor);
|
||||
FActorSpawnResult &SpawnResult);
|
||||
};
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
class AActor;
|
||||
|
||||
/// An view over an actor and its properties.
|
||||
/// A view over an actor and its properties.
|
||||
class FActorView
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -47,13 +47,28 @@ public:
|
|||
/// Spawns an actor based on @a ActorDescription at @a Transform. To properly
|
||||
/// despawn an actor created with this function call DestroyActor.
|
||||
///
|
||||
/// Return nullptr on failure.
|
||||
/// @return A pair containing the result of the spawn function and a view over
|
||||
/// the actor and its properties. If the status is different of Success the
|
||||
/// view is invalid.
|
||||
TPair<EActorSpawnResultStatus, FActorView> SpawnActorWithInfo(
|
||||
const FTransform &Transform,
|
||||
const FActorDescription &ActorDescription)
|
||||
{
|
||||
return ActorDispatcher.SpawnActor(Transform, ActorDescription);
|
||||
}
|
||||
|
||||
/// Spawns an actor based on @a ActorDescription at @a Transform. To properly
|
||||
/// despawn an actor created with this function call DestroyActor.
|
||||
///
|
||||
/// @return nullptr on failure.
|
||||
///
|
||||
/// @note Special overload for blueprints.
|
||||
UFUNCTION(BlueprintCallable)
|
||||
AActor *SpawnActor(
|
||||
const FTransform &Transform,
|
||||
const FActorDescription &ActorDescription)
|
||||
{
|
||||
return ActorDispatcher.SpawnActor(Transform, ActorDescription);
|
||||
return SpawnActorWithInfo(Transform, ActorDescription).Value.GetActor();
|
||||
}
|
||||
|
||||
/// Destroys an actor, properly removing it from the registry.
|
||||
|
|
|
@ -9,20 +9,99 @@
|
|||
|
||||
#include <compiler/disable-ue4-macros.h>
|
||||
#include <carla/Version.h>
|
||||
#include <carla/rpc/Actor.h>
|
||||
#include <carla/rpc/ActorDefinition.h>
|
||||
#include <carla/rpc/ActorDescription.h>
|
||||
#include <carla/rpc/Server.h>
|
||||
#include <carla/rpc/Transform.h>
|
||||
#include <compiler/enable-ue4-macros.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
// =============================================================================
|
||||
// -- Static local functions ---------------------------------------------------
|
||||
// =============================================================================
|
||||
|
||||
template <typename T, typename Other>
|
||||
static std::vector<T> MakeVectorFromTArray(const TArray<Other> &Array)
|
||||
{
|
||||
return {Array.GetData(), Array.GetData() + Array.Num()};
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// -- FTheNewCarlaServer::FPimpl -----------------------------------------------
|
||||
// =============================================================================
|
||||
|
||||
class FTheNewCarlaServer::FPimpl
|
||||
{
|
||||
public:
|
||||
|
||||
FPimpl(uint16_t port) : Server(port) {}
|
||||
FPimpl(uint16_t port) : Server(port) {
|
||||
BindActions();
|
||||
}
|
||||
|
||||
carla::rpc::Server Server;
|
||||
|
||||
UCarlaEpisode *CurrentEpisode = nullptr;
|
||||
UCarlaEpisode *Episode = nullptr;
|
||||
|
||||
private:
|
||||
|
||||
void BindActions();
|
||||
|
||||
void RespondErrorStr(const std::string &ErrorMessage) {
|
||||
UE_LOG(LogCarlaServer, Log, TEXT("Responding error, %s"), *carla::rpc::ToFString(ErrorMessage));
|
||||
carla::rpc::Server::RespondError(ErrorMessage);
|
||||
}
|
||||
|
||||
void RespondError(const FString &ErrorMessage) {
|
||||
RespondErrorStr(carla::rpc::FromFString(ErrorMessage));
|
||||
}
|
||||
|
||||
void RequireEpisode()
|
||||
{
|
||||
if (Episode == nullptr)
|
||||
{
|
||||
RespondErrorStr("episode not ready");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// =============================================================================
|
||||
// -- FTheNewCarlaServer::FPimpl Bind Actions ----------------------------------
|
||||
// =============================================================================
|
||||
|
||||
void FTheNewCarlaServer::FPimpl::BindActions()
|
||||
{
|
||||
namespace cr = carla::rpc;
|
||||
|
||||
Server.BindAsync("ping", []() { return true; });
|
||||
|
||||
Server.BindAsync("version", []() { return std::string(carla::version()); });
|
||||
|
||||
Server.BindSync("get_actor_definitions", [this]() {
|
||||
RequireEpisode();
|
||||
return MakeVectorFromTArray<cr::ActorDefinition>(Episode->GetActorDefinitions());
|
||||
});
|
||||
|
||||
Server.BindSync("spawn_actor", [this](
|
||||
const cr::Transform &Transform,
|
||||
const cr::ActorDescription &Definition) {
|
||||
RequireEpisode();
|
||||
auto Result = Episode->SpawnActorWithInfo(Transform, Definition);
|
||||
if (Result.Key != EActorSpawnResultStatus::Success)
|
||||
{
|
||||
RespondError(FActorSpawnResult::StatusToString(Result.Key));
|
||||
}
|
||||
cr::Actor actor;
|
||||
actor.id = Result.Value.GetActorId();
|
||||
return actor;
|
||||
});
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// -- FTheNewCarlaServer -------------------------------------------------------
|
||||
// =============================================================================
|
||||
|
||||
FTheNewCarlaServer::FTheNewCarlaServer() : Pimpl(nullptr) {}
|
||||
|
||||
FTheNewCarlaServer::~FTheNewCarlaServer() {}
|
||||
|
@ -30,27 +109,18 @@ FTheNewCarlaServer::~FTheNewCarlaServer() {}
|
|||
void FTheNewCarlaServer::Start(uint16_t Port)
|
||||
{
|
||||
UE_LOG(LogCarlaServer, Log, TEXT("Initializing rpc-server at port %d"), Port);
|
||||
|
||||
Pimpl = MakeUnique<FPimpl>(Port);
|
||||
|
||||
namespace cr = carla::rpc;
|
||||
|
||||
auto &srv = Pimpl->Server;
|
||||
|
||||
srv.BindAsync("ping", []() { return true; });
|
||||
|
||||
srv.BindAsync("version", []() { return std::string(carla::version()); });
|
||||
}
|
||||
|
||||
void FTheNewCarlaServer::NotifyBeginEpisode(UCarlaEpisode &Episode)
|
||||
{
|
||||
UE_LOG(LogCarlaServer, Log, TEXT("New episode '%s' started"), *Episode.GetMapName());
|
||||
Pimpl->CurrentEpisode = &Episode;
|
||||
Pimpl->Episode = &Episode;
|
||||
}
|
||||
|
||||
void FTheNewCarlaServer::NotifyEndEpisode()
|
||||
{
|
||||
Pimpl->CurrentEpisode = nullptr;
|
||||
Pimpl->Episode = nullptr;
|
||||
}
|
||||
|
||||
void FTheNewCarlaServer::AsyncRun(uint32 NumberOfWorkerThreads)
|
||||
|
|
Loading…
Reference in New Issue