CARLA
Loading...
Searching...
No Matches
Tagger.cpp
Go to the documentation of this file.
1// Copyright (c) 2026 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 "Tagger.h"
8#include "Carla.h"
10
11#include <util/ue-header-guard-begin.h>
12#include "Components/SkeletalMeshComponent.h"
13#include "Components/StaticMeshComponent.h"
14#include "Engine/SkeletalMesh.h"
15#include "Engine/StaticMesh.h"
16#include "EngineUtils.h"
17#include "PhysicsEngine/PhysicsAsset.h"
18#include <util/ue-header-guard-end.h>
19
20namespace crp = carla::rpc;
21
22template <typename T>
23static auto CastEnum(T label)
24{
25 return static_cast<typename std::underlying_type<T>::type>(label);
26}
27
29 if (String == "Building") return crp::CityObjectLabel::Buildings;
30 else if (String == "Fence") return crp::CityObjectLabel::Fences;
31 else if (String == "Pedestrian") return crp::CityObjectLabel::Pedestrians;
32 else if (String == "Pole") return crp::CityObjectLabel::Poles;
33 else if (String == "Other") return crp::CityObjectLabel::Other;
34 else if (String == "Road") return crp::CityObjectLabel::Roads;
35 else if (String == "RoadLine") return crp::CityObjectLabel::RoadLines;
36 else if (String == "SideWalk") return crp::CityObjectLabel::Sidewalks;
37 else if (String == "TrafficSign") return crp::CityObjectLabel::TrafficSigns;
38 else if (String == "Vegetation") return crp::CityObjectLabel::Vegetation;
39 else if (String == "Car") return crp::CityObjectLabel::Car;
40 else if (String == "Wall") return crp::CityObjectLabel::Walls;
41 else if (String == "Sky") return crp::CityObjectLabel::Sky;
42 else if (String == "Ground") return crp::CityObjectLabel::Ground;
43 else if (String == "Bridge") return crp::CityObjectLabel::Bridge;
44 else if (String == "RailTrack") return crp::CityObjectLabel::RailTrack;
45 else if (String == "GuardRail") return crp::CityObjectLabel::GuardRail;
46 else if (String == "TrafficLight") return crp::CityObjectLabel::TrafficLight;
47 else if (String == "Static") return crp::CityObjectLabel::Static;
48 else if (String == "Dynamic") return crp::CityObjectLabel::Dynamic;
49 else if (String == "Water") return crp::CityObjectLabel::Water;
50 else if (String == "Terrain") return crp::CityObjectLabel::Terrain;
51 else if (String == "Truck") return crp::CityObjectLabel::Truck;
52 else if (String == "Motorcycle") return crp::CityObjectLabel::Motorcycle;
53 else if (String == "Bicycle") return crp::CityObjectLabel::Bicycle;
54 else if (String == "Bus") return crp::CityObjectLabel::Bus;
55 else if (String == "Rider") return crp::CityObjectLabel::Rider;
56 else if (String == "Train") return crp::CityObjectLabel::Train;
57 else if (String == "Rock") return crp::CityObjectLabel::Rock;
58 else if (String == "Stone") return crp::CityObjectLabel::Rock;
59 else if (String == "Bush") return crp::CityObjectLabel::Vegetation;
60 else return crp::CityObjectLabel::None;
61}
62
63void ATagger::SetStencilValue( UPrimitiveComponent &Component, const uint32 ActorID, const crp::CityObjectLabel &Label, const bool bSetRenderCustomDepth)
64{
65
66static TMap<unsigned short, unsigned int> TruncatedIDUsedDebug;
67
68#ifdef CARLA_TAGGER_EXTRA_LOG
69 unsigned short truncated_id = static_cast<unsigned short>(ActorID);
70 if(TruncatedIDUsedDebug.Contains(truncated_id)){
71 UE_LOG(LogCarla, Warning, TEXT("Warning: The Instance ID %d has been used %d time/s previously on this scene"), truncated_id, TruncatedIDUsedDebug[truncated_id]);
72 TruncatedIDUsedDebug[truncated_id]++;
73 }
74 else
75 {
76 TruncatedIDUsedDebug.Emplace(truncated_id, 1);
77 }
78#endif //CARLA_TAGGER_EXTRA_LOG
79
80 Component.SetCustomPrimitiveDataVector4(4, FVector4((float) ActorID, (float) CastEnum(Label), 0.0f, 0.0f));
81}
82
84{
85 return (Label == crp::CityObjectLabel::Pedestrians ||
86 Label == crp::CityObjectLabel::TrafficSigns ||
87 Label == crp::CityObjectLabel::Car ||
88 Label == crp::CityObjectLabel::Train ||
89 Label == crp::CityObjectLabel::Bicycle ||
90 Label == crp::CityObjectLabel::Motorcycle ||
91 Label == crp::CityObjectLabel::Bus ||
92 Label == crp::CityObjectLabel::Rider ||
93 Label == crp::CityObjectLabel::Truck ||
94 Label == crp::CityObjectLabel::TrafficLight);
95}
96
97FLinearColor ATagger::GetActorLabelColor(const AActor &Actor, const crp::CityObjectLabel &Label)
98{
99 uint32 id = Actor.GetUniqueID();
100 // TODO: Warn if id > 0xffff.
101
102 // Encode label and id like semantic segmentation does
103 // TODO: Steal bits from R channel and maybe A channel?
104 FLinearColor Color(0.0f, 0.0f, 0.0f, 1.0f);
105 Color.R = CastEnum(Label) / 255.0f;
106 Color.G = ((id & 0x00ff) >> 0) / 255.0f;
107 Color.B = ((id & 0xff00) >> 8) / 255.0f;
108
109 return Color;
110}
111
112
113// =============================================================================
114// -- static ATagger functions -------------------------------------------------
115// =============================================================================
116
117/// Sets the label tag of a component. Actors are tagged more than once (the
118/// OnActorSpawned delegate runs before a factory assigns the mesh, streamed
119/// levels are re-tagged by TagActorsInLevel) and GetTagOfTaggedComponent reads
120/// ComponentTags[0], so a previous label tag is replaced instead of appended.
121static void ATagger_SetLabelTag(UPrimitiveComponent &Component, crp::CityObjectLabel Label)
122{
123 Component.ComponentTags.RemoveAll([](const FName &Tag) {
124 const FString TagString = Tag.ToString();
125 return ATagger::GetTagAsString(ATagger::GetTagFromString(TagString)) == TagString;
126 });
127 Component.ComponentTags.Insert(FName(*ATagger::GetTagAsString(Label)), 0);
128}
129
130void ATagger::TagActor(const AActor &Actor, bool bTagForSemanticSegmentation)
131{
132#ifdef CARLA_TAGGER_EXTRA_LOG
133 UE_LOG(LogCarla, Log, TEXT("Actor: %s"), *Actor.GetName());
134#endif // CARLA_TAGGER_EXTRA_LOG
135
136 // Iterate static meshes.
137 TArray<UStaticMeshComponent *> StaticMeshComponents;
138 Actor.GetComponents<UStaticMeshComponent>(StaticMeshComponents);
139
140 for (UStaticMeshComponent *Component : StaticMeshComponents)
141 {
142 auto Label = GetLabelByPath(Component->GetStaticMesh());
143 if (Label == crp::CityObjectLabel::Pedestrians && Cast<ACarlaWheeledVehicle>(&Actor))
144 {
145 Label = crp::CityObjectLabel::Rider;
146 }
147
148 SetStencilValue(*Component, Actor.GetUniqueID(), Label, bTagForSemanticSegmentation);
149 ATagger_SetLabelTag(*Component, Label);
150 #ifdef CARLA_TAGGER_EXTRA_LOG
151 UE_LOG(LogCarla, Log, TEXT(" + StaticMeshComponent: %s"), *Component->GetName());
152 UE_LOG(LogCarla, Log, TEXT(" - Label: \"%s\""), *GetTagAsString(Label));
153 #endif // CARLA_TAGGER_EXTRA_LOG
154 }
155
156 // Iterate skeletal meshes.
157 TArray<USkeletalMeshComponent *> SkeletalMeshComponents;
158 Actor.GetComponents<USkeletalMeshComponent>(SkeletalMeshComponents);
159
160 for (USkeletalMeshComponent *Component : SkeletalMeshComponents) {
161 auto Label = GetLabelByPath(Component->GetPhysicsAsset());
162 if (Label == crp::CityObjectLabel::Pedestrians && Cast<ACarlaWheeledVehicle>(&Actor))
163 {
164 Label = crp::CityObjectLabel::Rider;
165 }
166
167 SetStencilValue(*Component, Actor.GetUniqueID(), Label, bTagForSemanticSegmentation);
168 ATagger_SetLabelTag(*Component, Label);
169 #ifdef CARLA_TAGGER_EXTRA_LOG
170 UE_LOG(LogCarla, Log, TEXT(" + SkeletalMeshComponent: %s"), *Component->GetName());
171 UE_LOG(LogCarla, Log, TEXT(" - Label: \"%s\""), *GetTagAsString(Label));
172 #endif // CARLA_TAGGER_EXTRA_LOG
173 }
174
175}
176
177void ATagger::TagActorsInLevel(UWorld &World, bool bTagForSemanticSegmentation)
178{
179 for (TActorIterator<AActor> it(&World); it; ++it) {
181 }
182}
183
184
185void ATagger::TagActorsInLevel(ULevel &Level, bool bTagForSemanticSegmentation)
186{
187 for (AActor * Actor : Level.Actors) {
189 }
190}
191
193{
194 static const TMap<FName, crp::CityObjectLabel> KnownTags = []()
195 {
196 TMap<FName, crp::CityObjectLabel> Map;
197 for (uint8 Value = 0; Value <= static_cast<uint8>(crp::CityObjectLabel::Rock); ++Value)
198 {
199 const FString Name = GetTagAsString(static_cast<crp::CityObjectLabel>(Value));
200 Map.Add(FName(*Name), GetTagFromString(Name));
201 }
202 return Map;
203 }();
204
205 if (const crp::CityObjectLabel* Found = KnownTags.Find(Tag))
206 {
207 return *Found;
208 }
209
210 return GetTagFromString(Tag.ToString());
211}
212
213crp::CityObjectLabel ATagger::GetTagOfTaggedComponent(const UPrimitiveComponent &Component)
214{
215 if (Component.ComponentTags.Num() > 0) {
216 return GetTagFromName(Component.ComponentTags[0]);
217 }
218 return static_cast<crp::CityObjectLabel>(Component.CustomDepthStencilValue);
219}
220
221void ATagger::GetTagsOfTaggedActor(const AActor &Actor, TSet<crp::CityObjectLabel> &Tags)
222{
223 TArray<UPrimitiveComponent *> Components;
224 Actor.GetComponents<UPrimitiveComponent>(Components);
225 for (auto *Component : Components) {
226 if (Component != nullptr) {
227 const auto Tag = GetTagOfTaggedComponent(*Component);
228 if (Tag != crp::CityObjectLabel::None) {
229 Tags.Add(Tag);
230 }
231 }
232 }
233}
234
236{
237 if(Tag.Contains("Building")) return crp::CityObjectLabel::Buildings;
238 if(Tag.Contains("Fence")) return crp::CityObjectLabel::Fences;
239 if(Tag.Contains("Pedestrian")) return crp::CityObjectLabel::Pedestrians;
240 if(Tag.Contains("Pole")) return crp::CityObjectLabel::Poles;
241 if(Tag.Contains("Other")) return crp::CityObjectLabel::Other;
242 if(Tag.Contains("Roads")) return crp::CityObjectLabel::Roads;
243 if(Tag.Contains("RoadLine")) return crp::CityObjectLabel::RoadLines;
244 if(Tag.Contains("SideWalk")) return crp::CityObjectLabel::Sidewalks;
245 if(Tag.Contains("TrafficSign")) return crp::CityObjectLabel::TrafficSigns;
246 if(Tag.Contains("Vegetation")) return crp::CityObjectLabel::Vegetation;
247 if(Tag.Contains("Car")) return crp::CityObjectLabel::Car;
248 if(Tag.Contains("Wall")) return crp::CityObjectLabel::Walls;
249 if(Tag.Contains("Sky")) return crp::CityObjectLabel::Sky;
250 if(Tag.Contains("Ground")) return crp::CityObjectLabel::Ground;
251 if(Tag.Contains("Bridge")) return crp::CityObjectLabel::Bridge;
252 if(Tag.Contains("RailTrack")) return crp::CityObjectLabel::RailTrack;
253 if(Tag.Contains("GuardRail")) return crp::CityObjectLabel::GuardRail;
254 if(Tag.Contains("TrafficLight")) return crp::CityObjectLabel::TrafficLight;
255 if(Tag.Contains("Static")) return crp::CityObjectLabel::Static;
256 if(Tag.Contains("Dynamic")) return crp::CityObjectLabel::Dynamic;
257 if(Tag.Contains("Water")) return crp::CityObjectLabel::Water;
258 if(Tag.Contains("Terrain")) return crp::CityObjectLabel::Terrain;
259 if(Tag.Contains("Truck")) return crp::CityObjectLabel::Truck;
260 if(Tag.Contains("Motorcycle")) return crp::CityObjectLabel::Motorcycle;
261 if(Tag.Contains("Bicycle")) return crp::CityObjectLabel::Bicycle;
262 if(Tag.Contains("Bus")) return crp::CityObjectLabel::Bus;
263 if(Tag.Contains("Rider")) return crp::CityObjectLabel::Rider;
264 if(Tag.Contains("Train")) return crp::CityObjectLabel::Train;
265 if(Tag.Contains("Rock")) return crp::CityObjectLabel::Rock;
266 return crp::CityObjectLabel::None;
267}
268
270{
271 switch (Label) {
272#define CARLA_GET_LABEL_STR(lbl) case crp::CityObjectLabel:: lbl : return TEXT(#lbl);
273 default:
275 CARLA_GET_LABEL_STR(Buildings)
276 CARLA_GET_LABEL_STR(Fences)
278 CARLA_GET_LABEL_STR(Pedestrians)
280 CARLA_GET_LABEL_STR(RoadLines)
282 CARLA_GET_LABEL_STR(Sidewalks)
283 CARLA_GET_LABEL_STR(TrafficSigns)
284 CARLA_GET_LABEL_STR(Vegetation)
288 CARLA_GET_LABEL_STR(Ground)
289 CARLA_GET_LABEL_STR(Bridge)
290 CARLA_GET_LABEL_STR(RailTrack)
291 CARLA_GET_LABEL_STR(GuardRail)
293 CARLA_GET_LABEL_STR(Static)
294 CARLA_GET_LABEL_STR(Dynamic)
296 CARLA_GET_LABEL_STR(Terrain)
298 CARLA_GET_LABEL_STR(Motorcycle)
299 CARLA_GET_LABEL_STR(Bicycle)
304
305#undef CARLA_GET_LABEL_STR
306 }
307}
308
309// =============================================================================
310// -- non-static ATagger functions ---------------------------------------------
311// =============================================================================
312
314{
315 PrimaryActorTick.bCanEverTick = false;
316}
317
318#if WITH_EDITOR
319void ATagger::PostEditChangeProperty(FPropertyChangedEvent& PropertyChangedEvent)
320{
321 Super::PostEditChangeProperty(PropertyChangedEvent);
322 if (PropertyChangedEvent.Property) {
323 if (bTriggerTagObjects && (GetWorld() != nullptr)) {
325 }
326 }
327 bTriggerTagObjects = false;
328}
329#endif // WITH_EDITOR
static void ATagger_SetLabelTag(UPrimitiveComponent &Component, crp::CityObjectLabel Label)
Sets the label tag of a component.
Definition Tagger.cpp:121
static auto CastEnum(T label)
Definition Tagger.cpp:23
#define CARLA_GET_LABEL_STR(lbl)
static void GetTagsOfTaggedActor(const AActor &Actor, TSet< crp::CityObjectLabel > &Tags)
Retrieve the tags of an already tagged actor.
Definition Tagger.cpp:221
static bool IsThing(const crp::CityObjectLabel &Label)
Definition Tagger.cpp:83
static FString GetTagAsString(crp::CityObjectLabel Tag)
Transform a CityObjectLabel into a string.
Definition Tagger.cpp:269
static crp::CityObjectLabel GetLabelByFolderName(const FString &String)
Method that computes the label corresponding to a folder path.
Definition Tagger.cpp:28
static crp::CityObjectLabel GetTagFromName(const FName &Tag)
Transform a tag name into a CityObjectLabel.
Definition Tagger.cpp:192
static crp::CityObjectLabel GetTagOfTaggedComponent(const UPrimitiveComponent &Component)
Retrieve the tag of an already tagged component.
Definition Tagger.cpp:213
static void SetStencilValue(UPrimitiveComponent &Component, const uint32 ActorID, const crp::CityObjectLabel &Label, const bool bSetRenderCustomDepth)
Definition Tagger.cpp:63
bool bTriggerTagObjects
Definition Tagger.h:152
ATagger()
Definition Tagger.cpp:313
static crp::CityObjectLabel GetLabelByPath(const T *Object)
Method that computes the label corresponding to an specific object using the folder path in which it ...
Definition Tagger.h:81
bool bTagForSemanticSegmentation
Definition Tagger.h:155
static void TagActor(const AActor &Actor, bool bTagForSemanticSegmentation)
Set the tag of an actor.
Definition Tagger.cpp:130
static void TagActorsInLevel(UWorld &World, bool bTagForSemanticSegmentation)
Set the tag of every actor in level.
Definition Tagger.cpp:177
static crp::CityObjectLabel GetTagFromString(FString Tag)
Transform a string into a CityObjectLabel.
Definition Tagger.cpp:235
static FLinearColor GetActorLabelColor(const AActor &Actor, const crp::CityObjectLabel &Label)
Definition Tagger.cpp:97