Matrices de Transformación

Las matrices de rotación y traslación nos sirven para transformar una coordenada entre diferentes sistemas coordenados, pero tambien lo podemos ver, como la transformación que le hace cada eslabon a nuestro punto de ubicación.

Empecemos con la rotación:

$$ R_z = \begin{pmatrix} \cos{\theta} & -\sin{\theta} & 0 & 0 \\ \sin{\theta} & \cos{\theta} & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \end{pmatrix} $$

La matriz que escribimos, girará nuestro de eje de coordenadas con respecto al eje $z$ un angulo $\theta$.

Por cierto, las funciones trigonométricas toman como argumento el angulo en radianes, por lo que tomaré la convencion de llamar a $\tau = 2 \pi$, para definir los angulos como fracciones de la vuelta completa.


In [ ]:
from math import pi, sin, cos
from numpy import matrix
from matplotlib.pyplot import figure, plot, style
from mpl_toolkits.mplot3d import Axes3D
style.use("ggplot")
%matplotlib notebook

In [ ]:
τ = 2*pi

Para empezar definiremos nuestra posición de inicio, como la coordenada:

$$ P_1 = \begin{pmatrix} 1 \\ 0 \\ 0 \end{pmatrix} $$

In [ ]:
pos_1 = matrix([[1],
                [0],
                [0],
                [1]])

Agregamos un $1$ al final, debido a que las matrices de transformación homogenea son de dimensión $\Re^{4\times 4}$ y de otra manera no concordarian las dimensiones.

De manera similar vamos a definir el punto origen, el cual nos va a permitir definir una trayectoria para dibujar nuestro vector:


In [ ]:
o = matrix([[0],
            [0],
            [0],
            [1]])

Una vez que tenemos estos puntos, juntamos los elementos de $x$, $y$ y $z$ de cada uno para poderlos graficar:


In [ ]:
xs = [o.item(0), pos_1.item(0)]
ys = [o.item(1), pos_1.item(1)]
zs = [o.item(2), pos_1.item(2)]

Ahora podemos graficar en tres dimensiones de la siguiente manera:


In [ ]:
# Define el cuadro general en donde se diuja la gráfica
f1 = figure(figsize=(6, 6))
# Agrega el area para graficar a nuestra figura
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(-0.1, 1.1)
a1.set_ylim(-0.1, 1.1)
a1.set_zlim(-0.1, 1.1);

Ejercicio

Dibuja un triangulo que tenga vertices en los puntos $p_1 = (1,1)$, $p_2 = (1,2)$ y $p_3 = (2,2)$, en el plano $xy$ (con una elevación $z=0$).


In [ ]:
fig = figure(figsize=(6, 6))
ax = fig.add_subplot(111, projection='3d')

# YOUR CODE HERE
raise NotImplementedError()
ax.set_xlim(-0.1, 2.1)
ax.set_ylim(-0.1, 2.1)
ax.set_zlim(-0.1, 1.1);

In [ ]:
from numpy.testing import assert_allclose
ls = ax.get_lines()
assert_allclose(ls[0].get_xdata(), [0,  0.02154399], rtol=1e-05, atol=1e-05)
assert_allclose(ls[1].get_xdata(), [0.02154399, 0.05997832], rtol=1e-05, atol=1e-05)
assert_allclose(ls[2].get_xdata(), [0.05997832, 0], rtol=1e-05, atol=1e-05)

Podemos definir matrices de la siguiente manera, y ver que el resultado es lo que esperariamos si quisieramos rotar el vector unitario $\hat{i}$ , con $30^o$ es decir $\frac{\tau}{12}$.


In [ ]:
rot_1 = matrix([[cos(τ/12), -sin(τ/12), 0, 0],
                [sin(τ/12), cos(τ/12), 0, 0],
                [0, 0, 1, 0],
                [0, 0, 0, 1]])

rot_1*pos_1

Pero podemos hacer algo mejor, podemos definir una función que nos devuelva una matriz de rotación, dandole como argumento el angulo de rotación.


In [ ]:
def rotacion_z(θ):
    '''
    Esta función devuelve una matriz de transformación con valores numéricos,
    correspondientes a una rotación alrededor del eje z.
    '''
    A = matrix([[cos(θ), -sin(θ), 0, 0],
                [sin(θ), cos(θ), 0, 0],
                [0, 0, 1, 0],
                [0, 0, 0, 1]])
    return A

Con lo que podemos usar esta función para crear la matriz de rotación necesaria:


In [ ]:
rot_2 = rotacion_z(τ/12)
rot_2

Entonces, tendremos el mismo resultado, con un codigo mas limpio.


In [ ]:
p = rot_2*pos_1
p

Y usamos el mismo codigo para separar las coordenadas $x$, $y$ y $z$:


In [ ]:
xs = [o.item(0), p.item(0)]
ys = [o.item(1), p.item(1)]
zs = [o.item(2), p.item(2)]

In [ ]:
f2 = figure(figsize=(8, 8))
a2 = f2.add_subplot(111, projection='3d')

a2.plot(xs, ys, zs, "-o")
a2.set_xlim(-0.1, 1.1)
a2.set_ylim(-0.1, 1.1)
a2.set_zlim(-0.1, 1.1);