From c7bb57fee65e80ae2793ee07f1701247475d18a9 Mon Sep 17 00:00:00 2001 From: AdamAnouar <43108465+AdamAnouar@users.noreply.github.com> Date: Sat, 1 Apr 2023 01:59:01 +0200 Subject: [PATCH] Assignment_03_Adam_Anouar --- .../assignment_03/adam_anouar/Capture.PNG | Bin 0 -> 48464 bytes .../adam_anouar/assignment_03.ghx | 6005 +++++++++++++++++ 2 files changed, 6005 insertions(+) create mode 100644 lecture_04/assignment_03/adam_anouar/Capture.PNG create mode 100644 lecture_04/assignment_03/adam_anouar/assignment_03.ghx diff --git a/lecture_04/assignment_03/adam_anouar/Capture.PNG b/lecture_04/assignment_03/adam_anouar/Capture.PNG new file mode 100644 index 0000000000000000000000000000000000000000..247e52ab7250d4836ff1880b4cea7bc2a129f8ad GIT binary patch literal 48464 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 w6hr}M&~tow;@qrC81Qhx9(~{8xw5h + + + + + + + 0 + 2 + 2 + + + + + + + 1 + 0 + 7 + + + + + + c4f913db-409d-41a9-88e1-f6f90989047d + Shaded + 1 + + 100;150;0;0 + + + 100;0;150;0 + + + + + + 637527254194888879 + + assignment_03.ghx + + + + + 0 + + + + + + 114 + 92 + + 0.377149671 + + + + + 0 + + + + + + + 0 + + + + + 2 + + + + + GhPython, Version=7.28.23058.3001, Culture=neutral, PublicKeyToken=null + 7.28.23058.3001 + + 00000000-0000-0000-0000-000000000000 + + + + + + + Pufferfish, Version=3.0.0.0, Culture=neutral, PublicKeyToken=null + 3.0.0.0 + Michael Pryor + 1c9de8a1-315f-4c56-af06-8f69fee80a7a + Pufferfish + 3.0.0.0 + + + + + + + 58 + + + + + c552a431-af5b-46a9-a8a4-0fcbc27ef596 + Group + + + + + 1 + + 150;170;135;255 + + A group of Grasshopper objects + bfe572e7-d997-4c3c-8488-4e03d01804ea + b278407c-79b3-49ef-a2c8-ee682b33d9ef + 6fe2e9d2-130c-4a02-b347-a1c6b831fc5a + 9a4be73c-3082-4c74-be27-41c7c1688c53 + 4 + 3dd78fb5-3c65-4715-b2db-b9489d44fd71 + Group + + + + + + + + + + + c552a431-af5b-46a9-a8a4-0fcbc27ef596 + Group + + + + + 1 + + 150;170;135;255 + + A group of Grasshopper objects + d5ffda3e-a3ab-4688-9de8-1d9d9e2789e3 + 4b0a07e0-a378-4f92-8f0a-6c1f1fb427f2 + 1d31a79f-b7ba-423f-944c-23f606999dae + eaec99d4-5f03-4209-953f-02aee1235de3 + 4a5bf47a-b0af-4831-a451-6b776364bb7e + 5 + 5a4ca04f-0f26-4978-bcce-92edaa3c4b8e + Group + + + + + + + + + + + c552a431-af5b-46a9-a8a4-0fcbc27ef596 + Group + + + + + 1 + + 150;170;135;255 + + A group of Grasshopper objects + 781a5de8-c54c-4805-927f-519a45da032f + 4b0a07e0-a378-4f92-8f0a-6c1f1fb427f2 + 1d31a79f-b7ba-423f-944c-23f606999dae + eaec99d4-5f03-4209-953f-02aee1235de3 + 4a5bf47a-b0af-4831-a451-6b776364bb7e + 20c7f0ab-fd13-4bd7-a130-c6fe893d2a0b + 47c152bc-c823-4835-aad3-3bf5c281e892 + d19cf29a-0512-4632-b4e0-ecc00c5b8487 + 2ceac33a-a5ff-4a42-8067-32e6a2c7fbee + ac227038-eb23-4cb5-94d8-f63bb92375a4 + b3787c61-219b-4ed9-b49f-1e7dd56236b1 + b395bfb0-5717-46c4-924c-a3ba167b1e0d + 4e66fe1b-29b3-4955-9524-ca986decd9ac + 78471367-17af-4599-8661-808ba87f82a6 + bfa816f1-e4c0-482e-9515-4b540fd2f427 + 82091d9c-f1c0-4207-8d3d-b1dca673d5df + 5d051c72-528a-498d-a91b-f91e344562b4 + baea3a7f-42ad-4480-b62c-39cd2f8c2e8a + 18 + 8b8d6fbf-db19-4267-9188-c4fdd76620b6 + Group + + + + + + + + + + + 8ec86459-bf01-4409-baee-174d0d2b13d0 + Data + + + + + Contains a collection of generic data + 4e66fe1b-29b3-4955-9524-ca986decd9ac + Data + Robot + false + 846547a4-0964-4bea-b2e5-d3fd03e0ff69 + 1 + + + + + + 1254 + 168 + 50 + 24 + + + 1279.353 + 180.9772 + + + + + + + + + + 7f5c6c55-f846-4a08-9c9a-cfdc285cc6fe + Scribble + + + + + false + + 46.70692 + 119.7138 + + + 272.0458 + 119.7138 + + + 272.0458 + 139.8124 + + + 46.70692 + 139.8124 + + A quick note + Cambria + 82091d9c-f1c0-4207-8d3d-b1dca673d5df + false + Scribble + Scribble + 22 + 1) Load robot from ROS + + + + + + 41.70692 + 114.7138 + 235.3389 + 30.09864 + + + 46.70692 + 119.7138 + + + + + + + + + + 8ec86459-bf01-4409-baee-174d0d2b13d0 + Data + + + + + Contains a collection of generic data + aacb02be-ffde-4997-b910-3a5670a6e5b1 + Data + Target planes + false + 44d4a187-3a93-413f-992e-d4cc7e2e19ad + 1 + + + + + + 1240 + 476 + 50 + 24 + + + 1265.041 + 488.8133 + + + + + + + + + + c552a431-af5b-46a9-a8a4-0fcbc27ef596 + Group + + + + + 1 + + 150;240;218;146 + + A group of Grasshopper objects + 0c3c0677-cbf3-46be-b539-e48399697bc7 + de6b7a53-8f17-48cc-bb14-1aedc473dd1c + 04770360-9eb5-44e4-911f-142deec44bdc + aacb02be-ffde-4997-b910-3a5670a6e5b1 + 50ee1702-2c6a-4092-b68b-7fd9ec30c129 + 9dbe68e7-ae2d-4df4-89a9-ae0ec5759854 + d17c9d6f-7bf6-411c-816c-4c1caad151b9 + 37fef6aa-0c60-4da4-9d31-1ae0bdd95cd2 + d6cabb95-93fe-48fe-9b1b-2070fdd10e56 + 3974a64b-9fea-4aa6-a9ad-21315ef8260a + b171143f-e5e1-4bc8-92f7-eb329037f691 + 11 + cf91e427-c398-45be-b915-f55275cc67b7 + Group + + + + + + + + + + + 8ec86459-bf01-4409-baee-174d0d2b13d0 + Data + + + + + Contains a collection of generic data + d385349b-7e03-4362-b9d0-eacd34e2562b + Data + Pickup plane + false + 3a86f18b-7506-4d48-8a5c-6048a1108886 + 1 + + + + + + 1241 + 348 + 50 + 24 + + + 1266.929 + 360.6916 + + + + + + + + + + c552a431-af5b-46a9-a8a4-0fcbc27ef596 + Group + + + + + 1 + + 150;240;218;146 + + A group of Grasshopper objects + d385349b-7e03-4362-b9d0-eacd34e2562b + 66c3b06d-1415-476b-875b-53498de1860a + c9e84bc7-5f07-46ef-9e42-32f7d85d0c13 + 39a429c7-2480-4ff8-8f4c-5bd8a47369a7 + 224add91-1cc7-47af-8c77-af2d42147144 + ff0bbdd7-eb5b-4ed6-a652-505db2c0ac8c + 13d747bd-3e05-4a41-8ea0-75bad3d5248b + dd675efd-9233-4ad4-bb47-4b8f4932cc90 + 68575641-3532-400d-95f0-a0242e51e625 + eb5acce9-f665-4261-a8bc-ffd4947a64da + 0bd900d0-2016-4c53-af3b-1c52cf194064 + 11 + 3c032157-3bf9-40ee-9b12-e4e807d15ccc + Group + + + + + + + + + + + 7f5c6c55-f846-4a08-9c9a-cfdc285cc6fe + Scribble + + + + + false + + 46.70692 + 281.4785 + + + 269.3387 + 281.4785 + + + 269.3387 + 301.5771 + + + 46.70692 + 301.5771 + + A quick note + Cambria + ff0bbdd7-eb5b-4ed6-a652-505db2c0ac8c + false + Scribble + Scribble + 22 + 2) Define pick-up plane + + + + + + 41.70692 + 276.4785 + 232.6318 + 30.09863 + + + 46.70692 + 281.4785 + + + + + + + + + + 7f5c6c55-f846-4a08-9c9a-cfdc285cc6fe + Scribble + + + + + false + + 46.70692 + 431.5476 + + + 263.9891 + 431.5476 + + + 263.9891 + 451.7751 + + + 46.70692 + 451.7751 + + A quick note + Cambria + 9dbe68e7-ae2d-4df4-89a9-ae0ec5759854 + false + Scribble + Scribble + 22 + 3) Define target planes + + + + + + 41.70692 + 426.5476 + 227.2822 + 30.22754 + + + 46.70692 + 431.5476 + + + + + + + + + + 410755b1-224a-4c1e-a407-bf32fb45ea7e + 00000000-0000-0000-0000-000000000000 + Robot Visualize + + + + + """ +Visualizes the robot. + +COMPAS FAB v0.27.0 +""" +from compas.artists import Artist +from compas.geometry import Frame +from compas.geometry import Transformation +from compas_fab.robots import PlanningScene +from ghpythonlib.componentbase import executingcomponent as component + + +class RobotVisualize(component): + def RunScript( + self, + robot, + group, + configuration, + show_visual, + show_collision, + show_frames, + show_base_frame, + show_end_effector_frame, + show_cm, + show_acm, + ): + + visual = None + collision = None + collision_meshes = None + attached_meshes = None + frames = None + base_frame = None + ee_frame = None + + if robot: + show_visual = True if show_visual is None else show_visual + show_cm = True if show_cm is None else show_cm + show_acm = True if show_acm is None else show_acm + configuration = configuration or robot.zero_configuration() + + robot.update(configuration, visual=show_visual, collision=show_collision) + compas_frames = robot.transformed_frames(configuration, group) + + if show_visual: + visual = robot.artist.draw_visual() + + if show_collision: + collision = robot.artist.draw_collision() + + if show_base_frame: + base_compas_frame = compas_frames[0] + artist = Artist(base_compas_frame) + base_frame = artist.draw() + + if show_end_effector_frame: + ee_compas_frame = robot.forward_kinematics( + configuration, group, options=dict(solver="model") + ) + artist = Artist(ee_compas_frame) + ee_frame = artist.draw() + + if show_frames: + frames = [] + for compas_frame in compas_frames[1:]: + artist = Artist(compas_frame) + frame = artist.draw() + frames.append(frame) + + if show_cm or show_acm: + scene = PlanningScene(robot) + scene = robot.client.get_planning_scene() + + collision_meshes = [] + attached_meshes = [] + + if show_cm: + for co in scene.world.collision_objects: + header = co.header + frame_id = header.frame_id + cms = co.to_collision_meshes() + + for cm in cms: + if cm.frame != Frame.worldXY(): + t = Transformation.from_frame(cm.frame) + mesh = cm.mesh.transformed(t) + else: + mesh = cm.mesh + + collision_meshes.append(Artist(mesh).draw()) + + if show_acm: + for aco in scene.robot_state.attached_collision_objects: + for acm in aco.to_attached_collision_meshes(): + frame_id = aco.object["header"]["frame_id"] + frame = robot.forward_kinematics( + configuration, options=dict(link=frame_id) + ) + t = Transformation.from_frame(frame) + + # Local CM frame + if ( + acm.collision_mesh.frame + and acm.collision_mesh.frame != Frame.worldXY() + ): + t = t * Transformation.from_frame( + acm.collision_mesh.frame + ) + + mesh = acm.collision_mesh.mesh.transformed(t) + + attached_meshes.append(Artist(mesh).draw()) + + return ( + visual, + collision, + collision_meshes, + attached_meshes, + frames, + base_frame, + ee_frame, + ) + + Visualizes the robot. +COMPAS FAB v0.27.0 + true + true + 2 + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAALDwAACw8BkvkDpQAAAdhJREFUSEu1lLFKA0EQhlUIQVBMOhGLgGAtxAcIYmmRJpWNrZ2dhSCWqURtxC6VRSofIYWlhS8QyBMEOzvP/zt2jtm9VSLEg+9ud2bnn9nZu1spiuJfyRqXSdb4F3ZvX1vigmfOXzP8FQm/iEJ8iH7qjyZUIUZiIgjseb9HvjMxE4jbE4jt2Lo0CGca0BOI3Ti8nzGFdYTFv9cShAWlUzyK6zC/E9aGHFFbND8Q1c5TBwHPgiQPYU4C2uZFPVEbNa/aA9wqg5wIE2RP6AuSsH2DAzV/2Q49aRPtwzYzTW5VBXKwC+sjIvQ+qiiso52IWSG00B941CKfwA7UDs0qqiUJ61nnD5z10ffALe2hb48x8Ws88lEIhWWLqBnC4jQBRIUsStYosdxbUx6croFgAJcWo6st5sE+ruw28EiMbfs3xbjBnxWKEw8quw1SEEvEgaQtCQydWJv1zjb3OpFoisT8G2KMJNINYlBWq8t2NfQakWCKxH48cAlNg+CT8AmPvUYkCArmq82JRmydnJeCa+sbX42dvfsgPk31ogko2L7kX9m+GpcJYLXR/AzjqD0QTUDBCyWA5v5hlSTQTfWiCSiQX4X91H5l8+jUzgHeUi2oGZZN1rg8ipVvhzuVIxcFIsQAAAAASUVORK5CYII= + + false + 7a58f25a-3dc8-4dfa-bf0f-35404273569e + true + true + Robot Visualize + Robot Visualize + + + + + + 2356 + 139 + 257 + 204 + + + 2503 + 241 + + + + + + 10 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 7 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + + + + + true + The robot. + 439bbb30-bb2a-4f39-bfd6-8205cd93fd09 + robot + robot + true + 0 + true + 619d4216-bdfd-4395-b679-83b02e397c53 + 1 + 87f87f55-5b71-41f4-8aea-21d494016f81 + 2 + + + + + + 2358 + 141 + 130 + 20 + + + 2424.5 + 151 + + + + + + + + true + The planning group used for end-effector and base visualization. + ad36f822-0439-4ba3-b51a-c348f6f591ec + group + group + true + 0 + true + 0 + 37261734-eec7-4f50-b6a8-b8d1f3c4396b + + + + + + 2358 + 161 + 130 + 20 + + + 2424.5 + 171 + + + + + + + + true + The robot's full configuration. + 9fb95b19-f673-4906-9998-b63a5811ea88 + configuration + configuration + true + 0 + true + 4ca3f55b-10fb-41c3-9f24-2b4809b96eeb + 1 + 87f87f55-5b71-41f4-8aea-21d494016f81 + + + + + + 2358 + 181 + 130 + 20 + + + 2424.5 + 191 + + + + + + + + true + Whether or not to show the robot's visual meshes. + 22d8ace2-7a15-4a22-9430-2f721280765e + show_visual + show_visual + true + 0 + true + 0 + d60527f5-b5af-4ef6-8970-5f96fe412559 + + + + + + 2358 + 201 + 130 + 20 + + + 2424.5 + 211 + + + + + + + + true + Whether or not to show the robot's collision meshes. + ad827435-eaa9-47db-8456-0f04c22dde3a + show_collision + show_collision + true + 0 + true + 0 + d60527f5-b5af-4ef6-8970-5f96fe412559 + + + + + + 2358 + 221 + 130 + 20 + + + 2424.5 + 231 + + + + + + + + true + Whether or not to show the robot's joint frames. + 35824dc3-741e-4a85-9d9f-f350f6328850 + show_frames + show_frames + true + 0 + true + 0 + d60527f5-b5af-4ef6-8970-5f96fe412559 + + + + + + 2358 + 241 + 130 + 20 + + + 2424.5 + 251 + + + + + + + + true + Whether or not to show the robot's base frame. + 5c36de85-2908-4ed4-8bfb-be05a5fc15a0 + show_base_frame + show_base_frame + true + 0 + true + 0 + d60527f5-b5af-4ef6-8970-5f96fe412559 + + + + + + 2358 + 261 + 130 + 20 + + + 2424.5 + 271 + + + + + + + + true + Whether or not to show the robot's end-effector frame. + 43679585-4dff-44fc-8144-04d51b6597a3 + show_end_effector_frame + show_end_effector_frame + true + 0 + true + 0 + d60527f5-b5af-4ef6-8970-5f96fe412559 + + + + + + 2358 + 281 + 130 + 20 + + + 2424.5 + 291 + + + + + + + + true + Whether or not to show the collision meshes (if any). + b0245b8b-4b25-480e-8434-34500dd361dd + show_cm + show_cm + true + 0 + true + 0 + d60527f5-b5af-4ef6-8970-5f96fe412559 + + + + + + 2358 + 301 + 130 + 20 + + + 2424.5 + 311 + + + + + + + + true + Whether or not to show the attached collision meshes (if any). + c258dd5f-afd6-4742-9840-e8ae6df45c59 + show_acm + show_acm + true + 0 + true + 0 + d60527f5-b5af-4ef6-8970-5f96fe412559 + + + + + + 2358 + 321 + 130 + 20 + + + 2424.5 + 331 + + + + + + + + Rhino meshes of the robot's visual geometry (if any). + b51fd205-41de-4772-b77b-54118aa40c2c + visual + visual + false + 0 + + + + + + 2518 + 141 + 93 + 28 + + + 2564.5 + 155.2857 + + + + + + + + Rhino meshes of the robot's collision geometry (if any). + 3fd4309e-805a-4b2a-8b39-fb39cda51d21 + collision + collision + false + 0 + + + + + + 2518 + 169 + 93 + 29 + + + 2564.5 + 183.8571 + + + + + + + + Rhino meshes of the scene's collision meshes (if any). + ba8f5aaf-7d4f-4021-b0f3-328651e5f766 + collision_meshes + collision_meshes + false + 0 + + + + + + 2518 + 198 + 93 + 28 + + + 2564.5 + 212.4286 + + + + + + + + Rhino meshes of the scene's attached collision meshes (if any). + 00b4652c-1968-4bef-b124-5b86f4dc25bc + attached_meshes + attached_meshes + false + 0 + + + + + + 2518 + 226 + 93 + 29 + + + 2564.5 + 241 + + + + + + + + The robot's joint frames as Rhino planes (if any). + 243eeb3c-e1ad-4233-9a1a-b0ec9fd1c962 + frames + frames + false + 0 + + + + + + 2518 + 255 + 93 + 28 + + + 2564.5 + 269.5714 + + + + + + + + The robot's base frame as a Rhino plane (if any). + 91fd1995-e0da-4f23-a4c6-afeefc044dee + base_frame + base_frame + false + 0 + + + + + + 2518 + 283 + 93 + 29 + + + 2564.5 + 298.1429 + + + + + + + + The robot's end-effector frame as a Rhino plane (if any). + 5a2c4711-ae2f-4f0f-b633-afc7c8fccfd2 + ee_frame + ee_frame + false + 0 + + + + + + 2518 + 312 + 93 + 29 + + + 2564.5 + 326.7143 + + + + + + + + + + + + + + 7f5c6c55-f846-4a08-9c9a-cfdc285cc6fe + Scribble + + + + + false + + 46.70692 + 651.1613 + + + 317.5712 + 651.1613 + + + 317.5712 + 671.2599 + + + 46.70692 + 671.2599 + + A quick note + Cambria + fccb98c9-c6e5-4caa-8384-ca0ddf85fd1f + false + Scribble + Scribble + 22 + 4) Solve IK for pick-up plane + + + + + + 41.70692 + 646.1613 + 280.8643 + 30.09863 + + + 46.70692 + 651.1613 + + + + + + + + + + 8ec86459-bf01-4409-baee-174d0d2b13d0 + Data + + + + + Contains a collection of generic data + 02bc89eb-6961-419b-a5c7-ecf1d7beb296 + Data + Pickup config + false + 1d8af690-69c5-4c9f-b553-1a05f97e8281 + 1 + + + + + + 1242 + 734 + 50 + 24 + + + 1267.176 + 746.6949 + + + + + + + + + + 7f5c6c55-f846-4a08-9c9a-cfdc285cc6fe + Scribble + + + + + false + + 73.59002 + 675.2849 + + + 238.8635 + 675.2849 + + + 238.8635 + 689.9958 + + + 73.59002 + 689.9958 + + A quick note + Cambria + 6e5b9db8-970d-4e5b-bf3d-6ec1c492b072 + false + Scribble + Scribble + 16 + Results in pickup config + + + + + + 68.59002 + 670.2849 + 175.2734 + 24.71094 + + + 73.59002 + 675.2849 + + + + + + + + + + c552a431-af5b-46a9-a8a4-0fcbc27ef596 + Group + + + + + 1 + + 150;240;218;146 + + A group of Grasshopper objects + fccb98c9-c6e5-4caa-8384-ca0ddf85fd1f + 02bc89eb-6961-419b-a5c7-ecf1d7beb296 + 6e5b9db8-970d-4e5b-bf3d-6ec1c492b072 + fb4c5d39-e0a5-4c45-b606-72de43c589ac + b96209a7-93e4-4212-b096-c83e82b4da7b + 98209ace-c305-4683-b351-d9b9daf31e36 + df49cbca-ec61-4dc7-8c55-18e7e63a3700 + 5c90bf29-e6aa-4294-8822-68408c74406a + 8 + 3962a36b-d451-45d1-acb9-c99a5708db90 + Group + + + + + + + + + + + 00027467-0d24-4fa7-b178-8dc0ac5f42ec + Value List + + + + + Provides a list of preset values to choose from + 137a3255-a54e-4e4c-a9c3-e6d902b2a8bb + 2 + 3 + Value List + List + false + 0 + + + + + 0 + Pickup config + false + + + + + 1 + Trajectory + true + + + + + + 1591 + 171 + 123 + 22 + + + + + + + + + + eeafc956-268e-461d-8e73-ee05c6f72c01 + Stream Filter + + + + + Filters a collection of input streams + 471af287-d88e-43f4-9bb2-98daa088f633 + Stream Filter + Filter + + + + + + 2046 + 170 + 77 + 64 + + + 2078 + 202 + + + + + + 3 + 2e3ab970-8545-46bb-836c-1c11e5610bce + 8ec86459-bf01-4409-baee-174d0d2b13d0 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + 1 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + + + + + Index of Gate stream + fde7ac2c-1b3d-473c-8b2b-4addc4d52e1a + Gate + G + false + 137a3255-a54e-4e4c-a9c3-e6d902b2a8bb + 1 + + + + + + 2048 + 172 + 15 + 20 + + + 2057 + 182 + + + + + + 1 + + + + + 1 + {0} + + + + + 0 + + + + + + + + + + + 2 + Input stream at index 0 + e6a67ce5-d55f-4ec2-a44c-573291be81a5 + false + Stream 0 + 0 + true + a38644b3-ef3b-4bc2-bf1d-8843907a4a1f + 1 + + + + + + 2048 + 192 + 15 + 20 + + + 2057 + 202 + + + + + + + + 2 + Input stream at index 1 + 14985ec3-7977-426f-bc6b-ad27afc61e04 + false + Stream 1 + 1 + true + a4b043bc-8e30-4b4c-bb40-e7f42497696d + 1 + + + + + + 2048 + 212 + 15 + 20 + + + 2057 + 222 + + + + + + + + 2 + Filtered stream + ddfd1927-535b-4f08-acf1-f1762fa62a54 + false + Stream + S(1) + false + 0 + + + + + + 2093 + 172 + 28 + 60 + + + 2107 + 202 + + + + + + + + + + + + + + c552a431-af5b-46a9-a8a4-0fcbc27ef596 + Group + + + + + 1 + + 150;0;155;194 + + A group of Grasshopper objects + 7a58f25a-3dc8-4dfa-bf0f-35404273569e + 137a3255-a54e-4e4c-a9c3-e6d902b2a8bb + 471af287-d88e-43f4-9bb2-98daa088f633 + 766f518e-d29b-4814-a406-a45e5ded4a64 + e4b338fe-125d-4929-92e1-4e17c08f9b3b + f53212f5-507f-4bda-b372-34bf2b7020a3 + a38644b3-ef3b-4bc2-bf1d-8843907a4a1f + e9d20ac9-0dbc-44cb-9f48-878ae446678f + 619d4216-bdfd-4395-b679-83b02e397c53 + df7fb28b-31b3-40c8-ab8a-ec66c12ea055 + 10 + ca0ff086-508f-4122-8664-195d1a456efe + Group + + + + + + + + + + + 7f5c6c55-f846-4a08-9c9a-cfdc285cc6fe + Scribble + + + + + false + + 1582.769 + 120.3864 + + + 1707.131 + 120.3864 + + + 1707.131 + 135.9303 + + + 1582.769 + 135.9303 + + A quick note + Cambria + 766f518e-d29b-4814-a406-a45e5ded4a64 + false + Scribble + Scribble + 22 + Visualization + + + + + + 1577.769 + 115.3864 + 134.3623 + 25.54395 + + + 1582.769 + 120.3864 + + + + + + + + + + 8ec86459-bf01-4409-baee-174d0d2b13d0 + Data + + + + + Contains a collection of generic data + b96209a7-93e4-4212-b096-c83e82b4da7b + Data + Pickup plane + false + d385349b-7e03-4362-b9d0-eacd34e2562b + 1 + 2 + + + + + + 201 + 724 + 50 + 24 + + + 226.7217 + 736.2081 + + + + + + + + + + 8ec86459-bf01-4409-baee-174d0d2b13d0 + Data + + + + + Contains a collection of generic data + 98209ace-c305-4683-b351-d9b9daf31e36 + Data + Robot + false + 4e66fe1b-29b3-4955-9524-ca986decd9ac + 1 + 2 + + + + + + 70 + 709 + 50 + 24 + + + 95.8785 + 721.4962 + + + + + + + + + + 7f5c6c55-f846-4a08-9c9a-cfdc285cc6fe + Scribble + + + + + false + + 46.70692 + 861.2363 + + + 379.9403 + 861.2363 + + + 379.9403 + 881.4102 + + + 46.70692 + 881.4102 + + A quick note + Cambria + ba94b074-3f68-4274-8b84-f87aa5c4cb3e + false + Scribble + Scribble + 22 + 5) Plan trajectory to selected plane + + + + + + 41.70692 + 856.2363 + 343.2334 + 30.17383 + + + 46.70692 + 861.2363 + + + + + + + + + + 7f5c6c55-f846-4a08-9c9a-cfdc285cc6fe + Scribble + + + + + false + + 75.11641 + 888.1221 + + + 314.8351 + 888.1221 + + + 314.8351 + 902.833 + + + 75.11641 + 902.833 + + A quick note + Cambria + 01b0a494-be40-47b6-bdc4-7c92967b9f38 + false + Scribble + Scribble + 16 + From pickup config to target plane + + + + + + 70.11641 + 883.1221 + 249.7187 + 24.71094 + + + 75.11641 + 888.1221 + + + + + + + + + + 8ec86459-bf01-4409-baee-174d0d2b13d0 + Data + + + + + Contains a collection of generic data + 55db7485-e593-4762-a166-64303d976c7a + Data + Target planes + false + aacb02be-ffde-4997-b910-3a5670a6e5b1 + 1 + 2 + + + + + + 81 + 988 + 50 + 24 + + + 106.0911 + 1000.628 + + + + + + + + + + 8ec86459-bf01-4409-baee-174d0d2b13d0 + Data + + + + + Contains a collection of generic data + 538c02c6-6b3b-4712-a784-dda0bc63f847 + Data + Robot + false + 4e66fe1b-29b3-4955-9524-ca986decd9ac + 1 + 2 + + + + + + 82 + 931 + 50 + 24 + + + 107.0106 + 943.0975 + + + + + + + + + + 8ec86459-bf01-4409-baee-174d0d2b13d0 + Data + + + + + Contains a collection of generic data + c666c109-2ccb-4c50-90cd-00130af76eaa + Data + Pickup config + false + 02bc89eb-6961-419b-a5c7-ecf1d7beb296 + 1 + 2 + + + + + + 81 + 959 + 50 + 24 + + + 106.6234 + 971.4724 + + + + + + + + + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider + + + + + Numeric slider for single values + e4b338fe-125d-4929-92e1-4e17c08f9b3b + Number Slider + + false + 0 + + + + + + 1591 + 205 + 160 + 20 + + + 1591.409 + 205.586 + + + + + + 3 + 1 + 1 + 100 + 0 + 0 + 21 + + + + + + + + + 59daf374-bc21-4a5e-8282-5504fb7ae9ae + List Item + + + + + 0 + Retrieve a specific item from a list. + df7fb28b-31b3-40c8-ab8a-ec66c12ea055 + List Item + Item + + + + + + 2163 + 190 + 64 + 64 + + + 2197 + 222 + + + + + + 3 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + 2e3ab970-8545-46bb-836c-1c11e5610bce + cb95db89-6165-43b6-9c41-5702bc5bf137 + 1 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + + + + + 1 + Base list + 39c89e61-bc93-43d0-a501-c5bba7a3da6e + List + L + false + ddfd1927-535b-4f08-acf1-f1762fa62a54 + 1 + + + + + + 2165 + 192 + 17 + 20 + + + 2175 + 202 + + + + + + + + Item index + 83d287eb-3d9d-4785-b735-156766b364e7 + Index + i + false + e4b338fe-125d-4929-92e1-4e17c08f9b3b + 1 + + + + + + 2165 + 212 + 17 + 20 + + + 2175 + 222 + + + + + + 1 + + + + + 1 + {0} + + + + + 0 + + + + + + + + + + + Wrap index to list bounds + 60da4aea-66d4-49fc-8aa9-a5189edc913b + Wrap + W + false + 0 + + + + + + 2165 + 232 + 17 + 20 + + + 2175 + 242 + + + + + + 1 + + + + + 1 + {0} + + + + + true + + + + + + + + + + + Item at {i'} + 4ca3f55b-10fb-41c3-9f24-2b4809b96eeb + false + Item + i + false + 0 + + + + + + 2212 + 192 + 13 + 60 + + + 2218.5 + 222 + + + + + + + + + + + + + + 8ec86459-bf01-4409-baee-174d0d2b13d0 + Data + + + + + Contains a collection of generic data + bcf27a28-24e5-4d31-8438-444d7fe511cb + Data + Trajectory + false + 4e17b2ad-e9af-41eb-b6a5-7585e1f6e333 + 1 + + + + + + 1246 + 954 + 50 + 24 + + + 1271.31 + 966.862 + + + + + + + + + + 410755b1-224a-4c1e-a407-bf32fb45ea7e + 00000000-0000-0000-0000-000000000000 + GhPython Script + + + + + configs = trajectory.points + GhPython provides a Python script component + + 182 + 182 + + + 558 + 571 + + true + true + 2 + false + f53212f5-507f-4bda-b372-34bf2b7020a3 + false + true + GhPython Script + get configs + + + + + + 1704 + 315 + 132 + 28 + + + 1774 + 329 + + + + + + 1 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 1 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + + + + + true + Script variable Python + 50f68354-3c25-4a84-a5f7-ddaf267be516 + trajectory + trajectory + true + 0 + true + e9d20ac9-0dbc-44cb-9f48-878ae446678f + 1 + 87f87f55-5b71-41f4-8aea-21d494016f81 + + + + + + 1706 + 317 + 53 + 24 + + + 1734 + 329 + + + + + + + + Script output configs. + a4b043bc-8e30-4b4c-bb40-e7f42497696d + configs + configs + false + 0 + + + + + + 1789 + 317 + 45 + 24 + + + 1811.5 + 329 + + + + + + + + + + + + + + 8ec86459-bf01-4409-baee-174d0d2b13d0 + Data + + + + + Contains a collection of generic data + a38644b3-ef3b-4bc2-bf1d-8843907a4a1f + Data + Pickup config + false + 02bc89eb-6961-419b-a5c7-ecf1d7beb296 + 1 + 2 + + + + + + 1605 + 298 + 50 + 24 + + + 1630.11 + 310.7518 + + + + + + + + + + 8ec86459-bf01-4409-baee-174d0d2b13d0 + Data + + + + + Contains a collection of generic data + e9d20ac9-0dbc-44cb-9f48-878ae446678f + Data + Trajectory + false + bcf27a28-24e5-4d31-8438-444d7fe511cb + 1 + 2 + + + + + + 1596 + 322 + 50 + 24 + + + 1621.626 + 334.0815 + + + + + + + + + + 8ec86459-bf01-4409-baee-174d0d2b13d0 + Data + + + + + Contains a collection of generic data + 619d4216-bdfd-4395-b679-83b02e397c53 + Data + Robot + false + 4e66fe1b-29b3-4955-9524-ca986decd9ac + 1 + 2 + + + + + + 1591 + 273 + 50 + 24 + + + 1616.464 + 285.9058 + + + + + + + + + + c552a431-af5b-46a9-a8a4-0fcbc27ef596 + Group + + + + + 1 + + 150;240;218;146 + + A group of Grasshopper objects + ba94b074-3f68-4274-8b84-f87aa5c4cb3e + 01b0a494-be40-47b6-bdc4-7c92967b9f38 + 55db7485-e593-4762-a166-64303d976c7a + 97392278-c93e-4240-86e9-5e59dc2eb992 + 4a09e38e-e49b-43a1-809e-f310b5a4c3e2 + 1f8b3c58-8382-468d-8885-a179a0ad05e0 + 538c02c6-6b3b-4712-a784-dda0bc63f847 + c666c109-2ccb-4c50-90cd-00130af76eaa + 13b3eb29-3c6d-41ba-80fe-d6214ebc9674 + 9d4e5cda-5bb7-42fe-acfa-968fa6c6c067 + cd76efff-9d02-4eb1-b6dd-080d6a0e6d4d + bcf27a28-24e5-4d31-8438-444d7fe511cb + d93333c1-6121-4133-94e5-b1cdbd79792d + 8a1cd44e-8393-4da1-ba94-6a53dd4e3f37 + 54d5165c-c7b9-4b61-a3f4-725adfe6cedb + 15 + 4c3c7466-b1c2-4942-9ac0-63cb70a5b6b7 + Group + + + + + + + + + + + 59e0b89a-e487-49f8-bab8-b5bab16be14c + Panel + + + + + A panel for custom notes and text values + ecc8c71a-07d9-4980-90b1-a3cd2f8081a6 + Panel + + false + 0 + 0 + Define multiple target planes in any way you like, for example, +reference a curve from Rhino, divide it and assign a plane to each point + +Make sure all planes are oriented in a way that makes sense +for the robot to reach it as well. + + + + + + -530 + 485 + 523 + 96 + + 0 + 0 + 0 + + + + + 3 + + 255;255;250;90 + + true + true + true + false + false + true + + + + + Courier New + 8 + + + + + + + + + + + 59e0b89a-e487-49f8-bab8-b5bab16be14c + Panel + + + + + A panel for custom notes and text values + fb166dfc-4abf-4aa5-9ecf-d86922966dfe + Panel + + false + 0 + 0 + Define one pick-up plane in any way you like, +for example, reference a point from Rhino and assign a plane to it. + +Make sure the plane is oriented in a way that makes sense +for the robot to reach it. You can check this by observing the +results of the IK solution for this pickup-plane. + + + + + + -536 + 293 + 529 + 96 + + 0 + 0 + 0 + + -535.2353 + 293.4706 + + + + + + 3 + + 255;255;250;90 + + true + true + true + false + false + true + + + + + Courier New + 8 + + + + + + + + + + + 59e0b89a-e487-49f8-bab8-b5bab16be14c + Panel + + + + + A panel for custom notes and text values + c7cc41e4-23fe-4958-87c2-e75feb10ebac + Panel + + false + 0 + 0 + Load the robot from ROS. + +Make sure ROS/MoveIt is running before you start (ie. "Compose up"). + + + + + + -536 + 124 + 529 + 96 + + 0 + 0 + 0 + + -535.2353 + 124.4706 + + + + + + 3 + + 255;255;250;90 + + true + true + true + false + false + true + + + + + Courier New + 8 + + + + + + + + + + + 59e0b89a-e487-49f8-bab8-b5bab16be14c + Panel + + + + + A panel for custom notes and text values + 3f032319-94be-407d-8e0f-7615f6976834 + Panel + + false + 0 + 0 + Use inverse kinematics of the robot to find +a feasible configuration to reach the pickup plane. + +You can use the COMPAS FAB component or +code it in a GHPython component. + + + + + + -530 + 680 + 523 + 96 + + 0 + 0 + 0 + + -529.5882 + 680.8822 + + + + + + 3 + + 255;255;250;90 + + true + true + true + false + false + true + + + + + Courier New + 8 + + + + + + + + + + + 59e0b89a-e487-49f8-bab8-b5bab16be14c + Panel + + + + + A panel for custom notes and text values + 1f02a236-cf56-4437-8d21-1243b22a7b8e + Panel + + false + 0 + 0 + With the pickup config and a list of target planes, you are ready to compute the solution trajectory for each plane. + +First create a constraint from the selected plane, then use the plan free-space motion to calculate a trajectory. + + + + + + -530 + 942 + 523 + 96 + + 0 + 0 + 0 + + -529.353 + 942.6469 + + + + + + 3 + + 255;255;250;90 + + true + true + true + false + false + true + + + + + Courier New + 8 + + + + + + + + + + + 410755b1-224a-4c1e-a407-bf32fb45ea7e + 00000000-0000-0000-0000-000000000000 + ROS Connect + + + + + """ +Connect or disconnect to ROS. + +COMPAS FAB v0.27.0 +""" +from ghpythonlib.componentbase import executingcomponent as component +from scriptcontext import sticky as st + +from compas_fab.backends import RosClient +from compas_fab.ghpython.components import create_id + + +class ROSConnect(component): + def RunScript(self, ip, port, connect): + ros_client = None + + ip = ip or '127.0.0.1' + port = port or 9090 + + key = create_id(self, 'ros_client') + ros_client = st.get(key, None) + + if ros_client: + st[key].close() + if connect: + st[key] = RosClient(ip, port) + st[key].run(5) + + ros_client = st.get(key, None) + is_connected = ros_client.is_connected if ros_client else False + return (ros_client, is_connected) + + Connect or disconnect to ROS. +COMPAS FAB v0.27.0 + true + true + 2 + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAALEAAACxABrSO9dQAAAdZJREFUSEu1lD2O4kAQRrkBcwP2BnADfARuABEhcAMcEEyCQKuVCCEkY27A3ADCyUAimQyHm/V+r9bNNp5iSLwtPWF/9dvdZRohhP+KK9aJK9aJK9aJKzpk4k08W4XYiB/CYquJPJbX6zVMp9PQbrcV0XhIt9sN6/VaIVZoQLyXMGVC8piYXwp5jMfj0Gq1zK/f7yvUVsdLGnkRBV0RlHT2/g2WHH+KonmJI4PD4ZA6HwVFPd9IR1hTzWZTj76Tcjay1Wr1QWIKnE6n0Ov17DnhXeSiWnTJbvHZ7/d3BkNrg3E2m/2OBbiH4XCITkLg+YhNnMVtakRuib0CWgMMYlMUxetutzPH8vwZ00f+HB8auznHe6CxagDdnMt3ztPOkunAWYsiPcF3YYxGo19ZloXtdvtT78d4b9yDVpEmf8Eg8qiJt7gLCi0WC9v2IxjV6Mu9aU3SAh2MYhI1wZaPBMcZfwadl8n5oqX8Sya7OZkhgSJoge1Xu04pE/Ot3E4hTUQBmyDB+d7ZBIU4f4INBmE+n3/meR4ul8tS2pe4+5e/91CURRjH7BuYIIYCX/vf8fgqaKYFHxEvz6CZh8nBFUGLQl7nN7y4Kq5YJ65YJ65YJ65YH6HxB7b14P1B22tpAAAAAElFTkSuQmCC + + false + 5d051c72-528a-498d-a91b-f91e344562b4 + true + true + ROS Connect + ROS + + + + + + 329 + 114 + 153 + 64 + + + 392 + 146 + + + + + + 3 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 2 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + + + + + true + The ip address ROS. Defaults to 127.0.0.1. + 9f8ec376-61c8-4a5a-9978-8260b3433971 + ip + ip + true + 0 + true + 0 + 37261734-eec7-4f50-b6a8-b8d1f3c4396b + + + + + + 331 + 116 + 46 + 20 + + + 355.5 + 126 + + + + + + + + true + The port of ROS. Defaults to 9090. + 606cb857-159f-4994-b643-f4573ca19d5f + port + port + true + 0 + true + 0 + 48d01794-d3d8-4aef-990e-127168822244 + + + + + + 331 + 136 + 46 + 20 + + + 355.5 + 146 + + + + + + + + true + If True, connects to ROS. If False, disconnects from ROS. Defaults to False. + f3e97277-64e0-4595-adcd-93143d53f341 + connect + connect + true + 0 + true + f9dd4743-5ef1-4938-a2ce-b61e2f89ff71 + 1 + d60527f5-b5af-4ef6-8970-5f96fe412559 + + + + + + 331 + 156 + 46 + 20 + + + 355.5 + 166 + + + + + + + + The ROS client. + 1c3a0665-a31f-4f6b-a343-89073c77e7a7 + ros_client + ros_client + false + 0 + + + + + + 407 + 116 + 73 + 30 + + + 443.5 + 131 + + + + + + + + True if connection established. + 17ce31a9-caeb-4613-ab0b-fb88664811c6 + is_connected + is_connected + false + 0 + + + + + + 407 + 146 + 73 + 30 + + + 443.5 + 161 + + + + + + + + + + + + + + 2e78987b-9dfb-42a2-8b76-3923ac8bd91a + Boolean Toggle + + + + + Boolean (true/false) toggle + f9dd4743-5ef1-4938-a2ce-b61e2f89ff71 + Boolean Toggle + Toggle + false + 0 + true + + + + + + 106 + 163 + 104 + 22 + + + + + + + + + + 410755b1-224a-4c1e-a407-bf32fb45ea7e + 00000000-0000-0000-0000-000000000000 + ROS Robot + + + + + """ +Load robot directly from ROS. + +COMPAS FAB v0.27.0 +""" +from compas_ghpython.artists import RobotModelArtist +from ghpythonlib.componentbase import executingcomponent as component +from scriptcontext import sticky as st + +from compas_fab.ghpython.components import create_id + + +class ROSRobot(component): + def RunScript(self, ros_client, load): + key = create_id(self, 'robot') + + if ros_client and ros_client.is_connected and load: + # Load URDF from ROS + st[key] = ros_client.load_robot(load_geometry=True, precision='12f') + st[key].artist = RobotModelArtist(st[key].model) + + robot = st.get(key, None) + if robot: # client sometimes need to be restarted, without needing to reload geometry + robot.client = ros_client + return robot + + Load robot directly from ROS. +COMPAS FAB v0.27.0 + true + true + 2 + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAALEAAACxABrSO9dQAAAVtJREFUSEu9lMFRwzAQRVMCJaSElJASUgIlUAGTEhguXHPinBJSAiWkBDow/9n6ZmWtQzwYduaNpdVqtf5redN13Z+SOtckdS5B9iCeeKbrmXMJsrNg8CkOzXo1Gao5iYtg4z6uR2SP4iqY+Ans3Y5xk00sTjfsBcmOgbjOmMK2wvs/mgNKQL8o3sRzmb8Iy5BRySLbifHNpwsM3gWHvJY5ByAb44xKRtkoTz+vJkNiBn7CQXAIr29oqNd7OWTIhHxMrmNOD0oQb2EdSYL2VUUlDjlJ5kKQMDa8lahsdEPdNFfUHFLiiYsNJ766D9WG3lHLYy7TOCOjEArLi2gcQ7ATR2bvxC1yZ/7VjI1bQu4cXjt+KeaYxd8idQLJQmLDoelPbY7UaWTxCzGnLHaO1Glkv2546xhubUz2E8i2m+YxreP7Ji9htvmt4x8O4Ffhn9q93C/R2qTO9eg2XxfZxOCoCLXEAAAAAElFTkSuQmCC + + false + baea3a7f-42ad-4480-b62c-39cd2f8c2e8a + true + true + ROS Robot + Robot + + + + + + 525 + 137 + 124 + 44 + + + 595 + 159 + + + + + + 2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 1 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + + + + + true + The ROS client. + f7ba96f4-94e2-4197-b4a3-31f6a0ca2f34 + ros_client + ros_client + true + 0 + true + 1c3a0665-a31f-4f6b-a343-89073c77e7a7 + 1 + 87f87f55-5b71-41f4-8aea-21d494016f81 + + + + + + 527 + 139 + 53 + 20 + + + 555 + 149 + + + + + + + + true + If True, loads the robot from ROS. Defaults to False. + e89e10b5-2ece-44bd-87f9-1811ce89ed0b + load + load + true + 0 + true + f9dd4743-5ef1-4938-a2ce-b61e2f89ff71 + 1 + d60527f5-b5af-4ef6-8970-5f96fe412559 + + + + + + 527 + 159 + 53 + 20 + + + 555 + 169 + + + + + + + + The robot. + 846547a4-0964-4bea-b2e5-d3fd03e0ff69 + robot + robot + false + 0 + + + + + + 610 + 139 + 37 + 40 + + + 628.5 + 159 + + + + + + + + + + + + + + 410755b1-224a-4c1e-a407-bf32fb45ea7e + 00000000-0000-0000-0000-000000000000 + Inverse Kinematics + + + + + """ +Calculate the robot's inverse kinematic for a given plane. + +COMPAS FAB v0.27.0 +""" +from compas_rhino.conversions import RhinoPlane +from ghpythonlib.componentbase import executingcomponent as component + + +class InverseKinematics(component): + def RunScript(self, robot, plane, start_configuration, group): + configuration = None + if robot and robot.client and robot.client.is_connected and plane: + frame = RhinoPlane.from_geometry(plane).to_compas_frame() + configuration = robot.inverse_kinematics(frame, start_configuration, group) + return configuration + + Calculate the robot's inverse kinematic for a given plane. +COMPAS FAB v0.27.0 + true + true + 2 + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAALEAAACxABrSO9dQAAAYFJREFUSEu1lLFxwzAMRVWn8gApNIKKDOAubbqk1AgeQRP4NIJG0AgqMoCq1BpBGzD/ywANkbAt3dm4eyfwkwBEElIRQngprvhMXHEL7+ff0tNTXFFBkhqMIAgz6MG3+AcvzuKKDJRETDqBFjSgE005efEWV0QgEzJBl+gs/CdzZLTzHpmAoEqCe9VgNWjePj5/oHMn3B13xnV37yITJEEMhH0BOsrqWLBuuQfYEVR2btFTAQEDmHQMawCdyTyZzCYeAAeEfrz8VXKC5Mv2dQzrJFALWDyNtDFeHQXJ0yOybzcD3scJWJ3YnQyazytQSoHlkmG6Az5XfQ9jMTosbIveLkCQnG2qBRg8p2tk7iDzHFhiI2RBFpi+YWzZFFgFRlnHYs1q3g5SYL0E1t78FlyRwLh9OiTr76344iW5Xq57/lvJhaIogZ6psunX7JEL11azH1H8cPaSC9fE/EW04se+3ksu5MdDbrbpI3Lh0tf246H/ki7iv+Xoze/BFZ9HKP4BuwtzfPsUblIAAAAASUVORK5CYII= + + false + df49cbca-ec61-4dc7-8c55-18e7e63a3700 + true + true + Inverse Kinematics + IK + + + + + + 504 + 704 + 207 + 84 + + + 619 + 746 + + + + + + 4 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 1 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + + + + + true + The robot. + 249e3fc8-1590-4989-8d02-71555d17803d + robot + robot + true + 0 + true + 846547a4-0964-4bea-b2e5-d3fd03e0ff69 + 1 + 87f87f55-5b71-41f4-8aea-21d494016f81 + 2 + + + + + + 506 + 706 + 98 + 20 + + + 556.5 + 716 + + + + + + + + true + The plane or frame to calculate the inverse kinematic for. + 7f79fc84-f4dc-442f-b7ec-2c6ef6d32d53 + plane + plane + true + 0 + true + b96209a7-93e4-4212-b096-c83e82b4da7b + 1 + 87f87f55-5b71-41f4-8aea-21d494016f81 + + + + + + 506 + 726 + 98 + 20 + + + 556.5 + 736 + + + + + + + + true + If passed, calculates the inverse such that the joint positions differ the least from the start_configuration. Defaults to the zero configuration. + 8aab3d36-825a-4b59-a5df-f5a5a92c336a + start_configuration + start_configuration + true + 0 + true + 0 + 87f87f55-5b71-41f4-8aea-21d494016f81 + + + + + + 506 + 746 + 98 + 20 + + + 556.5 + 756 + + + + + + + + true + The planning group used for calculation. Defaults to the robot's main planning group. + fd831072-ab33-48dd-88f3-f5635811e6b2 + group + group + true + 0 + true + 0 + 37261734-eec7-4f50-b6a8-b8d1f3c4396b + + + + + + 506 + 766 + 98 + 20 + + + 556.5 + 776 + + + + + + + + The planning group's configuration. + 1d8af690-69c5-4c9f-b553-1a05f97e8281 + configuration + configuration + false + 0 + + + + + + 634 + 706 + 75 + 80 + + + 671.5 + 746 + + + + + + + + + + + + + + fbac3e32-f100-4292-8692-77240a42fd1a + Point + + + + + Contains a collection of three-dimensional points + 13d747bd-3e05-4a41-8ea0-75bad3d5248b + Point + Pt + false + 0 + + + + + + 315 + 294 + 50 + 24 + + + 340 + 306 + + + + + + 1 + + + + + 1 + {0} + + + + + + + 0.0788496805924328 + 0.563241716990942 + 0 + + + + + + + + + + + + + + cfb6b17f-ca82-4f5d-b604-d4f69f569de3 + Plane Normal + + + + + Create a plane perpendicular to a vector. + dd675efd-9233-4ad4-bb47-4b8f4932cc90 + Plane Normal + Pl + + + + + + 444 + 300 + 65 + 44 + + + 476 + 322 + + + + + + Origin of plane + a4967eb6-ce45-4b5a-a8bb-b57de9bc5816 + Origin + O + false + 13d747bd-3e05-4a41-8ea0-75bad3d5248b + 1 + + + + + + 446 + 302 + 15 + 20 + + + 455 + 312 + + + + + + 1 + + + + + 1 + {0} + + + + + + + 0 + 0 + 0 + + + + + + + + + + + + Z-Axis direction of plane + 6f2ccb4f-ad90-40cb-aa81-912ca1f36990 + Z-Axis + Z + false + 1f4c1d7b-92ac-410e-b8cf-de51d8691d13 + 1 + + + + + + 446 + 322 + 15 + 20 + + + 455 + 332 + + + + + + 1 + + + + + 1 + {0} + + + + + + 0 + 0 + 1 + + + + + + + + + + + + Plane definition + 3a86f18b-7506-4d48-8a5c-6048a1108886 + Plane + P + false + 0 + + + + + + 491 + 302 + 16 + 40 + + + 499 + 322 + + + + + + + + + + + + 9103c240-a6a9-4223-9b42-dbd19bf38e2b + Unit Z + + + + + Unit vector parallel to the world {z} axis. + 68575641-3532-400d-95f0-a0242e51e625 + Unit Z + Z + + + + + + 230 + 332 + 63 + 28 + + + 259 + 346 + + + + + + Unit multiplication + 1ec380b2-779c-4e5e-b32f-e1e05e1eaa2d + Factor + F + false + 0 + + + + + + 232 + 334 + 12 + 24 + + + 239.5 + 346 + + + + + + 1 + + + + + 1 + {0} + + + + + 1 + + + + + + + + + + + World {z} vector + 351348f7-2844-4518-aa54-7e8529b995cf + Unit vector + V + false + 0 + + + + + + 274 + 334 + 17 + 24 + + + 282.5 + 346 + + + + + + + + + + + + a3371040-e552-4bc8-b0ff-10a840258e88 + Negative + + + + + Compute the negative of a value. + eb5acce9-f665-4261-a8bc-ffd4947a64da + Negative + Neg + + + + + + 343 + 332 + 61 + 28 + + + 372 + 346 + + + + + + Input value + 28852126-05f6-43ae-8988-6d8909c2ffdf + Value + x + false + 351348f7-2844-4518-aa54-7e8529b995cf + 1 + + + + + + 345 + 334 + 12 + 24 + + + 352.5 + 346 + + + + + + + + Output value + 1f4c1d7b-92ac-410e-b8cf-de51d8691d13 + Result + y + false + 0 + + + + + + 387 + 334 + 15 + 24 + + + 394.5 + 346 + + + + + + + + + + + + d5967b9f-e8ee-436b-a8ad-29fdcecf32d5 + Curve + + + + + Contains a collection of generic curves + b171143f-e5e1-4bc8-92f7-eb329037f691 + Curve + Crv + false + 0 + + + + + + 205 + 462 + 50 + 24 + + + 230.4504 + 474.1136 + + + + + + 1 + + + + + 1 + {0} + + + + + -1 + + Y2BkYGD4DwQgGgR4mIBEWFBGZl6+c35ubn6ejkJYalFxZn6erbmekYWekbGBqYWesYGBoY6Cc2lOSWlRqm1eamlJUWKOjkJAaVJOZrJ3amVIfnZqnq2pqZGRhWGqpXmyuampqbEBK8gSSbDZeu6p+bmpJUWVen6lRUnFzqVFZaksQFn2MohlXIlFyRmZZanGKbmc+QWpeXkgVSwpiSWJIEUcHBxMIHcKqDMwGAFp18d8PJzMQAY/iMgEWsP0q56JIRbqqd//mRhEoP6TFFwfF8h9RXD/PwaBZkalD15SleJ/gPKqULUCzFCFINewMaCDD/YYQhDx/egiHNgVgsHO03c5+N89sd8Fpr/YT9vo0yuW+h+DBtlvIB4dV9Z7Zf+y+txSO7fXcPvPyHInLJW7YK/tlnb9NAdCfJKWe/maKQ/s34X//XY38Slc/J3J+s0CS57Yv1u/yKLh8UW4eP3DCfLtTq/sM74VF9pobIGLP13ZMrMn7bP9hWPZonmzFsPFb0naHv9fz9QA43Pj8ecoGAWEAQA= + + 00000000-0000-0000-0000-000000000000 + + + + + + + + + + + + + 2162e72e-72fc-4bf8-9459-d4d82fa8aa14 + Divide Curve + + + + + Divide a curve into equal length segments + true + 37fef6aa-0c60-4da4-9d31-1ae0bdd95cd2 + Divide Curve + Divide + + + + + + 293 + 443 + 65 + 64 + + + 325 + 475 + + + + + + Curve to divide + 17b7b741-c039-457b-bc69-9a5f2f8e5819 + Curve + C + false + b171143f-e5e1-4bc8-92f7-eb329037f691 + 1 + + + + + + 295 + 445 + 15 + 20 + + + 304 + 455 + + + + + + + + Number of segments + c4252d68-c3f0-4449-bc33-3963a1f5b379 + Count + N + false + 0 + + + + + + 295 + 465 + 15 + 20 + + + 304 + 475 + + + + + + 1 + + + + + 1 + {0} + + + + + 10 + + + + + + + + + + + Split segments at kinks + c67cd2ce-aeaf-48f1-b87d-ae648d16cb78 + Kinks + K + false + 0 + + + + + + 295 + 485 + 15 + 20 + + + 304 + 495 + + + + + + 1 + + + + + 1 + {0} + + + + + false + + + + + + + + + + + 1 + Division points + 02d756d0-695e-4b84-977a-5211a88fe540 + Points + P + false + 0 + + + + + + 340 + 445 + 16 + 20 + + + 348 + 455 + + + + + + + + 1 + Tangent vectors at division points + ff7cd25b-7346-40cf-93bd-b862456b2fad + Tangents + T + false + 0 + + + + + + 340 + 465 + 16 + 20 + + + 348 + 475 + + + + + + + + 1 + Parameter values at division points + 9f8a284b-b097-43d8-8703-768571059955 + Parameters + t + false + 0 + + + + + + 340 + 485 + 16 + 20 + + + 348 + 495 + + + + + + + + + + + + 2a5cfb31-028a-4b34-b4e1-9b20ae15312e + Cross Product + + + + + Compute vector cross product. + d6cabb95-93fe-48fe-9b1b-2070fdd10e56 + Cross Product + XProd + + + + + + 423 + 478 + 66 + 64 + + + 455 + 510 + + + + + + First vector + 7677fda3-a48e-4b19-9a38-3848beb2729e + Vector A + A + false + ff7cd25b-7346-40cf-93bd-b862456b2fad + 1 + + + + + + 425 + 480 + 15 + 20 + + + 434 + 490 + + + + + + + + Second vector + ab1ebaa3-5740-431c-8fc9-a779c8b99336 + Vector B + B + false + 351348f7-2844-4518-aa54-7e8529b995cf + 1 + + + + + + 425 + 500 + 15 + 20 + + + 434 + 510 + + + + + + + + Unitize output + 45f1c846-268d-49fd-a50d-dcd25e91cccc + Unitize + U + false + 0 + + + + + + 425 + 520 + 15 + 20 + + + 434 + 530 + + + + + + 1 + + + + + 1 + {0} + + + + + false + + + + + + + + + + + Cross product vector + 633bc054-2115-4c2b-8be8-c286377bce3d + Vector + V + false + 0 + + + + + + 470 + 480 + 17 + 30 + + + 478.5 + 495 + + + + + + + + Vector length + 8243a1a9-6216-4bc2-93b0-d7d17da9a8c7 + Length + L + false + 0 + + + + + + 470 + 510 + 17 + 30 + + + 478.5 + 525 + + + + + + + + + + + + bc3e379e-7206-4e7b-b63a-ff61f4b38a3e + Construct Plane + + + + + Construct a plane from an origin point and {x}, {y} axes. + true + 3974a64b-9fea-4aa6-a9ad-21315ef8260a + Construct Plane + Pl + + + + + + 527 + 443 + 68 + 64 + + + 559 + 475 + + + + + + Origin of plane + ada5ea08-627b-4ef2-9244-2c11db2d896f + Origin + O + false + 02d756d0-695e-4b84-977a-5211a88fe540 + 1 + + + + + + 529 + 445 + 15 + 20 + + + 538 + 455 + + + + + + 1 + + + + + 1 + {0} + + + + + + + 0 + 0 + 0 + + + + + + + + + + + + X-Axis direction of plane + 07101ef1-80e2-4825-a3da-9039e03fb50f + X-Axis + X + false + ff7cd25b-7346-40cf-93bd-b862456b2fad + 1 + + + + + + 529 + 465 + 15 + 20 + + + 538 + 475 + + + + + + 1 + + + + + 1 + {0} + + + + + + 1 + 0 + 0 + + + + + + + + + + + + Y-Axis direction of plane + c37c73c0-ad8c-442c-941a-484cdb43364c + Y-Axis + Y + false + 633bc054-2115-4c2b-8be8-c286377bce3d + 1 + + + + + + 529 + 485 + 15 + 20 + + + 538 + 495 + + + + + + 1 + + + + + 1 + {0} + + + + + + 0 + 1 + 0 + + + + + + + + + + + + Constructed plane + 44d4a187-3a93-413f-992e-d4cc7e2e19ad + Plane + Pl + false + 0 + + + + + + 574 + 445 + 19 + 60 + + + 583.5 + 475 + + + + + + + + + + + + 410755b1-224a-4c1e-a407-bf32fb45ea7e + 00000000-0000-0000-0000-000000000000 + Inverse Kinematics + + + + + """ +Calculate the robot's inverse kinematic for a given plane. + +COMPAS FAB v0.27.0 +""" +from compas_rhino.conversions import RhinoPlane +from ghpythonlib.componentbase import executingcomponent as component + + +class InverseKinematics(component): + def RunScript(self, robot, plane, start_configuration, group): + configuration = None + if robot and robot.client and robot.client.is_connected and plane: + frame = RhinoPlane.from_geometry(plane).to_compas_frame() + configuration = robot.inverse_kinematics(frame, start_configuration, group) + return configuration + + Calculate the robot's inverse kinematic for a given plane. +COMPAS FAB v0.27.0 + true + true + 2 + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAALDwAACw8BkvkDpQAAAYFJREFUSEu1lLFxwzAMRVWn8gApNIKKDOAubbqk1AgeQRP4NIJG0AgqMoCq1BpBGzD/ywANkbAt3dm4eyfwkwBEElIRQngprvhMXHEL7+ff0tNTXFFBkhqMIAgz6MG3+AcvzuKKDJRETDqBFjSgE005efEWV0QgEzJBl+gs/CdzZLTzHpmAoEqCe9VgNWjePj5/oHMn3B13xnV37yITJEEMhH0BOsrqWLBuuQfYEVR2btFTAQEDmHQMawCdyTyZzCYeAAeEfrz8VXKC5Mv2dQzrJFALWDyNtDFeHQXJ0yOybzcD3scJWJ3YnQyazytQSoHlkmG6Az5XfQ9jMTosbIveLkCQnG2qBRg8p2tk7iDzHFhiI2RBFpi+YWzZFFgFRlnHYs1q3g5SYL0E1t78FlyRwLh9OiTr76344iW5Xq57/lvJhaIogZ6psunX7JEL11azH1H8cPaSC9fE/EW04se+3ksu5MdDbrbpI3Lh0tf246H/ki7iv+Xoze/BFZ9HKP4BuwtzfPsUblIAAAAASUVORK5CYII= + + false + 0bd900d0-2016-4c53-af3b-1c52cf194064 + true + true + Inverse Kinematics + IK + + + + + + 652 + 287 + 207 + 84 + + + 767 + 329 + + + + + + 4 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 1 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + + + + + true + The robot. + a98f5131-0055-48d7-a0c2-fe32212117c6 + robot + robot + true + 0 + true + 846547a4-0964-4bea-b2e5-d3fd03e0ff69 + 1 + 87f87f55-5b71-41f4-8aea-21d494016f81 + 2 + + + + + + 654 + 289 + 98 + 20 + + + 704.5 + 299 + + + + + + + + true + The plane or frame to calculate the inverse kinematic for. + 84d72e79-136b-457e-8f5b-27843e5bf7b3 + plane + plane + true + 0 + true + 3a86f18b-7506-4d48-8a5c-6048a1108886 + 1 + 87f87f55-5b71-41f4-8aea-21d494016f81 + + + + + + 654 + 309 + 98 + 20 + + + 704.5 + 319 + + + + + + + + true + If passed, calculates the inverse such that the joint positions differ the least from the start_configuration. Defaults to the zero configuration. + 1682b475-974e-4465-847b-6f521d231a4b + start_configuration + start_configuration + true + 0 + true + 0 + 87f87f55-5b71-41f4-8aea-21d494016f81 + + + + + + 654 + 329 + 98 + 20 + + + 704.5 + 339 + + + + + + + + true + The planning group used for calculation. Defaults to the robot's main planning group. + 9da8c8d9-ac45-43a1-8553-97c0c52b171a + group + group + true + 0 + true + 0 + 37261734-eec7-4f50-b6a8-b8d1f3c4396b + + + + + + 654 + 349 + 98 + 20 + + + 704.5 + 359 + + + + + + + + The planning group's configuration. + ac00155a-4a35-4e0d-98f3-e0b82a464386 + configuration + configuration + false + 0 + + + + + + 782 + 289 + 75 + 80 + + + 819.5 + 329 + + + + + + + + + + + + + + 410755b1-224a-4c1e-a407-bf32fb45ea7e + 00000000-0000-0000-0000-000000000000 + Constraints From Plane + + + + + """ +Create a position and an orientation constraint from a plane calculated for the group's end-effector link. + +COMPAS FAB v0.27.0 +""" +import math + +from compas_rhino.conversions import RhinoPlane +from ghpythonlib.componentbase import executingcomponent as component + + +class ConstraintsFromPlane(component): + def RunScript(self, robot, plane, group, tolerance_position, tolerance_xaxis, tolerance_yaxis, tolerance_zaxis): + goal_constraints = None + if robot and plane: + tolerance_position = tolerance_position or 0.001 + tolerance_xaxis = tolerance_xaxis or 1. + tolerance_yaxis = tolerance_yaxis or 1. + tolerance_zaxis = tolerance_zaxis or 1. + + frame = RhinoPlane.from_geometry(plane).to_compas_frame() + tolerances_axes = [math.radians(tolerance_xaxis), math.radians(tolerance_yaxis), math.radians(tolerance_zaxis)] + goal_constraints = robot.constraints_from_frame(frame, tolerance_position, tolerances_axes, group) + + return goal_constraints + + Create a position and an orientation constraint from a plane calculated for the group's end-effector link. +COMPAS FAB v0.27.0 + true + true + 2 + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAALDwAACw8BkvkDpQAAAd9JREFUSEu1lTFLw0AYho92ENShVFHE1p4ILipkcBXqDxA6OQfHThn8ARk7OBQdXfIPzOyUwUFwKfgHSifBJU7idL7f9S7ctV+bVHB4yN17+Z4vuZxVKKX+FTacRYjnBpdXgQ1dIJdgyK1VgQ1dIA/BiFurAhu6QJ4CDP62TWzoAnFuGvS49TLY0AJpYOREwt1TBhtaII2cBmPunjLY0AJp5jQgJHffMtjQBdIYZNxaFdjQZVmDo44MwdLmbEi8CNGl66Z4GqzV0zcai0fRBcVxhTwGGM7XW9gQ8hAoMLhpXXyLIFYQJ2ACRvKk3Yd4RHJDDhIw9428CeHILUnzTvQhzoHaudqeSqWc4Jrp8VRuGwWur0xORBA3wNfG7bqWU5P6fe398PhgQHOqxbVrGng/K4vkOUhNpl8bDXqds9Zn57T9U3uo0Zaprevmh21AYBzRHBR/9VbeAxmIgPeKBAro6fQHBa9oNNy73E3b5/u6gVkj9BsB2rqYaj3RIkyx3p5VoFpWuAgU0R4X5x5j75hiTG9K8shmRXEVUDg0gtDMZxvYo6u/G+EJykBhA4yNhOS2IT25lRdPT3iCKkAggT3/LrR9npzwJqsAWQBsI/pNYv/jzQWrAKk+vtzaFCV+ASnZhhTkLZwXAAAAAElFTkSuQmCC + + false + d93333c1-6121-4133-94e5-b1cdbd79792d + true + true + Constraints From Plane + Constraints From Plane + + + + + + 501 + 973 + 193 + 144 + + + 614 + 1045 + + + + + + 7 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 1 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + + + + + true + The robot. + cbf6a458-85d1-42a7-94f7-416fdfa1b2f0 + robot + robot + true + 0 + true + 538c02c6-6b3b-4712-a784-dda0bc63f847 + 1 + 87f87f55-5b71-41f4-8aea-21d494016f81 + 2 + + + + + + 503 + 975 + 96 + 20 + + + 552.5 + 985 + + + + + + + + true + The plane or frame from which we create position and orientation constraints. + 87942239-75a1-43f9-98a8-39af07ed3dbf + plane + plane + true + 0 + true + 1b843cc6-0c2b-4427-85b3-c5303911f7e9 + 1 + 87f87f55-5b71-41f4-8aea-21d494016f81 + + + + + + 503 + 995 + 96 + 20 + + + 552.5 + 1005 + + + + + + + + true + The planning group for which we specify the constraint. Defaults to the robot's main planning group. + 5f458976-1a25-4cf2-bb59-977ecaa69acf + group + group + true + 0 + true + 0 + 37261734-eec7-4f50-b6a8-b8d1f3c4396b + + + + + + 503 + 1015 + 96 + 20 + + + 552.5 + 1025 + + + + + + + + true + The allowed tolerance to the frame's position (defined in the robot's units). Defaults to 0.001 + f4df44e0-61e9-4a9c-adc5-322c77ee723c + tolerance_position + tolerance_position + true + 0 + true + 0 + 39fbc626-7a01-46ab-a18e-ec1c0c41685b + + + + + + 503 + 1035 + 96 + 20 + + + 552.5 + 1045 + + + + + + + + true + The allowed tolerance of the frame's X-axis in degrees. + 38431b6b-d582-43ce-b820-9189820976ff + tolerance_xaxis + tolerance_xaxis + true + 0 + true + 0 + 39fbc626-7a01-46ab-a18e-ec1c0c41685b + + + + + + 503 + 1055 + 96 + 20 + + + 552.5 + 1065 + + + + + + + + true + The allowed tolerance of the frame's Y-axis in degrees. + 27304578-70c5-46fe-966d-55f6d2a284f3 + tolerance_yaxis + tolerance_yaxis + true + 0 + true + 0 + 39fbc626-7a01-46ab-a18e-ec1c0c41685b + + + + + + 503 + 1075 + 96 + 20 + + + 552.5 + 1085 + + + + + + + + true + The allowed tolerance of the frame's Z-axis in degrees. + 745b4728-c179-4f50-ad5c-43f1ca9fb8f8 + tolerance_zaxis + tolerance_zaxis + true + 0 + true + 0 + 39fbc626-7a01-46ab-a18e-ec1c0c41685b + + + + + + 503 + 1095 + 96 + 20 + + + 552.5 + 1105 + + + + + + + + A list containing a position and an orientation constraint. + 1a96f4f6-fa5c-4bec-8121-df8feb673fae + constraints + constraints + false + 0 + + + + + + 629 + 975 + 63 + 140 + + + 660.5 + 1045 + + + + + + + + + + + + + + 59daf374-bc21-4a5e-8282-5504fb7ae9ae + List Item + + + + + 0 + Retrieve a specific item from a list. + 8a1cd44e-8393-4da1-ba94-6a53dd4e3f37 + List Item + Item + + + + + + 240 + 988 + 64 + 64 + + + 274 + 1020 + + + + + + 3 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + 2e3ab970-8545-46bb-836c-1c11e5610bce + cb95db89-6165-43b6-9c41-5702bc5bf137 + 1 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + + + + + 1 + Base list + 5adfeb6c-e7f6-49be-a873-3d13194ccef5 + List + L + false + 55db7485-e593-4762-a166-64303d976c7a + 1 + + + + + + 242 + 990 + 17 + 20 + + + 252 + 1000 + + + + + + + + Item index + 3c505437-9eea-46c1-ab35-c8afc8032305 + Index + i + false + 0 + + + + + + 242 + 1010 + 17 + 20 + + + 252 + 1020 + + + + + + 1 + + + + + 1 + {0} + + + + + 0 + + + + + + + + + + + Wrap index to list bounds + 578930d2-94b0-4edd-8d4a-cd8a25689009 + Wrap + W + false + 0 + + + + + + 242 + 1030 + 17 + 20 + + + 252 + 1040 + + + + + + 1 + + + + + 1 + {0} + + + + + true + + + + + + + + + + + Item at {i'} + 1b843cc6-0c2b-4427-85b3-c5303911f7e9 + false + Item + i + false + 0 + + + + + + 289 + 990 + 13 + 60 + + + 295.5 + 1020 + + + + + + + + + + + + + + 410755b1-224a-4c1e-a407-bf32fb45ea7e + 00000000-0000-0000-0000-000000000000 + Plan Motion + + + + + """ +Calculate a motion path. + +COMPAS FAB v0.27.0 +""" +from ghpythonlib.componentbase import executingcomponent as component +from scriptcontext import sticky as st + +from compas_fab.ghpython.components import create_id + + +class PlanMotion(component): + def RunScript(self, robot, goal_constraints, start_configuration, group, attached_collision_meshes, path_constraints, planner_id, compute): + + key = create_id(self, 'trajectory') + + path_constraints = list(path_constraints) if path_constraints else None + attached_collision_meshes = list(attached_collision_meshes) if attached_collision_meshes else None + planner_id = str(planner_id) if planner_id else 'RRTConnect' + + if robot and robot.client and robot.client.is_connected and start_configuration and goal_constraints and compute: + st[key] = robot.plan_motion(goal_constraints, + start_configuration=start_configuration, + group=group, + options=dict( + attached_collision_meshes=attached_collision_meshes, + path_constraints=path_constraints, + planner_id=planner_id, + )) + + trajectory = st.get(key, None) + return trajectory + + Calculate a motion path. +COMPAS FAB v0.27.0 + true + true + 2 + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAALEAAACxABrSO9dQAAAY1JREFUSEu1lM1tAjEQhSmBDkgJFMCBEnKJuKYESuAQiRoicaADKIEOkgK455icckHK5n3e8WbsHRJAG0sfjOc9478xo6Zp/pUwOSRhckjC5LWojcVWHMRezDvNGz1qM7ETm0j3qL0KAk+a5NyAtTO+iQ3fZ7z3Ins9+6QHAybGpyDBj58sPgb+lWk1h6QHA14EP/gkZpZjEgJ2M6n8U9NqVkn3ZhuQV1ucvdqD4OjWPm9avQvuZJy0wPxuprR6l6dCCN593ul3Yg5Fvui0Z78UC583jTyBuqUGahwjiyt3XnTasiTorVKNydGXtWZ63nm63C5fdP4+hiOaiHZIcRD8OgHHwCTh41ILV2kaY4t7S/kuaC+JaoBHb3IedvAl6grj1RNAsbtsoJY/zJDZeqP58iPkLrr3YH2Ck/cnzQz8QRHUTHsD2h0QpFetxtt4Fhztruc3U77cmqKmzbsQTMJ9+HG9B5j86eOKHZifms8FQSKsrORNHxfewS38BBdU0S2EySEJk0MSJoejGX0DqCUOkgYB1loAAAAASUVORK5CYII= + + false + 54d5165c-c7b9-4b61-a3f4-725adfe6cedb + true + true + Plan Motion + Plan Motion + + + + + + 895 + 884 + 224 + 164 + + + 1046 + 966 + + + + + + 8 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 1 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + + + + + true + The robot. + 3ab0c3a7-74d4-4e20-8d40-f9d959596a64 + robot + robot + true + 0 + true + 538c02c6-6b3b-4712-a784-dda0bc63f847 + 1 + 87f87f55-5b71-41f4-8aea-21d494016f81 + 2 + + + + + + 897 + 886 + 134 + 20 + + + 965.5 + 896 + + + + + + + + 1 + true + The goal to be achieved, defined in a set of constraints. Constraints can be very specific, for example defining value domains for each joint, such that the goal configuration is included, or defining a volume in space, to which a specific robot link (e.g. the end-effector) is required to move to. + e4550953-1c4d-4196-accf-09e0629aecf8 + goal_constraints + goal_constraints + true + 1 + true + 1a96f4f6-fa5c-4bec-8121-df8feb673fae + 1 + 87f87f55-5b71-41f4-8aea-21d494016f81 + + + + + + 897 + 906 + 134 + 20 + + + 965.5 + 916 + + + + + + + + true + The robot's full configuration, i.e. values for all configurable joints of the entire robot, at the starting position. Defaults to the all-zero configuration. + 045b29a2-7cdc-4ea7-b8be-65710ec81364 + start_configuration + start_configuration + true + 0 + true + c666c109-2ccb-4c50-90cd-00130af76eaa + 1 + 87f87f55-5b71-41f4-8aea-21d494016f81 + + + + + + 897 + 926 + 134 + 20 + + + 965.5 + 936 + + + + + + + + true + The planning group used for calculation. Defaults to the robot's main planning group. + bc8ad3dc-fbe4-440a-98c4-151f7e612cbb + group + group + true + 0 + true + 0 + 37261734-eec7-4f50-b6a8-b8d1f3c4396b + + + + + + 897 + 946 + 134 + 20 + + + 965.5 + 956 + + + + + + + + 1 + true + A list of attached collision meshes to be included for planning. + 8ef44a5c-ec14-4d30-9c85-7fed0cea4feb + attached_collision_meshes + attached_collision_meshes + true + 1 + true + 0 + 87f87f55-5b71-41f4-8aea-21d494016f81 + + + + + + 897 + 966 + 134 + 20 + + + 965.5 + 976 + + + + + + + + 1 + true + Optional constraints that can be imposed along the solution path. Note that path calculation won't work if the start_configuration violates these constraints. Defaults to None. + 79c1632c-fba5-40b8-a628-530ad610655d + path_constraints + path_constraints + true + 1 + true + 0 + 87f87f55-5b71-41f4-8aea-21d494016f81 + + + + + + 897 + 986 + 134 + 20 + + + 965.5 + 996 + + + + + + + + true + The name of the algorithm used for path planning. Defaults to 'RRTConnect' + 59c97f48-1889-4f3b-b990-cedd3ddf9849 + planner_id + planner_id + true + 0 + true + 0 + 37261734-eec7-4f50-b6a8-b8d1f3c4396b + + + + + + 897 + 1006 + 134 + 20 + + + 965.5 + 1016 + + + + + + + + true + If True, calculates a trajectory. + 2dd1af7b-a420-4d72-8c10-01811c07df29 + compute + compute + true + 0 + true + e8dd8875-225b-4b6d-a8de-4f454ff7d868 + 1 + d60527f5-b5af-4ef6-8970-5f96fe412559 + + + + + + 897 + 1026 + 134 + 20 + + + 965.5 + 1036 + + + + + + + + The calculated trajectory. + 4e17b2ad-e9af-41eb-b6a5-7585e1f6e333 + trajectory + trajectory + false + 0 + + + + + + 1061 + 886 + 56 + 160 + + + 1089 + 966 + + + + + + + + + + + + + + 2e78987b-9dfb-42a2-8b76-3923ac8bd91a + Boolean Toggle + + + + + Boolean (true/false) toggle + e8dd8875-225b-4b6d-a8de-4f454ff7d868 + Boolean Toggle + Toggle + false + 0 + false + + + + + + 735 + 1033 + 104 + 22 + + + + + + + + + + b83c36e8-c587-4607-a4b3-d9fdad45d185 + 1c9de8a1-315f-4c56-af06-8f69fee80a7a + Flip Plane + + + + + Flip a plane by specified axes with the option of using a guide plane. + 711d6fa3-3862-4211-a255-f8c00962a10d + Flip Plane + FlipPln + + + + + + 701 + 443 + 67 + 104 + + + 734 + 495 + + + + + + Plane to flip + abc3aafd-8660-4da2-b7a9-b9b7e034def6 + Plane + Pl + false + 44d4a187-3a93-413f-992e-d4cc7e2e19ad + 1 + + + + + + 703 + 445 + 16 + 20 + + + 712.5 + 455 + + + + + + + + Optional guide plane to determine if the plane should flip, based on the guide plane axis angle to the axis of plane to flip + 70ee89b8-6d85-4c25-a81f-6e6012e6adde + Guide + G + true + 0 + + + + + + 703 + 465 + 16 + 20 + + + 712.5 + 475 + + + + + + + + Flip the planes X axis + 46e3bfc4-b95f-44bc-908c-be468fd2a325 + Flip X + X + false + 0 + + + + + + 703 + 485 + 16 + 20 + + + 712.5 + 495 + + + + + + 1 + + + + + 1 + {0} + + + + + false + + + + + + + + + + + Flip the planes Y axis + 21e47292-bdcc-4ecc-9890-bf40fedfefdc + Flip Y + Y + false + 0 + + + + + + 703 + 505 + 16 + 20 + + + 712.5 + 515 + + + + + + 1 + + + + + 1 + {0} + + + + + false + + + + + + + + + + + Flip the planes Z axis + 1352c30f-e3c9-4c38-800e-8703728f4f9d + Flip Z + Z + false + 0 + + + + + + 703 + 525 + 16 + 20 + + + 712.5 + 535 + + + + + + 1 + + + + + 1 + {0} + + + + + true + + + + + + + + + + + Resulting flipped plane + a4e35366-aed9-4624-91f1-08abb1a092fd + Flipped + F + false + 0 + + + + + + 749 + 445 + 17 + 50 + + + 757.5 + 470 + + + + + + + + True if plane was flipped, False if plane was not flipped + 4aa67233-ed42-4970-aca1-04b6a9204c9f + Result Boolean + R + false + 0 + + + + + + 749 + 495 + 17 + 50 + + + 757.5 + 520 + + + + + + + + + + + + + + + + + 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 + + + + + \ No newline at end of file