HBM posture regression model (driver)¶
This is a Jupyter notebook applying the posture regression model by Park et al. (2016), which is based on volunteer data, to HBM anthropometries. The resulting hip coordinates are used as a target position for the Petit et al. 2019 validation loadcase prepared as part of the HBM4VT validation loadcases. Full reference to the underlying regression model:
Park, J., Ebert, S. M., Reed, M. P., & Hallman, J. J. (2016). Statistical Models for Predicting Automobile Driving Postures for Men and Women Including Effects of Age. Human Factors, 58(2), 261–278. https://doi.org/10.1177/0018720815610249
How to use this notebook¶
- Run the import cell.
- Provide your HBM anthropometry in the respective cell.
- Run the regression model.
- Run the cell plotting the target posture.
- Copy the resulting LS-Dyna input deck lines into the respective input file you are working on (where it says
$### copy the following lines into your main file ###).
# imports
import pandas as pd
import numpy as np
import plotly.express as px
Update your HBM anthropometry parameters below¶
Input the anthropometry parameters for your HBM below. In case you don't know the correct value for the ratio of erect sitting height (ESH) to stature (esh_stature_ratio), you can jump to the cell at the end of the notebook, which provides an iterative approach to the problem.
# input your HBM data in mm, kg, years
label = 'THUMS v4.1 AM50'
gender = "male" # either "female" or "male"
stature = 1780 # in mm
esh_stature_ratio = 0.50 # ratio of erect sitting height (ESH) and stature
weight = 77.6 # in kg
age = 50 # in years; default: 50
# Petit et al. 2019 environment specification
H30 = 272.45 # updated seat height, which results in same H-point height for the THUMS v4.1 AM50 as when using HBMPos = 1
L6re = 0
# not used: H17 = 646 mm
# regression model (do not change)
def regression_driver_gender_age(gender,stature,esh_stature_ratio,weight,age,H30,L6re):
# Full reference:
#
# Park, J., Ebert, S. M., Reed, M. P., & Hallman, J. J. (2016).
# Statistical Models for Predicting Automobile Driving Postures for
# Men and Women Including Effects of Age. Human Factors, 58(2),
# 261–278. <https://doi.org/10.1177/0018720815610249>
#
assert gender in ['female','male'], 'Please specify the gender as either "female" or "male".'
BMI = weight/(stature/1000)**2
if gender == 'female':
LM_01_eye_X = 340+(0.355*stature)+(2.82*BMI)-(0.413*H30)+(0.55*L6re)
LM_01_eye_Z = -432+(0.347*stature)+(942*esh_stature_ratio)+(0.923*H30)
LM_02_tragion_X = 426+0.348*stature+(3.13*BMI)-0.42*H30+0.55*L6re
LM_02_tragion_Z = -538+0.369*stature+1054*esh_stature_ratio+0.927*H30
LM_03_C7_T1_X = 430+0.356*stature+2.99*BMI-0.394*H30+0.535*L6re
LM_03_C7_T1_Z = -399+0.299*stature+699*esh_stature_ratio+1.07*BMI+0.93*H30
LM_04_T12_L1_X = 8674-4.71*stature-15609*esh_stature_ratio+3.09*BMI-0.37*H30+0.491*L6re+9.57*stature*esh_stature_ratio
LM_04_T12_L1_Z = 81.3+0.0893*stature+0.939*H30
LM_05_L5_S1_X = 9853-5.36*stature-17602*esh_stature_ratio-5.4*BMI-2.84*age-0.388*H30+0.467*L6re+10.8*stature*esh_stature_ratio+0.112*BMI*age
LM_05_L5_S1_Z = 407-673*esh_stature_ratio+1.29*BMI-7.41*age+0.939*H30+13.8*esh_stature_ratio*age
LM_06_hip_X = 9446-5.19*stature-5.06*BMI-16970*esh_stature_ratio-2.75*age-0.365*H30+0.465*L6re+10.5*stature*esh_stature_ratio+0.109*BMI*age
LM_06_hip_Z = 276-680*esh_stature_ratio+4.54*BMI-5.55*age+0.906*H30-0.0576*BMI*age+12.9*esh_stature_ratio*age
LM_07_knee_X = 5036-2.73*stature-8853*esh_stature_ratio-0.429*H30+0.346*L6re+5.4*stature*esh_stature_ratio
LM_07_knee_Z = 600+0.0789*stature-1049*esh_stature_ratio-0.405*age+0.748*H30-0.233*L6re
LM_08_ankle_X = 409-0.137*stature-1.23*BMI-0.382*age+0.115*H30+0.142*L6re
LM_08_ankle_Z = 63.4+0.479*BMI+0.115*H30
if gender == 'male':
LM_01_eye_X = 291+(0.436*stature)-(0.482*H30)+(0.591*L6re)
LM_01_eye_Z = -413+(0.313*stature)+(878*esh_stature_ratio)+(2.24*BMI)+(0.968*H30)
LM_02_tragion_X = 357+0.447*stature-0.482*H30+0.597*L6re
LM_02_tragion_Z = -365+0.305*stature+830*esh_stature_ratio+1.99*BMI-0.198*age+0.974*H30
LM_03_C7_T1_X = 367+0.452*stature-0.454*H30+0.552*L6re
LM_03_C7_T1_Z = -290+0.209*stature+659*esh_stature_ratio+3.18*BMI+0.972*H30
LM_04_T12_L1_X = -420+0.862*stature+11.5*age-0.414*H30+0.541*L6re-0.00611*stature*age
LM_04_T12_L1_Z = 62.5+0.084*stature+0.806*BMI+0.965*H30+0.0321*L6re
LM_05_L5_S1_X = 1619+0.38*stature-2286*esh_stature_ratio-2.34*BMI-15.5*age-0.41*H30+0.524*L6re+30.5*esh_stature_ratio*age
LM_05_L5_S1_Z = 11.2+2.14*BMI+0.96*H30
LM_06_hip_X = 214+0.616*stature-680*esh_stature_ratio+7.21*age-0.392*H30+0.546*L6re-0.00386*stature*age
LM_06_hip_Z = 533-1051*esh_stature_ratio-25.1*BMI-0.182*age+0.935*H30+50.8*esh_stature_ratio*BMI
LM_07_knee_X = 4082-1.85*stature-6958*esh_stature_ratio+0.838*BMI-0.474*H30+0.391*L6re+3.68*stature*esh_stature_ratio
LM_07_knee_Z = -68.9+0.256*stature-361*esh_stature_ratio+0.731*H30-0.272*L6re
LM_08_ankle_X = 131+0.725*BMI+0.0753*H30+0.141*L6re
LM_08_ankle_Z = -34.5+0.069*stature+0.107*age+0.0974*H30
LM_x=[LM_01_eye_X,LM_02_tragion_X,LM_03_C7_T1_X,LM_04_T12_L1_X,LM_05_L5_S1_X,LM_06_hip_X,LM_07_knee_X,LM_08_ankle_X]
LM_z=[LM_01_eye_Z,LM_02_tragion_Z,LM_03_C7_T1_Z,LM_04_T12_L1_Z,LM_05_L5_S1_Z,LM_06_hip_Z,LM_07_knee_Z,LM_08_ankle_Z]
return [LM_x,LM_z]
Plot of target posture and export of hip coordinates¶
# plot of target position
fig = px.line(width=500,height=500)
fig.add_scatter(x=np.array(regression_driver_gender_age(gender,stature,esh_stature_ratio,weight,age,H30,L6re)[0]),
y=np.array(regression_driver_gender_age(gender,stature,esh_stature_ratio,weight,age,H30,L6re)[1]),
name=label, showlegend=True)
fig.update_layout(legend=dict(xanchor='center',
x=0.5,
yanchor='bottom',
y=-0.2))
fig.show()
# export of parameters for simulation
print('$### copy the following lines into your main file ###')
print('$ hip point for '+label)
print('R x_Hp %5.4f'%((regression_driver_gender_age(gender,stature,esh_stature_ratio,weight,age,H30,L6re)[0][5])))
print('R z_Hp %5.4f'%((regression_driver_gender_age(gender,stature,esh_stature_ratio,weight,age,H30,L6re)[1][5])))
$### copy the following lines into your main file ### $ hip point for THUMS v4.1 AM50 R x_Hp 880.6396 R z_Hp 260.4883
Stick figure based on the HBM parameters¶
You can export a "stick figure" based on your parameters as a plausibility check or to estimate the correct value for the ratio of erect sitting height (ESH) to stature (esh_stature_ratio). To do the latter, follow the this procedure:
- Estimate an initial value (usually the value should be between 0.5 and 0.54).
- Create the target posture above.
- Export the
stick_figure.kfile using the cell below. - Load this file on top of you HBM in a pre-processor.
- A stick figure (like the one in the plot above) should be visible. At each landmark position a box illustrating the RMSE for its position is shown.
- Compare the femur length by placing the hip point of the regression models stick figure over the HBM acetabulum. If necessary, rotate the stick figure around this hip point until the "femur" of both models are aligned.
- Check femur length:
- If the knee joint (specifically the
lateral femoral epicondyle) of your HBM is further forward than that in the stick figure (i.e. the HBM femur is longer), decrease the value foresh_stature_ratioand start again with bullet point 2. - If the knee joint (specifically the
lateral femoral epicondyle) of your HBM is further rearward than that in the stick figure (i.e. the HBM femur is shorter), increase the value foresh_stature_ratioand start again with bullet point 2. - If the knee joint (specifically the
lateral femoral epicondyle) position looks similar in the HBM and the regression model stick figure, use the hip point coordinates calculated with thisesh_stature_ratio.
- If the knee joint (specifically the
landmarks_RMSE = pd.read_csv("data/experiment/posture_regression_model_landmarks_RMSE.csv", delimiter=';', na_values='-', header = [0,1], index_col=0)
with open('data/experiment/stick_figure_template.k', 'r') as file:
data = file.read()
data = data.replace("placeholder_err_eyeX", str(landmarks_RMSE[(gender)].RMSE_x.loc['Eye/Orbit']))
data = data.replace("placeholder_err_traX", str(landmarks_RMSE[(gender)].RMSE_x.loc['Tragion']))
data = data.replace("placeholder_err_C7X", str(landmarks_RMSE[(gender)].RMSE_x.loc['C7/T1']))
data = data.replace("placeholder_err_T12X", str(landmarks_RMSE[(gender)].RMSE_x.loc['T12/L1']))
data = data.replace("placeholder_err_L5X", str(landmarks_RMSE[(gender)].RMSE_x.loc['L5/S1']))
data = data.replace("placeholder_err_hipX", str(landmarks_RMSE[(gender)].RMSE_x.loc['Hip']))
data = data.replace("placeholder_err_kneX", str(landmarks_RMSE[(gender)].RMSE_x.loc['Right Knee']))
data = data.replace("placeholder_err_ankX", str(landmarks_RMSE[(gender)].RMSE_x.loc['Right Ankle']))
data = data.replace("placeholder_err_eyeZ", str(landmarks_RMSE[(gender)].RMSE_z.loc['Eye/Orbit']))
data = data.replace("placeholder_err_traZ", str(landmarks_RMSE[(gender)].RMSE_z.loc['Tragion']))
data = data.replace("placeholder_err_C7Z", str(landmarks_RMSE[(gender)].RMSE_z.loc['C7/T1']))
data = data.replace("placeholder_err_T12Z", str(landmarks_RMSE[(gender)].RMSE_z.loc['T12/L1']))
data = data.replace("placeholder_err_L5Z", str(landmarks_RMSE[(gender)].RMSE_z.loc['L5/S1']))
data = data.replace("placeholder_err_hipZ", str(landmarks_RMSE[(gender)].RMSE_z.loc['Hip']))
data = data.replace("placeholder_err_kneZ", str(landmarks_RMSE[(gender)].RMSE_z.loc['Right Knee']))
data = data.replace("placeholder_err_ankZ", str(landmarks_RMSE[(gender)].RMSE_z.loc['Right Ankle']))
data = data.replace("placeholder_tra_eyeX", str("%.3f" % regression_driver_gender_age(gender,stature,esh_stature_ratio,weight,age,H30,L6re)[0][0]))
data = data.replace("placeholder_tra_traX", str("%.3f" % regression_driver_gender_age(gender,stature,esh_stature_ratio,weight,age,H30,L6re)[0][1]))
data = data.replace("placeholder_tra_C7X", str("%.3f" % regression_driver_gender_age(gender,stature,esh_stature_ratio,weight,age,H30,L6re)[0][2]))
data = data.replace("placeholder_tra_T12X", str("%.3f" % regression_driver_gender_age(gender,stature,esh_stature_ratio,weight,age,H30,L6re)[0][3]))
data = data.replace("placeholder_tra_L5X", str("%.3f" % regression_driver_gender_age(gender,stature,esh_stature_ratio,weight,age,H30,L6re)[0][4]))
data = data.replace("placeholder_tra_hipX", str("%.3f" % regression_driver_gender_age(gender,stature,esh_stature_ratio,weight,age,H30,L6re)[0][5]))
data = data.replace("placeholder_tra_kneX", str("%.3f" % regression_driver_gender_age(gender,stature,esh_stature_ratio,weight,age,H30,L6re)[0][6]))
data = data.replace("placeholder_tra_ankX", str("%.3f" % regression_driver_gender_age(gender,stature,esh_stature_ratio,weight,age,H30,L6re)[0][7]))
data = data.replace("placeholder_tra_eyeZ", str("%.3f" % regression_driver_gender_age(gender,stature,esh_stature_ratio,weight,age,H30,L6re)[1][0]))
data = data.replace("placeholder_tra_traZ", str("%.3f" % regression_driver_gender_age(gender,stature,esh_stature_ratio,weight,age,H30,L6re)[1][1]))
data = data.replace("placeholder_tra_C7Z", str("%.3f" % regression_driver_gender_age(gender,stature,esh_stature_ratio,weight,age,H30,L6re)[1][2]))
data = data.replace("placeholder_tra_T12Z", str("%.3f" % regression_driver_gender_age(gender,stature,esh_stature_ratio,weight,age,H30,L6re)[1][3]))
data = data.replace("placeholder_tra_L5Z", str("%.3f" % regression_driver_gender_age(gender,stature,esh_stature_ratio,weight,age,H30,L6re)[1][4]))
data = data.replace("placeholder_tra_hipZ", str("%.3f" % regression_driver_gender_age(gender,stature,esh_stature_ratio,weight,age,H30,L6re)[1][5]))
data = data.replace("placeholder_tra_kneZ", str("%.3f" % regression_driver_gender_age(gender,stature,esh_stature_ratio,weight,age,H30,L6re)[1][6]))
data = data.replace("placeholder_tra_ankZ", str("%.3f" % regression_driver_gender_age(gender,stature,esh_stature_ratio,weight,age,H30,L6re)[1][7]))
with open(r'stick_figure.k', 'w') as file:
file.write(data)