Make a base class for wheeled vehicles

This commit is contained in:
nsubiron 2017-08-31 13:34:42 +01:00
parent 4fc0fe7b89
commit b22754b7fa
12 changed files with 353 additions and 365 deletions

View File

@ -18,16 +18,10 @@
#include "MapGen/RoadMap.h"
// Find first component of type road.
AAICarlaVehicleController::AAICarlaVehicleController() :
Super(),
MovementComponent(nullptr),
TrafficLightStop(false)
{
TrafficLightStop(false) {
bAutoManageActiveCameraTarget = false;
//MAX_SPEED = ((rand() * 10) - 5) + MAX_SPEED;
}
@ -38,10 +32,11 @@ AAICarlaVehicleController::~AAICarlaVehicleController() {}
// -- APlayerController --------------------------------------------------------
// =============================================================================
void AAICarlaVehicleController::SetupInputComponent(){ Super::SetupInputComponent(); }
void AAICarlaVehicleController::SetupInputComponent() {
Super::SetupInputComponent();
}
void AAICarlaVehicleController::Possess(APawn *aPawn)
{
void AAICarlaVehicleController::Possess(APawn *aPawn) {
Super::Possess(aPawn);
if (IsPossessingAVehicle()) {
@ -75,56 +70,33 @@ void AAICarlaVehicleController::Possess(APawn *aPawn)
}
void AAICarlaVehicleController::BeginPlay()
{
void AAICarlaVehicleController::BeginPlay() {
TActorIterator<ACityMapGenerator> It(GetWorld());
if (It) {
RoadMap = It->GetRoadMap();
}
}
bool AAICarlaVehicleController::RayTrace(
UWorld *World,
const FVector &Start,
const FVector &End,
bool &Stop)
{
//FHitResult Hit;
const FVector &End) {
FHitResult OutHit;
static FName TraceTag = FName(TEXT("VehicleTrace"));
//World->DebugDrawTraceTag = TraceTag;
FCollisionQueryParams collisionParams (TraceTag, true);
FCollisionQueryParams collisionParams(TraceTag, true);
collisionParams.AddIgnoredActor(this);
const bool Success = World->LineTraceSingleByObjectType(
OutHit,
Start,
End,
FCollisionObjectQueryParams(ECollisionChannel::ECC_WorldDynamic),
FCollisionObjectQueryParams(FCollisionObjectQueryParams::AllDynamicObjects),
collisionParams);
if (Success) {
if (OutHit.bBlockingHit)
//for (FHitResult &Item : OutHits) {
//if (ATagger::MatchComponent(*Item.Component, ECityObjectLabel::Vehicles) || ATagger::MatchComponent(*Item.Component, ECityObjectLabel::Pedestrians)) {
Stop = true;
return true;
//}
//}
}
return false;
return Success && OutHit.bBlockingHit;
}
void AAICarlaVehicleController::Tick(float DeltaTime){
void AAICarlaVehicleController::Tick(float DeltaTime) {
Super::Tick(DeltaTime);
check(MovementComponent != nullptr);
@ -136,58 +108,45 @@ void AAICarlaVehicleController::Tick(float DeltaTime){
FRoadMapPixelData roadData = RoadMap->GetDataAt(GetPawn()->GetActorLocation());
float steering = 2.0, throttle = 1.0f;//, brake = 0.0f;
FVector direction;
if (route.Num() > 0){
if (route.Num() > 0) {
steering = GoTo(route[route_it], direction);
}
else{
} else {
steering = CalcStreeringValue(direction);
}
auto speed = MovementComponent->GetForwardSpeed() * 0.036f;
FVector forwardVector = GetPawn()->GetActorForwardVector().GetSafeNormal();
float distance;
if (speed < 10.0f) distance = 50.0f;
else {
distance = pow(speed/10.0f,2) * 100.0f;
if (speed < 10.0f) {distance = 50.0f;} else {
distance = pow(speed / 10.0f, 2) * 100.0f;
}
const FVector StartCenter = GetPawn()->GetActorLocation() + (forwardVector * (250.0f + VehicleBounds->GetScaledBoxExtent().X/2.0f)) + FVector(0.0f, 0.0f, 50.0f);
const FVector EndCenter = StartCenter + direction * (distance + VehicleBounds->GetScaledBoxExtent().X/2.0f);
const FVector StartCenter = GetPawn()->GetActorLocation() + (forwardVector * (250.0f + VehicleBounds->GetScaledBoxExtent().X / 2.0f)) + FVector(0.0f, 0.0f, 50.0f);
const FVector EndCenter = StartCenter + direction * (distance + VehicleBounds->GetScaledBoxExtent().X / 2.0f);
const FVector StartRight = StartCenter + (FVector(forwardVector.Y, -forwardVector.X, forwardVector.Z) * 100.0f);
const FVector EndRight = StartRight + direction * (distance + VehicleBounds->GetScaledBoxExtent().X/2.0f);
const FVector EndRight = StartRight + direction * (distance + VehicleBounds->GetScaledBoxExtent().X / 2.0f);
const FVector StartLeft = StartCenter + (FVector(-forwardVector.Y, forwardVector.X, forwardVector.Z) * 100.0f);
const FVector EndLeft = StartLeft + direction * (distance + VehicleBounds->GetScaledBoxExtent().X/2.0f);
const FVector EndLeft = StartLeft + direction * (distance + VehicleBounds->GetScaledBoxExtent().X / 2.0f);
//const FVector RightEnd = Start + GetPawn()->GetActorForwardVector().GetSafeNormal() * (200 + VehicleBounds->GetScaledBoxExtent().X/2.0f);
//RayTrace to detect trafficLights or Vehicles
bool stop;
auto World = GetWorld();
if (TrafficLightStop) {
if (TrafficLightStop ||
RayTrace(World, StartCenter, EndCenter) ||
RayTrace(World, StartRight, EndRight) ||
RayTrace(World, StartLeft, EndLeft)) {
throttle = Stop(speed);
}
else {
if (RayTrace(World, StartCenter, EndCenter, stop)
|| RayTrace(World, StartRight, EndRight, stop)
|| RayTrace(World, StartLeft, EndLeft, stop)) {
if (stop)throttle = Stop(speed);
else throttle = Move(speed);
}
else{
throttle = Move(speed);
}
} else {
throttle = Move(speed);
}
MovementComponent->SetSteeringInput(steering);
@ -198,178 +157,171 @@ void AAICarlaVehicleController::Tick(float DeltaTime){
}
float AAICarlaVehicleController::GoTo(FVector objective, FVector &direction){
float AAICarlaVehicleController::GoTo(FVector objective, FVector &direction) {
#ifdef CARLA_AI_VEHICLES_EXTRA_LOG
UE_LOG(LogCarla, Log, TEXT("it: %i"), route_it);
UE_LOG(LogCarla, Log, TEXT("it: %i"), route_it);
#endif // CARLA_AI_VEHICLES_EXTRA_LOG
float steering = 0;
if (objective.Equals(GetPawn()->GetActorLocation(), 80.0f)){
++route_it;
if (route_it == route.Num()){
route.Empty();
route_it = 0;
return CalcStreeringValue(direction);
}
float steering = 0;
if (objective.Equals(GetPawn()->GetActorLocation(), 80.0f)) {
++route_it;
if (route_it == route.Num()) {
route.Empty();
route_it = 0;
return CalcStreeringValue(direction);
}
}
objective.Z = GetPawn()->GetActorLocation().Z;
objective.Z = GetPawn()->GetActorLocation().Z;
direction = objective - GetPawn()->GetActorLocation();
direction = direction.GetSafeNormal();
direction = objective - GetPawn()->GetActorLocation();
direction = direction.GetSafeNormal();
FVector forward = GetPawn()->GetActorForwardVector();
FVector forward = GetPawn()->GetActorForwardVector();
float dirAngle = direction.UnitCartesianToSpherical().Y;
float actorAngle = forward.UnitCartesianToSpherical().Y;
float dirAngle = direction.UnitCartesianToSpherical().Y;
float actorAngle = forward.UnitCartesianToSpherical().Y;
dirAngle *= (180.0f/PI);
actorAngle *= (180.0/PI);
dirAngle *= (180.0f / PI);
actorAngle *= (180.0 / PI);
float angle = dirAngle - actorAngle;
float angle = dirAngle - actorAngle;
if (angle > 180.0f) angle -= 360.0f;
else if (angle < -180.0f) angle += 360.0f;
if (angle > 180.0f) { angle -= 360.0f;} else if (angle < -180.0f) {
angle += 360.0f;
}
if (angle < -steerAngle) steering = -1.0f;
else if (angle > steerAngle) steering = 1.0f;
else steering += angle/steerAngle;
if (angle < -steerAngle) { steering = -1.0f;} else if (angle > steerAngle) {
steering = 1.0f;
} else { steering += angle / steerAngle;}
return steering;
}
float AAICarlaVehicleController::CalcStreeringValue(FVector &direction){
float AAICarlaVehicleController::CalcStreeringValue(FVector &direction) {
float steering = 0;
float steering = 0;
/*
if (VehicleRightControl == nullptr || VehicleLeftControl == nullptr){
UE_LOG(LogCarla, Error, TEXT("Vehicle control point not found!"));
return 0;
}
*/
FVector BoxExtent = VehicleBounds->GetScaledBoxExtent();
FVector forward = GetPawn()->GetActorForwardVector();
FVector BoxExtent = VehicleBounds->GetScaledBoxExtent();
FVector forward = GetPawn()->GetActorForwardVector();
FVector rightSensorPosition (BoxExtent.X/2.0f, (BoxExtent.Y/2.0f) + 100.0f, 0.0f);
FVector leftSensorPosition (BoxExtent.X/2.0f, -(BoxExtent.Y/2.0f) - 100.0f, 0.0f);
FVector rightSensorPosition(BoxExtent.X / 2.0f, (BoxExtent.Y / 2.0f) + 100.0f, 0.0f);
FVector leftSensorPosition(BoxExtent.X / 2.0f, -(BoxExtent.Y / 2.0f) - 100.0f, 0.0f);
float forwardMagnitude = BoxExtent.X/2.0f;
float forwardMagnitude = BoxExtent.X / 2.0f;
float Magnitude = (float) sqrt(pow((double)leftSensorPosition.X,2.0) + pow((double)leftSensorPosition.Y,2.0));
float Magnitude = (float) sqrt(pow((double) leftSensorPosition.X, 2.0) + pow((double) leftSensorPosition.Y, 2.0));
//same for the right and left
float offset = FGenericPlatformMath::Acos(forwardMagnitude/Magnitude);
//same for the right and left
float offset = FGenericPlatformMath::Acos(forwardMagnitude / Magnitude);
float actorAngle = forward.UnitCartesianToSpherical().Y;
float actorAngle = forward.UnitCartesianToSpherical().Y;
float sinR = FGenericPlatformMath::Sin(actorAngle+offset);
float cosR = FGenericPlatformMath::Cos(actorAngle+offset);
float sinR = FGenericPlatformMath::Sin(actorAngle + offset);
float cosR = FGenericPlatformMath::Cos(actorAngle + offset);
float sinL = FGenericPlatformMath::Sin(actorAngle - offset);
float cosL = FGenericPlatformMath::Cos(actorAngle - offset);
float sinL = FGenericPlatformMath::Sin(actorAngle-offset);
float cosL = FGenericPlatformMath::Cos(actorAngle-offset);
rightSensorPosition.Y = sinR * Magnitude;
rightSensorPosition.X = cosR * Magnitude;
rightSensorPosition.Y = sinR * Magnitude;
rightSensorPosition.X = cosR * Magnitude;
leftSensorPosition.Y = sinL * Magnitude;
leftSensorPosition.X = cosL * Magnitude;
leftSensorPosition.Y = sinL * Magnitude;
leftSensorPosition.X = cosL * Magnitude;
FVector rightPositon = GetPawn()->GetActorLocation() + FVector(rightSensorPosition.X, rightSensorPosition.Y, 0.0f);
FVector leftPosition = GetPawn()->GetActorLocation() + FVector(leftSensorPosition.X, leftSensorPosition.Y, 0.0f);
FVector rightPositon = GetPawn()->GetActorLocation() + FVector(rightSensorPosition.X, rightSensorPosition.Y, 0.0f);
FVector leftPosition = GetPawn()->GetActorLocation() + FVector(leftSensorPosition.X, leftSensorPosition.Y, 0.0f);
FRoadMapPixelData rightRoadData = RoadMap->GetDataAt(rightPositon);
if (!rightRoadData.IsRoad()) { steering -= 0.2f;}
FRoadMapPixelData rightRoadData = RoadMap->GetDataAt(rightPositon);
if (!rightRoadData.IsRoad()) steering -= 0.2f;
FRoadMapPixelData leftRoadData = RoadMap->GetDataAt(leftPosition);
if (!leftRoadData.IsRoad()) { steering += 0.2f;}
FRoadMapPixelData leftRoadData = RoadMap->GetDataAt(leftPosition);
if (!leftRoadData.IsRoad()) steering += 0.2f;
FRoadMapPixelData roadData = RoadMap->GetDataAt(GetPawn()->GetActorLocation());
if (!roadData.IsRoad()) {
steering = -1;
} else if (roadData.HasDirection()) {
FRoadMapPixelData roadData = RoadMap->GetDataAt(GetPawn()->GetActorLocation());
if (!roadData.IsRoad()){
steering = -1;
}
else if (roadData.HasDirection()){
direction = roadData.GetDirection();
FVector right = rightRoadData.GetDirection();
FVector left = leftRoadData.GetDirection();
direction = roadData.GetDirection();
FVector right = rightRoadData.GetDirection();
FVector left = leftRoadData.GetDirection();
forward.Z = 0.0f;
float dirAngle = direction.UnitCartesianToSpherical().Y;
float rightAngle = right.UnitCartesianToSpherical().Y;
float leftAngle = left.UnitCartesianToSpherical().Y;
forward.Z = 0.0f;
dirAngle *= (180.0f / PI);
rightAngle *= (180.0 / PI);
leftAngle *= (180.0 / PI);
actorAngle *= (180.0 / PI);
float dirAngle = direction.UnitCartesianToSpherical().Y;
float rightAngle = right.UnitCartesianToSpherical().Y;
float leftAngle = left.UnitCartesianToSpherical().Y;
float min = dirAngle - 90.0f;
if (min < -180.0f) { min = 180.0f + (min + 180.0f);}
dirAngle *= (180.0f/PI);
rightAngle *= (180.0/PI);
leftAngle *= (180.0/PI);
actorAngle *= (180.0/PI);
float min = dirAngle - 90.0f;
if (min < -180.0f) min = 180.0f + (min + 180.0f);
float max = dirAngle + 90.0f;
if (max > 180.0f) max = -180.0f + (max - 180.0f);
if (dirAngle < -90.0 || dirAngle > 90.0){
if (rightAngle < min && rightAngle > max) steering -= 0.2f;
if (leftAngle < min && leftAngle > max) steering += 0.2f;
}
else{
if (rightAngle < min || rightAngle > max) steering -= 0.2f;
if (leftAngle < min || leftAngle > max) steering += 0.2f;
}
float angle = dirAngle - actorAngle;
if (angle > 180.0f) angle -= 360.0f;
else if (angle < -180.0f) angle += 360.0f;
if (angle < -steerAngle) steering = -1.0f;
else if (angle > steerAngle) steering = 1.0f;
else steering += angle/steerAngle;
float max = dirAngle + 90.0f;
if (max > 180.0f) { max = -180.0f + (max - 180.0f);}
if (dirAngle < -90.0 || dirAngle > 90.0) {
if (rightAngle < min && rightAngle > max) { steering -= 0.2f;}
if (leftAngle < min && leftAngle > max) { steering += 0.2f;}
} else {
if (rightAngle < min || rightAngle > max) { steering -= 0.2f;}
if (leftAngle < min || leftAngle > max) { steering += 0.2f;}
}
return steering;
float angle = dirAngle - actorAngle;
if (angle > 180.0f) { angle -= 360.0f;} else if (angle < -180.0f) {
angle += 360.0f;
}
if (angle < -steerAngle) { steering = -1.0f;} else if (angle > steerAngle) {
steering = 1.0f;
} else { steering += angle / steerAngle;}
}
return steering;
}
// return throttle value
float AAICarlaVehicleController::Stop(const float speed){
float AAICarlaVehicleController::Stop(const float speed) {
// const float brake = 1.0f - (speed/MAX_SPEED);
// return FMath::Max(0.2f, brake);
if (speed >= 1.0) return -speed/MAX_SPEED;
if (speed >= 1.0) {return -speed / MAX_SPEED;}
return 0.0f;
}
// return throttle value
float AAICarlaVehicleController::Move(const float speed){
/// UE_LOG(LogCarla, Log,
// TEXT("MAX_SPEED: %f SPEED: %f"),
// MAX_SPEED,
// speed
// );
float AAICarlaVehicleController::Move(const float speed) {
/// UE_LOG(LogCarla, Log,
// TEXT("MAX_SPEED: %f SPEED: %f"),
// MAX_SPEED,
// speed
// );
if (speed >= MAX_SPEED){
if (speed >= MAX_SPEED) {
return Stop(speed);
}
else if (speed >= MAX_SPEED-10.0f){
} else if (speed >= MAX_SPEED - 10.0f) {
return 0.5;
}
return 1.0f;
return 1.0f;
}
void AAICarlaVehicleController::RedTrafficLight(bool state){
if (state) TrafficLightStop = true;
else TrafficLightStop = false;
void AAICarlaVehicleController::RedTrafficLight(bool state) {
if (state) {TrafficLightStop = true;} else {TrafficLightStop = false;}
}
void AAICarlaVehicleController::NewSpeedLimit(float speed){
void AAICarlaVehicleController::NewSpeedLimit(float speed) {
MAX_SPEED = speed;
@ -378,8 +330,7 @@ void AAICarlaVehicleController::NewSpeedLimit(float speed){
#endif // CARLA_AI_VEHICLES_EXTRA_LOG
}
void AAICarlaVehicleController::NewRoute(TArray<FVector> positions){
void AAICarlaVehicleController::NewRoute(TArray<FVector> positions) {
this->route = positions;
route_it = 0;
}

View File

@ -88,7 +88,7 @@ public:
private:
bool RayTrace( UWorld *World, const FVector &Start, const FVector &End, bool &Stop);
bool RayTrace(UWorld *World, const FVector &Start, const FVector &End);
/// @}
// ===========================================================================

View File

@ -3,13 +3,14 @@
#include "Carla.h"
#include "VehicleSpawnerBase.h"
#include "CarlaWheeledVehicle.h"
#include "Util/RandomEngine.h"
#include "Engine/PlayerStartPIE.h"
#include "EngineUtils.h"
#include "GameFramework/Character.h"
#include "GameFramework/PlayerStart.h"
#include "Util/RandomEngine.h"
// Sets default values
AVehicleSpawnerBase::AVehicleSpawnerBase(const FObjectInitializer& ObjectInitializer) :
Super(ObjectInitializer) {}
@ -77,7 +78,7 @@ void AVehicleSpawnerBase::TryToSpawnRandomVehicle()
void AVehicleSpawnerBase::SpawnVehicleAtSpawnPoint(
const APlayerStart &SpawnPoint)
{
AWheeledVehicle *Vehicle;
ACarlaWheeledVehicle *Vehicle;
SpawnVehicle(SpawnPoint.GetActorTransform(), Vehicle);
if ((Vehicle != nullptr) && !Vehicle->IsPendingKill()) {
Vehicle->AIControllerClass = AAICarlaVehicleController::StaticClass();

View File

@ -5,6 +5,7 @@
#include "Util/ActorWithRandomEngine.h"
#include "VehicleSpawnerBase.generated.h"
class ACarlaWheeledVehicle;
class APlayerStart;
UCLASS(Abstract)
@ -23,13 +24,13 @@ protected:
virtual void BeginPlay() override;
UFUNCTION(BlueprintImplementableEvent)
void SpawnVehicle(const FTransform &SpawnTransform, AWheeledVehicle *&SpawnedCharacter);
void SpawnVehicle(const FTransform &SpawnTransform, ACarlaWheeledVehicle *&SpawnedCharacter);
//UFUNCTION(BlueprintImplementableEvent)
void TryToSpawnRandomVehicle();
UFUNCTION(BlueprintImplementableEvent)
AAICarlaVehicleController* GetVehicleController(AWheeledVehicle* Vechicle);
AAICarlaVehicleController* GetVehicleController(ACarlaWheeledVehicle* Vechicle);
public:
@ -40,7 +41,7 @@ public:
return Vehicles.Num();
}
const TArray<AWheeledVehicle *> &GetVehicles() const {
const TArray<ACarlaWheeledVehicle *> &GetVehicles() const {
return Vehicles;
}
@ -62,5 +63,5 @@ protected:
TArray<APlayerStart *> SpawnPoints;
UPROPERTY(Category = "Vehicle Spawner", BlueprintReadOnly, VisibleAnywhere, AdvancedDisplay)
TArray<AWheeledVehicle *> Vehicles;
TArray<ACarlaWheeledVehicle *> Vehicles;
};

View File

@ -0,0 +1,80 @@
// CARLA, Copyright (C) 2017 Computer Vision Center (CVC)
#include "Carla.h"
#include "CarlaWheeledVehicle.h"
#include "Components/BoxComponent.h"
#include "Engine/CollisionProfile.h"
// =============================================================================
// -- Constructor and destructor -----------------------------------------------
// =============================================================================
ACarlaWheeledVehicle::ACarlaWheeledVehicle(const FObjectInitializer& ObjectInitializer) :
Super(ObjectInitializer)
{
VehicleBounds = CreateDefaultSubobject<UBoxComponent>(TEXT("VehicleBounds"));
VehicleBounds->SetupAttachment(RootComponent);
VehicleBounds->SetHiddenInGame(true);
VehicleBounds->SetCollisionProfileName(UCollisionProfile::NoCollision_ProfileName);
}
ACarlaWheeledVehicle::~ACarlaWheeledVehicle() {}
// =============================================================================
// -- Get functions ------------------------------------------------------------
// =============================================================================
float ACarlaWheeledVehicle::GetVehicleForwardSpeed() const
{
return GetVehicleMovementComponent()->GetForwardSpeed() * 0.036f;
}
FVector ACarlaWheeledVehicle::GetVehicleOrientation() const
{
return GetActorTransform().GetRotation().GetForwardVector();
}
int32 ACarlaWheeledVehicle::GetVehicleCurrentGear() const
{
return GetVehicleMovementComponent()->GetCurrentGear();
}
FVector ACarlaWheeledVehicle::GetVehicleBoundsExtent() const
{
return VehicleBounds->GetScaledBoxExtent();
}
// =============================================================================
// -- Set functions ------------------------------------------------------------
// =============================================================================
void ACarlaWheeledVehicle::SetThrottleInput(const float Value)
{
GetVehicleMovementComponent()->SetThrottleInput(Value);
}
void ACarlaWheeledVehicle::SetSteeringInput(const float Value)
{
GetVehicleMovementComponent()->SetSteeringInput(Value);
}
void ACarlaWheeledVehicle::SetBrakeInput(const float Value)
{
GetVehicleMovementComponent()->SetBrakeInput(Value);
}
void ACarlaWheeledVehicle::SetReverse(const bool Value)
{
if (Value != bIsInReverse) {
bIsInReverse = Value;
auto MovementComponent = GetVehicleMovementComponent();
MovementComponent->SetUseAutoGears(!bIsInReverse);
MovementComponent->SetTargetGear(bIsInReverse ? -1 : 1, true);
}
}
void ACarlaWheeledVehicle::SetHandbrakeInput(const bool Value)
{
GetVehicleMovementComponent()->SetHandbrakeInput(Value);
}

View File

@ -0,0 +1,97 @@
// CARLA, Copyright (C) 2017 Computer Vision Center (CVC)
#pragma once
#include "CoreMinimal.h"
#include "WheeledVehicle.h"
#include "CarlaWheeledVehicle.generated.h"
class UBoxComponent;
/// Base class for CARLA wheeled vehicles.
UCLASS()
class CARLA_API ACarlaWheeledVehicle : public AWheeledVehicle
{
GENERATED_BODY()
// ===========================================================================
/// @name Constructor and destructor
// ===========================================================================
/// @{
public:
ACarlaWheeledVehicle(const FObjectInitializer &ObjectInitializer);
~ACarlaWheeledVehicle();
/// @}
// ===========================================================================
/// @name Get functions
// ===========================================================================
/// @{
public:
/// Forward speed in km/h. Might be negative if goes backwards.
UFUNCTION(Category = "CARLA Wheeled Vehicle", BlueprintCallable)
float GetVehicleForwardSpeed() const;
/// Orientation vector of the vehicle, pointing forward.
UFUNCTION(Category = "CARLA Wheeled Vehicle", BlueprintCallable)
FVector GetVehicleOrientation() const;
/// Active gear of the vehicle.
UFUNCTION(Category = "CARLA Wheeled Vehicle", BlueprintCallable)
int32 GetVehicleCurrentGear() const;
/// Extent of the vehicle's bounds.
UFUNCTION(Category = "CARLA Wheeled Vehicle", BlueprintCallable)
FVector GetVehicleBoundsExtent() const;
/// @}
// ===========================================================================
/// @name Set functions
// ===========================================================================
/// @{
public:
UFUNCTION(Category = "CARLA Wheeled Vehicle", BlueprintCallable)
void SetThrottleInput(float Value);
UFUNCTION(Category = "CARLA Wheeled Vehicle", BlueprintCallable)
void SetSteeringInput(float Value);
UFUNCTION(Category = "CARLA Wheeled Vehicle", BlueprintCallable)
void SetBrakeInput(float Value);
UFUNCTION(Category = "CARLA Wheeled Vehicle", BlueprintCallable)
void SetReverse(bool Value);
UFUNCTION(Category = "CARLA Wheeled Vehicle", BlueprintCallable)
void ToggleReverse()
{
SetReverse(!bIsInReverse);
}
UFUNCTION(Category = "CARLA Wheeled Vehicle", BlueprintCallable)
void SetHandbrakeInput(bool Value);
UFUNCTION(Category = "CARLA Wheeled Vehicle", BlueprintCallable)
void HoldHandbrake()
{
SetHandbrakeInput(true);
}
UFUNCTION(Category = "CARLA Wheeled Vehicle", BlueprintCallable)
void ReleaseHandbrake()
{
SetHandbrakeInput(false);
}
private:
UPROPERTY(EditAnywhere)
UBoxComponent *VehicleBounds;
UPROPERTY()
bool bIsInReverse = false;
};

View File

@ -123,7 +123,8 @@ void CarlaGameController::Tick(float DeltaSeconds)
// Read control, block if the settings say so.
if (Server != nullptr) {
const bool bShouldBlock = CarlaSettings->bSynchronousMode;
if (Errc::Error == Server->ReadControl(*Player, bShouldBlock)) {
check(Player->IsPossessingAVehicle());
if (Errc::Error == Server->ReadControl(*Player->GetPossessedVehicle(), bShouldBlock)) {
Server = nullptr;
}
}

View File

@ -6,7 +6,7 @@
#include "GameFramework/PlayerStart.h"
#include "CarlaPlayerState.h"
#include "CarlaVehicleController.h"
#include "CarlaWheeledVehicle.h"
#include "SceneCaptureCamera.h"
#include "Settings/CarlaSettings.h"
@ -154,7 +154,7 @@ CarlaServer::ErrorCode CarlaServer::SendEpisodeReady(const bool bBlocking)
return ParseErrorCode(carla_write_episode_ready(Server, values, GetTimeOut(TimeOut, bBlocking)));
}
CarlaServer::ErrorCode CarlaServer::ReadControl(ACarlaVehicleController &Player, const bool bBlocking)
CarlaServer::ErrorCode CarlaServer::ReadControl(ACarlaWheeledVehicle &Player, const bool bBlocking)
{
carla_control values;
auto ec = ParseErrorCode(carla_read_control(Server, values, GetTimeOut(TimeOut, bBlocking)));
@ -188,18 +188,10 @@ static void SetBoxAndSpeed(carla_agent &values, const ACharacter *Walker)
values.box_extent = {45.0f, 35.0f, 100.0f};
}
static void SetBoxAndSpeed(carla_agent &values, const AWheeledVehicle *Vehicle)
static void SetBoxAndSpeed(carla_agent &values, const ACarlaWheeledVehicle *Vehicle)
{
/// @todo This is very slow and the code is duplicated at
/// ACarlaVehicleController.
values.forward_speed = Vehicle->GetVehicleMovementComponent()->GetForwardSpeed() * 0.036f;
TArray<UBoxComponent *> BoundingBoxes;
Vehicle->GetComponents<UBoxComponent>(BoundingBoxes);
if (BoundingBoxes.Num() > 0) {
Set(values.box_extent, BoundingBoxes[0]->GetScaledBoxExtent());
} else {
UE_LOG(LogCarla, Error, TEXT("Vehicle is missing the bounding box!"));
}
values.forward_speed = Vehicle->GetVehicleForwardSpeed();
Set(values.box_extent, Vehicle->GetVehicleBoundsExtent());
}
template <typename T>

View File

@ -2,6 +2,8 @@
#pragma once
class ACarlaGameState;
class ACarlaWheeledVehicle;
class APlayerStart;
class UCarlaSettings;
@ -34,7 +36,7 @@ public:
ErrorCode SendEpisodeReady(bool bBlocking);
ErrorCode ReadControl(ACarlaVehicleController &Player, bool bBlocking);
ErrorCode ReadControl(ACarlaWheeledVehicle &Player, bool bBlocking);
ErrorCode SendMeasurements(
const ACarlaGameState &GameState,

View File

@ -16,8 +16,7 @@
// =============================================================================
ACarlaVehicleController::ACarlaVehicleController(const FObjectInitializer& ObjectInitializer) :
Super(ObjectInitializer),
MovementComponent(nullptr)
Super(ObjectInitializer)
{
PrimaryActorTick.bCanEverTick = true;
PrimaryActorTick.TickGroup = TG_PrePhysics;
@ -43,25 +42,17 @@ void ACarlaVehicleController::Possess(APawn *aPawn)
Super::Possess(aPawn);
if (IsPossessingAVehicle()) {
UE_LOG(LogCarla, Error, TEXT("Controller already possessing a pawn!"));
UE_LOG(LogCarla, Error, TEXT("Controller already possessing a vehicle!"));
return;
}
auto *WheeledVehicle = Cast<AWheeledVehicle>(aPawn);
if (WheeledVehicle != nullptr) {
Vehicle = Cast<ACarlaWheeledVehicle>(aPawn);
if (Vehicle != nullptr) {
// Bind hit events.
aPawn->OnActorHit.AddDynamic(this, &ACarlaVehicleController::OnCollisionEvent);
// Get vehicle movement component.
MovementComponent = WheeledVehicle->GetVehicleMovementComponent();
auto *MovementComponent = Vehicle->GetVehicleMovementComponent();
check(MovementComponent != nullptr);
MovementComponent->bReverseAsBrake = false;
// Get vehicle box component.
TArray<UBoxComponent *> BoundingBoxes;
WheeledVehicle->GetComponents<UBoxComponent>(BoundingBoxes);
if (BoundingBoxes.Num() > 0) {
VehicleBounds = BoundingBoxes[0];
} else {
UE_LOG(LogCarla, Error, TEXT("Pawn is missing the bounding box!"));
}
// Get custom player state.
CarlaPlayerState = Cast<ACarlaPlayerState>(PlayerState);
check(CarlaPlayerState != nullptr);
@ -108,11 +99,11 @@ void ACarlaVehicleController::Tick(float DeltaTime)
if (IsPossessingAVehicle()) {
CarlaPlayerState->UpdateTimeStamp(DeltaTime);
const FVector PreviousSpeed = CarlaPlayerState->ForwardSpeed * CarlaPlayerState->GetOrientation();
CarlaPlayerState->Transform = GetVehicleTransform();
CarlaPlayerState->ForwardSpeed = GetVehicleForwardSpeed();
CarlaPlayerState->Transform = Vehicle->GetActorTransform();
CarlaPlayerState->ForwardSpeed = Vehicle->GetVehicleForwardSpeed();
const FVector CurrentSpeed = CarlaPlayerState->ForwardSpeed * CarlaPlayerState->GetOrientation();
CarlaPlayerState->Acceleration = (CurrentSpeed - PreviousSpeed) / DeltaTime;
CarlaPlayerState->CurrentGear = GetVehicleCurrentGear();
CarlaPlayerState->CurrentGear = Vehicle->GetVehicleCurrentGear();
IntersectPlayerWithRoadMap();
const auto NumberOfCameras = SceneCaptureCameras.Num();
check(NumberOfCameras == CarlaPlayerState->Images.Num());
@ -125,39 +116,6 @@ void ACarlaVehicleController::Tick(float DeltaTime)
}
}
// =============================================================================
// -- Vehicle pawn info --------------------------------------------------------
// =============================================================================
FTransform ACarlaVehicleController::GetVehicleTransform() const
{
check(GetPawn() != nullptr);
return GetPawn()->GetActorTransform();
}
FVector ACarlaVehicleController::GetVehicleLocation() const
{
check(GetPawn() != nullptr);
return GetPawn()->GetActorLocation();
}
float ACarlaVehicleController::GetVehicleForwardSpeed() const
{
check(MovementComponent != nullptr);
return MovementComponent->GetForwardSpeed() * 0.036f;
}
FVector ACarlaVehicleController::GetVehicleOrientation() const
{
return GetVehicleTransform().GetRotation().GetForwardVector();
}
int32 ACarlaVehicleController::GetVehicleCurrentGear() const
{
check(MovementComponent != nullptr);
return MovementComponent->GetCurrentGear();
}
// =============================================================================
// -- Scene capture ------------------------------------------------------------
// =============================================================================
@ -184,44 +142,6 @@ void ACarlaVehicleController::AddSceneCaptureCamera(
*PostProcessEffect::ToString(Camera->GetPostProcessEffect()));
}
// =============================================================================
// -- Vehicle movement methods -------------------------------------------------
// =============================================================================
void ACarlaVehicleController::SetThrottleInput(float Value)
{
check(MovementComponent != nullptr);
MovementComponent->SetThrottleInput(Value);
}
void ACarlaVehicleController::SetSteeringInput(float Value)
{
check(MovementComponent != nullptr);
MovementComponent->SetSteeringInput(Value);
}
void ACarlaVehicleController::SetBrakeInput(float Value)
{
check(MovementComponent != nullptr);
MovementComponent->SetBrakeInput(Value);
}
void ACarlaVehicleController::SetReverse(bool Value)
{
if (Value != bIsInReverse) {
check(MovementComponent != nullptr);
bIsInReverse = Value;
MovementComponent->SetUseAutoGears(!bIsInReverse);
MovementComponent->SetTargetGear(bIsInReverse ? -1 : 1, true);
}
}
void ACarlaVehicleController::SetHandbrakeInput(bool Value)
{
check(MovementComponent != nullptr);
MovementComponent->SetHandbrakeInput(Value);
}
// =============================================================================
// -- Manual mode --------------------------------------------------------------
// =============================================================================
@ -250,7 +170,7 @@ void ACarlaVehicleController::OnCollisionEvent(
const FHitResult& Hit)
{
// Register collision only if we are moving faster than 1 km/h.
if (FMath::Abs(GetVehicleForwardSpeed()) > 1.0f) {
if (FMath::Abs(Vehicle->GetVehicleForwardSpeed()) > 1.0f) {
CarlaPlayerState->RegisterCollision(Actor, OtherActor, NormalImpulse, Hit);
}
}
@ -262,14 +182,15 @@ void ACarlaVehicleController::OnCollisionEvent(
void ACarlaVehicleController::SetupControllerInput()
{
check(InputComponent != nullptr);
check(IsPossessingAVehicle());
// Vehicle movement.
if (IsInManualMode()) {
InputComponent->BindAxis("MoveForward", this, &ACarlaVehicleController::SetThrottleInput);
InputComponent->BindAxis("MoveRight", this, &ACarlaVehicleController::SetSteeringInput);
InputComponent->BindAxis("Brake", this, &ACarlaVehicleController::SetBrakeInput);
InputComponent->BindAction("ToggleReverse", IE_Pressed, this, &ACarlaVehicleController::ToggleReverse);
InputComponent->BindAction("Handbrake", IE_Pressed, this, &ACarlaVehicleController::HoldHandbrake);
InputComponent->BindAction("Handbrake", IE_Released, this, &ACarlaVehicleController::ReleaseHandbrake);
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
}
@ -284,15 +205,12 @@ void ACarlaVehicleController::IntersectPlayerWithRoadMap()
if (RoadMap == nullptr) {
UE_LOG(LogCarla, Error, TEXT("Controller doesn't have a road map"));
return;
} else if (VehicleBounds == nullptr) {
UE_LOG(LogCarla, Error, TEXT("Vehicle doesn't have a bounding box"));
return;
}
constexpr float ChecksPerCentimeter = 0.1f;
auto Result = RoadMap->Intersect(
GetPawn()->GetTransform(),
VehicleBounds->GetScaledBoxExtent(),
Vehicle->GetActorTransform(),
Vehicle->GetVehicleBoundsExtent(),
ChecksPerCentimeter);
CarlaPlayerState->OffRoadIntersectionFactor = Result.OffRoad;

View File

@ -7,10 +7,9 @@
class ACarlaHUD;
class ACarlaPlayerState;
class ACarlaWheeledVehicle;
class ASceneCaptureCamera;
class UBoxComponent;
class URoadMap;
class UWheeledVehicleMovementComponent;
struct FCameraDescription;
/**
@ -48,29 +47,20 @@ public:
/// @}
// ===========================================================================
/// @name Vehicle pawn info
/// @name Player state
// ===========================================================================
/// @{
public:
bool IsPossessingAVehicle() const
{
return MovementComponent != nullptr;
return Vehicle != nullptr;
}
/// World transform of the vehicle.
FTransform GetVehicleTransform() const;
/// World location of the vehicle.
FVector GetVehicleLocation() const;
/// Speed forward in km/h. Might be negative if goes backwards.
float GetVehicleForwardSpeed() const;
/// Orientation vector of the vehicle, pointing forward.
FVector GetVehicleOrientation() const;
int32 GetVehicleCurrentGear() const;
ACarlaWheeledVehicle *GetPossessedVehicle() const
{
return Vehicle;
}
const ACarlaPlayerState &GetPlayerState() const
{
@ -88,38 +78,6 @@ public:
const FCameraDescription &CameraDescription,
const FCameraPostProcessParameters *OverridePostProcessParameters = nullptr);
/// @}
// ===========================================================================
/// @name Vehicle movement
// ===========================================================================
/// @{
public:
void SetThrottleInput(float Value);
void SetSteeringInput(float Value);
void SetBrakeInput(float Value);
void SetReverse(bool Value);
void ToggleReverse()
{
SetReverse(!bIsInReverse);
}
void SetHandbrakeInput(bool Value);
void HoldHandbrake()
{
SetHandbrakeInput(true);
}
void ReleaseHandbrake()
{
SetHandbrakeInput(false);
}
/// @}
// ===========================================================================
/// @name Manual mode
@ -168,13 +126,6 @@ private:
/// @name Other
// ===========================================================================
/// @{
public:
void SetRoadMap(URoadMap *inRoadMap)
{
RoadMap = inRoadMap;
}
private:
void IntersectPlayerWithRoadMap();
@ -191,10 +142,7 @@ private:
bool bManualMode = false;
UPROPERTY()
bool bIsInReverse = false;
UPROPERTY()
UWheeledVehicleMovementComponent *MovementComponent;
ACarlaWheeledVehicle *Vehicle;
UPROPERTY()
TArray<ASceneCaptureCamera *> SceneCaptureCameras;
@ -202,9 +150,6 @@ private:
UPROPERTY()
URoadMap *RoadMap;
UPROPERTY()
UBoxComponent *VehicleBounds;
// Cast for quick access to the custom player state.
UPROPERTY()
ACarlaPlayerState *CarlaPlayerState;

View File

@ -31,13 +31,13 @@ APlayerCameraController::APlayerCameraController(const FObjectInitializer& Objec
// Do not collide, may clip into level.
SpringArm->bDoCollisionTest = false;
// Create the camera component
// Create the camera component.
PlayerCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("Camera0"));
PlayerCamera->SetupAttachment(SpringArm, USpringArmComponent::SocketName);
PlayerCamera->bUsePawnControlRotation = false;
PlayerCamera->FieldOfView = 90.f;
// Create the on-board camera component
// Create the on-board camera component.
OnBoardCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("OnBoardCamera0"));
OnBoardCamera->SetRelativeLocation(FVector(140.f, 0.f, 140.f));
OnBoardCamera->SetRelativeRotation(FRotator(-10.f, 0.f, 0.f));