11#include "Async/TaskGraphInterfaces.h"
12#include "Engine/Texture2D.h"
13#include "Async/ParallelFor.h"
35 PrimaryActorTick.bCanEverTick =
true;
36 PrimaryActorTick.TickGroup = TG_PostUpdateWork;
55 const int32 Size = Width * Height;
89#ifdef EngineAllowRenderingMinimized
106 PointCloudMessage->fields.Add({
"x", 0, ROSMessages::sensor_msgs::PointCloud2::PointField::UINT16, 1 });
107 PointCloudMessage->fields.Add({
"y", 2, ROSMessages::sensor_msgs::PointCloud2::PointField::UINT16, 1 });
108 PointCloudMessage->fields.Add({
"t", 4, ROSMessages::sensor_msgs::PointCloud2::PointField::UINT32, 1 });
109 PointCloudMessage->fields.Add({
"pol", 8, ROSMessages::sensor_msgs::PointCloud2::PointField::UINT8, 1 });
116 Super::EndPlay(EndPlayReason);
142 DvsTopic->ConditionalBeginDestroy();
172 UE_LOG(LogTemp, Warning, TEXT(
"DVSCamera.cpp: DVS Camera output window closed."));
183 LastImage.SetNumUninitialized(Buffer.Num());
186 ParallelFor(Buffer.Num(), [&](int32 i)
188 LastImage[i] = FColorToGrayScaleFloat(Buffer[i]);
194 const int32 Size = Buffer.Num();
200 ParallelFor(Size, [&](int32 Index)
203 LastImage[Index] = std::log(LogEps + GrayScale);
209 std::vector<DVSEvent> Events;
213 const int32 Size = Width * Height;
225 if (Buffer.Num() != Size)
239 UWorld* World = GetWorld();
259 DVSEventFill.x = 100;
260 DVSEventFill.y = 100;
261 DVSEventFill.t = 100;
264 FColor desiredColor = FColor::Black;
265 FMemory::Memset(
DVSOutput.GetData(), desiredColor.ToPackedARGB(),
DVSOutput.Num() *
sizeof(FColor));
267 static constexpr float tolerance = 1e-6;
278 for (
size_t y = 0; y < Height; y++)
280 for (
int x = 0; x < Width; ++x)
282 const uint32 i = (Width * y) + x;
287 if (std::fabs(it - itdt) > tolerance)
289 const float pol = (itdt >= it) ? +1.0 : -1.0;
290 float C = (pol > 0) ? cp : cm;
291 const float sigma_C = (pol > 0) ? sigma_cp : sigma_cm;
295 C += std::normal_distribution<float>(0, sigma_C)(
Engine);
296 constexpr float minimum_contrast_threshold = 0.01;
297 C = std::max(minimum_contrast_threshold, C);
299 float curr_cross = prev_cross;
300 bool all_crossings =
false;
303 curr_cross += pol * C;
305 if ((pol > 0 && curr_cross > it && curr_cross <= itdt)
306 || (pol < 0 && curr_cross < it && curr_cross >= itdt))
308 const std::uint64_t edt = (curr_cross - it) * delta_t_ns / (itdt - it);
314 if (t >= last_stamp_at_xy)
316 const std::uint64_t dt = t - last_stamp_at_xy;
322 DVSOutput[i] = val ? FColor::Red : FColor::Black;
331 all_crossings =
true;
333 }
while (!all_crossings);
351 return it1.t < it2.t;
369 FString RawDataTopicName = FString::Printf(TEXT(
"/agrarsense/out/sensors/%s_raw"), *ID);
371 DvsTopic = NewObject<UTopic>(UTopic::StaticClass());
372 DvsTopic->Init(
ROSInstance->ROSIntegrationCore, RawDataTopicName, TEXT(
"sensor_msgs/PointCloud2"));
376 UE_LOG(LogTemp, Warning, TEXT(
"DVSCamera.cpp: Created DVS Camera raw data ROS topic. Topic name: %s"), *RawDataTopicName);
382 FString ImageTopicName = FString::Printf(TEXT(
"/agrarsense/out/sensors/%s"), *ID);
384 ROSTopic = NewObject<UTopic>(UTopic::StaticClass());
385 ROSTopic->Init(
ROSInstance->ROSIntegrationCore, ImageTopicName, TEXT(
"sensor_msgs/Image"));
389 UE_LOG(LogTemp, Warning, TEXT(
"DVSCamera.cpp: Created DVS Camera Image ROS topic. Topic name: %s"), *ImageTopicName);
419 FGraphEventRef SendDataToROSTask = FFunctionGraphTask::CreateAndDispatchWhenReady([
this]()
422 }, TStatId(),
nullptr, ENamedThreads::AnyBackgroundHiPriTask);
430 if (SendDataToROSTask.IsValid())
432 FTaskGraphInterface::Get().WaitUntilTaskCompletes(SendDataToROSTask);
475 uint8* TextureData =
static_cast<uint8*
>(
CaptureFrameTexture->GetPlatformData()->Mips[0].BulkData.Lock(LOCK_READ_WRITE));
478 FMemory::Memcpy(TextureData, Buffer.GetData(), Buffer.Num() *
sizeof(FColor));
static constexpr float INV_MAX_VALUE
static constexpr float G_WEIGHT
static constexpr float R_WEIGHT
static constexpr float B_WEIGHT
void ChangeCameraParameters(FCameraBaseParameters newParameters)
UTexture2D * CaptureFrameTexture
FCameraDelegate_OnWindowResized OnCameraWindowResized
TSharedPtr< FUnrealWindow > UnrealWindow
int GetCameraWidth() const
int GetCameraHeight() const
float FColorToGrayScaleFloat(const FColor &Color)
void ImageToLogGray(const TArray< FColor > &Buffer)
void SendRawDVSImageDataToROS()
TSharedPtr< FUnrealWindow > DVSUnrealWindow
TArray< FColor > DVSOutput
ADVSCamera(const FObjectInitializer &ObjectInitializer)
TArray< float > PreviousImage
FOnWindowClosed OnDVSWindowClosed
virtual void AddProcessingToFrameBuffer(TArray< FColor > &buffer) override
void ChangeParametersInternal()
std::vector< DVSEvent > EventArray
TSharedPtr< ROSMessages::sensor_msgs::PointCloud2 > PointCloudMessage
FDVSCameraParameters DVSCameraParameters
void ChangeDVSCameraParameters(FDVSCameraParameters NewParameters)
void DVSWindowClosedCallback(const TSharedRef< SWindow > &Window)
TArray< float > RefValues
void Init(FCameraBaseParameters parameters, bool SimulateSensor=true) override
void CreateROSTopic() override
void DVSInit(FDVSCameraParameters Parameters, bool SimulateSensor=true)
FDVSCameraParameters TempDVSCameraParameters
TArray< double > LastEventTimestamp
void ImageToGray(const TArray< FColor > &Buffer)
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override
std::vector< DVSEvent > SimulateDVS(const TArray< FColor > &Buffer)
void OnMainCameraWindowResized(ACamera *Camera, FCameraBaseParameters Params)
TArray< float > LastImage
void UpdateDVSWindowOutput(const TArray< FColor > &Buffer)
constexpr double NanoSecToSecTrunc(std::int64_t nanoseconds)
constexpr std::int64_t SecToNanoSec(double seconds)
UROSIntegrationGameInstance * ROSInstance
bool CanSimulateSensor() const
FString GetSensorIdentifier() const
bool IsROSConnected() const
float SigmaPositiveThreshold
float SigmaNegativeThreshold
bool ParalellImageConversion
bool SortByIncreasingTimestamp
FCameraBaseParameters CameraParameters