in robogym/envs/dactyl/common/cube_manipulator.py [0:0]
def rotate_face(self, axis, side, angle):
"""
Rotate given face (identified by axis and side) by given angle.
Cube should be in a reasonably aligned state for this to work well.
"""
assert 0 <= axis <= 2
assert 0 <= side <= 1
angle = rotation.normalize_angles(np.array(angle))
if np.abs(angle) < 1e-4:
# No need to do anything, the angle is too small to care
return
side = side * 2 - 1
qpos_copy = self.sim.data.qpos.copy()
# For each cubelet
for i in range(27):
cubelet_meta = self.cubelet_meta_info[i]
if cubelet_meta["type"] == "cubelet":
mtx = self._cubelet_rotation_matrix(cubelet_meta, qpos_copy)
current_coords = mtx @ cubelet_meta["coords"].astype(float)
is_selected = np.take(current_coords, axis) * side > 0.5
if is_selected:
euler = np.zeros(3)
euler[axis] = angle
combined_matrix = rotation.euler2mat(euler) @ mtx
new_euler = rotation.mat2euler(combined_matrix)
self.sim.data.qpos[cubelet_meta["euler_qpos"]] = new_euler
elif cubelet_meta["type"] == "driver":
# No transformation matrix really here
current_coords = cubelet_meta["coords"]
is_selected = np.take(current_coords, axis) * side > 0.5
if is_selected:
joint_idx = self.joints_qpos_idx[cubelet_meta["driver"]]
self.sim.data.qpos[joint_idx] += angle