예제 #1
0
def exercise2a():
    """ Exercise 2a
    The goal of this exercise is to understand the relationship
    between muscle length and tension.
    Here you will re-create the isometric muscle contraction experiment.
    To do so, you will have to keep the muscle at a constant length and
    observe the force while stimulating the muscle at a constant activation."""
    # Defination of muscles
    parameters = MuscleParameters()
    biolog.warning("Loading default muscle parameters")
    biolog.info(parameters.showParameters())

    # Create muscle object
    muscle = Muscle.Muscle(parameters)
    muscle.l_opt = 0.11
    activation = 0.05
    stretch=np.arange(-0.09, 0.09, 0.001)
    res = isometric_contraction(muscle, stretch, activation)
    plt.title('Force-Length when activation is %s' %activation)
    plt.title('Force-Length when Lopt is %s' %muscle.l_opt)
    plt.ylim(0,1.7*max(res[1]))
#    plt.ylim(0,2500)
    plt.plot(res[0],res[1])
    plt.plot(res[0],res[2])
    plt.plot(res[0],res[2]+res[1])
    plt.legend(['active force','passive force','total force'])
    plt.xlabel('Length(m)')
    plt.ylabel('Force(N)')
    plt.grid()
    plt.show()
    
    """ Example for plotting graphs using matplotlib. """
예제 #2
0
 def mass(self, value):
     """Keyword Arguments:
        value --  Set the value of pendulum's mass [kg] """
     self.parameters['mass'] = value
     self.setInertia()
     biolog.info('Changed pendulum mass to {} [kg]'.format(
         self.parameters['mass']))
예제 #3
0
def calc(a, b, op='add'):
    if op == 'add':
        return a + b
    elif op == 'sub':
        return a - b
    else:
        biolog.info('valid operations are add and sub')
예제 #4
0
 def L(self, value):
     """ Keyword Arguments:
     value -- Set the value of pendulum's length [m] """
     self.parameters['L'] = value
     self.setInertia()
     biolog.info('Changed pendulum length to {} [m]'.format(
         self.parameters['L']))
예제 #5
0
def exercise_compile(master_file, **kwargs):
    """ Compile exercise master file

    Kwargs:
    - folder_s: Statement output folder
    - folder_c: Corrections output folder
    """
    master_name, master_extension = master_file.split(".")
    statement_file = "{}/{}{}.{}".format(
        kwargs.pop("folder_s", "Statement/Python"),
        master_name,
        kwargs.pop("end_s", ""),
        master_extension
    )
    corrections_file = "{}/{}{}.{}".format(
        kwargs.pop("folder_c", "Corrections/Python"),
        master_name,
        kwargs.pop("end_c", ""),
        master_extension
    )
    for filename, symbol_insert, symbol_remove in [
            [statement_file, SYM_STAT, SYM_CORR],
            [corrections_file, SYM_CORR, SYM_STAT]
    ]:
        biolog.info("Compiling {}".format(filename))
        check_and_create_dir(filename)
        _compile(master_file, filename, symbol_insert, symbol_remove)
    return
예제 #6
0
def main():
    """Main function that runs all the exercises."""
    biolog.info('Implementing Lab 5 : Exercise 3')
    exercise3()
    biolog.info('Implementing Lab 5 : Exercise 4')
    exercise4()
    return
예제 #7
0
 def s_theta_ref2(self, value):
     """ Keyword Arguments:
     value -- Set the value of spring 2 reference angle [rad] """
     self.parameters['s_theta_ref2'] = value
     biolog.info(
         'Changed spring 2 reference angle to {} [rad]'.format(
             self.parameters['s_theta_ref2']))
예제 #8
0
def ode_integrate_rk(fun_rk, x0, time_max, time_step):
    """ Integrate function using Euler method

    - fun: Function df/dt = f(x, t) to integrate
    - x0: Initial state
    - time_tot: Total time to simulate [s]
    - time_step: Time step [s]

    For Runge-Kutta, use:
    solver = ode(fun)
    solver.set_integrator('dopri5')
    solver.set_initial_value(x0, time[0])
    xi = solver.integrate(ti)

    Note that solver.integrate(ti) only integrates for one time step at time ti
    (where ti is the current time), so you will need to use a for loop

    Make sure to use the Result class similarly to the example_integrate
    found above (i.e. Result(x, time))
    """
    time = np.arange(0, time_max, time_step)
    x = np.zeros([len(time), len(x0)])
    x[0] = float(x0)
    solver = ode(fun_rk)
    solver.set_integrator('dopri5')
    solver.set_initial_value(x0, time[0])
    for i, ti in enumerate(
            time[:]):  # time[:] = copy of the array time, with all elements
        x[i] = solver.integrate(ti)
    biolog.info("ODE integration with RK implemented")
    return Result(x, time)
예제 #9
0
def main():
    """Main function that runs all the exercises."""
    biolog.info('Implementing Lab 4 : Exercise 1')
    exercise1()
    biolog.info('Implementing Lab 4 : Exercise 2')
    exercise2()
    return
예제 #10
0
 def __init__(self, **kwargs):
     super(PendulumParameters, self).__init__()
     self.g = kwargs.pop("g", 9.81)  # Gravity constant
     self.L = kwargs.pop("L", 1.)  # Length
     self.d = kwargs.pop("d", 0.3)  # damping origin = 0.3
     self.sin = kwargs.pop("sin", np.sin)  # Sine function
     self.dry = kwargs.pop("dry", True)  # Use dry friction (True or False)
     biolog.info(self)
     return
예제 #11
0
def exercise2b():
    """ Exercise 2b
    Under isotonic conditions external load is kept constant.
    A constant stimulation is applied and then suddenly the muscle
    is allowed contract. The instantaneous velocity at which the muscle
    contracts is of our interest"""

    # Definition of muscles
    muscle_parameters = MuscleParameters()
    print(muscle_parameters.showParameters())

    mass_parameters = MassParameters()
    print(mass_parameters.showParameters())

    # Create muscle object
    muscle = Muscle.Muscle(muscle_parameters)

    # Point 2d. Different load values.
    biolog.info("Calling for point 2d")
    isoK = isotonic_contraction(muscle)
    lineV = np.arange(-1, 2500, 1)
    zerV = np.zeros(np.size(lineV))
    plt.figure("Plot of Force vs Velocity")
    plt.plot(isoK[0], isoK[1])
    plt.title("Tension vs Normalised Velocity", fontsize=18)
    plt.plot(zerV, lineV, linestyle=':', color='red')
    plt.xlabel('Normalised Velocity [-]')
    plt.ylabel('Total Force of the Muscle [N]')
    plt.legend(['Force/Velocity [N]'])
    plt.minorticks_on()
    plt.grid(which='major', linestyle='-', linewidth='0.5', color='black')
    plt.grid(which='minor', linestyle=':', linewidth='0.5', color='black')
    save_figure('velociplot')
    #    plt.plot(isoK[0], isoK[1], 'o', markersize = 5)

    # Point 2f. Different muscle activation values.
    activations = np.arange(0.5, 1.05, 0.05)
    plt.figure(
        'Muscle Force vs Normalised velocity for varying activation time')
    legend2 = list()
    #print(activations)
    for i, a in enumerate(activations):
        muscle1 = Muscle.Muscle(muscle_parameters)
        #print("Activation = {} [s]".format(a))
        iso = isotonic_contraction(muscle1, activation=a)
        #print("lapin \n {}".format(iso[2]))
        legend2.append("Activation = {} [-]".format(a))
        plt.plot(iso[0], iso[1])  # plot for active force
    plt.xlabel('Normalised Velocity [-]')
    plt.ylabel('Total Force [N]')
    plt.plot(zerV, lineV, linestyle=':', color='red')
    plt.legend(legend2)
    plt.grid()
    plt.minorticks_on()
    plt.grid(which='major', linestyle='-', linewidth='0.5', color='black')
    plt.grid(which='minor', linestyle=':', linewidth='0.5', color='black')
    save_figure('F_vs_Vel_Activations')
예제 #12
0
 def k2(self, value):
     """ Keyword Arguments:
     value -- Set the value of spring constant for spring 2[N/rad] """
     if (value < 0.0):
         biolog.warning('Setting bad spring constant. Should be positive!')
     else:
         self.parameters['k2'] = value
     biolog.info(
         'Changed spring constant of spring 1 to {} [N/rad]'.format(self.parameters['k2']))
예제 #13
0
 def b2(self, value):
     """ Keyword Arguments:
     value -- Set the value of damping constant for damper 2. [N-s/rad] """
     if (value < 0.0):
         biolog.warning('Setting bad damping values. Should be positive!')
     else:
         self.parameters['b2'] = value
     biolog.info(
         'Changed damping constant for damper 2 to {} [N-s/rad]'.format(self.parameters['b2']))
def isometric_contraction():
    iso_sys = MusculoSkeletalSystem(
        '../../../musculo_skeletal_generator/conf/muscles.yaml')

    #: Initialize network parameters
    #: pylint: disable=invalid-name
    dt = 1  #: Time step
    _time = np.arange(0, 100, dt)  #: Time

    #: Vector to store results
    res = np.empty([len(_time), len(iso_sys.muscle_sys.dae.x)])
    res_deep = np.empty([len(_time), len(iso_sys.muscle_sys.dae.z)])

    muscle_stretch = np.concatenate(
        (np.linspace(0.0, -0.05, 25), np.linspace(-0.1, 0.05, 50)))

    length = np.empty(np.shape(muscle_stretch))
    force = np.empty(np.shape(muscle_stretch))
    active_force = np.empty(np.shape(muscle_stretch))
    passive_force = np.empty(np.shape(muscle_stretch))
    start_time = time.time()

    #: Integrate the network
    muscle_act = {'m1': 0.75}
    for idxx, stretch in enumerate(muscle_stretch):
        iso_sys.muscle_sys.dae.p[0] = stretch
        for idx, _ in enumerate(_time):
            iso_sys.step(muscle_act)
            res[idx] = iso_sys.state['muscles']['xf'].full()[:, 0]
            res_deep[idx] = iso_sys.state['muscles']['zf'].full()[:, 0]
        length[idxx] = res[-1, 0]
        force[idxx] = res_deep[-1, 0]
        active_force[idxx] = res_deep[-1, 1]
        passive_force[idxx] = res_deep[-1, 2]
    l_opt = iso_sys.muscle_sys.muscles['m1'].l_opt.val
    f_max = iso_sys.muscle_sys.muscles['m1'].f_max.val

    end_time = time.time()

    biolog.info('Execution Time : {}'.format(end_time - start_time))

    # Plotting
    plt.figure('2a Force-Length')
    plt.plot(length / l_opt, force)
    plt.plot(length / l_opt, active_force)
    plt.plot(length / l_opt, passive_force)
    plt.plot(np.ones((25, 1)), np.linspace(0., f_max, 25), '--')
    plt.text(0.6, 600, 'Below \n optimal \n length', fontsize=14)
    plt.text(1.1, 600, 'Above \n optimal \n length', fontsize=14)
    plt.title('Force-Length Relationship')
    plt.xlabel('Muscle CE Length')
    plt.ylabel('Muscle Force')
    plt.legend(('Force', 'Active Force', 'Passive Force'), loc=2)
    plt.grid()
    plt.show()
예제 #15
0
def plot_integration_methods(**kwargs):
    """ Plot integration methods results """
    biolog.info("Plotting integration results")

    # Results
    analytical = kwargs.pop("analytical", None)
    euler = kwargs.pop("euler", None)
    ode = kwargs.pop("ode", None)
    ode_rk = kwargs.pop("ode_rk", None)
    euler_ts_small = kwargs.pop("euler_ts_small", None)

    # Figures
    fig_all = kwargs.pop("figure", "Integration methods".replace(" ", "_"))
    fig_ts = "Integration methods smaller ts".replace(" ", "_")
    fig_euler = "Euler integration".replace(" ", "_")
    d = "."

    # Time steps information
    et_val = kwargs.pop("euler_timestep", None)
    ets_val = kwargs.pop("euler_timestep_small", None)
    et = " (ts={})".format(et_val) if et_val is not None else ""
    ets = " (ts={})".format(ets_val) if ets_val is not None else ""

    # Analytical
    if analytical is not None:
        analytical.plot_state(figure=fig_euler, label="Analytical", marker=d)

    # Euler
    if euler is not None:
        euler.plot_state(figure=fig_euler, label="Euler" + et, marker=d)

    # ODE
    ls = " "
    ode_plot = False
    if ode is not None:
        if ode_plot is False:
            analytical.plot_state(figure=fig_all, label="Analytical", marker=d)
            euler.plot_state(figure=fig_all, label="Euler" + et, marker=d)
            ode_plot = True
        ode.plot_state(figure=fig_all, label="LSODA", linestyle=ls, marker="x")

    # ODE Runge-Kutta
    if ode_rk is not None:
        if ode_plot is False:
            analytical.plot_state(figure=fig_all, label="Analytical", marker=d)
            euler.plot_state(figure=fig_all, label="Euler" + et, marker=d)
        ode_rk.plot_state(figure=fig_all, label="RK", linestyle=ls, marker=d)

    # Euler with lower time step
    if euler_ts_small is not None:
        euler_ts_small.plot_state(figure=fig_ts, label="Euler" + ets)
        analytical.plot_state(figure=fig_ts, label="Analytical", marker=d)

    return
예제 #16
0
def isometric_contraction(
    muscle,
    stretch=np.arange(-0.05, 0.05, 0.001),  # !!! stretch is in percent!
    activation=0.25):  # activation original = 0.05
    """ This function implements the isometric contraction
    of the muscle.

    Parameters:
    -----------
        muscle : <Muscle>
            Instance of Muscle class
        stretch : list/array
            A list/array of muscle stretches to be evaluated
        activation : float
            Muscle activation

    Returns:
    -------
    """
    stretch = np.array(stretch)

    biolog.warning('Exercise 2b isotonic contraction to be implemented')

    # Time settings
    t_start = 0.0  # Start time
    t_stop = 0.25  # Stop time
    dt = 0.0001  # Time step
    timesteps = np.arange(t_start, t_stop, dt)  # Useless??
    # Empty vectors for further isometric representations
    Fp = np.zeros(np.size(stretch))  # passive force
    Fa = np.zeros(np.size(stretch))  # active force
    F = np.zeros(np.size(stretch))  # total force
    totLen = np.zeros(np.size(
        stretch))  # total length of the CONTRACTILE ELEMENT (l_CE + stretch)
    stabs = np.zeros(np.size(timesteps))

    biolog.info("Muscle Isometric implemented")
    for i, s in enumerate(stretch):
        for j, t in enumerate(timesteps):
            effect = muscle_integrate(muscle, s, activation, dt)
            stabs[j] = effect['activeForce']


#        effect=muscle_integrate(muscle, s, activation, dt)
#        effect=muscle_integrate(muscle, s, activation, dt)
        Fp[i] = effect['passiveForce']
        Fa[i] = effect['activeForce']
        F[i] = effect['force']
        totLen[i] = effect['l_CE'] + s * effect['l_CE']
        #print("Length of the contractile element is: {} \n and its TOTAL length+stretch is: {}".format(effect['l_CE'],totLen[i]))
        #print("LIMIT: {} \n {}".format(muscle.l_MTC-muscle.l_CE, muscle.l_slack))
    c = np.array([totLen, Fp, Fa, F, timesteps, stabs])
    #print(c)
    return c
예제 #17
0
def fixed_point(A):
    """ Compute fixed point """
    x = sympy.symbols(
        ["x{}".format(i) for i in range(2)]
    )  # used to denominate the x = (x,y) vector just as follow: x = (x[0], x[1])
    sol = sympy.solve(
        np.dot(A, x), x
    )  # Use solve() to solve algebraic equations. We suppose all equations are equaled to 0, so solving x**2 == 1 translates into the following code: solve(x**2 - 1, x)
    x0 = sol[x[0]], sol[x[1]]
    biolog.info("Fixed point: {}".format(x0))
    biolog.info("x is = to: {}".format(x0))
    return
예제 #18
0
def euler_integrate(fun, x0, time_max, time_step):
    """ Integrate function using Euler method

    - fun: Function df/dt = f(x, t) to integrate
    - x0: Initial state
    - time_tot: Total time to simulate [s]
    - time_step: Time step [s]

    For loop in Python:

    >>> a = [0, 0, 0]  # Same as [0 for _ in range(3)] (List comprehension)
    >>> for i in range(3):
    ...     a[i] = i
    >>> print(a)
    [0, 1, 2]

    Creating a matrix of zeros in python:

    >>> state = np.zeros([3, 2])
    >>> print(state)
    [[0. 0.]
     [0. 0.]
     [0. 0.]]

    For loop for a state in python

    >>> state = np.zeros([3, 2])
    >>> state[0, 0], state[0, 1] = 1, 2
    >>> for i, time in enumerate([0, 0.1, 0.2]):
    ...     state[i, 0] += time
    ...     state[i, 1] -= time
    >>> print(state)
    [[ 1.   2. ]
     [ 0.1 -0.1]
     [ 0.2 -0.2]]

    Make sure to use the Result class similarly to the example_integrate
    found above (i.e. Result(x, time))
    """
    time = np.arange(0, time_max, time_step)
    x = np.zeros([len(time), len(x0)])
    x[0] = float(x0)
    for i, ti in enumerate(
            time[:-1]
    ):  # time[:-1] = copy of array "time", w/o the last element
        x[i + 1] = x[i] + 2. * (5. - x[i]) * (time_step)
        # biolog.info(ti)
    biolog.info("Euler integration implemented")
    return Result(x, time)
예제 #19
0
    def initialize_musculoskeletal_system(self,config_file = '../../../modeling/configFiles/human-config.yaml'):
        """
        Initialize musculoskeletalsystem.
        """
        biolog.info('Initializing musculoskeletalsystem')
        dt = 0.001
        opts = {'tf': dt,
                'jit': False,
                "enable_jacobian": True,
                "print_time": False,
                "print_stats": False,
                "reltol": 1e-6,
                "abstol": 1e-6} 

        musculo_sys = MusculoSkeletalSystem(config_file, opts=opts)
        return musculo_sys
예제 #20
0
    def add_pendulum_system(self, system):
        """Add the pendulum system.

        Parameters
        ----------
        system: Pendulum
            Pendulum system
        """
        if self.systems_list.count('pendulum') == 1:
            biolog.warning(
                'You have already added the pendulum model to the system.')
            return
        else:
            biolog.info('Added pedulum model to the system')
            self.systems_list.append('pendulum')
            self.pendulum_sys = system
예제 #21
0
    def add_neural_system(self, system):
        """Add the neural network system.

        Parameters
        ----------
        system: NeuralSystem
            Neural Network system
        """
        if self.systems_list.count('neural') == 1:
            biolog.warning(
                'You have already added the neural model to the system.')
            return
        else:
            biolog.info('Added neural network to the system')
            self.systems_list.append('neural')
            self.neural_sys = system
예제 #22
0
    def add_muscle_system(self, system):
        """Add the muscle system.

        Parameters
        ----------
        system: MuscleSystem
            Muscle system
        """
        if self.systems_list.count('muscle') == 1:
            biolog.warning(
                'You have already added the muscle model to the system.')
            return
        else:
            biolog.info('Added muscle model to the system')
            self.systems_list.append('muscle')
            self.muscle_sys = system
예제 #23
0
def analytic_function(t):
    """ Analytic funtion x(t) (To be written)

    Notes:
    - To write exponential(x) in Python with numpy: np.exp(x)
    Example:
    >>> np.exp(0.0)
    1.0

    This function should simply return the state with same shape as input t
    (i.e. as a list or an areray)
    """
    # COMPLETE CODE
    import biolog
    biolog.info("Analytical function implemented")
    return 5-4*(np.exp(-2*t)) # the point . is to cast floats
예제 #24
0
def error(errors, n=0):
    """ Compute and return error

    This function should receive a vector of errors of same size as the time
    vector in the integration. It should return a single value based on these
    errors.

    The variable n can be optionally be used to implement different errors and
    compare them.

    """
    # COMPLETE CODE
    biolog.info("Error computation code completed")
    mean_Err = np.abs(np.mean(errors))
    print(mean_Err)
    return mean_Err
예제 #25
0
def hopf_ocillator():
    """ 4a - Hopf oscillator simulation """
    biolog.info("Hopf oscillator implemented")
    params = HopfParameters(mu=1., omega=1.0)
    time = np.arange(0, 30, 0.01)
    title = "Hopf oscillator {} (x0={})"
    label = ["x0", "x1"]
    x0_list = [[1e-3, 1e-3], [1.0,
                              1.0]]  # x0 = x -direction, x-1 = y-direction
    for x0 in x0_list:
        hopf = integrate(hopf_equation, x0, time, args=(params, ))
        hopf.plot_state(title.format("state", x0), label)
    hopf_multiple = integrate_multiple(  # to display different graphs on the same plot
        hopf_equation,
        x0_list,
        time,
        args=(params, ))
    hopf_multiple.plot_phase(title.format("phase", x0_list), label=label)
    return
예제 #26
0
def exercise1b():
    """ Exercise 1  """
    biolog.info("Executing Lab 4 : Exercise 1")
    parameters = PendulumParameters()
    ### With damping
    t_start = 0.0
    t_stop = 10.0
    dt = 0.05

    biolog.warning("Using large time step dt={}".format(dt))
    time = np.arange(t_start, t_stop, dt)

    parameters.b1 = 0.5
    parameters.b2 = 0.5
    x0 = [np.pi / 3, 0]
    biolog.info(parameters.showParameters())
    res = integrate(pendulum_integration, x0, time, args=(parameters, ))

    res.plot_state("State")
예제 #27
0
def ode_integrate(fun, x0, time_max, time_step):
    """ Integrate function using Euler method

    - fun: Function df/dt = f(x, t) to integrate
    - x0: Initial state
    - time_tot: Total time to simulate [s]
    - time_step: Time step [s]

    Use odeint from the scipy library for integration

    Make sure to then use the Result class similarly to the example_integrate
    found above (i.e. Result(x, time))
    """
    time = np.arange(0, time_max, time_step)
    x = np.zeros([len(time), len(x0)])
    x[0] = float(x0)
    x = odeint(fun, x0, time)
    biolog.info("ODE integration implemented")
    return Result(x, time)
예제 #28
0
    def show_system_properties(self):
        """Function prints the system properties in the system.
        """

        for sys in self.systems_list:
            if (sys == 'pendulum'):
                biolog.info(self.pendulum_sys.parameters.showParameters())
            elif (sys == 'muscle'):
                biolog.info(
                    self.muscle_sys.Muscle1.parameters.showParameters())
                biolog.info(
                    self.muscle_sys.Muscle2.parameters.showParameters())
            elif (sys == 'neural'):
                biolog.info(self.neural_sys.parameters.showParameters())
예제 #29
0
    def __init__(self, **kwargs):
        super(PendulumParameters, self).__init__('Pendulum')

        self.parameters = {}
        self.units = {}

        self.units['g'] = 'N-m/s2'
        self.units['L'] = 'm'
        self.units['sin'] = ''
        self.units['k1'] = 'N/rad'
        self.units['k2'] = 'N/rad'
        self.units['s_theta_ref1'] = 'rad'
        self.units['s_theta_ref2'] = 'rad'
        self.units['b1'] = 'N-s/rad'
        self.units['b2'] = 'N-s/rad'

        # Pendulum parameters
        self.parameters['g'] = kwargs.pop("g", 9.81)  # Gravity constant
        self.parameters['L'] = kwargs.pop("L", 1.)  # Length
        self.parameters['sin'] = kwargs.pop("sin", np.sin)  # Sine function
        # Spring parameters
        self.parameters['k1'] = kwargs.pop(
            "k1", 500.)  # Spring constant of Spring 1
        self.parameters['k2'] = kwargs.pop(
            "k2", 500.)  # Spring constant of Spring 2
        self.parameters['s_theta_ref1'] = kwargs.pop(
            "s_theta_ref1", 0.0)  # Spring 1 reference angle
        self.parameters['s_theta_ref2'] = kwargs.pop(
            "s_theta_ref2", 0.0)  # Spring 2 reference angle
        # Damping parameters
        self.parameters['b1'] = kwargs.pop(
            "b1", 50.0)  # Damping constant of Damper 1
        self.parameters['b2'] = kwargs.pop(
            "b2", 5.0)  # Damping constant of Damper 2

        biolog.info(self)
        return
예제 #30
0
def exercise3():
    """ Exercise 3 """
    parameters = PendulumParameters()  # Checkout pendulum.py for more info
    biolog.info(parameters)
    # Simulation parameters
    time = np.arange(0, 30, 0.01)  # Simulation time
    x0 = [0.1, 0.0]  # Initial state

    # To use/modify pendulum parameters (See PendulumParameters documentation):
    # parameters.g = 9.81  # Gravity constant
    # parameters.L = 1.  # Length
    # parameters.d = 0.3  # damping
    # parameters.sin = np.sin  # Sine function
    # parameters.dry = False  # Use dry friction (True or False)

    # Example of system integration (Similar to lab1)
    # (NOTE: pendulum_equation must be imlpemented first)
    biolog.debug("Running integration example")
    res = integrate(pendulum_integration, x0, time, args=(parameters, ))
    res.plot_state("State")
    res.plot_phase("Phase")

    # Evolutions
    # Write code here (You can add functions for the different cases)
    biolog.warning(
        "Evolution of pendulum in normal conditions must be implemented")
    biolog.warning("Evolution of pendulum without damping must be implemented")
    biolog.warning(
        "Evolution of pendulum with perturbations must be implemented")
    biolog.warning(
        "Evolution of pendulum with dry friction must be implemented")

    # Show plots of all results
    if DEFAULT["save_figures"] is False:
        plt.show()
    return