Skip to content

Instantly share code, notes, and snippets.

@WesleyYue
Last active December 11, 2019 22:22
Show Gist options
  • Save WesleyYue/b268038fe5c61a3833950f4c482d1596 to your computer and use it in GitHub Desktop.
Save WesleyYue/b268038fe5c61a3833950f4c482d1596 to your computer and use it in GitHub Desktop.
29736f4fa046c111d44ada71a0b1922e
Display the source blob
Display the rendered blob
Raw
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.3"
},
"colab": {
"name": "29736f4fa046c111d44ada71a0b1922e",
"provenance": [],
"collapsed_sections": [],
"include_colab_link": true
}
},
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "view-in-github",
"colab_type": "text"
},
"source": [
"<a href=\"https://colab.research.google.com/gist/WesleyYue/b268038fe5c61a3833950f4c482d1596/notebook.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
]
},
{
"cell_type": "code",
"metadata": {
"id": "Kxj5v5rjCMc_",
"colab_type": "code",
"outputId": "ec12d5bf-5b1b-462e-9d34-b9faa5b51bb0",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 377
}
},
"source": [
"!pip install numpy pytransform3d"
],
"execution_count": 2,
"outputs": [
{
"output_type": "stream",
"text": [
"Requirement already satisfied: numpy in /usr/local/lib/python3.6/dist-packages (1.17.4)\n",
"Collecting pytransform3d\n",
" Downloading https://files.pythonhosted.org/packages/db/50/3b28c11f214eb4003c02d97ab2bc1aaa9123895c2c0058107fa29449f979/pytransform3d-1.1.1.tar.gz\n",
"Requirement already satisfied: scipy in /usr/local/lib/python3.6/dist-packages (from pytransform3d) (1.3.3)\n",
"Requirement already satisfied: matplotlib in /usr/local/lib/python3.6/dist-packages (from pytransform3d) (3.1.2)\n",
"Requirement already satisfied: lxml in /usr/local/lib/python3.6/dist-packages (from pytransform3d) (4.2.6)\n",
"Requirement already satisfied: beautifulsoup4 in /usr/local/lib/python3.6/dist-packages (from pytransform3d) (4.6.3)\n",
"Requirement already satisfied: kiwisolver>=1.0.1 in /usr/local/lib/python3.6/dist-packages (from matplotlib->pytransform3d) (1.1.0)\n",
"Requirement already satisfied: python-dateutil>=2.1 in /usr/local/lib/python3.6/dist-packages (from matplotlib->pytransform3d) (2.6.1)\n",
"Requirement already satisfied: pyparsing!=2.0.4,!=2.1.2,!=2.1.6,>=2.0.1 in /usr/local/lib/python3.6/dist-packages (from matplotlib->pytransform3d) (2.4.5)\n",
"Requirement already satisfied: cycler>=0.10 in /usr/local/lib/python3.6/dist-packages (from matplotlib->pytransform3d) (0.10.0)\n",
"Requirement already satisfied: setuptools in /usr/local/lib/python3.6/dist-packages (from kiwisolver>=1.0.1->matplotlib->pytransform3d) (42.0.2)\n",
"Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.6/dist-packages (from python-dateutil>=2.1->matplotlib->pytransform3d) (1.12.0)\n",
"Building wheels for collected packages: pytransform3d\n",
" Building wheel for pytransform3d (setup.py) ... \u001b[?25l\u001b[?25hdone\n",
" Created wheel for pytransform3d: filename=pytransform3d-1.1.1-cp36-none-any.whl size=28793 sha256=1435accc0c01c6dffa07be7e4430254417e12b4c7b34270489298c24665430ef\n",
" Stored in directory: /root/.cache/pip/wheels/1a/07/33/6e38e02d04412cc7b01dbe200bf79afa55bb5481028a10d923\n",
"Successfully built pytransform3d\n",
"Installing collected packages: pytransform3d\n",
"Successfully installed pytransform3d-1.1.1\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "73hHZMJ6BhbP",
"colab_type": "code",
"outputId": "862636bd-7c6b-4b52-cfda-e2364e9d9854",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 34
}
},
"source": [
"%pylab inline\n",
"import pytransform3d.rotations as pr"
],
"execution_count": 3,
"outputs": [
{
"output_type": "stream",
"text": [
"Populating the interactive namespace from numpy and matplotlib\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "1Xz3gCl1BhbU",
"colab_type": "code",
"colab": {}
},
"source": [
"import numpy as np\n",
"theta_A2B = 0.5 * np.pi\n",
"theta_B2A = -theta_A2B\n",
"\n",
"R = pr.matrix_from_angle(2, 0.5 * np.pi)"
],
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "1T6bdNPfBlP2",
"colab_type": "code",
"outputId": "cae9e19b-9633-47da-f9ad-626342c554cd",
"colab": {
"base_uri": "https://localhost:8080/",
"height": 136
}
},
"source": [
"import cv2\n",
"cv_R, _ = cv2.Rodrigues(np.array([0,0, theta_B2A]))\n",
"\n",
"print(R)\n",
"print(cv_R)\n",
"print(np.allclose(R, cv_R))"
],
"execution_count": 11,
"outputs": [
{
"output_type": "stream",
"text": [
"[[ 6.123234e-17 1.000000e+00 0.000000e+00]\n",
" [-1.000000e+00 6.123234e-17 0.000000e+00]\n",
" [ 0.000000e+00 0.000000e+00 1.000000e+00]]\n",
"[[ 6.123234e-17 1.000000e+00 0.000000e+00]\n",
" [-1.000000e+00 6.123234e-17 0.000000e+00]\n",
" [ 0.000000e+00 0.000000e+00 1.000000e+00]]\n",
"True\n"
],
"name": "stdout"
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "oW0ezVcaBhba",
"colab_type": "code",
"colab": {}
},
"source": [
"random_state = random.RandomState(0)\n",
"points = random_state.randn(10, 2) * 0.1 + np.array([[1, 1]])\n",
"points = np.hstack((points, np.zeros((len(points), 1))))"
],
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "Vw5JvG9mBhbd",
"colab_type": "code",
"colab": {}
},
"source": [
"def plot_coordinate_frame(ls=\"-\"):\n",
" subplot(111, aspect=\"equal\")\n",
" plot([0, 2], [0, 0], c=\"r\", ls=ls)\n",
" plot([0, 0], [0, 2], c=\"g\", ls=ls)\n",
" xlim((-2, 2))\n",
" ylim((-2, 2))\n",
" grid()"
],
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "9PbIh6kDBhbg",
"colab_type": "code",
"colab": {}
},
"source": [
"def rotate_points(R, points):\n",
" return points.dot(R.T)"
],
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "zVir1DGMBhbi",
"colab_type": "code",
"colab": {}
},
"source": [
"def plot_points(points):\n",
" scatter(points[:, 0], points[:, 1])"
],
"execution_count": 0,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "oNI_2lR2Bhbl",
"colab_type": "code",
"outputId": "d9f85880-9b7e-49b7-ec22-0b8740a0eb96",
"colab": {}
},
"source": [
"plot_coordinate_frame()\n",
"plot_points(points)\n",
"# new coordinate frame\n",
"plot([-0.05, -0.05], [0, 2], c=\"r\", ls=\"--\")\n",
"plot([-2, 0], [0.05, 0.05], c=\"g\", ls=\"--\")"
],
"execution_count": 0,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"[<matplotlib.lines.Line2D at 0x7f7145a07ac8>]"
]
},
"metadata": {
"tags": []
},
"execution_count": 65
},
{
"output_type": "display_data",
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"tags": [],
"needs_background": "light"
}
}
]
},
{
"cell_type": "code",
"metadata": {
"id": "NaCHm0W6Bhbp",
"colab_type": "code",
"outputId": "e96130bb-1a6f-4133-bf40-8d628aa47114",
"colab": {}
},
"source": [
"rotated_points = rotate_points(R, points)\n",
"plot_coordinate_frame(ls=\"--\")\n",
"plot_points(rotated_points)\n",
"# old coordinate frame\n",
"plot([0, 0], [-0.05, -2], c=\"r\")\n",
"plot([0, 2], [-0.05, -0.05], c=\"g\")"
],
"execution_count": 0,
"outputs": [
{
"output_type": "execute_result",
"data": {
"text/plain": [
"[<matplotlib.lines.Line2D at 0x7f7146316f60>]"
]
},
"metadata": {
"tags": []
},
"execution_count": 75
},
{
"output_type": "display_data",
"data": {
"image/png": "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\n",
"text/plain": [
"<Figure size 432x288 with 1 Axes>"
]
},
"metadata": {
"tags": [],
"needs_background": "light"
}
}
]
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment