{"id":660,"date":"2021-06-29T05:54:40","date_gmt":"2021-06-29T09:54:40","guid":{"rendered":"https:\/\/blogs.sw.siemens.com\/plm-components\/?p=660"},"modified":"2026-03-26T08:03:21","modified_gmt":"2026-03-26T12:03:21","slug":"kineoworks-step-by-step-4-pick-place","status":"publish","type":"post","link":"https:\/\/blogs.sw.siemens.com\/plm-components\/kineoworks-step-by-step-4-pick-place\/","title":{"rendered":"KineoWorks step-by-step #4: pick &#038; place"},"content":{"rendered":"\n<p><a href=\"https:\/\/www.plm.automation.siemens.com\/global\/en\/products\/plm-components\/kineo.html\" target=\"_blank\" rel=\"noreferrer noopener\">KineoWorks<\/a><a href=\"https:\/\/www.plm.automation.siemens.com\/global\/fr\/products\/plm-components\/kineo.html\" target=\"_blank\" rel=\"noreferrer noopener\"> <\/a>is a software component that automatically computes collision-free motion, solving complex path-planning problems in applications such as robotic collision-free trajectory optimization. In this series of articles, Etienne Ferr\u00e9, Development Director of Kineo components, describes some of the key steps that you can easily implement to develop a sophisticated robotics simulation.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">Part 4: Pick &amp; Place<\/h1>\n\n\n\n<p>So far in this series, we have described processes for&nbsp;<a href=\"https:\/\/blogs.sw.siemens.com\/plm-components\/kineoworks%e2%80%afstep-by-step-path-planning\/\">path planning<\/a>,&nbsp;<a href=\"https:\/\/blogs.sw.siemens.com\/plm-components\/kineoworks-step-by-step-building-your-robot-with-kwik\/\">building a robot<\/a> and <a href=\"https:\/\/blogs.sw.siemens.com\/plm-components\/kineoworks-step-by-step-working-with-trajectories\/\">working with trajectories<\/a>. The final post of this series walks you through a simple pick-and-place scenario in which a robot moves objects from one conveyor to another. It also illustrates the use of the&nbsp;<em>Robot Factory<\/em> library&nbsp; to create a 6-DOF robot with a gripper tool.<\/p>\n\n\n\n<p>The solution consists of two tasks:<\/p>\n\n\n\n<ol class=\"wp-block-list\" type=\"1\"><li>Creating the system and configuring the collision scene.<\/li><li>Defining the problem and its stages.<\/li><\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">Creating the Main System<\/h2>\n\n\n\n<p>The main system is just an empty container that will allow us to group the robot and the part together in a common system.<\/p>\n\n\n\n<p>Self-collision testing for the robot is configured in the robot factory library for the robot, so no such configuration is needed here for creating the standard system. <\/p>\n\n\n\n<div class=\"wp-block-image\"><figure class=\"aligncenter size-large is-resized\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/10\/2021\/03\/PickPlace2.png\" alt=\"pick and place robot\" class=\"wp-image-661\" width=\"590\" height=\"431\" srcset=\"https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/10\/2021\/03\/PickPlace2.png 786w, https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/10\/2021\/03\/PickPlace2-600x438.png 600w, https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/10\/2021\/03\/PickPlace2-768x561.png 768w\" sizes=\"auto, (max-width: 590px) 100vw, 590px\" \/><\/figure><\/div>\n\n\n\n<h3 class=\"wp-block-heading\">Creating the Robot<\/h3>\n\n\n\n<p>You can create a 6-DOF robot and gripper tool with our Robot Factory library using the following code:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>void CkttPickAndPlace::makeRobot()\n{\n  \/\/ Make the robot\n  CkwsRobotShPtr robot = CkttRobotFactory::makeRobot();\n  m_system-&gt;attachSystem(\"systemBase\", robot, \"robot\");\n  \/\/ Move flange position with tcp geometry at the middle of the gripper clamps.\n  robot-&gt;flange()-&gt;currentRigidPosition(robot-&gt;flange()-&gt;currentPosition() * \nCkitMat4::fromTranslation(0, 0, 170));\n  robot-&gt;flange()-&gt;mountingMode(CkwsHandler::STICKY);\n  \/\/ Make the gripper\n  CkwsSystemShPtr gripper = CkttToolFactory::makeGripper();\n  CkitMat4 gripperPosition = robot-&gt;flange()-&gt;currentPosition() * CkitMat4::fromBryantDegrees(0, 0, -170, 0, 0, 90);\n  gripper-&gt;rootJoint()-&gt;setCurrentRigidPosition(gripperPosition);\n  robot-&gt;attachSystem(\"flange\", gripper, \"gripper\");\n  \/\/ Add collision tests between robot and gripper\n  robot-&gt;addCollisionTestsForJointAndSystem(\"base\", \"gripper\", CkwsScene::FAIL_ON_EXISTING_TEST, true) KIT_MUST_SUCCEED;\n  robot-&gt;addCollisionTestsForJointAndSystem(\"joint1\", \"gripper\", CkwsScene::FAIL_ON_EXISTING_TEST, true) KIT_MUST_SUCCEED;\n  robot-&gt;addCollisionTestsForJointAndSystem(\"joint2\", \"gripper\", CkwsScene::FAIL_ON_EXISTING_TEST, true) KIT_MUST_SUCCEED;\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Creating the Pick-and-Place Scenario<\/h3>\n\n\n\n<p>Next, define the preliminary settings to obtain the start and end configurations of the main system:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Define the pick and place positions<\/li><li>Compute the optimal gripper opening<\/li><li>Create the part to be moved<\/li><li>Create any obstacles in the scene<\/li><\/ul>\n\n\n\n<pre class=\"wp-block-code\"><code>void CkttPickAndPlace::makePickAndPlaceScenario()\n{\n  \/\/ Pick and place pos\n  m_pickPos = CkitMat4::fromBryantDegrees(485, 120, 476, -180, 0.0, 0.0);\n  m_placePos = CkitMat4::fromBryantDegrees(120, -485, 476, 180, 0.0, 0.0);\n  \/\/ Retrieve the rank of the gripper control dof for later use\n  m_system-&gt;getRankOfDof(m_system-&gt;jointWithName(\"robot.gripper.gripperControl\")-&gt;dof(0), m_ctrlGripperDofRank);\n  \/\/ Search for the gripper opening value\n  searchForBestGripperOpening();\n  \/\/ Make the movable part \n  makeMovablePart();\n  \/\/ Make Obstacles\n  makeObstacles();\n  \n  \/\/ Get start configuration\n  m_startConfig = CkwsConfig(m_system);\n  m_system-&gt;getCurrentConfig(m_startConfig);\n  m_startConfig.dofValue(m_ctrlGripperDofRank, GRIPPER_OPEN);\n  \/\/ Get end configuration\n  size_t positionerRank = 0;\n  m_endConfig = CkwsConfig(m_system);\n  m_system-&gt;getCurrentConfig(m_endConfig);\n  m_system-&gt;getRankOfDof(m_system-&gt;system(\"movablePart\")-&gt;positioner()-&gt;dof(0), positionerRank);\n  m_endConfig.dofValue(positionerRank,   m_placePos.translation()&#91;0] - m_pickPos.translation()&#91;0]);\n  m_endConfig.dofValue(positionerRank+1, m_placePos.translation()&#91;1] - m_pickPos.translation()&#91;1]);\n  m_endConfig.dofValue(positionerRank+2, m_placePos.translation()&#91;2] - m_pickPos.translation()&#91;2]);\n  m_endConfig.dofValue(m_ctrlGripperDofRank, GRIPPER_OPEN);\n}<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Configuring the Stages<\/h2>\n\n\n\n<p>Stages of the problem are all based on variants of our initial system.<\/p>\n\n\n\n<p>Here are the variants you will be using:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Configuration <span class=\"has-inline-color has-pale-pink-color\">m_startConfig:<\/span>&nbsp;the initial position<\/li><li>System&nbsp;<code><span class=\"has-inline-color has-pale-pink-color\">m_system:<\/span><\/code>&nbsp;robot in joint motion; everything else frozen<\/li><li>System&nbsp;<code><span class=\"has-inline-color has-pale-pink-color\">m_systemWithPartAttached:<\/span><\/code>&nbsp;robot in joint motion; gripper frozen; part attached to robot<\/li><li>Configuration&nbsp;<code><span class=\"has-inline-color has-pale-pink-color\">m_endConfig:<\/span><\/code>&nbsp;variant of the system that represents the permitted final states<\/li><\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Initial Position<\/h3>\n\n\n\n<p>The initial configuration is defined as the robot in candle position, the gripper open and the movable part on the input conveyor.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><span class=\"has-inline-color has-black-color\">  \/\/ Get start configuration\n  m_startConfig = CkwsConfig(m_system);\n  m_system-&gt;getCurrentConfig(m_startConfig);\n  m_startConfig.dofValue(m_ctrlGripperDofRank, GRIPPER_OPEN);<\/span><\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">System without Attached Part<\/h3>\n\n\n\n<p>For this case you can use a system that is specially configured with a robot that can move freely from one position to another. Here, the system is represented by the<span class=\"has-inline-color has-pale-pink-color\">&nbsp;<code>m_system<\/code><\/span>&nbsp;variable.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code><code>void CkttPickAndPlace::makeMainSystem()\n{\n  \/\/ Make the main system\n  m_system = CkwsSystem::create();\n  CkwsJointShPtr systemBase = CkwsJoint::create(CkwsKEAnchor::create());\n  m_system-&gt;setRootJoint(systemBase);\n  systemBase-&gt;name(\"systemBase\");\n}<\/code><\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">System with Attached Part<\/h3>\n\n\n\n<p>Next, create a copy of the system in which the robot can move freely from one position to another and the part is already picked using the function below. You will use it later in the construction of the problem for moving the part from the pick position to the place position. The robot will be in joint motion. To attach the objects and move them from one conveyor to the other,&nbsp;<span class=\"has-inline-color has-pale-pink-color\">CkwsPositioner<\/span>,&nbsp;<span class=\"has-inline-color has-pale-pink-color\">CkwsHandle<\/span>&nbsp;and&nbsp;<span class=\"has-inline-color has-pale-pink-color\">CkwsHandler<\/span>&nbsp;objects are used<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>void CkttPickAndPlace::makeSystemWithPartAttached()\n{\n  m_systemWithPartAttached = CkwsSystem::createCopy(m_system);\n  CkwsHandlerShPtr robotHandler = m_systemWithPartAttached-&gt;robot(\"robot\")-&gt;flange();\n  CkwsHandleShPtr movablePartHandle = m_systemWithPartAttached-&gt;system(\"movablePart\")-&gt;positioner()-&gt;handle(0);\n  applyPickConfig(m_systemWithPartAttached);\n  KIT_ASSERT_SUCCESS(robotHandler-&gt;mountHandle(movablePartHandle));\n  KIT_ASSERT_SUCCESS(m_systemWithPartAttached-&gt;removeCollisionTestsForSystems(\"robot.gripper\", \"movablePart\"));\n}<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Final Position<\/h3>\n\n\n\n<p>The end position is defined as the robot in candle position, with the gripper open and the movable part on the output conveyor.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>  \/\/ Get end configuration\n  size_t positionerRank = 0;\n  m_endConfig = CkwsConfig(m_system);\n  m_system-&gt;getCurrentConfig(m_endConfig);\n  m_system-&gt;getRankOfDof(m_system-&gt;system(\"movablePart\")-&gt;positioner()-&gt;dof(0), positionerRank);\n  m_endConfig.dofValue(positionerRank,   m_placePos.translation()&#91;0] - m_pickPos.translation()&#91;0]);\n  m_endConfig.dofValue(positionerRank+1, m_placePos.translation()&#91;1] - m_pickPos.translation()&#91;1]);\n  m_endConfig.dofValue(positionerRank+2, m_placePos.translation()&#91;2] - m_pickPos.translation()&#91;2]);\n  m_endConfig.dofValue(m_ctrlGripperDofRank, GRIPPER_OPEN);<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Solving the Problem <\/h2>\n\n\n\n<p>In KineoWorks, a <em>problem<\/em> is a complex task that is described and solved in a sequence of stages. Each stage is a stage of the system, plus additional constraints that are specific to problem stages and not part of the system itself.<\/p>\n\n\n\n<p>In this section the opening and closing of the tool is not considered. You will use the configuration and clones of the system that you obtained previously. The <em>problem<\/em> will be created and each stage of the resolution will be configured as shown in the following subsections.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Initial Position<\/h3>\n\n\n\n<p>Start position is defined as the robot in candle position, with the gripper open and the movable part on the input conveyor.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>  mainProblem-&gt;addStage(m_startConfig);<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Moving to the Pick Position<\/h3>\n\n\n\n<p>In this stage, there is no particular configuration and the robot can move freely from start to pick position. Since neither the part nor the gripper should move, you will need to freeze them. Freezing a system or joint locks it to the current value: since the previous step defined the part position, it will stay where it is.<\/p>\n\n\n\n<p>You do not need to explicitly create a step for the moment the robot picks the part, since this step will be automatically deduced by KineoWorks as the intersection of the stage where the robot approaches the part and the stage where the robot moves it.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>  mainProblem-&gt;addStage()\n    -&gt;freezeSystem(\"movablePart\")\n    -&gt;freezeJoint(\"robot.gripper.gripperControl\");<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Moving the Part to the Place Position<\/h3>\n\n\n\n<p>In this stage the robot must move freely in order to move the part from the Pick position to the Place position. The robot in this system already has the part attached. In addition, since the gripper should not move while carrying the part, you will need to freeze the gripper motion.<\/p>\n\n\n\n<p>As in the previous step, the moment the robot drops the part will be computed as the intersection of this stage and the next one.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>  mainProblem-&gt;addStageFromSystem(m_systemWithPartAttached)\n    -&gt;freezeJoint(\"robot.gripper.gripperControl\");<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Moving to back to Home Position<\/h3>\n\n\n\n<p>Once the part has arrived on the output conveyor, the robot must return to its home position. This means that everything except the robot should remain still. So in this stage you will allow the robot to move freely from the place position to the end position, freezing the part and the gripper.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>  mainProblem-&gt;addStage()\n    -&gt;freezeSystem(\"movablePart\")\n    -&gt;freezeJoint(\"robot.gripper.gripperControl\");<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Final Position<\/h3>\n\n\n\n<p>Here, you simply use the final state that was previously defined. <\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>mainProblem-&gt;addStage(m_endConfig);<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Running the Problem<\/h2>\n\n\n\n<p>In order to find the path described above, you can apply the problem to a path planning operation. Moreover, it is possible to run this operation either in a blocking or in a non-blocking way, in terms of user interaction. Both options are described below.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Blocking Path Planning<\/h3>\n\n\n\n<p>This is the easiest way to solve a problem. However, the call is blocking and if there is no solution, it will never return. It is not recommended for production code; however, it is useful in the prototyping stage:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>CkwsHybridPathShPtr solution = problem-&gt;solve();<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Non-Blocking Path Planning<\/h3>\n\n\n\n<p>In order to perform atomic computations, it is possible to control the flow of path planning steps. This procedure is the recommended procedure when integrating path planning into an application in order to keep the application responsive. In other words, this technique works the same as the blocking procedure, but allows the user to keep control.<\/p>\n\n\n\n<p>In practice, you will use the fact that problems are <em>operations<\/em>. An operation is an iterative process that takes some input and generates some output.<\/p>\n\n\n\n<p>You may refer to the example below.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>bool userWantsToStop = false;\nCkitParameterMapShPtr inputParams;\nCkitParameterMapShPtr outputParams = CkitParameterMap::create();\nktStatus success = problem-&gt;start(inputParams, outputParams);\nif(KD_OK == success)\n{\n  bool goOn = true;\n  do\n  {\n    if(userWantsToStop) \/\/ can be set to true by a Cancel button\n    {\n      problem-&gt;abort();\n    }\n    success = problem-&gt;step(goOn);\n  }\n  while(goOn);\n}\nCkwsHybridPathShPtr solution;\nif(KD_OK == success)\n{\n  outputParams-&gt;getShPtr&lt; CkwsHybridPath &gt;(\"com.kineocam.problem.result-hybrid-path\", solution);\n}<\/code><\/pre>\n\n\n\n<p>This allows you to keep the UI responsive without using threads and enables you to implement a Cancel button, to retrieve information like the completion ratio for displaying a progress bar, etc&#8230;<\/p>\n\n\n\n<figure class=\"wp-block-video\"><video controls src=\"https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/10\/2021\/03\/pickplace.mp4\"><\/video><\/figure>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>The final post of this series walks you through a simple pick-and-place scenario in which a robot moves objects from one conveyor to another.<\/p>\n","protected":false},"author":36655,"featured_media":782,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"spanish_translation":"","french_translation":"","german_translation":"","italian_translation":"","polish_translation":"","japanese_translation":"","chinese_translation":"","footnotes":""},"categories":[94],"tags":[2],"industry":[83],"product":[],"coauthors":[410],"class_list":["post-660","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tips-tricks","tag-kineo","industry-software-development"],"featured_image_url":"https:\/\/blogs.sw.siemens.com\/wp-content\/uploads\/sites\/10\/2021\/06\/kineoworks-step-by-step-pick-place-main.png","_links":{"self":[{"href":"https:\/\/blogs.sw.siemens.com\/plm-components\/wp-json\/wp\/v2\/posts\/660","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blogs.sw.siemens.com\/plm-components\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.sw.siemens.com\/plm-components\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/plm-components\/wp-json\/wp\/v2\/users\/36655"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/plm-components\/wp-json\/wp\/v2\/comments?post=660"}],"version-history":[{"count":5,"href":"https:\/\/blogs.sw.siemens.com\/plm-components\/wp-json\/wp\/v2\/posts\/660\/revisions"}],"predecessor-version":[{"id":790,"href":"https:\/\/blogs.sw.siemens.com\/plm-components\/wp-json\/wp\/v2\/posts\/660\/revisions\/790"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/plm-components\/wp-json\/wp\/v2\/media\/782"}],"wp:attachment":[{"href":"https:\/\/blogs.sw.siemens.com\/plm-components\/wp-json\/wp\/v2\/media?parent=660"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/plm-components\/wp-json\/wp\/v2\/categories?post=660"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/plm-components\/wp-json\/wp\/v2\/tags?post=660"},{"taxonomy":"industry","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/plm-components\/wp-json\/wp\/v2\/industry?post=660"},{"taxonomy":"product","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/plm-components\/wp-json\/wp\/v2\/product?post=660"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/blogs.sw.siemens.com\/plm-components\/wp-json\/wp\/v2\/coauthors?post=660"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}