CARLA
 
载入中...
搜索中...
未找到
WheeledVehicleAIController.cpp
浏览该文件的文档.
1// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
2// de Barcelona (UAB).
3//
4// This work is licensed under the terms of the MIT license.
5// For a copy, see <https://opensource.org/licenses/MIT>.
6
7#include "Carla.h"
9
10#include "MapGen/RoadMap.h"
15
16#include "EngineUtils.h"
17#include "GameFramework/Pawn.h"
18#include "WheeledVehicleMovementComponent.h"
19
20// =============================================================================
21// -- 静态局部方法 -------------------------------------------------------------
22// =============================================================================
23
24// 判断从起点到终点的光线投射是否成功击中了一个阻挡物
25static bool RayCast(const AActor &Actor, const FVector &Start, const FVector &End)
26{
27 FHitResult OutHit; // 用于存储光线投射的结果
28 static FName TraceTag = FName(TEXT("VehicleTrace")); // 定义光线投射的标签,用于调试或区分不同的光线投射
29 FCollisionQueryParams CollisionParams(TraceTag, true); // 设置碰撞查询参数,允许物理碰撞
30 CollisionParams.AddIgnoredActor(&Actor); // 添加忽略的Actor,即发起光线投射的Actor本身不会被检测为碰撞对象
31
32 // 执行光线投射,检查从Start到End之间是否有物体被击中
33 const bool Success = Actor.GetWorld()->LineTraceSingleByObjectType(
34 OutHit,
35 Start,
36 End,
37 FCollisionObjectQueryParams(FCollisionObjectQueryParams::AllDynamicObjects), // 查询所有动态对象
38 CollisionParams);
39
40 // 调试用的代码,根据光线投射是否成功绘制不同颜色的线条,这里被注释掉了
41 // DrawDebugLine(Actor.GetWorld(), Start, End,
42 // Success ? FColor(255, 0, 0) : FColor(0, 255, 0), false);
43
44 // 返回光线投射是否成功且击中了阻挡物
45 return Success && OutHit.bBlockingHit;
46}
47
48// 判断车辆前方是否有障碍物
51 const float Speed,
52 const FVector &Direction)
53{
54 // 获取车辆的前向向量和车辆的边界框大小
55 const auto ForwardVector = Vehicle.GetVehicleOrientation();
56 const auto VehicleBounds = Vehicle.GetVehicleBoundingBoxExtent();
57
58 // 获取方向的安全法向量(单位向量)
59 FVector NormDirection = Direction.GetSafeNormal();
60
61 // 根据速度计算光线投射的距离,至少为50.0f,可能与速度的平方成正比(为什么这样做可能取决于具体的设计考虑)
62 const float Distance = std::max(50.0f, Speed * Speed);
63
64 // 计算光线投射的起点和终点,包括中心、右侧和左侧三个方向
65 const FVector StartCenter = Vehicle.GetActorLocation() +
66 (ForwardVector * (250.0f + VehicleBounds.X / 2.0f)) + FVector(0.0f, 0.0f, 50.0f);
67 const FVector EndCenter = StartCenter + NormDirection * (Distance + VehicleBounds.X / 2.0f);
68
69 const FVector StartRight = StartCenter +
70 (FVector(ForwardVector.Y, -ForwardVector.X, ForwardVector.Z) * 100.0f);
71 const FVector EndRight = StartRight + NormDirection * (Distance + VehicleBounds.X / 2.0f);
72
73 const FVector StartLeft = StartCenter +
74 (FVector(-ForwardVector.Y, ForwardVector.X, ForwardVector.Z) * 100.0f);
75 const FVector EndLeft = StartLeft + NormDirection * (Distance + VehicleBounds.X / 2.0f);
76
77 // 如果中心、右侧或左侧任意一个方向的光线投射击中了阻挡物,则返回true
78 return
79 RayCast(Vehicle, StartCenter, EndCenter) ||
80 RayCast(Vehicle, StartRight, EndRight) ||
81 RayCast(Vehicle, StartLeft, EndLeft);
82}
83
84// 清空队列中的所有元素
85template <typename T>
86static void ClearQueue(std::queue<T> &Queue)
87{
88 std::queue<T> EmptyQueue;
89 Queue.swap(EmptyQueue); // 通过交换队列来清空原队列
90}
91
92// =============================================================================
93// -- 构造函数和析构函数 -------------------------------------------------------
94// =============================================================================
95
96// AWheeledVehicleAIController类的构造函数
97AWheeledVehicleAIController::AWheeledVehicleAIController(const FObjectInitializer &ObjectInitializer)
98 : Super(ObjectInitializer)
99{
100 RandomEngine = CreateDefaultSubobject<URandomEngine>(TEXT("RandomEngine")); // 创建随机数引擎
101
102 RandomEngine->Seed(RandomEngine->GenerateRandomSeed()); // 为随机数引擎设置随机种子
103
104 PrimaryActorTick.bCanEverTick = true; // 允许该Actor参与Tick
105 PrimaryActorTick.TickGroup = TG_PrePhysics; // 设置Tick的优先级为物理计算之前
106}
107
108// AWheeledVehicleAIController类的析构函数
110
111// =============================================================================
112// -- AController --------------------------------------------------------------
113// =============================================================================
114
115// 当控制器接管一个pawn时调用
117{
118 Super::OnPossess(aPawn); // 调用父类的OnPossess方法
119
120 // 如果已经控制了一个车辆,则打印错误日志并返回
122 {
123 UE_LOG(LogCarla, Error, TEXT("Controller already possessing a vehicle!"));
124 return;
125 }
126 Vehicle = Cast<ACarlaWheeledVehicle>(aPawn); // 将传入的pawn转换为车辆类型
127 check(Vehicle != nullptr); // 确保转换成功
128 MaximumSteerAngle = Vehicle->GetMaximumSteerAngle(); // 获取车辆的最大转向角度
129 check(MaximumSteerAngle > 0.0f); // 确保最大转向角度大于0
130 ConfigureAutopilot(bAutopilotEnabled); // 根据是否启用自动驾驶配置自动驾驶参数
131
132 // 如果没有设置路线图,则尝试从世界中获取
133 if (RoadMap == nullptr)
134 {
135 TActorIterator<ACityMapGenerator> It(GetWorld());
136 RoadMap = (It ? It->GetRoadMap() : nullptr);
137 }
138}
139
140// 当控制器失去对一个pawn的控制时调用
142{
143 Super::OnUnPossess(); // 调用父类的OnUnPossess方法
144
145 Vehicle = nullptr; // 清空车辆指针
146}
147
148// 每一帧调用一次的函数
149void AWheeledVehicleAIController::Tick(const float DeltaTime)
150{
151 TRACE_CPUPROFILER_EVENT_SCOPE(AWheeledVehicleAIController::Tick); // 性能分析工具的事件范围
152 Super::Tick(DeltaTime); // 调用父类的Tick方法
153
154 // 如果没有控制一个车辆,则直接返回
156 {
157 return;
158 }
159
160 // 如果没有启用自动驾驶且控制不是粘性的,则放松车辆控制
162 {
163 Vehicle->ApplyVehicleControl(FVehicleControl{}, EVehicleInputPriority::Relaxation);
164 }
165
166 // 刷新车辆控制
168}
169
170// =============================================================================
171// -- 自动驾驶 ----------------------------------------------------------------
172// =============================================================================
173
174// 根据是否启用自动驾驶和是否保留当前状态来配置自动驾驶参数
175void AWheeledVehicleAIController::ConfigureAutopilot(const bool Enable, const bool KeepState)
176{
177 bAutopilotEnabled = Enable; // 设置自动驾驶启用状态
178 if (!KeepState)
179 {
180 // 重置状态
181 Vehicle->SetSteeringInput(0.0f); // 设置转向输入为0
182 Vehicle->SetThrottleInput(0.0f); // 设置油门输入为0
183 Vehicle->SetBrakeInput(0.0f); // 设置刹车输入为0
184 Vehicle->SetReverse(false); // 设置不倒车
185 Vehicle->SetHandbrakeInput(false); // 设置不拉手刹
186 ClearQueue(TargetLocations); // 清空目标位置队列
189 ECarlaWheeledVehicleState::FreeDriving : // 启用自动驾驶时设置为自由驾驶状态
190 ECarlaWheeledVehicleState::AutopilotOff); // 禁用自动驾驶时设置为自动驾驶关闭状态
191 }
192
193 TrafficLightState = ETrafficLightState::Green; // 默认交通灯状态为绿灯
194}
195
196// =============================================================================
197// -- 交通 --------------------------------------------------------------------
198// =============================================================================
199
200// 设置固定的行驶路线,可以覆盖当前的路线
202 const TArray<FVector> &Locations,
203 const bool bOverwriteCurrent)
204{
205 if (bOverwriteCurrent)
206 {
207 ClearQueue(TargetLocations); // 如果需要覆盖当前路线,则清空目标位置队列
208 }
209 for (auto &Location : Locations)
210 {
211 TargetLocations.emplace(Location); // 将新的位置添加到目标位置队列中
212 }
213}
UE_LOG(LogCarla, Log, TEXT("UActorDispatcher::Destroying actor: '%s' %x"), *Id, Actor)
TSharedPtr< const FActorInfo > carla::rpc::ActorState UWorld Actor
static bool RayCast(const AActor &Actor, const FVector &Start, const FVector &End)
static void ClearQueue(std::queue< T > &Queue)
static bool IsThereAnObstacleAhead(const ACarlaWheeledVehicle &Vehicle, const float Speed, const FVector &Direction)
Base class for CARLA wheeled vehicles.
void SetAIVehicleState(ECarlaWheeledVehicleState InState)
void SetThrottleInput(float Value)
float GetMaximumSteerAngle() const
Get the maximum angle at which the front wheel can steer.
void SetBrakeInput(float Value)
void SetSteeringInput(float Value)
void ApplyVehicleControl(const FVehicleControl &Control, EVehicleInputPriority Priority)
void SetHandbrakeInput(bool Value)
void ConfigureAutopilot(const bool Enable, const bool KeepState=false)
AWheeledVehicleAIController(const FObjectInitializer &ObjectInitializer)
void OnPossess(APawn *aPawn) override
void SetFixedRoute(const TArray< FVector > &Locations, bool bOverwriteCurrent=true)
设置启用 Autopilot 时要遵循的固定路线。
void Tick(float DeltaTime) override
void Seed(int32 InSeed)
播种随机引擎/初始化随机数生成器
static int32 GenerateRandomSeed()
生成一个非确定性随机数种子。