{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true,
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "%%bash --bg\n",
    "rviz -d ~/giskard_examples/launch/rviz_config/standalone.rviz"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "# imports and helper functions\n",
    "import rospy\n",
    "from geometry_msgs.msg import PoseStamped, Point, Quaternion, Vector3Stamped, PointStamped, Vector3\n",
    "from tf.transformations import quaternion_from_matrix, quaternion_about_axis\n",
    "from copy import deepcopy\n",
    "from giskard_msgs.msg import WorldBody, CollisionEntry, WorldGoal, GiskardError\n",
    "import numpy as np\n",
    "from giskardpy.goals.joint_goals import JointPositionList\n",
    "from IPython.display import display, Image\n",
    "from pdf2image import convert_from_path\n",
    "import os\n",
    "import glob\n",
    "import ipywidgets as widgets\n",
    "from IPython.display import display\n",
    "import subprocess\n",
    "\n",
    "\n",
    "# Define some helper functions\n",
    "def reset_giskard():\n",
    "    giskard.clear_motion_goals_and_monitors()\n",
    "    giskard.world.clear()\n",
    "    if ROBOT == 'pr2':\n",
    "        default_pose = {\n",
    "            'r_elbow_flex_joint': -0.15,\n",
    "            'r_forearm_roll_joint': 0,\n",
    "            'r_shoulder_lift_joint': 0,\n",
    "            'r_shoulder_pan_joint': 0,\n",
    "            'r_upper_arm_roll_joint': 0,\n",
    "            'r_wrist_flex_joint': -0.10001,\n",
    "            'r_wrist_roll_joint': 0,\n",
    "            'l_elbow_flex_joint': -0.15,\n",
    "            'l_forearm_roll_joint': 0,\n",
    "            'l_shoulder_lift_joint': 0,\n",
    "            'l_shoulder_pan_joint': 0,\n",
    "            'l_upper_arm_roll_joint': 0,\n",
    "            'l_wrist_flex_joint': -0.10001,\n",
    "            'l_wrist_roll_joint': 0,\n",
    "            'torso_lift_joint': 0.2,\n",
    "            'head_pan_joint': 0,\n",
    "            'head_tilt_joint': 0,\n",
    "            'l_gripper_l_finger_joint': 0.55,\n",
    "            'r_gripper_l_finger_joint': 0.55\n",
    "        }\n",
    "    done = giskard.monitors.add_set_seed_configuration(default_pose)\n",
    "    base_pose = PoseStamped()\n",
    "    base_pose.header.frame_id = 'map'\n",
    "    base_pose.pose.position = Point(0, 0, 0)\n",
    "    base_pose.pose.orientation.w = 1\n",
    "    done2 = giskard.monitors.add_set_seed_odometry(base_pose=base_pose)\n",
    "    giskard.motion_goals.allow_all_collisions()\n",
    "    giskard.monitors.add_end_motion(start_condition=f'{done} and {done2}')\n",
    "    giskard.execute()\n",
    "    giskard.clear_motion_goals_and_monitors()\n",
    "\n",
    "\n",
    "# global variables\n",
    "ROBOT = 'pr2'\n",
    "single_joint_goal = {'torso_lift_joint': 0.3}\n",
    "tool_frame = 'l_gripper_tool_frame'\n",
    "cam_frame = 'wide_stereo_optical_frame'\n",
    "base_link = 'base_footprint'\n",
    "gripper_joint = 'l_gripper_l_finger_joint'\n",
    "gripper_joint_open = 0.55\n",
    "gripper_joint_close = 0.1\n",
    "\n",
    "# List of available launch files\n",
    "launch_files = {\n",
    "    'PR2': 'giskardpy_pr2_standalone_vrb.launch'\n",
    "}\n",
    "\n",
    "# Dropdown widget\n",
    "dropdown = widgets.Dropdown(\n",
    "    options=launch_files.keys(),\n",
    "    value='PR2',\n",
    "    description='Select Robot:',\n",
    "    style={'description_width': 'initial'},\n",
    "    layout=widgets.Layout(width='200px')\n",
    ")\n",
    "\n",
    "# Button widget\n",
    "button = widgets.Button(\n",
    "    description='Start Launch File',\n",
    "    button_style='success',\n",
    ")\n",
    "\n",
    "\n",
    "def update_global_variables(robot):\n",
    "    global ROBOT\n",
    "    global single_joint_goal\n",
    "    global tool_frame\n",
    "    global cam_frame\n",
    "    global base_link\n",
    "    global gripper_joint\n",
    "    global gripper_joint_open\n",
    "    global gripper_joint_close\n",
    "    ROBOT = robot\n",
    "    if ROBOT == 'stretch':\n",
    "        single_joint_goal = {'joint_lift': 0.7}\n",
    "        tool_frame = 'link_grasp_center'\n",
    "        cam_frame = 'camera_color_optical_frame'\n",
    "        base_link = 'base_link'\n",
    "        gripper_joint = 'joint_gripper_finger_left'\n",
    "        gripper_joint_open = 0.55\n",
    "        gripper_joint_close = 0.1\n",
    "    elif ROBOT == 'pr2':\n",
    "        single_joint_goal = {'torso_lift_joint': 0.3}\n",
    "        tool_frame = 'l_gripper_tool_frame'\n",
    "        cam_frame = 'wide_stereo_optical_frame'\n",
    "        base_link = 'base_footprint'\n",
    "        gripper_joint = 'l_gripper_l_finger_joint'\n",
    "        gripper_joint_open = 0.55\n",
    "        gripper_joint_close = 0.1\n",
    "\n",
    "\n",
    "# Function to start the selected ROS launch file\n",
    "def on_button_click(b):\n",
    "    selected_launch_file = launch_files[dropdown.value]\n",
    "\n",
    "    update_global_variables(dropdown.value.lower())\n",
    "\n",
    "    try:\n",
    "        result = subprocess.run('rosnode kill /giskard', shell=True, check=True, stdout=subprocess.PIPE,\n",
    "                                stderr=subprocess.PIPE)\n",
    "        print(result.stdout.decode())\n",
    "        print(result.stderr.decode())\n",
    "    except subprocess.CalledProcessError as e:\n",
    "        print(f\"Error occurred: {e.stderr.decode()}\")\n",
    "\n",
    "    print(f\"Starting ROS launch file: {selected_launch_file}\")\n",
    "    command = f\"roslaunch giskardpy {selected_launch_file}\"\n",
    "    LAUNCH_PROCESS = subprocess.Popen(['/bin/bash', '-c', command],\n",
    "                                      stdout=subprocess.DEVNULL,\n",
    "                                      stderr=subprocess.DEVNULL, shell=False)\n",
    "\n",
    "\n",
    "# Attach the event handler to the button\n",
    "button.on_click(on_button_click)\n",
    "\n",
    "# Display widgets\n",
    "display(dropdown)\n",
    "display(button)\n",
    "rospy.init_node('giskard_examples')"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "# Hints\n",
    "Poses are fully described by a position `PoseStamped().pose.position.x/.y/.z` and an orientation given as a quaternion `PoseStamped().pose.orientation.x/.y/.z/.w`.\n",
    "An identity quaternion has the values (0, 0, 0, 1) for (x, y, z, w).\n",
    "Here quaternions can be calculated by different functions:\n",
    "- quaternion_from_matrix(4x4 array for rotation matrix)\n",
    "- quaternion_about_axis(angle, axis=[x, y, z])\n"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "from giskardpy.python_interface.python_interface import GiskardWrapper\n",
    "\n",
    "giskard = GiskardWrapper()"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "Execute the following cell to reset the state of the robot and the world.\n",
    "Also needed to initially load the world."
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "reset_giskard()\n",
    "\n",
    "kitchen_pose = PoseStamped()\n",
    "kitchen_pose.header.frame_id = 'map'\n",
    "kitchen_pose.pose.orientation.w = 1\n",
    "giskard.world.add_urdf(name='iai_kitchen',\n",
    "                       urdf=rospy.get_param('kitchen_description'),\n",
    "                       pose=kitchen_pose)\n",
    "box_name = 'box'\n",
    "fridge_handle_name = 'iai_fridge_door_handle'\n",
    "fridge_shelf_name = 'iai_fridge_door_shelf1_bottom'\n",
    "sink_area = 'sink_area_surface'\n",
    "left_gripper = 'l_gripper_tool_frame'\n",
    "right_gripper = 'r_gripper_tool_frame'\n",
    "\n",
    "box_pose = PoseStamped()\n",
    "box_pose.header.frame_id = sink_area\n",
    "box_pose.pose.position.z = 0.06\n",
    "box_pose.pose.position.x = 0.15\n",
    "box_pose.pose.orientation.w = 1\n",
    "giskard.world.add_box(name=box_name, size=[0.05, 0.05, 0.15], pose=box_pose, parent_link='map')"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "Define a Pose to grasp the box from the top with the left gripper."
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "goal_pose = PoseStamped()\n",
    "goal_pose.header.frame_id = None\n",
    "goal_pose.pose.position.x = None\n",
    "goal_pose.pose.position.y = None\n",
    "goal_pose.pose.position.z = None\n",
    "goal_pose.pose.orientation = Quaternion(*quaternion_from_matrix([[0, 0, 0, 0],\n",
    "                                                                 [0, 0, 0, 0],\n",
    "                                                                 [0, 0, 0, 0],\n",
    "                                                                 [0, 0, 0, 0]]))\n",
    "giskard.motion_goals.add_cartesian_pose(goal_pose=goal_pose, root_link='map', tip_link=left_gripper)\n",
    "giskard.motion_goals.allow_all_collisions()\n",
    "giskard.add_default_end_motion_conditions()\n",
    "assert giskard.execute().error.code == GiskardError.SUCCESS"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "Define a Pose to move the base to while holding the box. the goal is to move the box away from the counter."
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "giskard.world.update_parent_link_of_group(name=box_name, parent_link=left_gripper)\n",
    "\n",
    "drive_back_pose = PoseStamped()\n",
    "drive_back_pose.header.frame_id = None\n",
    "drive_back_pose.pose.position.x = None\n",
    "drive_back_pose.pose.position.y = None\n",
    "drive_back_pose.pose.position.z = None\n",
    "drive_back_pose.pose.orientation = Quaternion(None)\n",
    "\n",
    "giskard.motion_goals.add_cartesian_pose(goal_pose=drive_back_pose, root_link='map',\n",
    "                                              tip_link='base_footprint')\n",
    "giskard.motion_goals.allow_all_collisions()\n",
    "giskard.add_default_end_motion_conditions()\n",
    "assert giskard.execute().error.code == GiskardError.SUCCESS"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "Define a pose for the right gripper to grasp the handle of the fridge."
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "grasp_handle_pose = PoseStamped()\n",
    "grasp_handle_pose.header.frame_id = None\n",
    "grasp_handle_pose.pose.orientation = Quaternion(None)\n",
    "grasp_handle_pose.pose.position.x = None\n",
    "grasp_handle_pose.pose.position.y = None\n",
    "grasp_handle_pose.pose.position.z = None\n",
    "\n",
    "giskard.motion_goals.add_cartesian_pose(goal_pose=grasp_handle_pose, root_link='map',\n",
    "                                              tip_link=right_gripper)\n",
    "giskard.motion_goals.allow_all_collisions()\n",
    "giskard.add_default_end_motion_conditions()\n",
    "assert giskard.execute().error.code == GiskardError.SUCCESS"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "The next cell automatically opens the fridge without any edits."
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "giskard.motion_goals.add_open_container(tip_link=right_gripper,\n",
    "                                              environment_link=fridge_handle_name)\n",
    "giskard.motion_goals.allow_all_collisions()\n",
    "giskard.add_default_end_motion_conditions()\n",
    "assert giskard.execute().error.code == GiskardError.SUCCESS"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "Define a pose in the fridge shelf to place the grasped box at and define a pose to keep the right gripper at the handle of the fridge."
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "place_pose = PoseStamped()\n",
    "place_pose.header.frame_id = None\n",
    "place_pose.pose.position.x = None\n",
    "place_pose.pose.position.y = None\n",
    "place_pose.pose.position.z = None\n",
    "place_pose.pose.orientation = Quaternion(None)\n",
    "\n",
    "giskard.motion_goals.add_cartesian_pose(goal_pose=place_pose,\n",
    "                                        root_link='map',\n",
    "                                        tip_link=box_name,\n",
    "                                        name='goal1')\n",
    "\n",
    "grasp_handle_pose = PoseStamped()\n",
    "grasp_handle_pose.header.frame_id = None\n",
    "grasp_handle_pose.pose.position.x = None\n",
    "grasp_handle_pose.pose.position.y = None\n",
    "grasp_handle_pose.pose.position.z = None\n",
    "grasp_handle_pose.pose.orientation = Quaternion(None)\n",
    "\n",
    "giskard.motion_goals.add_cartesian_pose(goal_pose=grasp_handle_pose, root_link='map',\n",
    "                                        tip_link=right_gripper, name='goal2')\n",
    "giskard.motion_goals.allow_all_collisions()\n",
    "giskard.add_default_end_motion_conditions()\n",
    "assert giskard.execute().error.code == GiskardError.SUCCESS"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  },
  {
   "cell_type": "markdown",
   "source": [
    "The next cell closes the fridge without any edits."
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%% md\n"
    }
   }
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "outputs": [],
   "source": [
    "giskard.world.update_parent_link_of_group(name=box_name, parent_link=fridge_shelf_name)\n",
    "\n",
    "giskard.motion_goals.add_close_container(tip_link=right_gripper,\n",
    "                                               environment_link=fridge_handle_name)\n",
    "giskard.motion_goals.allow_all_collisions()\n",
    "giskard.add_default_end_motion_conditions()\n",
    "assert giskard.execute().error.code == GiskardError.SUCCESS"
   ],
   "metadata": {
    "collapsed": false,
    "pycharm": {
     "name": "#%%\n"
    }
   }
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}