Baseline drift (offset) correction from force plate analog data

Hello, I have an issue with the baseline drift (offset) correction from the force plate analog channel data. Please see the figure copied below (Figure 1) which shows how AnyBody reads the analog channel data from my .c3d file. It shows the offset in my analog force plate data (vertical component of force plate data is not zero during stance phase). I have got the "Baselines" correction values for each analog channel using Visual3D (Figure 2) to fix the drift/offset. Currently, I do not have access to the professional version of Visual3D to update the analog channel data with "Baselines" correction values. I am wondering if AnyBody has any option to apply the "Baselines" values to correct the drift in analog channels so that AnyBody can receive the drift-free force plate data.
I also have the processed force plate data in which drift is removed (FP1 & FP2 in Figure 2). However, I noticed that AnyBody only reads analog channel data, not the force plate data processed in Visual3D (FP1 & FP2).

I have alternatively used "Mokka" application to remove the baseline drifts in analog channels by selecting a range of reference frames. In this case, AnyBody can read the drift-free analog data, however, this results in different magnitude and temporal profile in the predicted joint reaction forces between left and right leg for a normal walking condition. Ideally, I did not expect that kind of variation in JRFs between left and right leg for a normal gait. Since I had to use different reference frames for left and right limb force plates, this might resulted in inconsistent (and inaccurate) drift correction between left and right leg followed by different magnitude and temporal profile of joint reaction forces (JRFs) in left and right leg.

I would highly appreciate your feedback on this regard. It would be great to know if I can apply the drift correction "Baselines" values within AnyBody. I would also appreciate your suggestion on any alternative way to fix this issue.

Figure 1:

Figure 2:

Hi Md Arifuzzaman Arif,

It's possible to apply baseline correction in AnyBody. I will share the piece of code first (this is for the LowerExtremity model in Plug-in-gait_simple folder in the AMMR):

Main = {
  AnyVar drift = -5.0;
  AnyVector CorrectedFz = Main.ModelSetup.C3DFileData.Analog.DataFiltered.Fz1 - drift;

   // this is the original Fz analog value that is used in the ForcePlate class.
  AnyVector OriginalFz = Main.ModelSetup.C3DFileData.Analog.DataFiltered.Fz1;
  
  // You can provide another channel as an object pointer (please note the &)
  // in the force plate class instead of using the default (original) channel. 
  Main.EnvironmentModel.ForcePlates.Plate1.ForcePlate.Fz = &Main.CorrectedFz;

};

Here is some explanation. The force plate class is set up to read the default channels containing the analog signal. However, you can overwrite and supply an object pointer to another channel. You will need to create this new channel. I have shown an example of adding an offset to the existing channel values. Then, the last line simply supplies the corrected channel as an object pointer. Please note that analog channel will be multiplied with calibration matrix to generate the force magnitude.

For the second part of your question, of course it is important to ensure that the correction you are making is actually correct. I think before looking at the joint reaction forces, you should look at the difference between the original GRF and the corrected GRF. That should most likely explain the difference in the predicted JRF

I hope this helps.

Best regards,
Dave

Hi Dave, Thank you for your reply. I have added this code to my model. However, I am having issues with defining the last line which is showing me errors consistently. I am wondering if I have assigned this code at an incorrect location. Could you please help me how/where I should define the last line? Currently it's showing me the following unknown error.
ERROR(SYS1) : Model load : Unknown error (*)

I have defined this 'baseline correction' section in the "Main" module of my model.

My Force Plate definition is currently like this:

Main.EnvironmentModel.ForcePlates =
{

// See forceplate specification for which option
// are available for the ForcePlateAutoDetection class:
// #include "<ANYMOCAP_PATH>/ForcePlates/ForcePlateAutoDetection.any"
// The ALLOW_MULTI_LIMB_CONTACT=OFF ensures the class can't create contact
// with both limbs simulatenously

ForcePlateAutoDetection Plate1(
PLATE_NO=1,
// HeightTolerance = 0.1,
HeightTolerance = 0.07,
VelThreshold = 2.2,
FORCEPLATE_TYPE = 4,
LIMB1=Main.HumanModel.BodyModel.Right.Leg.Seg.Foot,
LIMB2=Main.HumanModel.BodyModel.Left.Leg.Seg.Foot,
ALLOW_MULTI_LIMB_CONTACT = ON

) = {
GroundVelocity = {0,-0.60,0};}; //Instrumented Treadmill Velocity (Walking speed)

ForcePlateAutoDetection Plate2(
PLATE_NO=2,
// HeightTolerance = 0.1,
HeightTolerance = 0.07,
VelThreshold = 2.2,
FORCEPLATE_TYPE = 4,
LIMB1=Main.HumanModel.BodyModel.Right.Leg.Seg.Foot,
LIMB2=Main.HumanModel.BodyModel.Left.Leg.Seg.Foot,
ALLOW_MULTI_LIMB_CONTACT = ON
) = {GroundVelocity = {0,-0.60,0}; }; //Instrumented Treadmill Velocity (Walking speed)

// ForcePlateAutoDetection Plate3 (
// PLATE_NO=3,
// HeightTolerance = 0.07,
// VelThreshold = 2.2,
// FORCEPLATE_TYPE = 4,
// ALLOW_MULTI_LIMB_CONTACT = OFF
// ) = { };

};

I haven't modified anything else with the force plate definitions. I would highly appreciate your feedback to fix this baseline correction.

Thank you for your time. Have a good day!

Best Regards,
Arif

Hi Arif,

Can you show me the exact code that you have written in the Main file? Normally, on the Main file, you need to open and close the scope of Main and write the code inside it. Otherwise, you can write the code also somewhere else: like in the ForcePlates.any file. Just ensure that the pointers are correctly reflected.

If this doesn't work, then I would like to know which AMMR and AMS version are you using? Can you try without the code and share a screenshot of the ModelTree expanded to Main.EnvironmentModel.ForcePlates.Plate1.ForcePlate.Fz ?

Best regards,
Dave

Hi Dave,

Thank you for your reply. I have added the following line in my FullBody.main.any script.

#include "<ANYBODY_PATH_SETUP>FPBaselineOffsetCorrection.any"

Then, in the FPBaselineOffsetCorrection.any (located in the Setup folder) I have added the code that you mentioned earlier:

Main = {
    
  AnyVar drift = -5.0;
  AnyVector CorrectedFz = Main.ModelSetup.C3DFileData.Analog.DataFiltered._3_1_44_3_46_Force_46_Fz1 - drift;

   // this is the original Fz analog value that is used in the ForcePlate class.
  AnyVector OriginalFz = Main.ModelSetup.C3DFileData.Analog.DataFiltered._3_1_44_3_46_Force_46_Fz1;
  
  // You can provide another channel as an object pointer (please note the &)
  // in the force plate class instead of using the default (original) channel.
  
  Main.EnvironmentModel.ForcePlates.Plate1.ForcePlate.Fz = &Main.CorrectedFz;

};

I have noticed that the issue is with applying the CorrectedFz on the corresponding force plate component (Last line). Possibly I am not using the pointer correctly or this piece of code should be defined somewhere else. I would appreciate your feedback on this. I have tried to write this on ForcePlates.any file, but it's still showing me the same error message.

I am using AnyBody.7.3.x and AMMR version: AMMR.v2.4.2

Here's the screenshot of the ModelTree expanded to Main.EnvironmentModel.ForcePlates.Plate1.ForcePlate.Fz :

Best Regards,
Arif

Hi Arif,

I can reproduce the error with earlier version of AMS. In this case, I will suggest you please update to AMS 8.0.0 (or later). There was probably some bug that has been fixed. The rest of your implementation seems OK.

I will also recommend you use the latest AMMR with AMS 8.0.0

Best regards,
Dave