CARLA
 
载入中...
搜索中...
未找到
ActorDispatcher.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
13
14#include "Carla/Game/Tagger.h"
16
17#include "GameFramework/Controller.h"
18
20#include "carla/ros2/ROS2.h"
22
23// UActorDispatcher类中的Bind函数,用于绑定一个Actor定义和生成函数
25{
26 // 检查Actor定义是否有效
28 {
29 // 分配一个唯一的ID给这个定义
30 Definition.UId = static_cast<uint32>(SpawnFunctions.Num()) + 1u;
31 // 将定义添加到定义列表中
32 Definitions.Emplace(Definition);
33 // 将生成函数添加到生成函数列表中
34 SpawnFunctions.Emplace(Functor);
35 // 将对应的类添加到类列表中
36 Classes.Emplace(Definition.Class);
37 }
38 else
39 {
40 // 如果定义无效,记录警告日志
41 UE_LOG(LogCarla, Warning, TEXT("Invalid definition '%s' ignored"), *Definition.Id);
42 }
43}
44
45// UActorDispatcher类中的另一个Bind函数,用于绑定一个Actor工厂
47{
48 // 遍历Actor工厂中所有定义,并绑定它们
49 for (const auto &Definition : ActorFactory.GetDefinitions())
50 {
51 Bind(Definition, [&](const FTransform &Transform, const FActorDescription &Description) {
52 // 返回Actor工厂生成的Actor
53 return ActorFactory.SpawnActor(Transform, Description);
54 });
55 }
56}
57
58// UActorDispatcher类中的SpawnActor函数,用于生成Actor
59TPair<EActorSpawnResultStatus, FCarlaActor*> UActorDispatcher::SpawnActor(
60 const FTransform &Transform,
61 FActorDescription Description,
62 FCarlaActor::IdType DesiredId)
63{
64 // 检查Actor描述是否有效
65 if ((Description.UId == 0u) || (Description.UId > static_cast<uint32>(SpawnFunctions.Num())))
66 {
67 // 如果无效,记录错误日志并返回失败结果
68 UE_LOG(LogCarla, Error, TEXT("Invalid ActorDescription '%s' (UId=%d)"), *Description.Id, Description.UId);
69 return MakeTuple(EActorSpawnResultStatus::InvalidDescription, nullptr);
70 }
71
72 // 记录生成Actor的日志
73 UE_LOG(LogCarla, Log, TEXT("Spawning actor '%s'"), *Description.Id);
74
75 // 设置Actor描述中的类
76 Description.Class = Classes[Description.UId - 1];
77 // 调用对应的生成函数生成Actor
78 FActorSpawnResult Result = SpawnFunctions[Description.UId - 1](Transform, Description);
79
80 // 如果生成结果状态为成功但未返回Actor,记录警告日志并将状态设置为未知错误
81 if ((Result.Status == EActorSpawnResultStatus::Success) && (Result.Actor == nullptr))
82 {
83 UE_LOG(LogCarla, Warning, TEXT("ActorSpawnResult: Trying to spawn '%s'"), *Description.Id);
84 UE_LOG(LogCarla, Warning, TEXT("ActorSpawnResult: Reported success but did not return an actor"));
85 Result.Status = EActorSpawnResultStatus::UnknownError;
86 }
87
88 // 如果生成结果有效,则注册Actor,否则设置为nullptr
89 FCarlaActor* View = Result.IsValid() ?
90 RegisterActor(*Result.Actor, std::move(Description), DesiredId) : nullptr;
91 // 如果注册失败,记录警告日志并检查结果状态不应为成功
92 if (!View)
93 {
94 UE_LOG(LogCarla, Warning, TEXT("Failed to spawn actor '%s'"), *Description.Id);
95 check(Result.Status != EActorSpawnResultStatus::Success);
96 }
97 else
98 {
99 // 如果注册成功,对Actor进行标记
100 ATagger::TagActor(*View->GetActor(), true);
101 }
102 // 返回生成结果状态和Actor指针
103 return MakeTuple(Result.Status, View);
104}
105
107 const FTransform &Transform,
108 FActorDescription Description)
109{
110 // 检查Description是否有效,如果UId为0或超出SpawnFunctions数组的大小,则返回nullptr
111 if ((Description.UId == 0u) || (Description.UId > static_cast<uint32>(SpawnFunctions.Num())))
112 {
113 UE_LOG(LogCarla, Error, TEXT("Invalid ActorDescription '%s' (UId=%d)"), *Description.Id, Description.UId);
114 return nullptr;
115 }
116
117 // 记录日志,表示开始生成指定的Actor
118 UE_LOG(LogCarla, Log, TEXT("Spawning actor '%s'"), *Description.Id);
119
120 // 根据UId从Classes数组中获取对应的类,并赋值给Description.Class
121 Description.Class = Classes[Description.UId - 1];
122 // 使用对应的SpawnFunction生成Actor
123 FActorSpawnResult Result = SpawnFunctions[Description.UId - 1](Transform, Description);
124
125 // 如果生成结果状态为成功,但未返回Actor,则记录警告并返回nullptr
126 if ((Result.Status == EActorSpawnResultStatus::Success) && (Result.Actor == nullptr))
127 {
128 UE_LOG(LogCarla, Warning, TEXT("ActorSpawnResult: Trying to spawn '%s'"), *Description.Id);
129 UE_LOG(LogCarla, Warning, TEXT("ActorSpawnResult: Reported success but did not return an actor"));
130 Result.Status = EActorSpawnResultStatus::UnknownError;
131 return nullptr;
132 }
133
134 // 如果生成结果状态为成功,则返回生成的Actor
135 if (Result.Status == EActorSpawnResultStatus::Success)
136 {
137 return Result.Actor;
138 }
139
140 // 如果生成失败,则返回nullptr
141 return nullptr;
142}
143
145{
146 // 检查要销毁的Actor是否在注册表中存在
147 FCarlaActor* View = Registry.FindCarlaActor(ActorId);
148
149 // 如果Actor不在注册表中或已经被标记为待销毁,则返回false
150 if (!View)
151 {
152 UE_LOG(LogCarla, Warning, TEXT("Trying to destroy actor that is not in the registry"));
153 return false;
154 }
155
156 const FString &Id = View->GetActorInfo()->Description.Id;
157
158 // 获取Actor的控制器,如果存在,则尝试销毁
159 AActor* Actor = View->GetActor();
160 if(Actor)
161 {
162 APawn* Pawn = Cast<APawn>(Actor);
163 AController* Controller = (Pawn != nullptr ? Pawn->GetController() : nullptr);
164 if (Controller != nullptr)
165 {
166 UE_LOG(LogCarla, Log, TEXT("Destroying actor's controller: '%s'"), *Id);
167 bool Success = Controller->Destroy();
168 if (!Success)
169 {
170 UE_LOG(LogCarla, Error, TEXT("Failed to destroy actor's controller: '%s'"), *Id);
171 }
172 }
173
174 // 销毁Actor
175 // ...(代码未完整,以下为注释)
176 // 如果Actor存在,调用Destroy函数尝试销毁
177 // 如果销毁失败,记录错误日志
178 // 返回true表示销毁操作已尝试执行
179 return true;
180 }
181 // 如果Actor不存在,返回false表示销毁操作未执行
182 return false;
183}
184
185 UE_LOG(LogCarla, Log, TEXT("UActorDispatcher::Destroying actor: '%s' %x"), *Id, Actor);
186 UE_LOG(LogCarla, Log, TEXT(" %s"), Actor?*Actor->GetName():*FString("None"));
187 if (!Actor || !Actor->Destroy())
188 {
189 UE_LOG(LogCarla, Error, TEXT("Failed to destroy actor: '%s'"), *Id);
190 return false;
191 }
192 }
193
194 Registry.Deregister(ActorId);
195
196 return true;
197}
198
200 AActor &Actor, FActorDescription Description,
201 FActorRegistry::IdType DesiredId)
202{
203 FCarlaActor* View = Registry.Register(Actor, Description, DesiredId);
204 if (View)
205 {
206 // 待办事项:支持外部角色销毁
207 Actor.OnDestroyed.AddDynamic(this, &UActorDispatcher::OnActorDestroyed);
208
209 // ROS2 中 actor 到 ros_name 的映射
210 #if defined(WITH_ROS2)
211 auto ROS2 = carla::ros2::ROS2::GetInstance();
212 if (ROS2->IsEnabled())
213 {
214 // 参与者 ros_name
215 std::string RosName;
216 // 遍历actor的描述中的所有变体(属性)
217 for (auto &&Attr : Description.Variations)
218 {// 如果找到一个键为"ros_name"的属性
219 if (Attr.Key == "ros_name")
220 {// 将该属性的值(假设是TCHAR类型)转换为UTF-8编码的std::string
221 RosName = std::string(TCHAR_TO_UTF8(*Attr.Value.Value));
222 }
223 }
224 // 将actor的ID也转换为UTF-8编码的std::string
225 const std::string id = std::string(TCHAR_TO_UTF8(*Description.Id));
226 // 检查ROS名称是否与actor的ID相同
227 if (RosName == id) {
228 if(RosName.find("vehicle") != std::string::npos)
229 {// 构造一个新的车辆名称,包含"vehicle"和actor的ID(通过View->GetActorId()
230 std::string VehicleName = "vehicle" + std::to_string(View->GetActorId());
231 // 将这个新的车辆名称添加到ROS 2系统中,与actor关联
232 ROS2->AddActorRosName(static_cast<void*>(&Actor), VehicleName);
233 }
234 else
235 { // 如果ROS名称不包含"vehicle",则查找最后一个'.'字符的位置
236 size_t pos = RosName.find_last_of('.');
237 if (pos != std::string::npos) {
238 std::string lastToken = RosName.substr(pos + 1) + "__";
239 ROS2->AddActorRosName(static_cast<void*>(&Actor), lastToken);
240 }
241 }
242 } else {
243 ROS2->AddActorRosName(static_cast<void*>(&Actor), RosName);
244 }
245
246 // 英雄载具控制器
247 for (auto &&Attr : Description.Variations)
248 { // 如果找到一个键为"role_name"且值为"hero"或"ego"的属性
249 if (Attr.Key == "role_name" && (Attr.Value.Value == "hero" || Attr.Value.Value == "ego"))
250 {
251 ROS2->AddActorCallback(static_cast<void*>(&Actor), RosName, [RosName](void *Actor, carla::ros2::ROS2CallbackData Data) -> void
252 {
253 AActor *UEActor = reinterpret_cast<AActor *>(Actor);
254 ActorROS2Handler Handler(UEActor, RosName);
255 boost::variant2::visit(Handler, Data);
256 });
257 }
258 }
259 }
260 #endif
261 }
262 return View;
263}
264// UActorDispatcher 类是一个用于管理CARLA模拟器中actor(如车辆、行人等)的调度器。
265// 它提供了将actor置于休眠状态、唤醒actor以及处理actor销毁事件的方法
266void UActorDispatcher::PutActorToSleep(FCarlaActor::IdType Id, UCarlaEpisode* CarlaEpisode)
267{
268 Registry.PutActorToSleep(Id, CarlaEpisode);
269}
270// 唤醒指定的actor
271void UActorDispatcher::WakeActorUp(FCarlaActor::IdType Id, UCarlaEpisode* CarlaEpisode)
272{// 调用Registry的WakeActorUp方法,唤醒指定的actor
273 Registry.WakeActorUp(Id, CarlaEpisode);
274}
275
277{
278 FCarlaActor* CarlaActor = Registry.FindCarlaActor(Actor);// 尝试在Registry中找到与该Unreal Engine actor对应的CARLA actor
279 if (CarlaActor)
280 {
281 if (CarlaActor->IsActive())
282 {
283 Registry.Deregister(CarlaActor->GetActorId());
284 }
285 }
286// 如果定义了WITH_ROS2宏,表示项目集成了ROS 2
287 #if defined(WITH_ROS2)
288 auto ROS2 = carla::ros2::ROS2::GetInstance();
289 if (ROS2->IsEnabled())
290 {
291 ROS2->RemoveActorRosName(reinterpret_cast<void *>(Actor));
292 }
293 #endif
294}
UE_LOG(LogCarla, Log, TEXT("UActorDispatcher::Destroying actor: '%s' %x"), *Id, Actor)
TSharedPtr< const FActorInfo > carla::rpc::ActorState UWorld Actor
virtual TArray< FActorDefinition > GetDefinitions()
virtual FActorSpawnResult SpawnActor(const FTransform &SpawnAtTransform, const FActorDescription &ActorDescription)
static void TagActor(const AActor &Actor, bool bTagForSemanticSegmentation)
设置角色的标签。
Definition Tagger.cpp:106
FCarlaActor::IdType IdType
FCarlaActor * Register(AActor &Actor, FActorDescription Description, IdType DesiredId=0)
名称 参与者注册函数
void Deregister(IdType Id)
FCarlaActor * FindCarlaActor(IdType Id)
查看一个参与者和它的属性
Definition CarlaActor.h:23
AActor * GetActor()
Definition CarlaActor.h:75
uint32 IdType
Definition CarlaActor.h:25
bool IsActive() const
Definition CarlaActor.h:55
const FActorInfo * GetActorInfo() const
Definition CarlaActor.h:83
IdType GetActorId() const
Definition CarlaActor.h:67
static bool CheckActorDefinition(const FActorDefinition &ActorDefinitions)
返回角色定义是否有效。打印所有找到的错误
void OnActorDestroyed(AActor *Actor)
TFunction< FActorSpawnResult(const FTransform &, const FActorDescription &)> SpawnFunctionType
void Bind(FActorDefinition Definition, SpawnFunctionType SpawnFunction)
void PutActorToSleep(FCarlaActor::IdType Id, UCarlaEpisode *CarlaEpisode)
FActorRegistry Registry
void WakeActorUp(FCarlaActor::IdType Id, UCarlaEpisode *CarlaEpisode)
bool DestroyActor(AActor *Actor)
FCarlaActor * RegisterActor(AActor &Actor, FActorDescription ActorDescription, FActorRegistry::IdType DesiredId=0)
AActor * ReSpawnActor(const FTransform &Transform, FActorDescription ActorDescription)
TPair< EActorSpawnResultStatus, FCarlaActor * > SpawnActor(const FTransform &Transform, FActorDescription ActorDescription, FCarlaActor::IdType DesiredId=0)
TArray< FActorDefinition > Definitions
TArray< SpawnFunctionType > SpawnFunctions
TArray< TSubclassOf< AActor > > Classes
static std::shared_ptr< ROS2 > GetInstance()
Definition ROS2.h:51
boost::variant2::variant< VehicleControl > ROS2CallbackData
TSubclassOf< AActor > Class
要生成的参与者类(可选)
TMap< FString, FActorAttribute > Variations
用户选择了参与者的变化版本。请注意,此时是 由不可修改的属性表示
FActorDescription Description
Definition ActorInfo.h:31
EActorSpawnResultStatus Status