13#include <util/ue-header-guard-begin.h>
14#include "Engine/CollisionProfile.h"
15#include "Engine/Engine.h"
16#include "DrawDebugHelpers.h"
17#include "EngineUtils.h"
18#include <util/ue-header-guard-end.h>
22 return (SplineComponent !=
nullptr) &&
23 (SplineComponent->GetNumberOfSplinePoints() > 1);
28 auto *
Vehicle = (
IsValid(Actor) ? nullptr : Cast<ACarlaWheeledVehicle>(Actor));
30 Cast<AWheeledVehicleAIController>(
Vehicle->GetController()) :
36 const TArray<USplineComponent *> &Routes,
37 const TArray<float> &Probabilities)
39 check(Routes.Num() > 0);
41 if (Routes.Num() == 1)
47 check((Index >= 0) && (Index < Routes.Num()));
52 : Super(ObjectInitializer)
55 ObjectInitializer.CreateDefaultSubobject<USceneComponent>(
this, TEXT(
"SceneRootComponent"));
56 RootComponent->SetMobility(EComponentMobility::Static);
58 TriggerVolume = CreateDefaultSubobject<UBoxComponent>(TEXT(
"TriggerVolume"));
72 Super::BeginDestroy();
76void ARoutePlanner::PostEditChangeProperty(FPropertyChangedEvent &PropertyChangedEvent)
78 Super::PostEditChangeProperty(PropertyChangedEvent);
79 const auto Size =
Routes.Num();
80 if (PropertyChangedEvent.Property && (Size !=
Probabilities.Num()))
83 for (
auto i = 0; i < Size; ++i)
88 Routes[i] = NewObject<USplineComponent>(
this);
89 Routes[i]->SetupAttachment(RootComponent);
90 Routes[i]->SetHiddenInGame(
true);
91 Routes[i]->SetMobility(EComponentMobility::Static);
92 Routes[i]->RegisterComponent();
101 USplineComponent *NewSpline = NewObject<USplineComponent>(
this);
102 NewSpline->bHiddenInGame =
true;
105 NewSpline->EditorUnselectedSplineSegmentColor = FLinearColor(1.f, 0.15f, 0.15f);
108 NewSpline->SetLocationAtSplinePoint(0, routePoints[0], ESplineCoordinateSpace::World,
true);
109 NewSpline->SetLocationAtSplinePoint(1, routePoints[1], ESplineCoordinateSpace::World,
true);
111 for (
int i = 2; i < routePoints.Num(); ++i)
113 NewSpline->AddSplinePoint(routePoints[i], ESplineCoordinateSpace::World,
true);
133 TArray<FVector> WayPoints;
134 const auto Size = Route->GetNumberOfSplinePoints();
137 WayPoints.Reserve(Size);
138 for (
auto i = 1; i < Size; ++i)
140 WayPoints.Add(Route->GetLocationAtSplinePoint(i, ESplineCoordinateSpace::World));
147 UE_LOG(LogCarla, Error, TEXT(
"ARoutePlanner '%s' has a route with zero way-points."), *GetName());
154 const UObject *WorldContextObject,
155 const FVector &Location,
157 FRotator &OutRotation)
159 const UWorld *World = GEngine->GetWorldFromContextObject(WorldContextObject, EGetWorldErrorMode::ReturnNull);
160 if (World ==
nullptr)
166 float ClosestDistanceSq = FMath::Square(SearchRadius);
167 FVector ClosestDirection = FVector::ForwardVector;
169 for (TActorIterator<ARoutePlanner> It(World); It; ++It)
171 for (
const USplineComponent *Route : It->Routes)
177 const FVector ClosestPoint =
178 Route->FindLocationClosestToWorldLocation(Location, ESplineCoordinateSpace::World);
179 const float DistanceSq = FVector::DistSquared(Location, ClosestPoint);
180 if (DistanceSq <= ClosestDistanceSq)
183 ClosestDistanceSq = DistanceSq;
185 Route->FindDirectionClosestToWorldLocation(Location, ESplineCoordinateSpace::World);
192 OutRotation = ClosestDirection.Rotation();
201 UE_LOG(LogCarla, Warning, TEXT(
"ARoutePlanner '%s' has no route assigned."), *GetName());
205 for (
auto &&Route :
Routes)
209 UE_LOG(LogCarla, Error, TEXT(
"ARoutePlanner '%s' has a route with zero way-points."), *GetName());
235 Super::EndPlay(EndPlayReason);
239 UPrimitiveComponent * ,
241 UPrimitiveComponent * ,
247 if (Controller !=
nullptr)
256 for (
int i = 0, lenRoutes =
Routes.Num(); i < lenRoutes; ++i)
258 for (
int j = 0, lenNumPoints =
Routes[i]->GetNumberOfSplinePoints() - 1; j < lenNumPoints; ++j)
260 const FVector p0 =
Routes[i]->GetLocationAtSplinePoint(j + 0, ESplineCoordinateSpace::World);
261 const FVector p1 =
Routes[i]->GetLocationAtSplinePoint(j + 1, ESplineCoordinateSpace::World);
263 static const float MinThickness = 3.f;
264 static const float MaxThickness = 15.f;
266 const float Dist = (float) j / (
float) lenNumPoints;
267 const float OneMinusDist = 1.f - Dist;
268 const float Thickness = OneMinusDist * MaxThickness + MinThickness;
274 GetWorld(), p0, p1, FColor(0, 0, 255 * OneMinusDist),
275 true, -1.f, 0, Thickness);
281 GetWorld(), p0, p1, FColor(0, 255 * OneMinusDist, 0),
282 true, -1.f, 0, Thickness);
static AWheeledVehicleAIController * GetVehicleController(AActor *Actor)
static bool IsSplineValid(const USplineComponent *SplineComponent)
static const USplineComponent * PickARoute(URandomEngine &RandomEngine, const TArray< USplineComponent * > &Routes, const TArray< float > &Probabilities)
static bool IsValid(const ACarlaWheeledVehicle *Vehicle)
virtual void BeginPlay() override
TArray< TObjectPtr< USplineComponent > > Routes
virtual void BeginDestroy() override
void AddRoute(float probability, const TArray< FVector > &routePoints)
ARoutePlanner(const FObjectInitializer &ObjectInitializer)
void AssignRandomRoute(AWheeledVehicleAIController &Controller) const
void OnTriggerBeginOverlap(UPrimitiveComponent *OverlappedComp, AActor *OtherActor, UPrimitiveComponent *OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult &SweepResult)
TArray< float > Probabilities
static bool FindRoadFlowRotationAtLocation(const UObject *WorldContextObject, const FVector &Location, float SearchRadius, FRotator &OutRotation)
Searches every ARoutePlanner in the world for the route spline point closest to Location,...
TObjectPtr< UBoxComponent > TriggerVolume
virtual void EndPlay(EEndPlayReason::Type EndPlayReason) override
Wheeled vehicle controller with optional AI.
URandomEngine * GetRandomEngine()
void SetFixedRoute(const TArray< FVector > &Locations, bool bOverwriteCurrent=true)
Set a fixed route to follow if autopilot is enabled.
int32 GetIntWithWeight(const TArray< float > &Weights)