diff --git a/CMakeLists.txt b/CMakeLists.txt
index f8eeccd70ba49ec518786a5e8735ee486fcddaee..ae98355e3f18b0c3221cf81e8086c025f5ce9a69 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -17,6 +17,8 @@ find_package(catkin REQUIRED
         joint_trajectory_controller
         robot_state_publisher
         roscpp
+        tf2
+        tf2_geometry_msgs
         std_msgs
         xacro
         moveit_core
@@ -42,6 +44,7 @@ catkin_package(CATKIN_DEPENDS
         controller_interface
         hardware_interface
         pluginlib
+        tf2
         simulation_util
         DEPENDS
         # system_lib
@@ -52,15 +55,27 @@ catkin_package(CATKIN_DEPENDS
 # ######################################################################################################################
 
 # Specify additional locations of header files Your package locations should be listed before other locations
-include_directories(${catkin_INCLUDE_DIRS})
+include_directories(src ${catkin_INCLUDE_DIRS})
 
 add_executable(BasicCartesianPlanner src/BasicCartesianPlanner.cpp)
 add_executable(BasicJointSpacePlanner src/BasicJointSpacePlanner.cpp)
 add_executable(ObstacleAwarePlanner src/ObstacleAwarePlanner.cpp)
-add_executable(PickPlacePlanner src/PickPlacePlanner.cpp)
+add_executable(PickPlacePlanner src/PickPlacePlanner.cpp src/PickPlacePlannerMain.cpp)
 
 ## Add cmake target dependencies of the executable
 target_link_libraries(BasicCartesianPlanner ${catkin_LIBRARIES})
 target_link_libraries(BasicJointSpacePlanner ${catkin_LIBRARIES})
 target_link_libraries(ObstacleAwarePlanner ${catkin_LIBRARIES})
 target_link_libraries(PickPlacePlanner ${catkin_LIBRARIES})
+
+#############
+## Testing ##
+#############
+
+## Add gtest based cpp test target and link libraries
+
+if(CATKIN_ENABLE_TESTING)
+    find_package(rostest REQUIRED)
+    add_rostest_gtest(tests_grasping test/grasping.test test/test.cpp src/PickPlacePlanner.cpp)
+    target_link_libraries(tests_grasping ${catkin_LIBRARIES})
+endif()
\ No newline at end of file
diff --git a/package.xml b/package.xml
index 90cc3dea1b768399373584fd7020b852982c858f..bb19ef9d403c4caf40b0e37a3d727af699280993 100644
--- a/package.xml
+++ b/package.xml
@@ -42,11 +42,12 @@
   <depend>robot_state_publisher</depend>
   <depend>roscpp</depend>
   <depend>std_msgs</depend>
-  <depend>tf</depend>
   <depend>xacro</depend>
   <depend>moveit_simple_controller_manager</depend>
 
   <!-- CUSTOM -->
+  <depend>tf2</depend>
+  <depend>tf2_geometry_msgs</depend>
   <depend>moveit_core</depend>
   <depend>moveit_ros_planning_interface</depend>
   <depend>moveit_ros_perception</depend>
diff --git a/src/PickPlacePlanner.cpp b/src/PickPlacePlanner.cpp
index 0dcd019720a5976b08828c8220786432a625b1e7..613ad999aba753e723690a2f821470d4ab915bde 100644
--- a/src/PickPlacePlanner.cpp
+++ b/src/PickPlacePlanner.cpp
@@ -53,11 +53,15 @@
 #include <moveit/move_group_interface/move_group_interface.h>
 
 // TF2
-#include <tf2_geometry_msgs/tf2_geometry_msgs.h>
+#include "tf2_geometry_msgs/tf2_geometry_msgs.h"
 
 // Zone Spawner to add the collision objects to Gazebo
 #include <GazeboZoneSpawner.h>
 
+#include "PickPlacePlanner.h"
+
+namespace pick_place_planner {
+
 /**
  * Sets the posture argument to an open state for the two gripper fingers (8cm apart).
  * @param posture An empty posture that is filled with a posture for two fingers
@@ -100,7 +104,7 @@ void closedGripper(trajectory_msgs::JointTrajectory& posture)
  * Pick an object from a fixed position.
  * @param move_group The move group the pick operation is performed on
  */
-void pick(moveit::planning_interface::MoveGroupInterface& move_group)
+moveit::planning_interface::MoveItErrorCode pick(moveit::planning_interface::MoveGroupInterface& move_group)
 {
   // Create a vector of grasps to be attempted, currently only creating single grasp.
   // This is essentially useful when using a grasp generator to generate and test multiple grasps.
@@ -114,8 +118,46 @@ void pick(moveit::planning_interface::MoveGroupInterface& move_group)
   // your manipulator which in this case would be `"panda_link8"` You will have to compensate for the
   // transform from `"panda_link8"` to the palm of the end effector.
   grasps[0].grasp_pose.header.frame_id = "panda_link0";
-  tf2::Quaternion orientation;
-  orientation.setRPY(-M_PI / 2, -M_PI / 4, -M_PI / 2);
+
+  // object orientation (default orientation)
+  tf2::Quaternion object_orientation{0, 0, 0, 1};
+
+  // gripper orientation
+  tf2::Quaternion gripper_orientation;
+  // We know the gripper is rotated -45 degrees from the urdf model:
+  // The "hand" definition in franka_description/robots/hand.xacro
+  //     <robot xmlns:xacro="http://www.ros.org/wiki/xacro" name="hand">
+  //     <xacro:macro name="hand" params="connected_to:='' ns:='' rpy:='0 0 0' xyz:='0 0 0' ">
+  //       <xacro:unless value="${connected_to == ''}">
+  //         <joint name="${ns}_hand_joint" type="fixed">
+  //           <parent link="${connected_to}"/>
+  //           <child link="${ns}_hand"/>
+  //           <origin xyz="${xyz}" rpy="${rpy}"/>
+  //         </joint>
+  //       </xacro:unless>
+  //       <!-- other things... -->
+  //       </xacro:macro>
+  //     </robot>
+  //
+  // Its use in franka_description/robots/panda_arm_hand.urdf.xacro
+  //     <xacro:hand ns="panda" rpy="0 0 ${-pi/4}" connected_to="panda_link8"/>
+  gripper_orientation.setRPY(0, 0, -M_PI_4);
+  // If we did not know it, we could also look it up!
+  // tf2_ros::Buffer tfBuffer;
+  // tf2_ros::TransformListener tfListener(tfBuffer);
+  // ros::WallDuration(0.1).sleep(); // wait a bit for the tf listener
+  // tf2::fromMsg((tfBuffer.lookupTransform("panda_hand", "panda_link8", ros::Time(0)).transform).rotation, gripper_orientation);
+
+  // approach orientation
+  double approach_roll, approach_pitch, approach_yaw;
+  approach_roll =  -M_PI_2; // The neutral rotation has the gripper "looking down",
+  approach_pitch = -M_PI_4; // with these transformations, it grasps from one side.
+  approach_yaw =   -M_PI_4; // This results in (x=-0.5,y=-0.5,z=0,w=0.7071068)
+  tf2::Quaternion approach_orientation;
+  approach_orientation.setRPY(approach_roll, approach_pitch, approach_yaw);
+
+  tf2::Quaternion orientation = object_orientation * gripper_orientation * approach_orientation;
+
   grasps[0].grasp_pose.pose.orientation = tf2::toMsg(orientation);
   grasps[0].grasp_pose.pose.position.x = 0.4;
   grasps[0].grasp_pose.pose.position.y = 0;
@@ -150,14 +192,14 @@ void pick(moveit::planning_interface::MoveGroupInterface& move_group)
   // Set support surface as table1.
   move_group.setSupportSurfaceName("table1");
   // Call pick to pick up the object using the grasps given
-  move_group.pick("object", grasps);
+  return move_group.pick("object", grasps);
 }
 
 /**
  * Place an object at a fixed position on top of table2.
  * @param group
  */
-void place(moveit::planning_interface::MoveGroupInterface& group)
+moveit::planning_interface::MoveItErrorCode place(moveit::planning_interface::MoveGroupInterface& group)
 {
   std::vector<moveit_msgs::PlaceLocation> place_location;
   place_location.resize(1);
@@ -200,7 +242,7 @@ void place(moveit::planning_interface::MoveGroupInterface& group)
   // Set support surface as table2.
   group.setSupportSurfaceName("table2");
   // Call place to place the object using the place locations given.
-  group.place("object", place_location);
+  return group.place("object", place_location);
 }
 
 /**
@@ -342,34 +384,5 @@ void addCollisionObjects(moveit::planning_interface::PlanningSceneInterface& pla
   planning_scene_interface.applyCollisionObjects(collision_objects);
 }
 
-int main(int argc, char** argv)
-{
-  ros::init(argc, argv, "panda_arm_pick_place");
-  ros::NodeHandle nh;
-  ros::AsyncSpinner spinner(1);
-
-  ROS_INFO_NAMED("constraint_planner", ">>>>>>>>>>>>>>>> WAITING FOR ROBOT INIT <<<<<<<<<<<<<<<");
-  ros::Duration(3.0).sleep();
-  ROS_INFO_NAMED("constraint_planner", ">>>>>>>>>>>>>>>>> WAKING UP AFTER INIT <<<<<<<<<<<<<<<<");
-
-  spinner.start();
+} // end namespace pick_place_planner
 
-  ros::WallDuration(1.0).sleep();
-  moveit::planning_interface::PlanningSceneInterface planning_scene_interface;
-  moveit::planning_interface::MoveGroupInterface group("panda_arm");
-  group.setPlanningTime(45.0);
-
-  addCollisionObjects(planning_scene_interface);
-
-  // Wait a bit for ROS things to initialize
-  ros::WallDuration(1.0).sleep();
-
-  pick(group);
-
-  ros::WallDuration(1.0).sleep();
-
-  place(group);
-
-  ros::waitForShutdown();
-  return 0;
-}
diff --git a/src/PickPlacePlanner.h b/src/PickPlacePlanner.h
new file mode 100644
index 0000000000000000000000000000000000000000..980c2a87ac3ce18e5025b80bfbdbe2a0ed2afa28
--- /dev/null
+++ b/src/PickPlacePlanner.h
@@ -0,0 +1,46 @@
+
+#ifndef SAMPLE_APPLICATIONS_PICK_PLACE_PLANNER_H
+#define SAMPLE_APPLICATIONS_PICK_PLACE_PLANNER_H
+
+// ROS
+#include <ros/ros.h>
+
+// MoveIt
+#include <moveit/planning_scene_interface/planning_scene_interface.h>
+#include <moveit/move_group_interface/move_group_interface.h>
+
+namespace pick_place_planner {
+
+/**
+ * Sets the posture argument to an open state for the two gripper fingers (8cm apart).
+ * @param posture An empty posture that is filled with a posture for two fingers
+ */
+void openGripper(trajectory_msgs::JointTrajectory &posture);
+
+/**
+ * Sets the posture argument to a closed state for the two gripper fingers
+ * @param posture An empty posture that is filled with a posture for two fingers
+ */
+void closedGripper(trajectory_msgs::JointTrajectory &posture);
+
+/**
+ * Pick an object from a fixed position.
+ * @param move_group The move group the pick operation is performed on
+ */
+moveit::planning_interface::MoveItErrorCode pick(moveit::planning_interface::MoveGroupInterface &move_group);
+
+/**
+* Place an object at a fixed position on top of table2.
+* @param group
+*/
+moveit::planning_interface::MoveItErrorCode place(moveit::planning_interface::MoveGroupInterface &group);
+
+/**
+* Add the collision objects to the planning scene and to gazebo.
+* @param planning_scene_interface The interface to access the planning scene.
+*/
+void addCollisionObjects(moveit::planning_interface::PlanningSceneInterface &planning_scene_interface);
+
+}
+
+#endif // SAMPLE_APPLICATIONS_PICK_PLACE_PLANNER_H
\ No newline at end of file
diff --git a/src/PickPlacePlannerMain.cpp b/src/PickPlacePlannerMain.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0b2248c05c5f487069daa2cc410049b14afcd9e1
--- /dev/null
+++ b/src/PickPlacePlannerMain.cpp
@@ -0,0 +1,33 @@
+#include "PickPlacePlanner.h"
+
+int main(int argc, char** argv)
+{
+    ros::init(argc, argv, "panda_arm_pick_place");
+    ros::NodeHandle nh;
+    ros::AsyncSpinner spinner(1);
+
+    ROS_INFO_NAMED("constraint_planner", ">>>>>>>>>>>>>>>> WAITING FOR ROBOT INIT <<<<<<<<<<<<<<<");
+    ros::Duration(3.0).sleep();
+    ROS_INFO_NAMED("constraint_planner", ">>>>>>>>>>>>>>>>> WAKING UP AFTER INIT <<<<<<<<<<<<<<<<");
+
+    spinner.start();
+
+    ros::WallDuration(1.0).sleep();
+    moveit::planning_interface::PlanningSceneInterface planning_scene_interface;
+    moveit::planning_interface::MoveGroupInterface group("panda_arm");
+    group.setPlanningTime(45.0);
+
+    pick_place_planner::addCollisionObjects(planning_scene_interface);
+
+    // Wait a bit for ROS things to initialize
+    ros::WallDuration(1.0).sleep();
+
+    pick_place_planner::pick(group);
+
+    ros::WallDuration(1.0).sleep();
+
+    pick_place_planner::place(group);
+
+    ros::waitForShutdown();
+    return 0;
+}
\ No newline at end of file
diff --git a/test/grasping.test b/test/grasping.test
new file mode 100644
index 0000000000000000000000000000000000000000..235eec5237727f5d265bf517341eaad5126462df
--- /dev/null
+++ b/test/grasping.test
@@ -0,0 +1,12 @@
+<launch>
+    <include file="$(find panda_simulation)/launch/simulation.launch">
+        <arg name="slow_simulation" value="false" />
+    </include>
+
+    <node name="$(anon rviz)" pkg="rviz" type="rviz" respawn="false"
+          args="-d $(find sample_applications)/test/plan_visualizer.rviz" output="screen">
+        <rosparam command="load" file="$(find panda_moveit_config)/config/kinematics.yaml"/>
+    </node>
+
+    <test test-name="PickPlacePlannerTest" pkg="sample_applications" type="tests_grasping"  time-limit="3600.0" />
+</launch>
\ No newline at end of file
diff --git a/test/plan_visualizer.rviz b/test/plan_visualizer.rviz
new file mode 100644
index 0000000000000000000000000000000000000000..2f631356378c3b3dc72a04abff35b9b9d5f1893f
--- /dev/null
+++ b/test/plan_visualizer.rviz
@@ -0,0 +1,286 @@
+Panels:
+  []
+Preferences:
+  PromptSaveOnExit: true
+Toolbars:
+  toolButtonStyle: 2
+Visualization Manager:
+  Class: ""
+  Displays:
+    - Alpha: 0.5
+      Cell Size: 1
+      Class: rviz/Grid
+      Color: 160; 160; 164
+      Enabled: true
+      Line Style:
+        Line Width: 0.029999999329447746
+        Value: Lines
+      Name: Grid
+      Normal Cell Count: 0
+      Offset:
+        X: 0
+        Y: 0
+        Z: 0
+      Plane: XY
+      Plane Cell Count: 10
+      Reference Frame: <Fixed Frame>
+      Value: true
+    - Acceleration_Scaling_Factor: 1
+      Class: moveit_rviz_plugin/MotionPlanning
+      Enabled: true
+      Move Group Namespace: ""
+      MoveIt_Allow_Approximate_IK: false
+      MoveIt_Allow_External_Program: false
+      MoveIt_Allow_Replanning: false
+      MoveIt_Allow_Sensor_Positioning: false
+      MoveIt_Goal_Tolerance: 0
+      MoveIt_Planning_Attempts: 10
+      MoveIt_Planning_Time: 5
+      MoveIt_Use_Cartesian_Path: false
+      MoveIt_Use_Constraint_Aware_IK: true
+      MoveIt_Warehouse_Host: 127.0.0.1
+      MoveIt_Warehouse_Port: 33829
+      MoveIt_Workspace:
+        Center:
+          X: 0
+          Y: 0
+          Z: 0
+        Size:
+          X: 2
+          Y: 2
+          Z: 2
+      Name: MotionPlanning
+      Planned Path:
+        Color Enabled: false
+        Interrupt Display: false
+        Links:
+          All Links Enabled: true
+          Expand Joint Details: false
+          Expand Link Details: false
+          Expand Tree: false
+          Link Tree Style: Links in Alphabetic Order
+          panda_hand:
+            Alpha: 1
+            Show Axes: false
+            Show Trail: false
+            Value: true
+          panda_leftfinger:
+            Alpha: 1
+            Show Axes: false
+            Show Trail: false
+            Value: true
+          panda_link0:
+            Alpha: 1
+            Show Axes: false
+            Show Trail: false
+            Value: true
+          panda_link1:
+            Alpha: 1
+            Show Axes: false
+            Show Trail: false
+            Value: true
+          panda_link2:
+            Alpha: 1
+            Show Axes: false
+            Show Trail: false
+            Value: true
+          panda_link3:
+            Alpha: 1
+            Show Axes: false
+            Show Trail: false
+            Value: true
+          panda_link4:
+            Alpha: 1
+            Show Axes: false
+            Show Trail: false
+            Value: true
+          panda_link5:
+            Alpha: 1
+            Show Axes: false
+            Show Trail: false
+            Value: true
+          panda_link6:
+            Alpha: 1
+            Show Axes: false
+            Show Trail: false
+            Value: true
+          panda_link7:
+            Alpha: 1
+            Show Axes: false
+            Show Trail: false
+            Value: true
+          panda_link8:
+            Alpha: 1
+            Show Axes: false
+            Show Trail: false
+          panda_rightfinger:
+            Alpha: 1
+            Show Axes: false
+            Show Trail: false
+            Value: true
+          world:
+            Alpha: 1
+            Show Axes: false
+            Show Trail: false
+        Loop Animation: true
+        Robot Alpha: 0.5
+        Robot Color: 150; 50; 150
+        Show Robot Collision: false
+        Show Robot Visual: true
+        Show Trail: false
+        State Display Time: 0.05 s
+        Trail Step Size: 1
+        Trajectory Topic: move_group/display_planned_path
+      Planning Metrics:
+        Payload: 1
+        Show Joint Torques: false
+        Show Manipulability: false
+        Show Manipulability Index: false
+        Show Weight Limit: false
+        TextHeight: 0.07999999821186066
+      Planning Request:
+        Colliding Link Color: 255; 0; 0
+        Goal State Alpha: 1
+        Goal State Color: 250; 128; 0
+        Interactive Marker Size: 0
+        Joint Violation Color: 255; 0; 255
+        Planning Group: panda_arm
+        Query Goal State: false
+        Query Start State: false
+        Show Workspace: false
+        Start State Alpha: 1
+        Start State Color: 0; 255; 0
+      Planning Scene Topic: move_group/monitored_planning_scene
+      Robot Description: robot_description
+      Scene Geometry:
+        Scene Alpha: 0.8999999761581421
+        Scene Color: 50; 230; 50
+        Scene Display Time: 0.20000000298023224
+        Show Scene Geometry: true
+        Voxel Coloring: Z-Axis
+        Voxel Rendering: Occupied Voxels
+      Scene Robot:
+        Attached Body Color: 150; 50; 150
+        Links:
+          All Links Enabled: true
+          Expand Joint Details: false
+          Expand Link Details: false
+          Expand Tree: false
+          Link Tree Style: Links in Alphabetic Order
+          panda_hand:
+            Alpha: 1
+            Show Axes: false
+            Show Trail: false
+            Value: true
+          panda_leftfinger:
+            Alpha: 1
+            Show Axes: false
+            Show Trail: false
+            Value: true
+          panda_link0:
+            Alpha: 1
+            Show Axes: false
+            Show Trail: false
+            Value: true
+          panda_link1:
+            Alpha: 1
+            Show Axes: false
+            Show Trail: false
+            Value: true
+          panda_link2:
+            Alpha: 1
+            Show Axes: false
+            Show Trail: false
+            Value: true
+          panda_link3:
+            Alpha: 1
+            Show Axes: false
+            Show Trail: false
+            Value: true
+          panda_link4:
+            Alpha: 1
+            Show Axes: false
+            Show Trail: false
+            Value: true
+          panda_link5:
+            Alpha: 1
+            Show Axes: false
+            Show Trail: false
+            Value: true
+          panda_link6:
+            Alpha: 1
+            Show Axes: false
+            Show Trail: false
+            Value: true
+          panda_link7:
+            Alpha: 1
+            Show Axes: false
+            Show Trail: false
+            Value: true
+          panda_link8:
+            Alpha: 1
+            Show Axes: false
+            Show Trail: false
+          panda_rightfinger:
+            Alpha: 1
+            Show Axes: false
+            Show Trail: false
+            Value: true
+          world:
+            Alpha: 1
+            Show Axes: false
+            Show Trail: false
+        Robot Alpha: 0.5
+        Show Robot Collision: false
+        Show Robot Visual: false
+      Value: true
+      Velocity_Scaling_Factor: 1
+  Enabled: true
+  Global Options:
+    Background Color: 48; 48; 48
+    Default Light: true
+    Fixed Frame: panda_link0
+    Frame Rate: 30
+  Name: root
+  Tools:
+    - Class: rviz/Interact
+      Hide Inactive Objects: true
+    - Class: rviz/MoveCamera
+    - Class: rviz/Select
+    - Class: rviz_visual_tools/KeyTool
+  Value: true
+  Views:
+    Current:
+      Class: rviz/XYOrbit
+      Distance: 2.9803097248077393
+      Enable Stereo Rendering:
+        Stereo Eye Separation: 0.05999999865889549
+        Stereo Focal Distance: 1
+        Swap Stereo Eyes: false
+        Value: false
+      Focal Point:
+        X: 1.0864897966384888
+        Y: 0.3387787342071533
+        Z: 2.2351798634190345e-7
+      Focal Shape Fixed Size: true
+      Focal Shape Size: 0.05000000074505806
+      Invert Z Axis: false
+      Name: Current View
+      Near Clip Distance: 0.009999999776482582
+      Pitch: 0.270203560590744
+      Target Frame: panda_link0
+      Value: XYOrbit (rviz)
+      Yaw: 0.42677485942840576
+    Saved: ~
+Window Geometry:
+  Height: 1404
+  Hide Left Dock: false
+  Hide Right Dock: false
+  MotionPlanning:
+    collapsed: false
+  MotionPlanning - Trajectory Slider:
+    collapsed: false
+  QMainWindow State: 000000ff00000000fd00000002000000000000013b000004e1fc0200000003fb0000001c004d006f00740069006f006e0050006c0061006e006e0069006e00670000000080000003640000017200fffffffb0000000800480065006c00700100000334000000e10000000000000000fb0000000a00560069006500770073000000003b000004e1000000000000000000000003000004fe0000003ffc0100000001fb00000044004d006f00740069006f006e0050006c0061006e006e0069006e00670020002d0020005400720061006a006500630074006f0072007900200053006c00690064006500720100000000000004fe0000010000ffffff000004fe000004e100000004000000040000000800000008fc0000000100000002000000010000000a0054006f006f006c00730100000000ffffffff0000000000000000
+  Width: 1278
+  X: 0
+  Y: 18
diff --git a/test/test.cpp b/test/test.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..252882e836cc2ca082784b529350aedc3b9e7e88
--- /dev/null
+++ b/test/test.cpp
@@ -0,0 +1,82 @@
+#include "PickPlacePlanner.h"
+
+#include <gtest/gtest.h>
+
+class Grasping : public ::testing::Test {
+public:
+    Grasping(): spinner(nullptr) {};
+
+protected:
+
+    ros::AsyncSpinner* spinner;
+    ros::NodeHandle* node;
+
+    void SetUp() override {
+        ::testing::Test::SetUp();
+
+        this->node = new ros::NodeHandle("~");
+        this->spinner = new ros::AsyncSpinner(2);
+        this->spinner->start();
+
+        ROS_INFO(">>>>>>>>>>>>>>>> WAITING FOR ROBOT INIT <<<<<<<<<<<<<<<");
+        ros::Duration(3.0).sleep();
+        ROS_INFO(">>>>>>>>>>>>>>>>> WAKING UP AFTER INIT <<<<<<<<<<<<<<<<");
+
+        // clean up scene
+        CleanupScene();
+    }
+
+
+    static void CleanupScene() {
+        moveit::planning_interface::PlanningSceneInterface planning_scene_interface;
+
+        for (auto p : planning_scene_interface.getObjects()) {
+            p.second.operation = moveit_msgs::CollisionObject::REMOVE;
+            planning_scene_interface.applyCollisionObject(p.second);
+        }
+        ASSERT_EQ(planning_scene_interface.getObjects().size(), 0);
+        ASSERT_EQ(planning_scene_interface.getAttachedObjects().size(), 0);
+    }
+
+    void TearDown() override
+    {
+        ros::shutdown();
+        delete this->spinner;
+        delete this->node;
+        ::testing::Test::TearDown();
+    }
+
+};
+
+
+TEST_F(Grasping, PickPlacePlannerTest) {
+    ros::WallDuration(1.0).sleep();
+    moveit::planning_interface::PlanningSceneInterface planning_scene_interface;
+    moveit::planning_interface::MoveGroupInterface group("panda_arm");
+    group.setPlanningTime(45.0);
+
+    pick_place_planner::addCollisionObjects(planning_scene_interface);
+
+    // Wait a bit for ROS things to initialize
+    ros::WallDuration(1.0).sleep();
+
+    ASSERT_EQ(pick_place_planner::pick(group), moveit::planning_interface::MoveItErrorCode::SUCCESS);
+
+    ros::WallDuration(1.0).sleep();
+
+    ASSERT_EQ(pick_place_planner::place(group), moveit::planning_interface::MoveItErrorCode::SUCCESS);
+
+}
+
+
+int main(int argc, char** argv)
+{
+    ros::init(argc, argv, "panda_arm_pick_place_test");
+    ::testing::InitGoogleTest(&argc, argv);
+
+    int result = RUN_ALL_TESTS();
+
+    return result;
+}
+
+