Add support for spawning and controlling walkers

This commit is contained in:
nsubiron 2019-01-16 15:01:49 +01:00
parent aeecd3d6eb
commit 4ab822bcce
22 changed files with 468 additions and 26 deletions

View File

@ -5,7 +5,8 @@
* Added "sensor_tick" attribute to sensors (cameras and lidars) to specify the capture rate in seconds
* Added "get_forward_vector()" to rotation and transform, retrieves the unit vector on the rotation's X-axis
* Added support for Deepin in PythonAPI's setup.py
* Rename vehicle.get_vehicle_control() to vehicle.get_control() to be consistent with walkers
* Added support for spawning and controlling walkers (pedestrians)
* Renamed vehicle.get_vehicle_control() to vehicle.get_control() to be consistent with walkers
## CARLA 0.9.2

View File

@ -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 "carla/client/Walker.h"
#include "carla/client/detail/Simulator.h"
namespace carla {
namespace client {
void Walker::ApplyControl(const Control &control) {
if (control != _control) {
GetEpisode().Lock()->ApplyControlToWalker(*this, control);
_control = control;
}
}
Walker::Control Walker::GetWalkerControl() const {
return GetEpisode().Lock()->GetActorDynamicState(*this).state.walker_control;
}
} // namespace client
} // namespace carla

View File

@ -0,0 +1,37 @@
// 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/client/Actor.h"
#include "carla/rpc/WalkerControl.h"
namespace carla {
namespace client {
class Walker : public Actor {
public:
using Control = rpc::WalkerControl;
explicit Walker(ActorInitializer init) : Actor(std::move(init)) {}
/// Apply @a control to this Walker.
void ApplyControl(const Control &control);
/// Return the control last applied to this Walker.
///
/// @note This function does not call the simulator, it returns the Control
/// received in the last tick.
Control GetWalkerControl() const;
private:
Control _control;
};
} // namespace client
} // namespace carla

View File

@ -13,6 +13,7 @@
#include "carla/client/ServerSideSensor.h"
#include "carla/client/TrafficLight.h"
#include "carla/client/Vehicle.h"
#include "carla/client/Walker.h"
#include "carla/client/World.h"
#include "carla/client/detail/Client.h"
@ -76,6 +77,8 @@ namespace detail {
return MakeActorImpl<ServerSideSensor>(std::move(init), gc);
} else if (StringUtil::StartsWith(description.description.id, "vehicle.")) {
return MakeActorImpl<Vehicle>(std::move(init), gc);
} else if (StringUtil::StartsWith(description.description.id, "walker.")) {
return MakeActorImpl<Walker>(std::move(init), gc);
} else if (StringUtil::StartsWith(description.description.id, "traffic.traffic_light")) {
return MakeActorImpl<TrafficLight>(std::move(init), gc);
}

View File

@ -11,6 +11,7 @@
#include "carla/rpc/Client.h"
#include "carla/rpc/DebugShape.h"
#include "carla/rpc/VehicleControl.h"
#include "carla/rpc/WalkerControl.h"
#include "carla/streaming/Client.h"
#include <thread>
@ -143,6 +144,10 @@ namespace detail {
_pimpl->AsyncCall("apply_control_to_vehicle", vehicle, control);
}
void Client::ApplyControlToWalker(const rpc::Actor &walker, const rpc::WalkerControl &control) {
_pimpl->AsyncCall("apply_control_to_walker", walker, control);
}
void Client::SubscribeToStream(
const streaming::Token &token,
std::function<void(Buffer)> callback) {

View File

@ -28,6 +28,7 @@ namespace rpc {
class ActorDescription;
class DebugShape;
class VehicleControl;
class WalkerControl;
}
namespace sensor { class SensorData; }
namespace streaming { class Token; }
@ -102,6 +103,10 @@ namespace detail {
const rpc::Actor &vehicle,
const rpc::VehicleControl &control);
void ApplyControlToWalker(
const rpc::Actor &walker,
const rpc::WalkerControl &control);
void SubscribeToStream(
const streaming::Token &token,
std::function<void(Buffer)> callback);

View File

@ -13,6 +13,7 @@
#include "carla/client/Actor.h"
#include "carla/client/GarbageCollectionPolicy.h"
#include "carla/client/Vehicle.h"
#include "carla/client/Walker.h"
#include "carla/client/detail/Client.h"
#include "carla/client/detail/Episode.h"
#include "carla/client/detail/EpisodeProxy.h"
@ -202,6 +203,10 @@ namespace detail {
_client.ApplyControlToVehicle(vehicle.Serialize(), control);
}
void ApplyControlToWalker(Walker &walker, const rpc::WalkerControl &control) {
_client.ApplyControlToWalker(walker.Serialize(), control);
}
/// @}
// =========================================================================
/// @name Operations with sensors

View File

@ -0,0 +1,59 @@
// 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/MsgPack.h"
#ifdef LIBCARLA_INCLUDED_FROM_UE4
# include "Carla/Walker/WalkerControl.h"
#endif // LIBCARLA_INCLUDED_FROM_UE4
namespace carla {
namespace rpc {
class WalkerControl {
public:
WalkerControl() = default;
WalkerControl(
geom::Vector3D in_direction,
float in_speed)
: direction(in_direction),
speed(in_speed) {}
geom::Vector3D direction = {1.0f, 0.0f, 0.0f};
float speed = 0.0f;
#ifdef LIBCARLA_INCLUDED_FROM_UE4
WalkerControl(const FWalkerControl &Control)
: direction(Control.Direction.X, Control.Direction.Y, Control.Direction.Z),
speed(1e-2f * Control.Speed) {}
operator FWalkerControl() const {
FWalkerControl Control;
Control.Direction = {direction.x, direction.y, direction.z};
Control.Speed = 1e2f * speed;
return Control;
}
#endif // LIBCARLA_INCLUDED_FROM_UE4
bool operator!=(const WalkerControl &rhs) const {
return direction != rhs.direction || speed != rhs.speed;
}
bool operator==(const WalkerControl &rhs) const {
return !(*this != rhs);
}
MSGPACK_DEFINE_ARRAY(direction, speed);
};
} // namespace rpc
} // namespace carla

View File

@ -11,6 +11,7 @@
#include "carla/rpc/ActorId.h"
#include "carla/rpc/TrafficLightState.h"
#include "carla/rpc/VehicleControl.h"
#include "carla/rpc/WalkerControl.h"
#include <cstdint>
@ -51,6 +52,27 @@ namespace detail {
};
#pragma pack(pop)
#pragma pack(push, 1)
class PackedWalkerControl {
public:
PackedWalkerControl() = default;
PackedWalkerControl(const rpc::WalkerControl &control)
: direction{control.direction.x, control.direction.y, control.direction.z},
speed(control.speed) {}
operator rpc::WalkerControl() const {
return {geom::Vector3D{direction[0u], direction[1u], direction[2u]}, speed};
}
private:
float direction[3u];
float speed;
};
#pragma pack(pop)
} // namespace detail
#pragma pack(push, 1)
@ -67,6 +89,7 @@ namespace detail {
union TypeDependentState {
rpc::TrafficLightState traffic_light_state;
detail::PackedVehicleControl vehicle_control;
detail::PackedWalkerControl walker_control;
} state;
};

View File

@ -7,6 +7,7 @@
#include <carla/client/Actor.h>
#include <carla/client/TrafficLight.h>
#include <carla/client/Vehicle.h>
#include <carla/client/Walker.h>
#include <carla/rpc/TrafficLightState.h>
#include <boost/python/suite/indexing/vector_indexing_suite.hpp>
@ -74,6 +75,12 @@ void export_actor() {
.def(self_ns::str(self_ns::self))
;
class_<cc::Walker, bases<cc::Actor>, boost::noncopyable, boost::shared_ptr<cc::Walker>>("Walker", no_init)
.def("apply_control", &cc::Walker::ApplyControl, (arg("control")))
.def("get_control", &cc::Walker::GetWalkerControl)
.def(self_ns::str(self_ns::self))
;
enum_<cr::TrafficLightState>("TrafficLightState")
.value("Off", cr::TrafficLightState::Off)
.value("Red", cr::TrafficLightState::Red)

View File

@ -5,6 +5,7 @@
// For a copy, see <https://opensource.org/licenses/MIT>.
#include <carla/rpc/VehicleControl.h>
#include <carla/rpc/WalkerControl.h>
#include <ostream>
@ -23,12 +24,19 @@ namespace rpc {
return out;
}
std::ostream &operator<<(std::ostream &out, const WalkerControl &control) {
out << "WalkerControl(direction=" << control.direction
<< ", speed=" << control.speed << ')';
return out;
}
} // namespace rpc
} // namespace carla
void export_control() {
using namespace boost::python;
namespace cr = carla::rpc;
namespace cg = carla::geom;
class_<cr::VehicleControl>("VehicleControl")
.def(init<float, float, float, bool, bool, bool, int>(
@ -50,4 +58,15 @@ void export_control() {
.def("__ne__", &cr::VehicleControl::operator!=)
.def(self_ns::str(self_ns::self))
;
class_<cr::WalkerControl>("WalkerControl")
.def(init<cg::Vector3D, float>(
(arg("direction")=cg::Vector3D{1.0f, 0.0f, 0.0f},
arg("speed")=0.0f)))
.def_readwrite("direction", &cr::WalkerControl::direction)
.def_readwrite("speed", &cr::WalkerControl::speed)
.def("__eq__", &cr::WalkerControl::operator==)
.def("__ne__", &cr::WalkerControl::operator!=)
.def(self_ns::str(self_ns::self))
;
}

View File

@ -407,6 +407,40 @@ void UActorBlueprintFunctionLibrary::MakeVehicleDefinitions(
FillActorDefinitionArray(ParameterArray, Definitions, &MakeVehicleDefinition);
}
void UActorBlueprintFunctionLibrary::MakePedestrianDefinition(
const FPedestrianParameters &Parameters,
bool &Success,
FActorDefinition &Definition)
{
/// @todo We need to validate here the params.
FillIdAndTags(Definition, TEXT("walker"), TEXT("pedestrian"), Parameters.Id);
AddRecommendedValuesForActorRoleName(Definition, {TEXT("pedestrian")});
Definition.Class = Parameters.Class;
auto GetGender = [](EPedestrianGender Value) {
switch (Value)
{
case EPedestrianGender::Female: return TEXT("female");
case EPedestrianGender::Male: return TEXT("male");
default: return TEXT("other");
}
};
Definition.Attributes.Emplace(FActorAttribute{
TEXT("gender"),
EActorAttributeType::String,
GetGender(Parameters.Gender)});
Success = CheckActorDefinition(Definition);
}
void UActorBlueprintFunctionLibrary::MakePedestrianDefinitions(
const TArray<FPedestrianParameters> &ParameterArray,
TArray<FActorDefinition> &Definitions)
{
FillActorDefinitionArray(ParameterArray, Definitions, &MakePedestrianDefinition);
}
/// ============================================================================
/// -- Helpers to retrieve attribute values ------------------------------------
/// ============================================================================

View File

@ -8,7 +8,8 @@
#include "Carla/Actor/ActorDefinition.h"
#include "Carla/Actor/ActorDescription.h"
#include "Carla/Vehicle/CarlaWheeledVehicle.h"
#include "Carla/Actor/PedestrianParameters.h"
#include "Carla/Actor/VehicleParameters.h"
#include "Kismet/BlueprintFunctionLibrary.h"
@ -17,30 +18,6 @@
class ASceneCaptureSensor;
struct FLidarDescription;
USTRUCT(BlueprintType)
struct CARLA_API FVehicleParameters
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadWrite)
FString Make;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
FString Model;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
TSubclassOf<ACarlaWheeledVehicle> Class;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
int32 NumberOfWheels = 4;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
FString ObjectType;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
TArray<FColor> RecommendedColors;
};
UCLASS()
class UActorBlueprintFunctionLibrary : public UBlueprintFunctionLibrary
{
@ -103,6 +80,17 @@ public:
const TArray<FVehicleParameters> &ParameterArray,
TArray<FActorDefinition> &Definitions);
UFUNCTION(Category = "Carla Actor", BlueprintCallable)
static void MakePedestrianDefinition(
const FPedestrianParameters &Parameters,
bool &Success,
FActorDefinition &Definition);
UFUNCTION(Category = "Carla Actor", BlueprintCallable)
static void MakePedestrianDefinitions(
const TArray<FPedestrianParameters> &ParameterArray,
TArray<FActorDefinition> &Definitions);
/// @}
/// ==========================================================================
/// @name Helpers to retrieve attribute values

View File

@ -20,6 +20,10 @@ static FActorView::ActorType FActorRegistry_GetActorType(const FActorView &View)
{
return FActorView::ActorType::Vehicle;
}
else if (nullptr != Cast<ACharacter>(View.GetActor()))
{
return FActorView::ActorType::Walker;
}
else if (nullptr != Cast<ATrafficLightBase>(View.GetActor()))
{
return FActorView::ActorType::TrafficLight;

View File

@ -21,6 +21,7 @@ public:
enum class ActorType : uint8 {
Other,
Vehicle,
Walker,
TrafficLight
};

View File

@ -0,0 +1,37 @@
// 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 "GameFramework/Character.h"
#include "PedestrianParameters.generated.h"
UENUM(BlueprintType)
enum class EPedestrianGender : uint8
{
Other UMETA(DisplayName = "Other"),
Female UMETA(DisplayName = "Female"),
Male UMETA(DisplayName = "Male"),
SIZE UMETA(Hidden),
INVALID UMETA(Hidden)
};
USTRUCT(BlueprintType)
struct CARLA_API FPedestrianParameters
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadWrite)
FString Id;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
TSubclassOf<ACharacter> Class;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
EPedestrianGender Gender = EPedestrianGender::Other;
};

View File

@ -0,0 +1,36 @@
// 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/Vehicle/CarlaWheeledVehicle.h"
#include "VehicleParameters.generated.h"
USTRUCT(BlueprintType)
struct CARLA_API FVehicleParameters
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, BlueprintReadWrite)
FString Make;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
FString Model;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
TSubclassOf<ACarlaWheeledVehicle> Class;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
int32 NumberOfWheels = 4;
/// (OPTIONAL) Use for custom classification of vehicles.
UPROPERTY(EditAnywhere, BlueprintReadWrite)
FString ObjectType;
UPROPERTY(EditAnywhere, BlueprintReadWrite)
TArray<FColor> RecommendedColors;
};

View File

@ -8,6 +8,7 @@
#include "Carla/Sensor/WorldObserver.h"
#include "Carla/Traffic/TrafficLightBase.h"
#include "Carla/Walker/WalkerController.h"
#include "CoreGlobals.h"
@ -30,6 +31,15 @@ static auto AWorldObserver_GetActorState(const FActorView &View)
state.vehicle_control = carla::rpc::VehicleControl{Vehicle->GetVehicleControl()};
}
}
else if (AType::Walker == View.GetActorType())
{
auto Walker = Cast<APawn>(View.GetActor());
auto Controller = Walker != nullptr ? Cast<AWalkerController>(Walker->GetController()) : nullptr;
if (Controller != nullptr)
{
state.walker_control = carla::rpc::WalkerControl{Controller->GetWalkerControl()};
}
}
else if (AType::TrafficLight == View.GetActorType())
{
auto TrafficLight = Cast<ATrafficLightBase>(View.GetActor());

View File

@ -11,6 +11,7 @@
#include "Carla/Util/DebugShapeDrawer.h"
#include "Carla/Util/OpenDrive.h"
#include "Carla/Vehicle/CarlaWheeledVehicle.h"
#include "Carla/Walker/WalkerController.h"
#include "GameFramework/SpectatorPawn.h"
@ -25,6 +26,7 @@
#include <carla/rpc/Server.h>
#include <carla/rpc/Transform.h>
#include <carla/rpc/VehicleControl.h>
#include <carla/rpc/WalkerControl.h>
#include <carla/rpc/WeatherParameters.h>
#include <carla/streaming/Server.h>
#include <compiler/enable-ue4-macros.h>
@ -369,6 +371,23 @@ void FTheNewCarlaServer::FPimpl::BindActions()
Vehicle->ApplyVehicleControl(Control);
});
Server.BindSync("apply_control_to_walker", [this](cr::Actor Actor, cr::WalkerControl Control) {
RequireEpisode();
auto ActorView = Episode->GetActorRegistry().Find(Actor.id);
if (!ActorView.IsValid() || ActorView.GetActor()->IsPendingKill()) {
RespondErrorStr("unable to apply control: actor not found");
}
auto Pawn = Cast<APawn>(ActorView.GetActor());
if (Pawn == nullptr) {
RespondErrorStr("unable to apply control: actor is not a walker");
}
auto Controller = Cast<AWalkerController>(Pawn->GetController());
if (Controller == nullptr) {
RespondErrorStr("unable to apply control: walker has an incompatible controller");
}
Controller->ApplyWalkerControl(Control);
});
Server.BindSync("set_actor_autopilot", [this](cr::Actor Actor, bool bEnabled) {
RequireEpisode();
auto ActorView = Episode->GetActorRegistry().Find(Actor.id);

View File

@ -0,0 +1,21 @@
// 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 "WalkerControl.generated.h"
USTRUCT(BlueprintType)
struct CARLA_API FWalkerControl
{
GENERATED_BODY()
UPROPERTY(Category = "Walker Control", EditAnywhere, BlueprintReadWrite)
FVector Direction = {1.0f, 0.0f, 0.0f};
UPROPERTY(Category = "Walker Control", EditAnywhere, BlueprintReadWrite)
float Speed = 0.0f;
};

View File

@ -0,0 +1,50 @@
// 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 "Carla.h"
#include "Carla/Walker/WalkerController.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "GameFramework/Pawn.h"
AWalkerController::AWalkerController(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
PrimaryActorTick.bCanEverTick = true;
}
void AWalkerController::Possess(APawn *InPawn)
{
Super::Possess(InPawn);
auto *Character = Cast<ACharacter>(InPawn);
if (Character == nullptr)
{
UE_LOG(LogCarla, Error, TEXT("Walker is not a character!"));
return;
}
auto *MovementComponent = Character->GetCharacterMovement();
if (MovementComponent == nullptr)
{
UE_LOG(LogCarla, Error, TEXT("Walker missing character movement component!"));
return;
}
MovementComponent->MaxWalkSpeed = GetMaximumWalkSpeed();
}
void AWalkerController::Tick(float DeltaSeconds)
{
Super::Tick(DeltaSeconds);
auto *Pawn = GetPawn();
if (Pawn != nullptr)
{
Pawn->AddMovementInput(Control.Direction, Control.Speed / GetMaximumWalkSpeed());
}
}

View File

@ -0,0 +1,52 @@
// 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/Walker/WalkerControl.h"
#include "CoreMinimal.h"
#include "GameFramework/Controller.h"
#include "WalkerController.generated.h"
UCLASS()
class CARLA_API AWalkerController : public AController
{
GENERATED_BODY()
public:
AWalkerController(const FObjectInitializer& ObjectInitializer);
void Possess(APawn *InPawn) override;
void Tick(float DeltaSeconds) override;
/// Maximum walk speed allowed in centimetres per second.
UFUNCTION(BlueprintCallable)
float GetMaximumWalkSpeed() const
{
return 4096.0f; // ~147 km/h
}
UFUNCTION(BlueprintCallable)
void ApplyWalkerControl(const FWalkerControl &InControl)
{
Control = InControl;
}
UFUNCTION(BlueprintCallable)
const FWalkerControl &GetWalkerControl() const
{
return Control;
}
private:
UPROPERTY(VisibleAnywhere)
FWalkerControl Control;
};