Skip to content

Commit

Permalink
Aaron/collisionsensorfix (#7445)
Browse files Browse the repository at this point in the history
* Adding test for collision sensor

* Added Collision to root meshes and different mesh collision depending on mesh type, exposing function to Blueprint

* Removing logs

* Applying suggestions
  • Loading branch information
Blyron committed Apr 17, 2024
1 parent f22d49d commit e55a4ef
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 28 deletions.
110 changes: 85 additions & 25 deletions Unreal/CarlaUE4/Plugins/Carla/Source/Carla/Sensor/CollisionSensor.cpp
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
// Copyright (c) 2024 Computer Vision Center (CVC) at the Universitat Autonoma
// de Barcelona (UAB).
//
// This work is licensed under the terms of the MIT license.
// For a copy, see <https://opensource.org/licenses/MIT>.

#include "Carla.h"
#include "Carla/Sensor/CollisionSensor.h"
#include "Carla.h"
#include "CoreMinimal.h"

#include "Carla/Actor/ActorBlueprintFunctionLibrary.h"
#include "Carla/Actor/ActorRegistry.h"
#include "Carla/Game/CarlaEpisode.h"
#include "Carla/Game/CarlaEngine.h"
#include "Carla/Game/CarlaGameInstance.h"
#include "Carla/Game/CarlaGameModeBase.h"
#include "Carla/Vehicle/CarlaWheeledVehicle.h"
#include "Carla/Walker/WalkerBase.h"

ACollisionSensor::ACollisionSensor(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
PrimaryActorTick.bCanEverTick = false;
PrimaryActorTick.bCanEverTick = true;
}

FActorDefinition ACollisionSensor::GetSensorDefinition()
Expand All @@ -32,27 +35,37 @@ void ACollisionSensor::SetOwner(AActor *NewOwner)
Super::SetOwner(NewOwner);

/// @todo Deregister previous owner if there was one.

if (NewOwner != nullptr)
if (IsValid(NewOwner))
{
NewOwner->OnActorHit.AddDynamic(this, &ACollisionSensor::OnCollisionEvent);
ACarlaWheeledVehicle* Vehicle = Cast<ACarlaWheeledVehicle>(NewOwner);
if(IsValid(Vehicle))
{
Vehicle->GetMesh()->OnComponentHit.AddDynamic(this, &ACollisionSensor::OnComponentCollisionEvent);
}
else
{
AWalkerBase* Walker = Cast<AWalkerBase>(NewOwner);
if(IsValid(Walker))
{
Walker->GetMesh()->OnComponentHit.AddDynamic(this, &ACollisionSensor::OnComponentCollisionEvent);
}
else
{
OnActorHit.AddDynamic(this, &ACollisionSensor::OnActorCollisionEvent);
}
}
}
}

void ACollisionSensor::OnCollisionEvent(
AActor *Actor,
AActor *OtherActor,
FVector NormalImpulse,
const FHitResult &Hit)
{
if (Actor == nullptr || OtherActor == nullptr)
else
{
return;
UE_LOG(LogCarla, Log, TEXT("ACollisionSensor::SetOwner New owner is not valid or you are destroying collision sensor") );
}
}

uint64_t CurrentFrame = FCarlaEngine::GetFrameCounter();
void ACollisionSensor::PrePhysTick(float DeltaSeconds) {
Super::PrePhysTick(DeltaSeconds);

// remove all items from previous frames
uint64_t CurrentFrame = FCarlaEngine::GetFrameCounter();
CollisionRegistry.erase(
std::remove_if(
CollisionRegistry.begin(),
Expand All @@ -62,6 +75,29 @@ void ACollisionSensor::OnCollisionEvent(
return std::get<0>(Item) < CurrentFrame;
}),
CollisionRegistry.end());
}

void ACollisionSensor::OnCollisionEvent(
AActor *Actor,
AActor *OtherActor,
FVector NormalImpulse,
const FHitResult &Hit)
{
if (!IsValid(OtherActor))
{
UE_LOG(LogCarla, Error, TEXT("ACollisionSensor::OnActorCollisionEvent Error with collided actor; Not valid.\n Collider actor %s"),
*(Actor->GetName()) );
return;
}

if (!IsValid(Actor))
{
UE_LOG(LogCarla, Error, TEXT("ACollisionSensor::OnActorCollisionEvent Error with collider actor; Not valid.\n Collided actor %s"),
*(OtherActor->GetName()) );
return;
}

uint64_t CurrentFrame = FCarlaEngine::GetFrameCounter();

// check if this collision has been procesed already in this frame
for (auto& Collision: CollisionRegistry)
Expand All @@ -74,23 +110,27 @@ void ACollisionSensor::OnCollisionEvent(
}
}

const auto &Episode = GetEpisode();
const auto& CurrentEpisode = GetEpisode();
constexpr float TO_METERS = 1e-2;
NormalImpulse *= TO_METERS;
GetDataStream(*this).SerializeAndSend(
*this,
Episode.SerializeActor(Actor),
Episode.SerializeActor(OtherActor),
carla::geom::Vector3D{NormalImpulse.X, NormalImpulse.Y, NormalImpulse.Z});
CurrentEpisode.SerializeActor(Actor),
CurrentEpisode.SerializeActor(OtherActor),
carla::geom::Vector3D(
(float)NormalImpulse.X,
(float)NormalImpulse.Y,
(float)NormalImpulse.Z));

// record the collision event
if (Episode.GetRecorder()->IsEnabled()){
Episode.GetRecorder()->AddCollision(Actor, OtherActor);
if (CurrentEpisode.GetRecorder()->IsEnabled()){
CurrentEpisode.GetRecorder()->AddCollision(Actor, OtherActor);
}

CollisionRegistry.emplace_back(CurrentFrame, Actor, OtherActor);

// ROS2
#if defined(WITH_ROS2)
#if defined(WITH_ROS2)
auto ROS2 = carla::ros2::ROS2::GetInstance();
if (ROS2->IsEnabled())
{
Expand All @@ -107,5 +147,25 @@ void ACollisionSensor::OnCollisionEvent(
ROS2->ProcessDataFromCollisionSensor(0, StreamId, GetActorTransform(), OtherActor->GetUniqueID(), carla::geom::Vector3D{NormalImpulse.X, NormalImpulse.Y, NormalImpulse.Z}, this);
}
}
#endif
#endif
}

void ACollisionSensor::OnActorCollisionEvent(
AActor *Actor,
AActor *OtherActor,
FVector NormalImpulse,
const FHitResult &Hit)
{
OnCollisionEvent(Actor, OtherActor, NormalImpulse, Hit);
}

void ACollisionSensor::OnComponentCollisionEvent(
UPrimitiveComponent* HitComp,
AActor* OtherActor,
UPrimitiveComponent* OtherComp,
FVector NormalImpulse,
const FHitResult& Hit)
{
AActor* Actor = HitComp->GetOwner();
OnCollisionEvent(Actor, OtherActor, NormalImpulse, Hit);
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2017 Computer Vision Center (CVC) at the Universitat Autonoma
// Copyright (c) 2024 Computer Vision Center (CVC) at the Universitat Autonoma
// de Barcelona (UAB).
//
// This work is licensed under the terms of the MIT license.
Expand Down Expand Up @@ -26,17 +26,32 @@ class CARLA_API ACollisionSensor : public ASensor

ACollisionSensor(const FObjectInitializer& ObjectInitializer);

virtual void PrePhysTick(float DeltaSeconds) override;
void SetOwner(AActor *NewOwner) override;

private:

UFUNCTION()
void OnCollisionEvent(
AActor *Actor,
AActor *OtherActor,
FVector NormalImpulse,
const FHitResult &Hit);

UFUNCTION(BlueprintCallable, Category="Collision")
void OnActorCollisionEvent(
AActor *Actor,
AActor *OtherActor,
FVector NormalImpulse,
const FHitResult &Hit);

UFUNCTION()
void OnComponentCollisionEvent(
UPrimitiveComponent* HitComp,
AActor* OtherActor,
UPrimitiveComponent* OtherComp,
FVector NormalImpulse,
const FHitResult& Hit);

private:
/// Registry that saves all collisions. Used to avoid sending the same collision more than once per frame,
/// as the collision sensor uses the PhysX substepping tick. Helps with sensor usage and stream overload.
std::vector<std::tuple<uint64_t, AActor*, AActor*>> CollisionRegistry;
Expand Down

0 comments on commit e55a4ef

Please sign in to comment.