Examples presented in this document and the plugin have been made in Unreal Engine 4.14, 4.15, 4.18 and 4.20+. They might not work correctly with different versions of the Unreal Engine. |
Plugin integration
Please follow below steps in order to include ForceSeatMI plugin into your project.- Create C++ Unreal Engine project
- Inside root directory of your project create Plugins directory
- Copy ForceSeatMI plugin folder into Plugins directory
- Launch Unreal Engine editor
- Add ForceSeatMI plugin dependency to your project inside YourProject.Build.cs
PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore", "ForceSeatMI" });
- UE 4.15+ users: ForceSeatMI_VehicleTelemetry requires PhysXVehicles so make sure that this module it is added to your project
- After everything is built and compiled you can start using ForceSeatMI in your application!
ForceSeatMI plugin uses DLL which is installed as part of the ForceSeatPM software. Make sure that you have ForceSeatPM installed on your computer. |
Application: top table positioning
Examples:- TableLogPos_Unreal shows positioning in abstract(logical, percents) units
- TablePhyPos_Unreal shows positioning in real world units (Inverse Kinematics)
- Create a pointer member variable inside your class which will point to an instance of IForceSeatMI_API:
IForceSeatMI_API* m_api;
- Initialize it in class constructor:
m_api(&IForceSeatMI::Get().GetAPI())
- When simulation starts call (e.g. in BeginPlay() method of your APawn implementation):
m_api->BeginMotionControl();
- The SIM should send positioning data in constant intervals using one of the following functions:
m_api->SendTopTablePosLog(...); m_api->SendTopTablePosPhy(...); m_api->SendTopTableMatrixPhy(...);
- At the end of simulation call:
m_api->EndMotionControl();
Code
Below code comes from TableLogPos_Unreal example.ATableLogPos_UnrealPawn::ATableLogPos_UnrealPawn() : CurrentDrawingHeave(0) , CurrentDrawingPitch(0) , CurrentDrawingRoll(0) { // ... generated UE4 code removed for better clarity // ForceSeatMI - BEGIN memset(&PlatformPosition, 0, sizeof(PlatformPosition)); PlatformPosition.structSize = sizeof(PlatformPosition); // The demo program is able to provide pause, position and speed limit PlatformPosition.maxSpeed = PLATFORM_MAX_SPEED; PlatformPosition.mask = FSMI_POS_BIT_STATE | FSMI_POS_BIT_POSITION | FSMI_POS_BIT_MAX_SPEED; // ForceSeatMI - END } void ATableLogPos_UnrealPawn::Tick(float DeltaTime) { Super::Tick(DeltaTime); // ... generated UE4 code removed for better clarity // ForceSeatMI - BEGIN SendCoordinatesToPlatform(); // ForceSeatMI - END } void ATableLogPos_UnrealPawn::BeginPlay() { Super::BeginPlay(); // ForceSeatMI - BEGIN if (FSMI_True == IForceSeatMI::Get().GetAPI().BeginMotionControl()) { SendCoordinatesToPlatform(); } // ForceSeatMI - END // ... generated UE4 code removed for better clarity } void ATableLogPos_UnrealPawn::EndPlay(const EEndPlayReason::Type EndPlayReason) { Super::EndPlay(EndPlayReason); // ForceSeatMI - BEGIN IForceSeatMI::Get().GetAPI().EndMotionControl(); // ForceSeatMI - END } void ATableLogPos_UnrealPawn::SendCoordinatesToPlatform() { // ForceSeatMI - BEGIN PlatformPosition.state = FSMI_STATE_NO_PAUSE; PlatformPosition.roll = static_cast(FMath::Clamp(CurrentDrawingRoll / DRAWING_ROLL_MAX * PLATFORM_POSITION_LOGIC_MAX, PLATFORM_POSITION_LOGIC_MIN, PLATFORM_POSITION_LOGIC_MAX)); PlatformPosition.pitch = static_cast(FMath::Clamp(CurrentDrawingPitch / DRAWING_PITCH_MAX * PLATFORM_POSITION_LOGIC_MAX, PLATFORM_POSITION_LOGIC_MIN, PLATFORM_POSITION_LOGIC_MAX)); PlatformPosition.heave = static_cast(FMath::Clamp(CurrentDrawingHeave / DRAWING_HEAVE_MAX * PLATFORM_POSITION_LOGIC_MAX, PLATFORM_POSITION_LOGIC_MIN, PLATFORM_POSITION_LOGIC_MAX)); IForceSeatMI::Get().GetAPI().SendTopTablePosLog(&PlatformPosition); // ForceSeatMI - END }
Application: vehicle simulation
Examples: Telemetry_Veh_Unreal (use built-in ForceSeatPM profile SDK – Vehicle Telemetry) For vehicle simulation application IForceSeatMI_VehicleTelemetry helper interface can be used. IForceSeatMI_VehicleTelemetry requires PhysXVehicles and extracts automatically all necessary data from APawn and UWheeledVehicleMovementComponent objects. Typical operation routine consists of following steps:- Create a pointer member variable inside your class which will point to an instance of IForceSeatMI_VehicleTelemetry:
IForceSeatMI_VehicleTelemetry* m_veh;
- Initialize it in class constructor:
m_veh(&IForceSeatMI::Get().GetVehicleTelemetry())
- When simulation starts call (e.g. in BeginPlay() method of your APawn implementation):
m_veh->Begin();();
- The SIM should send telemetry data in constant intervals using following function:
m_veh->Tick(...);
- At the end of simulation call:
m_veh->End();
Code
Below code comes from Telemetry_Veh_Unreal example.void ATelemetry_Veh_UnrealPawn::Tick(float Delta) { Super::Tick(Delta); // ... generated UE4 code removed for better clarity // ForceSeatMI - BEGIN IForceSeatMI::Get().GetVehicleTelemetry().Tick(*this, *GetVehicleMovement(), Delta, false/* no pause */); // ForceSeatMI - END } void ATelemetry_Veh_UnrealPawn::BeginPlay() { Super::BeginPlay(); // ForceSeatMI - BEGIN IForceSeatMI::Get().GetVehicleTelemetry().Begin(); // ForceSeatMI - END }
Application: flight simulation
Examples: Telemetry_Fly_Unreal (use built-in ForceSeatPM profile SDK – Plane Telemetry) For flight simulation, a raw IForceSeatMI_API or IForceSeatMI_PlaneTelemetry helper interface can be used. IForceSeatMI_PlaneTelemetry automatically extracts all necessary data from APawn object and then calculates missing information like accelerations. Typical operation routine consists of following steps:- Create a pointer member variable inside your class which will point to an instance of IForceSeatMI_PlaneTelemetry:
IForceSeatMI_PlaneTelemetry* m_fly;
- Initialize it in class constructor:
m_fly(&IForceSeatMI::Get().GetPlaneTelemetry())
- When simulation starts call (e.g. in BeginPlay() method of your APawn implementation):
m_fly->Begin();();
- The SIM should send telemetry data in constant intervals using following function:
m_fly->Tick(...);
- At the end of simulation call:
m_fly->End();
Code
Below code comes from Telemetry_Fly_Unreal example.void ATelemetry_Fly_UnrealPawn::Tick(float DeltaSeconds) { // ... generated UE4 code removed for better clarity / Call any parent class Tick implementation Super::Tick(DeltaSeconds); // ForceSeatMI - BEGIN IForceSeatMI::Get().GetPlaneTelemetry().Tick(*this, DeltaSeconds, false/* no pause */); // ForceSeatMI - END } void ATelemetry_Fly_UnrealPawn::BeginPlay() { Super::BeginPlay(); // ForceSeatMI - BEGIN IForceSeatMI::Get().GetPlaneTelemetry().Begin(); // ForceSeatMI - END }