19#include <util/ue-header-guard-begin.h>
20#include "DrawDebugHelpers.h"
21#include "Engine/CollisionProfile.h"
22#include "Kismet/KismetMathLibrary.h"
23#include "PhysicsEngine/PhysicsObjectExternalInterface.h"
24#include "Async/ParallelFor.h"
25#include <util/ue-header-guard-end.h>
36 : Super(ObjectInitializer)
38 RandomEngine = CreateDefaultSubobject<URandomEngine>(TEXT(
"RandomEngine"));
47 Set(LidarDescription);
77 auto SensorTransform = DataStream.GetSensorTransform();
80 TRACE_CPUPROFILER_EVENT_SCOPE_STR(
"Send Stream");
81 DataStream.SerializeAndSend(*
this,
LidarData, DataStream.PopBufferFromPool());
84 #if defined(WITH_ROS2)
86 if (ROS2->IsEnabled())
88 TRACE_CPUPROFILER_EVENT_SCOPE_STR(
"ROS2 Send");
90 AActor* ParentActor = GetAttachParentActor();
93 FTransform LocalTransformRelativeToParent = GetActorTransform().GetRelativeTransform(ParentActor->GetActorTransform());
94 ROS2->ProcessDataFromLidar(DataStream.GetSensorType(), StreamId, LocalTransformRelativeToParent,
LidarData,
this);
98 ROS2->ProcessDataFromLidar(DataStream.GetSensorType(), StreamId, SensorTransform,
LidarData,
this);
105 const FHitResult& HitInfo,
const FTransform& InverseSensorTransform)
const
108 const FVector HitPoint = HitInfo.ImpactPoint;
109 Detection.
point = InverseSensorTransform.TransformPosition(HitPoint);
114 const float AbsAtm = exp(-AttenAtm * Distance);
116 const float IntRec = AbsAtm;
125 Super::PreprocessRays(Channels, MaxPointsPerChannel);
132 for (
auto ch = 0u; ch < Channels; ch++) {
133 for (
auto p = 0u; p < MaxPointsPerChannel; p++) {
145 Detection.
point += Noise;
148 const float Intensity = Detection.
intensity;
168 TRACE_CPUPROFILER_EVENT_SCOPE_STR(__FUNCTION__);
171 [
this](
FDetection& Detection) { return PostprocessDetection(Detection); });
188 return std::round(value / step) * step;
200 constexpr float MinHorizontalResolution = 0.01f;
201 const float HorizontalResolution = FMath::Max(
203 MinHorizontalResolution);
205 const uint32 PointsToScanWithOneLaser =
static_cast<uint32
>(
206 FMath::RoundHalfFromZero(HorizontalFov / HorizontalResolution));
208 if (PointsToScanWithOneLaser == 0)
213 TEXT(
"%s: no points requested this frame, increase horizontal_fov or decrease horizontal_resolution."),
223 const FTransform ActorTransform = GetTransform();
224 const FTransform InverseSensorTransform = ActorTransform.Inverse();
225 const FVector LidarBodyLocation = ActorTransform.GetLocation();
226 const FRotator LidarBodyRotation = ActorTransform.Rotator();
228 auto RunChannelRaycasts = [&]()
230 TRACE_CPUPROFILER_EVENT_SCOPE(ParallelFor);
231 ParallelFor(ChannelCount, [&](int32 idxChannel) {
232 TRACE_CPUPROFILER_EVENT_SCOPE(ParallelForTask);
234 FCollisionQueryParams TraceParams = FCollisionQueryParams(FName(TEXT(
"Laser_Trace")),
true,
this);
235 TraceParams.bTraceComplex =
true;
236 TraceParams.bReturnPhysicalMaterial =
false;
241 for (
auto idxPtsOneLaser = 0u; idxPtsOneLaser < PointsToScanWithOneLaser; idxPtsOneLaser++) {
242 if (!ChannelPreprocessCondition[idxPtsOneLaser])
247 FHitResult HitResult;
248 const float HorizAngle =
249 -HorizontalFov / 2.0f +
static_cast<float>(idxPtsOneLaser) * HorizontalResolution;
251 if (
ShootLaser(VertAngle, HorizAngle, HitResult, TraceParams, LidarBodyLocation, LidarBodyRotation)) {
260 auto LockedPhysObject = FPhysicsObjectExternalInterface::LockRead(GetWorld()->GetPhysicsScene());
261 RunChannelRaycasts();
262 LockedPhysObject.Release();
266 RunChannelRaycasts();
#define DEBUG_ASSERT(predicate)
static float SnapToStep(float value, float step)
virtual void Set(const FActorDescription &Description) override
void ComputeAndSaveDetections(const FTransform &SensorTransform) override
Copies the per-channel detections into the LidarData structure.
carla::sensor::data::LidarData FLidarData
float DropOffAlpha
Slope for the intensity dropoff of lidar points: alpha*Intensity + beta where alpha = dropoff_zero_in...
void ResetDetections(uint32_t Channels, uint32_t MaxPointsPerChannel) override
Clear the per-channel detection buffers.
void WriteDetectionAsync(uint32_t Channel, const FHitResult &HitInfo, const FTransform &InverseSensorTransform, const FVector &SensorLocation) override
Computes the detection of a hit inside the raycast ParallelFor.
AHSSLidar(const FObjectInitializer &ObjectInitializer)
virtual void SimulateLidar(const float DeltaTime, bool bLockPhysics=true) override
FDetection ComputeDetection(const FHitResult &HitInfo, const FTransform &InverseSensorTransform) const
std::vector< std::vector< FDetection > > Detections
static FActorDefinition GetSensorDefinition()
bool PostprocessDetection(FDetection &Detection) const
bool DropOffGenActive
Enable/Disable general dropoff of lidar points.
virtual void SendData(const float DeltaTime) override
void PreprocessRays(uint32_t Channels, uint32_t MaxPointsPerChannel) override
Method that allow to preprocess if the rays will be traced.
TArray< float > PointCloudLidarData
WITH_EDITOR-only mirror of the point cloud, used by the debug save path.
std::vector< uint32_t > PointsPerChannel
static void CompactAndWriteDetections(std::vector< std::vector< DetectionT > > &Detections, std::vector< uint32_t > &OutPointsPerChannel, uint32_t Channels, LidarDataT &LidarData, PostprocessT &&Postprocess)
Post-processes the detections channel by channel, drops the rejected ones and writes the rest to Lida...
void CreateLasers()
Creates a Laser for each channel.
static void ResetChannelDetections(std::vector< std::vector< DetectionT > > &Detections, uint32_t Channels, uint32_t MaxPointsPerChannel)
Clears every channel buffer and reserves room for a full scan.
TArray< float > LaserAngles
static void CopyDetectionsToPointCloud(const std::vector< std::vector< DetectionT > > &Detections, const std::vector< uint32_t > &InPointsPerChannel, TArray< float > &PointCloud)
Copies the kept detections into a flat x, y, z, intensity array (editor debug point cloud).
std::vector< std::vector< bool > > RayPreprocessCondition
FLidarDescription Description
bool ShootLaser(const float VerticalAngle, float HorizontalAngle, FHitResult &HitResult, FCollisionQueryParams &TraceParams, const FVector &LidarBodyLocation, const FRotator &LidarBodyRotation) const
Shoot a laser ray-trace, return whether the laser hit something.
virtual void Set(const FActorDescription &Description)
auto GetToken() const
Return the token that allows subscribing to this sensor's stream.
FAsyncDataStream GetDataStream(SensorType &&Self)
Return the FDataStream associated with this sensor.
URandomEngine * RandomEngine
Random Engine used to provide noise for sensor output.
void SetSeed(int32 InSeed)
static void SetLidar(const FActorDescription &Description, FLidarDescription &Lidar)
static FActorDefinition MakeLidarDefinition(const FString &Id)
float GetNormalDistribution(float Mean, float StandardDeviation)
static std::shared_ptr< ROS2 > GetInstance()
Helper class to store and serialize the data generated by a Lidar.
Serializes a stream endpoint.
const auto & get_stream_id() const
A definition of a Carla Actor with all the variation and attributes.
A description of a Carla Actor with all its variation.
float DropOffAtZeroIntensity
General drop off rate.
float HorizontalFov
Horizontal field of view.
int RandomSeed
Random seed for the noise/dropoff used by this sensor.
float DropOffGenRate
General drop off rate.
uint32 Channels
Number of lasers.
float DropOffIntensityLimit
General drop off rate.
float AtmospAttenRate
Attenuation Rate in the atmosphere in m^-1.
float HorizontalResolution
Horizontal resolution of the lidar, in degrees.
Vector3D MakeUnitVector(const float epsilon=2.0f *std::numeric_limits< float >::epsilon()) const
Return a unit-length copy of this vector.