@@ -58,8 +58,24 @@ void UUnrealLidar::TickComponent(
5858
5959 // Move sensor data to pending report buffers
6060 if (!Settings.report_no_return_points ) {
61+ size_t NumReturns = 0 ;
62+ for (const uint8_t bReturned : ReturnCloud) {
63+ NumReturns += (bReturned != 0 ) ? 1 : 0 ;
64+ }
65+
66+ if (Settings.report_point_cloud ) {
67+ PointCloudPending.reserve (PointCloudPending.size () + NumReturns * 3 );
68+ }
69+ if (Settings.report_azimuth_elevation_range ) {
70+ AzimuthElevationRangeCloudPending.reserve (
71+ AzimuthElevationRangeCloudPending.size () + NumReturns * 3 );
72+ }
73+ SegmentationCloudPending.reserve (SegmentationCloudPending.size () + NumReturns);
74+ IntensityCloudPending.reserve (IntensityCloudPending.size () + NumReturns);
75+ LaserIndexCloudPending.reserve (LaserIndexCloudPending.size () + NumReturns);
76+
6177 // Filter through the arrays and remove all no-return points
62- for (int32 i = 0 ; i < ReturnCloud.size (); i++ ) {
78+ for (size_t i = 0 ; i < ReturnCloud.size (); ++i ) {
6379 if (ReturnCloud[i]) {
6480 if (Settings.report_point_cloud ) {
6581 PointCloudPending.push_back (PointCloud[i * 3 ]);
@@ -130,8 +146,8 @@ void UUnrealLidar::TickComponent(
130146 LaserIndexCloud.size ());
131147 LaserIndexCloudPending.insert (
132148 LaserIndexCloudPending.end (),
133- std::make_move_iterator (IntensityCloud .begin ()),
134- std::make_move_iterator (IntensityCloud .end ()));
149+ std::make_move_iterator (LaserIndexCloud .begin ()),
150+ std::make_move_iterator (LaserIndexCloud .end ()));
135151 }
136152 }
137153 AzimuthElevationRangeCloud.clear ();
@@ -216,6 +232,15 @@ void UUnrealLidar::SetupLidarFromSettings(
216232 : projectairsim::SimClock::Get ()->SecToNanos (
217233 1 .0f / Settings.report_frequency );
218234
235+ LidarRangeCentimeters =
236+ projectairsim::TransformUtils::ToCentimeters (Settings.range );
237+ LaserTraceParams =
238+ FCollisionQueryParams (SCENE_QUERY_STAT (UnrealLidar), true );
239+ LaserTraceParams.bReturnPhysicalMaterial = false ;
240+ if (Settings.disable_self_hits && OwnerActor) {
241+ LaserTraceParams.AddIgnoredActor (OwnerActor);
242+ }
243+
219244 // Save scan axis orientation
220245 {
221246 auto quaternion = Settings.scan_orientation .normalized ();
@@ -256,7 +281,8 @@ void UUnrealLidar::InitializePose(const projectairsim::Transform& PoseNed) {
256281// Simulate shooting a laser via Unreal ray-tracing.
257282FHitResult UUnrealLidar::ShootSingleLaser (const LaserDirection& LaserDir,
258283 const FVector& LidarBodyLoc,
259- const FRotator& LidarBodyRot) {
284+ const FRotator& LidarBodyRot,
285+ const FCollisionQueryParams& TraceParams) {
260286 const FRotator LaserRotInSensorFrame (LaserDir.VerticalAngleDeg , /* pitch*/
261287 LaserDir.HorizontalAngleDeg , /* yaw*/
262288 0 /* roll*/ );
@@ -272,17 +298,9 @@ FHitResult UUnrealLidar::ShootSingleLaser(const LaserDirection& LaserDir,
272298 LaserDir.OffsetDistanceVertical ;
273299
274300 // Calculate "EndTrace": point corresponding to end of ray trace.
275- const FVector EndTrace =
276- LaserLoc + (projectairsim::TransformUtils::ToCentimeters (Settings.range ) *
277- RayDirectionVector);
301+ const FVector EndTrace = LaserLoc + (LidarRangeCentimeters * RayDirectionVector);
278302
279303 // Shoot ray via LineTraceSingleByChannel, result is saved in HitInfo
280- FCollisionQueryParams TraceParams;
281- if (Settings.disable_self_hits ) {
282- TraceParams.AddIgnoredActor (OwnerActor); // don't hit yourself
283- }
284- TraceParams.bTraceComplex = true ;
285- TraceParams.bReturnPhysicalMaterial = false ;
286304
287305 FHitResult HitInfo (ForceInit);
288306
@@ -351,42 +369,45 @@ void UUnrealLidar::Simulate(const float SimTimeDeltaSec) {
351369 const bool bReportPointCloud = Settings.report_point_cloud ;
352370 const bool bReportAzimuthElevationRange =
353371 Settings.report_azimuth_elevation_range ;
372+ const bool bDrawDebugPoints = Settings.draw_debug_points ;
354373
355- FCriticalSection Mutex;
356374 TArray<FHitResult> GroundTruthHits;
375+ FCriticalSection GroundTruthHitsMutex;
376+
377+ const int32 NumLasers = LasersToShoot.Num ();
378+ if (NumLasers <= 0 ) {
379+ PScanPattern->EndScan ();
380+ return ;
381+ }
382+
383+ if (bDrawDebugPoints) {
384+ GroundTruthHits.Reserve (NumLasers);
385+ }
357386
358387 if (bReportPointCloud) {
359- for (int32 i = 0 ; i < LasersToShoot.Num (); i++) {
360- PointCloud.push_back (NoReturnX);
361- PointCloud.push_back (NoReturnY);
362- PointCloud.push_back (NoReturnZ);
388+ PointCloud.resize (NumLasers * 3 );
389+ for (int32 i = 0 ; i < NumLasers; ++i) {
390+ PointCloud[i * 3 ] = NoReturnX;
391+ PointCloud[i * 3 + 1 ] = NoReturnY;
392+ PointCloud[i * 3 + 2 ] = NoReturnZ;
363393 }
364394 }
365395 if (bReportAzimuthElevationRange) {
366- AzimuthElevationRangeCloud.insert (AzimuthElevationRangeCloud.begin (),
367- LasersToShoot.Num () * 3 , 0 );
396+ AzimuthElevationRangeCloud.resize (NumLasers * 3 , 0 .0f );
368397 }
369- SegmentationCloud.insert (SegmentationCloud. begin (), LasersToShoot. Num (), 0 );
370- IntensityCloud.insert (IntensityCloud. begin (), LasersToShoot. Num (), 0 );
371- LaserIndexCloud.insert (LaserIndexCloud. begin (), LasersToShoot. Num () , 0 );
372- ReturnCloud.insert (ReturnCloud. begin (), LasersToShoot. Num (), false );
398+ SegmentationCloud.resize (NumLasers, NoSegmentationID );
399+ IntensityCloud.resize (NumLasers, 0 . 0f );
400+ LaserIndexCloud.resize (NumLasers , 0 );
401+ ReturnCloud.resize (NumLasers, 0 );
373402
374- ParallelFor (LasersToShoot. Num () , [&](int32 Idx) {
403+ ParallelFor (NumLasers , [&](int32 Idx) {
375404 const FHitResult HitInfo =
376- ShootSingleLaser (LasersToShoot[Idx], LidarBodyLoc, LidarScanRot);
405+ ShootSingleLaser (LasersToShoot[Idx], LidarBodyLoc, LidarScanRot,
406+ LaserTraceParams);
377407
378408 if (HitInfo.bBlockingHit == false ) {
379409 // No laser return
380410 if (bReportNoReturnPoints) {
381- // Add a special point value indicating no laser return
382- Mutex.Lock ();
383-
384- if (bReportPointCloud) {
385- PointCloud[Idx * 3 ] = NoReturnX;
386- PointCloud[Idx * 3 + 1 ] = NoReturnY;
387- PointCloud[Idx * 3 + 2 ] = NoReturnZ;
388- }
389-
390411 if (bReportAzimuthElevationRange) {
391412 double Azimuth = LasersToShoot[Idx].HorizontalAngleDeg ;
392413 double Elevation = LasersToShoot[Idx].VerticalAngleDeg ;
@@ -398,9 +419,7 @@ void UUnrealLidar::Simulate(const float SimTimeDeltaSec) {
398419 SegmentationCloud[Idx] = NoSegmentationID;
399420 IntensityCloud[Idx] = 0 .0f ;
400421 LaserIndexCloud[Idx] = LasersToShoot[Idx].Channel ;
401- ReturnCloud[Idx] = false ;
402-
403- Mutex.Unlock ();
422+ ReturnCloud[Idx] = 0 ;
404423 }
405424 } else {
406425 // Get CustomDepthStencilValue directly from the hit component
@@ -417,8 +436,6 @@ void UUnrealLidar::Simulate(const float SimTimeDeltaSec) {
417436 const projectairsim::Vector3 PointNed =
418437 UnrealTransform::UnrealToNedLinear (Point);
419438
420- Mutex.Lock ();
421-
422439 if (bReportPointCloud) {
423440 PointCloud[Idx * 3 ] = PointNed.x ();
424441 PointCloud[Idx * 3 + 1 ] = PointNed.y ();
@@ -440,19 +457,18 @@ void UUnrealLidar::Simulate(const float SimTimeDeltaSec) {
440457 SegmentationCloud[Idx] = SegmentationID;
441458 IntensityCloud[Idx] = CalculateIntensity (HitInfo);
442459 LaserIndexCloud[Idx] = LasersToShoot[Idx].Channel ;
443- ReturnCloud[Idx] = true ;
460+ ReturnCloud[Idx] = 1 ;
444461
445- if (Settings.draw_debug_points ) {
462+ if (bDrawDebugPoints) {
463+ FScopeLock ScopeLock (&GroundTruthHitsMutex);
446464 GroundTruthHits.Add (HitInfo);
447465 }
448-
449- Mutex.Unlock ();
450466 }
451467 });
452468
453469 // 3. Optional - draw debug hit points on Unreal scene
454470
455- if (Settings. draw_debug_points && UnrealWorld) {
471+ if (bDrawDebugPoints && UnrealWorld) {
456472 for (const auto & HitInfo : GroundTruthHits) {
457473 DrawDebugPoint (UnrealWorld, HitInfo.ImpactPoint ,
458474 10 , // size
0 commit comments