Add autopilot mode to player

This commit is contained in:
nsubiron 2017-09-04 16:36:30 +01:00
parent 7d4c0646c8
commit 766508eb86
7 changed files with 172 additions and 154 deletions

View File

@ -89,7 +89,7 @@ void AWheeledVehicleAIController::Possess(APawn *aPawn)
void AWheeledVehicleAIController::Tick(const float DeltaTime)
{
Super::PlayerTick(DeltaTime);
Super::Tick(DeltaTime);
if (bAutopilotEnabled) {
TickAutopilotController();
@ -103,6 +103,17 @@ void AWheeledVehicleAIController::Tick(const float DeltaTime)
void AWheeledVehicleAIController::SetAutopilot(const bool Enabled)
{
bAutopilotEnabled = Enabled;
// Reset state.
Vehicle->SetSteeringInput(0.0f);
Vehicle->SetThrottleInput(0.0f);
Vehicle->SetBrakeInput(0.0f);
Vehicle->SetReverse(false);
Vehicle->SetHandbrakeInput(false);
TrafficLightState = ETrafficLightState::Green;
decltype(TargetLocations) EmptyQueue;
TargetLocations.swap(EmptyQueue);
// We need reverse-as-brake behaviour when the AI is enabled only.
auto *MovementComponent = Vehicle->GetVehicleMovementComponent();
check(MovementComponent != nullptr);

View File

@ -155,14 +155,23 @@ void ACarlaGameModeBase::BeginPlay()
UE_LOG(LogCarla, Error, TEXT("Missing dynamic weather actor!"));
}
// Find road map.
TActorIterator<ACityMapGenerator> It(GetWorld());
URoadMap *RoadMap = (It ? It->GetRoadMap() : nullptr);
auto Controller = Cast<AWheeledVehicleAIController>(PlayerController);
if (Controller != nullptr) {
Controller->SetRoadMap(RoadMap);
} else {
UE_LOG(LogCarla, Error, TEXT("Player controller is not a AWheeledVehicleAIController!"));
}
// Setup other vehicles.
if (VehicleSpawner != nullptr) {
VehicleSpawner->SetNumberOfVehicles(CarlaSettings.NumberOfVehicles);
VehicleSpawner->SetSeed(CarlaSettings.SeedVehicles);
TActorIterator<ACityMapGenerator> It(GetWorld());
if (It) {
VehicleSpawner->SetRoadMap(It->GetRoadMap());
}
VehicleSpawner->SetRoadMap(RoadMap);
} else {
UE_LOG(LogCarla, Error, TEXT("Missing vehicle spawner actor!"));
}

View File

@ -19,7 +19,6 @@ ACarlaVehicleController::ACarlaVehicleController(const FObjectInitializer& Objec
Super(ObjectInitializer)
{
PrimaryActorTick.bCanEverTick = true;
PrimaryActorTick.TickGroup = TG_PrePhysics;
}
ACarlaVehicleController::~ACarlaVehicleController() {}
@ -28,31 +27,13 @@ ACarlaVehicleController::~ACarlaVehicleController() {}
// -- APlayerController --------------------------------------------------------
// =============================================================================
void ACarlaVehicleController::SetupInputComponent()
{
Super::SetupInputComponent();
if (InputComponent != nullptr) {
InputComponent->BindAction("ToggleManualMode", IE_Pressed, this, &ACarlaVehicleController::ToggleManualMode);
}
}
void ACarlaVehicleController::Possess(APawn *aPawn)
{
Super::Possess(aPawn);
if (IsPossessingAVehicle()) {
UE_LOG(LogCarla, Error, TEXT("Controller already possessing a vehicle!"));
return;
}
Vehicle = Cast<ACarlaWheeledVehicle>(aPawn);
if (Vehicle != nullptr) {
// Bind hit events.
aPawn->OnActorHit.AddDynamic(this, &ACarlaVehicleController::OnCollisionEvent);
// Get vehicle movement component.
auto *MovementComponent = Vehicle->GetVehicleMovementComponent();
check(MovementComponent != nullptr);
MovementComponent->bReverseAsBrake = false;
// Get custom player state.
CarlaPlayerState = Cast<ACarlaPlayerState>(PlayerState);
check(CarlaPlayerState != nullptr);
@ -66,6 +47,10 @@ void ACarlaVehicleController::Possess(APawn *aPawn)
}
}
// =============================================================================
// -- AActor -------------------------------------------------------------------
// =============================================================================
void ACarlaVehicleController::BeginPlay()
{
Super::BeginPlay();
@ -85,18 +70,14 @@ void ACarlaVehicleController::BeginPlay()
}
}
}
TActorIterator<ACityMapGenerator> It(GetWorld());
if (It) {
RoadMap = It->GetRoadMap();
}
}
void ACarlaVehicleController::Tick(float DeltaTime)
{
Super::PlayerTick(DeltaTime);
Super::Tick(DeltaTime);
if (IsPossessingAVehicle()) {
auto Vehicle = GetPossessedVehicle();
CarlaPlayerState->UpdateTimeStamp(DeltaTime);
const FVector PreviousSpeed = CarlaPlayerState->ForwardSpeed * CarlaPlayerState->GetOrientation();
CarlaPlayerState->Transform = Vehicle->GetActorTransform();
@ -142,23 +123,6 @@ void ACarlaVehicleController::AddSceneCaptureCamera(
*PostProcessEffect::ToString(Camera->GetPostProcessEffect()));
}
// =============================================================================
// -- Manual mode --------------------------------------------------------------
// =============================================================================
void ACarlaVehicleController::SetManualMode(bool On)
{
if (On != bManualMode) {
bManualMode = On;
SetupControllerInput();
}
}
void ACarlaVehicleController::ToggleManualMode()
{
SetManualMode(!bManualMode);
}
// =============================================================================
// -- Events -------------------------------------------------------------------
// =============================================================================
@ -170,29 +134,9 @@ void ACarlaVehicleController::OnCollisionEvent(
const FHitResult& Hit)
{
// Register collision only if we are moving faster than 1 km/h.
if (FMath::Abs(Vehicle->GetVehicleForwardSpeed()) > 1.0f) {
CarlaPlayerState->RegisterCollision(Actor, OtherActor, NormalImpulse, Hit);
}
}
// =============================================================================
// -- Input bindings -----------------------------------------------------------
// =============================================================================
void ACarlaVehicleController::SetupControllerInput()
{
check(InputComponent != nullptr);
check(IsPossessingAVehicle());
// Vehicle movement.
if (IsInManualMode()) {
InputComponent->BindAxis("MoveForward", Vehicle, &ACarlaWheeledVehicle::SetThrottleInput);
InputComponent->BindAxis("MoveRight", Vehicle, &ACarlaWheeledVehicle::SetSteeringInput);
InputComponent->BindAxis("Brake", Vehicle, &ACarlaWheeledVehicle::SetBrakeInput);
InputComponent->BindAction("ToggleReverse", IE_Pressed, Vehicle, &ACarlaWheeledVehicle::ToggleReverse);
InputComponent->BindAction("Handbrake", IE_Pressed, Vehicle, &ACarlaWheeledVehicle::HoldHandbrake);
InputComponent->BindAction("Handbrake", IE_Released, Vehicle, &ACarlaWheeledVehicle::ReleaseHandbrake);
} else {
UE_LOG(LogCarla, Error, TEXT("Not implemented")); /// @todo
if (FMath::Abs(GetPossessedVehicle()->GetVehicleForwardSpeed()) > 1.0f) {
CarlaPlayerState->RegisterCollision(Actor, OtherActor, NormalImpulse, Hit);
}
}
@ -202,11 +146,14 @@ void ACarlaVehicleController::SetupControllerInput()
void ACarlaVehicleController::IntersectPlayerWithRoadMap()
{
auto RoadMap = GetRoadMap();
if (RoadMap == nullptr) {
UE_LOG(LogCarla, Error, TEXT("Controller doesn't have a road map"));
UE_LOG(LogCarla, Error, TEXT("Controller doesn't have a road map!"));
return;
}
check(IsPossessingAVehicle());
auto Vehicle = GetPossessedVehicle();
constexpr float ChecksPerCentimeter = 0.1f;
auto Result = RoadMap->Intersect(
Vehicle->GetActorTransform(),

View File

@ -2,21 +2,17 @@
#pragma once
#include "PlayerCameraController.h"
#include "WheeledVehicleController.h"
#include "CarlaVehicleController.generated.h"
class ACarlaHUD;
class ACarlaPlayerState;
class ACarlaWheeledVehicle;
class ASceneCaptureCamera;
class URoadMap;
struct FCameraDescription;
/**
*
*/
/// The CARLA player controller.
UCLASS()
class CARLA_API ACarlaVehicleController : public APlayerCameraController
class CARLA_API ACarlaVehicleController : public AWheeledVehicleController
{
GENERATED_BODY()
@ -37,10 +33,15 @@ public:
/// @{
public:
virtual void SetupInputComponent() override;
virtual void Possess(APawn *aPawn) override;
/// @}
// ===========================================================================
/// @name AActor overrides
// ===========================================================================
/// @{
public:
virtual void BeginPlay() override;
virtual void Tick(float DeltaTime) override;
@ -52,16 +53,6 @@ public:
/// @{
public:
bool IsPossessingAVehicle() const
{
return Vehicle != nullptr;
}
ACarlaWheeledVehicle *GetPossessedVehicle() const
{
return Vehicle;
}
const ACarlaPlayerState &GetPlayerState() const
{
return *CarlaPlayerState;
@ -78,26 +69,6 @@ public:
const FCameraDescription &CameraDescription,
const FCameraPostProcessParameters *OverridePostProcessParameters = nullptr);
/// @}
// ===========================================================================
/// @name Manual mode
///
/// Manual mode refers here to whether the car can be controlled from the
/// server side. This is disabled by default when the client connects since it
/// interferes with the client input.
// ===========================================================================
/// @{
public:
bool IsInManualMode() const
{
return bManualMode;
}
void SetManualMode(bool On);
void ToggleManualMode();
/// @}
// ===========================================================================
/// @name Events
@ -114,16 +85,7 @@ private:
/// @}
// ===========================================================================
/// @name Input bindings
// ===========================================================================
/// @{
private:
void SetupControllerInput();
/// @}
// ===========================================================================
/// @name Other
/// @name Private methods
// ===========================================================================
/// @{
private:
@ -136,20 +98,9 @@ private:
// ===========================================================================
private:
/// Manual input mode. Not to be mistaken with the vehicle manual/automatic
/// transmission.
UPROPERTY()
bool bManualMode = false;
UPROPERTY()
ACarlaWheeledVehicle *Vehicle;
UPROPERTY()
TArray<ASceneCaptureCamera *> SceneCaptureCameras;
UPROPERTY()
URoadMap *RoadMap;
// Cast for quick access to the custom player state.
UPROPERTY()
ACarlaPlayerState *CarlaPlayerState;

View File

@ -45,7 +45,7 @@ void MockGameController::RegisterPlayer(AController &NewPlayer)
{
ACarlaVehicleController *VehicleController = Cast<ACarlaVehicleController>(&NewPlayer);
if (VehicleController != nullptr) {
VehicleController->SetManualMode(true);
VehicleController->EnableUserInput(true);
} else {
UE_LOG(LogCarla, Warning, TEXT("Player is not a ACarlaVehicleController"));
}

View File

@ -1,7 +1,7 @@
// CARLA, Copyright (C) 2017 Computer Vision Center (CVC)
#include "Carla.h"
#include "PlayerCameraController.h"
#include "WheeledVehicleController.h"
#include "Camera/CameraComponent.h"
#include "GameFramework/Pawn.h"
@ -11,7 +11,7 @@
// -- Constructor and destructor -----------------------------------------------
// =============================================================================
APlayerCameraController::APlayerCameraController(const FObjectInitializer& ObjectInitializer) :
AWheeledVehicleController::AWheeledVehicleController(const FObjectInitializer& ObjectInitializer) :
Super(ObjectInitializer)
{
bAutoManageActiveCameraTarget = false;
@ -46,13 +46,13 @@ APlayerCameraController::APlayerCameraController(const FObjectInitializer& Objec
OnBoardCamera->FieldOfView = 100.f;
}
APlayerCameraController::~APlayerCameraController() {}
AWheeledVehicleController::~AWheeledVehicleController() {}
// =============================================================================
// -- AActor -------------------------------------------------------------------
// =============================================================================
void APlayerCameraController::BeginPlay()
void AWheeledVehicleController::BeginPlay()
{
Super::BeginPlay();
EnableOnBoardCamera(bOnBoardCameraIsActive, true);
@ -62,19 +62,28 @@ void APlayerCameraController::BeginPlay()
// -- APlayerController --------------------------------------------------------
// =============================================================================
void APlayerCameraController::SetupInputComponent()
void AWheeledVehicleController::SetupInputComponent()
{
Super::SetupInputComponent();
if (InputComponent != nullptr) {
InputComponent->BindAxis("CameraZoom", this, &APlayerCameraController::ChangeCameraZoom);
InputComponent->BindAxis("CameraUp", this, &APlayerCameraController::ChangeCameraUp);
InputComponent->BindAxis("CameraRight", this, &APlayerCameraController::ChangeCameraRight);
InputComponent->BindAction("ToggleCamera", IE_Pressed, this, &APlayerCameraController::ToggleCamera);
InputComponent->BindAction("RestartLevel", IE_Pressed, this, &APlayerCameraController::RestartLevel);
// Camera movement.
InputComponent->BindAxis("CameraZoom", this, &AWheeledVehicleController::ChangeCameraZoom);
InputComponent->BindAxis("CameraUp", this, &AWheeledVehicleController::ChangeCameraUp);
InputComponent->BindAxis("CameraRight", this, &AWheeledVehicleController::ChangeCameraRight);
InputComponent->BindAction("ToggleCamera", IE_Pressed, this, &AWheeledVehicleController::ToggleCamera);
InputComponent->BindAction("RestartLevel", IE_Pressed, this, &AWheeledVehicleController::RestartLevel);
// Vehicle movement.
InputComponent->BindAction("ToggleAutopilot", IE_Pressed, this, &AWheeledVehicleAIController::ToggleAutopilot);
InputComponent->BindAxis("MoveForward", this, &AWheeledVehicleController::SetThrottleInput);
InputComponent->BindAxis("MoveRight", this, &AWheeledVehicleController::SetSteeringInput);
InputComponent->BindAxis("Brake", this, &AWheeledVehicleController::SetBrakeInput);
InputComponent->BindAction("ToggleReverse", IE_Pressed, this, &AWheeledVehicleController::ToggleReverse);
InputComponent->BindAction("Handbrake", IE_Pressed, this, &AWheeledVehicleController::HoldHandbrake);
InputComponent->BindAction("Handbrake", IE_Released, this, &AWheeledVehicleController::ReleaseHandbrake);
}
}
void APlayerCameraController::Possess(APawn *aPawn)
void AWheeledVehicleController::Possess(APawn *aPawn)
{
Super::Possess(aPawn);
SpringArm->AttachToComponent(
@ -85,7 +94,7 @@ void APlayerCameraController::Possess(APawn *aPawn)
FAttachmentTransformRules::KeepRelativeTransform);
}
void APlayerCameraController::CalcCamera(float DeltaTime, FMinimalViewInfo& OutResult)
void AWheeledVehicleController::CalcCamera(float DeltaTime, FMinimalViewInfo& OutResult)
{
if (bOnBoardCameraIsActive) {
OnBoardCamera->GetCameraView(DeltaTime, OutResult);
@ -94,30 +103,42 @@ void APlayerCameraController::CalcCamera(float DeltaTime, FMinimalViewInfo& OutR
}
}
// =============================================================================
// -- User input ---------------------------------------------------------------
// =============================================================================
void AWheeledVehicleController::EnableUserInput(const bool On)
{
bAllowUserInput = On;
if (bAllowUserInput) {
Super::SetAutopilot(false);
}
}
// =============================================================================
// -- Camera movement methods --------------------------------------------------
// =============================================================================
void APlayerCameraController::APlayerCameraController::ChangeCameraZoom(float Value)
void AWheeledVehicleController::AWheeledVehicleController::ChangeCameraZoom(float Value)
{
SpringArm->TargetArmLength = FMath::Clamp(SpringArm->TargetArmLength + Value, 150.0f, 2e4f);
}
void APlayerCameraController::ChangeCameraUp(float Value)
void AWheeledVehicleController::ChangeCameraUp(float Value)
{
auto Rotation = SpringArm->GetRelativeTransform().Rotator();
Rotation.Pitch = FMath::Clamp(Rotation.Pitch - Value, -85.0f, 0.0f);
SpringArm->SetRelativeRotation(Rotation);
}
void APlayerCameraController::ChangeCameraRight(float Value)
void AWheeledVehicleController::ChangeCameraRight(float Value)
{
auto Rotation = SpringArm->GetRelativeTransform().Rotator();
Rotation.Yaw -= Value;
SpringArm->SetRelativeRotation(Rotation);
}
void APlayerCameraController::EnableOnBoardCamera(const bool bEnable, const bool bForce)
void AWheeledVehicleController::EnableOnBoardCamera(const bool bEnable, const bool bForce)
{
if (bForce || (bOnBoardCameraIsActive != bEnable)) {
bOnBoardCameraIsActive = bEnable;
@ -130,3 +151,49 @@ void APlayerCameraController::EnableOnBoardCamera(const bool bEnable, const bool
}
}
}
// =============================================================================
// -- Vehicle movement methods -------------------------------------------------
// =============================================================================
void AWheeledVehicleController::SetThrottleInput(const float Value)
{
if (bAllowUserInput && !IsAutopilotEnabled()) {
GetPossessedVehicle()->SetThrottleInput(Value);
}
}
void AWheeledVehicleController::SetSteeringInput(const float Value)
{
if (bAllowUserInput && !IsAutopilotEnabled()) {
GetPossessedVehicle()->SetSteeringInput(Value);
}
}
void AWheeledVehicleController::SetBrakeInput(const float Value)
{
if (bAllowUserInput && !IsAutopilotEnabled()) {
GetPossessedVehicle()->SetBrakeInput(Value);
}
}
void AWheeledVehicleController::ToggleReverse()
{
if (bAllowUserInput && !IsAutopilotEnabled()) {
GetPossessedVehicle()->ToggleReverse();
}
}
void AWheeledVehicleController::HoldHandbrake()
{
if (bAllowUserInput && !IsAutopilotEnabled()) {
GetPossessedVehicle()->HoldHandbrake();
}
}
void AWheeledVehicleController::ReleaseHandbrake()
{
if (bAllowUserInput && !IsAutopilotEnabled()) {
GetPossessedVehicle()->ReleaseHandbrake();
}
}

View File

@ -2,16 +2,16 @@
#pragma once
#include "GameFramework/PlayerController.h"
#include "PlayerCameraController.generated.h"
#include "CoreMinimal.h"
#include "AI/WheeledVehicleAIController.h"
#include "WheeledVehicleController.generated.h"
class UCameraComponent;
class USpringArmComponent;
/// Adds a camera to the player that can rotate, zoom in, and zoom out. It also
/// binds the action for restarting the current level.
/// Wheeled vehicle controller with cameras and optional user input.
UCLASS()
class CARLA_API APlayerCameraController : public APlayerController
class CARLA_API AWheeledVehicleController : public AWheeledVehicleAIController
{
GENERATED_BODY()
@ -21,9 +21,9 @@ class CARLA_API APlayerCameraController : public APlayerController
/// @{
public:
APlayerCameraController(const FObjectInitializer& ObjectInitializer);
AWheeledVehicleController(const FObjectInitializer& ObjectInitializer);
~APlayerCameraController();
~AWheeledVehicleController();
/// @}
// ===========================================================================
@ -49,7 +49,18 @@ public:
/// @}
// ===========================================================================
/// @name Camera input
/// @name User input
// ===========================================================================
/// @{
public:
/// Enable keyboard control.
UFUNCTION(Category = "Vehicle User Input", BlueprintCallable)
void EnableUserInput(bool Enable);
/// @}
// ===========================================================================
/// @name Camera movement
// ===========================================================================
/// @{
private:
@ -67,6 +78,25 @@ private:
EnableOnBoardCamera(!bOnBoardCameraIsActive);
}
/// @}
// ===========================================================================
/// @name Vehicle movement
// ===========================================================================
/// @{
private:
void SetThrottleInput(float Value);
void SetSteeringInput(float Value);
void SetBrakeInput(float Value);
void ToggleReverse();
void HoldHandbrake();
void ReleaseHandbrake();
/// @}
// ===========================================================================
// -- Member variables -------------------------------------------------------
@ -84,4 +114,7 @@ private:
UPROPERTY()
bool bOnBoardCameraIsActive = false;
UPROPERTY(Category = "Vehicle User Input", VisibleAnywhere)
bool bAllowUserInput = false;
};