10#include "NiagaraDataInterfaceArrayFunctionLibrary.h"
11#include "NiagaraFunctionLibrary.h"
12#include "CollisionQueryParams.h"
13#include "Async/ParallelFor.h"
14#include "NiagaraComponent.h"
15#include "DrawDebugHelpers.h"
17ARadar::ARadar(
const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer)
19 PrimaryActorTick.bCanEverTick =
true;
32 UNiagaraSystem* NS = LoadObject<UNiagaraSystem>(
nullptr, TEXT(
"/Game/Agrarsense/Particles/PointCloud/NS_PointCloudFast"),
nullptr, LOAD_None,
nullptr);
50 UE_LOG(LogTemp, Warning, TEXT(
"Radar.cpp: Couldn't find Niagara particle system."));
67 RadarMessage = MakeShared<ROSMessages::sensor_msgs::PointCloud2>();
75 RadarMessage->fields[0].datatype = ROSMessages::sensor_msgs::PointCloud2::PointField::FLOAT32;
80 RadarMessage->fields[1].datatype = ROSMessages::sensor_msgs::PointCloud2::PointField::FLOAT32;
85 RadarMessage->fields[2].datatype = ROSMessages::sensor_msgs::PointCloud2::PointField::FLOAT32;
90 RadarMessage->fields[3].datatype = ROSMessages::sensor_msgs::PointCloud2::PointField::FLOAT32;
95 RadarMessage->fields[4].datatype = ROSMessages::sensor_msgs::PointCloud2::PointField::FLOAT32;
100 RadarMessage->fields[5].datatype = ROSMessages::sensor_msgs::PointCloud2::PointField::FLOAT32;
105 RadarMessage->fields[6].datatype = ROSMessages::sensor_msgs::PointCloud2::PointField::FLOAT32;
113 Super::EndPlay(EndPlayReason);
190 const FVector RadarLocation = GetActorLocation();
201 auto TraceParams = FCollisionQueryParams(FName(TEXT(
"Laser_Trace")),
true,
this);
202 TraceParams.bTraceComplex =
true;
203 TraceParams.bReturnPhysicalMaterial =
false;
205 constexpr float TO_METERS = 1e-2;
206 const FTransform& ActorTransform = GetActorTransform();
207 const FRotator& TransformRotator = ActorTransform.Rotator();
208 const FVector& RadarLocation = GetActorLocation();
209 const FVector& ForwardVector = GetActorForwardVector();
210 const FVector TransformXAxis = ActorTransform.GetUnitAxis(EAxis::X);
211 const FVector TransformYAxis = ActorTransform.GetUnitAxis(EAxis::Y);
212 const FVector TransformZAxis = ActorTransform.GetUnitAxis(EAxis::Z);
219 bool DebugLines =
false;
220 EParallelForFlags Flag = EParallelForFlags::Unbalanced;
223 Flag = EParallelForFlags::ForceSingleThread;
227 const float MaxRx = FMath::Tan(FMath::DegreesToRadians(HorizontalFOV * 0.5f)) * Range;
228 const float MaxRy = FMath::Tan(FMath::DegreesToRadians(VerticalFOV * 0.5f)) * Range;
229 const int NumPoints = (int)(PointsPerSecond * DeltaTime);
232 Rays.resize(NumPoints);
233 for (int32 i = 0; i <
Rays.size(); i++)
235 Rays[i].Radius =
static_cast<float>(rand()) /
static_cast<float>(RAND_MAX);
236 Rays[i].Angle = 0.0f +
static_cast<float>(rand()) / (
static_cast<float>(RAND_MAX / (2 * PI - 0.0f)));
241 ParallelFor(NumPoints, [&](int32 idx)
243 FHitResult OutHit(ForceInit);
244 const float Radius =
Rays[idx].Radius;
245 const float Angle =
Rays[idx].Angle;
248 FMath::SinCos(&Sin, &Cos, Angle);
250 const FVector EndLocation = RadarLocation + TransformRotator.RotateVector({
252 MaxRx * Radius * Cos,
258#ifdef ParallelLineTraceSingleByChannel_EXISTS
259 hit =
World->ParallelLineTraceSingleByChannel(
263 ECC_GameTraceChannel3,
265 FCollisionResponseParams::DefaultResponseParam);
267 hit =
World->LineTraceSingleByChannel(
271 ECC_GameTraceChannel3,
273 FCollisionResponseParams::DefaultResponseParam);
279 DrawDebugLine(
World, RadarLocation, EndLocation, FColor::Green,
false, 1.0f);
283 const TWeakObjectPtr<AActor> Actor = OutHit.GetActor();
284 if (hit && Actor.IsValid())
286 auto point = OutHit.ImpactPoint;
288 Rays[idx].HitPoint = point;
289 Rays[idx].Hit =
true;
291 Rays[idx].AzimuthAndElevation = FMath::GetAzimuthAndElevation(
292 (EndLocation - RadarLocation).GetSafeNormal() * Range,
297 Rays[idx].Distance = OutHit.Distance * TO_METERS;
311 for (
auto& ray :
Rays)
316 ray.RelativeVelocity,
317 (float)ray.AzimuthAndElevation.X,
318 (
float)ray.AzimuthAndElevation.Y,
342 constexpr float TO_METERS = 1e-2;
344 const FVector TargetVelocity = ActorVelocity;
345 const FVector TargetLocation = (OutHit.ImpactPoint * TO_METERS);
346 const FVector Direction = (TargetLocation - RadarLocation).GetSafeNormal();
348 const float V = TO_METERS * FVector::DotProduct(DeltaVelocity, Direction);
369 TUniquePtr<uint8> data(
new uint8[
RadarMessage->row_step]);
377 detection.depth * cos(detection.azimuth) * cos(-detection.altitude),
378 detection.depth * sin(-detection.azimuth) * cos(detection.altitude),
379 detection.depth * sin(detection.altitude),
386 memcpy(data.Get() + i * pointStep, ¶ms,
sizeof(params));
void BeginPlay() override
void ChangeRadarParameters(FRadarParameters Parameters)
float CalculateRelativeVelocity(const FHitResult &OutHit, const FVector &RadarLocation, const FVector ActorVelocity)
std::vector< RayData > Rays
UNiagaraComponent * NiagaraComponent
TSharedPtr< ROSMessages::sensor_msgs::PointCloud2 > RadarMessage
void SetVisualizeParticles(bool Visualize)
virtual void Tick(float DeltaTime) override
void Init(FRadarParameters parameters, bool SimulateSensor=true)
void SimulateRadar(float DeltaTime)
ARadar(const FObjectInitializer &ObjectInitializer)
void CalculateCurrentVelocity(const float DeltaTime)
FRadarParameters RadarParameters
FRadarParameters TempRadarParameters
std::vector< FRadarDetection > detections
TArray< FVector > HitLocations
void SetRadarParameters(FRadarParameters Parameters)
bool RadarParametersChanged
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override
static const FName NiagaraHitPoints
bool CanSimulateSensor() const
static void HideComponentForAllCameras(UPrimitiveComponent *PrimitiveComponent)
static const FName NiagaraPointsFloat
void SetSimulateSensor(bool SimulateSensor)
UTopic * GetROSTopic() const
virtual void CreateROSTopic()
static const FName NiagaraPointsInt