in robogym/envs/dactyl/common/cube_manipulator.py [0:0]
def from_pycuber(self, cube: pycuber.Cube):
"""
Set cubelet positions based on the pycuber cube state
Image copied from rubik_utils.py
Z(+) Up (Yellow) Faces:
| +X: Right (Orange)
| / Y(+) Back (Blue) -X: Left (Red)
_____________ / +Y: Back (Blue)
/ /| -Y: Front (Green)
/ / | +Z: Up (Yellow)
/ / | -Z: Down (White)
/____________/ |
| | |____ X(+) Right (Orange)
Left | | /
(Red) | Front | /
| (Green) | /
|____________|/
Down (White)
"""
# First, we zero out the cubelet positions to reset all of the cube state
self.sim.data.qpos[self.joints_qpos_idx] = 0.0
for cubelet in cube.children:
if isinstance(cubelet, pycuber.cube.Corner):
mtx = np.zeros((3, 3))
for element in cubelet.location:
# Example: Corner(B: [r], U: [y], L: [g])
# Original location: red, yellow, green: -X, +Z, -Y
# Current location back, up, left: +Y, +Z, -X
# Mapping: -X -> +Y, +Z -> +Z, -Y -> -X
axis, sign = PYCUBER_COLOR_AXES_DESCRIPTIONS[
cubelet[element].colour
]
vector = PYCUBER_LOCATION_AXES[element]
mtx[:, axis] = sign * vector
euler_angles = rotation.mat2euler(mtx)
original_location: np.array = sum(
PYCUBER_COLOR_AXES[x.colour] for x in cubelet.children
)
idx = (
(original_location[0] + 1) * 9
+ (original_location[1] + 1) * 3
+ original_location[2]
+ 1
)
# Set the euler angles
self.sim.data.qpos[
self.cubelet_meta_info[idx]["euler_qpos"]
] = euler_angles
elif isinstance(cubelet, pycuber.cube.Edge):
# Example:
# Edge(R: [o], B: [g])
# original location: orange-green +X, -Y, (1, -1, 0)
# current location: right-back, +X, +Y (1, 1, 0)
original_location = sum(
PYCUBER_COLOR_AXES[x.colour] for x in cubelet.children
)
mtx = np.zeros((3, 3))
axes = {0, 1, 2}
for element in cubelet.location:
axis, sign = PYCUBER_COLOR_AXES_DESCRIPTIONS[
cubelet[element].colour
]
vector = PYCUBER_LOCATION_AXES[element]
mtx[:, axis] = sign * vector
axes.remove(axis)
remaining_axis = axes.pop()
# Antisymmetric tensor
if remaining_axis == 0:
mtx[:, 0] = np.cross(mtx[:, 1], mtx[:, 2])
elif remaining_axis == 1:
mtx[:, 1] = -np.cross(mtx[:, 0], mtx[:, 2])
elif remaining_axis == 2:
mtx[:, 2] = np.cross(mtx[:, 0], mtx[:, 1])
euler_angles = rotation.mat2euler(mtx)
idx = (
(original_location[0] + 1) * 9
+ (original_location[1] + 1) * 3
+ original_location[2]
+ 1
)
# Set the euler angles
self.sim.data.qpos[
self.cubelet_meta_info[idx]["euler_qpos"]
] = euler_angles