{"id":178,"date":"2019-03-12T11:33:09","date_gmt":"2019-03-12T11:33:09","guid":{"rendered":"http:\/\/erdalpekel.de\/?p=178"},"modified":"2019-03-12T12:46:34","modified_gmt":"2019-03-12T12:46:34","slug":"publish-a-box-at-the-robot-arm-in-gazebo","status":"publish","type":"post","link":"https:\/\/erdalpekel.de\/?p=178","title":{"rendered":"Attach a box to the robot hand in Gazebo"},"content":{"rendered":"\n<p>In the second article of this series we added motion planning constraints on MoveIt! in order to prevent collisions with objects in the robots environment. In this post we are going to publish a simple box at the hand of the panda robot that will make the validation tasks like movement or camera calibration possible in the simulation.<\/p>\n\n\n\n<p>The box can be published by <\/p>\n\n\n\n<ol class=\"wp-block-list\"><li>Loading the box model into gazebo at startup,<\/li><li>subscribing to the joint states of panda robot,<\/li><li>calculating the hands current position in the world coordinate system and<\/li><li>publishing the new coordinates of the box to the intended Gazebo topic.<\/li><\/ol>\n\n\n\n<h3 class=\"wp-block-heading\">1. Loading the box into Gazebo at startup<\/h3>\n\n\n\n<p>The box model is contained in the file <em>box.xacro<\/em>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"jsx\" class=\"language-jsx line-numbers\">&lt;?xml version=\"1.0\"?>\n &lt;robot xmlns:xacro=\"http:\/\/www.ros.org\/wiki\/xacro\" name=\"simple_box\">\n    &lt;link name=\"object_base_link\">\n    &lt;\/link>\n\n    &lt;joint name=\"object_base_joint\" type=\"fixed\">\n        &lt;parent link=\"object_base_link\"\/>\n        &lt;child link=\"object_link\"\/>\n        &lt;axis xyz=\"0 0 1\" \/>\n        &lt;origin xyz=\"0 0 0\" rpy=\"0 0 0\"\/>\n    &lt;\/joint>\n \n   &lt;link name=\"object_link\">\n     &lt;inertial>\n       &lt;origin xyz=\"0 0 0\" \/>\n       &lt;mass value=\"1.0\" \/>\n       &lt;inertia  ixx=\"1.0\" ixy=\"0.0\"  ixz=\"0.0\"  iyy=\"100.0\"  iyz=\"0.0\"  izz=\"1.0\" \/>\n     &lt;\/inertial>\n     &lt;visual>\n       &lt;origin xyz=\"0 0 0\"\/>\n       &lt;geometry>\n         &lt;box size=\"0.04 0.04 0.08\" \/>\n        &lt;\/geometry>\n     &lt;\/visual>\n     &lt;collision>\n       &lt;origin xyz=\"0 0 0\"\/>\n       &lt;geometry>\n         &lt;box size=\"0.04 0.04 0.08\" \/>\n       &lt;\/geometry>\n     &lt;\/collision>\n   &lt;\/link>\n\n   &lt;gazebo reference=\"object_base_link\">\n    &lt;gravity>0&lt;\/gravity>\n   &lt;\/gazebo>\n\n   &lt;gazebo reference=\"object_link\">\n     &lt;material>Gazebo\/Blue&lt;\/material>\n   &lt;\/gazebo>\n &lt;\/robot><\/code><\/pre>\n\n\n\n<p>We will create a launch file <em>box.launch<\/em>, load this xacro file and also add a <em>robot_state_publisher<\/em> that will publish the box state to <em>tf<\/em>. Finally we spawn the box model in Gazebo:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"jsx\" class=\"language-jsx\">&lt;launch>\n    &lt;param name=\"box_description\" command=\"$(find xacro)\/xacro --inorder $(find panda_simulation)\/models\/box.xacro\"\/>\n    &lt;node name=\"box_state_publisher\" pkg=\"robot_state_publisher\" type=\"robot_state_publisher\" args=\"robot_description:=box_description\" \/>\n    &lt;node name=\"spawn_object\" pkg=\"gazebo_ros\" type=\"spawn_model\" args=\"-param box_description -urdf -model box\"\/>\n\n\n    &lt;!-- launch node -->\n    &lt;node pkg=\"panda_simulation\" type=\"box_publisher_node\" name=\"box_publisher_node\" \/>\n&lt;\/launch><\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">2. Subscribing to the joint states of panda robot <\/h3>\n\n\n\n<p>We will now create a new node called box_publisher and subscribe to the joint states of the panda robot, so that we can update the box position when the robot moves:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"cpp\" class=\"language-cpp\">ros::Subscriber joint_states_sub = node_handle.subscribe(\"\/panda\/joint_states\", 1, jointStatesCallback);<\/code><\/pre>\n\n\n\n<p>We will define the <em>jointStatesCallback<\/em> function that handles the updated robot hand position below.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">3. Calculating the hands current position in the world coordinate system<\/h3>\n\n\n\n<p>We also want to load the robot&#8217;s kinematic model so that we can calculate the transform of the hand relative to a reference frame (the world frame in our case):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"cpp\" class=\"language-cpp\">robot_model_loader::RobotModelLoader robot_model_loader(\"robot_description\");\nkinematic_model = robot_model_loader.getModel();\nkinematic_state = robot_state::RobotStatePtr(new robot_state::RobotState(kinematic_model));<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">4. Publishing the new coordinates of the box to the intended Gazebo topic<\/h3>\n\n\n\n<p>For this step we will create a publisher in the main function that is able to communicate the update box position and rotation to Gazebo:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"cpp\" class=\"language-cpp\">gazebo_model_state_pub = node_handle.advertise&lt;gazebo_msgs::ModelState>(\"\/gazebo\/set_model_state\", 1);<\/code><\/pre>\n\n\n\n<p>We will now define the core functionality of this node in the <em>jointStatesCallback<\/em> function. Its first part updates the kinematic state that we instantiated in the main function with the current joint values and retrieves the transform of the robot&#8217;s last link as <em>Eigen::Affine3d<\/em>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"cpp\" class=\"language-cpp\">const robot_state::JointModelGroup *joint_model_group = kinematic_model->getJointModelGroup(\"panda_arm\");\nconst std::vector&lt;std::string> &amp;joint_names = joint_model_group->getJointModelNames();\n\nstd::vector&lt;double> joint_states;\nfor (size_t i = 0; i &lt; joint_states_current.position.size() - 2; ++i) {\n  joint_states.push_back(joint_states_current.position[i + 2]);\n}\nkinematic_state->setJointGroupPositions(joint_model_group, joint_states);\n\nconst Eigen::Affine3d &amp;end_effector_state = kinematic_state->getGlobalLinkTransform(\"panda_link8\");<\/code><\/pre>\n\n\n\n<p>Now that we have the transform of the last link we face a major issue: We need to add the hands offset to this transform, otherwise we would literally place the object in the hand which would drive the Gazebo dynamics engine crazy. I will set this value to 12 cm for the hand and add 4 cm additionally for the finger afterwards. The final tranform is calculated with an <em>Eigen::Affine3d<\/em> that adds an offset along the z-axis of <em>panda_link8<\/em>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"cpp\" class=\"language-cpp\">double end_effector_z_offset = PANDA_ARM_TO_HAND_OFFSET + PANDA_HAND_TO_FINGER_OFFSET;\nEigen::Affine3d tmp_transform(Eigen::Translation3d(Eigen::Vector3d(0.0, 0.0, end_effector_z_offset)));\n\nEigen::Affine3d newState = end_effector_state * tmp_transform;<\/code><\/pre>\n\n\n\n<p>Finally, we will set this transform as the box transform in Gazebo by publishing with the publisher that we created before. The rotation needs to be set as a Quaternion so we will first convert it into an <em>Eigen::Quaterniond<\/em>. The final message is an instance of gazebo_msgs::ModelState. We set its reference frame to <em>world<\/em>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"cpp\" class=\"language-cpp\">geometry_msgs::Pose pose;\npose.position.x = newState.translation().x();\npose.position.y = newState.translation().y();\npose.position.z = newState.translation().z();\n\nEigen::Quaterniond quat(newState.rotation());\npose.orientation.w = quat.w();\npose.orientation.x = quat.x();\npose.orientation.y = quat.y();\npose.orientation.z = quat.z();\n\nROS_DEBUG_STREAM(\"translation\" &lt;&lt; std::endl &lt;&lt; newState.translation());\nROS_DEBUG_STREAM(\"rotation\" &lt;&lt; std::endl &lt;&lt; newState.rotation());\n\ngazebo_msgs::ModelState model_state;\n\/\/ This string results from the spawn_urdf call in the box.launch file argument: -model box\nmodel_state.model_name = std::string(\"box\");\nmodel_state.pose = pose;\nmodel_state.reference_frame = std::string(\"world\");\n\ngazebo_model_state_pub.publish(model_state);<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Results<\/h2>\n\n\n\n<p>The following two lines will start the simulation and add the box:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code lang=\"bash\" class=\"language-bash\">roslaunch panda_simulation simulation.launch\nroslaunch panda_simulation box.launch<\/code><\/pre>\n\n\n\n<p>I have also added a Visual Studio Code task for each of these launch files. You can read more about my ROS development workflow and the VS Code tasks in my previous <a href=\"https:\/\/erdalpekel.de\/?p=157\">blog post<\/a>.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img fetchpriority=\"high\" decoding=\"async\" width=\"614\" height=\"508\" src=\"https:\/\/erdalpekel.de\/wp-content\/uploads\/2019\/03\/gazebo_box.png\" alt=\"\" class=\"wp-image-185\" srcset=\"https:\/\/erdalpekel.de\/wp-content\/uploads\/2019\/03\/gazebo_box.png 614w, https:\/\/erdalpekel.de\/wp-content\/uploads\/2019\/03\/gazebo_box-300x248.png 300w\" sizes=\"(max-width: 614px) 100vw, 614px\" \/><figcaption>Publishing a box at the robot hand in Gazebo: Screenshot of static robot<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" width=\"904\" height=\"708\" src=\"https:\/\/erdalpekel.de\/wp-content\/uploads\/2019\/03\/gazebo_box-1.gif\" alt=\"\" class=\"wp-image-189\"\/><figcaption>Publishing a box at the robot hand in Gazebo: GIF of moving robot<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" width=\"904\" height=\"708\" src=\"https:\/\/erdalpekel.de\/wp-content\/uploads\/2019\/03\/gazebo_box-2.gif\" alt=\"\" class=\"wp-image-190\"\/><figcaption> Publishing a box at the robot hand in Gazebo: GIF of moving robot (2)<\/figcaption><\/figure>\n\n\n\n<p>The custom <a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/erdalpekel\/panda_simulation\" target=\"_blank\">ROS package<\/a> as well as the modified <a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/erdalpekel\/franka_ros\" target=\"_blank\">franka_ros<\/a> and <a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/erdalpekel\/panda_moveit_config\" target=\"_blank\">panda_moveit_config<\/a> repositories that are needed for the simulation are available in my <a rel=\"noreferrer noopener\" href=\"https:\/\/github.com\/erdalpekel\" target=\"_blank\">GitHub profile<\/a>.<\/p>\n\n\n\n<p>The next part of this series will be about implementing a ROS node that calibrates the robot at the goal position. For this we will add an RGB camera to the GAZEBO simulation environment and analyze the box&#8217;s position with the <a href=\"https:\/\/opencv.org\/\">OpenCV library<\/a> within the captured RGB image.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this post we are going to attach a simple box to the hand of Panda robot in the Gazebo simulation environment.<\/p>\n","protected":false},"author":1,"featured_media":194,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[10,6,5,3,8,7,4],"tags":[],"class_list":["post-178","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-c","category-gazebo","category-robot-operating-system-ros","category-robotics","category-ros","category-simulation","category-software-development"],"_links":{"self":[{"href":"https:\/\/erdalpekel.de\/index.php?rest_route=\/wp\/v2\/posts\/178","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/erdalpekel.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/erdalpekel.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/erdalpekel.de\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/erdalpekel.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=178"}],"version-history":[{"count":17,"href":"https:\/\/erdalpekel.de\/index.php?rest_route=\/wp\/v2\/posts\/178\/revisions"}],"predecessor-version":[{"id":203,"href":"https:\/\/erdalpekel.de\/index.php?rest_route=\/wp\/v2\/posts\/178\/revisions\/203"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/erdalpekel.de\/index.php?rest_route=\/wp\/v2\/media\/194"}],"wp:attachment":[{"href":"https:\/\/erdalpekel.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=178"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/erdalpekel.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=178"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/erdalpekel.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=178"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}