tinysim 0.0.4__py3-none-any.whl → 0.0.5__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.
- tinysim/__init__.py +7 -2
- tinysim/_tk_base.py +20 -2
- tinysim/_widget_base.py +41 -0
- tinysim/flappy/__init__.py +5 -3
- tinysim/flappy/tk.py +10 -34
- tinysim/flappy/widget.py +9 -38
- tinysim/frogger/__init__.py +21 -4
- tinysim/frogger/tk.py +12 -28
- tinysim/frogger/widget.py +8 -37
- tinysim/mountain_car/__init__.py +17 -12
- tinysim/mountain_car/tk.py +9 -27
- tinysim/mountain_car/widget.py +8 -37
- tinysim/tinyspace.py +68 -0
- tinysim/topdown_driving/__init__.py +16 -18
- tinysim/topdown_driving/tk.py +13 -38
- tinysim/topdown_driving/track_0.json +1 -753
- tinysim/topdown_driving/widget.py +8 -42
- {tinysim-0.0.4.dist-info → tinysim-0.0.5.dist-info}/METADATA +5 -6
- {tinysim-0.0.4.dist-info → tinysim-0.0.5.dist-info}/RECORD +35 -35
- {tinysim-0.0.4.dist-info → tinysim-0.0.5.dist-info}/WHEEL +1 -1
- tinysim_mujoco/gl_viewer.py +36 -11
- tinysim_mujoco/manipulation/__init__.py +19 -5
- tinysim_mujoco/manipulation/push_env.py +268 -0
- tinysim_mujoco/manipulation/push_env_cam.py +274 -0
- tinysim_mujoco/manipulation/xmls/panda.xml +59 -16
- tinysim_mujoco/manipulation/xmls/scene.xml +0 -3
- tinysim_mujoco/manipulation/xmls/table.xml +17 -13
- tinysim_mujoco/notebook_viewer.py +3 -6
- tinysim_mujoco/unitree_a1/__init__.py +7 -10
- tinysim_warp/__init__.py +108 -0
- tinysim_warp/cart_pole/__init__.py +44 -200
- tinysim_warp/quadruped/__init__.py +23 -160
- tinysim_warp/simple_quadruped/__init__.py +20 -91
- tinysim_warp/simple_quadruped/simple_quadruped.urdf +0 -9
- tinysim/simple_amr/__init__.py +0 -0
- tinysim/simple_amr/example_maps.py +0 -121
- tinysim/simple_amr/sim.js +0 -430
- tinysim/simple_amr/styles.css +0 -54
- tinysim/simple_amr/widget.py +0 -73
- {tinysim-0.0.4.dist-info → tinysim-0.0.5.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from PIL import Image as PILImage
|
|
3
|
+
|
|
4
|
+
try:
|
|
5
|
+
import mujoco
|
|
6
|
+
|
|
7
|
+
from . import ManipulationBaseEnv
|
|
8
|
+
except ImportError:
|
|
9
|
+
raise ImportError(
|
|
10
|
+
"Mujoco is not properly installed. Install using `pip install tinysim[mujoco]`"
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
_FLOAT_EPS = np.finfo(np.float64).eps
|
|
14
|
+
_EPS4 = _FLOAT_EPS * 4.0
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class ManipulationEnvV1:
|
|
18
|
+
|
|
19
|
+
def __init__(self, **kwargs):
|
|
20
|
+
kwargs["use_d405_camera"] = True
|
|
21
|
+
self.env = ManipulationBaseEnv(**kwargs)
|
|
22
|
+
self._model = self.env.model
|
|
23
|
+
self._data = self.env.data
|
|
24
|
+
self.frame_skip = 25
|
|
25
|
+
self.dt = self._model.opt.timestep * self.frame_skip
|
|
26
|
+
|
|
27
|
+
self._body_name2id = {}
|
|
28
|
+
for body_id in range(self._model.nbody):
|
|
29
|
+
name = mujoco.mj_id2name(self._model, mujoco.mjtObj.mjOBJ_BODY, body_id)
|
|
30
|
+
if name is not None:
|
|
31
|
+
self._body_name2id[name] = body_id
|
|
32
|
+
|
|
33
|
+
self.joint_names = []
|
|
34
|
+
for j in range(self._model.njnt):
|
|
35
|
+
name = mujoco.mj_id2name(self._model, mujoco.mjtObj.mjOBJ_JOINT, j)
|
|
36
|
+
if name is not None:
|
|
37
|
+
self.joint_names.append(name)
|
|
38
|
+
|
|
39
|
+
distance_threshold = 0.05
|
|
40
|
+
self.neutral_joint_values = np.array(
|
|
41
|
+
[0.00, 0.41, 0.00, -1.85, 0.00, 2.26, 0.79]
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
self.current_step = 0
|
|
45
|
+
self.maximum_episode_steps = 128
|
|
46
|
+
self.distance_threshold = distance_threshold
|
|
47
|
+
|
|
48
|
+
self.goal = self.get_site_xpos(self._model, self._data, "goal_site").copy()
|
|
49
|
+
self.initial_object_pos = self.get_site_xpos(
|
|
50
|
+
self._model, self._data, "obj_site"
|
|
51
|
+
).copy()
|
|
52
|
+
free_joint_index = self.joint_names.index("obj_joint")
|
|
53
|
+
self.arm_joint_names = self.joint_names[:free_joint_index][0:7]
|
|
54
|
+
# self.gripper_joint_names = self.joint_names[:free_joint_index][7:9]
|
|
55
|
+
self.set_joint_neutral()
|
|
56
|
+
self.reset_mocap_welds(self._model, self._data)
|
|
57
|
+
mujoco.mj_forward(self._model, self._data)
|
|
58
|
+
|
|
59
|
+
def reset_mocap_welds(self, model, data):
|
|
60
|
+
if model.nmocap > 0 and model.eq_data is not None:
|
|
61
|
+
for i in range(model.eq_data.shape[0]):
|
|
62
|
+
if model.eq_type[i] == mujoco.mjtEq.mjEQ_WELD:
|
|
63
|
+
model.eq_data[i, :7] = np.array([0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0])
|
|
64
|
+
mujoco.mj_forward(model, data)
|
|
65
|
+
|
|
66
|
+
def reset_mocap2body_xpos(self, model, data):
|
|
67
|
+
if model.eq_type is None or model.eq_obj1id is None or model.eq_obj2id is None:
|
|
68
|
+
return
|
|
69
|
+
for eq_type, obj1_id, obj2_id in zip(
|
|
70
|
+
model.eq_type, model.eq_obj1id, model.eq_obj2id
|
|
71
|
+
):
|
|
72
|
+
if eq_type != mujoco.mjtEq.mjEQ_WELD:
|
|
73
|
+
continue
|
|
74
|
+
|
|
75
|
+
mocap_id = model.body_mocapid[obj1_id]
|
|
76
|
+
if mocap_id != -1:
|
|
77
|
+
# obj1 is the mocap, obj2 is the welded body
|
|
78
|
+
body_idx = obj2_id
|
|
79
|
+
else:
|
|
80
|
+
# obj2 is the mocap, obj1 is the welded body
|
|
81
|
+
mocap_id = model.body_mocapid[obj2_id]
|
|
82
|
+
body_idx = obj1_id
|
|
83
|
+
|
|
84
|
+
assert mocap_id != -1
|
|
85
|
+
data.mocap_pos[mocap_id][:] = data.xpos[body_idx]
|
|
86
|
+
data.mocap_quat[mocap_id][:] = data.xquat[body_idx]
|
|
87
|
+
|
|
88
|
+
def mocap_set_action(self, model, data, action):
|
|
89
|
+
if model.nmocap > 0:
|
|
90
|
+
action, _ = np.split(action, (model.nmocap * 7,))
|
|
91
|
+
action = action.reshape(model.nmocap, 7)
|
|
92
|
+
pos_delta = action[:, :3]
|
|
93
|
+
quat_delta = action[:, 3:]
|
|
94
|
+
self.reset_mocap2body_xpos(model, data)
|
|
95
|
+
data.mocap_pos[:] = data.mocap_pos + pos_delta
|
|
96
|
+
data.mocap_quat[:] = data.mocap_quat + quat_delta
|
|
97
|
+
|
|
98
|
+
def ctrl_set_action(self, model, data, action):
|
|
99
|
+
if model.nmocap > 0:
|
|
100
|
+
_, action = np.split(action, (model.nmocap * 7,))
|
|
101
|
+
|
|
102
|
+
if len(data.ctrl) > 0:
|
|
103
|
+
for i in range(action.shape[0]):
|
|
104
|
+
if model.actuator_biastype[i] == 0:
|
|
105
|
+
data.ctrl[i] = action[i]
|
|
106
|
+
else:
|
|
107
|
+
idx = model.jnt_qposadr[model.actuator_trnid[i, 0]]
|
|
108
|
+
data.ctrl[i] = data.qpos[idx] + action[i]
|
|
109
|
+
|
|
110
|
+
def step(self, action):
|
|
111
|
+
self.current_step += 1
|
|
112
|
+
# just move the end effector in x, y, z
|
|
113
|
+
pos_ctrl = action.copy() * 0.05 # scale action
|
|
114
|
+
rot_ctrl = [
|
|
115
|
+
1.0,
|
|
116
|
+
0.0,
|
|
117
|
+
0.0,
|
|
118
|
+
0.0,
|
|
119
|
+
]
|
|
120
|
+
action = np.concatenate([pos_ctrl, rot_ctrl])
|
|
121
|
+
|
|
122
|
+
self.ctrl_set_action(self._model, self._data, action)
|
|
123
|
+
self.mocap_set_action(self._model, self._data, action)
|
|
124
|
+
|
|
125
|
+
self.env.step(n_frames=self.frame_skip)
|
|
126
|
+
obs = self._get_obs()
|
|
127
|
+
terminated = self._is_success(obs["achieved_goal"], self.goal)
|
|
128
|
+
truncated = self.current_step >= self.maximum_episode_steps
|
|
129
|
+
reward = self.compute_reward(obs["achieved_goal"], self.goal)
|
|
130
|
+
return obs, reward, terminated, truncated, {}
|
|
131
|
+
|
|
132
|
+
def mat2euler(self, mat):
|
|
133
|
+
mat = np.asarray(mat, dtype=np.float64)
|
|
134
|
+
cy = np.sqrt(mat[..., 2, 2] * mat[..., 2, 2] + mat[..., 1, 2] * mat[..., 1, 2])
|
|
135
|
+
condition = cy > _EPS4
|
|
136
|
+
euler = np.empty(mat.shape[:-1], dtype=np.float64)
|
|
137
|
+
euler[..., 2] = np.where(
|
|
138
|
+
condition,
|
|
139
|
+
-np.arctan2(mat[..., 0, 1], mat[..., 0, 0]),
|
|
140
|
+
-np.arctan2(-mat[..., 1, 0], mat[..., 1, 1]),
|
|
141
|
+
)
|
|
142
|
+
euler[..., 1] = np.where(
|
|
143
|
+
condition,
|
|
144
|
+
-np.arctan2(-mat[..., 0, 2], cy),
|
|
145
|
+
-np.arctan2(-mat[..., 0, 2], cy),
|
|
146
|
+
)
|
|
147
|
+
euler[..., 0] = np.where(
|
|
148
|
+
condition, -np.arctan2(mat[..., 1, 2], mat[..., 2, 2]), 0.0
|
|
149
|
+
)
|
|
150
|
+
return euler
|
|
151
|
+
|
|
152
|
+
def get_site_xpos(self, model, data, name):
|
|
153
|
+
site_id = mujoco.mj_name2id(model, mujoco.mjtObj.mjOBJ_SITE, name)
|
|
154
|
+
return data.site_xpos[site_id]
|
|
155
|
+
|
|
156
|
+
def get_site_xvelp(self, model, data, name):
|
|
157
|
+
site_id = mujoco.mj_name2id(model, mujoco.mjtObj.mjOBJ_SITE, name)
|
|
158
|
+
jacp = self.get_site_jacp(model, data, site_id)
|
|
159
|
+
xvelp = jacp @ data.qvel
|
|
160
|
+
return xvelp
|
|
161
|
+
|
|
162
|
+
def get_site_jacp(self, model, data, site_id):
|
|
163
|
+
jacp = np.zeros((3, model.nv))
|
|
164
|
+
mujoco.mj_jacSite(model, data, jacp, None, site_id)
|
|
165
|
+
return jacp
|
|
166
|
+
|
|
167
|
+
def _get_obs(self) -> dict:
|
|
168
|
+
ee_position = self.get_site_xpos(self._model, self._data, "tip").copy()
|
|
169
|
+
ee_velocity = (
|
|
170
|
+
self.get_site_xvelp(self._model, self._data, "tip").copy() * self.dt
|
|
171
|
+
)
|
|
172
|
+
object_position = self.get_site_xpos(self._model, self._data, "obj_site").copy()
|
|
173
|
+
object_rotation = self.mat2euler(
|
|
174
|
+
self.get_site_xmat(self._model, self._data, "obj_site")
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
frame = self.env.d405_viewer.capture_frame()
|
|
178
|
+
img = np.array(PILImage.fromarray(frame).resize((64, 64))).transpose(2, 0, 1)
|
|
179
|
+
|
|
180
|
+
return {
|
|
181
|
+
"observation_cap": img,
|
|
182
|
+
"observation": np.concatenate(
|
|
183
|
+
[
|
|
184
|
+
ee_position,
|
|
185
|
+
ee_velocity,
|
|
186
|
+
object_position,
|
|
187
|
+
object_rotation,
|
|
188
|
+
]
|
|
189
|
+
).copy(),
|
|
190
|
+
"achieved_goal": object_position.copy(),
|
|
191
|
+
"desired_goal": self.goal.copy(),
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
def set_joint_qpos(self, model, data, name, value):
|
|
195
|
+
"""Set the joint positions (qpos) of the model."""
|
|
196
|
+
joint_id = mujoco.mj_name2id(model, mujoco.mjtObj.mjOBJ_JOINT, name)
|
|
197
|
+
joint_addr = model.jnt_qposadr[joint_id]
|
|
198
|
+
# All joints are assumed to be of type mjJNT_HINGE in this environment
|
|
199
|
+
data.qpos[joint_addr] = value
|
|
200
|
+
|
|
201
|
+
def set_object_qpos(self, model, data):
|
|
202
|
+
joint_id = mujoco.mj_name2id(model, mujoco.mjtObj.mjOBJ_JOINT, "obj_joint")
|
|
203
|
+
joint_addr = model.jnt_qposadr[joint_id]
|
|
204
|
+
data.qpos[joint_addr : joint_addr + 3] = np.array(self.initial_object_pos)
|
|
205
|
+
# reset orientation
|
|
206
|
+
data.qpos[joint_addr + 3 : joint_addr + 7] = np.array([1.0, 0.0, 0.0, 0.0])
|
|
207
|
+
|
|
208
|
+
def _sample_goal(self):
|
|
209
|
+
goal = np.array([0.3, 0.0, 0.0])
|
|
210
|
+
return goal
|
|
211
|
+
|
|
212
|
+
def goal_distance(self, goal_a, goal_b):
|
|
213
|
+
assert goal_a.shape == goal_b.shape
|
|
214
|
+
return np.linalg.norm(goal_a - goal_b, axis=-1)
|
|
215
|
+
|
|
216
|
+
def compute_reward(self, achieved_goal, desired_goal, info=None):
|
|
217
|
+
d = self.goal_distance(achieved_goal, desired_goal)
|
|
218
|
+
# give reward for the end effector being close to the object
|
|
219
|
+
ee_position = self.get_site_xpos(self._model, self._data, "tip")
|
|
220
|
+
object_position = self.get_site_xpos(self._model, self._data, "obj_site")
|
|
221
|
+
ee_object_distance = np.linalg.norm(ee_position - object_position, axis=-1)
|
|
222
|
+
|
|
223
|
+
# the arm tries to cheat by moving the object with the side of the gripper
|
|
224
|
+
# negative ward if the arm contacts the ground with
|
|
225
|
+
effector_distance_reward = -0.1 * (ee_object_distance > 0.05).astype(np.float32)
|
|
226
|
+
|
|
227
|
+
# todo: check correctness
|
|
228
|
+
# give some reward if the cube is moving towards the goal
|
|
229
|
+
object_velocity = self.get_site_xvelp(self._model, self._data, "obj_site")
|
|
230
|
+
goal_direction = desired_goal[0] - object_position
|
|
231
|
+
goal_direction /= np.linalg.norm(goal_direction) + 1e-8
|
|
232
|
+
velocity_towards_goal = np.dot(object_velocity, goal_direction)
|
|
233
|
+
velocity_reward = max(0.0, velocity_towards_goal)
|
|
234
|
+
|
|
235
|
+
reward = -d + effector_distance_reward + velocity_reward
|
|
236
|
+
return reward
|
|
237
|
+
|
|
238
|
+
# sparse
|
|
239
|
+
# return -(d > self.distance_threshold).astype(np.float32)
|
|
240
|
+
|
|
241
|
+
def _is_success(self, achieved_goal, desired_goal):
|
|
242
|
+
d = self.goal_distance(achieved_goal, desired_goal)
|
|
243
|
+
return (d < self.distance_threshold).astype(np.float32)
|
|
244
|
+
|
|
245
|
+
def set_joint_neutral(self):
|
|
246
|
+
for name, value in zip(self.arm_joint_names, self.neutral_joint_values):
|
|
247
|
+
self.set_joint_qpos(self._model, self._data, name, value)
|
|
248
|
+
|
|
249
|
+
def _reset_sim(self) -> bool:
|
|
250
|
+
self.set_joint_neutral()
|
|
251
|
+
self.set_object_qpos(self._model, self._data)
|
|
252
|
+
mujoco.mj_forward(self._model, self._data)
|
|
253
|
+
|
|
254
|
+
def reset(self, **kwargs):
|
|
255
|
+
self.current_step = 0
|
|
256
|
+
self._reset_sim()
|
|
257
|
+
obs = self._get_obs()
|
|
258
|
+
|
|
259
|
+
# self.env.step(n_frames=self.frame_skip)
|
|
260
|
+
# frame = self.env.viewer.capture_frame()
|
|
261
|
+
# import matplotlib.pyplot as plt
|
|
262
|
+
# plt.imsave("debug_frame.png", frame)
|
|
263
|
+
# raise Exception("Debug")
|
|
264
|
+
return obs, {}
|
|
265
|
+
|
|
266
|
+
def get_site_xmat(self, model, data, name: str):
|
|
267
|
+
site_id = mujoco.mj_name2id(model, mujoco.mjtObj.mjOBJ_SITE, name)
|
|
268
|
+
return data.site_xmat[site_id].reshape(3, 3)
|
|
269
|
+
|
|
270
|
+
def get_body_state(self, name):
|
|
271
|
+
body_id = self._body_name2id[name]
|
|
272
|
+
body_xpos = self._data.xpos[body_id]
|
|
273
|
+
body_xquat = self._data.xquat[body_id]
|
|
274
|
+
return np.concatenate([body_xpos, body_xquat])
|
|
@@ -52,7 +52,6 @@
|
|
|
52
52
|
<material class="panda" name="green" rgba="0 1 0 1"/>
|
|
53
53
|
<material class="panda" name="light_blue" rgba="0.039216 0.541176 0.780392 1"/>
|
|
54
54
|
|
|
55
|
-
<!-- Collision meshes -->
|
|
56
55
|
<mesh name="link0_collision" file="link0.stl"/>
|
|
57
56
|
<mesh name="link1_collision" file="link1.stl"/>
|
|
58
57
|
<mesh name="link2_collision" file="link2.stl"/>
|
|
@@ -65,7 +64,6 @@
|
|
|
65
64
|
<mesh name="link7_collision" file="link7.stl"/>
|
|
66
65
|
<mesh name="hand_collision" file="hand.stl"/>
|
|
67
66
|
|
|
68
|
-
<!-- Visual meshes -->
|
|
69
67
|
<mesh file="link0_0.obj"/>
|
|
70
68
|
<mesh file="link0_1.obj"/>
|
|
71
69
|
<mesh file="link0_2.obj"/>
|
|
@@ -128,6 +126,15 @@
|
|
|
128
126
|
<worldbody>
|
|
129
127
|
<light name="top" pos="0 0 2" mode="trackcom"/>
|
|
130
128
|
<camera name="front_cam" pos="1.1 0 0.5" xyaxes="0 1 0 -0.4 0 0.7"/>
|
|
129
|
+
|
|
130
|
+
<!-- Added -->
|
|
131
|
+
<body mocap="true" name="panda_mocap" pos="0.6 0 0.4">
|
|
132
|
+
<geom conaffinity="0" contype="0" pos="0 0 0" rgba="0 0.5 0 0.7" size="0.005 0.005 0.005" type="box"></geom>
|
|
133
|
+
<geom conaffinity="0" contype="0" pos="0 0 0" rgba="0 0.5 0 0.1" size="0.5 0.005 0.005" type="box"></geom>
|
|
134
|
+
<geom conaffinity="0" contype="0" pos="0 0 0" rgba="0 0.5 0 0.1" size="0.005 0.5 0.001" type="box"></geom>
|
|
135
|
+
<geom conaffinity="0" contype="0" pos="0 0 0" rgba="0 0.5 0 0.1" size="0.005 0.005 0.5" type="box"></geom>
|
|
136
|
+
</body>
|
|
137
|
+
|
|
131
138
|
<body name="link0" childclass="panda">
|
|
132
139
|
<inertial mass="0.629769" pos="0 0 0"
|
|
133
140
|
fullinertia="0.00315 0.00388 0.004285 8.2904e-7 0.00015 8.2299e-6"/>
|
|
@@ -146,17 +153,17 @@
|
|
|
146
153
|
<body name="link1" pos="0 0 0.333">
|
|
147
154
|
<inertial mass="4.970684" pos="0.003875 0.002081 -0.04762"
|
|
148
155
|
fullinertia="0.70337 0.70661 0.0091170 -0.00013900 0.0067720 0.019169"/>
|
|
149
|
-
<joint name="joint1" range="-2.8973 2.8973"/>
|
|
156
|
+
<joint name="joint1" range="-2.8973 2.8973" /> <!-- Here -->
|
|
150
157
|
<geom material="white" mesh="link1" class="visual"/>
|
|
151
158
|
<geom mesh="link1_collision" class="collision"/>
|
|
152
159
|
<body name="link2" quat="1 -1 0 0">
|
|
153
160
|
<inertial mass="0.646926" pos="-0.003141 -0.02872 0.003495"
|
|
154
161
|
fullinertia="0.0079620 2.8110e-2 2.5995e-2 -3.925e-3 1.0254e-2 7.04e-4"/>
|
|
155
|
-
<joint name="joint2" range="-1.7628 1.7628"/>
|
|
162
|
+
<joint name="joint2" range="-1.7628 1.7628" /> <!-- Here -->
|
|
156
163
|
<geom material="white" mesh="link2" class="visual"/>
|
|
157
164
|
<geom mesh="link2_collision" class="collision"/>
|
|
158
165
|
<body name="link3" pos="0 -0.316 0" quat="1 1 0 0">
|
|
159
|
-
<joint name="joint3" range="-2.8973 2.8973"/>
|
|
166
|
+
<joint name="joint3" range="-2.8973 2.8973" /> <!-- Here -->
|
|
160
167
|
<inertial mass="3.228604" pos="2.7518e-2 3.9252e-2 -6.6502e-2"
|
|
161
168
|
fullinertia="3.7242e-2 3.6155e-2 1.083e-2 -4.761e-3 -1.1396e-2 -1.2805e-2"/>
|
|
162
169
|
<geom mesh="link3_0" material="white" class="visual"/>
|
|
@@ -167,7 +174,7 @@
|
|
|
167
174
|
<body name="link4" pos="0.0825 0 0" quat="1 1 0 0">
|
|
168
175
|
<inertial mass="3.587895" pos="-5.317e-2 1.04419e-1 2.7454e-2"
|
|
169
176
|
fullinertia="2.5853e-2 1.9552e-2 2.8323e-2 7.796e-3 -1.332e-3 8.641e-3"/>
|
|
170
|
-
<joint name="joint4" range="-3.0718 -0.0698"/>
|
|
177
|
+
<joint name="joint4" range="-3.0718 -0.0698" /> <!-- Here -->
|
|
171
178
|
<geom mesh="link4_0" material="white" class="visual"/>
|
|
172
179
|
<geom mesh="link4_1" material="white" class="visual"/>
|
|
173
180
|
<geom mesh="link4_2" material="black" class="visual"/>
|
|
@@ -176,7 +183,7 @@
|
|
|
176
183
|
<body name="link5" pos="-0.0825 0.384 0" quat="1 -1 0 0">
|
|
177
184
|
<inertial mass="1.225946" pos="-1.1953e-2 4.1065e-2 -3.8437e-2"
|
|
178
185
|
fullinertia="3.5549e-2 2.9474e-2 8.627e-3 -2.117e-3 -4.037e-3 2.29e-4"/>
|
|
179
|
-
<joint name="joint5" range="-2.8973 2.8973"/>
|
|
186
|
+
<joint name="joint5" range="-2.8973 2.8973" /> <!-- Here -->
|
|
180
187
|
<geom mesh="link5_0" material="black" class="visual"/>
|
|
181
188
|
<geom mesh="link5_1" material="white" class="visual"/>
|
|
182
189
|
<geom mesh="link5_2" material="white" class="visual"/>
|
|
@@ -186,7 +193,8 @@
|
|
|
186
193
|
<body name="link6" quat="1 1 0 0">
|
|
187
194
|
<inertial mass="1.666555" pos="6.0149e-2 -1.4117e-2 -1.0517e-2"
|
|
188
195
|
fullinertia="1.964e-3 4.354e-3 5.433e-3 1.09e-4 -1.158e-3 3.41e-4"/>
|
|
189
|
-
<joint name="joint6" range="-0.0175 3.7525"/>
|
|
196
|
+
<joint name="joint6" range="-0.0175 3.7525" /> <!-- Here -->
|
|
197
|
+
|
|
190
198
|
<geom mesh="link6_0" material="off_white" class="visual"/>
|
|
191
199
|
<geom mesh="link6_1" material="white" class="visual"/>
|
|
192
200
|
<geom mesh="link6_2" material="black" class="visual"/>
|
|
@@ -208,7 +216,7 @@
|
|
|
208
216
|
<body name="link7" pos="0.088 0 0" quat="1 1 0 0">
|
|
209
217
|
<inertial mass="7.35522e-01" pos="1.0517e-2 -4.252e-3 6.1597e-2"
|
|
210
218
|
fullinertia="1.2516e-2 1.0027e-2 4.815e-3 -4.28e-4 -1.196e-3 -7.41e-4"/>
|
|
211
|
-
<joint name="joint7" range="-2.8973 2.8973"/>
|
|
219
|
+
<joint name="joint7" range="-2.8973 2.8973" /> <!-- Here -->
|
|
212
220
|
<geom mesh="link7_0" material="white" class="visual"/>
|
|
213
221
|
<geom mesh="link7_1" material="black" class="visual"/>
|
|
214
222
|
<geom mesh="link7_2" material="black" class="visual"/>
|
|
@@ -226,9 +234,13 @@
|
|
|
226
234
|
<geom mesh="hand_3" material="white" class="visual"/>
|
|
227
235
|
<geom mesh="hand_4" material="off_white" class="visual"/>
|
|
228
236
|
<geom mesh="hand_collision" class="collision"/>
|
|
237
|
+
|
|
229
238
|
<geom name="hand_capsule_collision" type="capsule" class="collision" size="0.04 0.06" quat="1 1 0 0" pos="0 0 0.03"/>
|
|
230
|
-
|
|
231
|
-
|
|
239
|
+
|
|
240
|
+
<!-- These are the red circles between the fingers -->
|
|
241
|
+
<site name="gripper" pos="0 0 0.1" rgba="1 0 0 1"/>
|
|
242
|
+
<site name="tip" pos="0 0 0.1034" rgba="1 0 0 1" />
|
|
243
|
+
|
|
232
244
|
<body name="camera_d405" pos="0.05 0.0 0.066021" quat="0.6644633 0.2418451 -0.2418451 -0.6644633">
|
|
233
245
|
<geom class="visual" mesh="d405"/>
|
|
234
246
|
<geom class="collision" type="box" size=".018 .018 .01" pos="0 0 -0.01" group="4"/>
|
|
@@ -237,9 +249,9 @@
|
|
|
237
249
|
sensorsize="0.003896 0.00214" focal="0.00193 0.00193"/>
|
|
238
250
|
</body>
|
|
239
251
|
</body>
|
|
240
|
-
<body name="left_finger" pos="0 0 0.0584">
|
|
252
|
+
<body name="left_finger" pos="0 0.0 0.0584"> <!-- Changed -->
|
|
241
253
|
<inertial mass="0.015" pos="0 0 0" diaginertia="2.375e-6 2.375e-6 7.5e-7"/>
|
|
242
|
-
<joint name="finger_joint1" class="finger"
|
|
254
|
+
<!-- <joint name="finger_joint1" class="finger"/> -->
|
|
243
255
|
<geom mesh="finger_0" material="off_white" class="visual"/>
|
|
244
256
|
<geom mesh="finger_1" material="black" class="visual"/>
|
|
245
257
|
<geom name="finger_left_collision" mesh="finger_0" class="collision"/>
|
|
@@ -248,9 +260,9 @@
|
|
|
248
260
|
<geom name="lf3_collision" class="fingertip_collision_3"/>
|
|
249
261
|
<geom name="lfp_collision" class="fingertip_pad_collision_6"/>
|
|
250
262
|
</body>
|
|
251
|
-
<body name="right_finger" pos="0 0 0.0584" quat="0 0 0 1">
|
|
263
|
+
<body name="right_finger" pos="0 0.0 0.0584" quat="0 0 0 1"> <!-- Changed -->
|
|
252
264
|
<inertial mass="0.015" pos="0 0 0" diaginertia="2.375e-6 2.375e-6 7.5e-7"/>
|
|
253
|
-
<joint name="finger_joint2" class="finger"
|
|
265
|
+
<!-- <joint name="finger_joint2" class="finger"/> -->
|
|
254
266
|
<geom mesh="finger_0" material="off_white" class="visual"/>
|
|
255
267
|
<geom mesh="finger_1" material="black" class="visual"/>
|
|
256
268
|
<geom name="finger_right_collision" mesh="finger_0" class="collision"/>
|
|
@@ -270,10 +282,41 @@
|
|
|
270
282
|
</body>
|
|
271
283
|
</worldbody>
|
|
272
284
|
|
|
273
|
-
<equality>
|
|
285
|
+
<!-- <equality>
|
|
274
286
|
<joint joint1="finger_joint1" joint2="finger_joint2" solimp="0.95 0.99 0.001" solref="0.005 1"/>
|
|
287
|
+
</equality> -->
|
|
288
|
+
<equality>
|
|
289
|
+
<weld body1="panda_mocap" body2="hand" solimp="0.9 0.95 0.001" solref="0.02 1"></weld>
|
|
275
290
|
</equality>
|
|
276
291
|
|
|
292
|
+
<!-- Actuators for the panda robot -->
|
|
293
|
+
|
|
294
|
+
<!-- <actuator>
|
|
295
|
+
<general class="panda" name="actuator1" joint="joint1" kp="870" forcerange="-87 87" ctrlrange="-2.9671 2.9671"/>
|
|
296
|
+
<general class="panda" name="actuator2" joint="joint2" kp="870" forcerange="-87 87" ctrlrange="-1.8326 1.8326"/>
|
|
297
|
+
<general class="panda" name="actuator3" joint="joint3" gainprm="3500" biasprm="0 -3500 -350"/>
|
|
298
|
+
<general class="panda" name="actuator4" joint="joint4" gainprm="3500" biasprm="0 -3500 -350" ctrlrange="-3.0718 -0.0698"/>
|
|
299
|
+
<general class="panda" name="actuator5" joint="joint5" gainprm="2000" biasprm="0 -2000 -200" forcerange="-12 12"/>
|
|
300
|
+
<general class="panda" name="actuator6" joint="joint6" gainprm="2000" biasprm="0 -2000 -200" forcerange="-12 12" ctrlrange="-0.0175 3.7525"/>
|
|
301
|
+
<general class="panda" name="actuator7" joint="joint7" gainprm="2000" biasprm="0 -2000 -200" forcerange="-12 12"/>
|
|
302
|
+
</actuator> -->
|
|
303
|
+
|
|
304
|
+
<actuator>
|
|
305
|
+
<position class="panda" name="actuator1" joint="joint1" kv="870" kp="870" forcerange="-87 87" ctrlrange="-2.9671 2.9671"/>
|
|
306
|
+
<position class="panda" name="actuator2" joint="joint2" kv="870" kp="870" forcerange="-87 87" ctrlrange="-1.8326 1.8326"/>
|
|
307
|
+
<position class="panda" name="actuator3" joint="joint3" kv="870" kp="870" forcerange="-87 87" ctrlrange="-2.9671 2.9671"/>
|
|
308
|
+
<position class="panda" name="actuator4" joint="joint4" kv="870" kp="870" forcerange="-87 87" ctrlrange="-3.1416 0.0"/>
|
|
309
|
+
<position class="panda" name="actuator5" joint="joint5" kv="120" kp="120" forcerange="-12 12" ctrlrange="-2.9671 2.9671"/>
|
|
310
|
+
<position class="panda" name="actuator6" joint="joint6" kv="120" kp="120" forcerange="-12 12" ctrlrange="-0.0175 3.7525"/>
|
|
311
|
+
<position class="panda" name="actuator7" joint="joint7" kv="120" kp="120" forcerange="-12 12" ctrlrange="-2.9671 2.9671"/>
|
|
312
|
+
</actuator>
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
<!-- <actuator>
|
|
316
|
+
<general name="r_gripper_finger_joint" joint="finger_joint1" class="panda" gainprm="500 0 0" biasprm="0 -500 -10" forcerange="-120 120" ctrlrange="0 0.04"/>
|
|
317
|
+
<general name="l_gripper_finger_joint" joint="finger_joint2" class="panda" gainprm="500 0 0" biasprm="0 -500 -10" forcerange="-120 120" ctrlrange="0 0.04"/>
|
|
318
|
+
</actuator> -->
|
|
319
|
+
|
|
277
320
|
<contact>
|
|
278
321
|
<exclude body1="link0" body2="link1"/>
|
|
279
322
|
</contact>
|
|
@@ -2,20 +2,17 @@
|
|
|
2
2
|
<include file="panda.xml"/>
|
|
3
3
|
<include file="table.xml"/>
|
|
4
4
|
<statistic center="0 0 0.1" extent="0.8"/>
|
|
5
|
-
|
|
6
5
|
<visual>
|
|
7
6
|
<headlight diffuse="0.6 0.6 0.6" ambient="0.3 0.3 0.3" specular="0 0 0"/>
|
|
8
7
|
<rgba haze="0.15 0.25 0.35 1"/>
|
|
9
8
|
<global azimuth="120" elevation="-20"/>
|
|
10
9
|
</visual>
|
|
11
|
-
|
|
12
10
|
<asset>
|
|
13
11
|
<texture type="skybox" builtin="gradient" rgb1="0.3 0.5 0.7" rgb2="0 0 0" width="512" height="3072"/>
|
|
14
12
|
<texture type="2d" name="groundplane" builtin="checker" mark="edge" rgb1="0.2 0.3 0.4" rgb2="0.1 0.2 0.3"
|
|
15
13
|
markrgb="0.8 0.8 0.8" width="300" height="300"/>
|
|
16
14
|
<material name="groundplane" texture="groundplane" texuniform="true" texrepeat="5 5" reflectance="0.2"/>
|
|
17
15
|
</asset>
|
|
18
|
-
|
|
19
16
|
<worldbody>
|
|
20
17
|
<light pos="0 0 1.5" dir="0 0 -1" directional="true"/>
|
|
21
18
|
<geom name="floor" size="0 0 0.05" type="plane" material="groundplane" contype="1" conaffinity="1"/>
|
|
@@ -5,10 +5,8 @@
|
|
|
5
5
|
specular="0.2"
|
|
6
6
|
shininess="0.2"/>
|
|
7
7
|
</asset>
|
|
8
|
-
|
|
9
8
|
<worldbody>
|
|
10
|
-
<body name="table" pos="0.55 0 0">
|
|
11
|
-
|
|
9
|
+
<!-- <body name="table" pos="0.55 0 0">
|
|
12
10
|
<geom name="table_top"
|
|
13
11
|
type="box"
|
|
14
12
|
size="0.25 0.35 0.02"
|
|
@@ -16,22 +14,28 @@
|
|
|
16
14
|
material="table_wood"
|
|
17
15
|
contype="1"
|
|
18
16
|
conaffinity="1"/>
|
|
19
|
-
|
|
20
17
|
<geom name="leg_fl" type="box" size="0.025 0.025 0.25" pos=" 0.22 0.32 0.25"/>
|
|
21
18
|
<geom name="leg_fr" type="box" size="0.025 0.025 0.25" pos=" 0.22 -0.32 0.25"/>
|
|
22
19
|
<geom name="leg_bl" type="box" size="0.025 0.025 0.25" pos="-0.22 0.32 0.25"/>
|
|
23
20
|
<geom name="leg_br" type="box" size="0.025 0.025 0.25" pos="-0.22 -0.32 0.25"/>
|
|
21
|
+
</body> -->
|
|
22
|
+
<!-- <body name="box1" pos="0.35 0 0.60">
|
|
23
|
+
<joint type="free" damping="0.01" name="obj_joint"/>
|
|
24
|
+
<site name="obj_site" pos="0 0 0" size="0.01" type="sphere"/>
|
|
25
|
+
<geom name="box1_geom"
|
|
26
|
+
type="box"
|
|
27
|
+
size="0.02 0.02 0.02"
|
|
28
|
+
rgba="0.8 0.2 0.2 1"
|
|
29
|
+
friction="1" condim="6"/>
|
|
30
|
+
</body> -->
|
|
31
|
+
<body name="obj" pos="0.6 0.0 0.05" quat="1 0 0 0">
|
|
32
|
+
<joint type="free" damping="0.01" name="obj_joint"/>
|
|
33
|
+
<geom name="obj_geom" mass="0.1" type="box" size="0.03 0.03 0.03" rgba="0.5 0.7 0.5 1" friction="1" condim="6"/>
|
|
34
|
+
<site name="obj_site" pos="0 0 0" size="0.01" type="sphere"/>
|
|
24
35
|
</body>
|
|
25
36
|
|
|
26
|
-
<body name="
|
|
27
|
-
|
|
28
|
-
<geom name="box1_geom"
|
|
29
|
-
type="box"
|
|
30
|
-
size="0.05 0.05 0.05"
|
|
31
|
-
rgba="0.8 0.2 0.2 1"
|
|
32
|
-
density="200"
|
|
33
|
-
contype="1"
|
|
34
|
-
conaffinity="1"/>
|
|
37
|
+
<body name="goal_site" pos="0.3 0.0 0.0" quat="1 0 0 0">
|
|
38
|
+
<site name="goal_site" pos="0 0 0" size="0.05" type="sphere" rgba="0 1 0 0.5"/>
|
|
35
39
|
</body>
|
|
36
40
|
</worldbody>
|
|
37
41
|
</mujoco>
|
|
@@ -1,19 +1,16 @@
|
|
|
1
|
-
import numpy as np
|
|
2
1
|
import mujoco
|
|
2
|
+
import numpy as np
|
|
3
3
|
from IPython.display import display
|
|
4
4
|
from PIL import Image as PILImage
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
class NotebookViewer:
|
|
8
|
-
def __init__(self, model, data):
|
|
8
|
+
def __init__(self, model, data, width=640, height=480):
|
|
9
9
|
self.model = model
|
|
10
10
|
self.data = data
|
|
11
|
-
self.width = 640
|
|
12
|
-
self.height = 480
|
|
13
|
-
|
|
14
11
|
self.cam = mujoco.MjvCamera()
|
|
15
12
|
self.opt = mujoco.MjvOption()
|
|
16
|
-
self.renderer = mujoco.Renderer(model,
|
|
13
|
+
self.renderer = mujoco.Renderer(model, height, width, max_geom=500)
|
|
17
14
|
|
|
18
15
|
self.cam.azimuth = 90
|
|
19
16
|
self.cam.elevation = -25
|
|
@@ -4,6 +4,7 @@ import numpy as np
|
|
|
4
4
|
|
|
5
5
|
try:
|
|
6
6
|
import mujoco
|
|
7
|
+
|
|
7
8
|
from ..gl_viewer import GLViewer
|
|
8
9
|
from ..notebook_viewer import NotebookViewer
|
|
9
10
|
except ImportError:
|
|
@@ -50,9 +51,6 @@ class UnitreeA1BaseEnv:
|
|
|
50
51
|
if self.viewer:
|
|
51
52
|
self.viewer.render()
|
|
52
53
|
|
|
53
|
-
def close(self):
|
|
54
|
-
self.viewer.close()
|
|
55
|
-
|
|
56
54
|
def reset(self):
|
|
57
55
|
mujoco.mj_resetData(self.model, self.data)
|
|
58
56
|
self.data.qpos[0:3] = [0.0, 0.0, 0.3]
|
|
@@ -77,6 +75,7 @@ class UnitreeA1BaseEnv:
|
|
|
77
75
|
class UnitreeA1WalkEnv:
|
|
78
76
|
def __init__(self, reward_weights, cost_weights, **kwargs):
|
|
79
77
|
self.env = UnitreeA1BaseEnv(**kwargs)
|
|
78
|
+
self.viewer = self.env.viewer
|
|
80
79
|
self.frame_skip = 20
|
|
81
80
|
self.obs_dim = 45
|
|
82
81
|
self._previous_observation = np.zeros(self.obs_dim, dtype=np.float32)
|
|
@@ -165,14 +164,14 @@ class UnitreeA1WalkEnv:
|
|
|
165
164
|
action_diff_penalty = np.sum(np.abs(action - self.prev_action))
|
|
166
165
|
action_sym = self.action_sym()
|
|
167
166
|
|
|
168
|
-
|
|
167
|
+
rewards = (
|
|
169
168
|
tracking_lin_vel_reward * self.reward_weights["linear_vel_tracking"]
|
|
170
169
|
+ tracking_ang_vel_reward * self.reward_weights["angular_vel_tracking"]
|
|
171
170
|
+ self.is_healthy * self.reward_weights["healthy"]
|
|
172
171
|
+ self.feet_air_time_reward * self.reward_weights["feet_airtime"]
|
|
173
172
|
)
|
|
174
173
|
|
|
175
|
-
|
|
174
|
+
neg_rewards = (
|
|
176
175
|
self.torque_cost * self.cost_weights["torque"]
|
|
177
176
|
+ action_diff_penalty * self.cost_weights["action_rate"]
|
|
178
177
|
+ lin_vel_z_penalty * self.cost_weights["vertical_vel"]
|
|
@@ -180,11 +179,9 @@ class UnitreeA1WalkEnv:
|
|
|
180
179
|
+ action_sym * self.cost_weights["action_sym"]
|
|
181
180
|
+ self.acceleration_cost * self.cost_weights["joint_acceleration"]
|
|
182
181
|
+ self.orientation_cost * self.cost_weights["orientation"]
|
|
183
|
-
+ self.
|
|
184
|
-
* self.cost_weights["default_joint_position"]
|
|
182
|
+
+ self.default_joint_pos_cost * self.cost_weights["default_joint_pos"]
|
|
185
183
|
)
|
|
186
|
-
|
|
187
|
-
return reward
|
|
184
|
+
return rewards - neg_rewards
|
|
188
185
|
|
|
189
186
|
def _tracking_velocity_penalty(self, lin_vel, ang_vel):
|
|
190
187
|
lin_vel_error = np.sum(np.abs(self.target_lin_vel[0] - lin_vel[0]))
|
|
@@ -235,7 +232,7 @@ class UnitreeA1WalkEnv:
|
|
|
235
232
|
return np.square(roll) + np.square(pitch)
|
|
236
233
|
|
|
237
234
|
@property
|
|
238
|
-
def
|
|
235
|
+
def default_joint_pos_cost(self):
|
|
239
236
|
joint_pos = self.env.get_joint_data()
|
|
240
237
|
soft_joint_limits_low = self.joint_limits_low * 0.9
|
|
241
238
|
soft_joint_limits_high = self.joint_limits_high * 0.9
|