12#include "FileHelper.h"
13#include "HighResScreenshot.h"
17#include "DrawDebugHelpers.h"
23#define LOCTEXT_NAMESPACE "CarlaRoadMap"
37 return FMath::Clamp(FMath::FloorToInt(Value), Min, Max);
48 const FVector2D SphericalCoords = Direction.UnitCartesianToSpherical();
50 return SphericalCoords.Y + PI;
81 return FColor(0u, 0u, 0u, 255u);
85 return FColor(255u, 255u, 255u, 255u);
88 auto ToColor = [](
float X){
89 return FMath::FloorToInt(256.0 * (X + PI) / (2.0f * PI)) % 256;
94 return FColor(0u, 255u, ToColor(Azimuth), 255u);
105 Super(ObjectInitializer),
107 PixelsPerCentimeter(1.0f),
119 "Declaration map of FRoadMapPixelData's value does not match current serialization type");
129 const uint32 inWidth,
130 const uint32 inHeight,
131 const float inPixelsPerCentimeter,
132 const FTransform &inWorldToMap,
133 const FVector &inMapOffset)
154 const FTransform &Transform,
155 const bool bInvertDirection)
157 bool bIsRoad =
false;
158 bool bHasDirection =
false;
159 FVector Direction(0.0f, 0.0f, 0.0f);
162 auto Rotator = Transform.GetRotation().Rotator();
169 case ECityMapMeshTag::RoadTwoLanes_LaneRight:
170 case ECityMapMeshTag::Road90DegTurn_Lane1:
171 case ECityMapMeshTag::RoadTIntersection_Lane1:
172 case ECityMapMeshTag::RoadTIntersection_Lane9:
173 case ECityMapMeshTag::RoadXIntersection_Lane1:
174 case ECityMapMeshTag::RoadXIntersection_Lane9:
176 bHasDirection =
true;
178 Rotator.Yaw += 180.0f;
180 case ECityMapMeshTag::RoadTwoLanes_LaneLeft:
181 case ECityMapMeshTag::Road90DegTurn_Lane0:
182 case ECityMapMeshTag::RoadTIntersection_Lane0:
183 case ECityMapMeshTag::RoadTIntersection_Lane2:
184 case ECityMapMeshTag::RoadTIntersection_Lane5:
185 case ECityMapMeshTag::RoadTIntersection_Lane8:
186 case ECityMapMeshTag::RoadXIntersection_Lane0:
187 case ECityMapMeshTag::RoadXIntersection_Lane8:
189 bHasDirection =
true;
191 case ECityMapMeshTag::Road90DegTurn_Lane9:
192 case ECityMapMeshTag::RoadTIntersection_Lane7:
193 case ECityMapMeshTag::RoadXIntersection_Lane7:
194 case ECityMapMeshTag::RoadXIntersection_Lane5:
196 bHasDirection =
true;
198 Rotator.Yaw += 90.0f;
200 case ECityMapMeshTag::Road90DegTurn_Lane7:
202 bHasDirection =
true;
204 Rotator.Yaw += 90.0f;
206 case ECityMapMeshTag::Road90DegTurn_Lane5:
208 bHasDirection =
true;
210 Rotator.Yaw += 90.0f + 35.0f;
212 case ECityMapMeshTag::Road90DegTurn_Lane3:
214 bHasDirection =
true;
216 Rotator.Yaw += 90.0f + 45.0f + 20.5f;
218 case ECityMapMeshTag::Road90DegTurn_Lane8:
219 case ECityMapMeshTag::RoadTIntersection_Lane4:
220 case ECityMapMeshTag::RoadXIntersection_Lane2:
221 case ECityMapMeshTag::RoadXIntersection_Lane4:
223 bHasDirection =
true;
225 Rotator.Yaw += 270.0f;
227 case ECityMapMeshTag::Road90DegTurn_Lane6:
229 bHasDirection =
true;
231 Rotator.Yaw += 270.0f + 50.0f;
233 case ECityMapMeshTag::Road90DegTurn_Lane4:
235 bHasDirection =
true;
237 Rotator.Yaw += 270.0f + 80.0f;
239 case ECityMapMeshTag::Road90DegTurn_Lane2:
241 bHasDirection =
true;
244 case ECityMapMeshTag::RoadTIntersection_Lane3:
245 case ECityMapMeshTag::RoadTIntersection_Lane6:
246 case ECityMapMeshTag::RoadXIntersection_Lane3:
247 case ECityMapMeshTag::RoadXIntersection_Lane6:
249 bHasDirection =
false;
254 FQuat Rotation(Rotator);
257 if (bInvertDirection) {
272 const FVector RelativePosition(
297 const FTransform &BoxTransform,
298 const FVector &BoxExtent,
299 float ChecksPerCentimeter)
const
301 auto DirectionOfMovement = BoxTransform.GetRotation().GetForwardVector();
302 DirectionOfMovement.Z = 0.0f;
303 uint32 CheckCount = 0u;
305 const float Step = 1.0f / ChecksPerCentimeter;
306 for (
float X = -BoxExtent.X; X < BoxExtent.X; X += Step) {
307 for (
float Y = -BoxExtent.Y; Y < BoxExtent.Y; Y += Step) {
309 auto Location = BoxTransform.TransformPosition(FVector(X, Y, 0.0f));
311 if (!Data.IsRoad()) {
313 }
else if (Data.HasDirection() &&
314 0.0f > FVector::DotProduct(Data.GetDirection(), DirectionOfMovement)) {
320 if (CheckCount > 0u) {
322 Result.
OffRoad /=
static_cast<float>(CheckCount);
326 UE_LOG(LogCarla, Warning, TEXT(
"URoadMap::Intersect did zero checks"));
336 UE_LOG(LogCarla, Error, TEXT(
"Cannot save invalid road map to disk"));
341 const FString ImagePath = FPaths::Combine(Folder, MapName + TEXT(
".png"));
343 const FString MetadataPath = FPaths::Combine(Folder, MapName + TEXT(
".txt"));
348 TUniquePtr<TImagePixelData<FColor>> PixelData = MakeUnique<TImagePixelData<FColor>>(DestSize);
359 FFormatNamedArguments Args;
360 Args.Add(
"MapName", FText::FromString(MapName));
364 Args.Add(
"Transform", FText::FromString(
WorldToMap.ToString()));
365 Args.Add(
"Offset", FText::FromString(
MapOffset.ToString()));
368 const auto Contents = FText::Format(
369 LOCTEXT(
"RoadMapMetadata",
370 "Map name = {MapName}\n"
371 "Size = {Width}x{Height} pixels\n"
372 "Density = {CmPerPixel} cm/pixel\n"
373 "World-To-Map Transform (T|R|S) = ({Transform})\n"
374 "Map Offset = ({Offset})\n"),
377 if (!FFileHelper::SaveStringToFile(Contents.ToString(), *MetadataPath)) {
378 UE_LOG(LogCarla, Error, TEXT(
"Failed to save map metadata"));
382 UE_LOG(LogCarla, Log, TEXT(
"Saved road map to \"%s\""), *ImagePath);
389void URoadMap::Log()
const
392 const float MapSizeInMB =
399 TEXT(
"Generated road map %dx%d (%.2fMB) with %.2f cm/pixel"),
407 UE_LOG(LogCarla, Error, TEXT(
"Error generating road map"));
413void URoadMap::DrawDebugPixelsToLevel(UWorld *
World,
const bool bJustFlushDoNotDraw)
const
416 const FVector ZOffset(0.0f, 0.0f, 50.0f);
418 FlushPersistentDebugLines(
World);
420 if (!bJustFlushDoNotDraw) {
422 for (
auto X = 0u; X <
Width; ++X) {
423 for (
auto Y = 0u; Y <
Height; ++Y) {
429 auto Color = Data.EncodeAsColor();
431 if (Data.HasDirection()) {
432 const FVector ArrowEnd =
Location + 50.0f * Data.GetDirection();
433 DrawDebugDirectionalArrow(
World, Location, ArrowEnd, 60.0f, Color,
true);
435 DrawDebugPoint(
World, Location, 6.0f, Color,
true);
444#undef LOCTEXT_NAMESPACE
UE_LOG(LogCarla, Log, TEXT("UActorDispatcher::Destroying actor: '%s' %x"), *Id, Actor)
TSharedPtr< const FActorInfo > carla::rpc::ActorState UWorld * World
ECityMapMeshTag
用于标识ProceduralMapGenerator所使用的网格的标签
static uint32 ClampFloatToUInt(const float Value, int32 Min, int32 Max)
static float GetRotatedAzimuthAngle(const FVector &Direction)
static TFuture< bool > SavePixelsToDisk(UTextureRenderTarget2D &RenderTarget, const FString &FilePath)
异步保存 RenderTarget 中的像素到磁盘。
uint32 Height
地图的高度(以像素为单位)。
FVector GetWorldLocation(uint32 PixelX, uint32 PixelY) const
返回给定像素的世界位置。
int32 GetIndex(uint32 PixelX, uint32 PixelY) const
void Reset(uint32 Width, uint32 Height, float PixelsPerCentimeter, const FTransform &WorldToMap, const FVector &MapOffset)
重置当前映射 - 初始化给定大小的空映射。
void SetPixelAt(uint32 PixelX, uint32 PixelY, ECityMapMeshTag Tag, const FTransform &Transform, bool bInvertDirection=false)
URoadMap(const FObjectInitializer &ObjectInitializer)
创建有效的空地图(每个点都是越野的)。
float PixelsPerCentimeter
每厘米像素数。
TArray< uint16 > RoadMapData
FVector MapOffset
地图坐标中的偏移量。
uint32 Width
地图的宽度(以像素为单位)。
FTransform WorldToMap
世界到地图的转换。
bool SaveAsPNG(const FString &Folder, const FString &MapName) const
将当前地图另存为 PNG,并将像素数据编码为颜色。
FRoadMapIntersectionResult Intersect(const FTransform &BoxTransform, const FVector &BoxExtent, float ChecksPerCentimeter) const
将角色边界与地图相交。
FRoadMapPixelData GetDataAt(uint32 PixelX, uint32 PixelY) const
检索存储在给定像素处的数据。
Vector3D GetForwardVector() const
sensor::data::Color Color
别名定义,将sensor::data::Color命名空间下的Color类重命名为当前命名空间下的Color。
float OppositeLane
框侵入对面车道的百分比(方向错误)。
数据存储在路线图像素中。请参阅 URoadMap。
float GetDirectionAzimuthalAngle() const
获取道路方向的方位角 [-PI, PI](球面 坐标)的 S Package。
bool HasDirection() const
此像素是否定义了方向(例如,道路交叉口为 不是越野,但都没有明确的方向)。
static constexpr uint16 MaximumEncodedAngle
static uint16 Encode(bool IsRoad, bool HasDirection, const FVector &Direction)
bool IsRoad() const
此像素是否位于道路上。
static constexpr int HasDirectionRow
static constexpr int IsRoadRow
FColor EncodeAsColor() const