From 1279610f2459b2deb42f783a9640a4fc1056e329 Mon Sep 17 00:00:00 2001
From: Stephen30 <91248027+stephen300105@users.noreply.github.com>
Date: Wed, 23 Mar 2022 05:04:07 +0100
Subject: [PATCH 1/2] Ming_Yang, Wang assignment
---
lecture_04/assignment_03/assignment-03.json | 1 +
lecture_04/assignment_03/assignment_03.py | 76 +++++++++++++++++++++
2 files changed, 77 insertions(+)
create mode 100644 lecture_04/assignment_03/assignment-03.json
create mode 100644 lecture_04/assignment_03/assignment_03.py
diff --git a/lecture_04/assignment_03/assignment-03.json b/lecture_04/assignment_03/assignment-03.json
new file mode 100644
index 0000000..869c177
--- /dev/null
+++ b/lecture_04/assignment_03/assignment-03.json
@@ -0,0 +1 @@
+[{"dtype": "compas.robots/Configuration", "value": {"joint_values": [2.561262720869387, -5.845043360828665, -1.067981152698738, -4.0825497691261345, 1.5707964585802723, 4.132059047869463], "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.212580402338498, -5.6890812488180975, -1.4328564192444617, -3.87363666067149, 1.5707964587832621, 3.7833767293385714], "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.8257972591896752, -5.625716027297366, -1.5888987135132564, -3.780959638934701, 1.5707964423990544, 3.3965935861897454], "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.4690334553023976, -5.638830284028951, -1.5560718566051077, -3.8006722817307574, 1.5707964110613697, 3.039829782302467], "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.1849644879977033, -5.719080940749628, -1.3609189851999328, -3.9155745228308336, 1.5707963742135331, 2.7557608149977737], "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.9504148713420365, -5.857413858219323, -1.0398192304557676, -4.098341373414232, 1.5707963369781726, 2.5212111983421095], "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.7304478559449634, -6.040034968906261, -0.632294992266762, -4.323244504758792, 1.5707962986336736, 2.3012441829450396], "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.9609183626460736, -2.2560051576574396, -1.7804900223131386, -0.67589380051819, 1.5707963283936743, -0.39012203603423334], "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.2151951573367987, -2.3018552476676435, -1.6818990100531652, -0.7286347232264484, 1.5707963283139124, -0.6443988307249585], "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.4614541701041044, -2.354350707857781, -1.5695136332221329, -0.788524640291731, 1.5707963281244355, -0.8906578434922641], "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.6933975993893724, -2.432441231285667, -1.4030353091719046, -0.8769124412710774, 1.5707963278493013, -1.122601272777532], "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/assignment_03.py b/lecture_04/assignment_03/assignment_03.py
new file mode 100644
index 0000000..61f0be7
--- /dev/null
+++ b/lecture_04/assignment_03/assignment_03.py
@@ -0,0 +1,76 @@
+"""Assignment 03: Using inverse kinematics
+"""
+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 Translation
+from compas.geometry import Point
+from compas.geometry import Vector
+
+import math
+
+
+# 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 = []
+
+ T = Translation.from_vector([0.1,0,0.1])
+ frame_0 = frames[0].transformed(T)
+
+ start_configuration = robot.zero_configuration()
+
+ # Configuration.joint_values = (0,-math.pi/2,0,-math.pi/2,0,0)
+ # configs.append(start_configuration)
+
+ configuration_1st = robot.inverse_kinematics(frame_0, start_configuration)
+ configs.append(configuration_1st)
+
+
+ for i,f in enumerate(frames):
+ c = robot.inverse_kinematics(f,configs[i])
+ configs.append(c)
+
+ configs.pop(0)
+
+ 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.000)),
+ Frame(Point(-0.186, 0.194, 0.082), Vector(1.000, 0.000, 0.000), Vector(0.000, -1.000, 0.000)),
+ Frame(Point(-0.106, 0.252, 0.082), Vector(1.000, 0.000, 0.000), Vector(0.000, -1.000, 0.000)),
+ Frame(Point(-0.020, 0.299, 0.082), Vector(1.000, 0.000, 0.000), Vector(0.000, -1.000, 0.000)),
+ Frame(Point(0.074, 0.329, 0.082), Vector(1.000, 0.000, 0.000), Vector(0.000, -1.000, 0.000)),
+ Frame(Point(0.172, 0.330, 0.082), Vector(1.000, 0.000, 0.000), Vector(0.000, -1.000, 0.000)),
+ Frame(Point(0.263, 0.295, 0.082), Vector(1.000, 0.000, 0.000), Vector(0.000, -1.000, 0.000)),
+ Frame(Point(0.339, 0.233, 0.082), Vector(1.000, 0.000, 0.000), Vector(0.000, -1.000, 0.000)),
+ Frame(Point(0.400, 0.155, 0.082), Vector(1.000, 0.000, 0.000), Vector(0.000, -1.000, 0.000)),
+ 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))
From 8490f3cc8e385893d1c8f77fda9a67a3e65f8751 Mon Sep 17 00:00:00 2001
From: Stephen30 <91248027+stephen300105@users.noreply.github.com>
Date: Wed, 23 Mar 2022 05:05:00 +0100
Subject: [PATCH 2/2] Update solution_viewer.ghx
---
lecture_04/assignment_03/solution_viewer.ghx | 1246 ++++++++++++++++--
1 file changed, 1115 insertions(+), 131 deletions(-)
diff --git a/lecture_04/assignment_03/solution_viewer.ghx b/lecture_04/assignment_03/solution_viewer.ghx
index 984ddf4..b5e7fef 100644
--- a/lecture_04/assignment_03/solution_viewer.ghx
+++ b/lecture_04/assignment_03/solution_viewer.ghx
@@ -48,10 +48,10 @@
-
- 76
- 184
+ 107
+ -57
- - 0.7676566
+ - 1.27500021
@@ -73,8 +73,8 @@
- - GhPython, Version=7.15.22039.13001, Culture=neutral, PublicKeyToken=null
- - 7.15.22039.13001
+ - GhPython, Version=7.14.22010.17001, Culture=neutral, PublicKeyToken=null
+ - 7.14.22010.17001
- 00000000-0000-0000-0000-000000000000
@@ -85,9 +85,9 @@
- - 11
+ - 19
-
+
- 2e78987b-9dfb-42a2-8b76-3923ac8bd91a
@@ -110,7 +110,7 @@
-
31
228
- 110
+ 113
22
@@ -141,7 +141,7 @@
-
29
252
- 94
+ 96
22
@@ -208,8 +208,8 @@ configuration = calculate_ik_for_frames(robot, frames)
- GhPython provides a Python script component
-
- 905
- -745
+ 304
+ 304
-
685
@@ -228,10 +228,10 @@ configuration = calculate_ik_for_frames(robot, frames)
-
- 787
- 233
- 149
- 60
+ 785
+ 241
+ 156
+ 44
-
844
@@ -266,14 +266,14 @@ configuration = calculate_ik_for_frames(robot, frames)
-
- 789
- 235
- 40
- 28
+ 787
+ 243
+ 42
+ 20
-
- 810.5
- 249
+ 809.5
+ 253
@@ -298,14 +298,14 @@ configuration = calculate_ik_for_frames(robot, frames)
-
- 789
+ 787
263
- 40
- 28
+ 42
+ 20
-
- 810.5
- 277
+ 809.5
+ 273
@@ -325,12 +325,12 @@ configuration = calculate_ik_for_frames(robot, frames)
-
859
- 235
- 75
- 56
+ 243
+ 80
+ 40
-
- 896.5
+ 899
263
@@ -361,9 +361,9 @@ configuration = calculate_ik_for_frames(robot, frames)
-
- 990
+ 989
251
- 64
+ 65
64
-
@@ -397,13 +397,13 @@ configuration = calculate_ik_for_frames(robot, frames)
-
- 992
+ 991
253
- 17
+ 18
20
-
- 1002
+ 1001.5
263
@@ -424,13 +424,13 @@ configuration = calculate_ik_for_frames(robot, frames)
-
- 992
+ 991
273
- 17
+ 18
20
-
- 1002
+ 1001.5
283
@@ -470,13 +470,13 @@ configuration = calculate_ik_for_frames(robot, frames)
-
- 992
+ 991
293
- 17
+ 18
20
-
- 1002
+ 1001.5
303
@@ -555,14 +555,14 @@ configuration = calculate_ik_for_frames(robot, frames)
-
- 697
+ 716
338
- 160
+ 162
20
-
- 697.8439
- 338.424
+ 716.2881
+ 338.076
@@ -574,7 +574,7 @@ configuration = calculate_ik_for_frames(robot, frames)
- 10
- 0
- 0
- - 0
+ - 3
@@ -601,9 +601,9 @@ configuration = calculate_ik_for_frames(robot, frames)
-
688
- 267
+ 265
50
- 20
+ 24
-
713.3483
@@ -869,7 +869,7 @@ COMPAS FAB v0.22.0
- true
- true
-
- iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAALDwAACw8BkvkDpQAAAdZJREFUSEu1lD2O4kAQRrkBcwP2BnADfARuABEhcAMcEEyCQKuVCCEkY27A3ADCyUAimQyHm/V+r9bNNp5iSLwtPWF/9dvdZRohhP+KK9aJK9aJK9aJKzpk4k08W4XYiB/CYquJPJbX6zVMp9PQbrcV0XhIt9sN6/VaIVZoQLyXMGVC8piYXwp5jMfj0Gq1zK/f7yvUVsdLGnkRBV0RlHT2/g2WHH+KonmJI4PD4ZA6HwVFPd9IR1hTzWZTj76Tcjay1Wr1QWIKnE6n0Ov17DnhXeSiWnTJbvHZ7/d3BkNrg3E2m/2OBbiH4XCITkLg+YhNnMVtakRuib0CWgMMYlMUxetutzPH8vwZ00f+HB8auznHe6CxagDdnMt3ztPOkunAWYsiPcF3YYxGo19ZloXtdvtT78d4b9yDVpEmf8Eg8qiJt7gLCi0WC9v2IxjV6Mu9aU3SAh2MYhI1wZaPBMcZfwadl8n5oqX8Sya7OZkhgSJoge1Xu04pE/Ot3E4hTUQBmyDB+d7ZBIU4f4INBmE+n3/meR4ul8tS2pe4+5e/91CURRjH7BuYIIYCX/vf8fgqaKYFHxEvz6CZh8nBFUGLQl7nN7y4Kq5YJ65YJ65YJ65YH6HxB7b14P1B22tpAAAAAElFTkSuQmCC
+ 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
@@ -882,9 +882,9 @@ COMPAS FAB v0.22.0
-
- 178
+ 176
187
- 153
+ 159
64
-
@@ -921,13 +921,13 @@ COMPAS FAB v0.22.0
-
- 180
+ 178
189
- 46
+ 48
20
-
- 204.5
+ 203.5
199
@@ -951,13 +951,13 @@ COMPAS FAB v0.22.0
-
- 180
+ 178
209
- 46
+ 48
20
-
- 204.5
+ 203.5
219
@@ -982,13 +982,13 @@ COMPAS FAB v0.22.0
-
- 180
+ 178
229
- 46
+ 48
20
-
- 204.5
+ 203.5
239
@@ -1010,11 +1010,11 @@ COMPAS FAB v0.22.0
-
256
189
- 73
+ 77
30
-
- 292.5
+ 294.5
204
@@ -1036,11 +1036,11 @@ COMPAS FAB v0.22.0
-
256
219
- 73
+ 77
30
-
- 292.5
+ 294.5
234
@@ -1093,7 +1093,7 @@ COMPAS FAB v0.22.0
- true
- true
-
- iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAALDwAACw8BkvkDpQAAAVtJREFUSEu9lMFRwzAQRVMCJaSElJASUgIlUAGTEhguXHPinBJSAiWkBDow/9n6ZmWtQzwYduaNpdVqtf5redN13Z+SOtckdS5B9iCeeKbrmXMJsrNg8CkOzXo1Gao5iYtg4z6uR2SP4iqY+Ans3Y5xk00sTjfsBcmOgbjOmMK2wvs/mgNKQL8o3sRzmb8Iy5BRySLbifHNpwsM3gWHvJY5ByAb44xKRtkoTz+vJkNiBn7CQXAIr29oqNd7OWTIhHxMrmNOD0oQb2EdSYL2VUUlDjlJ5kKQMDa8lahsdEPdNFfUHFLiiYsNJ766D9WG3lHLYy7TOCOjEArLi2gcQ7ATR2bvxC1yZ/7VjI1bQu4cXjt+KeaYxd8idQLJQmLDoelPbY7UaWTxCzGnLHaO1Glkv2546xhubUz2E8i2m+YxreP7Ji9htvmt4x8O4Ffhn9q93C/R2qTO9eg2XxfZxOCoCLXEAAAAAElFTkSuQmCC
+ iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAALDQAACw0B7QfALAAAAVtJREFUSEu9lMFRwzAQRVMCJaSElJASUgIlUAGTEhguXHPinBJSAiWkBDow/9n6ZmWtQzwYduaNpdVqtf5redN13Z+SOtckdS5B9iCeeKbrmXMJsrNg8CkOzXo1Gao5iYtg4z6uR2SP4iqY+Ans3Y5xk00sTjfsBcmOgbjOmMK2wvs/mgNKQL8o3sRzmb8Iy5BRySLbifHNpwsM3gWHvJY5ByAb44xKRtkoTz+vJkNiBn7CQXAIr29oqNd7OWTIhHxMrmNOD0oQb2EdSYL2VUUlDjlJ5kKQMDa8lahsdEPdNFfUHFLiiYsNJ766D9WG3lHLYy7TOCOjEArLi2gcQ7ATR2bvxC1yZ/7VjI1bQu4cXjt+KeaYxd8idQLJQmLDoelPbY7UaWTxCzGnLHaO1Glkv2546xhubUz2E8i2m+YxreP7Ji9htvmt4x8O4Ffhn9q93C/R2qTO9eg2XxfZxOCoCLXEAAAAAElFTkSuQmCC
- false
- ed6dd17e-9615-4209-9f27-8c842a439b86
@@ -1106,10 +1106,10 @@ COMPAS FAB v0.22.0
-
- 384
- 224
- 124
- 54
+ 381
+ 229
+ 129
+ 44
-
454
@@ -1144,14 +1144,14 @@ COMPAS FAB v0.22.0
-
- 386
- 226
- 53
- 25
+ 383
+ 231
+ 56
+ 20
-
- 414
- 238.5
+ 412.5
+ 241
@@ -1175,14 +1175,14 @@ COMPAS FAB v0.22.0
-
- 386
+ 383
251
- 53
- 25
+ 56
+ 20
-
- 414
- 263.5
+ 412.5
+ 261
@@ -1202,12 +1202,12 @@ COMPAS FAB v0.22.0
-
469
- 226
- 37
- 50
+ 231
+ 39
+ 40
-
- 487.5
+ 488.5
251
@@ -1228,7 +1228,7 @@ COMPAS FAB v0.22.0
-
+
- """
Visualizes the robot.
@@ -1294,10 +1294,11 @@ class RobotVisualize(component):
- Visualizes the robot.
COMPAS FAB v0.22.0
+ - true
- true
- true
-
- iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAALDwAACw8BkvkDpQAAAdhJREFUSEu1lLFKA0EQhlUIQVBMOhGLgGAtxAcIYmmRJpWNrZ2dhSCWqURtxC6VRSofIYWlhS8QyBMEOzvP/zt2jtm9VSLEg+9ud2bnn9nZu1spiuJfyRqXSdb4F3ZvX1vigmfOXzP8FQm/iEJ8iH7qjyZUIUZiIgjseb9HvjMxE4jbE4jt2Lo0CGca0BOI3Ti8nzGFdYTFv9cShAWlUzyK6zC/E9aGHFFbND8Q1c5TBwHPgiQPYU4C2uZFPVEbNa/aA9wqg5wIE2RP6AuSsH2DAzV/2Q49aRPtwzYzTW5VBXKwC+sjIvQ+qiiso52IWSG00B941CKfwA7UDs0qqiUJ61nnD5z10ffALe2hb48x8Ws88lEIhWWLqBnC4jQBRIUsStYosdxbUx6croFgAJcWo6st5sE+ruw28EiMbfs3xbjBnxWKEw8quw1SEEvEgaQtCQydWJv1zjb3OpFoisT8G2KMJNINYlBWq8t2NfQakWCKxH48cAlNg+CT8AmPvUYkCArmq82JRmydnJeCa+sbX42dvfsgPk31ogko2L7kX9m+GpcJYLXR/AzjqD0QTUDBCyWA5v5hlSTQTfWiCSiQX4X91H5l8+jUzgHeUi2oGZZN1rg8ipVvhzuVIxcFIsQAAAAASUVORK5CYII=
+ iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAALDQAACw0B7QfALAAAAdhJREFUSEu1lLFKA0EQhlUIQVBMOhGLgGAtxAcIYmmRJpWNrZ2dhSCWqURtxC6VRSofIYWlhS8QyBMEOzvP/zt2jtm9VSLEg+9ud2bnn9nZu1spiuJfyRqXSdb4F3ZvX1vigmfOXzP8FQm/iEJ8iH7qjyZUIUZiIgjseb9HvjMxE4jbE4jt2Lo0CGca0BOI3Ti8nzGFdYTFv9cShAWlUzyK6zC/E9aGHFFbND8Q1c5TBwHPgiQPYU4C2uZFPVEbNa/aA9wqg5wIE2RP6AuSsH2DAzV/2Q49aRPtwzYzTW5VBXKwC+sjIvQ+qiiso52IWSG00B941CKfwA7UDs0qqiUJ61nnD5z10ffALe2hb48x8Ws88lEIhWWLqBnC4jQBRIUsStYosdxbUx6croFgAJcWo6st5sE+ruw28EiMbfs3xbjBnxWKEw8quw1SEEvEgaQtCQydWJv1zjb3OpFoisT8G2KMJNINYlBWq8t2NfQakWCKxH48cAlNg+CT8AmPvUYkCArmq82JRmydnJeCa+sbX42dvfsgPk31ogko2L7kX9m+GpcJYLXR/AzjqD0QTUDBCyWA5v5hlSTQTfWiCSiQX4X91H5l8+jUzgHeUi2oGZZN1rg8ipVvhzuVIxcFIsQAAAAASUVORK5CYII=
- false
- 10a49928-eb17-4269-a1f5-98ee19233fed
@@ -1310,9 +1311,9 @@ COMPAS FAB v0.22.0
-
- 1235
+ 1225
231
- 261
+ 278
204
-
@@ -1362,13 +1363,13 @@ COMPAS FAB v0.22.0
-
- 1237
+ 1227
233
- 134
+ 144
20
-
- 1305.5
+ 1300.5
243
@@ -1392,13 +1393,13 @@ COMPAS FAB v0.22.0
-
- 1237
+ 1227
253
- 134
+ 144
20
-
- 1305.5
+ 1300.5
263
@@ -1423,13 +1424,13 @@ COMPAS FAB v0.22.0
-
- 1237
+ 1227
273
- 134
+ 144
20
-
- 1305.5
+ 1300.5
283
@@ -1454,13 +1455,13 @@ COMPAS FAB v0.22.0
-
- 1237
+ 1227
293
- 134
+ 144
20
-
- 1305.5
+ 1300.5
303
@@ -1484,13 +1485,13 @@ COMPAS FAB v0.22.0
-
- 1237
+ 1227
313
- 134
+ 144
20
-
- 1305.5
+ 1300.5
323
@@ -1514,13 +1515,13 @@ COMPAS FAB v0.22.0
-
- 1237
+ 1227
333
- 134
+ 144
20
-
- 1305.5
+ 1300.5
343
@@ -1544,13 +1545,13 @@ COMPAS FAB v0.22.0
-
- 1237
+ 1227
353
- 134
+ 144
20
-
- 1305.5
+ 1300.5
363
@@ -1574,13 +1575,13 @@ COMPAS FAB v0.22.0
-
- 1237
+ 1227
373
- 134
+ 144
20
-
- 1305.5
+ 1300.5
383
@@ -1604,13 +1605,13 @@ COMPAS FAB v0.22.0
-
- 1237
+ 1227
393
- 134
+ 144
20
-
- 1305.5
+ 1300.5
403
@@ -1634,13 +1635,13 @@ COMPAS FAB v0.22.0
-
- 1237
+ 1227
413
- 134
+ 144
20
-
- 1305.5
+ 1300.5
423
@@ -1662,11 +1663,11 @@ COMPAS FAB v0.22.0
-
1401
233
- 93
+ 100
33
-
- 1447.5
+ 1451
249.6667
@@ -1688,11 +1689,11 @@ COMPAS FAB v0.22.0
-
1401
266
- 93
+ 100
33
-
- 1447.5
+ 1451
283
@@ -1714,11 +1715,11 @@ COMPAS FAB v0.22.0
-
1401
299
- 93
+ 100
34
-
- 1447.5
+ 1451
316.3333
@@ -1740,11 +1741,11 @@ COMPAS FAB v0.22.0
-
1401
333
- 93
+ 100
33
-
- 1447.5
+ 1451
349.6667
@@ -1766,11 +1767,11 @@ COMPAS FAB v0.22.0
-
1401
366
- 93
+ 100
33
-
- 1447.5
+ 1451
383
@@ -1792,11 +1793,11 @@ COMPAS FAB v0.22.0
-
1401
399
- 93
+ 100
34
-
- 1447.5
+ 1451
416.3333
@@ -1809,6 +1810,989 @@ COMPAS FAB v0.22.0
+
+
+ - 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/xhBQAAAAlwSFlzAAALDAAACwwBP0AiyAAAAdhJREFUSEu1lLFKA0EQhlUIQVBMOhGLgGAtxAcIYmmRJpWNrZ2dhSCWqURtxC6VRSofIYWlhS8QyBMEOzvP/zt2jtm9VSLEg+9ud2bnn9nZu1spiuJfyRqXSdb4F3ZvX1vigmfOXzP8FQm/iEJ8iH7qjyZUIUZiIgjseb9HvjMxE4jbE4jt2Lo0CGca0BOI3Ti8nzGFdYTFv9cShAWlUzyK6zC/E9aGHFFbND8Q1c5TBwHPgiQPYU4C2uZFPVEbNa/aA9wqg5wIE2RP6AuSsH2DAzV/2Q49aRPtwzYzTW5VBXKwC+sjIvQ+qiiso52IWSG00B941CKfwA7UDs0qqiUJ61nnD5z10ffALe2hb48x8Ws88lEIhWWLqBnC4jQBRIUsStYosdxbUx6croFgAJcWo6st5sE+ruw28EiMbfs3xbjBnxWKEw8quw1SEEvEgaQtCQydWJv1zjb3OpFoisT8G2KMJNINYlBWq8t2NfQakWCKxH48cAlNg+CT8AmPvUYkCArmq82JRmydnJeCa+sbX42dvfsgPk31ogko2L7kX9m+GpcJYLXR/AzjqD0QTUDBCyWA5v5hlSTQTfWiCSiQX4X91H5l8+jUzgHeUi2oGZZN1rg8ipVvhzuVIxcFIsQAAAAASUVORK5CYII=
+
+ - false
+ - 0b2f4ee5-66ca-4077-b741-2e4858ccaeac
+ - true
+ - true
+ - Robot Visualize
+ - Robot Visualize
+
+
+
+
+ -
+ 1228
+ 474
+ 278
+ 204
+
+ -
+ 1389
+ 576
+
+
+
+
+
+ - 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.
+ - 38939a2f-4118-4dc9-9681-b4d359786df5
+ - robot
+ - robot
+ - true
+ - 0
+ - true
+ - d4bae7b0-750f-4b86-a929-7bf58d55c307
+ - 1
+ - 87f87f55-5b71-41f4-8aea-21d494016f81
+ - 2
+
+
+
+
+ -
+ 1230
+ 476
+ 144
+ 20
+
+ -
+ 1303.5
+ 486
+
+
+
+
+
+
+
+ - true
+ - The planning group used for end-effector and base visualization.
+ - 791df07c-1921-4ad1-939f-6d2fb4099503
+ - group
+ - group
+ - true
+ - 0
+ - true
+ - 0
+ - 37261734-eec7-4f50-b6a8-b8d1f3c4396b
+
+
+
+
+ -
+ 1230
+ 496
+ 144
+ 20
+
+ -
+ 1303.5
+ 506
+
+
+
+
+
+
+
+ - true
+ - The robot's full configuration.
+ - 3829e793-c4d4-492b-97c1-fdae0862756a
+ - configuration
+ - configuration
+ - true
+ - 0
+ - true
+ - 6cf97b0d-08d6-431a-9ade-d1211356b98f
+ - 1
+ - 87f87f55-5b71-41f4-8aea-21d494016f81
+
+
+
+
+ -
+ 1230
+ 516
+ 144
+ 20
+
+ -
+ 1303.5
+ 526
+
+
+
+
+
+
+
+ - 1
+ - true
+ - A list of attached collision meshes.
+ - 9175821d-cf5f-4b41-a175-9dcd0ab43931
+ - attached_collision_meshes
+ - attached_collision_meshes
+ - true
+ - 1
+ - true
+ - 0
+ - 87f87f55-5b71-41f4-8aea-21d494016f81
+
+
+
+
+ -
+ 1230
+ 536
+ 144
+ 20
+
+ -
+ 1303.5
+ 546
+
+
+
+
+
+
+
+ - true
+ - Whether or not to show the robot's visual meshes.
+ - 1e07bedb-3543-488d-911e-35d5d7fa8962
+ - show_visual
+ - show_visual
+ - true
+ - 0
+ - true
+ - 0
+ - d60527f5-b5af-4ef6-8970-5f96fe412559
+
+
+
+
+ -
+ 1230
+ 556
+ 144
+ 20
+
+ -
+ 1303.5
+ 566
+
+
+
+
+
+
+
+ - true
+ - Whether or not to show the robot's collision meshes.
+ - e5ea71d7-35b2-4bc6-bf1d-a015c26498ef
+ - show_collision
+ - show_collision
+ - true
+ - 0
+ - true
+ - 0
+ - d60527f5-b5af-4ef6-8970-5f96fe412559
+
+
+
+
+ -
+ 1230
+ 576
+ 144
+ 20
+
+ -
+ 1303.5
+ 586
+
+
+
+
+
+
+
+ - true
+ - Whether or not to show the robot's joint frames.
+ - 13069860-ce07-482a-9db9-6cb684dbce39
+ - show_frames
+ - show_frames
+ - true
+ - 0
+ - true
+ - 0
+ - d60527f5-b5af-4ef6-8970-5f96fe412559
+
+
+
+
+ -
+ 1230
+ 596
+ 144
+ 20
+
+ -
+ 1303.5
+ 606
+
+
+
+
+
+
+
+ - true
+ - Whether or not to show the robot's base frame.
+ - 4db73b53-e314-4e75-8a7b-6f526d076de2
+ - show_base_frame
+ - show_base_frame
+ - true
+ - 0
+ - true
+ - 0
+ - d60527f5-b5af-4ef6-8970-5f96fe412559
+
+
+
+
+ -
+ 1230
+ 616
+ 144
+ 20
+
+ -
+ 1303.5
+ 626
+
+
+
+
+
+
+
+ - true
+ - Whether or not to show the robot's end-effector frame.
+ - 0b78ab53-c190-41e2-a96d-077f0ac9bf05
+ - show_end_effector_frame
+ - show_end_effector_frame
+ - true
+ - 0
+ - true
+ - 0
+ - d60527f5-b5af-4ef6-8970-5f96fe412559
+
+
+
+
+ -
+ 1230
+ 636
+ 144
+ 20
+
+ -
+ 1303.5
+ 646
+
+
+
+
+
+
+
+ - true
+ - Whether or not to show the attached collision meshes (if any).
+ - a10f3fa4-1b79-4714-91b4-77f1a27336c2
+ - show_acm
+ - show_acm
+ - true
+ - 0
+ - true
+ - 0
+ - d60527f5-b5af-4ef6-8970-5f96fe412559
+
+
+
+
+ -
+ 1230
+ 656
+ 144
+ 20
+
+ -
+ 1303.5
+ 666
+
+
+
+
+
+
+
+ - The robot's visual Rhino meshes (if any).
+ - 0b833af4-7e09-425a-a702-19aed07a2cfc
+ - visual
+ - visual
+ - false
+ - 0
+
+
+
+
+ -
+ 1404
+ 476
+ 100
+ 33
+
+ -
+ 1454
+ 492.6667
+
+
+
+
+
+
+
+ - The robot's collision Rhino meshes (if any).
+ - d23c923d-4173-4e36-980a-f61ef0e808aa
+ - collision
+ - collision
+ - false
+ - 0
+
+
+
+
+ -
+ 1404
+ 509
+ 100
+ 33
+
+ -
+ 1454
+ 526
+
+
+
+
+
+
+
+ - The attached collision Rhino meshes (if any).
+ - f7ab0f71-7a87-410b-98c5-c918be908e27
+ - attached_meshes
+ - attached_meshes
+ - false
+ - 0
+
+
+
+
+ -
+ 1404
+ 542
+ 100
+ 34
+
+ -
+ 1454
+ 559.3334
+
+
+
+
+
+
+
+ - The robot's joint frames as Rhino planes (if any).
+ - 41114392-d3cf-4130-9f8a-b0e643c3f4cd
+ - frames
+ - frames
+ - false
+ - 0
+
+
+
+
+ -
+ 1404
+ 576
+ 100
+ 33
+
+ -
+ 1454
+ 592.6667
+
+
+
+
+
+
+
+ - The robot's base frame as a Rhino plane (if any).
+ - 95f47926-93b6-495f-9018-36a05b19f629
+ - base_frame
+ - base_frame
+ - false
+ - 0
+
+
+
+
+ -
+ 1404
+ 609
+ 100
+ 33
+
+ -
+ 1454
+ 626
+
+
+
+
+
+
+
+ - The robot's end-effector frame as a Rhino plane (if any).
+ - e2c6c21e-90b8-4e33-a3d5-78b1b5242ddc
+ - ee_frame
+ - ee_frame
+ - false
+ - 0
+
+
+
+
+ -
+ 1404
+ 642
+ 100
+ 33
+
+ -
+ 1454
+ 659.3333
+
+
+
+
+
+
+
+
+
+
+
+
+
+ - 57da07bd-ecab-415d-9d86-af36d7073abc
+ - Number Slider
+
+
+
+
+ - Numeric slider for single values
+ - c4b5b947-524c-4625-a940-28616064ccea
+ - Number Slider
+ - a6
+ - false
+ - 0
+
+
+
+
+ -
+ 677
+ 599
+ 227
+ 20
+
+ -
+ 677.2665
+ 599.05
+
+
+
+
+
+ - 3
+ - 1
+ - 1
+ - 360
+ - -360
+ - 0
+ - 0
+
+
+
+
+
+
+
+
+ - 410755b1-224a-4c1e-a407-bf32fb45ea7e
+ - 00000000-0000-0000-0000-000000000000
+ - Python Script
+
+
+
+
+ - import math
+from compas.robots import Configuration
+
+config = Configuration.from_revolute_values([math.radians(a) for a in vals])
+
+ - GhPython provides a Python script component
+ -
+ 191
+ 194
+
+ -
+ 1300
+ 740
+
+ - true
+ - true
+ - false
+ - d85207c1-dfae-4aa0-a6bd-8a735410940d
+ - false
+ - true
+ - Python Script
+ - config
+
+
+
+
+ -
+ 968
+ 525
+ 104
+ 28
+
+ -
+ 1012
+ 539
+
+
+
+
+
+ - 1
+ - 84fa917c-1ed8-4db3-8be1-7bdc4a6495a2
+ - 1
+ - 8ec86459-bf01-4409-baee-174d0d2b13d0
+
+
+
+
+ - 1
+ - true
+ - Script input a1.
+ - a4371db6-7801-4527-8966-3bff55e66b99
+ - vals
+ - vals
+ - true
+ - 1
+ - true
+ - 4b83dabb-3ae5-4018-bddb-47cbc06a8179
+ - aca92276-402f-4cbe-86cc-976491a7a93b
+ - 9f1b8099-978b-4566-b244-5f08f468ec49
+ - ea36e11d-cccd-43cd-954f-479a1070b8be
+ - 4badb2ae-7e0b-4097-b7c5-ac6ecd206e7d
+ - c4b5b947-524c-4625-a940-28616064ccea
+ - 6
+ - 87f87f55-5b71-41f4-8aea-21d494016f81
+
+
+
+
+ -
+ 970
+ 527
+ 27
+ 24
+
+ -
+ 985
+ 539
+
+
+
+
+
+
+
+ - Script output config.
+ - 6cf97b0d-08d6-431a-9ade-d1211356b98f
+ - config
+ - config
+ - false
+ - 0
+
+
+
+
+ -
+ 1027
+ 527
+ 43
+ 24
+
+ -
+ 1048.5
+ 539
+
+
+
+
+
+
+
+
+
+
+
+
+
+ - 57da07bd-ecab-415d-9d86-af36d7073abc
+ - Number Slider
+
+
+
+
+ - Numeric slider for single values
+ - 4badb2ae-7e0b-4097-b7c5-ac6ecd206e7d
+ - Number Slider
+ - a5
+ - false
+ - 0
+
+
+
+
+ -
+ 676
+ 576
+ 227
+ 20
+
+ -
+ 676.6666
+ 576.0501
+
+
+
+
+
+ - 3
+ - 1
+ - 1
+ - 360
+ - -360
+ - 0
+ - 0
+
+
+
+
+
+
+
+
+ - 57da07bd-ecab-415d-9d86-af36d7073abc
+ - Number Slider
+
+
+
+
+ - Numeric slider for single values
+ - 4b83dabb-3ae5-4018-bddb-47cbc06a8179
+ - Number Slider
+ - a1
+ - false
+ - 0
+
+
+
+
+ -
+ 676
+ 484
+ 227
+ 20
+
+ -
+ 676.8266
+ 484.1299
+
+
+
+
+
+ - 3
+ - 1
+ - 1
+ - 360
+ - -360
+ - 0
+ - -36
+
+
+
+
+
+
+
+
+ - 57da07bd-ecab-415d-9d86-af36d7073abc
+ - Number Slider
+
+
+
+
+ - Numeric slider for single values
+ - ea36e11d-cccd-43cd-954f-479a1070b8be
+ - Number Slider
+ - a4
+ - false
+ - 0
+
+
+
+
+ -
+ 676
+ 553
+ 227
+ 20
+
+ -
+ 676.6666
+ 553.0498
+
+
+
+
+
+ - 3
+ - 1
+ - 1
+ - 360
+ - -360
+ - 0
+ - -90
+
+
+
+
+
+
+
+
+ - 57da07bd-ecab-415d-9d86-af36d7073abc
+ - Number Slider
+
+
+
+
+ - Numeric slider for single values
+ - aca92276-402f-4cbe-86cc-976491a7a93b
+ - Number Slider
+ - a2
+ - false
+ - 0
+
+
+
+
+ -
+ 676
+ 506
+ 227
+ 20
+
+ -
+ 676.5396
+ 506.5606
+
+
+
+
+
+ - 3
+ - 1
+ - 1
+ - 360
+ - -360
+ - 0
+ - -90
+
+
+
+
+
+
+
+
+ - 57da07bd-ecab-415d-9d86-af36d7073abc
+ - Number Slider
+
+
+
+
+ - Numeric slider for single values
+ - 9f1b8099-978b-4566-b244-5f08f468ec49
+ - Number Slider
+ - a3
+ - false
+ - 0
+
+
+
+
+ -
+ 677
+ 530
+ 227
+ 20
+
+ -
+ 677.2665
+ 530.33
+
+
+
+
+
+ - 3
+ - 1
+ - 1
+ - 360
+ - -360
+ - 0
+ - 0
+
+
+
+
+
+
@@ -1816,7 +2800,7 @@ COMPAS FAB v0.22.0
-
- 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
+ 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