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
Definition: CarlaActor.cpp:83
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)
CARLA轮式车辆的基类.
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)
播种随机引擎/初始化随机数生成器
Definition: RandomEngine.h:44
static int32 GenerateRandomSeed()
生成一个非确定性随机数种子。