18#include <util/ue-header-guard-begin.h>
19#include "DrawDebugHelpers.h"
20#include "Engine/CollisionProfile.h"
21#include "Kismet/KismetMathLibrary.h"
22#include "PhysicsEngine/PhysicsObjectExternalInterface.h"
23#include "Async/ParallelFor.h"
24#include <util/ue-header-guard-end.h>
37 : Super(ObjectInitializer)
39 PrimaryActorTick.bCanEverTick =
true;
47 LidarSubsystem->RegisterLidar(
this);
55 LidarSubsystem->UnregisterLidar(
this);
57 Super::EndPlay(EndPlayReason);
62 Super::Set(ActorDescription);
65 Set(LidarDescription);
79 check(NumberOfLasers > 0u);
80 const float DeltaAngle = NumberOfLasers == 1u ? 0.f :
82 static_cast<float>(NumberOfLasers - 1);
84 for(
auto i = 0u; i < NumberOfLasers; ++i)
86 const float VerticalAngle =
96 auto SensorTransform = DataStream.GetSensorTransform();
98 TRACE_CPUPROFILER_EVENT_SCOPE_STR(
"Send Stream");
99 DataStream.SerializeAndSend(*
this,
SemanticLidarData, DataStream.PopBufferFromPool());
102 #if defined(WITH_ROS2)
104 if (ROS2->IsEnabled())
106 TRACE_CPUPROFILER_EVENT_SCOPE_STR(
"ROS2 Send");
108 AActor* ParentActor = GetAttachParentActor();
111 FTransform LocalTransformRelativeToParent = GetActorTransform().GetRelativeTransform(ParentActor->GetActorTransform());
112 ROS2->ProcessDataFromSemanticLidar(DataStream.GetSensorType(), StreamId, LocalTransformRelativeToParent,
SemanticLidarData,
this);
116 ROS2->ProcessDataFromSemanticLidar(DataStream.GetSensorType(), StreamId, SensorTransform,
SemanticLidarData,
this);
126 const uint32 PointsToScanWithOneLaser =
127 FMath::RoundHalfFromZero(
130 if (PointsToScanWithOneLaser <= 0)
135 TEXT(
"%s: no points requested this frame, try increasing the number of points per second."),
146 const float AngleDistanceOfLaserMeasure = AngleDistanceOfTick / PointsToScanWithOneLaser;
152 const FTransform ActorTransform = GetTransform();
153 const FTransform InverseSensorTransform = ActorTransform.Inverse();
154 const FVector LidarBodyLocation = ActorTransform.GetLocation();
155 const FRotator LidarBodyRotation = ActorTransform.Rotator();
157 auto RunChannelRaycasts = [&]()
159 TRACE_CPUPROFILER_EVENT_SCOPE(ParallelFor);
160 ParallelFor(ChannelCount, [&](int32 idxChannel) {
161 TRACE_CPUPROFILER_EVENT_SCOPE(ParallelForTask);
163 FCollisionQueryParams TraceParams = FCollisionQueryParams(FName(TEXT(
"Laser_Trace")),
true,
this);
164 TraceParams.bTraceComplex =
true;
165 TraceParams.bReturnPhysicalMaterial =
false;
170 for (
auto idxPtsOneLaser = 0u; idxPtsOneLaser < PointsToScanWithOneLaser; idxPtsOneLaser++) {
172 if (!ChannelPreprocessCondition[idxPtsOneLaser])
177 FHitResult HitResult;
178 const float HorizAngle = std::fmod(CurrentHorizontalAngle + AngleDistanceOfLaserMeasure
181 if (
ShootLaser(VertAngle, HorizAngle, HitResult, TraceParams, LidarBodyLocation, LidarBodyRotation)) {
190 auto LockedPhysObject = FPhysicsObjectExternalInterface::LockRead(GetWorld()->GetPhysicsScene());
191 RunChannelRaycasts();
192 LockedPhysObject.Release();
196 RunChannelRaycasts();
211 conds.resize(MaxPointsPerChannel);
212 std::fill(conds.begin(), conds.end(),
true);
228 TRACE_CPUPROFILER_EVENT_SCOPE_STR(__FUNCTION__);
247 const FVector HitPoint = HitInfo.ImpactPoint;
248 Detection.
point = InverseSensorTransform.TransformPosition(HitPoint);
250 const FVector VecInc = - (HitPoint - SensorLocation).GetSafeNormal();
251 Detection.
cos_inc_angle = FVector::DotProduct(VecInc, HitInfo.ImpactNormal);
255 const AActor* actor = HitInfo.GetActor();
257 Detection.
object_tag =
static_cast<uint32_t
>(crp::CityObjectLabel::None);
265 if (actor !=
nullptr && actor->IsA<ALandscape>())
269 else if (HitInfo.Component.IsValid())
274 if (actor !=
nullptr)
285 UE_LOG(LogCarla, Warning, TEXT(
"Actor not valid %p!!!!"), actor);
291 const FVector& LidarBodyLocation,
const FRotator& LidarBodyRotation)
const
293 TRACE_CPUPROFILER_EVENT_SCOPE_STR(__FUNCTION__);
295 FRotator LaserRotation(VerticalAngle, HorizontalAngle, 0);
296 FRotator ResultRotation = UKismetMathLibrary::ComposeRotators(
302 FVector EndTrace = Range * UKismetMathLibrary::GetForwardVector(ResultRotation) + LidarBodyLocation;
304 return GetWorld()->ParallelLineTraceSingleByChannel(
308 ECC_GameTraceChannel2,
310 FCollisionResponseParams::DefaultResponseParam
325 if (
State.lidar_horizontal_angle)
#define DEBUG_ASSERT(predicate)
carla::sensor::data::SemanticLidarData FSemanticLidarData
void GetMirrorState(carla::multigpu::SensorState &State) const override
Multi-GPU: the runtime state this sensor starts its next tick from (noise generator,...
static FActorDefinition GetSensorDefinition()
std::vector< uint32_t > PointsPerChannel
void SetMirrorState(const carla::multigpu::SensorState &State) override
virtual void SendData(const float DeltaTime)
virtual void BeginPlay() override
virtual void ComputeAndSaveDetections(const FTransform &SensorTransform)
Copies the per-channel detections into the LidarData structure.
virtual void PreprocessRays(uint32_t Channels, uint32_t MaxPointsPerChannel)
Method that allow to preprocess if the rays will be traced.
virtual void SimulateLidar(const float DeltaTime, bool bLockPhysics=true)
void CreateLasers()
Creates a Laser for each channel.
void ComputeRawDetection(const FHitResult &HitInfo, const FTransform &InverseSensorTransform, const FVector &SensorLocation, FSemanticDetection &Detection) const
Compute all raw detection information.
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
virtual void WriteDetectionAsync(uint32_t Channel, const FHitResult &HitInfo, const FTransform &InverseSensorTransform, const FVector &SensorLocation)
Computes the detection of a hit inside the raycast ParallelFor.
virtual void EndPlay(EEndPlayReason::Type EndPlayReason) override
virtual void Set(const FActorDescription &Description) override
ARayCastSemanticLidar(const FObjectInitializer &ObjectInitializer)
std::vector< std::vector< bool > > RayPreprocessCondition
virtual void ResetDetections(uint32_t Channels, uint32_t MaxPointsPerChannel)
Clear the per-channel detection buffers.
FLidarDescription Description
std::vector< std::vector< FSemanticDetection > > SemanticDetections
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.
FSemanticLidarData SemanticLidarData
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.
const UCarlaEpisode & GetEpisode() const
static crp::CityObjectLabel GetTagOfTaggedComponent(const UPrimitiveComponent &Component)
Retrieve the tag of an already tagged component.
static crp::CityObjectLabel GetTagFromString(FString Tag)
Transform a string into a CityObjectLabel.
A registry of all the Carla actors.
FCarlaActor * FindCarlaActor(IdType Id)
A view over an actor and its properties.
IdType GetPrimaryActorId() const
The id clients know this actor by: the primary's for a mirror on a Multi-GPU secondary,...
static void SetLidar(const FActorDescription &Description, FLidarDescription &Lidar)
static FActorDefinition MakeLidarDefinition(const FString &Id)
const FActorRegistry & GetActorRegistry() const
Subsystem responsible for simulating all ray-cast LiDARs of a world.
uint32 GetState() const
The engine's state, to continue its exact sequence elsewhere (a Multi-GPU secondary's mirror of a sen...
void SetState(uint32 State)
Continue from State, as GetState returned it; an impossible value is ignored.
static constexpr T ToRadians(T deg)
static constexpr T ToDegrees(T rad)
static std::shared_ptr< ROS2 > GetInstance()
virtual void WriteChannelCount(std::vector< uint32_t > points_per_channel)
void WritePointsSync(const std::vector< SemanticLidarDetection > &detections)
float GetHorizontalAngle() const
virtual void ResetMemory(std::vector< uint32_t > points_per_channel)
void SetHorizontalAngle(float angle)
Helper class to store and serialize the data generated by a RawLidar.
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 HorizontalFov
Horizontal field of view.
float LowerFovLimit
Lower laser angle, counts from horizontal, negative values means under horizontal line.
float Range
Measure distance in centimeters.
uint32 Channels
Number of lasers.
uint32 PointsPerSecond
Points generated by all lasers per second.
float RotationFrequency
Lidar rotation frequency.
float UpperFovLimit
Upper laser angle, counts from horizontal, positive values means above horizontal line.
One record of frame data packet 27: the runtime state a sensor of the primary starts this frame's tic...