{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "f96fd41d",
   "metadata": {},
   "source": [
    "# Importing a robot arm multibody model from a URDF file\n",
    "The purpose of this notebook is to\n",
    "- demonstrate the creation of a {py:class}`Karana.Dynamics.Multibody` instance for a robot arm from a URDF model file \n",
    "- show the structure of the loaded model\n",
    "- show a 3D visualization of the robot arm\n",
    "- serve as a `hello world` script for verifying a proper `kdFlex` installation\n",
    "\n",
    "Resources\n",
    "- [Other notebook examples](https://portal.karanadyn.com/docs/examples_page.html) \n",
    "- [kdFlex Documentation](https://portal.karanadyn.com/docs/index.html)\n",
    "\n",
    "**Acknowledgements**\n",
    "The Barrett WAM urdf is sourced from the public repository [barrett-ros2-pkg](https://git.barrett.com/software/barrett-ros2-pkg.git). Thank you to the authors and contributors."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5978859c",
   "metadata": {},
   "source": [
    "Import **kdFlex** Python modules objects for use later"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "dce602b8",
   "metadata": {},
   "outputs": [],
   "source": [
    "from pathlib import Path\n",
    "import atexit\n",
    "\n",
    "import Karana.Core as kc\n",
    "import Karana.Frame as kf\n",
    "import Karana.Dynamics.SOADyn_types as kdt\n",
    "import Karana.KUtils.BasicPrefab as kub\n",
    "from Karana.KUtils.Sim import Sim"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bcb35c5b",
   "metadata": {},
   "source": [
    "Build the filepath to the URDF file we will import"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "fd13f1bc",
   "metadata": {},
   "outputs": [],
   "source": [
    "resources = Path().absolute().parent / \"resources\"\n",
    "urdf_file = resources / \"wam7dof\" / \"wam7dof_hand.urdf\""
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c8b05075",
   "metadata": {},
   "source": [
    "Import the URDF file to create a BasicPrefabDS. The \"DS\" is short for \"Data Structure\". This is kdFlex's native, file-format agnostic way of specifying a multibody and associated KModels. We'll use this next to create our simulation."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "c6ce1a4a",
   "metadata": {},
   "outputs": [],
   "source": [
    "basic_prefab_ds = kub.BasicPrefabDS.fromFile(urdf_file)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4fd06632",
   "metadata": {},
   "source": [
    "Instantiate and configure the {py:class}`Karana.Dynamics.Multibody` based on the BasicPrefabDS description."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "8e99d2b9",
   "metadata": {},
   "outputs": [],
   "source": [
    "sim, prefab = Sim.fromBasicPrefabDS(basic_prefab_ds)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3c4aeea4",
   "metadata": {},
   "source": [
    "Finalize the model to get it ready for use."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "115f56a0",
   "metadata": {},
   "outputs": [],
   "source": [
    "sim.mb.ensureHealthy()\n",
    "sim.mb.resetData()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "97db71f8",
   "metadata": {},
   "source": [
    "Set up the 3D graphics."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "024e4376",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "        <div style=\"height:300px; resize:vertical; overflow: auto;\">\n",
       "          <iframe src=\"http://newton:35967\" style=\"width:100%; height:100%; border:0; display:block;\"></iframe>\n",
       "        </div>\n",
       "        "
      ],
      "text/plain": [
       "<IPython.core.display.HTML object>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "_, graphics = sim.setupGraphics(port=0)\n",
    "graphics.defaultCamera().pointCameraAt(\n",
    "    offset=[0.2, 0.5, 1.7],\n",
    "    target=[0, 0, 1],\n",
    "    up=[1, 0, 0],\n",
    ")\n",
    "del graphics"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2b90d05e",
   "metadata": {},
   "source": [
    "Display the bodies in the multibody model."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "e9ab8bad",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[WebUI] Web server is running on port 35967\n",
      "You may be able to connect in your browser at:\n",
      "\t\u001b[1mhttp://newton:35967\u001b[0m\n",
      "\n",
      "LEGEND: <body number> <body name> <parent body> <hinge type> [prescribed subhinges] <U dofs/offset> [flex dofs/offset]\n",
      "\n",
      "      Body           Parent               Hinge    Dofs          \n",
      "      ____           ______               _____    ____          \n",
      "   1. FirstLink      wam7dof_MBVROOT_    REVOLUTE  1/0           \n",
      "   2. SecondLink     FirstLink           REVOLUTE  1/1           \n",
      "   3. ThirdLink      SecondLink          REVOLUTE  1/2           \n",
      "   4. FourthLink     ThirdLink           REVOLUTE  1/3           \n",
      "   5. FifthLink      FourthLink          REVOLUTE  1/4           \n",
      "   6. SixthLink      FifthLink           REVOLUTE  1/5           \n",
      "   7. SeventhLink    SixthLink           REVOLUTE  1/6           \n",
      "   8. bhand_base     SeventhLink          LOCKED   0/7           \n",
      "   9. bhand_link11   bhand_base          REVOLUTE  1/7           \n",
      "  10. bhand_link12   bhand_link11        REVOLUTE  1/8           \n",
      "  11. bhand_link13   bhand_link12        REVOLUTE  1/9           \n",
      "  12. bhand_link21   bhand_base          REVOLUTE  1/10          \n",
      "  13. bhand_link22   bhand_link21        REVOLUTE  1/11          \n",
      "  14. bhand_link23   bhand_link22        REVOLUTE  1/12          \n",
      "  15. bhand_link32   bhand_base          REVOLUTE  1/13          \n",
      "  16. bhand_link33   bhand_link32        REVOLUTE  1/14          \n",
      "                                                   ____          \n",
      "                                                   15            \n",
      "\n"
     ]
    }
   ],
   "source": [
    "sim.mb.displayModel()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "77a82391",
   "metadata": {},
   "source": [
    "Display the topological structure of the multibody system"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "e88214b0",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " Nodes\n",
      " ---\n",
      "LEGEND: [<hinge type[/dofs]> <prescribed subhinges>] <body name>[/num embedded bodies > 0] <flex dofs > 0>\n",
      "|-wam7dof_MBVROOT_\n",
      "   |-[REVOLUTE] FirstLink\n",
      "      |-[REVOLUTE] SecondLink\n",
      "         |-[REVOLUTE] ThirdLink\n",
      "            |-[REVOLUTE] FourthLink\n",
      "               |-[REVOLUTE] FifthLink\n",
      "                  |-[REVOLUTE] SixthLink\n",
      "                     |-[REVOLUTE] SeventhLink\n",
      "                        |-[LOCKED] bhand_base\n",
      "                           |-[REVOLUTE] bhand_link11\n",
      "                              |-[REVOLUTE] bhand_link12\n",
      "                                 |-[REVOLUTE] bhand_link13\n",
      "                           |-[REVOLUTE] bhand_link21\n",
      "                              |-[REVOLUTE] bhand_link22\n",
      "                                 |-[REVOLUTE] bhand_link23\n",
      "                           |-[REVOLUTE] bhand_link32\n",
      "                              |-[REVOLUTE] bhand_link33\n",
      "\n"
     ]
    }
   ],
   "source": [
    "sim.mb.dumpTree()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "df73d006",
   "metadata": {},
   "source": [
    "Animate the graphics by articulating the individual joints."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "8f575fb9",
   "metadata": {},
   "outputs": [],
   "source": [
    "sim.mb.articulateBodies()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0ec19236",
   "metadata": {},
   "source": [
    "Cleanup"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "136c1c30",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<function __main__.cleanup()>"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def cleanup():\n",
    "    \"\"\"Cleanup the simulation.\"\"\"\n",
    "    global basic_prefab_ds, prefab, sim\n",
    "    del basic_prefab_ds, prefab, sim\n",
    "\n",
    "\n",
    "atexit.register(cleanup)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "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.12.3"
  },
  "name": "notebook.ipynb"
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
