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);
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);