Example #1
0
 def __init__(self, param, captive_dt=0.5):
     # Setup force model
     self.param = param
     self.force_model = ForceModel(param)
     self.drag_func = self.force_model.get_square_model()
     # Initialize External force function
     self.force_func = zero_force_func
     # Time step of realtime system integrating the measured forces
     self.captive_dt = captive_dt
Example #2
0
def get_time_const(v0, param):
    """
    Calculates the systems time constant as a function of the operating
    velocity. 
    """
    # Setup force model and predict gain and phase
    force_model = ForceModel(param)
    m = param.sub_body_mass + param.sub_mount_mass
    dummy, b = force_model.get_linear_coef(v0)
    return m / b
Example #3
0
 def __init__(self, param, inertial_dt=0.1, pgain=5.0):
     # Setup force model
     self.param = param
     self.force_model = ForceModel(param)
     self.drag_func = self.force_model.get_square_model()
     # Initialize External force function
     self.force_func = zero_force_func
     # Time step of realtime system integrating the measured forces
     self.inertial_dt = inertial_dt
     self.pgain = pgain
Example #4
0
    # --------------------------------------------------------------------------
    # Part 1 Compute example bode plots for system frequency response as a
    # function of the operatiing point. Based on linearized force model.
    # --------------------------------------------------------------------------

    # Test frequency range - f0 must be low enough that there is no phase shift
    f0 = 0.001
    f1 = 10.0

    # Test velocities
    num_test_v0 = 2
    min_vel, max_vel = param.sub_velocity_range
    test_v0 = scipy.linspace(0.05 * max_vel, max_vel, num_test_v0)

    # Setup force model and predict gain and phase
    force_model = ForceModel(param)
    m = param.sub_body_mass + param.sub_mount_mass

    for i, v0 in enumerate(test_v0):

        # Compute the frequency response of the system
        dummy, b = force_model.get_linear_coef(v0)
        gain, phase, f = get_freq_response(f0, f1, m, b, n=10000)

        # Normalize gains - note, input and output don't have same units
        gain = gain - gain[0]

        # Plot results
        pylab.figure(1)
        pylab.subplot(211)
        pylab.semilogx(f, gain, label='v0 = %1.2f m/s' % (v0, ))
Example #5
0
class CaptiveTrajSim(object):
    """
    Encapsulates a simulation of a captive trajectory system modeling a
    the first order dynamics of the sled system.

    Simulates normal and captive trajectory system for comparison. System
    update_dt can be varied to determine the effect of the realtime system
    update interval.
    """
    def __init__(self, param, captive_dt=0.5):
        # Setup force model
        self.param = param
        self.force_model = ForceModel(param)
        self.drag_func = self.force_model.get_square_model()
        # Initialize External force function
        self.force_func = zero_force_func
        # Time step of realtime system integrating the measured forces
        self.captive_dt = captive_dt

    def normal_system_func(self, v, t):
        """
        Function governing normal system dynamics, i.e., f(v,t) where

        dv/dt = f(v,t).
        """
        # Get mass and damping
        m = param.sub_body_mass + param.sub_mount_mass
        # Compute function value
        val = -scipy.sign(v) * self.drag_func(v) / m + self.force_func(v,
                                                                       t) / m
        return val

    def captive_system_func(self, v, t, v_cap):
        """
        Function governing the captive trajectory system dynamics , i.e., f(v,t) where

        dv/dt = f(v,t).

        Note, In this case v is ignored and v_cap is used as the forces remain
        constant between realtime system updates. The system is simulated by
        running an odeint integration for the system evolution between every
        realtime system update.
        """
        # Get mass and damping
        m = param.sub_body_mass + param.sub_mount_mass
        # Compute function value
        val = -scipy.sign(v_cap) * self.drag_func(v_cap) / m + self.force_func(
            v_cap, t) / m
        return val

    def run_normal(self, v0, T, num=1000):
        """
        Runs a simulation of the system reponse to the external force function
        self.force_func. This is the normal system response - not the captive
        trajectory model.

        Inputs:

        v0  = initial velocity
        dt  = sample interval for output values
        T   = duration of simulation 
        """
        t = scipy.linspace(0, T, num)
        v = scipy.integrate.odeint(self.normal_system_func, v0, t)
        return t, v

    def run_captive(self, v0, T, num=100):
        """
        Run a simulation of the captive trajectory system response to the external 
        force function self.force_func. This is a prediction of the captive trajectory 
        system response. 
        v0 = 
        """
        t_curr = 0.0
        v_curr = v0
        t = []
        v = []

        while t_curr < T:

            # Integrate system forward to next realtime update
            t_next = t_curr + self.captive_dt
            if t_next > T:
                t_next = T
            t_sim = scipy.linspace(0, t_next - t_curr, num)
            v_sim = scipy.integrate.odeint(self.captive_system_func,
                                           v_curr,
                                           t_sim,
                                           args=(v_curr, ))

            # Add simulation segments to t and velcity lists
            t_sim = [val + t_curr for val in t_sim]
            t.extend(t_sim)
            v.extend(v_sim)

            # Update t_curr and v_curr
            t_curr = t_next
            v_curr = v_sim[-1]

        # Convert lists to arrays
        t = scipy.array(t)
        v = scipy.array(v)

        return t, v

    def get_verror_est(self, f0, f1, num=5):
        """
        Get velocity error estimate as a function of the captive trajectory system
        update frequency.

        Note, the force_func must be set to something reasonable for this to work.
        A step function is a good choice.
        """
        capt_f_array = scipy.linspace(f0, f1, num)
        capt_dt_array = 1.0 / capt_f_array
        verror_array = scipy.zeros(capt_dt_array.shape)

        for i, capt_dt in enumerate(capt_dt_array):

            # Run simulation for given captive trajectory update interval
            self.captive_dt = capt_dt
            v0 = 0.0
            t_norm, v_norm = self.run_normal(v0, T, num=2000)
            t_capt, v_capt = self.run_captive(v0, T, num=100)

            # Interpolate normal trajectory onto captive trajectory time base
            v_norm = scipy.reshape(v_norm, t_norm.shape)
            v_capt = scipy.reshape(v_capt, t_capt.shape)
            interp_func = scipy.interpolate.interp1d(t_norm, v_norm)
            v_norm_interp = interp_func(t_capt)

            # Compute maximum absolute velocity error
            verror = scipy.absolute((v_capt - v_norm_interp))
            verror_array[i] = verror.max()

        return capt_f_array, verror_array
           'subject_1', 'subject_2', 'subject_3', 'subject_4', 'subject_5', 'subject_6',
           'tau_1_rest+1STD', 'tau_1_rest+2STD', 'tau_1_rest+3STD',
           'tau_2-1STD', 'tau_2-2STD', 'tau_2+1STD', 'tau_2+2STD',
           'tau_fat+1STD', 'tau_fat+2STD', 'tau_fat-1STD', 'tau_fat-2STD']
SUB_FOLDER = 'sensitivity_analysis/'
CONFIG_FOLDER = 'configs/'
validated_configuration = 'model_configuration.csv'

total_time = (0 * 1000, 230 * 1000)
validation_train = get_validation_train()

config = load_model_configuration(validated_configuration)
tau_c, tau_2, tau_fat, alpha_scale_factor, alpha_Km, alpha_tau_1, \
    CN0, F0, scale_factor_rest, tau_1_rest, Km_rest = config.values()

validated_force_model = ForceModel(scale_factor_rest, Km_rest, tau_1_rest, tau_2)

validated_initial_state = [CN0, F0, scale_factor_rest, Km_rest, tau_1_rest]
V_CN, V_F, V_A, V_Km, V_tau_1, V_t = simulate(validated_force_model, total_time, validation_train,
                                              validated_initial_state, tau_c, tau_fat,
                                              alpha_scale_factor, alpha_Km, alpha_tau_1)
V_t = V_t / 1000
validated_f60_time = V_t[np.where(V_t <= 60)]
validated_f60_data = V_F[np.where(V_t <= 60)]
validated_l60_time = V_t[np.logical_and(170 <= V_t, V_t <= 230)]
validated_l60_data = V_F[np.logical_and(170 <= V_t, V_t <= 230)]

for CONFIG in CONFIGS:
    config = load_model_configuration(SUB_FOLDER + CONFIG_FOLDER + CONFIG + '.csv')
    tau_c, tau_2, tau_fat, alpha_scale_factor, alpha_Km, alpha_tau_1, \
        CN0, F0, scale_factor_rest, tau_1_rest, Km_rest = config.values()
Example #7
0
class InertialSledSim(object):
    """
    Encapsulates a simulation of the inertial sled system. A PID controller
    is used to try and keep the sled in position with the model. 
    """
    def __init__(self, param, inertial_dt=0.1, pgain=5.0):
        # Setup force model
        self.param = param
        self.force_model = ForceModel(param)
        self.drag_func = self.force_model.get_square_model()
        # Initialize External force function
        self.force_func = zero_force_func
        # Time step of realtime system integrating the measured forces
        self.inertial_dt = inertial_dt
        self.pgain = pgain

    def normal_system_func(self, w, t):
        """
        Function governing normal system dynamics. Basic second order system with
        square law fluid dynamic drag.
        """
        v = w[0]
        x = w[1]
        m = param.sub_body_mass + param.sub_mount_mass
        dvdt = -scipy.sign(v) * self.drag_func(v) / m + self.force_func(v,
                                                                        t) / m
        dxdt = v
        return scipy.array([dvdt, dxdt])

    def inertial_system_func(self, x, t, vel_setpt):
        """
        Function governing the dynamics of the sled system. We are setting sled
        velocity so this is first order in position.  Currenlty doesn't
        incorporate sled/controller dynamics assumes we can control the sleds
        velocity with reasonable accuracy. Will need to add sled + controller
        dynamics later. Currently, just integration of the velocity setput.
        """
        dx = vel_setpt
        return dx

    def run_normal(self, x0, v0, T, num=100):
        """
        Runs a simulation of the system reponse to the external force function
        self.force_func. This is the normal system response - not the captive
        trajectory model.
        """
        w0 = scipy.array([v0, x0])
        t = scipy.linspace(0, T, num)
        w = scipy.integrate.odeint(self.normal_system_func, w0, t)
        x = w[:, 1]
        v = w[:, 0]
        return t, x, v

    def run_inertial(self, x0, v0, t_sled, x_sled, v_sled, T, num=30):
        """ 
        Run a simulation of inertial sled system. Used a proportional 
        controller with feed forward velocity term.
        """
        t_sled = t_sled - t_sled[0]
        x_sled_func = scipy.interpolate.interp1d(t_sled, x_sled)
        v_sled_func = scipy.interpolate.interp1d(t_sled, v_sled)

        t_curr = 0.0
        x_curr = x0
        v_setpt = v0

        t = []
        x = []
        v = []

        while t_curr < T:

            # Update velocity set point
            x_error = x_sled_func(t_curr) - x_curr
            v_setpt = self.pgain * x_error + v_sled_func(t_curr)

            t_next = t_curr + self.inertial_dt
            if t_next > T:
                t_next = T
            t_sim = scipy.linspace(0, t_next - t_curr, num)
            x_sim = scipy.integrate.odeint(self.inertial_system_func,
                                           x_curr,
                                           t_sim,
                                           args=(v_setpt, ))

            # Add simulation segments to t and velcity lists
            N = t_sim.shape[0]
            t_sim = [val + t_curr for val in t_sim]
            t.extend(list(t_sim))
            v.extend(list(v_setpt * scipy.ones((N, ))))
            x.extend(list(x_sim))

            # Update t_curr and v_curr
            t_curr = t_next
            x_curr = x_sim[-1]

    # Convert lists to arrays
        t = scipy.array(t)
        x = scipy.array(x)
        v = scipy.array(v)
        return t, x, v

    def get_perror_est(self, f0, f1, num=5):
        """
        Computes the maximum absolute positon error over a range of realtime loop update
        frequencies form f0 to f1 with the number of step given by num.
        """
        f_array = scipy.linspace(f0, f1, num)
        dt_array = 1.0 / f_array
        perror_array = scipy.zeros(f_array.shape)

        for i, dt in enumerate(dt_array):

            print 'f: ', 1.0 / dt

            # Run simulation for given realtime loop update interval
            self.inertial_dt = dt
            x0 = 0.0
            v0 = 0.0
            t_model, x_model, v_model = self.run_normal(x0, v0, T, num=1000)
            t_sled, x_sled, v_sled = self.run_inertial(x0, v0, t_model,
                                                       x_model, v_model, T)

            # Interpolate normal trajectory onto captive trajectory time base
            x_model = scipy.reshape(x_model, t_model.shape)
            x_sled = scipy.reshape(x_sled, t_sled.shape)
            interp_func = scipy.interpolate.interp1d(t_model, x_model)
            x_model_interp = interp_func(t_sled)

            # Compute maximum absolute velocity error
            perror = scipy.absolute((x_sled - x_model_interp))
            perror_array[i] = perror.max()

        return f_array, perror_array