Search code examples
pythonpython-3.xnumpymodeling

How to update the state variables of a vehicle using longitudinal dynamics model?


I'm trying to model the dynamics of a vehicle moving longitudinally using python classes, the equations that my model should step through are clarified in the image link below :

https://drive.google.com/file/d/1CK75Q5JzkHM3YRQkWGpI6JojXwhrplD3/view?usp=sharing

I built my model based on the following logic :

  1. create a class.
  2. define all state variables as instance attributes.
  3. create instance method that takes throttle and inclination angle inputs and steps through the dynamics equations and updates the state variables.

to use the model the following steps are to be followed :

  1. create a class instance (object)
  2. define a time period to loop through (start,stop,step)
  3. create two arrays that has the data of both throttle and inclination angle to be passed to the model at each time sample
  4. loop through the time period calling the step method each time and save the desired state variables in a new array
  5. plot the desired array of state variable VS time

a brief view of the code is illustrated in code section bellow :

import sys
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimg

class Vehicle():
    def __init__(self):
    # ==================================
    #  Parameters are defined below but i deleted them to shorten the code
    # ==================================

    #Throttle to engine torque
    # Gear ratio, effective radius, mass + inertia
    # Aerodynamic and friction coefficients
    # Tire force 

    # State variables
    self.x = 0
    self.v = 5
    self.a = 0
    self.w_e = 100
    self.w_e_dot = 0

    self.sample_time = 0.01

def reset(self):
    # reset state variables
    self.x = 0
    self.v = 5
    self.a = 0
    self.w_e = 100
    self.w_e_dot = 0

def step(self, throttle, alpha):
    # calculate F_x, F_load, and T_e respictively
    # F_x calculations
    w_w = self.GR * self.w_e
    slip = ((w_w * self.r_e) - self.v) / self.v
    if (slip < 1 and slip > -1):
        f_x = self.c * slip
    else:
        f_x = self.F_max

    # F_load calculations
    f_aero = self.c_a * (self.v * self.v)
    r_x = self.c_r1 * self.v
    f_g = self.m * self.g * np.sin(alpha)
    f_load = f_aero + r_x + f_g

    # T_e calculations
    t_e = throttle * (self.a_0 + (self.a_1 * self.w_e) + (self.a_2 * self.w_e**2))

    # now update vehicle and engine acceleration rates
    self.a = (1 / self.m) * (f_x - f_load)
    self.w_e_dot = (1 / self.J_e) * (t_e - (self.GR * self.r_e * f_load))

    # now update vehicle position, speed and engine speed according to the updated vehicle and engine acceleration rates
    # using newton's formulas of motion (assuming constant acceleration during sample time )
    self.x = (self.v * self.sample_time) + (0.5 * self.a * self.sample_time**2) + self.x 
    self.v = (self.a * self.sample_time) + self.v
    self.w_e = (self.w_e_dot * self.sample_time) + self.w_e

i tested my model for both constant and varying throttle and inclination angle inputs and it behaves as expected. for example when gradually increase the throttle with a zero incline angle, the acceleration, speed and wheel angular speed and acceleration also increase, when the inclination angle is not zero the behavior varies according to it (i.e. if it were so big with a small throttle the car wouldn't be able to move due to high load forces which causes negative acceleration)

the following is an example where a constant throttle with a zero incline were passed to the model for time period of 100 seconds with a sample time of 0.01 second and then plot the speed vs time :

sample_time = 0.01
time_end = 100
model = Vehicle()

t_data = np.arange(0,time_end,sample_time)
v_data = np.zeros_like(t_data)

# throttle percentage between 0 and 1
throttle = 0.2

# incline angle (in radians)
alpha = 0

for i in range(t_data.shape[0]):
v_data[i] = model.v
model.step(throttle, alpha)

plt.plot(t_data, v_data)
plt.show()

the result is illustrated in the image in the following link :

https://drive.google.com/open?id=1ldPozpuJI24MPdOb9tnyQI03oHKF3W5f

which is somehow reasonable because the car accelerates until forces are balanced and the speed becomes constant.

the grader on coursera-platform provides a desired trajectory (specific and throttle and inclination angle for a given time period) and i'm asked to pass them my model as mentioned above and then save the data of the position state variable (x) to a file and submit it to the grading system. but it always outputs the following message whenever i try to do so:

assessment failed !! your trajectory deviates too much or your model is incorrect !

and it does not offer any information about the correct results. i really can't find out where the error is coming from and have no idea how to fix it. i know it's a very long question but i really need help, can anyone help please??


Solution

  • I could successfully find out where the error was, it turned out that the model was build correctly but i made a big mistake when i passed the trajectory data (throttle and inclination angle alpha) into my model, i passed the incline angle to the model based on time samples while it was given based on the distance (i.e. it was given that the incline angle was 0.05 rad for the first 60 meters and 0.1 rad for the next 90 meters) but fed these data into the model according to time passed (i.e. for the first 5 seconds pass an incline angle of .05 and for the next 10 seconds pas an incline angle of 0.1) which caused a slight deviation in the path and as a result the grader refused it. hope this helps someone one day, thanks all.

    here is the code i wrote first which was wrong :

    time_end = 20
    t_data = np.arange(0,time_end,sample_time)
    x_data = np.zeros_like(t_data)
    throttle_data = np.zeros_like(t_data)
    alpha_data = np.zeros_like(t_data)
    # reset the states
    model.reset()
    
    # ==================================
    #  Learner solution begins here
    # ==================================
    # throttle profile
    for i in range(499):
    throttle_data[i] = (0.06*sample_time*i) + 0.2
    
    throttle_data[500:1499] = 0.5
    
    for i in range(1500,1999):
    throttle_data[i] = 2 - (0.1*sample_time*i)
    
    # incline angle profile (in radians)
    alpha_data[0:499] = np.arctan(3/60)
    alpha_data[500:1499] = np.arctan(9/90)
    alpha_data[1500:1999] = 0
    
    for i in range(t_data.shape[0]):
    x_data[i] = model.x
    model.step(throttle_data[i], alpha_data[i])
    # ==================================
    #  Learner solution ends here
    # ==================================
    
    # Plot x vs t for visualization
    plt.plot(t_data, x_data)
    plt.show()
    

    and this is the correct code :

    time_end = 20
    t_data = np.arange(0,time_end,sample_time)
    x_data = np.zeros_like(t_data)
    # reset the states
    model.reset()
    # ==================================
    # Learner solution begins here
    # ==================================
    for i in range(t_data.shape[0]):
        x_data[i] = model.x
        if t_data[i] < 5:
            throttle = (0.3/5)*t_data[i] + 0.2
        else:
            if t_data[i] < 15:
                throttle = 0.5
            else:
                throttle = (-0.5/5)*t_data[i] + 2
        if x_data[i] < 60:
            alpha = 0.0499583957
        else:
            if x_data[i] < 150:
                alpha = 0.0996686525
            else:
                alpha = 0 
    model.step(throttle, alpha)
    # ==================================
    # Learner solution ends here
    # ==================================
    # Plot x vs t for visualization
    plt.plot(t_data , x_data) 
    plt.show()