This short tutorial explains how to create new profile and how scripting engine works.

Creating new profile

For most of supported games there are already built-in profiles. However in case a custom profile is needed, one can start from cloning existing profile or start from scratch.

1. Open main program window and click on existing profile.
2. Click Clone

3. Enter name for new profile and click OK.

4. The Profile Editor will be opened.
5. For purpose of this exercise, remove all scripts except the one for Any platform.

5. Click Save to apply changes.
6. Click View – it will open a directory contains the script.

7. Finally open the script (*.js) in text editor (e.g. Notepad, Notepad++).

NOTE: ForceSeatPM monitors for changes in script file. It means that when the script file is modified in e.g Notepad, there is no need to reactive the profile. ForceSeatPM will automatically reload the script as long as the profile the script belongs to is still active.

Input plug

Input plug-in defines source of main telemetry data. Below is a list of plug-ins and their purposes. Please notice that this list can change in next version of the software.

  • FlighSimulator – dedicated for Microsoft Flight Simulator X
  • GPBikes – dedicated for PiBoSo GP-Bikes
  • IL2 – dedicated for IL2
  • Outsim – dedicated for games that uses Outsim protocol, for example: Live For Speed, GRID, GRID 2, Dirt, Dirt 2, Dirt 3, F1 2010, F1 2011, F1 2012
  • RFBaseGame – for games that uses the same plug-in API as rFactor 1/ 2 e.g.: rFactor, rFactor 2, Game Stock Car 2012.
    Please notice that there is different connector for rFactor 2 comparing to rFactor 1 but still both are supported by the same plug-in on ForceSeatPM side.
  • SimBinRace – dedicated for games from SimBin, e.g.: GTR2, Race 07 family, RaceRoom Racing Experience
  • XPlane – dedicated for X-Plane 10, both x86 and x64

Besides game specific plug-ins there are also more generic plugins:

  • DirectInput – it captures a steering wheel/joystick device, it can be used with any game that uses Microsoft DirectInput interface to interact with a game controller. Usually it is good to combine it with ForceFeedback as effect plug-in.
  • ForceSeatMI – for programs and games that use MotionSystem ForceSeatMI API which is a part of ForceSeat SDK.

Some plug-ins require a connector (a different type of plug-in, usually DLL library) to be installed in a game folder, other just need game reconfiguration.

In most cases all these tasks (connector installation and game reconfiguration) are done by ForceSeatPM semi-automatically – they appear as issues in Action Center and one just has to click Install or Configure.

However if for some reason ForceSeatPM is not able to find game installation folder, manual connector installation has to be performed via Games Integration.

Motion cueing

Motion system moves according to the parameters specified in the motion profile. Input parameters come from input plug-in and/or effect plug-in and they can have different names depending on selected plug-ins. The final position of a platform is a result of combination and transformation of different values received from the game. This transformation can be performed by a mapping mechanism or by a script mechanism.

The first one calculates final position of the platform by applying list of defined transformations of input values. It is easy in use but it is limited to predefined algorithms and transformations.

The second one uses Javascript custom code that gets values from the game as input and outputs desired platform position.

Please notice that instead of direct actuator positions, it is recommended to use axes. In this approach e.g. left-right rotation can be transformed by firmware into motion of two actuators for 2-dof platform but also for six actuators movement for 6-dof platform. It makes the profile more independent to the platform configuration.

Following axes are used by ForceSeatPM and the platform firmware:

  • Left-Right rotation (Roll)
  • Rear-Front rotation (Pitch)
  • Horizontal Left-Right rotation (Yaw)
  • Down-Up movement (Heave)
  • Left-Right movement (Surge)
  • Rear-Front movement (Sway)

For both motion cueing mechanisms, it is very important to understand the relation between output values (axis values) and the actual platform motion:

  • If you want to stop the platform in a center position all parameters should be equal 0.
  • Maximum movement in each axis is represented by value of 32767 or -32767, for instance for left-right rotation, -32767 means maximum to the left, 32767 means maximum to the right

The system therefore can move to 65535 possible positions on each of the motion axis and it is important to scale parameters from the game to the range of (-32767, 32767). Additionally every platform has some latency, so it is also important to scale and filter all parameters to reduce visible effect of delay.

The whole trick is to figure out how to use limited actuators operating range and G-force to make a player thinks that he or she is affected by the same forces as in real world when e.g. he or she is driving a car.

Data mapping transformation

After selecting input and effects plug-in, it is time to define mapping between telemetry received from the game and platform movements. Let’s start with defining generic parameters:

  • Start Ramp – defines how fast an actuator should accelerate: rapid means that actuator will accelerate as fast as possible; very slow means that it can take even few seconds to achieve desired speed. Slow acceleration is recommended for flight simulators.
  • Stop Ramp – similar as above, but for breaking/stopping.
  • Maximum speed – maximum allowed actuators speed, the actuators will never move faster than this defined value. Please notice that setting this value to low can make the actuator not move at all.
  • Transformation type – defines if mapping or script code is used during calculation of platform position, for this example mapping is selected.

Next step is mapping definition. Click Add Mapping and first item will be added to a list. There are following fields that need configuration:

  • Source – name of the input value received from the game, usually it is good to use values related to acceleration in a vehicle coordinate system (e.g. Acceleration body X for rFactor)
  • Motion type – name of a platform axis
  • Algorithm– defines how to process telemetry value before sending it to the motion system:
    • 1:1 – no processing, pass unchanged value.
    • Delta Value – motion system receives the difference between a current value and a previous value.
    • Average of Last 2, 3 or 5 – motion system receives an average value of recent N values.
    • Offset – defines a contant value that is added to the parameter before it is proceeded.
    • Factor – value from the game is multiplied by the factor after applying algorithm and offset.
    • Range – the final value is reduced to defined range.

The final equation for single axis looks as follows:


You can use the same source a few times and you can also use the same axis a few times. In this case final value for axis is just a sum.

In theory data mapping looks simple, but the trick is to find the best parameters values and the best combination of different source signals. Usually it takes hours of experiments and diagnostic module can be useful here.

Typical scenario looks as follows:

  1. Create a basic profile for the game.
  2. Activate the profile and open diagnostic for input/effects plug-in. It can be done from Profile Editor (by clicking Diagnostic button) or from a main program window in profile details view.
  3. Start the game in a windowed mode (if it is possible), otherwise use second display.
  4. Play the game and observe platform movements and also values in diagnostic window.
  5. Adjust the profile.
  6. Repeat steps 4 and 5 until results are as expected.

Please notice that is it not necessary to reactivate the profile, it is enough to just click Save.

Script transformation

If the data mapping is not enough and additional processing has to be performed, the solution is script transformation mechanism. It uses Javascript to define a small program that transforms input data into platform’s axis: http://doc.qt.io/qt-5/ecmascript.html

When the built-in profile is cloned, it already has an script. Most of script for racing games uses MoSy_DefaultProcessor and usually it is enough to tune its parameters. For flight simulators usually combination of low pass filters is used. You can always check default scripts for reference.

Please notice that the script execution time is crucial. No delays, waits or long operations are allowed, otherwise it will introduce extra latency.

The script itself has to define a function called process(), all other functions and variables are optional.

The default script file contains a list of all available input fields (defined as global variables) and output axes that have to be set (also defined as global variables). It is up to a user to write a code that maps input fields into output fields. Usually it is good to use low pass and high pass filters to catch bump and hits and at the same time slightly smooth normal movements (left-right rotations).

For purpose of this tutorial, we will focus on racing games and adjusting parameters of „default processor”.

Signal filters for racing games

Parameters that configure motion platform moves are grouped into 6 categories. Each category is mapped to one axis.

For each of axis there is 7 parameters that configure low-pass and high-pass filters. Low-pass filter is used to get main trend from input signal and high-pass filter to get bumps, vibrations and other irregular and rapid signal changes.

Please check following script fragment for reference:

var rollLowPassFactor        = 45;
var rollHighPassFactor       = 10;
var rollOutputFactor         = 12;
var rollHighOutputFactor     = -7;
var rollMax                  =  90;
var rollHighPassFilterCutOff = 90;
var rollBumpMin              = 5;
 
var heaveLowPassFactor        = 25;
var heaveHighPassFactor       = 10;
var heaveOutputFactor         = 15;
var heaveHighOutputFactor     = -12;
var heaveMax                  = 25;
var heaveHighPassFilterCutOff = 30;
var heaveBumpMin              = 15;
 
// ...
 
function process() {
	var rollValue = -in_FieldAccGX * 10;
	var pitchValue = in_FieldAccGZ * 10;
	var heaveValue = in_FieldAccGY * 10;
	var yawValue = -in_FieldHeadingChange / 10;
	var surgeValue = in_FieldAccGZ * 10;
	var swayValue = -in_FieldAccGX * 10;
 
	MoSy_DefaultProcessor(rollValue, pitchValue, heaveValue, yawValue, surgeValue, swayValue);

The meaning of parameters is as follows:

  • …LowPassFactor – level of low-pass filter. Increasing this value makes the main trend smoother and reduces vibrations and bumps. Too big value can cause a lag between motion platform moves and moves in the game. Range: [1, ∞)
  • …HighPassFactor – level of high-pass filter. Low value causes output signal to change rapidly with high amplitude. Increasing this value reduces amplitude and frequency of the changes. This parameter is used to configure level of bumps. Range: [1, ∞)
  • …OutputFactor – it defines how much low-pass filter output value affects axis move. Range: [0, ∞)
  • …HighOutputFactor – it defines how much hight-pass filter output value affects axis move. Range: [0, ∞)
  • …Max – it limits maximum platform movement that comes from low-pass filter output value on axis. Range: [0, 127] – the value is multiplied by 256 in MySo_DefaultProcessor
  • …HighPassFilterCutOff – it limits maximum platform movement that comes from hight-pass filter output value on axis. Range: [0, 127] – the value is multiplied by 256 in MySo_DefaultProcessor
  • …BumpMin – it is used to eliminate small and frequent vibrations by high-pass filter and leave. Low value causes lot of vibrations in high-pass filter output signal. Range: [0, ∞)

Flight simulators – FSX and P3D

Both plug-ins use SimConnect interface. Each field in script is mapped to SimConnect variable. The mapping is as follows:

  • in_FieldVelocityBodyX – „VELOCITY BODY X”
  • in_FieldVelocityBodyY – „VELOCITY BODY Y”
  • in_FieldVelocityBodyZ – „VELOCITY BODY Z”
  • in_FieldAccelerationBodyX – „ACCELERATION BODY X”
  • in_FieldAccelerationBodyY – „ACCELERATION BODY Y”
  • in_FieldAccelerationBodyZ – „ACCELERATION BODY Z”
  • in_FieldRotationVelocityBodyX – „ROTATION VELOCITY BODY X”
  • in_FieldRotationVelocityBodyY – „ROTATION VELOCITY BODY Y”
  • in_FieldRotationVelocityBodyZ – „ROTATION VELOCITY BODY Z”
  • in_FieldPlaneAltAboveGround – „PLANE ALT ABOVE GROUND”
  • in_FieldPlanePitchDegrees – „PLANE PITCH DEGREES”
  • in_FieldPlaneBankDegree – „PLANE BANK DEGREES”
  • in_FieldTurnCoordinatorBall – „TURN COORDINATOR BALL”
  • in_FieldGForce – „G FORCE”
  • in_FieldGear0Position – „GEAR POSITION:0”
  • in_FieldGear1Position – „GEAR POSITION:1”
  • in_FieldSimOnGround – „SIM ON GROUND”
  • in_FieldWheelRpm – „WHEEL RPM”
  • in_FieldPlaneHeadingDegreesTrue – „PLANE HEADING DEGREES TRUE”
  • in_FieldPlaneHeadingDegreesMagnetic – „PLANE HEADING DEGREES MAGNETIC”

Detailed description of SimConnect variables can be found on following pages:

Flight simulators – X-Plane

Each field in script is mapped to DataRef variable. The mapping is as follows:

  • in_FieldLatitude – „sim/flightmodel/position/lat_ref”
  • in_FieldPitch – „sim/flightmodel/position/theta”
  • in_FieldRoll – „sim/flightmodel/position/phi”
  • in_FieldTrueHeading – „sim/flightmodel/position/psi”
  • in_FieldMagneticHeading – „sim/flightmodel/position/magpsi”
  • in_FieldLocalAccelerationX – „sim/flightmodel/position/local_ax”
  • in_FieldLocalAccelerationY – „sim/flightmodel/position/local_ay”
  • in_FieldLocalAccelerationZ – „sim/flightmodel/position/local_az”
  • in_FieldAngleOfAttach – „sim/flightmodel/position/alpha”
  • in_FieldYaw – „sim/flightmodel/position/beta”
  • in_FieldFlyPitch – „sim/flightmodel/position/vpath”
  • in_FieldFlyHeading – „sim/flightmodel/position/hpath”
  • in_FieldGroundSpeed – „sim/flightmodel/position/groundspeed”
  • in_FieldAirSpir – „sim/flightmodel/position/true_airspeed”
  • in_FieldSlipDeg – „sim/cockpit2/gauges/indicators/slip_deg”
  • in_FieldTurnRateHeading – „sim/cockpit2/gauges/indicators/turn_rate_heading_deg_pilot”
  • in_FieldTurnRateRoll – „sim/flightmodel/misc/turnrate_roll”
  • in_FieldForceDownwardByAllEngines – „sim/flightmodel/forces/fnrml_prop”
  • in_FieldForceSidewaysByAllEngines – „sim/flightmodel/forces/fside_prop”
  • in_FieldForceForwardByAllEngines – „sim/flightmodel/forces/faxil_prop”
  • in_FieldAeroForceDownward – „sim/flightmodel/forces/fnrml_aero”
  • in_FieldAeroForceSideways – „sim/flightmodel/forces/fside_aero”
  • in_FieldAeroForceForward – „sim/flightmodel/forces/faxil_aero”
  • in_FieldGearForceDownward – „sim/flightmodel/forces/fnrml_gear”
  • in_FieldGearForceSideways – „sim/flightmodel/forces/fside_gear”
  • in_FieldGearForceFordward – „sim/flightmodel/forces/faxil_gear”
  • in_FieldTotalWeight – „sim/flightmodel/weight/m_total”
  • in_FieldGForceDownward – „sim/flightmodel/forces/g_nrml”
  • in_FieldGForceForward – „sim/flightmodel/forces/g_axil”
  • in_FieldGForceSideways – „sim/flightmodel/forces/g_side”

Detailed description of variables can be found on following pages:

Predefined variables and functions in scripts

List of predefined variables and functions can be found here.