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.
- libjsoncpp.so +0 -0
- libjsoncpp.so.1.9.4 +0 -0
- libjsoncpp.so.24 +0 -0
- liblibplaco.so +0 -0
- placo/libassimp.so.5 +0 -0
- placo/libboost_filesystem.so.1.74.0 +0 -0
- placo/libboost_python310.so.1.74.0 +0 -0
- placo/libconsole_bridge.so.1.0 +0 -0
- placo/libdraco.so.4 +0 -0
- placo/libeigenpy.so +0 -0
- placo/libeiquadprog.so +0 -0
- placo/libgcc_s.so.1 +0 -0
- placo/libhpp-fcl.so +0 -0
- placo/libjsoncpp.so +0 -0
- placo/libjsoncpp.so.1.9.4 +0 -0
- placo/libjsoncpp.so.24 +0 -0
- placo/liblibplaco.so +0 -0
- placo/libminizip.so.1 +0 -0
- placo/liboctomap.so.1.9 +0 -0
- placo/liboctomath.so.1.9 +0 -0
- placo/libpinocchio.so.2.6.17 +0 -0
- placo/libqhull_r.so.8.0 +0 -0
- placo/libqhullcpp.so.8.0 +0 -0
- placo/libstdc++.so.6 +0 -0
- placo/libtinyxml.so.2.6.2 +0 -0
- placo/liburdfdom_model.so.3.0 +0 -0
- placo/liburdfdom_world.so.3.0 +0 -0
- placo/libz.so.1 +0 -0
- placo/placo.py +4 -0
- placo/placo.pyi +6398 -0
- placo/placo.so +0 -0
- {placo-0.1.0.dist-info → placo-0.1.1.dist-info}/METADATA +1 -1
- placo-0.1.1.dist-info/RECORD +39 -0
- placo-0.1.1.dist-info/top_level.txt +1 -0
- placo.pyi +6398 -0
- placo.so +0 -0
- placo_utils/tf.py +1 -0
- placo_utils/visualization.py +194 -0
- placo-0.1.0.dist-info/RECORD +0 -4
- placo-0.1.0.dist-info/top_level.txt +0 -1
- {placo-0.1.0.dist-info → placo-0.1.1.dist-info}/WHEEL +0 -0
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
|
placo-0.1.0.dist-info/RECORD
DELETED
|
@@ -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
|