{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "7ef475a3",
   "metadata": {},
   "source": [
    "# Load Mars 2020 rover model from a URDF file\n",
    "\n",
    "Requirements:\n",
    "- [Import/export](../example_import_export/notebook.ipynb)\n",
    "\n",
    "**Acknowledgements**  \n",
    "The rover model is sourced from the Jet Propulsion Laboratory, California Institute of Technology, from their public repository [nasa-jpl/m2020-urdf-models](https://github.com/nasa-jpl/m2020-urdf-models.git).  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "dce602b8",
   "metadata": {},
   "outputs": [],
   "source": [
    "import atexit\n",
    "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"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bcb35c5b",
   "metadata": {},
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "fd13f1bc",
   "metadata": {},
   "outputs": [],
   "source": [
    "resources = Path().absolute().parent / \"resources\"\n",
    "urdf_file = resources / \"m2020\" / \"m2020.urdf\""
   ]
  },
  {
   "cell_type": "markdown",
   "id": "64ddd559",
   "metadata": {},
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "c6ce1a4a",
   "metadata": {},
   "outputs": [],
   "source": [
    "basic_prefab_ds = kub.BasicPrefabDS.fromFile(urdf_file)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3698fcc7",
   "metadata": {},
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "51a4d9af",
   "metadata": {},
   "outputs": [],
   "source": [
    "frame_container = kf.FrameContainer(\"root\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "338ef48e",
   "metadata": {},
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "8e99d2b9",
   "metadata": {},
   "outputs": [],
   "source": [
    "prefab, prop = kub.BasicPrefab.createStandalone(basic_prefab_ds, frame_container)\n",
    "multibody = prop.getSubTree().multibody()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3c4aeea4",
   "metadata": {},
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "115f56a0",
   "metadata": {},
   "outputs": [],
   "source": [
    "multibody.ensureHealthy()\n",
    "multibody.resetData()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "97db71f8",
   "metadata": {},
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "024e4376",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "        <div style=\"height:300px; resize:vertical; overflow: auto;\">\n",
       "          <iframe src=\"http://newton:32773\" 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": [
    "cleanup_viz, graphics = multibody.setupGraphics(port=0)\n",
    "graphics.defaultCamera().pointCameraAt(offset=[3, 3, -2], target=[1, 0, -1], up=[0, 0, -1])"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2b90d05e",
   "metadata": {},
   "source": [
    "Display the contents of the multibody system"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "89d18db5",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[WebUI] Web server is running on port 32773\n",
      "You may be able to connect in your browser at:\n",
      "\t\u001b[1mhttp://newton:32773\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. Body_Chassis            Perseverance_MBVROOT_    FULL6DOF  6/0           \n",
      "   2. Body_MHS_DebrisShield   Body_Chassis             FULL6DOF  6/6           \n",
      "   3. Body_Differential       Body_Chassis             REVOLUTE  1/12          \n",
      "   4. Frame_DIFF              Body_Differential         LOCKED   0/13          \n",
      "   5. Body_RockerLeft         Body_Chassis             REVOLUTE  1/13          \n",
      "   6. Body_BogieLeft          Body_RockerLeft          REVOLUTE  1/14          \n",
      "   7. Body_SteerLeftRear      Body_BogieLeft           REVOLUTE  1/15          \n",
      "   8. Body_WheelLeftRear      Body_SteerLeftRear       REVOLUTE  1/16          \n",
      "   9. Frame_WHEEL_LR          Body_WheelLeftRear        LOCKED   0/17          \n",
      "  10. Frame_STEER_LR          Body_SteerLeftRear        LOCKED   0/17          \n",
      "  11. Body_WheelLeftMiddle    Body_BogieLeft           REVOLUTE  1/17          \n",
      "  12. Frame_WHEEL_LM          Body_WheelLeftMiddle      LOCKED   0/18          \n",
      "  13. Frame_BOGIE_L           Body_BogieLeft            LOCKED   0/18          \n",
      "  14. Body_SteerLeftFront     Body_RockerLeft          REVOLUTE  1/18          \n",
      "  15. Body_WheelLeftFront     Body_SteerLeftFront      REVOLUTE  1/19          \n",
      "  16. Frame_WHEEL_LF          Body_WheelLeftFront       LOCKED   0/20          \n",
      "  17. Frame_STEER_LF          Body_SteerLeftFront       LOCKED   0/20          \n",
      "  18. Frame_ROCKER_L          Body_RockerLeft           LOCKED   0/20          \n",
      "  19. Body_RockerRight        Body_Chassis             REVOLUTE  1/20          \n",
      "  20. Body_BogieRight         Body_RockerRight         REVOLUTE  1/21          \n",
      "  21. Body_SteerRightRear     Body_BogieRight          REVOLUTE  1/22          \n",
      "  22. Body_WheelRightRear     Body_SteerRightRear      REVOLUTE  1/23          \n",
      "  23. Frame_WHEEL_RR          Body_WheelRightRear       LOCKED   0/24          \n",
      "  24. Frame_STEER_RR          Body_SteerRightRear       LOCKED   0/24          \n",
      "  25. Body_WheelRightMiddle   Body_BogieRight          REVOLUTE  1/24          \n",
      "  26. Frame_WHEEL_RM          Body_WheelRightMiddle     LOCKED   0/25          \n",
      "  27. Frame_BOGIE_R           Body_BogieRight           LOCKED   0/25          \n",
      "  28. Body_SteerRightFront    Body_RockerRight         REVOLUTE  1/25          \n",
      "  29. Body_WheelRightFront    Body_SteerRightFront     REVOLUTE  1/26          \n",
      "  30. Frame_WHEEL_RF          Body_WheelRightFront      LOCKED   0/27          \n",
      "  31. Frame_STEER_RF          Body_SteerRightFront      LOCKED   0/27          \n",
      "  32. Frame_ROCKER_R          Body_RockerRight          LOCKED   0/27          \n",
      "  33. Body_RSM_AZ             Body_Chassis             REVOLUTE  1/27          \n",
      "  34. Body_RSM_EL             Body_RSM_AZ              REVOLUTE  1/28          \n",
      "  35. Frame_MEL               Body_RSM_EL               LOCKED   0/29          \n",
      "  36. Frame_SCI               Body_RSM_EL               LOCKED   0/29          \n",
      "  37. Frame_SCRMI             Body_RSM_EL               LOCKED   0/29          \n",
      "  38. Frame_SCLIBS            Body_RSM_EL               LOCKED   0/29          \n",
      "  39. Frame_SCIR              Body_RSM_EL               LOCKED   0/29          \n",
      "  40. Frame_MCL               Body_RSM_EL               LOCKED   0/29          \n",
      "  41. Frame_MCR               Body_RSM_EL               LOCKED   0/29          \n",
      "  42. Frame_NCL               Body_RSM_EL               LOCKED   0/29          \n",
      "  43. Frame_NCR               Body_RSM_EL               LOCKED   0/29          \n",
      "  44. Frame_NCL_FOV           Body_RSM_EL               LOCKED   0/29          \n",
      "  45. Frame_NCR_FOV           Body_RSM_EL               LOCKED   0/29          \n",
      "  46. Frame_MAZ               Body_RSM_AZ               LOCKED   0/29          \n",
      "  47. Body_HGA_AZ             Body_Chassis             REVOLUTE  1/29          \n",
      "  48. Body_HGA_EL             Body_HGA_AZ              REVOLUTE  1/30          \n",
      "  49. Frame_ANT               Body_HGA_EL               LOCKED   0/31          \n",
      "  50. Frame_HGAG              Body_HGA_AZ               LOCKED   0/31          \n",
      "  51. Body_RA_Base            Body_Chassis              LOCKED   0/31          \n",
      "  52. Body_RA_Link1           Body_RA_Base             REVOLUTE  1/31          \n",
      "  53. Body_RA_Link2           Body_RA_Link1            REVOLUTE  1/32          \n",
      "  54. Body_RA_Link3           Body_RA_Link2            REVOLUTE  1/33          \n",
      "  55. Body_RA_Link4           Body_RA_Link3            REVOLUTE  1/34          \n",
      "  56. Body_RA_Link5           Body_RA_Link4            REVOLUTE  1/35          \n",
      "  57. Body_Turret             Body_RA_Link5             LOCKED   0/36          \n",
      "  58. Body_CorerFeed          Body_Turret               SLIDER   1/36          \n",
      "  59. Body_StabilizerFar      Body_Turret               SLIDER   1/37          \n",
      "  60. Body_StabilizerNear     Body_Turret               SLIDER   1/38          \n",
      "  61. Body_WATSON_Cap         Body_Turret              REVOLUTE  1/39          \n",
      "  62. Body_SHERLOC_Cap        Body_Turret              REVOLUTE  1/40          \n",
      "  63. Frame_RA5               Body_RA_Link5             LOCKED   0/41          \n",
      "  64. Frame_RA6               Body_RA_Link5             LOCKED   0/41          \n",
      "  65. Frame_TURRET            Body_RA_Link5             LOCKED   0/41          \n",
      "  66. Frame_DOCKING_POST      Body_RA_Link5             LOCKED   0/41          \n",
      "  67. Frame_DRILL             Body_RA_Link5             LOCKED   0/41          \n",
      "  68. Frame_FCS               Body_RA_Link5             LOCKED   0/41          \n",
      "  69. Frame_GDRT              Body_RA_Link5             LOCKED   0/41          \n",
      "  70. Frame_PIXL              Body_RA_Link5             LOCKED   0/41          \n",
      "  71. Frame_SHERLOC           Body_RA_Link5             LOCKED   0/41          \n",
      "  72. Frame_WATSON            Body_RA_Link5             LOCKED   0/41          \n",
      "  73. Frame_RA4               Body_RA_Link4             LOCKED   0/41          \n",
      "  74. Frame_RA3               Body_RA_Link3             LOCKED   0/41          \n",
      "  75. Frame_RA2               Body_RA_Link2             LOCKED   0/41          \n",
      "  76. Frame_RA1               Body_RA_Link1             LOCKED   0/41          \n",
      "  77. Frame_CAL_PIXL          Body_RA_Link1             LOCKED   0/41          \n",
      "  78. Frame_RNAV              Body_Chassis              LOCKED   0/41          \n",
      "  79. Frame_RMECH             Body_Chassis              LOCKED   0/41          \n",
      "  80. Frame_FHCB              Body_Chassis              LOCKED   0/41          \n",
      "  81. Frame_FHC1              Body_Chassis              LOCKED   0/41          \n",
      "  82. Frame_FHC2              Body_Chassis              LOCKED   0/41          \n",
      "  83. Frame_FHC3              Body_Chassis              LOCKED   0/41          \n",
      "  84. Frame_FHC4              Body_Chassis              LOCKED   0/41          \n",
      "  85. Frame_FHC1_FOV          Body_Chassis              LOCKED   0/41          \n",
      "  86. Frame_FHC2_FOV          Body_Chassis              LOCKED   0/41          \n",
      "  87. Frame_FHC3_FOV          Body_Chassis              LOCKED   0/41          \n",
      "  88. Frame_FHC4_FOV          Body_Chassis              LOCKED   0/41          \n",
      "  89. Frame_RHC1              Body_Chassis              LOCKED   0/41          \n",
      "  90. Frame_RHC2              Body_Chassis              LOCKED   0/41          \n",
      "  91. Frame_RHC1_FOV          Body_Chassis              LOCKED   0/41          \n",
      "  92. Frame_RHC2_FOV          Body_Chassis              LOCKED   0/41          \n",
      "  93. Frame_ATS1              Body_Chassis              LOCKED   0/41          \n",
      "  94. Frame_ATS2              Body_Chassis              LOCKED   0/41          \n",
      "  95. Frame_ATS3              Body_Chassis              LOCKED   0/41          \n",
      "  96. Frame_ATS4              Body_Chassis              LOCKED   0/41          \n",
      "  97. Frame_ATS5              Body_Chassis              LOCKED   0/41          \n",
      "  98. Frame_HS                Body_Chassis              LOCKED   0/41          \n",
      "  99. Frame_ICU               Body_Chassis              LOCKED   0/41          \n",
      " 100. Frame_RDS               Body_Chassis              LOCKED   0/41          \n",
      " 101. Frame_TIRS              Body_Chassis              LOCKED   0/41          \n",
      " 102. Frame_WS1               Body_Chassis              LOCKED   0/41          \n",
      " 103. Frame_WS2               Body_Chassis              LOCKED   0/41          \n",
      " 104. Frame_MOXIE             Body_Chassis              LOCKED   0/41          \n",
      " 105. Frame_MI                Body_Chassis              LOCKED   0/41          \n",
      " 106. Frame_RIMUA             Body_Chassis              LOCKED   0/41          \n",
      " 107. Frame_RIMUB             Body_Chassis              LOCKED   0/41          \n",
      " 108. Frame_RIMFAX            Body_Chassis              LOCKED   0/41          \n",
      " 109. Frame_HGAS              Body_Chassis              LOCKED   0/41          \n",
      " 110. Frame_RA_BASE           Body_Chassis              LOCKED   0/41          \n",
      " 111. Frame_CAL_MC1           Body_Chassis              LOCKED   0/41          \n",
      " 112. Frame_CAL_MC2           Body_Chassis              LOCKED   0/41          \n",
      " 113. Frame_CAL_SC            Body_Chassis              LOCKED   0/41          \n",
      " 114. Frame_CAL_SHERLOC       Body_Chassis              LOCKED   0/41          \n",
      "                                                                 ____          \n",
      "                                                                 41            \n",
      "\n"
     ]
    }
   ],
   "source": [
    "multibody.displayModel()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "979ee288",
   "metadata": {},
   "source": [
    "Display the bodies topology"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "289845b7",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      " Nodes\n",
      " ---\n",
      "LEGEND: [<hinge type> <prescribed subhinges>] <body name>[/num embedded bodies > 0] <flex dofs > 0>\n",
      "|-Perseverance_MBVROOT_\n",
      "   |-[FULL6DOF] Body_Chassis\n",
      "      |-[FULL6DOF] Body_MHS_DebrisShield\n",
      "      |-[REVOLUTE] Body_Differential\n",
      "         |-[LOCKED] Frame_DIFF\n",
      "      |-[REVOLUTE] Body_RockerLeft\n",
      "         |-[REVOLUTE] Body_BogieLeft\n",
      "            |-[REVOLUTE] Body_SteerLeftRear\n",
      "               |-[REVOLUTE] Body_WheelLeftRear\n",
      "                  |-[LOCKED] Frame_WHEEL_LR\n",
      "               |-[LOCKED] Frame_STEER_LR\n",
      "            |-[REVOLUTE] Body_WheelLeftMiddle\n",
      "               |-[LOCKED] Frame_WHEEL_LM\n",
      "            |-[LOCKED] Frame_BOGIE_L\n",
      "         |-[REVOLUTE] Body_SteerLeftFront\n",
      "            |-[REVOLUTE] Body_WheelLeftFront\n",
      "               |-[LOCKED] Frame_WHEEL_LF\n",
      "            |-[LOCKED] Frame_STEER_LF\n",
      "         |-[LOCKED] Frame_ROCKER_L\n",
      "      |-[REVOLUTE] Body_RockerRight\n",
      "         |-[REVOLUTE] Body_BogieRight\n",
      "            |-[REVOLUTE] Body_SteerRightRear\n",
      "               |-[REVOLUTE] Body_WheelRightRear\n",
      "                  |-[LOCKED] Frame_WHEEL_RR\n",
      "               |-[LOCKED] Frame_STEER_RR\n",
      "            |-[REVOLUTE] Body_WheelRightMiddle\n",
      "               |-[LOCKED] Frame_WHEEL_RM\n",
      "            |-[LOCKED] Frame_BOGIE_R\n",
      "         |-[REVOLUTE] Body_SteerRightFront\n",
      "            |-[REVOLUTE] Body_WheelRightFront\n",
      "               |-[LOCKED] Frame_WHEEL_RF\n",
      "            |-[LOCKED] Frame_STEER_RF\n",
      "         |-[LOCKED] Frame_ROCKER_R\n",
      "      |-[REVOLUTE] Body_RSM_AZ\n",
      "         |-[REVOLUTE] Body_RSM_EL\n",
      "            |-[LOCKED] Frame_MEL\n",
      "            |-[LOCKED] Frame_SCI\n",
      "            |-[LOCKED] Frame_SCRMI\n",
      "            |-[LOCKED] Frame_SCLIBS\n",
      "            |-[LOCKED] Frame_SCIR\n",
      "            |-[LOCKED] Frame_MCL\n",
      "            |-[LOCKED] Frame_MCR\n",
      "            |-[LOCKED] Frame_NCL\n",
      "            |-[LOCKED] Frame_NCR\n",
      "            |-[LOCKED] Frame_NCL_FOV\n",
      "            |-[LOCKED] Frame_NCR_FOV\n",
      "         |-[LOCKED] Frame_MAZ\n",
      "      |-[REVOLUTE] Body_HGA_AZ\n",
      "         |-[REVOLUTE] Body_HGA_EL\n",
      "            |-[LOCKED] Frame_ANT\n",
      "         |-[LOCKED] Frame_HGAG\n",
      "      |-[LOCKED] Body_RA_Base\n",
      "         |-[REVOLUTE] Body_RA_Link1\n",
      "            |-[REVOLUTE] Body_RA_Link2\n",
      "               |-[REVOLUTE] Body_RA_Link3\n",
      "                  |-[REVOLUTE] Body_RA_Link4\n",
      "                     |-[REVOLUTE] Body_RA_Link5\n",
      "                        |-[LOCKED] Body_Turret\n",
      "                           |-[SLIDER] Body_CorerFeed\n",
      "                           |-[SLIDER] Body_StabilizerFar\n",
      "                           |-[SLIDER] Body_StabilizerNear\n",
      "                           |-[REVOLUTE] Body_WATSON_Cap\n",
      "                           |-[REVOLUTE] Body_SHERLOC_Cap\n",
      "                        |-[LOCKED] Frame_RA5\n",
      "                        |-[LOCKED] Frame_RA6\n",
      "                        |-[LOCKED] Frame_TURRET\n",
      "                        |-[LOCKED] Frame_DOCKING_POST\n",
      "                        |-[LOCKED] Frame_DRILL\n",
      "                        |-[LOCKED] Frame_FCS\n",
      "                        |-[LOCKED] Frame_GDRT\n",
      "                        |-[LOCKED] Frame_PIXL\n",
      "                        |-[LOCKED] Frame_SHERLOC\n",
      "                        |-[LOCKED] Frame_WATSON\n",
      "                     |-[LOCKED] Frame_RA4\n",
      "                  |-[LOCKED] Frame_RA3\n",
      "               |-[LOCKED] Frame_RA2\n",
      "            |-[LOCKED] Frame_RA1\n",
      "            |-[LOCKED] Frame_CAL_PIXL\n",
      "      |-[LOCKED] Frame_RNAV\n",
      "      |-[LOCKED] Frame_RMECH\n",
      "      |-[LOCKED] Frame_FHCB\n",
      "      |-[LOCKED] Frame_FHC1\n",
      "      |-[LOCKED] Frame_FHC2\n",
      "      |-[LOCKED] Frame_FHC3\n",
      "      |-[LOCKED] Frame_FHC4\n",
      "      |-[LOCKED] Frame_FHC1_FOV\n",
      "      |-[LOCKED] Frame_FHC2_FOV\n",
      "      |-[LOCKED] Frame_FHC3_FOV\n",
      "      |-[LOCKED] Frame_FHC4_FOV\n",
      "      |-[LOCKED] Frame_RHC1\n",
      "      |-[LOCKED] Frame_RHC2\n",
      "      |-[LOCKED] Frame_RHC1_FOV\n",
      "      |-[LOCKED] Frame_RHC2_FOV\n",
      "      |-[LOCKED] Frame_ATS1\n",
      "      |-[LOCKED] Frame_ATS2\n",
      "      |-[LOCKED] Frame_ATS3\n",
      "      |-[LOCKED] Frame_ATS4\n",
      "      |-[LOCKED] Frame_ATS5\n",
      "      |-[LOCKED] Frame_HS\n",
      "      |-[LOCKED] Frame_ICU\n",
      "      |-[LOCKED] Frame_RDS\n",
      "      |-[LOCKED] Frame_TIRS\n",
      "      |-[LOCKED] Frame_WS1\n",
      "      |-[LOCKED] Frame_WS2\n",
      "      |-[LOCKED] Frame_MOXIE\n",
      "      |-[LOCKED] Frame_MI\n",
      "      |-[LOCKED] Frame_RIMUA\n",
      "      |-[LOCKED] Frame_RIMUB\n",
      "      |-[LOCKED] Frame_RIMFAX\n",
      "      |-[LOCKED] Frame_HGAS\n",
      "      |-[LOCKED] Frame_RA_BASE\n",
      "      |-[LOCKED] Frame_CAL_MC1\n",
      "      |-[LOCKED] Frame_CAL_MC2\n",
      "      |-[LOCKED] Frame_CAL_SC\n",
      "      |-[LOCKED] Frame_CAL_SHERLOC\n",
      "\n"
     ]
    }
   ],
   "source": [
    "multibody.dumpTree()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "baa82b16",
   "metadata": {},
   "source": [
    "Uncomment this line below to see an animation of all the hinges in the model (this can take a while to run!)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "8f575fb9",
   "metadata": {},
   "outputs": [],
   "source": [
    "# multibody.articulateBodies()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "73ed21f0",
   "metadata": {},
   "source": [
    "Cleanup"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "7ce7a654",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<function __main__.cleanup()>"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "def cleanup():\n",
    "    \"\"\"Cleanup the simulation.\"\"\"\n",
    "    global basic_prefab_ds, graphics, prefab\n",
    "    del basic_prefab_ds, graphics, prefab\n",
    "\n",
    "    kc.discard(prop)\n",
    "    cleanup_viz()\n",
    "    kc.discard(multibody)\n",
    "    kc.discard(frame_container)\n",
    "\n",
    "\n",
    "atexit.register(cleanup)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "47ef5b9e",
   "metadata": {},
   "source": [
    "## Summary\n",
    "You now know how to import a Mars 2020 Perseverance rover URDF.\n",
    "\n",
    "## Further Readings \n",
    "[Load a robotic arm urdf](../example_urdf/notebook.ipynb)  \n",
    "[Enforce loop constraints in a double-wishbone model](../example_double_wishbone/notebook.ipynb)  \n",
    "[Create and use constraints in a slider-crank model](../example_slider_crank/notebook.ipynb)  \n",
    "[Drive an ATRVjr rover](../example_atrvjr_drive/notebook.ipynb)"
   ]
  }
 ],
 "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
}
