diff --git a/lecture_04/assignment_03/Lin_chewei/assignment-03.json b/lecture_04/assignment_03/Lin_chewei/assignment-03.json new file mode 100644 index 0000000..3cd4b39 --- /dev/null +++ b/lecture_04/assignment_03/Lin_chewei/assignment-03.json @@ -0,0 +1 @@ +[{"dtype": "compas.robots/Configuration", "value": {"joint_values": [0.22544341204728363, -2.0968085857698457, -2.128177623592219, -0.4874039665304446, 1.5707951025366123, 1.7962398912533473], "joint_types": [0, 0, 0, 0, 0, 0], "joint_names": ["shoulder_pan_joint", "shoulder_lift_joint", "elbow_joint", "wrist_1_joint", "wrist_2_joint", "wrist_3_joint"]}}, {"dtype": "compas.robots/Configuration", "value": {"joint_values": [-0.027166413891432185, -2.0032502003286217, -2.3434720084221143, -0.3683795965084574, 1.6704280842019585, 1.5434947470166338], "joint_types": [0, 0, 0, 0, 0, 0], "joint_names": ["shoulder_pan_joint", "shoulder_lift_joint", "elbow_joint", "wrist_1_joint", "wrist_2_joint", "wrist_3_joint"]}}, {"dtype": "compas.robots/Configuration", "value": {"joint_values": [-0.36759775052655236, -1.9494596879232018, -2.4053871518660137, -0.4292859513624741, 1.754852352910178, 1.196575831466971], "joint_types": [0, 0, 0, 0, 0, 0], "joint_names": ["shoulder_pan_joint", "shoulder_lift_joint", "elbow_joint", "wrist_1_joint", "wrist_2_joint", "wrist_3_joint"]}}, {"dtype": "compas.robots/Configuration", "value": {"joint_values": [-0.7516654957685005, -1.9465492727639666, -2.3061039799652217, -0.6617960819855494, 1.782294398644407, 0.7976109038045373], "joint_types": [0, 0, 0, 0, 0, 0], "joint_names": ["shoulder_pan_joint", "shoulder_lift_joint", "elbow_joint", "wrist_1_joint", "wrist_2_joint", "wrist_3_joint"]}}, {"dtype": "compas.robots/Configuration", "value": {"joint_values": [-1.1073947485684787, -2.0174820314868875, -2.088910007947618, -0.9496168778794705, 1.737578262420177, 0.43439612569123875], "joint_types": [0, 0, 0, 0, 0, 0], "joint_names": ["shoulder_pan_joint", "shoulder_lift_joint", "elbow_joint", "wrist_1_joint", "wrist_2_joint", "wrist_3_joint"]}}, {"dtype": "compas.robots/Configuration", "value": {"joint_values": [-1.4135740616616774, -2.1390635561297233, -1.8161799382694923, -1.2158479039195114, 1.6408770283030758, 0.14085464317423715], "joint_types": [0, 0, 0, 0, 0, 0], "joint_names": ["shoulder_pan_joint", "shoulder_lift_joint", "elbow_joint", "wrist_1_joint", "wrist_2_joint", "wrist_3_joint"]}}, {"dtype": "compas.robots/Configuration", "value": {"joint_values": [-1.680609028110169, -2.219128636446844, -1.6828365453824001, -1.188851434662567, 1.5300835851476766, -0.10201498277241407], "joint_types": [0, 0, 0, 0, 0, 0], "joint_names": ["shoulder_pan_joint", "shoulder_lift_joint", "elbow_joint", "wrist_1_joint", "wrist_2_joint", "wrist_3_joint"]}}, {"dtype": "compas.robots/Configuration", "value": {"joint_values": [-1.9354865452626713, -2.266674216902976, -1.6261868072769476, -1.0927872964634988, 1.4681305559295035, -0.35056289935626933], "joint_types": [0, 0, 0, 0, 0, 0], "joint_names": ["shoulder_pan_joint", "shoulder_lift_joint", "elbow_joint", "wrist_1_joint", "wrist_2_joint", "wrist_3_joint"]}}, {"dtype": "compas.robots/Configuration", "value": {"joint_values": [-2.188250312646932, -2.301318770249356, -1.6023863102259377, -0.9703320935575104, 1.4570072257517943, -0.6082271089161407], "joint_types": [0, 0, 0, 0, 0, 0], "joint_names": ["shoulder_pan_joint", "shoulder_lift_joint", "elbow_joint", "wrist_1_joint", "wrist_2_joint", "wrist_3_joint"]}}, {"dtype": "compas.robots/Configuration", "value": {"joint_values": [-2.4442081366746335, -2.351104061373698, -1.5437112211358086, -0.8817071181930184, 1.4944501181389513, -0.8709616133734153], "joint_types": [0, 0, 0, 0, 0, 0], "joint_names": ["shoulder_pan_joint", "shoulder_lift_joint", "elbow_joint", "wrist_1_joint", "wrist_2_joint", "wrist_3_joint"]}}, {"dtype": "compas.robots/Configuration", "value": {"joint_values": [-2.6933975667893493, -2.432441064645617, -1.4030362191325068, -0.8769116919401005, 1.5707963226896162, -1.1226012405363799], "joint_types": [0, 0, 0, 0, 0, 0], "joint_names": ["shoulder_pan_joint", "shoulder_lift_joint", "elbow_joint", "wrist_1_joint", "wrist_2_joint", "wrist_3_joint"]}}] \ No newline at end of file diff --git a/lecture_04/assignment_03/Lin_chewei/assignment_03.py b/lecture_04/assignment_03/Lin_chewei/assignment_03.py new file mode 100644 index 0000000..b026e39 --- /dev/null +++ b/lecture_04/assignment_03/Lin_chewei/assignment_03.py @@ -0,0 +1,60 @@ +import os +import compas +from compas_fab.backends import RosClient +from compas_fab.robots import Configuration + +from compas.geometry import Frame +from compas.geometry import Point +from compas.geometry import Vector + + +# Step 1: Inside this function, complete the main part of the solution for the assignment: +# - Taking a robot and a list of frames as parameter, calculate a feasible configuration for each of the frames +# - Try to find an optimal start_configuration for each so that the motion from one config to the next is minimized +def calculate_ik_for_frames(robot, frames): + configs = [] + previous_config = robot.zero_configuration() + previous_config.joint_values = (0.15, -2.01, -1.08, -0.97, 1.55, 0.0) + + for frame in frames: + _config = robot.inverse_kinematics(frame, previous_config) + configs.append(_config) + previous_config = _config + + return configs + + +# Step 2: store all found configurations in a JSON file using compas.json_dump or compas.json_dumps +def store_configurations(configurations, filename): + compas.json_dump(configurations, filename) + + +# Use the following to test from the command line +# Or copy solution_viewer.ghx next to the folder where you created assignment_03.py to visualize the same in Grasshopper +if __name__ == '__main__': + + frames = [ + Frame(Point(-0.329, 0.059, 0.082), Vector(1.000, 0.000, 0.000), Vector(0.000, -1.000, 0.000)), + Frame(Point(-0.260, 0.129, 0.082), Vector(1.000, 0.000, 0.000), Vector(0.000, -1.000, 0.100)), + Frame(Point(-0.186, 0.194, 0.082), Vector(1.000, 0.000, 0.000), Vector(0.000, -1.000, 0.200)), + Frame(Point(-0.106, 0.252, 0.082), Vector(1.000, 0.000, 0.000), Vector(0.000, -1.000, 0.300)), + Frame(Point(-0.020, 0.299, 0.082), Vector(1.000, 0.000, 0.000), Vector(0.000, -1.000, 0.400)), + Frame(Point(0.074, 0.329, 0.082), Vector(1.000, 0.000, 0.000), Vector(0.000, -1.000, 0.500)), + Frame(Point(0.172, 0.330, 0.082), Vector(1.000, 0.000, 0.000), Vector(0.000, -1.000, 0.400)), + Frame(Point(0.263, 0.295, 0.082), Vector(1.000, 0.000, 0.000), Vector(0.000, -1.000, 0.300)), + Frame(Point(0.339, 0.233, 0.082), Vector(1.000, 0.000, 0.000), Vector(0.000, -1.000, 0.200)), + Frame(Point(0.400, 0.155, 0.082), Vector(1.000, 0.000, 0.000), Vector(0.000, -1.000, 0.100)), + Frame(Point(0.448, 0.070, 0.082), Vector(1.000, 0.000, 0.000), Vector(0.000, -1.000, 0.000))] + + # Loads the robot from ROS + with RosClient('localhost') as client: + robot = client.load_robot() + + # Step 1: calculate IK solutions for each frame + configurations = calculate_ik_for_frames(robot, frames) + print("Found {} configurations".format(len(configurations))) + + # Step 2: store all configurations in a JSON file + filename = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'assignment-03.json') + store_configurations(configurations, filename) + print("Stored results in {}".format(filename)) diff --git a/lecture_04/assignment_03/Lin_chewei/robot_ik.jpg b/lecture_04/assignment_03/Lin_chewei/robot_ik.jpg new file mode 100644 index 0000000..39650d0 Binary files /dev/null and b/lecture_04/assignment_03/Lin_chewei/robot_ik.jpg differ diff --git a/lecture_04/assignment_03/Lin_chewei/solution_viewer.ghx b/lecture_04/assignment_03/Lin_chewei/solution_viewer.ghx new file mode 100644 index 0000000..0e41f74 --- /dev/null +++ b/lecture_04/assignment_03/Lin_chewei/solution_viewer.ghx @@ -0,0 +1,4014 @@ + + + + + + + + 0 + 2 + 2 + + + + + + + 1 + 0 + 7 + + + + + + 267186b6-22d4-4301-830e-efc68b78e363 + Shaded + 1 + + 100;150;0;0 + + + 100;0;150;0 + + + + + + 637515172939181553 + + solution_viewer.ghx + + + + + 0 + + + + + + -1391 + -560 + + 1.38408291 + + + + + 0 + + + + + + + 0 + + + + + 1 + + + + + Elk.Mapping, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + 1.0.0.0 + timothy.b.logan@gmail.com + 00000000-0000-0000-0000-000000000000 + + + + + + + + + 29 + + + + + 2e78987b-9dfb-42a2-8b76-3923ac8bd91a + Boolean Toggle + + + + + Boolean (true/false) toggle + c7d255bb-e9cf-4deb-b4de-248fedfcc9fd + Boolean Toggle + Connect + false + 0 + true + + + + + + 31 + 228 + 113 + 22 + + + + + + + + + + 2e78987b-9dfb-42a2-8b76-3923ac8bd91a + Boolean Toggle + + + + + Boolean (true/false) toggle + 1e891ee1-8c8e-4909-bfa8-9478fe5871e0 + Boolean Toggle + Load + false + 0 + true + + + + + + 29 + 252 + 96 + 22 + + + + + + + + + + c552a431-af5b-46a9-a8a4-0fcbc27ef596 + Group + + + + + 1 + + 150;170;135;255 + + A group of Grasshopper objects + 16792f65-ce66-4c57-8894-6616e5c283b2 + c7d255bb-e9cf-4deb-b4de-248fedfcc9fd + 1e891ee1-8c8e-4909-bfa8-9478fe5871e0 + 84446ac2-e8f7-4c7d-9d31-dab3deade42d + eccb9686-8536-4332-975d-684efb918cee + ed6dd17e-9615-4209-9f27-8c842a439b86 + 6 + ca5efeaf-96ea-4f51-8b8c-044bf95f301c + Group + + + + + + + + + + + 410755b1-224a-4c1e-a407-bf32fb45ea7e + 00000000-0000-0000-0000-000000000000 + GhPython Script + + + + + # NOTE: Don't write you solution here! +# Write the code in the assignment_03.py and if +# the file is located in the same folder as this GH file +# then Grasshopper will find it and import it +from compas_ghpython import unload_modules +from compas.geometry import Frame, Point, Vector +unload_modules('assignment_03') + +try: + from assignment_03 import calculate_ik_for_frames +except ImportError: + raise Exception("Please make sure you have the file assignment_03.py in the same location as this GH file") + +from compas_fab.ghpython.components import coerce_frame + +frames = [ + Frame(Point(-0.329, 0.059, 0.082), Vector(1.000, 0.000, 0.000), Vector(0.000, -1.000, 0.000)), + Frame(Point(-0.260, 0.129, 0.082), Vector(1.000, 0.000, 0.000), Vector(0.000, -1.000, 0.100)), + Frame(Point(-0.186, 0.194, 0.082), Vector(1.000, 0.000, 0.000), Vector(0.000, -1.000, 0.200)), + Frame(Point(-0.106, 0.252, 0.082), Vector(1.000, 0.000, 0.000), Vector(0.000, -1.000, 0.300)), + Frame(Point(-0.020, 0.299, 0.082), Vector(1.000, 0.000, 0.000), Vector(0.000, -1.000, 0.400)), + Frame(Point(0.074, 0.329, 0.082), Vector(1.000, 0.000, 0.000), Vector(0.000, -1.000, 0.500)), + Frame(Point(0.172, 0.330, 0.082), Vector(1.000, 0.000, 0.000), Vector(0.000, -1.000, 0.400)), + Frame(Point(0.263, 0.295, 0.082), Vector(1.000, 0.000, 0.000), Vector(0.000, -1.000, 0.300)), + Frame(Point(0.339, 0.233, 0.082), Vector(1.000, 0.000, 0.000), Vector(0.000, -1.000, 0.200)), + Frame(Point(0.400, 0.155, 0.082), Vector(1.000, 0.000, 0.000), Vector(0.000, -1.000, 0.100)), + Frame(Point(0.448, 0.070, 0.082), Vector(1.000, 0.000, 0.000), Vector(0.000, -1.000, 0.000))] + +configuration = calculate_ik_for_frames(robot, frames) + + GhPython provides a Python script component + + 43 + 69 + + + 1114 + 826 + + true + true + true + false + 205c786a-b8cf-4a07-8455-eea7b91954d2 + false + true + GhPython Script + Python + + + + + + 785 + 241 + 156 + 44 + + + 844 + 263 + + + + + + 2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 1 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + + + + + true + Script variable Python + ba3333a4-a4af-41c9-9db8-4a84ea6a37df + robot + robot + true + 0 + true + d4bae7b0-750f-4b86-a929-7bf58d55c307 + 1 + 87f87f55-5b71-41f4-8aea-21d494016f81 + + + + + + 787 + 243 + 42 + 20 + + + 809.5 + 253 + + + + + + + + 1 + true + Script input frames. + c640367c-4d94-4702-8a36-9b422631f663 + frames + frames + true + 1 + true + 0 + 87f87f55-5b71-41f4-8aea-21d494016f81 + + + + + + 787 + 263 + 42 + 20 + + + 809.5 + 273 + + + + + + + + Script output configuration. + 66f1bdea-7701-4476-b28d-6ea50cb1a15e + configuration + configuration + false + 0 + + + + + + 859 + 243 + 80 + 40 + + + 899 + 263 + + + + + + + + + + + + + + 59daf374-bc21-4a5e-8282-5504fb7ae9ae + List Item + + + + + 0 + Retrieve a specific item from a list. + true + 7198f137-5adf-40bd-9365-ce004651bcdf + List Item + Item + + + + + + 989 + 251 + 65 + 64 + + + 1024 + 283 + + + + + + 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 + a71a26e2-bc83-4c3a-bb49-8f2a379f82e6 + List + L + false + 66f1bdea-7701-4476-b28d-6ea50cb1a15e + 1 + + + + + + 991 + 253 + 18 + 20 + + + 1001.5 + 263 + + + + + + + + Item index + 7da95829-d7e8-4d73-b01e-2a3b037c616a + Index + i + false + 9c88f1df-80d2-4fc0-a569-528fab1a8314 + 1 + + + + + + 991 + 273 + 18 + 20 + + + 1001.5 + 283 + + + + + + 1 + + + + + 1 + {0} + + + + + 0 + + + + + + + + + + + Wrap index to list bounds + 5349e571-6e69-4fef-be96-8ba696ebf207 + Wrap + W + false + 0 + + + + + + 991 + 293 + 18 + 20 + + + 1001.5 + 303 + + + + + + 1 + + + + + 1 + {0} + + + + + true + + + + + + + + + + + Item at {i'} + 6c5c47d3-b49d-4dbf-a287-2305b02558e7 + false + Item + i + false + 0 + + + + + + 1039 + 253 + 13 + 60 + + + 1045.5 + 283 + + + + + + + + + + + + + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider + + + + + Numeric slider for single values + 9c88f1df-80d2-4fc0-a569-528fab1a8314 + Number Slider + + false + 0 + + + + + + 780 + 321 + 162 + 20 + + + 780.9314 + 321.8065 + + + + + + 3 + 1 + 1 + 10 + 0 + 0 + 0 + + + + + + + + + c552a431-af5b-46a9-a8a4-0fcbc27ef596 + Group + + + + + 1 + + 150;170;135;255 + + A group of Grasshopper objects + 205c786a-b8cf-4a07-8455-eea7b91954d2 + 7198f137-5adf-40bd-9365-ce004651bcdf + 9c88f1df-80d2-4fc0-a569-528fab1a8314 + 716141ca-3bd8-4b27-8dca-290a69e4a2eb + 4 + a10ab389-c3a2-495c-979b-e89e0f6f17c4 + Group + + + + + + + + + + + 410755b1-224a-4c1e-a407-bf32fb45ea7e + 00000000-0000-0000-0000-000000000000 + ROS Connect + + + + + """ +Connect or disconnect to ROS. + +COMPAS FAB v0.22.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.22.0 + true + true + true + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAALDQAACw0B7QfALAAAAdZJREFUSEu1lD2O4kAQRrkBcwP2BnADfARuABEhcAMcEEyCQKuVCCEkY27A3ADCyUAimQyHm/V+r9bNNp5iSLwtPWF/9dvdZRohhP+KK9aJK9aJK9aJKzpk4k08W4XYiB/CYquJPJbX6zVMp9PQbrcV0XhIt9sN6/VaIVZoQLyXMGVC8piYXwp5jMfj0Gq1zK/f7yvUVsdLGnkRBV0RlHT2/g2WHH+KonmJI4PD4ZA6HwVFPd9IR1hTzWZTj76Tcjay1Wr1QWIKnE6n0Ov17DnhXeSiWnTJbvHZ7/d3BkNrg3E2m/2OBbiH4XCITkLg+YhNnMVtakRuib0CWgMMYlMUxetutzPH8vwZ00f+HB8auznHe6CxagDdnMt3ztPOkunAWYsiPcF3YYxGo19ZloXtdvtT78d4b9yDVpEmf8Eg8qiJt7gLCi0WC9v2IxjV6Mu9aU3SAh2MYhI1wZaPBMcZfwadl8n5oqX8Sya7OZkhgSJoge1Xu04pE/Ot3E4hTUQBmyDB+d7ZBIU4f4INBmE+n3/meR4ul8tS2pe4+5e/91CURRjH7BuYIIYCX/vf8fgqaKYFHxEvz6CZh8nBFUGLQl7nN7y4Kq5YJ65YJ65YJ65YH6HxB7b14P1B22tpAAAAAElFTkSuQmCC + + false + eccb9686-8536-4332-975d-684efb918cee + true + true + ROS Connect + ROS + + + + + + 176 + 187 + 159 + 64 + + + 241 + 219 + + + + + + 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. + cbcceb8e-d113-460c-8c91-6474031ab1a7 + ip + ip + true + 0 + true + 0 + 37261734-eec7-4f50-b6a8-b8d1f3c4396b + + + + + + 178 + 189 + 48 + 20 + + + 203.5 + 199 + + + + + + + + true + The port of ROS. Defaults to 9090. + 23ab18d4-0816-4280-b382-e2cbdab4caa9 + port + port + true + 0 + true + 0 + 48d01794-d3d8-4aef-990e-127168822244 + + + + + + 178 + 209 + 48 + 20 + + + 203.5 + 219 + + + + + + + + true + If True, connects to ROS. If False, disconnects from ROS. Defaults to False. + da4e32db-96ba-40c4-b661-67c91677a2ed + connect + connect + true + 0 + true + c7d255bb-e9cf-4deb-b4de-248fedfcc9fd + 1 + d60527f5-b5af-4ef6-8970-5f96fe412559 + + + + + + 178 + 229 + 48 + 20 + + + 203.5 + 239 + + + + + + + + The ROS client. + 20b3b82c-7d50-4449-b49c-d0195f7b838a + ros_client + ros_client + false + 0 + + + + + + 256 + 189 + 77 + 30 + + + 294.5 + 204 + + + + + + + + True if connection established. + f636540e-bf52-4933-9f75-bdfdc23e479c + is_connected + is_connected + false + 0 + + + + + + 256 + 219 + 77 + 30 + + + 294.5 + 234 + + + + + + + + + + + + + + 410755b1-224a-4c1e-a407-bf32fb45ea7e + 00000000-0000-0000-0000-000000000000 + ROS Robot + + + + + """ +Load robot directly from ROS. + +COMPAS FAB v0.22.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.22.0 + + 156 + 156 + + + 558 + 530 + + true + true + true + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAALDQAACw0B7QfALAAAAVtJREFUSEu9lMFRwzAQRVMCJaSElJASUgIlUAGTEhguXHPinBJSAiWkBDow/9n6ZmWtQzwYduaNpdVqtf5redN13Z+SOtckdS5B9iCeeKbrmXMJsrNg8CkOzXo1Gao5iYtg4z6uR2SP4iqY+Ans3Y5xk00sTjfsBcmOgbjOmMK2wvs/mgNKQL8o3sRzmb8Iy5BRySLbifHNpwsM3gWHvJY5ByAb44xKRtkoTz+vJkNiBn7CQXAIr29oqNd7OWTIhHxMrmNOD0oQb2EdSYL2VUUlDjlJ5kKQMDa8lahsdEPdNFfUHFLiiYsNJ766D9WG3lHLYy7TOCOjEArLi2gcQ7ATR2bvxC1yZ/7VjI1bQu4cXjt+KeaYxd8idQLJQmLDoelPbY7UaWTxCzGnLHaO1Glkv2546xhubUz2E8i2m+YxreP7Ji9htvmt4x8O4Ffhn9q93C/R2qTO9eg2XxfZxOCoCLXEAAAAAElFTkSuQmCC + + false + ed6dd17e-9615-4209-9f27-8c842a439b86 + true + true + ROS Robot + Robot + + + + + + 381 + 229 + 129 + 44 + + + 454 + 251 + + + + + + 2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 1 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + + + + + true + The ROS client. + 9df689c7-f25f-4820-b9e3-e243f1ac71db + ros_client + ros_client + true + 0 + true + 20b3b82c-7d50-4449-b49c-d0195f7b838a + 1 + 87f87f55-5b71-41f4-8aea-21d494016f81 + + + + + + 383 + 231 + 56 + 20 + + + 412.5 + 241 + + + + + + + + true + If True, loads the robot from ROS. Defaults to False. + 28374d3d-390d-4b67-88a5-0746309c0629 + load + load + true + 0 + true + 1e891ee1-8c8e-4909-bfa8-9478fe5871e0 + 1 + d60527f5-b5af-4ef6-8970-5f96fe412559 + + + + + + 383 + 251 + 56 + 20 + + + 412.5 + 261 + + + + + + + + The robot. + d4bae7b0-750f-4b86-a929-7bf58d55c307 + robot + robot + false + 0 + + + + + + 469 + 231 + 39 + 40 + + + 488.5 + 251 + + + + + + + + + + + + + + 410755b1-224a-4c1e-a407-bf32fb45ea7e + 00000000-0000-0000-0000-000000000000 + Robot Visualize + + + + + """ +Visualizes the robot. + +COMPAS FAB v0.22.0 +""" +from compas.geometry import Frame +from compas.geometry import Transformation +from compas_ghpython.artists import FrameArtist +from compas_ghpython.artists import MeshArtist +from ghpythonlib.componentbase import executingcomponent as component + + +class RobotVisualize(component): + def RunScript(self, robot, group, configuration, attached_collision_meshes, show_visual, show_collision, + show_frames, show_base_frame, show_end_effector_frame, show_acm): + + visual = None + collision = 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 + 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 = FrameArtist(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 = FrameArtist(ee_compas_frame) + ee_frame = artist.draw() + + if show_frames: + frames = [] + for compas_frame in compas_frames[1:]: + artist = FrameArtist(compas_frame) + frame = artist.draw() + frames.append(frame) + + if show_acm: + attached_meshes = [] + for acm in attached_collision_meshes: + frame = robot.forward_kinematics(configuration, options=dict(solver='model', link_name=acm.link_name)) + T = Transformation.from_frame_to_frame(Frame.worldXY(), frame) + mesh = acm.collision_mesh.mesh.transformed(T) + attached_meshes.append(MeshArtist(mesh).draw()) + + return (visual, collision, attached_meshes, frames, base_frame, ee_frame) + + Visualizes the robot. +COMPAS FAB v0.22.0 + true + true + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAALDQAACw0B7QfALAAAAdhJREFUSEu1lLFKA0EQhlUIQVBMOhGLgGAtxAcIYmmRJpWNrZ2dhSCWqURtxC6VRSofIYWlhS8QyBMEOzvP/zt2jtm9VSLEg+9ud2bnn9nZu1spiuJfyRqXSdb4F3ZvX1vigmfOXzP8FQm/iEJ8iH7qjyZUIUZiIgjseb9HvjMxE4jbE4jt2Lo0CGca0BOI3Ti8nzGFdYTFv9cShAWlUzyK6zC/E9aGHFFbND8Q1c5TBwHPgiQPYU4C2uZFPVEbNa/aA9wqg5wIE2RP6AuSsH2DAzV/2Q49aRPtwzYzTW5VBXKwC+sjIvQ+qiiso52IWSG00B941CKfwA7UDs0qqiUJ61nnD5z10ffALe2hb48x8Ws88lEIhWWLqBnC4jQBRIUsStYosdxbUx6croFgAJcWo6st5sE+ruw28EiMbfs3xbjBnxWKEw8quw1SEEvEgaQtCQydWJv1zjb3OpFoisT8G2KMJNINYlBWq8t2NfQakWCKxH48cAlNg+CT8AmPvUYkCArmq82JRmydnJeCa+sbX42dvfsgPk31ogko2L7kX9m+GpcJYLXR/AzjqD0QTUDBCyWA5v5hlSTQTfWiCSiQX4X91H5l8+jUzgHeUi2oGZZN1rg8ipVvhzuVIxcFIsQAAAAASUVORK5CYII= + + false + 10a49928-eb17-4269-a1f5-98ee19233fed + true + true + Robot Visualize + Robot Visualize + + + + + + 1874 + 197 + 278 + 204 + + + 2035 + 299 + + + + + + 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 + 6 + 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. + 5665115c-dc6f-4b96-b649-90363f6f156d + robot + robot + true + 0 + true + d4bae7b0-750f-4b86-a929-7bf58d55c307 + 1 + 87f87f55-5b71-41f4-8aea-21d494016f81 + 2 + + + + + + 1876 + 199 + 144 + 20 + + + 1949.5 + 209 + + + + + + + + true + The planning group used for end-effector and base visualization. + 19283912-83ba-4eb0-ba1c-6f5ac3311327 + group + group + true + 0 + true + 0 + 37261734-eec7-4f50-b6a8-b8d1f3c4396b + + + + + + 1876 + 219 + 144 + 20 + + + 1949.5 + 229 + + + + + + + + true + The robot's full configuration. + 1fca49ea-0635-4a0a-b95b-c9f257682b15 + configuration + configuration + true + 0 + true + 413f4b7d-50ca-45ce-9bd2-84a106772d59 + 1 + 87f87f55-5b71-41f4-8aea-21d494016f81 + + + + + + 1876 + 239 + 144 + 20 + + + 1949.5 + 249 + + + + + + + + 1 + true + A list of attached collision meshes. + 651066a0-4de6-4d81-960c-74dd5ebba2c2 + attached_collision_meshes + attached_collision_meshes + true + 1 + true + 0 + 87f87f55-5b71-41f4-8aea-21d494016f81 + + + + + + 1876 + 259 + 144 + 20 + + + 1949.5 + 269 + + + + + + + + true + Whether or not to show the robot's visual meshes. + fd6c0bb5-7a57-4ca6-81c0-035515585a87 + show_visual + show_visual + true + 0 + true + 0 + d60527f5-b5af-4ef6-8970-5f96fe412559 + + + + + + 1876 + 279 + 144 + 20 + + + 1949.5 + 289 + + + + + + + + true + Whether or not to show the robot's collision meshes. + dac981a0-3655-427f-83bb-869a928c361c + show_collision + show_collision + true + 0 + true + 0 + d60527f5-b5af-4ef6-8970-5f96fe412559 + + + + + + 1876 + 299 + 144 + 20 + + + 1949.5 + 309 + + + + + + + + true + Whether or not to show the robot's joint frames. + de2c0813-2228-47c0-a1fb-25fecad1fc57 + show_frames + show_frames + true + 0 + true + 0 + d60527f5-b5af-4ef6-8970-5f96fe412559 + + + + + + 1876 + 319 + 144 + 20 + + + 1949.5 + 329 + + + + + + + + true + Whether or not to show the robot's base frame. + 7639b92d-56d4-4e95-8462-1a3570422d31 + show_base_frame + show_base_frame + true + 0 + true + 0 + d60527f5-b5af-4ef6-8970-5f96fe412559 + + + + + + 1876 + 339 + 144 + 20 + + + 1949.5 + 349 + + + + + + + + true + Whether or not to show the robot's end-effector frame. + f438ee13-4ba8-4090-9a27-aaec8905fe02 + show_end_effector_frame + show_end_effector_frame + true + 0 + true + 5e3279a2-6f98-4b23-ae56-5659c1281c18 + 1 + d60527f5-b5af-4ef6-8970-5f96fe412559 + + + + + + 1876 + 359 + 144 + 20 + + + 1949.5 + 369 + + + + + + + + true + Whether or not to show the attached collision meshes (if any). + 9222d70d-5e4f-4408-b727-43a01bb10333 + show_acm + show_acm + true + 0 + true + 0 + d60527f5-b5af-4ef6-8970-5f96fe412559 + + + + + + 1876 + 379 + 144 + 20 + + + 1949.5 + 389 + + + + + + + + The robot's visual Rhino meshes (if any). + d172c507-69c0-458a-97b9-642920bb140f + visual + visual + false + 0 + + + + + + 2050 + 199 + 100 + 33 + + + 2100 + 215.6667 + + + + + + + + The robot's collision Rhino meshes (if any). + d53f0b28-0a87-4e89-932c-575be550c6f7 + collision + collision + false + 0 + + + + + + 2050 + 232 + 100 + 33 + + + 2100 + 249 + + + + + + + + The attached collision Rhino meshes (if any). + 2069798a-a5d1-4168-afa3-d64cf6264cd8 + attached_meshes + attached_meshes + false + 0 + + + + + + 2050 + 265 + 100 + 34 + + + 2100 + 282.3333 + + + + + + + + The robot's joint frames as Rhino planes (if any). + 8913b320-9e60-4c95-b721-c90ef3174981 + frames + frames + false + 0 + + + + + + 2050 + 299 + 100 + 33 + + + 2100 + 315.6667 + + + + + + + + The robot's base frame as a Rhino plane (if any). + ba6264fe-2f01-4ec7-abb3-24d0af02a5c3 + base_frame + base_frame + false + 0 + + + + + + 2050 + 332 + 100 + 33 + + + 2100 + 349 + + + + + + + + The robot's end-effector frame as a Rhino plane (if any). + cc6cd5a6-9a99-4006-be91-e55a54aacf7e + ee_frame + ee_frame + false + 0 + + + + + + 2050 + 365 + 100 + 34 + + + 2100 + 382.3333 + + + + + + + + + + + + + + 410755b1-224a-4c1e-a407-bf32fb45ea7e + 00000000-0000-0000-0000-000000000000 + GhPython Script + + + + + from compas_fab.robots import Configuration + +config = Configuration.from_revolute_values(x) + + GhPython provides a Python script component + + 104 + 104 + + + 558 + 530 + + true + true + false + false + e49367ea-4c70-4652-b3b9-6da8dfa54119 + false + true + GhPython Script + Python + + + + + + 964 + 390 + 89 + 44 + + + 993 + 412 + + + + + + 1 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 2 + 3ede854e-c753-40eb-84cb-b48008f14fd4 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + + + + + 1 + true + The x script variable + 2986baae-8d51-4402-a267-2eb6653d2a04 + x + x + true + 1 + true + 179679fb-e408-4a60-841d-e86f0575518e + d5363987-91eb-4870-8a34-65cfa65f28a2 + 51bb5ab5-2448-4845-baf7-c80b4960a54b + c9c0291d-bdb2-42c8-8485-e09f9a01e4d2 + f51a9ad8-bd5b-46f4-8576-bd9a6a7d5983 + fb1d170e-71f6-47d3-8fe6-27b378224d69 + 6 + 39fbc626-7a01-46ab-a18e-ec1c0c41685b + + + + + + 966 + 392 + 12 + 40 + + + 973.5 + 412 + + + + + + + + The execution information, as output and error streams + 9c63e747-b6bc-4507-8627-1831850545be + out + out + false + 0 + + + + + + 1008 + 392 + 43 + 20 + + + 1029.5 + 402 + + + + + + + + Script output config. + b25441dd-5dac-44ea-ba56-2c253f774dd1 + config + config + false + 0 + + + + + + 1008 + 412 + 43 + 20 + + + 1029.5 + 422 + + + + + + + + + + + + + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider + + + + + Numeric slider for single values + 179679fb-e408-4a60-841d-e86f0575518e + Number Slider + + false + 0 + + + + + + 777 + 404 + 162 + 20 + + + 777.0078 + 404.0164 + + + + + + 2 + 1 + 0 + 3.14 + -3.14 + 0 + 0.15 + + + + + + + + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider + + + + + Numeric slider for single values + d5363987-91eb-4870-8a34-65cfa65f28a2 + Number Slider + + false + 0 + + + + + + 777 + 426 + 162 + 20 + + + 777.0078 + 426.8164 + + + + + + 2 + 1 + 0 + 3.14 + -3.14 + 0 + -2.01 + + + + + + + + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider + + + + + Numeric slider for single values + 51bb5ab5-2448-4845-baf7-c80b4960a54b + Number Slider + + false + 0 + + + + + + 777 + 448 + 162 + 20 + + + 777.0078 + 448.6164 + + + + + + 2 + 1 + 0 + 3.14 + -3.14 + 0 + -1.8 + + + + + + + + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider + + + + + Numeric slider for single values + c9c0291d-bdb2-42c8-8485-e09f9a01e4d2 + Number Slider + + false + 0 + + + + + + 777 + 470 + 162 + 20 + + + 777.0078 + 470.4164 + + + + + + 2 + 1 + 0 + 3.14 + -3.14 + 0 + -0.97 + + + + + + + + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider + + + + + Numeric slider for single values + f51a9ad8-bd5b-46f4-8576-bd9a6a7d5983 + Number Slider + + false + 0 + + + + + + 777 + 492 + 162 + 20 + + + 777.0078 + 492.2163 + + + + + + 2 + 1 + 0 + 3.14 + -3.14 + 0 + 1.55 + + + + + + + + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider + + + + + Numeric slider for single values + fb1d170e-71f6-47d3-8fe6-27b378224d69 + Number Slider + + false + 0 + + + + + + 777 + 514 + 162 + 20 + + + 777.0078 + 514.804 + + + + + + 2 + 1 + 0 + 3.14 + -3.14 + 0 + -0.41 + + + + + + + + + 2e78987b-9dfb-42a2-8b76-3923ac8bd91a + Boolean Toggle + + + + + Boolean (true/false) toggle + 5e3279a2-6f98-4b23-ae56-5659c1281c18 + Boolean Toggle + Toggle + false + 0 + true + + + + + + 1159 + 382 + 106 + 22 + + + + + + + + + + 8ec86459-bf01-4409-baee-174d0d2b13d0 + Data + + + + + Contains a collection of generic data + true + e176611a-6234-442e-9cba-7f2bb739da1a + Data + Data + false + 0 + + + + + + 785 + 369 + 50 + 24 + + + 810.05 + 381.65 + + + + + + 1 + + + + + 11 + {0;0} + + + + + Grasshopper.Kernel.Types.GH_Plane + + -0.328996061987069 + 0.0589997863205354 + 0.0820025390807471 + 0.999999999999591 + -1.52205983500691E-07 + 8.91832180002542E-07 + -1.52204681098557E-07 + -0.999999999998922 + -1.46036671656503E-06 + + + + + + Grasshopper.Kernel.Types.GH_Plane + + -0.259999175301696 + 0.128999063702886 + 0.0819999383982555 + 0.999999999994021 + -2.5962333247904E-07 + -3.44831737824999E-06 + 8.47852179257533E-08 + -0.99503719925682 + 0.0995036285526145 + + + + + + Grasshopper.Kernel.Types.GH_Plane + + -0.185997720667743 + 0.193997166513972 + 0.0820000822653364 + 0.999999999962178 + -2.0518781610844E-06 + -8.45190313769696E-06 + -3.54466189313372E-07 + -0.980580420532091 + 0.196117410927695 + + + + + + Grasshopper.Kernel.Types.GH_Plane + + -0.105999771888304 + 0.251999039129915 + 0.0819999862265907 + 0.99999999999769 + -5.16465691036329E-07 + -2.0865212969713E-06 + 1.04874966631396E-07 + -0.957826031183761 + 0.287348732356268 + + + + + + Grasshopper.Kernel.Types.GH_Plane + + -0.0199996656424884 + 0.298999726514655 + 0.0820004161657311 + 0.999999999999868 + -2.27512691418152E-09 + -5.14002900926475E-07 + 1.88783653333669E-07 + -0.928476558342992 + 0.371391007709552 + + + + + + Grasshopper.Kernel.Types.GH_Plane + + 0.0740003579052222 + 0.32899951277318 + 0.0820003156010757 + 0.999999999999684 + 1.2490174103617E-07 + -7.8504484119603E-07 + 4.62798664588472E-07 + -0.894426896821608 + 0.44721418385585 + + + + + + Grasshopper.Kernel.Types.GH_Plane + + 0.172000020951436 + 0.329999925909599 + 0.0820000368004187 + 1 + 4.15666271307642E-10 + -1.39294003799795E-09 + 9.03261390553736E-10 + -0.928476689703321 + 0.37139067930895 + + + + + + Grasshopper.Kernel.Types.GH_Plane + + 0.262999939761616 + 0.294999931783999 + 0.0820000454835823 + 0.999999999999999 + -5.07083784980938E-09 + 3.74803633872345E-08 + -1.56268860098311E-08 + -0.957826276381033 + 0.287347915033404 + + + + + + Grasshopper.Kernel.Types.GH_Plane + + 0.338999871865215 + 0.232999946632596 + 0.0820000332816467 + 0.999999999999998 + 2.74710517237015E-09 + 6.87069333086127E-08 + -1.07807833663982E-08 + -0.980580665887247 + 0.196116184156543 + + + + + + Grasshopper.Kernel.Types.GH_Plane + + 0.399999846843165 + 0.154999957387238 + 0.0819999675182763 + 1 + 5.09819622561856E-09 + 2.32074528974202E-08 + 2.76366671573588E-09 + -0.995037189116083 + 0.0995037299600652 + + + + + + Grasshopper.Kernel.Types.GH_Plane + + 0.447999785027379 + 0.0699998851799913 + 0.0819999074090274 + 1 + 7.47030142795755E-10 + 5.71081739908766E-09 + 7.47030133763101E-10 + -1 + 1.58167446951156E-09 + + + + + + + + + + + + + + 410755b1-224a-4c1e-a407-bf32fb45ea7e + 00000000-0000-0000-0000-000000000000 + Plan Motion + + + + + """ +Calculate a motion path. + +COMPAS FAB v0.23.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.23.0 + + 26 + 26 + + + 558 + 530 + + true + true + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAGNSURBVEhLtZTNbQIxEIUpgQ5ICRTAgRJyibimBErgEIkaInGgAyiBDpICuOeYnHJByuZ93vFm7B0SQBtLH4znPeO/MaOmaf6VMDkkYXJIwuS1qI3FVhzEXsw7zRs9ajOxE5tI96i9CgJPmuTcgLUzvokN32e89yJ7PfukBwMmxqcgwY+fLD4G/pVpNYekBwNeBD/4JGaWYxICdjOp/FPTalZJ92YbkFdbnL3ag+Do1j5vWr0L7mSctMD8bqa0epenQgjefd7pd2IORb7otGe/FAufN408gbqlBmocI4srd1502rIk6K1SjcnRl7Vmet55utwuX3T+PoYjmoh2SHEQ/DoBx8Ak4eNSC1dpGmOLe0v5LmgviWqAR29yHnbwJeoK49UTQLG7bKCWP8yQ2Xqj+fIj5C6692B9gpP3J80M/EER1Ex7A9odEKRXrcbbeBYc7a7nN1O+3Jqips27EEzCffhxvQeY/Onjih2Yn5rPBUEirKzkTR8X3sEt/AQXVNEthMkhCZNDEiaHoxl9A6glDpIGAdZaAAAAAElFTkSuQmCC + + false + b5094db4-def9-4481-8aea-6b11da79c1e4 + true + true + Plan Motion + Plan Motion + + + + + + 1339 + 583 + 237 + 164 + + + 1500 + 665 + + + + + + 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. + 0925bfe8-6585-4b39-83bd-61aa7f76676d + robot + robot + true + 0 + true + d4bae7b0-750f-4b86-a929-7bf58d55c307 + 1 + 87f87f55-5b71-41f4-8aea-21d494016f81 + 2 + + + + + + 1341 + 585 + 144 + 20 + + + 1414.5 + 595 + + + + + + + + 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. + 4203eb38-581c-4e89-a579-18f1b8aaa100 + goal_constraints + goal_constraints + true + 1 + true + dc06fc26-c9fb-42f7-b166-dbedee774c54 + 1 + 87f87f55-5b71-41f4-8aea-21d494016f81 + + + + + + 1341 + 605 + 144 + 20 + + + 1414.5 + 615 + + + + + + + + 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. + 353b9ef0-7ceb-42cd-bdc1-44e528f2cb5a + start_configuration + start_configuration + true + 0 + true + d21b302d-733d-43c3-99b7-ed76b289ccf2 + 1 + 87f87f55-5b71-41f4-8aea-21d494016f81 + + + + + + 1341 + 625 + 144 + 20 + + + 1414.5 + 635 + + + + + + + + true + The planning group used for calculation. Defaults to the robot's main planning group. + 6a57f432-325c-4bde-9ec6-e50cc6a40947 + group + group + true + 0 + true + 0 + 37261734-eec7-4f50-b6a8-b8d1f3c4396b + + + + + + 1341 + 645 + 144 + 20 + + + 1414.5 + 655 + + + + + + + + 1 + true + A list of attached collision meshes to be included for planning. + 10373bc6-4f63-4879-9e40-9d61bd3b2cd5 + attached_collision_meshes + attached_collision_meshes + true + 1 + true + 0 + 87f87f55-5b71-41f4-8aea-21d494016f81 + + + + + + 1341 + 665 + 144 + 20 + + + 1414.5 + 675 + + + + + + + + 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. + e598a986-1d3a-4f72-896d-67b9963501f3 + path_constraints + path_constraints + true + 1 + true + 0 + 87f87f55-5b71-41f4-8aea-21d494016f81 + + + + + + 1341 + 685 + 144 + 20 + + + 1414.5 + 695 + + + + + + + + true + The name of the algorithm used for path planning. Defaults to 'RRTConnect' + 811868ee-de48-49c2-8c37-399214e45ad9 + planner_id + planner_id + true + 0 + true + 0 + 37261734-eec7-4f50-b6a8-b8d1f3c4396b + + + + + + 1341 + 705 + 144 + 20 + + + 1414.5 + 715 + + + + + + + + true + If True, calculates a trajectory. + d898a50d-c871-4183-911c-0a866f2010fb + compute + compute + true + 0 + true + 0e039002-4ace-4096-9c19-39d45feca304 + 1 + d60527f5-b5af-4ef6-8970-5f96fe412559 + + + + + + 1341 + 725 + 144 + 20 + + + 1414.5 + 735 + + + + + + + + The calculated trajectory. + ef509c78-ae6e-423b-8fb9-de1fa352953c + trajectory + trajectory + false + 0 + + + + + + 1515 + 585 + 59 + 160 + + + 1544.5 + 665 + + + + + + + + + + + + + + 59daf374-bc21-4a5e-8282-5504fb7ae9ae + List Item + + + + + 0 + Retrieve a specific item from a list. + 00b1de58-fe69-4814-b75e-0502b3df897b + List Item + Item + + + + + + 991 + 683 + 65 + 64 + + + 1026 + 715 + + + + + + 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 + fee18168-7838-44a2-9eaf-27915eb404c9 + List + L + false + 66f1bdea-7701-4476-b28d-6ea50cb1a15e + 1 + + + + + + 993 + 685 + 18 + 20 + + + 1003.5 + 695 + + + + + + + + Item index + 2bb70c21-862c-4870-8ac1-cf4383ce74bd + Index + i + false + 65803e22-e03d-4119-84d2-9b18c4a45841 + 1 + + + + + + 993 + 705 + 18 + 20 + + + 1003.5 + 715 + + + + + + 1 + + + + + 1 + {0} + + + + + 0 + + + + + + + + + + + Wrap index to list bounds + 333ced2f-fc7e-46be-bf21-ee7607435227 + Wrap + W + false + 0 + + + + + + 993 + 725 + 18 + 20 + + + 1003.5 + 735 + + + + + + 1 + + + + + 1 + {0} + + + + + true + + + + + + + + + + + Item at {i'} + d21b302d-733d-43c3-99b7-ed76b289ccf2 + false + Item + i + false + 0 + + + + + + 1041 + 685 + 13 + 60 + + + 1047.5 + 715 + + + + + + + + + + + + + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider + + + + + Numeric slider for single values + 65803e22-e03d-4119-84d2-9b18c4a45841 + Number Slider + + false + 0 + + + + + + 783 + 705 + 162 + 20 + + + 783.4814 + 705.1565 + + + + + + 3 + 1 + 1 + 10 + 0 + 0 + 0 + + + + + + + + + 59daf374-bc21-4a5e-8282-5504fb7ae9ae + List Item + + + + + 0 + Retrieve a specific item from a list. + 7972a781-fcad-4a57-a252-306c16d3e803 + List Item + Item + + + + + + 990 + 771 + 65 + 64 + + + 1025 + 803 + + + + + + 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 + 140d4327-f1e3-491e-bdcc-9ed0ee59a233 + List + L + false + 66f1bdea-7701-4476-b28d-6ea50cb1a15e + 1 + + + + + + 992 + 773 + 18 + 20 + + + 1002.5 + 783 + + + + + + + + Item index + 114346bd-6c36-43e3-b036-80561e5481e7 + Index + i + false + d4707977-5878-4e65-9fc1-6520d5f1ff16 + 1 + + + + + + 992 + 793 + 18 + 20 + + + 1002.5 + 803 + + + + + + 1 + + + + + 1 + {0} + + + + + 0 + + + + + + + + + + + Wrap index to list bounds + c910915d-637b-436a-8cd9-bdc20a8fd94c + Wrap + W + false + 0 + + + + + + 992 + 813 + 18 + 20 + + + 1002.5 + 823 + + + + + + 1 + + + + + 1 + {0} + + + + + true + + + + + + + + + + + Item at {i'} + 5724622f-add7-4b93-b0de-a03bb6db0ef2 + false + Item + i + false + 0 + + + + + + 1040 + 773 + 13 + 60 + + + 1046.5 + 803 + + + + + + + + + + + + + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider + + + + + Numeric slider for single values + d4707977-5878-4e65-9fc1-6520d5f1ff16 + Number Slider + + false + 0 + + + + + + 791 + 793 + 162 + 20 + + + 791.1313 + 793.7065 + + + + + + 3 + 1 + 1 + 10 + 0 + 0 + 8 + + + + + + + + + 410755b1-224a-4c1e-a407-bf32fb45ea7e + 00000000-0000-0000-0000-000000000000 + GhPython Script + + + + + goal_constraints = robot.constraints_from_configuration(config, +[0.1]*6, [0.1]*6) + GhPython provides a Python script component + + 52 + 52 + + + 558 + 530 + + true + false + false + 69358696-5598-48f9-b134-3be62b11ac5b + false + true + GhPython Script + Python + + + + + + 1099 + 771 + 168 + 44 + + + 1156 + 793 + + + + + + 2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 2 + 3ede854e-c753-40eb-84cb-b48008f14fd4 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + + + + + true + Script variable Python + ccd6b604-f098-4f46-b47d-e31d7e76f08d + x + robot + true + 0 + true + d4bae7b0-750f-4b86-a929-7bf58d55c307 + 1 + 35915213-5534-4277-81b8-1bdc9e7383d2 + + + + + + 1101 + 773 + 40 + 20 + + + 1122.5 + 783 + + + + + + + + true + Script input config. + feaa9a74-0da6-4c61-a4cf-0a7214e722f9 + config + config + true + 0 + true + 5724622f-add7-4b93-b0de-a03bb6db0ef2 + 1 + 35915213-5534-4277-81b8-1bdc9e7383d2 + + + + + + 1101 + 793 + 40 + 20 + + + 1122.5 + 803 + + + + + + + + The execution information, as output and error streams + 2dd3c4e5-061d-4628-8b0f-4b37c2438998 + out + out + false + 0 + + + + + + 1171 + 773 + 94 + 20 + + + 1218 + 783 + + + + + + + + Script output goal_constraints. + dc06fc26-c9fb-42f7-b166-dbedee774c54 + a + goal_constraints + false + 0 + + + + + + 1171 + 793 + 94 + 20 + + + 1218 + 803 + + + + + + + + + + + + + + a8b97322-2d53-47cd-905e-b932c3ccd74e + Button + + + + + Button object with two values + False + True + 0e039002-4ace-4096-9c19-39d45feca304 + Button + Button + false + 0 + + + + + + 1195 + 726 + 105 + 22 + + + + + + + + + + 410755b1-224a-4c1e-a407-bf32fb45ea7e + 00000000-0000-0000-0000-000000000000 + Trajectory Visualize + + + + + """ +Visualizes a trajectory. + +COMPAS FAB v0.23.0 +""" +from compas_ghpython import draw_frame +from compas_ghpython import list_to_ghtree +from ghpythonlib.componentbase import executingcomponent as component + + +class TrajectoryVisualize(component): + def RunScript(self, robot, group, trajectory): + start_configuration = None + configurations = [] + fraction = 0. + time = 0. + + planes = [] + positions = [] + velocities = [] + accelerations = [] + + if robot and trajectory: + group = group or robot.main_group_name + + for c in trajectory.points: + configurations.append(robot.merge_group_with_full_configuration(c, trajectory.start_configuration, group)) + frame = robot.forward_kinematics(c, group, options=dict(solver='model')) + planes.append(draw_frame(frame)) + positions.append(c.positions) + velocities.append(c.velocities) + accelerations.append(c.accelerations) + + start_configuration = trajectory.start_configuration + fraction = trajectory.fraction + time = trajectory.time_from_start + + P = list_to_ghtree(list(zip(*positions))) + V = list_to_ghtree(list(zip(*velocities))) + A = list_to_ghtree(list(zip(*accelerations))) + + # return outputs if you have them; here I try it for you: + return (start_configuration, configurations, fraction, time, planes, P, V, A) + + Visualizes a trajectory. +COMPAS FAB v0.23.0 + true + true + + iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAACxIAAAsSAdLdfvwAAAHiSURBVEhLtZMxS0JhFIZNNJASEqesuOLUFIJT4CC0R4u4BEm/wCnXQMKmfkGDQ1NLLtHq0BgUDUFwi36BNrUU3s57OcfO/e4xKuzCg973fc/5znfvdxNBEPwrpjhLTHGWmOJfWD253iEGzCGxBN0MCxTqckHV8gXym0TgMIBnFgAKvKlwlXgnGlOyd5xzKcfCXOARpxxCY/k/JmK7Yc+iFglyGM1h+kQ4MWvYUbiYUdMn3OavxFIkyOHJ5I6Ox9QgLgjP8YrEC6EXaMKbhFQYC2BS3/CkuOV67NeYomhWCFO2iMiU7I0ILBCekCn+SGuRAOAG5pSk4dgC60VjqLBW65EQkBAKDA9NMOWt4WHneLR0+6VHQoAC8jWaUxaOrqgqIZwrr5rKrzyyPhTdbYAvEp85mLwo5eMkBZmN2ofbqNC5fGYNHIuui3soVuAcl8VXOS+7tdtTzerQ83udsdIqkpeiMjd16UlQIA3fQZDMZMNm6eXSGbT5tfUH3M+l0vc6L0U4u9YC046jv7C5HS6QyhfCbDKzKDto66wUTNtBX4cF0r38ftfnhkGufqAfT0lnddGP3oGGriduOuTfm1hG31DDb0+RC11tbixEHk+YcYXfQFdFNQe5WMYVZo0pzo4g8QkeesDrM2SJXwAAAABJRU5ErkJggg== + + false + 871ff208-19c2-4cf6-84ff-59272508f238 + true + true + Trajectory Visualize + Trajectory Visualize + + + + + + 1689 + 509 + 198 + 164 + + + 1762 + 591 + + + + + + 3 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2 + 8 + 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 + 8ec86459-bf01-4409-baee-174d0d2b13d0 + + + + + true + The robot. + 59eb3e16-ee68-4729-96d1-e737bb2bbab6 + robot + robot + true + 0 + true + d4bae7b0-750f-4b86-a929-7bf58d55c307 + 1 + 87f87f55-5b71-41f4-8aea-21d494016f81 + 2 + + + + + + 1691 + 511 + 56 + 53 + + + 1720.5 + 537.6667 + + + + + + + + true + The planning group for which this trajectory was planned. + e1020857-c012-4969-a50e-16f6743bbd23 + group + group + true + 0 + true + 0 + 37261734-eec7-4f50-b6a8-b8d1f3c4396b + + + + + + 1691 + 564 + 56 + 53 + + + 1720.5 + 591 + + + + + + + + true + The calculated trajectory. + 6698a6b9-c1f8-43d1-8c0c-1ca25887f8e1 + trajectory + trajectory + true + 0 + true + ef509c78-ae6e-423b-8fb9-de1fa352953c + 1 + 87f87f55-5b71-41f4-8aea-21d494016f81 + + + + + + 1691 + 617 + 56 + 54 + + + 1720.5 + 644.3334 + + + + + + + + The start configuration of the trajectory. + 122f1810-7687-4d98-bc4f-29960a34ca0b + start_configuration + start_configuration + false + 0 + + + + + + 1777 + 511 + 108 + 20 + + + 1831 + 521 + + + + + + + + The full configurations along the trajectory. + 4d6b08c4-577b-4ff5-b693-47e44827bac5 + configurations + configurations + false + 0 + + + + + + 1777 + 531 + 108 + 20 + + + 1831 + 541 + + + + + + + + Indicates the fraction of requested trajectory that was calculated, e.g. 1 means the full trajectory was found. + 8819ad14-3b9f-46a5-9e7c-2443d6971399 + fraction + fraction + false + 0 + + + + + + 1777 + 551 + 108 + 20 + + + 1831 + 561 + + + + + + + + The time which is needed to execute that trajectory at full speed. + 9dfb5357-c4b4-42de-9e80-278255c040ab + time + time + false + 0 + + + + + + 1777 + 571 + 108 + 20 + + + 1831 + 581 + + + + + + + + The planes of the robot's end-effector. + e23bb059-980f-48ba-845f-bd8eebf53eb0 + planes + planes + false + 0 + + + + + + 1777 + 591 + 108 + 20 + + + 1831 + 601 + + + + + + + + The positions along the trajectory + 0c81a3a7-14f9-4482-b237-2557c88efc87 + P + P + false + 0 + + + + + + 1777 + 611 + 108 + 20 + + + 1831 + 621 + + + + + + + + The velocities along the trajectory + 7df56f3f-f7ae-4cb6-a0c6-9c544f26c2ed + V + V + false + 0 + + + + + + 1777 + 631 + 108 + 20 + + + 1831 + 641 + + + + + + + + The accelerations along the trajectory + 4ecc7121-84c5-4585-abe6-feb8e42a25a8 + A + A + false + 0 + + + + + + 1777 + 651 + 108 + 20 + + + 1831 + 661 + + + + + + + + + + + + + + 59daf374-bc21-4a5e-8282-5504fb7ae9ae + List Item + + + + + 0 + Retrieve a specific item from a list. + true + eddec187-c6b4-4a85-bf6d-826a6e3b4117 + List Item + Item + + + + + + 1697 + 396 + 65 + 64 + + + 1732 + 428 + + + + + + 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 + 54564c7d-1328-42c6-9e85-1975267ed45a + List + L + false + 4d6b08c4-577b-4ff5-b693-47e44827bac5 + 1 + + + + + + 1699 + 398 + 18 + 20 + + + 1709.5 + 408 + + + + + + + + Item index + 668e6f05-59cd-4725-8a0e-7654764867ce + Index + i + false + cd1f39f7-c7b1-4f55-b426-b32b1fcf49e4 + 1 + + + + + + 1699 + 418 + 18 + 20 + + + 1709.5 + 428 + + + + + + 1 + + + + + 1 + {0} + + + + + 0 + + + + + + + + + + + Wrap index to list bounds + d27d40b3-645c-43e8-ad05-0d950aafedf9 + Wrap + W + false + 0 + + + + + + 1699 + 438 + 18 + 20 + + + 1709.5 + 448 + + + + + + 1 + + + + + 1 + {0} + + + + + true + + + + + + + + + + + Item at {i'} + 413f4b7d-50ca-45ce-9bd2-84a106772d59 + false + Item + i + false + 0 + + + + + + 1747 + 398 + 13 + 60 + + + 1753.5 + 428 + + + + + + + + + + + + + + 57da07bd-ecab-415d-9d86-af36d7073abc + Number Slider + + + + + Numeric slider for single values + cd1f39f7-c7b1-4f55-b426-b32b1fcf49e4 + Number Slider + + false + 0 + + + + + + 1499 + 488 + 162 + 20 + + + 1499.15 + 488.95 + + + + + + 3 + 1 + 1 + 10 + 0 + 0 + 0 + + + + + + + + + + + + + + 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 + + + + + \ No newline at end of file