mp_yam_code / source /bimanual /yam /tasks /push_relay.py
yqi19's picture
YAM bimanual task suite: env, solvers, tasks, converters
7399b6f verified
Raw
History Blame Contribute Delete
2.84 kB
"""Bimanual L-shaped relay push: each arm drives one leg, and neither can do the other's.
The route turns a corner on purpose. The right arm's shoulder is at y=-0.2 and the left arm's at
y=+0.2, so an arm can only push comfortably AWAY from its own shoulder: the right arm can drive
the block in +x, the left arm can drive it in -y. Getting the block from the start to the pad
needs both, in that order.
A straight-line relay does not work here, and not for a tuning reason: pushing along -y means
standing on the block's +y side, which the right arm can only reach by stretching over the block
itself -- the approach swipes it off the table.
"""
from ..registry import register_task
from ..envs import YamTaskEnv
from ..solvers import push
from .. import conditions as C
@register_task("push_relay")
class PushRelayTask(YamTaskEnv):
title = "RELAY-PUSH THE BLOCK AROUND THE CORNER"
tags = ["bimanual", "push", "no-grasp", "coordination", "primitive"]
instruction = {"default": "Push the block onto the pad, using both arms in turn."}
bimanual = True
# Both legs run DIAGONALLY (+x and -y together), which is the direction each arm naturally
# pushes: the left shoulder is at (-0.2,+0.2) and the right at (-0.2,-0.2), so a hand stands
# on the near side of the block and drives it away and across. A leg 1 out at y=+0.12 with
# the RIGHT arm never reached the block at all -- it sat at 0.20 m of error for 220 steps.
block_spawn = (-0.15, 0.12) # deep in the left arm's band
spawn_jitter = (0.018, 0.015)
corner_xy = (0.02, -0.02) # end of the left arm's diagonal leg
target_xy = (0.18, -0.10) # end of the right arm's diagonal leg; left arm cannot reach
target_size = 0.11
gripper_effort, gripper_damping = 78, 88
def _load_scene(self):
self.scene.build_marker({"name": "corner", "xy": self.corner_xy, "size": 0.085,
"color": (0.55, 0.55, 0.58), "xy_jitter": (0.012, 0.012)})
self.scene.build_marker({"name": "target", "xy": self.target_xy, "size": self.target_size,
"color": (0.90, 0.68, 0.15), "xy_jitter": (0.012, 0.012)})
self._placed = [self.scene.place_object(
{"name": "cube_y", "xy": self.block_spawn, "xy_jitter": self.spawn_jitter})]
def solve(self):
return push.relay(self, obj="cube_y", legs=[
{"arm": "left", "target": "corner"}, # diagonal, away from the left shoulder
{"arm": "right", "target": "target"}, # diagonal, away from the right shoulder
])
def evaluate(self):
return self.check(
C.labelled("block reached the pad", C.object_moved_to("cube_y", "target", tol=0.07)),
C.labelled("block never left the table", C.object_level("cube_y", 40.0)))