placo 0.1.0__py3-none-any.whl → 0.1.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of placo might be problematic. Click here for more details.

placo.so ADDED
Binary file
placo_utils/tf.py ADDED
@@ -0,0 +1 @@
1
+ import meshcat.transformations as tf
@@ -0,0 +1,194 @@
1
+ import meshcat
2
+ import pinocchio as pin
3
+ import numpy as np
4
+ import meshcat.geometry as g
5
+ import meshcat.transformations as tf
6
+ import placo
7
+
8
+
9
+ viewer = None
10
+ robot_names: dict = {}
11
+
12
+
13
+ def get_viewer() -> meshcat.Visualizer:
14
+ """
15
+ Gets the meshcat viewer, if it doesn't exist, create it
16
+ """
17
+ global viewer
18
+
19
+ if viewer is None:
20
+ viewer = meshcat.Visualizer()
21
+ print(f"Viewer URL: {viewer.url()}")
22
+
23
+ return viewer
24
+
25
+
26
+ def robot_viz(robot: placo.RobotWrapper, name: str = "robot") -> pin.visualize.MeshcatVisualizer:
27
+ """
28
+ Builds an instance of pinocchio MeshcatVisualizer, which allows to push the model to the meshcat
29
+ visualizer passed as parameter
30
+
31
+ The robot can further be displayed using:
32
+
33
+ > viz.display(q)
34
+ """
35
+ global robot_names
36
+
37
+ robot_names[robot] = name
38
+ viz = pin.visualize.MeshcatVisualizer(robot.model, robot.collision_model, robot.visual_model)
39
+ viz.initViewer(viewer=get_viewer())
40
+ viz.loadViewerModel(name)
41
+
42
+ return viz
43
+
44
+
45
+ cylinders: dict = {}
46
+
47
+
48
+ def frame_viz(name: str, T: np.ndarray, opacity: float = 1.0) -> None:
49
+ """
50
+ Visualizes a given frame
51
+ """
52
+ global cylinders
53
+ vis = get_viewer()
54
+ axises = {
55
+ "x": (0xFF0000, (-np.pi / 2, [0, 0, 1])),
56
+ "y": (0x00FF00, (0, [0, 1, 0])),
57
+ "z": (0x0000FF, (np.pi / 2, [1, 0, 0])),
58
+ }
59
+
60
+ for axis_name in axises:
61
+ color, rotate = axises[axis_name]
62
+ node_name = f"frames/{name}/{axis_name}"
63
+
64
+ if node_name not in cylinders:
65
+ cylinders[node_name] = vis[node_name]
66
+ cylinders[node_name].set_object(
67
+ g.Cylinder(0.1, 0.005),
68
+ g.MeshLambertMaterial(color=color, opacity=opacity),
69
+ )
70
+ obj = cylinders[node_name]
71
+
72
+ obj.set_transform(T @ tf.rotation_matrix(*rotate) @ tf.translation_matrix([0, 0.05, 0]))
73
+
74
+
75
+ def point_viz(name: str, point: np.ndarray, radius: float = 0.01, color: float = 0xFF0000, opacity: float = 1.0) -> None:
76
+ """
77
+ Prints a point (sphere)
78
+ """
79
+ vis = get_viewer()
80
+ vis["points"][name].set_object(g.Sphere(radius), g.MeshPhongMaterial(color=color, opacity=opacity))
81
+ vis["points"][name].set_transform(tf.translation_matrix(point))
82
+
83
+
84
+ def robot_frame_viz(robot: placo.RobotWrapper, frame: str) -> None:
85
+ """
86
+ Draw a frame from the robot
87
+ """
88
+ node_name = f"{robot_names[robot]}_{frame}"
89
+ frame_viz(node_name, robot.get_T_world_frame(frame))
90
+
91
+
92
+ steps: int = 0
93
+
94
+
95
+ def footsteps_viz(footsteps: placo.Footsteps, T: np.ndarray = np.eye(4)) -> None:
96
+ global steps
97
+ vis = get_viewer()
98
+
99
+ if len(footsteps) < steps:
100
+ vis["footsteps"].delete()
101
+ steps = len(footsteps)
102
+
103
+ k = 0
104
+ for footstep in footsteps:
105
+ k += 1
106
+ polygon = [(T @ [*xy, 0, 1])[:3] for xy in footstep.support_polygon()]
107
+ polygon = np.array([*polygon, polygon[-1]])
108
+
109
+ if isinstance(footstep, placo.Support):
110
+ if len(footstep.footsteps) >= 2:
111
+ color = 0x1111AA
112
+ else:
113
+ color = 0xFF3333 if str(footstep.footsteps[0].side) == "left" else 0x33FF33
114
+ else:
115
+ color = 0xFF3333 if str(footstep.side) == "left" else 0x33FF33
116
+
117
+ vis["footsteps"][str(k)].set_object(g.LineLoop(g.PointsGeometry(polygon.T), g.MeshBasicMaterial(color=color)))
118
+
119
+
120
+ def line_viz(name: str, points: np.ndarray, color: float = 0xFF0000) -> None:
121
+ """
122
+ Prints a line
123
+ """
124
+ vis = get_viewer()
125
+ vis["lines"][name].set_object(g.LineSegments(g.PointsGeometry(points.T), g.LineBasicMaterial(color=color)))
126
+
127
+
128
+ def arrow_viz(
129
+ name: str,
130
+ point_from: np.ndarray,
131
+ point_to: np.ndarray,
132
+ color: float = 0xFF0000,
133
+ radius: float = 0.003,
134
+ ) -> None:
135
+ """
136
+ Prints an arrow
137
+ """
138
+ head_length = radius*3
139
+ vis = get_viewer()
140
+ length = np.linalg.norm(point_to - point_from)
141
+ length = max(1e-3, length - head_length)
142
+
143
+ cylinder = g.Cylinder(length, radius)
144
+ head = g.Cylinder(head_length, 2 * radius, 0.0, 2 * radius)
145
+
146
+ T = tf.translation_matrix(point_from)
147
+ if np.linalg.norm(point_to - point_from) > 1e-6:
148
+ new_y = (point_to - point_from) / np.linalg.norm(point_to - point_from)
149
+ new_z = np.cross(np.array([0, 0, 1]), new_y)
150
+ new_z /= np.linalg.norm(new_z)
151
+ new_x = np.cross(new_y, new_z)
152
+ new_x /= np.linalg.norm(new_x)
153
+ new_z = np.cross(new_x, new_y)
154
+ new_z /= np.linalg.norm(new_z)
155
+ T[:3, :3] = np.vstack([new_x, new_y, new_z]).T
156
+
157
+ T_cylinder = T @ tf.translation_matrix(np.array([0, length / 2.0, 0.0]))
158
+ T_head = T @ tf.translation_matrix(np.array([0, length + head_length / 2.0, 0.0]))
159
+
160
+ vis["arrows"][name]["cylinder"].set_object(cylinder, g.MeshBasicMaterial(color=color))
161
+ vis["arrows"][name]["cylinder"].set_transform(T_cylinder)
162
+ vis["arrows"][name]["head"].set_object(head, g.MeshBasicMaterial(color=color))
163
+ vis["arrows"][name]["head"].set_transform(T_head)
164
+
165
+ previous_contacts: int = 0
166
+
167
+ def contacts_viz(solver: placo.DynamicsSolver, ratio=0.1, radius=0.005):
168
+ global previous_contacts
169
+ robot = solver.robot
170
+ frames = robot.frame_names()
171
+
172
+ for k in range(solver.count_contacts()):
173
+ contact = solver.get_contact(k)
174
+
175
+ if isinstance(contact, placo.PointContact):
176
+ frame_name = frames[contact.position_task().frame_index]
177
+ T_world_frame = robot.get_T_world_frame(frame_name)
178
+ arrow_viz(f"contact_{k}", T_world_frame[:3, 3], T_world_frame[:3, 3] + contact.wrench * ratio, color=0x00FF00, radius=radius)
179
+ elif isinstance(contact, placo.Contact6D):
180
+ frame_name = frames[contact.position_task().frame_index]
181
+ T_world_frame = robot.get_T_world_frame(frame_name)
182
+ wrench = T_world_frame[:3, :3] @ contact.wrench[:3]
183
+ origin = T_world_frame[:3, 3] + T_world_frame[:3, :3] @ contact.zmp()
184
+ arrow_viz(f"contact_{k}", origin, origin + wrench * ratio, color=0x00FFAA, radius=radius)
185
+ elif isinstance(contact, placo.ExternalWrenchContact):
186
+ frame_name = frames[contact.frame_index]
187
+ T_world_frame = robot.get_T_world_frame(frame_name)
188
+ arrow_viz(f"contact_{k}", T_world_frame[:3, 3], T_world_frame[:3, 3] + contact.w_ext[:3] * ratio, color=0xFF2222, radius=radius)
189
+
190
+ vis = get_viewer()
191
+ while k < previous_contacts:
192
+ k += 1
193
+ vis["arrows"][f"contact_{k}"].delete()
194
+ previous_contacts = k
@@ -1,4 +0,0 @@
1
- placo-0.1.0.dist-info/METADATA,sha256=t40owEiNgmTk-GuvG-nsTyVoaxgywdF3B9eNVc9ThXo,480
2
- placo-0.1.0.dist-info/WHEEL,sha256=G16H4A3IeoQmnOrYV4ueZGKSjhipXx8zc8nu9FGlvMA,92
3
- placo-0.1.0.dist-info/top_level.txt,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
4
- placo-0.1.0.dist-info/RECORD,,
@@ -1 +0,0 @@
1
-
File without changes