|
1 | 1 | import os
|
2 | 2 | from timeit import default_timer as timer
|
3 | 3 |
|
| 4 | +import numpy as np |
4 | 5 | import torch
|
5 | 6 |
|
6 | 7 | import pytorch_kinematics as pk
|
@@ -55,7 +56,8 @@ def test_jacobian_follower():
|
55 | 56 | goal_pos = goal[..., :3, 3]
|
56 | 57 | goal_rot = pk.matrix_to_euler_angles(goal[..., :3, :3], "XYZ")
|
57 | 58 |
|
58 |
| - ik = pk.PseudoInverseIK(chain, max_iterations=30, num_retries=10, |
| 59 | + num_retries = 10 |
| 60 | + ik = pk.PseudoInverseIK(chain, max_iterations=30, num_retries=num_retries, |
59 | 61 | joint_limits=lim.T,
|
60 | 62 | early_stopping_any_converged=True,
|
61 | 63 | early_stopping_no_improvement="all",
|
@@ -85,53 +87,73 @@ def test_jacobian_follower():
|
85 | 87 | p.setAdditionalSearchPath(search_path)
|
86 | 88 |
|
87 | 89 | yaw = 90
|
88 |
| - pitch = -55 |
89 |
| - dist = 1. |
90 |
| - target = goal_pos[0].cpu().numpy() |
| 90 | + pitch = -65 |
| 91 | + # dist = 1. |
| 92 | + dist = 2.4 |
| 93 | + target = np.array([2., 1.5, 0]) |
91 | 94 | p.resetDebugVisualizerCamera(dist, yaw, pitch, target)
|
92 | 95 |
|
93 |
| - p.loadURDF("plane.urdf", [0, 0, 0], useFixedBase=True) |
| 96 | + plane_id = p.loadURDF("plane.urdf", [0, 0, 0], useFixedBase=True) |
| 97 | + p.changeVisualShape(plane_id, -1, rgbaColor=[0.3, 0.3, 0.3, 1]) |
| 98 | + |
| 99 | + # make 1 per retry with positional offsets |
| 100 | + robots = [] |
| 101 | + num_robots = 16 |
| 102 | + # 4x4 grid position offset |
| 103 | + offset = 1.0 |
94 | 104 | m = rob_tf.get_matrix()
|
95 | 105 | pos = m[0, :3, 3]
|
96 | 106 | rot = m[0, :3, :3]
|
97 | 107 | quat = pk.matrix_to_quaternion(rot)
|
98 | 108 | pos = pos.cpu().numpy()
|
99 | 109 | rot = pk.wxyz_to_xyzw(quat).cpu().numpy()
|
100 |
| - armId = p.loadURDF(urdf, basePosition=pos, baseOrientation=rot, useFixedBase=True) |
101 | 110 |
|
102 |
| - _make_robot_translucent(armId, alpha=0.6) |
103 |
| - # p.resetBasePositionAndOrientation(armId, [0, 0, 0], [0, 0, 0, 1]) |
104 |
| - # draw goal |
105 |
| - # place a translucent sphere at the goal |
| 111 | + for i in range(num_robots): |
| 112 | + this_offset = np.array([i % 4 * offset, i // 4 * offset, 0]) |
| 113 | + armId = p.loadURDF(urdf, basePosition=pos + this_offset, baseOrientation=rot, useFixedBase=True) |
| 114 | + # _make_robot_translucent(armId, alpha=0.6) |
| 115 | + robots.append({"id": armId, "offset": this_offset, "pos": pos}) |
| 116 | + |
106 | 117 | show_max_num_retries_per_goal = 10
|
107 |
| - for goal_num in range(M): |
108 |
| - # draw cone to indicate pose instead of sphere |
109 |
| - visId = p.createVisualShape(p.GEOM_MESH, fileName="meshes/cone.obj", meshScale=1.0, |
110 |
| - rgbaColor=[0., 1., 0., 0.5]) |
111 |
| - # visId = p.createVisualShape(p.GEOM_SPHERE, radius=0.05, rgbaColor=[0., 1., 0., 0.5]) |
112 |
| - r = goal_rot[goal_num] |
113 |
| - xyzw = pk.wxyz_to_xyzw(pk.matrix_to_quaternion(pk.euler_angles_to_matrix(r, "XYZ"))) |
114 |
| - goalId = p.createMultiBody(baseMass=0, baseVisualShapeIndex=visId, |
115 |
| - basePosition=goal_pos[goal_num].cpu().numpy(), |
116 |
| - baseOrientation=xyzw.cpu().numpy()) |
117 |
| - |
118 |
| - solutions = sol.solutions[goal_num] |
119 |
| - # sort based on if they converged |
120 |
| - converged = sol.converged[goal_num] |
121 |
| - idx = torch.argsort(converged.to(int), descending=True) |
122 |
| - solutions = solutions[idx] |
123 |
| - |
124 |
| - # print how many retries converged for this one |
125 |
| - print("Goal %d converged %d / %d" % (goal_num, converged.sum(), converged.numel())) |
126 |
| - |
127 |
| - for i, q in enumerate(solutions): |
128 |
| - if i > show_max_num_retries_per_goal: |
129 |
| - break |
130 |
| - for dof in range(q.shape[0]): |
131 |
| - p.resetJointState(armId, dof, q[dof]) |
132 |
| - input("Press enter to continue") |
133 |
| - |
134 |
| - p.removeBody(goalId) |
| 118 | + |
| 119 | + goals = [] |
| 120 | + # draw cone to indicate pose instead of sphere |
| 121 | + visId = p.createVisualShape(p.GEOM_MESH, fileName="meshes/cone.obj", meshScale=1.0, |
| 122 | + rgbaColor=[0., 1., 0., 0.5]) |
| 123 | + for i in range(num_robots): |
| 124 | + goals.append(p.createMultiBody(baseMass=0, baseVisualShapeIndex=visId)) |
| 125 | + |
| 126 | + try: |
| 127 | + import window_recorder |
| 128 | + with window_recorder.WindowRecorder(save_dir="."): |
| 129 | + # batch over goals with num_robots |
| 130 | + for j in range(0, M, num_robots): |
| 131 | + this_selection = slice(j, j + num_robots) |
| 132 | + r = goal_rot[this_selection] |
| 133 | + xyzw = pk.wxyz_to_xyzw(pk.matrix_to_quaternion(pk.euler_angles_to_matrix(r, "XYZ"))) |
| 134 | + |
| 135 | + solutions = sol.solutions[this_selection, :, :] |
| 136 | + converged = sol.converged[this_selection, :] |
| 137 | + |
| 138 | + # print how many retries converged for this one |
| 139 | + print("Goal %d to %d converged %d / %d" % (j, j + num_robots, converged.sum(), converged.numel())) |
| 140 | + |
| 141 | + # outer loop over retries, inner loop over goals (for each robot shown in parallel) |
| 142 | + for ii in range(num_retries): |
| 143 | + if ii > show_max_num_retries_per_goal: |
| 144 | + break |
| 145 | + for jj in range(num_robots): |
| 146 | + p.resetBasePositionAndOrientation(goals[jj], |
| 147 | + goal_pos[j + jj].cpu().numpy() + robots[jj]["offset"], |
| 148 | + xyzw[jj].cpu().numpy()) |
| 149 | + armId = robots[jj]["id"] |
| 150 | + q = solutions[jj, ii, :] |
| 151 | + for dof in range(q.shape[0]): |
| 152 | + p.resetJointState(armId, dof, q[dof]) |
| 153 | + |
| 154 | + input("Press enter to continue") |
| 155 | + except ImportError: |
| 156 | + print("pip install window_recorder") |
135 | 157 |
|
136 | 158 | while True:
|
137 | 159 | p.stepSimulation()
|
|
0 commit comments