Basic walker AI

This commit is contained in:
nsubiron 2017-06-03 18:11:23 +01:00
parent 0beacfdd83
commit 6b5fcdf546
4 changed files with 151 additions and 5 deletions

View File

@ -4,6 +4,120 @@
#include "WalkerAIController.h"
#include "Navigation/CrowdFollowingComponent.h"
#include "Perception/AIPerceptionComponent.h"
#include "Perception/AISenseConfig_Sight.h"
#include "Perception/AISense_Sight.h"
#include "WheeledVehicle.h"
#include "WheeledVehicleMovementComponent.h"
#ifdef CARLA_AI_WALKERS_EXTRA_LOG
# define LOG_AI_WALKER(Verbosity, Text) UE_LOG(LogCarla, Verbosity, Text, *GetPawn()->GetName());
#else
# define LOG_AI_WALKER(Verbosity, Text)
#endif // CARLA_AI_WALKERS_EXTRA_LOG
AWalkerAIController::AWalkerAIController(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer.SetDefaultSubobjectClass<UCrowdFollowingComponent>(TEXT("PathFollowingComponent"))) {}
: Super(ObjectInitializer.SetDefaultSubobjectClass<UCrowdFollowingComponent>(TEXT("PathFollowingComponent")))
{
PrimaryActorTick.bCanEverTick = true;
PrimaryActorTick.TickInterval = 5.0f; // seconds.
auto Perception = CreateDefaultSubobject<UAIPerceptionComponent>(TEXT("AIPerception Component"));
check(Perception != nullptr);
SetPerceptionComponent(*Perception);
SightConfiguration = CreateDefaultSubobject<UAISenseConfig_Sight>(TEXT("SightConfiguration"));
SightConfiguration->SightRadius = 800.0f;
SightConfiguration->LoseSightRadius = (SightConfiguration->SightRadius + 100.0f);
SightConfiguration->PeripheralVisionAngleDegrees = 90.0f;
SightConfiguration->DetectionByAffiliation.bDetectEnemies = true;
SightConfiguration->DetectionByAffiliation.bDetectNeutrals = true;
SightConfiguration->DetectionByAffiliation.bDetectFriendlies = true;
Perception->ConfigureSense(*SightConfiguration);
Perception->SetDominantSense(SightConfiguration->GetSenseImplementation());
Perception->OnPerceptionUpdated.AddDynamic(this, &AWalkerAIController::SenseActors);
}
void AWalkerAIController::Tick(float DeltaSeconds)
{
Super::Tick(DeltaSeconds);
switch (GetMoveStatus()) {
case EPathFollowingStatus::Idle:
case EPathFollowingStatus::Waiting:
LOG_AI_WALKER(Warning, TEXT("Walker %s is stuck!"));
bIsStuck = true;
break;
case EPathFollowingStatus::Paused:
LOG_AI_WALKER(Log, TEXT("Walker %s is paused"));
bIsPaused = true;
TryResumeMovement();
break;
};
}
FPathFollowingRequestResult AWalkerAIController::MoveTo(
const FAIMoveRequest& MoveRequest,
FNavPathSharedPtr* OutPath)
{
bIsStuck = false;
LOG_AI_WALKER(Log, TEXT("Walker %s requested to move"));
return Super::MoveTo(MoveRequest, OutPath);
}
static bool VehicleIsMoving(const AWheeledVehicle *Vehicle)
{
const auto *MovementComponent =
(Vehicle != nullptr ? Vehicle->GetVehicleMovementComponent() : nullptr);
return
(MovementComponent != nullptr) &&
(MovementComponent->GetForwardSpeed() > 0.0f);
}
static bool ContainsAMovingVehicle(const TArray<AActor *> &Actors)
{
for (auto *Actor : Actors) {
if (VehicleIsMoving(Cast<AWheeledVehicle>(Actor))) {
return true;
}
}
return false;
}
void AWalkerAIController::SenseActors(const TArray<AActor *> Actors)
{
if (!bIsPaused && ContainsAMovingVehicle(Actors)) {
TryPauseMovement();
}
}
void AWalkerAIController::TryResumeMovement()
{
auto MoveRequestID = GetCurrentMoveRequestID();
if (MoveRequestID == FAIRequestID()) { // equals invalid request.
LOG_AI_WALKER(Error, TEXT("Walker %s: Invalid move ID"));
} else {
if (!ResumeMove(MoveRequestID)) {
LOG_AI_WALKER(Error, TEXT("Unable to resume walker %s move"));
} else {
LOG_AI_WALKER(Log, TEXT("Resume walker %s's move"));
bIsPaused = false;
}
}
}
void AWalkerAIController::TryPauseMovement()
{
auto MoveRequestID = GetCurrentMoveRequestID();
if (MoveRequestID == FAIRequestID()) { // equals invalid request.
LOG_AI_WALKER(Error, TEXT("Walker %s: Invalid move ID"));
} else {
if (!PauseMove(MoveRequestID)) {
LOG_AI_WALKER(Error, TEXT("Unable to pause walker %s move"));
} else {
LOG_AI_WALKER(Log, TEXT("Pause walker %s's move"));
bIsPaused = true;
}
}
}

View File

@ -5,6 +5,8 @@
#include "AIController.h"
#include "WalkerAIController.generated.h"
class UAISenseConfig_Sight;
UCLASS()
class CARLA_API AWalkerAIController : public AAIController
{
@ -12,5 +14,34 @@ class CARLA_API AWalkerAIController : public AAIController
public:
AWalkerAIController(const FObjectInitializer& ObjectInitializer = FObjectInitializer::Get());
AWalkerAIController(const FObjectInitializer& ObjectInitializer);
virtual void Tick(float DeltaSeconds) override;
virtual FPathFollowingRequestResult MoveTo(
const FAIMoveRequest& MoveRequest,
FNavPathSharedPtr* OutPath = nullptr) override;
UFUNCTION(BlueprintCallable)
void SenseActors(TArray<AActor *> Actors);
bool WalkerIsStuck() const
{
return bIsStuck;
}
private:
void TryResumeMovement();
void TryPauseMovement();
UPROPERTY(Category = "Walker AI Controller", VisibleAnywhere)
UAISenseConfig_Sight *SightConfiguration;
UPROPERTY(VisibleAnywhere)
bool bIsPaused = false;
UPROPERTY(VisibleAnywhere)
bool bIsStuck = false;
};

View File

@ -111,7 +111,7 @@ void AWalkerSpawnerBase::Tick(float DeltaTime)
auto Walker = WalkersBlackList[Index];
auto Controller = GetController(Walker);
if ((Controller == nullptr) ||
(Controller->GetMoveStatus() != EPathFollowingStatus::Moving)) {
(Controller->WalkerIsStuck())) {
WalkersBlackList.RemoveAtSwap(Index);
if (Walker != nullptr) {
Walker->Destroy();
@ -129,7 +129,7 @@ void AWalkerSpawnerBase::Tick(float DeltaTime)
if (Walker != nullptr) {
Walker->Destroy();
}
} else if (Controller->GetMoveStatus() != EPathFollowingStatus::Moving) {
} else if (Controller->WalkerIsStuck()) {
TrySetDestination(*Walker);
WalkersBlackList.Add(Walker);
Walkers.RemoveAtSwap(Index);

View File

@ -11,9 +11,10 @@
DECLARE_LOG_CATEGORY_EXTERN(LogCarla, Log, All);
DECLARE_LOG_CATEGORY_EXTERN(LogCarlaServer, Log, All);
// Options to compile with extra debug options.
// Options to compile with extra debug log.
#if WITH_EDITOR
// #define CARLA_AI_VEHICLES_EXTRA_LOG
// #define CARLA_AI_WALKERS_EXTRA_LOG
// #define CARLA_ROAD_GENERATOR_EXTRA_LOG /// @todo #1 Crashes in Linux.
// #define CARLA_SERVER_EXTRA_LOG
// #define CARLA_TAGGER_EXTRA_LOG