PythonAPI fixes, rework PixelReader.
This commit is contained in:
parent
74d19eece2
commit
3856c97f15
|
@ -69,7 +69,7 @@ set (PNG_TOOLS OFF)
|
|||
set (PNG_BUILD_ZLIB ON)
|
||||
set (ZLIB_INCLUDE_DIR ${zlib_SOURCE_DIR})
|
||||
if (WIN32)
|
||||
set (ZLIB_LIBRARY ${zlib_BINARY_DIR}/zlibstatic.lib)
|
||||
set (ZLIB_LIBRARY ${zlib_BINARY_DIR}/zlibstatic${CARLA_DEBUG_AFFIX}.lib)
|
||||
else ()
|
||||
set (ZLIB_LIBRARY ${zlib_BINARY_DIR}/libz.a)
|
||||
endif ()
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
cmake_minimum_required (VERSION 3.20.0)
|
||||
|
||||
cmake_policy (SET CMP0097 NEW)
|
||||
cmake_policy (SET CMP0091 NEW)
|
||||
cmake_policy (SET CMP0077 OLD)
|
||||
|
||||
set (CARLA_VERSION_MAJOR 0)
|
||||
|
@ -62,34 +63,14 @@ else ()
|
|||
set (LIB_EXT .a)
|
||||
endif ()
|
||||
|
||||
set (CARLA_DEFAULT_DEPENDENCY_ARGS)
|
||||
|
||||
if (CMAKE_C_COMPILER)
|
||||
list (
|
||||
APPEND CARLA_DEFAULT_DEPENDENCY_ARGS
|
||||
-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
|
||||
)
|
||||
endif ()
|
||||
|
||||
if (CMAKE_INSTALL_PREFIX)
|
||||
list (
|
||||
APPEND CARLA_DEFAULT_DEPENDENCY_ARGS
|
||||
-DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}
|
||||
)
|
||||
endif ()
|
||||
|
||||
if (CMAKE_CXX_COMPILER)
|
||||
list (
|
||||
APPEND CARLA_DEFAULT_DEPENDENCY_ARGS
|
||||
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
|
||||
)
|
||||
endif ()
|
||||
|
||||
if (CMAKE_BUILD_TYPE)
|
||||
list (
|
||||
APPEND CARLA_DEFAULT_DEPENDENCY_ARGS
|
||||
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
|
||||
)
|
||||
if (WIN32)
|
||||
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
set (CARLA_DEBUG_AFFIX d)
|
||||
set (CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreadedDebugDLL")
|
||||
else ()
|
||||
set (CARLA_DEBUG_AFFIX )
|
||||
set (CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreadedDLL")
|
||||
endif ()
|
||||
endif ()
|
||||
|
||||
set (
|
||||
|
@ -102,11 +83,12 @@ if (WIN32)
|
|||
list (APPEND CARLA_COMMON_DEFINITIONS _WIN32_WINNT=0x0601) # --- Windows 10 ---
|
||||
list (APPEND CARLA_COMMON_DEFINITIONS _CRT_SECURE_NO_WARNINGS)
|
||||
list (APPEND CARLA_COMMON_DEFINITIONS HAVE_SNPRINTF)
|
||||
list (APPEND CARLA_COMMON_DEFINITIONS _USE_MATH_DEFINES)
|
||||
endif ()
|
||||
|
||||
set (CARLA_EXCEPTION_DEFINITIONS)
|
||||
|
||||
if (ENABLE_EXCEPTIONS)
|
||||
# Nothing
|
||||
else ()
|
||||
list (APPEND CARLA_EXCEPTION_DEFINITIONS ASIO_NO_EXCEPTIONS)
|
||||
list (APPEND CARLA_EXCEPTION_DEFINITIONS BOOST_NO_EXCEPTIONS)
|
||||
|
@ -114,8 +96,6 @@ else ()
|
|||
list (APPEND CARLA_EXCEPTION_DEFINITIONS PUGIXML_NO_EXCEPTIONS)
|
||||
endif ()
|
||||
|
||||
add_compile_definitions (_USE_MATH_DEFINES)
|
||||
|
||||
include (${CARLA_WORKSPACE_PATH}/CMake/CarlaDependencies.cmake)
|
||||
|
||||
if (BUILD_CARLA_CLIENT OR BUILD_CARLA_SERVER)
|
||||
|
|
|
@ -33,5 +33,12 @@ ADepthCamera::ADepthCamera(const FObjectInitializer &ObjectInitializer)
|
|||
void ADepthCamera::PostPhysTick(UWorld *World, ELevelTick TickType, float DeltaSeconds)
|
||||
{
|
||||
TRACE_CPUPROFILER_EVENT_SCOPE(ADepthCamera::PostPhysTick);
|
||||
FPixelReader::SendPixelsInRenderThread<ADepthCamera, FColor>(*this);
|
||||
|
||||
ImageUtil::ReadSensorImageDataAsyncFColor(*this, [this](
|
||||
TArrayView<const FColor> Pixels,
|
||||
FIntPoint Size) -> bool
|
||||
{
|
||||
SendImageDataToClient(*this, Pixels);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -4,22 +4,26 @@
|
|||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#include "Carla/Sensor/ImageUtil.h"
|
||||
#include "Runtime/RHI/Public/RHISurfaceDataConversion.h"
|
||||
#include "Carla/Carla.h"
|
||||
#include <Carla/Sensor/ImageUtil.h>
|
||||
#include <Carla/Sensor/ShaderBasedSensor.h>
|
||||
#include <Carla/Carla.h>
|
||||
#include <Runtime/RHI/Public/RHISurfaceDataConversion.h>
|
||||
#include <Runtime/ImageWriteQueue/Public/ImageWriteQueue.h>
|
||||
#include <HighResScreenshot.h>
|
||||
#include <RHIGPUReadback.h>
|
||||
|
||||
|
||||
|
||||
namespace ImageUtil
|
||||
{
|
||||
void DecodePixelsByFormat(
|
||||
void* PixelData,
|
||||
int32 SourcePitch,
|
||||
FIntPoint SourceExtent,
|
||||
FIntPoint DestinationExtent,
|
||||
EPixelFormat Format,
|
||||
FReadSurfaceDataFlags Flags,
|
||||
TArrayView<FLinearColor> Out)
|
||||
bool DecodePixelsByFormat(
|
||||
const void* PixelData,
|
||||
int32 SourcePitch,
|
||||
FIntPoint SourceExtent,
|
||||
FIntPoint DestinationExtent,
|
||||
EPixelFormat Format,
|
||||
FReadSurfaceDataFlags Flags,
|
||||
TArrayView<FLinearColor> Out)
|
||||
{
|
||||
SourcePitch *= GPixelFormats[Format].BlockBytes;
|
||||
auto OutPixelCount = DestinationExtent.X * DestinationExtent.Y;
|
||||
|
@ -69,19 +73,19 @@ namespace ImageUtil
|
|||
break;
|
||||
default:
|
||||
UE_LOG(LogCarla, Warning, TEXT("Unsupported format %llu"), (unsigned long long)Format);
|
||||
check(false);
|
||||
break;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void DecodePixelsByFormat(
|
||||
void* PixelData,
|
||||
int32 SourcePitch,
|
||||
FIntPoint SourceExtent,
|
||||
FIntPoint DestinationExtent,
|
||||
EPixelFormat Format,
|
||||
FReadSurfaceDataFlags Flags,
|
||||
TArrayView<FColor> Out)
|
||||
bool DecodePixelsByFormat(
|
||||
const void* PixelData,
|
||||
int32 SourcePitch,
|
||||
FIntPoint SourceExtent,
|
||||
FIntPoint DestinationExtent,
|
||||
EPixelFormat Format,
|
||||
FReadSurfaceDataFlags Flags,
|
||||
TArrayView<FColor> Out)
|
||||
{
|
||||
SourcePitch *= GPixelFormats[Format].BlockBytes;
|
||||
auto OutPixelCount = DestinationExtent.X * DestinationExtent.Y;
|
||||
|
@ -137,8 +141,202 @@ namespace ImageUtil
|
|||
break;
|
||||
default:
|
||||
UE_LOG(LogCarla, Warning, TEXT("Unsupported format %llu"), (unsigned long long)Format);
|
||||
check(false);
|
||||
break;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ReadImageData(
|
||||
UTextureRenderTarget2D& RenderTarget,
|
||||
TArray<FColor>& Out)
|
||||
{
|
||||
check(IsInGameThread());
|
||||
auto Resource = RenderTarget.GameThread_GetRenderTargetResource();
|
||||
FReadSurfaceDataFlags ReadFlags(RCM_UNorm);
|
||||
ReadFlags.SetLinearToGamma(true);
|
||||
return Resource->ReadPixels(Out, ReadFlags);
|
||||
}
|
||||
|
||||
bool ReadImageData(
|
||||
UTextureRenderTarget2D& RenderTarget,
|
||||
TArray64<FColor>& Out)
|
||||
{
|
||||
auto Resource = RenderTarget.GameThread_GetRenderTargetResource();
|
||||
FReadSurfaceDataFlags ReadFlags(RCM_UNorm);
|
||||
ReadFlags.SetLinearToGamma(true);
|
||||
Out.SetNum(RenderTarget.GetSurfaceWidth() * RenderTarget.GetSurfaceHeight());
|
||||
return Resource->ReadPixelsPtr(Out.GetData(), ReadFlags);
|
||||
}
|
||||
|
||||
TUniquePtr<TImagePixelData<FColor>> ReadImageData(
|
||||
UTextureRenderTarget2D& RenderTarget)
|
||||
{
|
||||
const auto Size = FIntPoint(
|
||||
RenderTarget.GetSurfaceWidth(),
|
||||
RenderTarget.GetSurfaceHeight());
|
||||
auto PixelData = MakeUnique<TImagePixelData<FColor>>(Size);
|
||||
ReadImageData(RenderTarget, PixelData->Pixels);
|
||||
return TUniquePtr<TImagePixelData<FColor>>();
|
||||
}
|
||||
|
||||
TFuture<bool> SaveImageData(
|
||||
UTextureRenderTarget2D& RenderTarget,
|
||||
const FStringView& Path)
|
||||
{
|
||||
return SaveImageData(ReadImageData(RenderTarget), Path);
|
||||
}
|
||||
|
||||
TFuture<bool> SaveImageData(
|
||||
TUniquePtr<TImagePixelData<FColor>> Data,
|
||||
const FStringView& Path)
|
||||
{
|
||||
auto& HighResScreenshotConfig = GetHighResScreenshotConfig();
|
||||
auto ImageTask = MakeUnique<FImageWriteTask>();
|
||||
ImageTask->PixelData = MoveTemp(Data);
|
||||
ImageTask->Filename = Path;
|
||||
ImageTask->Format = EImageFormat::PNG;
|
||||
ImageTask->CompressionQuality = (int32)EImageCompressionQuality::Default;
|
||||
ImageTask->bOverwriteFile = true;
|
||||
ImageTask->PixelPreProcessors.Add(TAsyncAlphaWrite<FColor>(255));
|
||||
return HighResScreenshotConfig.ImageWriteQueue->Enqueue(MoveTemp(ImageTask));
|
||||
}
|
||||
|
||||
static void ReadImageDataAsyncCommand(
|
||||
UTextureRenderTarget2D& RenderTarget,
|
||||
ReadImageDataAsyncCallback&& Callback)
|
||||
{
|
||||
static thread_local auto RenderQueryPool = RHICreateRenderQueryPool(RQT_AbsoluteTime);
|
||||
|
||||
auto& CmdList = FRHICommandListImmediate::Get();
|
||||
auto Resource = static_cast<FTextureRenderTarget2DResource*>(
|
||||
RenderTarget.Resource);
|
||||
auto Texture = Resource->GetRenderTargetTexture();
|
||||
if (Texture == nullptr)
|
||||
return;
|
||||
auto Readback = MakeUnique<FRHIGPUTextureReadback>(TEXT("ReadImageData-Readback"));
|
||||
auto Size = Texture->GetSizeXY();
|
||||
auto Format = Texture->GetFormat();
|
||||
auto ResolveRect = FResolveRect();
|
||||
Readback->EnqueueCopy(CmdList, Texture, ResolveRect);
|
||||
|
||||
auto Query = RenderQueryPool->AllocateQuery();
|
||||
CmdList.EndRenderQuery(Query.GetQuery());
|
||||
CmdList.ImmediateFlush(EImmediateFlushType::FlushRHIThread);
|
||||
uint64 DeltaTime;
|
||||
RHIGetRenderQueryResult(Query.GetQuery(), DeltaTime, true);
|
||||
Query.ReleaseQuery();
|
||||
|
||||
AsyncTask(ENamedThreads::HighTaskPriority, [
|
||||
Readback = MoveTemp(Readback),
|
||||
Callback = std::move(Callback),
|
||||
Size, Format]
|
||||
{
|
||||
while (!Readback->IsReady())
|
||||
std::this_thread::yield();
|
||||
int32 RowPitch, BufferHeight;
|
||||
auto Mapping = Readback->Lock(RowPitch, &BufferHeight);
|
||||
if (Mapping != nullptr)
|
||||
Callback(Mapping, RowPitch, BufferHeight, Format, Size);
|
||||
Readback->Unlock();
|
||||
});
|
||||
}
|
||||
|
||||
bool ReadImageDataAsync(
|
||||
UTextureRenderTarget2D& RenderTarget,
|
||||
ReadImageDataAsyncCallback&& Callback)
|
||||
{
|
||||
if (IsInRenderingThread())
|
||||
{
|
||||
ReadImageDataAsyncCommand(
|
||||
RenderTarget,
|
||||
std::move(Callback));
|
||||
}
|
||||
else
|
||||
{
|
||||
ENQUEUE_RENDER_COMMAND(ReadImageDataAsyncCmd)([
|
||||
&RenderTarget,
|
||||
Callback = std::move(Callback)
|
||||
](auto& CmdList) mutable
|
||||
{
|
||||
ReadImageDataAsyncCommand(
|
||||
RenderTarget,
|
||||
std::move(Callback));
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ReadSensorImageDataAsync(
|
||||
AShaderBasedSensor& Sensor,
|
||||
ReadImageDataAsyncCallback&& Callback)
|
||||
{
|
||||
TArray<FColor> Pixels;
|
||||
auto RenderTarget = Sensor.GetCaptureRenderTarget();
|
||||
if (RenderTarget == nullptr)
|
||||
return false;
|
||||
return ReadImageDataAsync(
|
||||
*RenderTarget,
|
||||
std::move(Callback));
|
||||
}
|
||||
|
||||
|
||||
bool ReadImageDataAsyncFColor(
|
||||
UTextureRenderTarget2D& RenderTarget,
|
||||
ReadImageDataAsyncCallbackFColor&& Callback)
|
||||
{
|
||||
return ReadImageDataAsync(RenderTarget, [Callback = std::move(Callback)](
|
||||
const void* Mapping,
|
||||
size_t RowPitch,
|
||||
size_t BufferHeight,
|
||||
EPixelFormat Format,
|
||||
FIntPoint Size) -> bool
|
||||
{
|
||||
FReadSurfaceDataFlags Flags;
|
||||
TArray<FColor> Pixels;
|
||||
Pixels.SetNum(Size.X * Size.Y);
|
||||
if (!DecodePixelsByFormat(Mapping, RowPitch, Size, Size, Format, Flags, Pixels))
|
||||
return false;
|
||||
return Callback(Pixels, Size);
|
||||
});
|
||||
}
|
||||
|
||||
bool ReadSensorImageDataAsyncFColor(
|
||||
AShaderBasedSensor& Sensor,
|
||||
ReadImageDataAsyncCallbackFColor&& Callback)
|
||||
{
|
||||
auto RenderTarget = Sensor.GetCaptureRenderTarget();
|
||||
if (RenderTarget == nullptr)
|
||||
return false;
|
||||
return ReadImageDataAsyncFColor(*RenderTarget, std::move(Callback));
|
||||
}
|
||||
|
||||
bool ReadImageDataAsyncFLinearColor(
|
||||
UTextureRenderTarget2D& RenderTarget,
|
||||
ReadImageDataAsyncCallbackFLinearColor&& Callback)
|
||||
{
|
||||
return ReadImageDataAsync(RenderTarget, [Callback = std::move(Callback)](
|
||||
const void* Mapping,
|
||||
size_t RowPitch,
|
||||
size_t BufferHeight,
|
||||
EPixelFormat Format,
|
||||
FIntPoint Size) -> bool
|
||||
{
|
||||
FReadSurfaceDataFlags Flags;
|
||||
TArray<FLinearColor> Pixels;
|
||||
Pixels.SetNum(Size.X * Size.Y);
|
||||
if (!DecodePixelsByFormat(Mapping, RowPitch, Size, Size, Format, Flags, Pixels))
|
||||
return false;
|
||||
return Callback(Pixels, Size);
|
||||
});
|
||||
}
|
||||
|
||||
bool ReadSensorImageDataAsyncFLinearColor(
|
||||
AShaderBasedSensor& Sensor,
|
||||
ReadImageDataAsyncCallbackFLinearColor&& Callback)
|
||||
{
|
||||
auto RenderTarget = Sensor.GetCaptureRenderTarget();
|
||||
if (RenderTarget == nullptr)
|
||||
return false;
|
||||
return ReadImageDataAsyncFLinearColor(*RenderTarget, std::move(Callback));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,29 +5,101 @@
|
|||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
#include "CoreMinimal.h"
|
||||
#include <CoreMinimal.h>
|
||||
#include <CoreGlobals.h>
|
||||
#include <Engine/TextureRenderTarget2D.h>
|
||||
#include <Runtime/ImageWriteQueue/Public/ImagePixelData.h>
|
||||
#include <functional>
|
||||
|
||||
|
||||
|
||||
class FRHIGPUTextureReadback;
|
||||
class AShaderBasedSensor;
|
||||
class UTextureRenderTarget2D;
|
||||
|
||||
namespace ImageUtil
|
||||
{
|
||||
void DecodePixelsByFormat(
|
||||
void* PixelData,
|
||||
int32 SourcePitch,
|
||||
FIntPoint SourceExtent,
|
||||
FIntPoint DestinationExtent,
|
||||
EPixelFormat Format,
|
||||
FReadSurfaceDataFlags Flags,
|
||||
TArrayView<FColor> Out);
|
||||
bool DecodePixelsByFormat(
|
||||
const void* PixelData,
|
||||
int32 SourcePitch,
|
||||
FIntPoint SourceExtent,
|
||||
FIntPoint DestinationExtent,
|
||||
EPixelFormat Format,
|
||||
FReadSurfaceDataFlags Flags,
|
||||
TArrayView<FColor> Out);
|
||||
|
||||
void DecodePixelsByFormat(
|
||||
void* PixelData,
|
||||
int32 SourcePitch,
|
||||
FIntPoint SourceExtent,
|
||||
FIntPoint DestinationExtent,
|
||||
EPixelFormat Format,
|
||||
FReadSurfaceDataFlags Flags,
|
||||
TArrayView<FLinearColor> Out);
|
||||
bool DecodePixelsByFormat(
|
||||
const void* PixelData,
|
||||
int32 SourcePitch,
|
||||
FIntPoint SourceExtent,
|
||||
FIntPoint DestinationExtent,
|
||||
EPixelFormat Format,
|
||||
FReadSurfaceDataFlags Flags,
|
||||
TArrayView<FLinearColor> Out);
|
||||
|
||||
bool ReadImageData(
|
||||
UTextureRenderTarget2D& RenderTarget,
|
||||
TArray<FColor>& Out);
|
||||
|
||||
bool ReadImageData(
|
||||
UTextureRenderTarget2D& RenderTarget,
|
||||
TArray64<FColor>& Out);
|
||||
|
||||
TUniquePtr<TImagePixelData<FColor>> ReadImageData(
|
||||
UTextureRenderTarget2D& RenderTarget);
|
||||
|
||||
TFuture<bool> SaveImageData(
|
||||
UTextureRenderTarget2D& RenderTarget,
|
||||
const FStringView& Path);
|
||||
|
||||
TFuture<bool> SaveImageData(
|
||||
TUniquePtr<TImagePixelData<FColor>> Data,
|
||||
const FStringView& Path);
|
||||
|
||||
using ReadImageDataAsyncCallback = std::function<
|
||||
bool(
|
||||
const void*, // MappedData
|
||||
size_t, // RowPitch
|
||||
size_t, // BufferHeight
|
||||
EPixelFormat, // Format
|
||||
FIntPoint // Extent
|
||||
)
|
||||
>;
|
||||
|
||||
using ReadImageDataAsyncCallbackFColor = std::function<
|
||||
bool(
|
||||
TArrayView<const FColor>, // Data
|
||||
FIntPoint // Extent
|
||||
)
|
||||
>;
|
||||
|
||||
using ReadImageDataAsyncCallbackFLinearColor = std::function<
|
||||
bool(
|
||||
TArrayView<const FLinearColor>, // Data
|
||||
FIntPoint // Extent
|
||||
)
|
||||
>;
|
||||
|
||||
bool ReadImageDataAsync(
|
||||
UTextureRenderTarget2D& RenderTarget,
|
||||
ReadImageDataAsyncCallback&& Callback);
|
||||
|
||||
bool ReadSensorImageDataAsync(
|
||||
AShaderBasedSensor& Sensor,
|
||||
ReadImageDataAsyncCallback&& Callback);
|
||||
|
||||
bool ReadImageDataAsyncFColor(
|
||||
UTextureRenderTarget2D& RenderTarget,
|
||||
ReadImageDataAsyncCallbackFColor&& Callback);
|
||||
|
||||
bool ReadSensorImageDataAsyncFColor(
|
||||
AShaderBasedSensor& Sensor,
|
||||
ReadImageDataAsyncCallbackFColor&& Callback);
|
||||
|
||||
bool ReadImageDataAsyncFLinearColor(
|
||||
UTextureRenderTarget2D& RenderTarget,
|
||||
ReadImageDataAsyncCallbackFLinearColor&& Callback);
|
||||
|
||||
bool ReadSensorImageDataAsyncFLinearColor(
|
||||
AShaderBasedSensor& Sensor,
|
||||
ReadImageDataAsyncCallbackFLinearColor&& Callback);
|
||||
}
|
||||
|
|
|
@ -62,7 +62,13 @@ void AInstanceSegmentationCamera::PostPhysTick(UWorld *World, ELevelTick TickTyp
|
|||
UPrimitiveComponent *Component = Cast<UPrimitiveComponent>(Object);
|
||||
SceneCapture->ShowOnlyComponents.Emplace(Component);
|
||||
}
|
||||
|
||||
|
||||
FPixelReader::SendPixelsInRenderThread<AInstanceSegmentationCamera, FColor>(*this);
|
||||
|
||||
ImageUtil::ReadSensorImageDataAsyncFColor(*this, [this](
|
||||
TArrayView<const FColor> Pixels,
|
||||
FIntPoint Size) -> bool
|
||||
{
|
||||
SendImageDataToClient(*this, Pixels);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -27,5 +27,13 @@ ANormalsCamera::ANormalsCamera(const FObjectInitializer &ObjectInitializer)
|
|||
void ANormalsCamera::PostPhysTick(UWorld *World, ELevelTick TickType, float DeltaSeconds)
|
||||
{
|
||||
TRACE_CPUPROFILER_EVENT_SCOPE(ANormalsCamera::PostPhysTick);
|
||||
FPixelReader::SendPixelsInRenderThread<ANormalsCamera, FColor>(*this);
|
||||
|
||||
|
||||
ImageUtil::ReadSensorImageDataAsyncFColor(*this, [this](
|
||||
TArrayView<const FColor> Pixels,
|
||||
FIntPoint Size) -> bool
|
||||
{
|
||||
SendImageDataToClient(*this, Pixels);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -108,9 +108,6 @@ void FPixelReader::SendPixelsInRenderThread(TSensor& Sensor, bool use16BitFormat
|
|||
/// Blocks until the render thread has finished all it's tasks.
|
||||
Sensor.EnqueueRenderSceneImmediate();
|
||||
FlushRenderingCommands();
|
||||
SavePixelsToDisk(
|
||||
*Sensor.CaptureRenderTarget,
|
||||
TEXT("F:\\Carla\\PythonAPI\\examples\\_out\\image.png"));
|
||||
|
||||
// Enqueue a command in the render-thread that will write the image buffer to
|
||||
// the data stream. The stream is created in the capture thus executed in the
|
||||
|
|
|
@ -62,7 +62,14 @@ void ASceneCaptureCamera::PostPhysTick(UWorld *World, ELevelTick TickType, float
|
|||
TRACE_CPUPROFILER_EVENT_SCOPE_TEXT(*ProfilerText);
|
||||
}
|
||||
);
|
||||
FPixelReader::SendPixelsInRenderThread<ASceneCaptureCamera, FColor>(*this);
|
||||
|
||||
ImageUtil::ReadSensorImageDataAsyncFColor(*this, [this](
|
||||
TArrayView<const FColor> Pixels,
|
||||
FIntPoint Size) -> bool
|
||||
{
|
||||
SendImageDataToClient(*this, Pixels);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
#ifdef CARLA_HAS_GBUFFER_API
|
||||
|
|
|
@ -27,5 +27,12 @@ ASemanticSegmentationCamera::ASemanticSegmentationCamera(
|
|||
void ASemanticSegmentationCamera::PostPhysTick(UWorld *World, ELevelTick TickType, float DeltaSeconds)
|
||||
{
|
||||
TRACE_CPUPROFILER_EVENT_SCOPE(ASemanticSegmentationCamera::PostPhysTick);
|
||||
FPixelReader::SendPixelsInRenderThread<ASemanticSegmentationCamera, FColor>(*this);
|
||||
|
||||
ImageUtil::ReadSensorImageDataAsyncFColor(*this, [this](
|
||||
TArrayView<const FColor> Pixels,
|
||||
FIntPoint Size) -> bool
|
||||
{
|
||||
SendImageDataToClient(*this, Pixels);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
|
|
@ -4,15 +4,15 @@
|
|||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#include "Carla/Sensor/Sensor.h"
|
||||
#include "Carla.h"
|
||||
#include "Carla/Sensor/SensorManager.h"
|
||||
|
||||
#include "Carla/Actor/ActorDescription.h"
|
||||
#include "Carla/Actor/ActorBlueprintFunctionLibrary.h"
|
||||
#include "Carla/Game/CarlaStatics.h"
|
||||
|
||||
#include "Engine/CollisionProfile.h"
|
||||
#include <Carla/Sensor/Sensor.h>
|
||||
#include <Carla.h>
|
||||
#include <Carla/Sensor/SensorManager.h>
|
||||
#include <Carla/Actor/ActorDescription.h>
|
||||
#include <Carla/Actor/ActorBlueprintFunctionLibrary.h>
|
||||
#include <Carla/Game/CarlaStatics.h>
|
||||
#include <Engine/CollisionProfile.h>
|
||||
#include <Carla/Sensor/ImageUtil.h>
|
||||
#include <Carla/Sensor/ShaderBasedSensor.h>
|
||||
|
||||
ASensor::ASensor(const FObjectInitializer &ObjectInitializer)
|
||||
: Super(ObjectInitializer)
|
||||
|
|
|
@ -14,6 +14,13 @@
|
|||
|
||||
#include "GameFramework/Actor.h"
|
||||
|
||||
#include <compiler/disable-ue4-macros.h>
|
||||
#include <carla/Logging.h>
|
||||
#include <carla/Buffer.h>
|
||||
#include <carla/BufferView.h>
|
||||
#include <carla/sensor/SensorRegistry.h>
|
||||
#include <compiler/enable-ue4-macros.h>
|
||||
|
||||
#include "Sensor.generated.h"
|
||||
|
||||
struct FActorDescription;
|
||||
|
@ -106,10 +113,70 @@ protected:
|
|||
///
|
||||
/// You need to provide a reference to self, this is necessary for template
|
||||
/// deduction.
|
||||
template <typename SensorT>
|
||||
FAsyncDataStream GetDataStream(const SensorT &Self)
|
||||
template <typename SensorType>
|
||||
FAsyncDataStream GetDataStream(SensorType&& Self)
|
||||
{
|
||||
return Stream.MakeAsyncDataStream(Self, GetEpisode().GetElapsedGameTime());
|
||||
return Stream.MakeAsyncDataStream<std::remove_cvref_t<SensorType>>(
|
||||
std::forward<SensorType>(Self),
|
||||
GetEpisode().GetElapsedGameTime());
|
||||
}
|
||||
|
||||
template <
|
||||
typename SensorType,
|
||||
typename PixelType>
|
||||
static void SendImageDataToClient(
|
||||
SensorType&& Sensor,
|
||||
TArrayView<PixelType> Pixels)
|
||||
{
|
||||
auto Stream = Sensor.GetDataStream(Sensor);
|
||||
Stream.SetFrameNumber(FCarlaEngine::GetFrameCounter());
|
||||
auto Buffer = Stream.PopBufferFromPool();
|
||||
Buffer.copy_from(0, boost::asio::buffer(Pixels.GetData(), Pixels.Num() * sizeof(FColor)));
|
||||
if (!Buffer.data())
|
||||
return;
|
||||
carla::Buffer BufferReady(
|
||||
std::move(
|
||||
carla::sensor::SensorRegistry::Serialize(
|
||||
Sensor,
|
||||
std::move(Buffer))));
|
||||
auto BufferView =
|
||||
carla::BufferView::CreateFrom(
|
||||
std::move(BufferReady));
|
||||
#if defined(WITH_ROS2)
|
||||
auto ROS2 = carla::ros2::ROS2::GetInstance();
|
||||
if (ROS2->IsEnabled())
|
||||
{
|
||||
TRACE_CPUPROFILER_EVENT_SCOPE_STR("ROS2 Send PixelReader");
|
||||
auto StreamId = carla::streaming::detail::token_type(Sensor.GetToken()).get_stream_id();
|
||||
auto Res = std::async(std::launch::async, [&Sensor, ROS2, &Stream, StreamId, BufView]()
|
||||
{
|
||||
// get resolution of camera
|
||||
int W = -1, H = -1;
|
||||
float Fov = -1.0f;
|
||||
auto WidthOpt = Sensor.GetAttribute("image_size_x");
|
||||
if (WidthOpt.has_value())
|
||||
W = FCString::Atoi(*WidthOpt->Value);
|
||||
auto HeightOpt = Sensor.GetAttribute("image_size_y");
|
||||
if (HeightOpt.has_value())
|
||||
H = FCString::Atoi(*HeightOpt->Value);
|
||||
auto FovOpt = Sensor.GetAttribute("fov");
|
||||
if (FovOpt.has_value())
|
||||
Fov = FCString::Atof(*FovOpt->Value);
|
||||
// send data to ROS2
|
||||
AActor* ParentActor = Sensor.GetAttachParentActor();
|
||||
if (ParentActor)
|
||||
{
|
||||
FTransform LocalTransformRelativeToParent = Sensor.GetActorTransform().GetRelativeTransform(ParentActor->GetActorTransform());
|
||||
ROS2->ProcessDataFromCamera(Stream.GetSensorType(), StreamId, LocalTransformRelativeToParent, W, H, Fov, BufView, &Sensor);
|
||||
}
|
||||
else
|
||||
{
|
||||
ROS2->ProcessDataFromCamera(Stream.GetSensorType(), StreamId, Stream.GetSensorTransform(), W, H, Fov, BufView, &Sensor);
|
||||
}
|
||||
});
|
||||
}
|
||||
#endif
|
||||
Stream.Send(Sensor, BufferView);
|
||||
}
|
||||
|
||||
/// Seed of the pseudo-random engine.
|
||||
|
|
Loading…
Reference in New Issue