Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature/openplx-integration #3

Draft
wants to merge 32 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
4149a7f
Bundle Brick in build time
AlgoryxJosef Oct 11, 2024
1fe4fed
Add test-code for importing brick file in barrier
AlgoryxJosef Oct 17, 2024
a7aac36
Add missing libraries and import using hardcoded paths
AlgoryxJosef Oct 22, 2024
4f8e264
Fix bad call to register_factories
AlgoryxJosef Oct 22, 2024
e4ceb08
Add factory handling automatic import with empty implementation
AlgoryxJosef Oct 24, 2024
24c6c56
Use FactoryCreateFile instead in factory
AlgoryxJosef Oct 24, 2024
1eb7c76
Get callback for both import and reimport automatically
AlgoryxJosef Oct 25, 2024
3badf9f
Add temporary button hooks in BrickAsset view for experimenting
AlgoryxJosef Oct 28, 2024
bcbf8f3
Add more experiment hooks
AlgoryxJosef Oct 29, 2024
b2629c0
Add support for brick import using regular import pipeline
AlgoryxJosef Nov 5, 2024
33d9b08
Remove deleted header include
AlgoryxJosef Nov 6, 2024
bf02200
Add missing include
AlgoryxJosef Nov 6, 2024
35b4911
Add internal brick_experiments header
AlgoryxJosef Nov 7, 2024
c027d8e
Import and assign name to secondary constraints
AlgoryxJosef Nov 7, 2024
1bb97dd
Add brick inputs to SimObjectCollection
AlgoryxJosef Nov 7, 2024
df5035e
Rename Brick->OpenPLX and import signal as blueprint variable
AlgoryxJosef Nov 8, 2024
e0ab0c0
Start implementing a SignalHandler who will propagate signals
AlgoryxJosef Nov 11, 2024
b058090
Add SignalHandler and refactor some locations of import classes
AlgoryxJosef Nov 12, 2024
e8d56d7
Add SignalHandlerComponent during import
AlgoryxJosef Nov 12, 2024
38d7551
Fix typo
AlgoryxJosef Nov 12, 2024
cfebbfb
Prepare a PLX_ModelInfo subsystem to keep track of all native PLX tre…
AlgoryxJosef Nov 14, 2024
05778a6
PLXModelRegistry now holds all loaded PLX models
AlgoryxJosef Nov 14, 2024
10fa0ac
Set correct default value of input variables
AlgoryxJosef Nov 15, 2024
761899a
Read in Outputs during import (only single output type is supported)
AlgoryxJosef Nov 15, 2024
ce48f90
Cache inputs for fast lookup in ModelDatum
AlgoryxJosef Nov 15, 2024
7ea7ee9
Implement receive for one output type
AlgoryxJosef Nov 15, 2024
3b482e1
Merge branch 'master' into feature/agx-modelformat-integration
AlgoryxJosef Dec 2, 2024
0774031
Rename Brick -> OpenPLX part 1
AlgoryxJosef Dec 2, 2024
aede220
Add missing thirdparty lib
AlgoryxJosef Dec 2, 2024
dfa9de5
Link against needed hash-library
AlgoryxJosef Dec 4, 2024
ac9bfee
Restore signal handling with new implementation
AlgoryxJosef Dec 4, 2024
d4e2671
Fixes regarding signal handling
AlgoryxJosef Dec 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions Source/AGXCommon/Public/OpenPLX/PLX_Inputs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright 2024, Algoryx Simulation AB.

#pragma once

// Unreal Engine includes.
#include "CoreMinimal.h"
#include "UObject/Class.h"

#include "PLX_Inputs.generated.h"

USTRUCT(BlueprintType)
struct AGXCOMMON_API FPLX_Input
{
GENERATED_BODY()

FPLX_Input() = default;
explicit FPLX_Input(const FString& InName)
: Name(InName)
{
}

virtual ~FPLX_Input() = default;

UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "OpenPXL")
FString Name;

virtual UScriptStruct* GetType() const
{
return FPLX_Input::StaticStruct();
}
};

USTRUCT(BlueprintType)
struct AGXCOMMON_API FPLX_LinearVelocity1DInput : public FPLX_Input
{
GENERATED_BODY()

FPLX_LinearVelocity1DInput() = default;
explicit FPLX_LinearVelocity1DInput(const FString& InName)
: FPLX_Input(InName)
{
}

virtual UScriptStruct* GetType() const override
{
return FPLX_LinearVelocity1DInput::StaticStruct();
}
};
48 changes: 48 additions & 0 deletions Source/AGXCommon/Public/OpenPLX/PLX_Outputs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright 2024, Algoryx Simulation AB.

#pragma once

// Unreal Engine includes.
#include "CoreMinimal.h"
#include "UObject/Class.h"

#include "PLX_Outputs.generated.h"

USTRUCT(BlueprintType)
struct AGXCOMMON_API FPLX_Output
{
GENERATED_BODY()

FPLX_Output() = default;
explicit FPLX_Output(const FString& InName)
: Name(InName)
{
}

virtual ~FPLX_Output() = default;

UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "OpenPXL")
FString Name;

virtual UScriptStruct* GetType() const
{
return FPLX_Output::StaticStruct();
}
};

USTRUCT(BlueprintType)
struct AGXCOMMON_API FPLX_AngleOutput : public FPLX_Output
{
GENERATED_BODY()

FPLX_AngleOutput() = default;
explicit FPLX_AngleOutput(const FString& InName)
: FPLX_Output(InName)
{
}

virtual UScriptStruct* GetType() const override
{
return FPLX_AngleOutput::StaticStruct();
}
};
8 changes: 2 additions & 6 deletions Source/AGXUnreal/Private/AGX_Simulation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -664,12 +664,8 @@ void UAGX_Simulation::Deinitialize()
#endif

Super::Deinitialize();
if (!HasNative())
{
return;
}

ReleaseNative();
if (HasNative())
ReleaseNative();
}

#if WITH_EDITOR
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ FAGX_ConstraintController& FAGX_ConstraintController::operator=(
SpookDamping = Other.SpookDamping;
ForceRange = Other.ForceRange;
bRotational = Other.bRotational;
Name = Other.Name;
return *this;
}

Expand Down Expand Up @@ -201,6 +202,7 @@ void FAGX_ConstraintController::UpdateNativeProperties()
NativeBarrier->SetCompliance(Compliance);
NativeBarrier->SetSpookDamping(SpookDamping);
NativeBarrier->SetForceRange(ForceRange);
NativeBarrier->SetName(Name);
UpdateNativePropertiesImpl();
}

Expand All @@ -224,10 +226,14 @@ void FAGX_ConstraintController::CopyFrom(

if (ForceOverwriteInstances || Instance->ForceRange == ForceRange)
Instance->ForceRange = Source.GetForceRange();

if (ForceOverwriteInstances || Instance->Name == Name)
Instance->Name = Source.GetName();
}

bEnable = Source.GetEnable();
Compliance = Source.GetCompliance();
SpookDamping = Source.GetSpookDamping();
ForceRange = Source.GetForceRange();
Name = Source.GetName();
}
46 changes: 46 additions & 0 deletions Source/AGXUnreal/Private/OpenPLX/PLX_ModelRegistry.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright 2024, Algoryx Simulation AB.

#pragma once

#include "OpenPLX/PLX_ModelRegistry.h"


UPLX_ModelRegistry* UPLX_ModelRegistry::GetFrom(UWorld* World)
{
if (World == nullptr || !World->IsGameWorld())
return nullptr;

return World->GetSubsystem<UPLX_ModelRegistry>();
}

bool UPLX_ModelRegistry::HasNative() const
{
return Native.HasNative();
}

FPLXModelRegistry* UPLX_ModelRegistry::GetNative()
{
if (!HasNative())
return nullptr;

return &Native;
}

const FPLXModelRegistry* UPLX_ModelRegistry::GetNative() const
{
if (!HasNative())
return nullptr;

return &Native;
}

void UPLX_ModelRegistry::Initialize(FSubsystemCollectionBase& Collection)
{
Super::Initialize(Collection);
}

void UPLX_ModelRegistry::Deinitialize()
{
Native.ReleaseNative();
Super::Deinitialize();
}
106 changes: 106 additions & 0 deletions Source/AGXUnreal/Private/OpenPLX/PLX_SignalHandlerComponent.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
// Copyright 2024, Algoryx Simulation AB.

#include "OpenPLX/PLX_SignalHandlerComponent.h"

// AGX Dynamics for Unreal includes.
#include "AGX_Simulation.h"
#include "Constraints/AGX_ConstraintComponent.h"
#include "Import/AGX_ModelSourceComponent.h"
#include "OpenPLX/PLX_ModelRegistry.h"
#include "Utilities/AGX_ObjectUtilities.h"
#include "Utilities/AGX_StringUtilities.h"

UPLX_SignalHandlerComponent::UPLX_SignalHandlerComponent()
{
PrimaryComponentTick.bCanEverTick = false;
}

bool UPLX_SignalHandlerComponent::Send(const FPLX_LinearVelocity1DInput& Input, double Value)
{
if (!SignalHandler.IsInitialized())
return false;

return SignalHandler.Send(Input, Value);
}

namespace PLX_SignalHandlerComponent_helpers
{
TArray<FConstraintBarrier*> CollectConstraintBarriers(AActor* Owner)
{
if (Owner == nullptr)
return TArray<FConstraintBarrier*>();

TArray<UAGX_ConstraintComponent*> ConstraintsInThisActor =
FAGX_ObjectUtilities::Filter<UAGX_ConstraintComponent>(Owner->GetComponents());
TArray<FConstraintBarrier*> ConstraintBarriers;
for (UAGX_ConstraintComponent* Constraint : ConstraintsInThisActor)
{
if (auto CBarrier = Constraint->GetOrCreateNative())
{
if (CBarrier->HasNative())
ConstraintBarriers.Add(CBarrier);
}
}

return ConstraintBarriers;
}

TOptional<FString> GetPLXFilePath(AActor* Owner)
{
if (Owner == nullptr)
return {};

auto ModelSource = Owner->GetComponentByClass<UAGX_ModelSourceComponent>();
if (ModelSource == nullptr)
return {};

// Todo: this must point to the corresponding PLX file in the project files, copied from
// import, not the source file itself. This is to ensure portability of standalone-projects.
return ModelSource->FilePath;
}
}

bool UPLX_SignalHandlerComponent::Receive(const FPLX_AngleOutput& Output, double& OutValue)
{
return SignalHandler.Receive(Output, OutValue);
}

void UPLX_SignalHandlerComponent::BeginPlay()
{
using namespace PLX_SignalHandlerComponent_helpers;
Super::BeginPlay();

auto PLXFile = GetPLXFilePath(GetOwner());
if (!PLXFile.IsSet())
{
UE_LOG(
LogAGX, Warning,
TEXT("UPLX_SignalHandlerComponent '%s' in '%s' was unable to get OpenPLX file path "
"from UAGX_ModelSourceComponent. OpenPLX Signals will not work properly."),
*GetName(), *GetLabelSafe(GetOwner()));
return;
}

auto Sim = UAGX_Simulation::GetFrom(this);
auto SimulationBarrier = Sim != nullptr ? Sim->GetNative() : nullptr;
if (SimulationBarrier == nullptr)
{
// todo: log warning.
return;
}

auto PLXModelRegistry = UPLX_ModelRegistry::GetFrom(GetWorld());
auto PLXModelRegistryBarrier =
PLXModelRegistry != nullptr ? PLXModelRegistry->GetNative() : nullptr;
if (PLXModelRegistryBarrier == nullptr)
{
// Todo: log warning.
return;
}

// Collect all Constraints in the same AActor as us.
TArray<FConstraintBarrier*> ConstraintBarriers = CollectConstraintBarriers(GetOwner());

// Initialize SignalHandler in Barrier module.
SignalHandler.Init(*PLXFile, *SimulationBarrier, *PLXModelRegistryBarrier, ConstraintBarriers);
}
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ struct AGXUNREAL_API FAGX_ConstraintController

double GetForce();

UPROPERTY(EditAnywhere, Category = "AGX Constraint Controller")
FString Name;

/**
* Handle serialization backwards compatibility. May be overridden by subclasses as long as they
* call Super::Serialize.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,12 @@ enum class EAGX_ImportType : uint8
/** Imported type is Invalid. */
Invalid,

/** Imported type is AGX Dynamics Archive. */
/** Imported type is an AGX Dynamics Archive. */
Agx,

/** Imported type is URDF (Unified Robotic Description Format) model. */
/** Imported type is a OpenPLX model. */
Plx,

/** Imported type is a URDF (Unified Robotic Description Format) model. */
Urdf
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// Unreal Engine includes.
#include "Components/ActorComponent.h"
#include "CoreMinimal.h"
#include "Import/AGX_ImportEnums.h"

#include "AGX_ModelSourceComponent.generated.h"

Expand Down
38 changes: 38 additions & 0 deletions Source/AGXUnreal/Public/OpenPLX/PLX_ModelRegistry.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright 2024, Algoryx Simulation AB.

#pragma once

// AGX Dynamics for Unreal includes.
#include "OpenPLX/PLXModelRegistry.h"

// Unreal Engine includes.
#include "CoreMinimal.h"
#include "LevelInstance/LevelInstanceSubsystem.h"
#include "Subsystems/GameInstanceSubsystem.h"

#include "PLX_ModelRegistry.generated.h"


/**
* Todo: add description.
*/
UCLASS(ClassGroup = "PLX", Category = "PLX")
class AGXUNREAL_API UPLX_ModelRegistry : public ULevelInstanceSubsystem
{
GENERATED_BODY()

public:
static UPLX_ModelRegistry* GetFrom(UWorld* World);

bool HasNative() const;
FPLXModelRegistry* GetNative();
const FPLXModelRegistry* GetNative() const;

private:
// ~Begin USubsystem interface.
virtual void Initialize(FSubsystemCollectionBase& Collection) override;
virtual void Deinitialize() override;
// ~End USubsystem interface.

FPLXModelRegistry Native;
};
Loading