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, τ))
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)
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, τ))