Changing force plates in Foot MoCAP model


#1

Hello
I am in the processing of modifying the GM MoCAP foot model, and have changed the force plate definition to a type-2 in the environment.any file. However, I’m having an error further down with the script:

AnyVec3 ForcePlateResultantGlobal = (.Plate1.Fz.Flocal+.Plate1.Fy.Flocal+.Plate1.Fx.Flocal)*.Plate1.ForcePlate.Axes’;
AnyVar ForceTestSum = sum(.FootPressureNodeCoeffVec); //should be equal to 1

As it considers Fz as unresolved.
(I’ve entered this for my force plate definition:

[SIZE=3][SIZE=1][COLOR=black]ForcePlateType2 Plate1 (
PlateName = Plate1,
Folder =Main.ModelSetup.C3DFileData,
No=0,
Fx=Main.ModelSetup.C3DFileData.Analog.DataFiltered.Force_46_Fx1,
Fy=Main.ModelSetup.C3DFileData.Analog.DataFiltered.Force_46_Fy1,
Fz=Main.ModelSetup.C3DFileData.Analog.DataFiltered.Force_46_Fz1,
Mx=Main.ModelSetup.C3DFileData.Analog.DataFiltered.Moment_46_Mx1,
My=Main.ModelSetup.C3DFileData.Analog.DataFiltered.Moment_46_My1,
Mz=Main.ModelSetup.C3DFileData.Analog.DataFiltered.Moment_46_Mz1)
={
// Cal=Main.ModelSetup.C3DFileData.Groups.FORCE_PLATFORM.CAL_MATRIX.Data[0];
};

I realise this is probably a very simple query, but I am a novice, and therefore your input would be most welcome - thank you!

Claire
[/SIZE][/COLOR][/SIZE]


#2

Just for the record, the error has been resolved. It was due to a naming inconsistency between the model and the force plate.


#3

Hello, I am having similar problems with this forceplate. I’m trying to use it with the GM Foot model. I’m using the latest version of software.

Environment.any

ForcePlateType2 Plate1 (
PlateName = Plate1,
Folder =Main.ModelSetup.C3DFileData,
Limb= .BodyModelRef.Right.Leg.Seg.Foot, 
No=0,
Fx=Main.ModelSetup.C3DFileData.Analog.DataFiltered.Force_46_Fx1,
Fy=Main.ModelSetup.C3DFileData.Analog.DataFiltered.Force_46_Fy1,
Fz=Main.ModelSetup.C3DFileData.Analog.DataFiltered.Force_46_Fz1,
Mx=Main.ModelSetup.C3DFileData.Analog.DataFiltered.Moment_46_Mx1,
My=Main.ModelSetup.C3DFileData.Analog.DataFiltered.Moment_46_My1,
Mz=Main.ModelSetup.C3DFileData.Analog.DataFiltered.Moment_46_Mz1)
={};

Is returning with

ERROR(SCR.PRS9) :   D:/D..s/A..s/A..g/A..n/Beta/M..t/M..l/Environment.any(23)  :   'Foot'  :  Unresolved object

It’s probably a simple fix, so apologies in advance!

King Regards,
Zach


#4

Hi Zach,

The error says that the foot object is not found, this is because you are using the GM foot models, it does not have any segment called foot. For a detailed foot model you can not just use this forceplate and apply the forces to a single segment, basically you also need a plantar pressure measurement to distribute the forces among the individual segments.

In footGM model in the beta folder the force plate are used to obtain the direction of the GRF, but the distribution is done using the plantar pressure, so you need both.

Best regards
Søren


#5

Hi Søren, thank you, that makes a lot of sense!

I’ve been trying to integrate my own gait data with the GM model.

I’ve changed the marker definitions etc and I’ve replaced the Type2Force plate with the Type3Pressure plate. Although I do not have my own pressure data at the moment I was wondering if it is possible to get the model running with the pressure data within the file?

I’ve run it with my own gait data and the model has returned:

ERROR(OBJ1) :   D:/D..s/A..s/A..g/A..n/Beta/M..t/M..l/JointsAndDriversOptimized.any(18)  :   JntDriverTrunk  :  Time, 't', has an invalid value for this interpolation
Model loading skipped

Attached is my zip file for reference.
Thank you very much,
Zach


#6

Hi Zach,

I am afraid it would not make a lot of sense to run the model on an incomplete data set, having no pressure data/ or having it replaced with one from another trial.

The pressure data has a location in space so it will appear at a certain location depnding on where the subject touched the plate. If you use markers from one trial and pressure from another this will be in conflict in terms of location.

Secondly there will be troubles with the timing, your mocap data will start and end at a different time than the pressure data also causing issues.

Finally the error you see indicates that you are trying to drive the model using an interpolation driver which has no valid data. Usually the data is created in the kinematic study and saved in a file, which is then used by inverse analysis. The error you have indicates you have not completed the kinematic analysis successfully.

Best regard
Søren


#7

Hi Søren,

I have got corresponding pressure data converted to be read by anybody FootLocation.py I understand the height and width numbers in the python file but unsure of the bottom and left numbers mean?

I have loaded the model with which has returned the same error, but i am unsure of where to look to solve the issue, could it be how the gait or force plate data is organised?

With regards to the kinematic study, and the txt input files, do they need to be cleared of any data before running the model or will the model overwrite the data?

Also do the marker names need to be changed in the BareFootWalk-OptimizedParameters.txt too?

Kind Regards,
Zach


#8

Hi Zach,

Bottom and left are the postion of the lower left corner of the pressure data. The sample data does not display data from all cells of the plate, for each foorprint there is a square which has been cut out of the original data. The lower left represents the corner cell number of the square, similarly there are a width and height varaible representing number of cell in width and height

The reason for the error can also be related to the setting of the tstart and tend. I think in this model these values are read from the pressure data, i think there is a python file named timeinfo which is used for this. So if there is a mismatch between the tstart and the first time value in your data you will get the error. Say your tstart in the study is 1sec and the data says first time value is 2 sec it will give the error you see.

So look in the file it is complaining about check the first time value there and compare with tstart of study.

The txt files are automatically overwritten.

One more thing if you get the error in the kin study my answers above applies, if the error is inverse it is because you did not complete kin analysis.

Best regards
Søren


#9

Hi Søren,
I’ve switched off muscles from the model and i’m able to run the motionoptimisation parameters and kinematic analysis. I’ve also rotated the initial positon of the pelvis in the model and changed the tstart and tend times on the trail specific data.

When I switch on inverse dynamics model I get a python error:

ERROR(SCR.EXP0) :   D:/D..s/A..s/A..g/A..n/Beta/M..t/M..l/Environment.any(384)  :   'FootPressureNodeCoeffVec'  :  Error in expression. Please refer to the following error messages for details ...
ERROR(SCR.EXP.FUN.EXT5) :   D:/D..s/A..s/A..g/A..n/Beta/M..t/M..l/Environment.any(372)  :   PressureFunction  :  External module or submodule, D:\Documents\Anyscripts\AMMR.v1.6.2-MyDemo - GMScaling\Application\Beta\MoCap-GMFoot\Model\Final2.py, was not found.  Python error : ImportError: No module named 'scipy'
  File "D:\Documents\Anyscripts\AMMR.v1.6.2-MyDemo - GMScaling\Application\Beta\MoCap-GMFoot\Model\Final2.py", line 3, in <module>
    from scipy import interpolate

The file is in the right location. Is the SciPy kit accessible within AnyBody?
Do you have any ideas on what the problem may be?

Thank you for your time,
Zach


#10

Hi Zach,

It seems the python installation you are runnning may not be compatible with the one needed by the model.

The error relates to scipy which seems to not have been installed

I have just update the wiki page to include a description on how to setup the correct python environment, please see it here:

https://github.com/AnyBody/support/wiki/How-to-use-the-AnyBody-GlasgowMaastricht-foot-model-(Foot-GM)#the-model-utilize-python-which-version-should-be-used

Best regards
Søren


#11

Thank you Søren, I have successfully installed the new libraries and I am getting a new error. Although when i first installed the new envs it didnt install to my anaconda folder at first, but a .conda folder, which is probably an issue on my side in terms of inital set-up.

ERROR(SCR.EXP0) :   D:/D..s/A..s/A..g/A..n/Beta/M..t/M..l/Environment.any(384)  :   'FootPressureNodeCoeffVec'  :  Error in expression. Please refer to the following error messages for details ...
ERROR(SCR.EXP.FUN.EXT8) :   D:/D..s/A..s/A..g/A..n/Beta/M..t/M..l/Environment.any(372)  :   PressureFunction  :  Exception in Python extention module.
  Python error : ValueError: A value in x_new is below the interpolation range.
  File "D:\Documents\Anyscripts\AMMR.v1.6.2-MyDemo - GMScaling\Application\Beta\MoCap-GMFoot\Model\Final2.py", line 181, in PressureFunction
    ScaleFactor = CellCoeffFunction(timestep)[i] / CoeffSumVec[i]
  File "C:\Program Files\Anaconda3\envs\py27_foot\Lib\site-packages\scipy\interpolate\interpolate.py", line 477, in _evaluate
    out_of_bounds = self._check_bounds(x_new)

I see it is referring to an interpolation issue where where the x_new is below the interpolation range. Is this an issue with the frame rate, my pressure data starts at Frame 1 (10.0 ms) or is it an issue with the interaction between the gait and pressure time steps? Or potentially the Rectangle bottom/Left definition?

Also with the Type3Pressure plate, can you explain a little on the analog Channels 1-8. Aside from Force and moment x,y,z and COP I am struggling to work out what each channel is referring to.

Kind Regards,
Zach


#12

Hi Zach,

I am unsure what goes wrong with the python code,

I would try to make the input pressure data you have to be exactly the same format as the original data, to rule out any issues related to that. Alternatively you migth be able to alter the python files read your data format.

Concerning the channels, please have a look at c3d.org website, in the documentation section there is a section on forceplates, and there is short description on each type.

Best regards
Søren


#13

Hi Soren,

Thank you for your reply. I see there is a long list of detailed scripting inheritance with this model through previous employees.

I have been able to read in my pressure file (which is different to that used in the model) and I have the CooVec tuple from the python script I’m sure this tuple is used to describe the anterior/posterior/lat/med points in the model.

I have these nodes visually in my model view, but I have had to rotate and translate sRel in AnyScript to line up with the foot as it shows in the model (perhaps if i did it in the Python Script it could be more accurate). When i run the inverse dynamics operation the error i’m having is to do with the FootCal1 or foot calibration study and initial condition unable to solve.

...  InverseDynamicStudy.InitialConditions  :  Kinematic analysis failed in time step 0 : Fail...

I think it might be due to the manual positioning of the pressure data, but i’m not quite sure, would you have any thoughts on this?

Kind Regards,
Zach


#14

Hi Zach,

I have looked into the model and it uses the the joint angles from the kinematic model to drive the model in this calibration study. So the calibration model here relies on that the kinematics has been finished correctly first, because the joint angles are used by this study.

So the kinematics needs to runs correct before the calibration will be able to run?

Best regards
Søren


#15

Hi Søren,

So i have been able to run kinematic analysis with the muscles switched off, but when i try and run the kinematics with the muscles switched on, it fails.

ERROR(OBJ.MCH.KIN3) :   D:/D..s/A..s/A..y/A..n/Beta/M..t/M..l/Kinematics.any(70)  :   MotionOptimization.InitialConditions  :  Kinematic analysis failed in time step 0 : Velocity analysis is not completed

Do you have any ideas as to why this is the case?

Kind Regards,
Zach


#16

Hi Zach,

Usually mocap driven models are designed to run in two steps first the kinematics is solved then the joint angles are saved and used in the inverse dynamic simulations with the muscles on. The foot model has also been made in this way, so i would recommend you to follow this approach

[ol]
[li] Run kinematics without muscles , this will export all joint angles… this will run using overdetermined kinematics
[/li][li] Run inverse with muscles, this will run a model using determined kinematics
[/li][/ol]

Additional info:
There can be difference in kinematics between a model with and without muscles sometimes, because there might be additional segments defined which are used to obtain correct moment arms, i think this is also the case in the foot, so this may explain why you see a different behavior between the two studies.

To see if this can be the explanation go the the modeltree and click the kinematicstudy / inverseStudy and compare the object descriptions. For studies the object description contains a full list of segments, joints, drivers in the study and is a good way to see exactly what is contained in the model.

Best regards
Søren


#17

Hi Soren,
I’ve managed to get the inverse dynamic study to fail at step 17.

1.0) Inverse dynamic analysis...
1.0) Inverse dynamic analysis...
ERROR(OBJ.MCH.MUS4) :   D:/D..s/A..s/A..y/A..n/Beta/M..t/M..l/InverseDynamics.any(22)  :   InverseDynamicStudy.InverseDynamics  :  Muscle recruitment solver :  solver aborted due to singular KKT matrix
0) Replay Operation...
ERROR(OBJ.OperationReplay1) :   D:/D..s/A..s/A..y/A..n/Beta/M..t/M..l/InverseDynamics.any(22)  :   InverseDynamicStudy.Replay  :  Replaying data failed in time step 17. Data is not ready.

In which conditions this might be the case?

I have a few questions about the format of pressure data.

  1. Does the BareFootWalk-PressureData.txt in the repo model contain the pressure of both left and right feet in the matrix.

  2. If the BareFootWalk-PressureData.txt in the repo contains just the right foot which direction is the heel strike to toe off in the matrix. Does heel strike to toe off run from the top to the bottom of the matrix or from right to left?

I have tried a few variations of what I think it is, but cannot seem to get it passed time step 17 in the Inverse Dynamic Study.

Thank you for your time,
Zach


#18

Hi Zach,

Sorry for the slow reply i have been out of office.

The error you have now means that the muscle recruitment solver did not managed to create balance in the model.

This could possibly relate to the way the loads are being applied?

  1. Does the BareFootWalk-PressureData.txt in the repo model contain the pressure of both left and right feet in the matrix.

I am not sure but i think this is not the case, please open the file and search for left in text if you find a section relatinn to left then it contains it, but i would it is not the case.

  1. If the BareFootWalk-PressureData.txt in the repo contains just the right foot which direction is the heel strike to toe off in the matrix. Does heel strike to toe off run from the top to the bottom of the matrix or from right to left?

As i recall it the first line relates to the heel strike and the last line in the section relates to the toe off, so heel strike to toe off runs top to bottom.

The KKT error means that some DOF in the model is not carried by the muscles. Sometimes it can be a good idea to add artificial torque generators in the joints to detect which dof are giving the the problem and the try to alter the muscles/ligaments/loads/calibration. To see how this is done take look in the JointMuscle.any file of the leg or arm and then try to replicated this for the foot joints.

Best regards
Søren


#19

Thank you for your reply Søren and I will have a look at the that.

Recently, I have been tinkering with the final2.py file specifically in the section:

  


# Scale the bell function coeff sum to match the measured cell coeff
    #*******************************************************************
    for i in range(len(CoeffMat)):
        if CoeffSumVec[i] == 0:
            ScaleFactor = 0
        else:
            ScaleFactor = CellCoeffFunction(timestep)[i] / CoeffSumVec[i]
        for j in range(len(CoeffMat[0])):
            CoeffMat[i][j] = CoeffMat[i][j] * ScaleFactor

I have changed this section to:

  # Scale the bell function coeff sum to match the measured cell coeff
    #*******************************************************************
    for i in range(len(CoeffMat)):
        if CoeffSumVec[i] == 0:
            ScaleFactor = 0
        else:
            #ScaleFactor = CellCoeffFunction(timestep)[i] / CoeffSumVec[i]
              ScaleFactor = 0.0344
        for j in range(len(CoeffMat[0])):
            CoeffMat[i][j] = CoeffMat[i][j] * ScaleFactor

The inverse dynamics sequence runs further as a I reduce the 0.0344 to 0.001, but the resultant forces from the pressure nodes do not look to be delivering the appropriate force per timestep.

When I run the original piece of python script the error returns:


Python error : ValueError: A value in x_new is below the interpolation range.
  File "D:\Documents\Anyscripts\AMMR.v1.6.2-MyDemo - GMScaling\Application\Beta\MoCap-GMFoot\Model\Final2.py", line 181, in PressureFunction
    ScaleFactor = CellCoeffFunction(timestep)[i] / CoeffSumVec[i]
  File "C:\Program Files\Anaconda3\envs\py27_foot\Lib\site-packages\scipy\interpolate\interpolate.py", line 477, in _evaluate
    out_of_bounds = self._check_bounds(x_new)

Would it be possible for you or a python expert at AnyBody to help explain how the final2.py script interacts with the AMS.

My pressuredata.txt is is in a similar format as the repository model with the exception the frame every 10ms (repo model is 2ms) the pressure.txt inputs are:

Rectangle bottom
12
Rectangle left
18
Rectangle width
25
Rectangle height
54

and the Environment.any footlocation4.py reads:


AnyFolder &GlobalRef = .GlobalRef;
    GlobalRef = {
      AnyRefNode StrikeFootRef = {
        sRel = {..FootLocationCooVec[0] -0.35, ..FootLocationCooVec[1] -0.52, 0}*RotMat(-pi,y)*RotMat(-pi,x);
        AnyDrawNode Draw = {ScaleXYZ=0.005*{1,1,1}; RGB={1,0,0};};
      };
      AnyRefNode PosteriorFootRef = {
        sRel = {..FootLocationCooVec[2 ]-0.35, ..FootLocationCooVec[3] -0.56, 0}*RotMat(-pi,y)*RotMat(-pi,x);
        AnyDrawNode Draw = {ScaleXYZ=0.005*{1,1,1}; RGB={0,1,0};};
      };
      AnyRefNode AnteriorMedialFootRef = {
        sRel = {..FootLocationCooVec[4] -0.35, ..FootLocationCooVec[5] -0.52, 0}*RotMat(-pi,y)*RotMat(-pi,x);
        AnyDrawNode Draw = {ScaleXYZ=0.005*{1,1,1}; RGB={0,0,1};};
      };
      AnyRefNode AnteriorLateralFootRef = {
        sRel = {..FootLocationCooVec[6] -0.35, ..FootLocationCooVec[7] -0.52, 0}*RotMat(-pi,y)*RotMat(-pi,x);
        AnyDrawNode Draw = {ScaleXYZ=0.005*{1,1,1}; RGB={1,1,0};};
      };
      AnyRefNode DistalFootRef = {
        sRel = {..FootLocationCooVec[8] -0.35, ..FootLocationCooVec[9] -0.52, 0}*RotMat(-pi,y)*RotMat(-pi,x);
        AnyDrawNode Draw = {ScaleXYZ=0.005*{1,1,1}; RGB={0,0,0};};
      };
     AnyRefNode DistalPhal1Ref = {
        sRel = {..FootLocationCooVec[10] -0.35, ..FootLocationCooVec[11] -0.52, 0}*RotMat(-pi,y)*RotMat(-pi,x);
        AnyDrawNode Draw = {ScaleXYZ=0.005*{1,1,1}; RGB={0,0,0};};
      };
      AnyRefNode DistalPhal2Ref = {
        sRel = {..FootLocationCooVec[12] -0.35, ..FootLocationCooVec[13] -0.52, 0}*RotMat(-pi,y)*RotMat(-pi,x);
        AnyDrawNode Draw = {ScaleXYZ=0.005*{1,1,1}; RGB={0,0,0};};
      };
    };

Also, Is it possible to print the matrix on the AnyBody GUI?

Kind Regards,
Zach


#20

Hi Zach,

It looks to me like there is a mismatch between the time of your study and the data in the file.

The error you get relates to that the it is try to extrapolate the data which is not possible.

So it reads the data first into an interpolation function and then it use the interpoaltion function which it created using “timestep”, this value comes from AnyBody and it seems to not macth the time from the file.

You wrote the that the that the sampling is different, please check if there are harcoded smapling setting in the .py files which needs to be changed in your case.

Another cause of error could be if you have non syncronized data, so mismatch between time in mocap and pressure data.

I would not scale the data, like you have tried.

Best regards
Søren