def dynamics(cls, t, x, u, p): return vehicleDynamics_KS(x, u, p)
def vehicleDynamics_MB(x,uInit,p): # vehicleDynamics_MB - multi-body vehicle dynamics based on the DOT # (department of transportation) vehicle dynamics # # Syntax: # f = vehicleDynamics_MB(t,x,u,p) # # Inputs: # x - vehicle state vector # u - vehicle input vector # p - vehicle parameter vector # # Outputs: # f - right-hand side of differential equations # # Example: # # See also: --- # Author: Matthias Althoff # Written: 05-January-2017 # Last update:17-December-2017 # Last revision:--- #------------- BEGIN CODE -------------- # set gravity constant g = 9.81 #[m/s^2] #states #x1 = x-position in a global coordinate system #x2 = y-position in a global coordinate system #x3 = steering angle of front wheels #x4 = velocity in x-direction #x5 = yaw angle #x6 = yaw rate #x7 = roll angle #x8 = roll rate #x9 = pitch angle #x10 = pitch rate #x11 = velocity in y-direction #x12 = z-position #x13 = velocity in z-direction #x14 = roll angle front #x15 = roll rate front #x16 = velocity in y-direction front #x17 = z-position front #x18 = velocity in z-direction front #x19 = roll angle rear #x20 = roll rate rear #x21 = velocity in y-direction rear #x22 = z-position rear #x23 = velocity in z-direction rear #x24 = left front wheel angular speed #x25 = right front wheel angular speed #x26 = left rear wheel angular speed #x27 = right rear wheel angular speed #x28 = delta_y_f #x29 = delta_y_r #u1 = steering angle velocity of front wheels #u2 = acceleration #consider steering constraints u = [] u.append(steeringConstraints(x[2],uInit[0],p.steering)) # different name uInit/u due to side effects of u #consider acceleration constraints u.append(accelerationConstraints(x[3],uInit[1],p.longitudinal)) # different name uInit/u due to side effects of u #compute slip angle at cg #switch to kinematic model for small velocities if abs(x[3]) < 0.1: beta = 0 else: beta = math.atan(x[10]/x[3]) vel = math.sqrt(x[3]**2 + x[10]**2) #vertical tire forces F_z_LF = (x[16] + p.R_w*(math.cos(x[13]) - 1) - 0.5*p.T_f*math.sin(x[13]))*p.K_zt F_z_RF = (x[16] + p.R_w*(math.cos(x[13]) - 1) + 0.5*p.T_f*math.sin(x[13]))*p.K_zt F_z_LR = (x[21] + p.R_w*(math.cos(x[18]) - 1) - 0.5*p.T_r*math.sin(x[18]))*p.K_zt F_z_RR = (x[21] + p.R_w*(math.cos(x[18]) - 1) + 0.5*p.T_r*math.sin(x[18]))*p.K_zt #obtain individual tire speeds u_w_lf = (x[3] + 0.5*p.T_f*x[5])*math.cos(x[2]) + (x[10] + p.a*x[5])*math.sin(x[2]) u_w_rf = (x[3] - 0.5*p.T_f*x[5])*math.cos(x[2]) + (x[10] + p.a*x[5])*math.sin(x[2]) u_w_lr = x[3] + 0.5*p.T_r*x[5] u_w_rr = x[3] - 0.5*p.T_r*x[5] #compute longitudinal slip #switch to kinematic model for small velocities if abs(x[3]) < 0.1: s_lf = 0 s_rf = 0 s_lr = 0 s_rr = 0 else: s_lf = 1 - p.R_w*x[23]/u_w_lf s_rf = 1 - p.R_w*x[24]/u_w_rf s_lr = 1 - p.R_w*x[25]/u_w_lr s_rr = 1 - p.R_w*x[26]/u_w_rr #lateral slip angles #switch to kinematic model for small velocities if abs(x[3]) < 0.1: alpha_LF = 0 alpha_RF = 0 alpha_LR = 0 alpha_RR = 0 else: alpha_LF = math.atan((x[10] + p.a*x[5] - x[14]*(p.R_w - x[16]))/(x[3] + 0.5*p.T_f*x[5])) - x[2] alpha_RF = math.atan((x[10] + p.a*x[5] - x[14]*(p.R_w - x[16]))/(x[3] - 0.5*p.T_f*x[5])) - x[2] alpha_LR = math.atan((x[10] - p.b*x[5] - x[19]*(p.R_w - x[21]))/(x[3] + 0.5*p.T_r*x[5])) alpha_RR = math.atan((x[10] - p.b*x[5] - x[19]*(p.R_w - x[21]))/(x[3] - 0.5*p.T_r*x[5])) #auxiliary suspension movement z_SLF = (p.h_s - p.R_w + x[16] - x[11])/math.cos(x[6]) - p.h_s + p.R_w + p.a*x[8] + 0.5*(x[6] - x[13])*p.T_f z_SRF = (p.h_s - p.R_w + x[16] - x[11])/math.cos(x[6]) - p.h_s + p.R_w + p.a*x[8] - 0.5*(x[6] - x[13])*p.T_f z_SLR = (p.h_s - p.R_w + x[21] - x[11])/math.cos(x[6]) - p.h_s + p.R_w - p.b*x[8] + 0.5*(x[6] - x[18])*p.T_r z_SRR = (p.h_s - p.R_w + x[21] - x[11])/math.cos(x[6]) - p.h_s + p.R_w - p.b*x[8] - 0.5*(x[6] - x[18])*p.T_r dz_SLF = x[17] - x[12] + p.a*x[9] + 0.5*(x[7] - x[14])*p.T_f dz_SRF = x[17] - x[12] + p.a*x[9] - 0.5*(x[7] - x[14])*p.T_f dz_SLR = x[22] - x[12] - p.b*x[9] + 0.5*(x[7] - x[19])*p.T_r dz_SRR = x[22] - x[12] - p.b*x[9] - 0.5*(x[7] - x[19])*p.T_r #camber angles gamma_LF = x[6] + p.D_f*z_SLF + p.E_f*(z_SLF)**2 gamma_RF = x[6] - p.D_f*z_SRF - p.E_f*(z_SRF)**2 gamma_LR = x[6] + p.D_r*z_SLR + p.E_r*(z_SLR)**2 gamma_RR = x[6] - p.D_r*z_SRR - p.E_r*(z_SRR)**2 #compute longitudinal tire forces using the magic formula for pure slip F0_x_LF = tireModel.mFormulaLongitudinal(s_lf, gamma_LF, F_z_LF, p.tire) F0_x_RF = tireModel.mFormulaLongitudinal(s_rf, gamma_RF, F_z_RF, p.tire) F0_x_LR = tireModel.mFormulaLongitudinal(s_lr, gamma_LR, F_z_LR, p.tire) F0_x_RR = tireModel.mFormulaLongitudinal(s_rr, gamma_RR, F_z_RR, p.tire) #compute lateral tire forces using the magic formula for pure slip res = tireModel.mFormulaLateral(alpha_LF, gamma_LF, F_z_LF, p.tire) F0_y_LF = res[0] mu_y_LF = res[1] res = tireModel.mFormulaLateral(alpha_RF, gamma_RF, F_z_RF, p.tire) F0_y_RF = res[0] mu_y_RF = res[1] res = tireModel.mFormulaLateral(alpha_LR, gamma_LR, F_z_LR, p.tire) F0_y_LR = res[0] mu_y_LR = res[1] res = tireModel.mFormulaLateral(alpha_RR, gamma_RR, F_z_RR, p.tire) F0_y_RR = res[0] mu_y_RR = res[1] #compute longitudinal tire forces using the magic formula for combined slip F_x_LF = tireModel.mFormulaLongitudinalComb(s_lf, alpha_LF, F0_x_LF, p.tire) F_x_RF = tireModel.mFormulaLongitudinalComb(s_rf, alpha_RF, F0_x_RF, p.tire) F_x_LR = tireModel.mFormulaLongitudinalComb(s_lr, alpha_LR, F0_x_LR, p.tire) F_x_RR = tireModel.mFormulaLongitudinalComb(s_rr, alpha_RR, F0_x_RR, p.tire) #compute lateral tire forces using the magic formula for combined slip F_y_LF = tireModel.mFormulaLateralComb(s_lf, alpha_LF, gamma_LF, mu_y_LF, F_z_LF, F0_y_LF, p.tire) F_y_RF = tireModel.mFormulaLateralComb(s_rf, alpha_RF, gamma_RF, mu_y_RF, F_z_RF, F0_y_RF, p.tire) F_y_LR = tireModel.mFormulaLateralComb(s_lr, alpha_LR, gamma_LR, mu_y_LR, F_z_LR, F0_y_LR, p.tire) F_y_RR = tireModel.mFormulaLateralComb(s_rr, alpha_RR, gamma_RR, mu_y_RR, F_z_RR, F0_y_RR, p.tire) #auxiliary movements for compliant joint equations delta_z_f = p.h_s - p.R_w + x[16] - x[11] delta_z_r = p.h_s - p.R_w + x[21] - x[11] delta_phi_f = x[6] - x[13] delta_phi_r = x[6] - x[18] dot_delta_phi_f = x[7] - x[14] dot_delta_phi_r = x[7] - x[19] dot_delta_z_f = x[17] - x[12] dot_delta_z_r = x[22] - x[12] dot_delta_y_f = x[10] + p.a*x[5] - x[15] dot_delta_y_r = x[10] - p.b*x[5] - x[20] delta_f = delta_z_f*math.sin(x[6]) - x[27]*math.cos(x[6]) - (p.h_raf - p.R_w)*math.sin(delta_phi_f) delta_r = delta_z_r*math.sin(x[6]) - x[28]*math.cos(x[6]) - (p.h_rar - p.R_w)*math.sin(delta_phi_r) dot_delta_f = (delta_z_f*math.cos(x[6]) + x[27]*math.sin(x[6]))*x[7] + dot_delta_z_f*math.sin(x[6]) - dot_delta_y_f*math.cos(x[6]) - (p.h_raf - p.R_w)*math.cos(delta_phi_f)*dot_delta_phi_f dot_delta_r = (delta_z_r*math.cos(x[6]) + x[28]*math.sin(x[6]))*x[7] + dot_delta_z_r*math.sin(x[6]) - dot_delta_y_r*math.cos(x[6]) - (p.h_rar - p.R_w)*math.cos(delta_phi_r)*dot_delta_phi_r #compliant joint forces F_RAF = delta_f*p.K_ras + dot_delta_f*p.K_rad F_RAR = delta_r*p.K_ras + dot_delta_r*p.K_rad #auxiliary suspension forces (bump stop neglected squat/lift forces neglected) F_SLF = p.m_s*g*p.b/(2*(p.a+p.b)) - z_SLF*p.K_sf - dz_SLF*p.K_sdf + (x[6] - x[13])*p.K_tsf/p.T_f F_SRF = p.m_s*g*p.b/(2*(p.a+p.b)) - z_SRF*p.K_sf - dz_SRF*p.K_sdf - (x[6] - x[13])*p.K_tsf/p.T_f F_SLR = p.m_s*g*p.a/(2*(p.a+p.b)) - z_SLR*p.K_sr - dz_SLR*p.K_sdr + (x[6] - x[18])*p.K_tsr/p.T_r F_SRR = p.m_s*g*p.a/(2*(p.a+p.b)) - z_SRR*p.K_sr - dz_SRR*p.K_sdr - (x[6] - x[18])*p.K_tsr/p.T_r #auxiliary variables sprung mass sumX = F_x_LR + F_x_RR + (F_x_LF + F_x_RF)*math.cos(x[2]) - (F_y_LF + F_y_RF)*math.sin(x[2]) sumN = (F_y_LF + F_y_RF)*p.a*math.cos(x[2]) + (F_x_LF + F_x_RF)*p.a*math.sin(x[2]) \ + (F_y_RF - F_y_LF)*0.5*p.T_f*math.sin(x[2]) + (F_x_LF - F_x_RF)*0.5*p.T_f*math.cos(x[2]) \ + (F_x_LR - F_x_RR)*0.5*p.T_r - (F_y_LR + F_y_RR)*p.b sumY_s = (F_RAF + F_RAR)*math.cos(x[6]) + (F_SLF + F_SLR + F_SRF + F_SRR)*math.sin(x[6]) sumL = 0.5*F_SLF*p.T_f + 0.5*F_SLR*p.T_r - 0.5*F_SRF*p.T_f - 0.5*F_SRR*p.T_r \ - F_RAF/math.cos(x[6])*(p.h_s - x[11] - p.R_w + x[16] - (p.h_raf - p.R_w)*math.cos(x[13])) \ - F_RAR/math.cos(x[6])*(p.h_s - x[11] - p.R_w + x[21] - (p.h_rar - p.R_w)*math.cos(x[18])) sumZ_s = (F_SLF + F_SLR + F_SRF + F_SRR)*math.cos(x[6]) - (F_RAF + F_RAR)*math.sin(x[6]) sumM_s = p.a*(F_SLF + F_SRF) - p.b*(F_SLR + F_SRR) + ((F_x_LF + F_x_RF)*math.cos(x[2]) \ - (F_y_LF + F_y_RF)*math.sin(x[2]) + F_x_LR + F_x_RR)*(p.h_s - x[11]) #auxiliary variables unsprung mass sumL_uf = 0.5*F_SRF*p.T_f - 0.5*F_SLF*p.T_f - F_RAF*(p.h_raf - p.R_w) \ + F_z_LF*(p.R_w*math.sin(x[13]) + 0.5*p.T_f*math.cos(x[13]) - p.K_lt*F_y_LF) \ - F_z_RF*(-p.R_w*math.sin(x[13]) + 0.5*p.T_f*math.cos(x[13]) + p.K_lt*F_y_RF) \ - ((F_y_LF + F_y_RF)*math.cos(x[2]) + (F_x_LF + F_x_RF)*math.sin(x[2]))*(p.R_w - x[16]) sumL_ur = 0.5*F_SRR*p.T_r - 0.5*F_SLR*p.T_r - F_RAR*(p.h_rar - p.R_w) \ + F_z_LR*(p.R_w*math.sin(x[18]) + 0.5*p.T_r*math.cos(x[18]) - p.K_lt*F_y_LR) \ - F_z_RR*(-p.R_w*math.sin(x[18]) + 0.5*p.T_r*math.cos(x[18]) + p.K_lt*F_y_RR) \ - (F_y_LR + F_y_RR)*(p.R_w - x[21]) sumZ_uf = F_z_LF + F_z_RF + F_RAF*math.sin(x[6]) - (F_SLF + F_SRF)*math.cos(x[6]) sumZ_ur = F_z_LR + F_z_RR + F_RAR*math.sin(x[6]) - (F_SLR + F_SRR)*math.cos(x[6]) sumY_uf = (F_y_LF + F_y_RF)*math.cos(x[2]) + (F_x_LF + F_x_RF)*math.sin(x[2]) \ - F_RAF*math.cos(x[6]) - (F_SLF + F_SRF)*math.sin(x[6]) sumY_ur = (F_y_LR + F_y_RR) \ - F_RAR*math.cos(x[6]) - (F_SLR + F_SRR)*math.sin(x[6]) #dynamics common with single-track model f = [] # init 'right hand side' #switch to kinematic model for small velocities if abs(x[3]) < 0.1: #wheelbase lwb = p.a + p.b #system dynamics x_ks = [x[0], x[1], x[2], x[3], x[4]] f_ks = vehicleDynamics_KS(x_ks,u,p) f.extend(f_ks) f.append(u[1]*lwb*math.tan(x[2]) + x[3]/(lwb*math.cos(x[2])**2)*u[0]) else: f.append(math.cos(beta + x[4])*vel) f.append(math.sin(beta + x[4])*vel) f.append(u[0]) f.append(1/p.m*sumX + x[5]*x[10]) f.append(x[5]) f.append(1/(p.I_z - (p.I_xz_s)**2/p.I_Phi_s)*(sumN + p.I_xz_s/p.I_Phi_s*sumL)) # remaining sprung mass dynamics f.append(x[7]) f.append(1/(p.I_Phi_s - (p.I_xz_s)**2/p.I_z)*(p.I_xz_s/p.I_z*sumN + sumL)) f.append(x[9]) f.append(1/p.I_y_s*sumM_s) f.append(1/p.m_s*sumY_s - x[5]*x[3]) f.append(x[12]) f.append(g - 1/p.m_s*sumZ_s) #unsprung mass dynamics (front) f.append(x[14]) f.append(1/p.I_uf*sumL_uf) f.append(1/p.m_uf*sumY_uf - x[5]*x[3]) f.append(x[17]) f.append(g - 1/p.m_uf*sumZ_uf) #unsprung mass dynamics (rear) f.append(x[19]) f.append(1/p.I_ur*sumL_ur) f.append(1/p.m_ur*sumY_ur - x[5]*x[3]) f.append(x[22]) f.append(g - 1/p.m_ur*sumZ_ur) #convert acceleration input to brake and engine torque if u[1]>0: T_B = 0 T_E = p.m*p.R_w*u[1] else: T_B = p.m*p.R_w*u[1] T_E = 0 #wheel dynamics (p.T new parameter for torque splitting) f.append(1/p.I_y_w*(-p.R_w*F_x_LF + 0.5*p.T_sb*T_B + 0.5*p.T_se*T_E)) f.append(1/p.I_y_w*(-p.R_w*F_x_RF + 0.5*p.T_sb*T_B + 0.5*p.T_se*T_E)) f.append(1/p.I_y_w*(-p.R_w*F_x_LR + 0.5*(1-p.T_sb)*T_B + 0.5*(1-p.T_se)*T_E)) f.append(1/p.I_y_w*(-p.R_w*F_x_RR + 0.5*(1-p.T_sb)*T_B + 0.5*(1-p.T_se)*T_E)) #negative wheel spin forbidden for iState in range(23, 26): if x[iState]<0: x[iState] = 0 f[iState] = 0 #compliant joint equations f.append(dot_delta_y_f) f.append(dot_delta_y_r) return f
def vehicleDynamics_ST(x,uInit,p): # vehicleDynamics_ST - single-track vehicle dynamics # # Syntax: # f = vehicleDynamics_ST(x,u,p) # # Inputs: # x - vehicle state vector # u - vehicle input vector # p - vehicle parameter vector # # Outputs: # f - right-hand side of differential equations # # Example: # # Other m-files required: none # Subfunctions: none # MAT-files required: none # # See also: --- # Author: Matthias Althoff # Written: 12-January-2017 # Last update: 16-December-2017 # 03-September-2019 # Last revision:--- #------------- BEGIN CODE -------------- # set gravity constant g = 9.81 #[m/s^2] #create equivalent bicycle parameters mu = p.tire.p_dy1 C_Sf = -p.tire.p_ky1/p.tire.p_dy1 C_Sr = -p.tire.p_ky1/p.tire.p_dy1 lf = p.a lr = p.b h = p.h_s m = p.m I = p.I_z #states #x1 = x-position in a global coordinate system #x2 = y-position in a global coordinate system #x3 = steering angle of front wheels #x4 = velocity in x-direction #x5 = yaw angle #x6 = yaw rate #x7 = slip angle at vehicle center #u1 = steering angle velocity of front wheels #u2 = longitudinal acceleration #consider steering constraints u = [] u.append(steeringConstraints(x[2],uInit[0],p.steering)) # different name uInit/u due to side effects of u #consider acceleration constraints u.append(accelerationConstraints(x[3],uInit[1],p.longitudinal)) # different name uInit/u due to side effects of u # switch to kinematic model for small velocities if abs(x[3]) < 0.1: #wheelbase lwb = p.a + p.b; #system dynamics x_ks = [x[0], x[1], x[2], x[3], x[4]] f_ks = vehicleDynamics_KS(x_ks,u,p) f = [f_ks[0], f_ks[1], f_ks[2], f_ks[3], f_ks[4], u[1]/lwb*math.tan(x[2]) + x[3]/(lwb*math.cos(x[2])**2)*u[0], 0] else: #system dynamics f = [x[3]*math.cos(x[6] + x[4]), x[3]*math.sin(x[6] + x[4]), u[0], u[1], x[5], -mu*m/(x[3]*I*(lr+lf))*(lf**2*C_Sf*(g*lr-u[1]*h) + lr**2*C_Sr*(g*lf + u[1]*h))*x[5] \ +mu*m/(I*(lr+lf))*(lr*C_Sr*(g*lf + u[1]*h) - lf*C_Sf*(g*lr - u[1]*h))*x[6] \ +mu*m/(I*(lr+lf))*lf*C_Sf*(g*lr - u[1]*h)*x[2], (mu/(x[3]**2*(lr+lf))*(C_Sr*(g*lf + u[1]*h)*lr - C_Sf*(g*lr - u[1]*h)*lf)-1)*x[5] \ -mu/(x[3]*(lr+lf))*(C_Sr*(g*lf + u[1]*h) + C_Sf*(g*lr-u[1]*h))*x[6] \ +mu/(x[3]*(lr+lf))*(C_Sf*(g*lr-u[1]*h))*x[2]] return f
def func_KS(x, t, u, p): f = vehicleDynamics_KS(x, u, p) return f
def test_derivatives(): # test_derivatives - unit_test_function for checking whether the derivative # is computed correctly # # Syntax: # res = test_derivatives() # # Inputs: # --- # # Outputs: # res - boolean result (0/empty: test not passed, 1: test passed) # # Example: # # Other m-files required: none # Subfunctions: none # MAT-files required: none # # See also: --- # Author: Matthias Althoff # Written: 17-December-2017 # Last update: --- # Last revision:--- #------------- BEGIN CODE -------------- # initialize result res = [] # load parameters p = parameters_vehicle2() g = 9.81 #[m/s^2] # set state values x_ks = [3.9579422297936526, 0.0391650102771405, 0.0378491427211811, 16.3546957860883566, 0.0294717351052816] x_st = [2.0233348142065677, 0.0041907137716636, 0.0197545248559617, 15.7216236334290116, 0.0025857914776859, 0.0529001056654038, 0.0033012170610298] x_mb = [10.8808433066274794, 0.5371850187869442, 0.0980442671005920, 18.0711398687457745, 0.1649995631003776, 0.6158755000936103, -0.1198403612262477, -0.2762672756169581, 0.0131909920269115, -0.0718483683742141, -0.3428324595054725, 0.0103233373083297, -0.0399590564140291, -0.0246468320579360, -0.0551575051990853, 0.5798277643297529, 0.0172059354801703, 0.0067890113155477, -0.0184269459410162, -0.0408207136116175, -1.0064484829203018, 0.0166808347900582, -0.0049188492004049, 53.6551710641082451, 50.7045242506744316, 56.7917911784219598, 200.7079633169796296, -0.0939969123691911, -0.0881514621614376] # set input: (accelerating and steering) v_delta = 0.15 acc = 0.63*g u = [v_delta, acc] # insert into vehicle dynamics to obtain derivatives f_ks = vehicleDynamics_KS(x_ks,u,p) f_st = vehicleDynamics_ST(x_st,u,p) f_mb = vehicleDynamics_MB(x_mb,u,p) # ground truth f_ks_gt = [16.3475935934250209, 0.4819314886013121, 0.1500000000000000, 5.1464424102339752, 0.2401426578627629] f_st_gt = [15.7213512030862397, 0.0925527979719355, 0.1500000000000000, 5.3536773276413925, 0.0529001056654038, 0.6435589397748606, 0.0313297971641291] f_mb_gt = [17.8820162482414098, 2.6300428035858809, 0.1500000000000000, 2.7009396644636450, 0.6158755000936103, 1.3132879472301846, -0.2762672756169581, -0.1360581472638375, -0.0718483683742141, 0.4909514227532223, -2.6454134031927374, -0.0399590564140291, 0.0486778649724968, -0.0551575051990853, 0.0354501802049087, -1.1130397141873534, 0.0067890113155477, -0.0886810139593130, -0.0408207136116175, 0.0427680029698811, -4.3436374104751501, -0.0049188492004049, 0.1142109377736169, 10.0527321757776047, 0.0436512393438736, 14.3044528684659404, 590.5602192640882322, -0.2105876149500405, -0.2126005780977984] # comparison res.append(all(abs(numpy.array(f_ks) - numpy.array(f_ks_gt)) < 1e-14)) res.append(all(abs(numpy.array(f_st) - numpy.array(f_st_gt)) < 1e-14)) res.append(all(abs(numpy.array(f_mb) - numpy.array(f_mb_gt)) < 1e-14)) # print(abs(numpy.array(f_ks) - numpy.array(f_ks_gt))) # print(abs(numpy.array(f_st) - numpy.array(f_st_gt))) # print(abs(numpy.array(f_mb) - numpy.array(f_mb_gt))) # obtain final result res = all(res) print('derivative test:') print(res) return res