Visualización de sistemas mecánicos

Interactividad

Dentro del ambiente de desarrollo Jupyter, tenemos la oportunidad de ejecutar código en Python entre otros lenguajes; sin embargo se agregan muchas funciones especiales a Jupyter, las cuales son razon especifica para que estas prácticas esten diseñadas para este ambiente.

En este momento empezaremos a utilizar las capacidades interactivas de Jupyter, empezaremos importando la función interact y fixed de la libreria de widgets:


In [ ]:
# Se importan widgets de IPython para interactuar con la funcion
from ipywidgets import interact, fixed
# Si la linea anterior no funciona, se puede quitar el comentario a la siguiente linea
#from IPython.html.widgets import interact, fixed

In [ ]:
# Se define la constante τ, la cual representa la cantidad de radianes
# en una vuelta completa
from numpy import pi
τ = 2*pi

Vamos a definir una función como ejemplo, si la definimos y la usamos, obtendremos el resultado esperado:


In [ ]:
f = lambda x: x**2 + 5

In [ ]:
f(1)

Sin embargo es muy aburrido ¿Que pasa si queremos sondear la función por valores interesantes?

La sintaxis de la función interact es como sigue:

interact(funcion, valores_a_variar)

asi pues, empezando conla función podemos hacer lo siguiente:


In [ ]:
i1 = interact(f, x=5)

Nota que el deslizador empieza en el valor que le dimos y en el punto medio. Ademas, si solo le damos valores enteros, el programa va a suponer que no nos interesan los valores flotantes.

Para dar un rango de valores que queremos revisar, los damos en forma de tupla:

(valor_1, valor_2)

In [ ]:
i2 = interact(f, x=(0, τ))

Ejercicio

Utiliza la función interact para descubrir el valor aproximado, entre $0$ y $2$, en el que la función $g(x) = 3x^3 + x^2 - 2x + 5$ cruza por $0$.


In [ ]:
# YOUR CODE HERE
raise NotImplementedError()
i3 = interact(g, x=(0.0, 2.0))

In [ ]:
from nose.tools import assert_almost_equal
assert_almost_equal(i3.widget.result, 0, 0)

Interactividad de gráficas

Muy bien, empecemos con el ejemplo del pendulo doble, lo primero que hacemos es importar la libreria de graficación:


In [ ]:
%matplotlib inline
from matplotlib.pyplot import figure, plot, style
from mpl_toolkits.mplot3d import Axes3D
style.use("ggplot")

En este caso voy a utilizar una rotación alrededor de $z$ y una traslación en el eje $x$, asi que defino estas funciones:


In [ ]:
def r_z(θ):
    # Se importan funciones necesarias de la libreria numpy
    from numpy import matrix, sin, cos
    # Se calcula la matriz de transformación a devolver
    A = matrix([[cos(θ), -sin(θ), 0, 0],
                [sin(θ), cos(θ), 0, 0],
                [0, 0, 1, 0],
                [0, 0, 0, 1]])
    return A

def t_x(x):
    # Se importan funciones necesarias de la libreria numpy
    from numpy import matrix, sin, cos
    # Se calcula la matriz de transformación a devolver
    A = matrix([[1, 0, 0, x],
                [0, 1, 0, 0],
                [0, 0, 1, 0],
                [0, 0, 0, 1]])
    
    return A

Y voy a escribir una función robot, la cual va a tomar como argumentos mis variables, es decir los grados de libertad, y con estos valores calcular las transformaciones necesarias para obtener las posiciones de cada articulación y del actuador final. Una vez que tengo todas las posiciones, tan solo tengo que graficarlas para poder manipular esta grafica:


In [ ]:
def robot(q1=0, q2=0):
    '''
    Esta función calcula y grafica la cinemática directa de un manipulador planar rotacional
    de dos grados de libertad (pendulo doble).
    
    Necesita que la libreria matplotlib sea inicializada, al menos importando la función figure.
    '''
    # Se importan funciones necesarias de la libreria numpy
    from numpy import matrix, sin, cos
    
    # Se definen constantes
    l1 = 1
    l2 = 1
    
    # Se define el punto origen
    o0 = matrix([[0], [0], [0], [1]])
    
    # Se calculas las trasnformaciones H1 y H2
    H1 = r_z(q1)*t_x(l1)
    H2 = r_z(q2)*t_x(l2)
    
    # Se calcula la cinematica directa
    o1 = H1*o0
    o2 = H1*H2*o0
    
    # Define arreglos con las coordenadas x, y, y z de cada punto
    xs = [o0.item(0), o1.item(0), o2.item(0)]
    ys = [o0.item(1), o1.item(1), o2.item(1)]
    zs = [o0.item(2), o1.item(2), o2.item(2)]
    
    # Define el cuadro general en donde se diuja la gráfica
    f1 = figure(figsize=(8, 8))
    # Agrega el area para graficar a nuestra figura, y la define como un espacio tridimensional
    a1 = f1.add_subplot(111, projection='3d')

    # Utiliza los datos en xs, ys y zs para graficar una linea con bolitas en cada extremo
    a1.plot(xs, ys, zs, "-o")
    
    # Define los limites de la grafica en cada eje
    a1.set_xlim(-2.1, 2.1)
    a1.set_ylim(-2.1, 2.1)
    a1.set_zlim(-0.1, 1.1);

En este caso utilizo los rangos de valores (0, τ) ya que es toda la vuelta completa.


In [ ]:
interact(robot, q1=(0, τ), q2=(0, τ))