def cmu_humanoid_run_gaps(random_state=None): """Requires a CMU humanoid to run down a corridor with gaps.""" # Build a position-controlled CMU humanoid walker. walker = cmu_humanoid.CMUHumanoidPositionControlled( observable_options={'egocentric_camera': dict(enabled=True)}) # Build a corridor-shaped arena with gaps, where the sizes of the gaps and # platforms are uniformly randomized. arena = corr_arenas.GapsCorridor( platform_length=distributions.Uniform(.3, 2.5), gap_length=distributions.Uniform(.5, 1.25), corridor_width=10, corridor_length=100) # Build a task that rewards the agent for running down the corridor at a # specific velocity. task = corr_tasks.RunThroughCorridor(walker=walker, arena=arena, walker_spawn_position=(0.5, 0, 0), target_velocity=3.0, physics_timestep=0.005, control_timestep=0.03) return composer.Environment(time_limit=30, task=task, random_state=random_state, strip_singleton_obs_buffer_dim=True)
def rodent_run_gaps(random_state=None): """Requires a rodent to run down a corridor with gaps.""" # Build a position-controlled rodent walker. walker = rodent.Rat( observable_options={'egocentric_camera': dict(enabled=True)}) # Build a corridor-shaped arena with gaps, where the sizes of the gaps and # platforms are uniformly randomized. arena = corr_arenas.GapsCorridor(platform_length=distributions.Uniform( .4, .8), gap_length=distributions.Uniform(.05, .2), corridor_width=2, corridor_length=40, aesthetic='outdoor_natural') # Build a task that rewards the agent for running down the corridor at a # specific velocity. task = corr_tasks.RunThroughCorridor(walker=walker, arena=arena, walker_spawn_position=(5, 0, 0), walker_spawn_rotation=0, target_velocity=1.0, contact_termination=False, terminate_at_height=-0.3, physics_timestep=_PHYSICS_TIMESTEP, control_timestep=_CONTROL_TIMESTEP) return composer.Environment(time_limit=30, task=task, random_state=random_state, strip_singleton_obs_buffer_dim=True)
def _build_rodent_corridor_gaps(): """Build environment where a rodent runs over gaps.""" walker = walkers.Rat( observable_options={'egocentric_camera': dict(enabled=True)}, ) platform_length = distributions.Uniform(low=0.4, high=0.8) gap_length = distributions.Uniform(low=0.05, high=0.2) arena = arenas.corridors.GapsCorridor(corridor_width=2, platform_length=platform_length, gap_length=gap_length, corridor_length=40, aesthetic='outdoor_natural') rodent_task = tasks.corridors.RunThroughCorridor(walker=walker, arena=arena, walker_spawn_position=(5, 0, 0), walker_spawn_rotation=0, target_velocity=1.0, contact_termination=False, terminate_at_height=-0.3, physics_timestep=0.001, control_timestep=.02) raw_env = composer.Environment(time_limit=30, task=rodent_task, strip_singleton_obs_buffer_dim=True) return raw_env
def jumping_ball_run_gaps(random_state=None): walker = jumping_ball.JumpingBallWithHead() # Build a corridor-shaped arena with gaps, where the sizes of the gaps and # platforms are uniformly randomized. arena = corr_arenas.GapsCorridor( platform_length=distributions.Uniform(1.0, 2.5), # (0.3, 2.5) gap_length=distributions.Uniform(0.3, 0.7), # (0.5, 1.25) corridor_width=10, corridor_length=250) # Build a task that rewards the agent for running down the corridor at a # specific velocity. task = corr_tasks.RunThroughCorridor(walker=walker, arena=arena, walker_spawn_position=(1.0, 0, 0), target_velocity=3.0, contact_termination=False, physics_timestep=_PHYSICS_TIMESTEP, control_timestep=_CONTROL_TIMESTEP) return composer.Environment(time_limit=30, task=task, random_state=random_state, strip_singleton_obs_buffer_dim=True)
def build_vision_warehouse(random_state=None): """Build canonical 4-pedestal, 2-prop task.""" # Build a position-controlled CMU humanoid walker. walker = cmu_humanoid.CMUHumanoidPositionControlled( observable_options={'egocentric_camera': dict(enabled=True)}) # Build the task. size_distribution = distributions.Uniform(low=0.75, high=1.25) mass_distribution = distributions.Uniform(low=2, high=7) prop_resizer = mocap_loader.PropResizer(size_factor=size_distribution, mass=mass_distribution) task = warehouse.PhasedBoxCarry( walker=walker, num_props=2, num_pedestals=4, proto_modifier=prop_resizer, negative_reward_on_failure_termination=True) # return the environment return composer.Environment(time_limit=15, task=task, random_state=random_state, strip_singleton_obs_buffer_dim=True, max_reset_attempts=float('inf'))
def _build_humanoid_walls_env(): """Build humanoid walker walls environment.""" walker = walkers.CMUHumanoidPositionControlled( name='walker', observable_options={'egocentric_camera': dict(enabled=True)}, ) wall_width = distributions.Uniform(low=1, high=7) wall_height = distributions.Uniform(low=2.5, high=4.0) swap_wall_side = distributions.Bernoulli(prob=0.5) wall_r = distributions.Uniform(low=0.5, high=0.6) wall_g = distributions.Uniform(low=0.21, high=0.41) wall_rgba = colors.RgbVariation(r=wall_r, g=wall_g, b=0, alpha=1) arena = arenas.WallsCorridor(wall_gap=5.0, wall_width=wall_width, wall_height=wall_height, swap_wall_side=swap_wall_side, wall_rgba=wall_rgba, corridor_width=10, corridor_length=100) humanoid_task = tasks.RunThroughCorridor( walker=walker, arena=arena, walker_spawn_rotation=1.57, # pi / 2 physics_timestep=0.005, control_timestep=0.03) raw_env = composer.Environment(time_limit=30, task=humanoid_task, strip_singleton_obs_buffer_dim=True) return raw_env
def walker_run_gaps(random_state=None): walker = planar_walker.PlanarWalker() # Build a corridor-shaped arena with gaps, where the sizes of the gaps and # platforms are uniformly randomized. arena = corr_arenas.GapsCorridor( platform_length=distributions.Uniform(1.25, 2.5), # (0.3, 2.5) gap_length=distributions.Uniform(0.3, 0.7), # (0.5, 1.25) corridor_width=10, corridor_length=250) # Build a task that rewards the agent for running down the corridor at a # specific velocity. task = corr_tasks.RunThroughCorridor(walker=walker, arena=arena, walker_spawn_position=(1.0, 0, 0), stand_height=1.2, contact_termination=False, physics_timestep=_PHYSICS_TIMESTEP, control_timestep=_CONTROL_TIMESTEP) # (Chongyi Zheng): redefine reward function task.get_reward = _walker_get_reward.__get__(task, task.get_reward) return composer.Environment(time_limit=30, task=task, random_state=random_state, strip_singleton_obs_buffer_dim=True)
def build_vision_toss(random_state=None): """Build canonical ball tossing task.""" # Build a position-controlled CMU humanoid walker. walker = cmu_humanoid.CMUHumanoidPositionControlled( observable_options={'egocentric_camera': dict(enabled=True)}) # Build the task. size_distribution = distributions.Uniform(low=0.95, high=1.5) mass_distribution = distributions.Uniform(low=2, high=4) prop_resizer = mocap_loader.PropResizer(size_factor=size_distribution, mass=mass_distribution) task = ball_toss.BallToss(walker=walker, proto_modifier=prop_resizer, negative_reward_on_failure_termination=True, priority_friction=True, bucket_offset=3., y_range=0.5, toss_delay=1.5, randomize_init=True) # return the environment return composer.Environment(time_limit=6, task=task, random_state=random_state, strip_singleton_obs_buffer_dim=True, max_reset_attempts=float('inf'))
def __init__( self, arena, arm, hand, prop, obs_settings, workspace, control_timestep): """Initializes a new `Reach` task. Args: arena: `composer.Entity` instance. arm: `robot_base.RobotArm` instance. hand: `robot_base.RobotHand` instance. prop: `composer.Entity` instance specifying the prop to reach to, or None in which case the target is a fixed site whose position is specified by the workspace. obs_settings: `observations.ObservationSettings` instance. workspace: `_ReachWorkspace` specifying the placement of the prop and TCP. control_timestep: Float specifying the control timestep in seconds. """ self._arena = arena self._arm = arm self._hand = hand self._arm.attach(self._hand) self._arena.attach_offset(self._arm, offset=workspace.arm_offset) self.control_timestep = control_timestep self._tcp_initializer = initializers.ToolCenterPointInitializer( self._hand, self._arm, position=distributions.Uniform(*workspace.tcp_bbox), quaternion=workspaces.DOWN_QUATERNION) # Add custom camera observable. self._task_observables = cameras.add_camera_observables( arena, obs_settings, cameras.FRONT_CLOSE) target_pos_distribution = distributions.Uniform(*workspace.target_bbox) self._prop = prop if prop: # The prop itself is used to visualize the target location. self._make_target_site(parent_entity=prop, visible=False) self._target = self._arena.add_free_entity(prop) self._prop_placer = initializers.PropPlacer( props=[prop], position=target_pos_distribution, quaternion=workspaces.uniform_z_rotation, settle_physics=True) else: self._target = self._make_target_site(parent_entity=arena, visible=True) self._target_placer = target_pos_distribution obs = observable.MJCFFeature('pos', self._target) obs.configure(**obs_settings.prop_pose._asdict()) self._task_observables['target_position'] = obs # Add sites for visualizing the prop and target bounding boxes. workspaces.add_bbox_site( body=self.root_entity.mjcf_model.worldbody, lower=workspace.tcp_bbox.lower, upper=workspace.tcp_bbox.upper, rgba=constants.GREEN, name='tcp_spawn_area') workspaces.add_bbox_site( body=self.root_entity.mjcf_model.worldbody, lower=workspace.target_bbox.lower, upper=workspace.target_bbox.upper, rgba=constants.BLUE, name='target_spawn_area')
def __init__(self, arena, arm, hand, prop, obs_settings, workspace, control_timestep): """Initializes a new `Lift` task. Args: arena: `composer.Entity` instance. arm: `robot_base.RobotArm` instance. hand: `robot_base.RobotHand` instance. prop: `composer.Entity` instance. obs_settings: `observations.ObservationSettings` instance. workspace: `_LiftWorkspace` specifying the placement of the prop and TCP. control_timestep: Float specifying the control timestep in seconds. """ self._arena = arena self._arm = arm self._hand = hand self._arm.attach(self._hand) self._arena.attach_offset(self._arm, offset=workspace.arm_offset) self.control_timestep = control_timestep # Add custom camera observable. self._task_observables = cameras.add_camera_observables( arena, obs_settings, cameras.FRONT_CLOSE) self._tcp_initializer = initializers.ToolCenterPointInitializer( self._hand, self._arm, position=distributions.Uniform(*workspace.tcp_bbox), quaternion=workspaces.DOWN_QUATERNION) self._prop = prop self._arena.add_free_entity(prop) self._prop_placer = initializers.PropPlacer( props=[prop], position=distributions.Uniform(*workspace.prop_bbox), quaternion=workspaces.uniform_z_rotation, ignore_collisions=True, settle_physics=True) # Add sites for visualizing bounding boxes and target height. self._target_height_site = workspaces.add_bbox_site( body=self.root_entity.mjcf_model.worldbody, lower=(-1, -1, 0), upper=(1, 1, 0), rgba=constants.RED, name='target_height') workspaces.add_bbox_site(body=self.root_entity.mjcf_model.worldbody, lower=workspace.tcp_bbox.lower, upper=workspace.tcp_bbox.upper, rgba=constants.GREEN, name='tcp_spawn_area') workspaces.add_bbox_site(body=self.root_entity.mjcf_model.worldbody, lower=workspace.prop_bbox.lower, upper=workspace.prop_bbox.upper, rgba=constants.BLUE, name='prop_spawn_area')
class PitchTest(parameterized.TestCase): def _pitch_with_ball(self, pitch_size, ball_pos): pitch = pitch_lib.Pitch(size=pitch_size) self.assertEqual(pitch.size, pitch_size) sphere = props.Primitive(geom_type='sphere', size=(0.1,), pos=ball_pos) pitch.register_ball(sphere) pitch.attach(sphere) env = composer.Environment( composer.NullTask(pitch), random_state=np.random.RandomState(42)) env.reset() return pitch def test_pitch_none_detected(self): pitch = self._pitch_with_ball((12, 9), (0, 0, 0)) self.assertEmpty(pitch.detected_off_court()) self.assertIsNone(pitch.detected_goal()) def test_pitch_detected_off_court(self): pitch = self._pitch_with_ball((12, 9), (20, 0, 0)) self.assertLen(pitch.detected_off_court(), 1) self.assertIsNone(pitch.detected_goal()) def test_pitch_detected_away_goal(self): pitch = self._pitch_with_ball((12, 9), (-9.5, 0, 1)) self.assertLen(pitch.detected_off_court(), 1) self.assertEqual(team_lib.Team.AWAY, pitch.detected_goal()) def test_pitch_detected_home_goal(self): pitch = self._pitch_with_ball((12, 9), (9.5, 0, 1)) self.assertLen(pitch.detected_off_court(), 1) self.assertEqual(team_lib.Team.HOME, pitch.detected_goal()) @parameterized.parameters((True, distributions.Uniform()), (False, distributions.Uniform())) def test_randomize_pitch(self, keep_aspect_ratio, randomizer): pitch = pitch_lib.RandomizedPitch( min_size=(4, 3), max_size=(8, 6), randomizer=randomizer, keep_aspect_ratio=keep_aspect_ratio) pitch.initialize_episode_mjcf(np.random.RandomState(42)) self.assertBetween(pitch.size[0], 4, 8) self.assertBetween(pitch.size[1], 3, 6) if keep_aspect_ratio: self.assertAlmostEqual((pitch.size[0] - 4) / (8. - 4.), (pitch.size[1] - 3) / (6. - 3.))
def ant_run_walls(): walker = ant.Ant() arena = corr_arenas.WallsCorridor(wall_gap=4., wall_width=distributions.Uniform(1, 7), wall_height=3.0, corridor_width=10, corridor_length=250, include_initial_padding=False) task = corr_tasks.RunThroughCorridor(walker=walker, arena=arena, walker_spawn_position=(0.5, 0, 0), walker_spawn_rotation=0, stand_height=0.2, contact_termination=False, physics_timestep=_PHYSICS_TIMESTEP, control_timestep=_CONTROL_TIMESTEP) # (Chongyi Zheng): redefine reward function # task.get_reward = _ant_get_reward.__get__(task, task.get_reward) return composer.Environment(time_limit=30, task=task, strip_singleton_obs_buffer_dim=True)
def cmu_humanoid_run_walls(random_state=None): """Requires a CMU humanoid to run down a corridor obstructed by walls.""" # Build a position-controlled CMU humanoid walker. walker = cmu_humanoid.CMUHumanoidPositionControlled( observable_options={'egocentric_camera': dict(enabled=True)}) # Build a corridor-shaped arena that is obstructed by walls. arena = corr_arenas.WallsCorridor(wall_gap=4., wall_width=distributions.Uniform(1, 7), wall_height=3.0, corridor_width=10, corridor_length=100, include_initial_padding=False) # Build a task that rewards the agent for running down the corridor at a # specific velocity. task = corr_tasks.RunThroughCorridor(walker=walker, arena=arena, walker_spawn_position=(0.5, 0, 0), target_velocity=3.0, physics_timestep=0.005, control_timestep=0.03) return composer.Environment(time_limit=30, task=task, random_state=random_state, strip_singleton_obs_buffer_dim=True)
def testUniform(self): lower, upper = [2, 3, 4], [5, 6, 7] variation = distributions.Uniform(low=lower, high=upper) for _ in range(NUM_ITERATIONS): np.testing.assert_array_equal( variation(random_state=self._variation_random_state), self._np_random_state.uniform(lower, upper))
def __init__(self, arena, arm, hand, num_bricks, randomize_initial_order, randomize_desired_order, obs_settings, workspace, control_timestep): """Initializes a new `Reassemble` task. Args: arena: `composer.Entity` instance. arm: `robot_base.RobotArm` instance. hand: `robot_base.RobotHand` instance. num_bricks: The total number of bricks; must be between 2 and 6. randomize_initial_order: Boolean specifying whether to randomize the initial order of bricks in the stack at the start of each episode. randomize_desired_order: Boolean specifying whether to independently randomize the desired order of bricks in the stack at the start of each episode. By default the desired order will be the reverse of the initial order, with the exception of the base brick which is always the same as in the initial order since it is welded in place. obs_settings: `observations.ObservationSettings` instance. workspace: A `_BrickWorkspace` instance. control_timestep: Float specifying the control timestep in seconds. Raises: ValueError: If `num_bricks` is not between 2 and 6. """ super(Reassemble, self).__init__(arena=arena, arm=arm, hand=hand, num_bricks=num_bricks, obs_settings=obs_settings, workspace=workspace, control_timestep=control_timestep) self._randomize_initial_order = randomize_initial_order self._randomize_desired_order = randomize_desired_order # Randomized at the start of each episode if `randomize_initial_order` is # True. self._initial_order = np.arange(num_bricks) # Randomized at the start of each episode if `randomize_desired_order` is # True. self._desired_order = self._initial_order.copy() self._desired_order[1:] = self._desired_order[-1:0:-1] # In the random order case, create a `prop_pose` observable that informs the # agent of the desired order. if randomize_desired_order: desired_order_observable = observable.Generic( self._get_desired_order) desired_order_observable.configure( **obs_settings.prop_pose._asdict()) self._task_observables['desired_order'] = desired_order_observable # Distributions of positions and orientations for the base of the stack. self._base_pos = distributions.Uniform(*workspace.prop_bbox) self._base_quat = workspaces.uniform_z_rotation
def __init__(self, observation_settings, opponent, game_logic, board, markers): """Initializes the task. Args: observation_settings: An `observations.ObservationSettings` namedtuple specifying configuration options for each category of observation. opponent: Opponent used for generating opponent moves. game_logic: Logic for keeping track of the logical state of the board. board: Board to use. markers: Markers to use. """ self._game_logic = game_logic self._game_opponent = opponent arena = arenas.Standard(observable_options=observations.make_options( observation_settings, observations.ARENA_OBSERVABLES)) arena.attach(board) arm = kinova.JacoArm(observable_options=observations.make_options( observation_settings, observations.JACO_ARM_OBSERVABLES)) hand = kinova.JacoHand(observable_options=observations.make_options( observation_settings, observations.JACO_HAND_OBSERVABLES)) arm.attach(hand) arena.attach_offset(arm, offset=(0, _ARM_Y_OFFSET, 0)) arena.attach(markers) # Geoms belonging to the arm and hand are placed in a custom group in order # to disable their visibility to the top-down camera. NB: we assume that # there are no other geoms in ROBOT_GEOM_GROUP that don't belong to the # robot (this is usually the case since the default geom group is 0). If # there are then these will also be invisible to the top-down camera. for robot_geom in arm.mjcf_model.find_all('geom'): robot_geom.group = arenas.ROBOT_GEOM_GROUP self._arena = arena self._board = board self._arm = arm self._hand = hand self._markers = markers self._tcp_initializer = initializers.ToolCenterPointInitializer( hand=hand, arm=arm, position=distributions.Uniform(_TCP_LOWER_BOUNDS, _TCP_UPPER_BOUNDS), quaternion=_uniform_downward_rotation()) # Add an observable exposing the logical state of the board. board_state_observable = observable.Generic( lambda physics: self._game_logic.get_board_state()) board_state_observable.configure( **observation_settings.board_state._asdict()) self._task_observables = {'board_state': board_state_observable}
def _build_humanoid_corridor_gaps(): """Build humanoid walker walls environment.""" walker = walkers.CMUHumanoidPositionControlled( name='walker', observable_options={'egocentric_camera': dict(enabled=True)}, ) platform_length = distributions.Uniform(low=0.3, high=2.5) gap_length = distributions.Uniform(low=0.75, high=1.25) arena = arenas.GapsCorridor(corridor_width=10, platform_length=platform_length, gap_length=gap_length, corridor_length=100) humanoid_task = tasks.RunThroughCorridor( walker=walker, arena=arena, walker_spawn_position=(2, 0, 0), walker_spawn_rotation=1.57, # pi / 2 physics_timestep=0.005, control_timestep=0.03) raw_env = composer.Environment(time_limit=30, task=humanoid_task, strip_singleton_obs_buffer_dim=True) return raw_env
def test_sample_non_colliding_positions(self): halfwidth = 0.05 radius = halfwidth / 4. offset = np.array([0, 0, halfwidth + radius * 1.1]) lower = -np.full(3, halfwidth) + offset upper = np.full(3, halfwidth) + offset position_variation = distributions.Uniform(lower, upper) physics, spheres = _make_spheres(num_spheres=8, radius=radius, nconmax=1000) prop_placer = prop_initializer.PropPlacer(props=spheres, position=position_variation, ignore_collisions=False, settle_physics=False) prop_placer(physics, random_state=np.random.RandomState(0)) self.assertNoContactsInvolvingEntities(physics, spheres) self.assertPositionsWithinBounds(physics, spheres, lower, upper)
def __init__(self, min_size, max_size, randomizer=None, keep_aspect_ratio=False, goal_size=None, field_box=False, field_box_offset=0.0, top_camera_distance=_TOP_CAMERA_DISTANCE, name='randomized_pitch'): """Construct a randomized pitch. Args: min_size: a tuple of minimum (length, width) of the pitch. max_size: a tuple of maximum (length, width) of the pitch. randomizer: a callable that returns ratio between [0., 1.] that scales between min_size, max_size. keep_aspect_ratio: if `True`, keep the aspect ratio constant during randomization. goal_size: optional (depth, width, height) indicating the goal size. If not specified, the goal size is inferred from pitch size with a fixed default ratio. field_box: optional indicating if we should construct field box containing the ball (but not the walkers). field_box_offset: offset for the fieldbox if used. top_camera_distance: the distance of the top-down camera to the pitch. name: the name of this arena. """ super(RandomizedPitch, self).__init__(size=max_size, goal_size=goal_size, top_camera_distance=top_camera_distance, field_box=field_box, field_box_offset=field_box_offset, name=name) self._min_size = min_size self._max_size = max_size self._randomizer = randomizer or distributions.Uniform() self._keep_aspect_ratio = keep_aspect_ratio # Sample a new size and regenerate the soccer pitch. logging.info('%s between (%s, %s) with %s', self.__class__.__name__, min_size, max_size, self._randomizer)
def ant_run_walls(random_state=None): walker = ant.Ant() arena = corr_arenas.WallsCorridor(wall_gap=4., wall_width=distributions.Uniform(1, 7), wall_height=3.0, corridor_width=10, corridor_length=100, include_initial_padding=False) task = corr_tasks.RunThroughCorridor(walker=walker, arena=arena, walker_spawn_position=(0.5, 0, 0), walker_spawn_rotation=0, physics_timestep=_PHYSICS_TIMESTEP, control_timestep=_CONTROL_TIMESTEP) return composer.Environment(time_limit=30, task=task, random_state=random_state, strip_singleton_obs_buffer_dim=True)
def jumping_ball_run_walls(): walker = jumping_ball.JumpingBallWithHead() arena = corr_arenas.WallsCorridor(wall_gap=4., wall_width=distributions.Uniform(1, 7), wall_height=3.0, corridor_width=10, corridor_length=250, include_initial_padding=False) task = corr_tasks.RunThroughCorridor(walker=walker, arena=arena, walker_spawn_position=(0.5, 0, 0), walker_spawn_rotation=0, contact_termination=False, physics_timestep=_PHYSICS_TIMESTEP, control_timestep=_CONTROL_TIMESTEP) return composer.Environment(time_limit=30, task=task, strip_singleton_obs_buffer_dim=True)
def initialize_episode_mjcf(self, random_state): if self._randomize_order: self._desired_order = random_state.choice(len(self._bricks), size=self._target_height, replace=False) logging.info( 'Desired stack order (from bottom to top): [%s]', ' '.join(_COLOR_NAMES[i] for i in self._desired_order)) # If the base of the stack should be fixed, remove the freejoint for the # first brick (and ensure that all the others have freejoints). fixed_indices = [] if self._moveable_base else [self._desired_order[0]] _add_or_remove_freejoints(attachment_frames=self._brick_frames, fixed_indices=fixed_indices) # We need to define the prop initializer for the bricks here rather than in # the `__init__`, since `PropPlacer` looks for freejoints on instantiation. self._brick_placer = initializers.PropPlacer( props=self._bricks, position=distributions.Uniform(*self._prop_bbox), quaternion=workspaces.uniform_z_rotation, settle_physics=True)
_MIN_SITE_DIMENSION = 1e-6 # Ensures that all site dimensions are positive. _VISIBLE_GROUP = 0 _INVISIBLE_GROUP = 3 # Invisible sensor sites live in group 4 by convention. DOWN_QUATERNION = base.DOWN_QUATERNION BoundingBox = collections.namedtuple('BoundingBox', ['lower', 'upper']) uniform_z_rotation = rotations.QuaternionFromAxisAngle( axis=(0., 0., 1.), # NB: We must specify `single_sample=True` here otherwise we will sample a # length-4 array of angles rather than a scalar. This happens because # `PropPlacer` passes in the previous quaternion as `initial_value`, # and by default `distributions.Distribution` assumes that the shape # of the output array should be the same as that of `initial_value`. angle=distributions.Uniform(-np.pi, np.pi, single_sample=True)) def add_bbox_site(body, lower, upper, visible=False, **kwargs): """Adds a site for visualizing a bounding box to an MJCF model. Args: body: An `mjcf.Element`, the (world)body to which the site should be added. lower: A sequence of lower x,y,z bounds. upper: A sequence of upper x,y,z bounds. visible: Whether the site should be visible by default. **kwargs: Keyword arguments used to set other attributes of the newly created site. Returns: An `mjcf.Element` representing the newly created site.
def __init__(self, arena, arm, hand, num_bricks, obs_settings, workspace, control_timestep): if not 2 <= num_bricks <= 6: raise ValueError( '`num_bricks` must be between 2 and 6, got {}.'.format( num_bricks)) if num_bricks > 3: # The default values computed by MuJoCo's compiler are too small if there # are more than three stacked bricks, since each stacked pair generates # a large number of contacts. The values below are sufficient for up to # 6 stacked bricks. # TODO(b/78331644): It may be useful to log the size of `physics.model` # and `physics.data` after compilation to gauge the # impact of these changes on MuJoCo's memory footprint. arena.mjcf_model.size.nconmax = 400 arena.mjcf_model.size.njmax = 1200 self._arena = arena self._arm = arm self._hand = hand self._arm.attach(self._hand) self._arena.attach_offset(self._arm, offset=workspace.arm_offset) self.control_timestep = control_timestep # Add custom camera observable. self._task_observables = cameras.add_camera_observables( arena, obs_settings, cameras.FRONT_CLOSE) color_sequence = iter(_COLOR_VALUES) brick_obs_options = observations.make_options( obs_settings, observations.FREEPROP_OBSERVABLES) bricks = [] brick_frames = [] goal_hint_bricks = [] for _ in range(num_bricks): color = next(color_sequence) brick = props.Duplo(color=color, observable_options=brick_obs_options) brick_frames.append(arena.add_free_entity(brick)) bricks.append(brick) # Translucent, contactless brick with no observables. These are used to # provide a visual hint representing the goal state for each task. hint_brick = props.Duplo(color=color) _hintify(hint_brick, alpha=_HINT_ALPHA) arena.attach(hint_brick) goal_hint_bricks.append(hint_brick) self._bricks = bricks self._brick_frames = brick_frames self._goal_hint_bricks = goal_hint_bricks # Position and quaternion for the goal hint. self._goal_hint_pos = workspace.goal_hint_pos self._goal_hint_quat = workspace.goal_hint_quat self._tcp_initializer = initializers.ToolCenterPointInitializer( self._hand, self._arm, position=distributions.Uniform(*workspace.tcp_bbox), quaternion=workspaces.DOWN_QUATERNION) # Add sites for visual debugging. workspaces.add_bbox_site(body=self.root_entity.mjcf_model.worldbody, lower=workspace.tcp_bbox.lower, upper=workspace.tcp_bbox.upper, rgba=constants.GREEN, name='tcp_spawn_area') workspaces.add_bbox_site(body=self.root_entity.mjcf_model.worldbody, lower=workspace.prop_bbox.lower, upper=workspace.prop_bbox.upper, rgba=constants.BLUE, name='prop_spawn_area')
def __init__(self, arena, arm, hand, prop, obs_settings, workspace, control_timestep, table_col_tag): """Initializes a new `Reach` task. Args: arena: `composer.Entity` instance. arm: `robot_base.RobotArm` instance. hand: `robot_base.RobotHand` instance. prop: `composer.Entity` instance specifying the prop to reach to, or None in which case the target is a fixed site whose position is specified by the workspace. obs_settings: `observations.ObservationSettings` instance. workspace: `_ReachWorkspace` specifying the placement of the prop and TCP. control_timestep: Float specifying the control timestep in seconds. """ self._arena = arena self._arm = arm self._hand = hand self._arm.attach(self._hand) self._arena.attach_offset(self._arm, offset=workspace.arm_offset) self.control_timestep = control_timestep self._tcp_initializer = initializers.ToolCenterPointInitializer( self._hand, self._arm, position=distributions.Uniform(*workspace.tcp_bbox), quaternion=workspaces.DOWN_QUATERNION) # Add custom camera observable. self._task_observables = cameras.add_camera_observables( arena, obs_settings, cameras.FRONT_FAR) target_pos_distribution = distributions.Uniform(*workspace.target_bbox) self._prop = prop if prop: # The prop itself is used to visualize the target location. self._make_target_site(parent_entity=prop, visible=False) self._target = self._arena.add_free_entity(prop) self._prop_placer = initializers.PropPlacer( props=[prop], position=target_pos_distribution, quaternion=workspaces.uniform_z_rotation, settle_physics=True) else: self._target = self._make_target_site(parent_entity=arena, visible=True) self._target_placer = target_pos_distribution obs = observable.MJCFFeature('pos', self._target) obs.configure(**obs_settings.prop_pose._asdict()) self._task_observables['target_position'] = obs # Randomize the table surface if table_col_tag == 0: self.root_entity.mjcf_model.worldbody.add('geom', type='plane', pos="0 0 0.01", size="0.6 0.6 0.5", rgba=".6 .6 .5 1", contype="1", conaffinity="1", friction="2 0.1 0.002", material="j2s7/robot_bw") elif table_col_tag == 1: self.root_entity.mjcf_model.worldbody.add('geom', type='plane', pos="0 0 0.01", size="0.6 0.6 0.5", rgba=".6 .6 .5 1", contype="1", conaffinity="1", friction="2 0.1 0.002", material="j2s7/robot_bw") elif table_col_tag == 2: self.root_entity.mjcf_model.worldbody.add( 'geom', type='plane', pos="0 0 0.01", size="0.6 0.6 0.5", rgba=".6 .6 .5 1", contype="1", conaffinity="1", friction="2 0.1 0.002", material="j2s7/real_desk") # Blue stary sky self.root_entity.mjcf_model.asset.texture[0].mark = 'random' self.root_entity.mjcf_model.asset.texture[0].rgb1 = np.array( [.4, .6, .8]) self.root_entity.mjcf_model.asset.texture[0].width = 800 self.root_entity.mjcf_model.asset.texture[0].height = 800 # How to remove the checkerboard groundplane ? # For now this somehow sets it to a white plane! self.root_entity.mjcf_model.asset.texture[1].width = 1 self.root_entity.mjcf_model.asset.texture[1].height = 1 # Add sites for visualizing the prop and target bounding boxes. workspaces.add_bbox_site(body=self.root_entity.mjcf_model.worldbody, lower=workspace.tcp_bbox.lower, upper=workspace.tcp_bbox.upper, rgba=constants.GREEN, name='tcp_spawn_area') workspaces.add_bbox_site(body=self.root_entity.mjcf_model.worldbody, lower=workspace.target_bbox.lower, upper=workspace.target_bbox.upper, rgba=constants.BLUE, name='target_spawn_area')
def __init__(self, arena, arm, hand, prop, obs_settings, workspace, control_timestep, table_col_tag, sky_col_tag): """Initializes a new `Reach` task. Args: arena: `composer.Entity` instance. arm: `robot_base.RobotArm` instance. hand: `robot_base.RobotHand` instance. prop: `composer.Entity` instance specifying the prop to reach to, or None in which case the target is a fixed site whose position is specified by the workspace. obs_settings: `observations.ObservationSettings` instance. workspace: `_ReachWorkspace` specifying the placement of the prop and TCP. control_timestep: Float specifying the control timestep in seconds. """ self._arena = arena self._arm = arm self._hand = hand self._arm.attach(self._hand) self._arena.attach_offset(self._arm, offset=workspace.arm_offset) self.control_timestep = control_timestep self._tcp_initializer = initializers.ToolCenterPointInitializer( self._hand, self._arm, position=distributions.Uniform(*workspace.tcp_bbox), quaternion=workspaces.DOWN_QUATERNION) # Add custom camera observable. # Randomize camera viewing angle during training # Experimental randomize_cam = False if randomize_cam: camera_angle = random.choice([0, 1, 2, 3]) if camera_angle == 0: self._task_observables = cameras.add_camera_observables( arena, obs_settings, cameras.FRONT_FAR) elif camera_angle == 1: self._task_observables = cameras.add_camera_observables( arena, obs_settings, cameras.FRONT_CLOSE) elif camera_angle == 2: self._task_observables = cameras.add_camera_observables( arena, obs_settings, cameras.FRONT_CLOSE_TILT_UP) elif camera_angle == 3: self._task_observables = cameras.add_camera_observables( arena, obs_settings, cameras.FRONT_CLOSE_TILT_DOWN) else: self._task_observables = cameras.add_camera_observables( arena, obs_settings, cameras.FRONT_FAR) target_pos_distribution = distributions.Uniform(*workspace.target_bbox) self._prop = prop if prop: # The prop itself is used to visualize the target location. self._make_target_site(parent_entity=prop, visible=False) self._target = self._arena.add_free_entity(prop) self._prop_placer = initializers.PropPlacer( props=[prop], position=target_pos_distribution, quaternion=workspaces.uniform_z_rotation, settle_physics=True) else: self._target = self._make_target_site(parent_entity=arena, visible=True) self._target_placer = target_pos_distribution obs = observable.MJCFFeature('pos', self._target) obs.configure(**obs_settings.prop_pose._asdict()) self._task_observables['target_position'] = obs # Randomize the table surface if table_col_tag == 0: self.root_entity.mjcf_model.worldbody.add('geom', type='plane', pos="0 0 0.01", size="0.6 0.6 0.5", rgba=".6 .6 .5 1", contype="1", conaffinity="1", friction="2 0.1 0.002", material="j2s7/darkwood") elif table_col_tag == 1: self.root_entity.mjcf_model.worldbody.add('geom', type='plane', pos="0 0 0.01", size="0.6 0.6 0.5", rgba=".6 .6 .5 1", contype="1", conaffinity="1", friction="2 0.1 0.002", material="j2s7/marble") elif table_col_tag == 2: self.root_entity.mjcf_model.worldbody.add( 'geom', type='plane', pos="0 0 0.01", size="0.6 0.6 0.5", rgba=".6 .6 .5 1", contype="1", conaffinity="1", friction="2 0.1 0.002", material="j2s7/navy_blue") elif table_col_tag == 3: self.root_entity.mjcf_model.worldbody.add('geom', type='plane', pos="0 0 0.01", size="0.6 0.6 0.5", rgba=".6 .6 .5 1", contype="1", conaffinity="1", friction="2 0.1 0.002", material="j2s7/tennis") elif table_col_tag == 4: self.root_entity.mjcf_model.worldbody.add('geom', type='plane', pos="0 0 0.01", size="0.6 0.6 0.5", rgba=".6 .6 .5 1", contype="1", conaffinity="1", friction="2 0.1 0.002", material="j2s7/wood") elif table_col_tag == 5: self.root_entity.mjcf_model.worldbody.add( 'geom', type='plane', pos="0 0 0.01", size="0.6 0.6 0.5", rgba=".6 .6 .5 1", contype="1", conaffinity="1", friction="2 0.1 0.002", material="j2s7/wood_light") elif table_col_tag == 6: self.root_entity.mjcf_model.worldbody.add( 'geom', type='plane', pos="0 0 0.01", size="0.6 0.6 0.5", rgba=".6 .6 .5 1", contype="1", conaffinity="1", friction="2 0.1 0.002", material="j2s7/light_wood_v2") elif table_col_tag == 7: self.root_entity.mjcf_model.worldbody.add('geom', type='plane', pos="0 0 0.01", size="0.6 0.6 0.5", rgba=".6 .6 .5 1", contype="1", conaffinity="1", friction="2 0.1 0.002", material="j2s7/metal") elif table_col_tag == 8: self.root_entity.mjcf_model.worldbody.add('geom', type='plane', pos="0 0 0.01", size="0.6 0.6 0.5", rgba=".6 .6 .5 1", contype="1", conaffinity="1", friction="2 0.1 0.002", material="j2s7/grass") elif table_col_tag == 9: self.root_entity.mjcf_model.worldbody.add( 'geom', type='plane', pos="0 0 0.01", size="0.6 0.6 0.5", rgba=".6 .6 .5 1", contype="1", conaffinity="1", friction="2 0.1 0.002", material="j2s7/blue_cloud") elif table_col_tag == 10: self.root_entity.mjcf_model.worldbody.add( 'geom', type='plane', pos="0 0 0.01", size="0.6 0.6 0.5", rgba=".6 .6 .5 1", contype="1", conaffinity="1", friction="2 0.1 0.002", material="j2s7/marble_v2") elif table_col_tag == 11: self.root_entity.mjcf_model.worldbody.add( 'geom', type='plane', pos="0 0 0.01", size="0.6 0.6 0.5", rgba=".6 .6 .5 1", contype="1", conaffinity="1", friction="2 0.1 0.002", material="j2s7/wood_gray") # Sky change of colour if sky_col_tag == 1: # Red stary sky self.root_entity.mjcf_model.asset.texture[0].mark = 'random' self.root_entity.mjcf_model.asset.texture[0].rgb1 = np.array( [.8, .1, .4]) self.root_entity.mjcf_model.asset.texture[0].width = 800 self.root_entity.mjcf_model.asset.texture[0].height = 800 elif sky_col_tag == 2: # Orange stary sky self.root_entity.mjcf_model.asset.texture[0].mark = 'random' self.root_entity.mjcf_model.asset.texture[0].rgb1 = np.array( [.8, .5, .1]) self.root_entity.mjcf_model.asset.texture[0].width = 800 self.root_entity.mjcf_model.asset.texture[0].height = 800 elif sky_col_tag == 3: # Yellow stary sky self.root_entity.mjcf_model.asset.texture[0].mark = 'random' self.root_entity.mjcf_model.asset.texture[0].rgb1 = np.array( [1, 1, .4]) self.root_entity.mjcf_model.asset.texture[0].width = 800 self.root_entity.mjcf_model.asset.texture[0].height = 800 elif sky_col_tag == 4: # Pink stary sky self.root_entity.mjcf_model.asset.texture[0].mark = 'random' self.root_entity.mjcf_model.asset.texture[0].rgb1 = np.array( [1, .5, 1]) self.root_entity.mjcf_model.asset.texture[0].width = 800 self.root_entity.mjcf_model.asset.texture[0].height = 800 elif sky_col_tag == 5: # Amber stary sky self.root_entity.mjcf_model.asset.texture[0].mark = 'random' self.root_entity.mjcf_model.asset.texture[0].rgb1 = np.array( [1, .6, .4]) self.root_entity.mjcf_model.asset.texture[0].width = 800 self.root_entity.mjcf_model.asset.texture[0].height = 800 elif sky_col_tag == 6: # White stary sky self.root_entity.mjcf_model.asset.texture[0].rgb1 = np.array( [1., 1., 1.]) self.root_entity.mjcf_model.asset.texture[0].rgb2 = np.array( [1., 1., 1.]) self.root_entity.mjcf_model.asset.texture[0].width = 800 self.root_entity.mjcf_model.asset.texture[0].height = 800 elif sky_col_tag == 7: # Black stary sky self.root_entity.mjcf_model.asset.texture[0].rgb1 = np.array( [0, 0, 0]) self.root_entity.mjcf_model.asset.texture[0].width = 800 self.root_entity.mjcf_model.asset.texture[0].height = 800 elif sky_col_tag == 8: # Leave the checkerboard self.root_entity.mjcf_model.asset.texture[1].width = 1 self.root_entity.mjcf_model.asset.texture[1].height = 1 # TODO: Remove the checkerboard groundplane # For now this somehow sets it to a white plane! self.root_entity.mjcf_model.asset.texture[1].width = 1 self.root_entity.mjcf_model.asset.texture[1].height = 1 # Add sites for visualizing the prop and target bounding boxes. workspaces.add_bbox_site(body=self.root_entity.mjcf_model.worldbody, lower=workspace.tcp_bbox.lower, upper=workspace.tcp_bbox.upper, rgba=constants.GREEN, name='tcp_spawn_area') workspaces.add_bbox_site(body=self.root_entity.mjcf_model.worldbody, lower=workspace.target_bbox.lower, upper=workspace.target_bbox.upper, rgba=constants.BLUE, name='target_spawn_area')
def _uniform_downward_rotation(): angle = distributions.Uniform(-np.pi, np.pi, single_sample=True) quaternion = rotations.QuaternionFromAxisAngle(axis=(0., 0., 1.), angle=angle) return functools.partial(rotations.QuaternionPreMultiply(quaternion), initial_value=base.DOWN_QUATERNION)
def __init__(self, arena, arm, hand, prop, obs_settings, workspace, control_timestep, cradle): """Initializes a new `Place` task. Args: arena: `composer.Entity` instance. arm: `robot_base.RobotArm` instance. hand: `robot_base.RobotHand` instance. prop: `composer.Entity` instance. obs_settings: `observations.ObservationSettings` instance. workspace: A `_PlaceWorkspace` instance. control_timestep: Float specifying the control timestep in seconds. cradle: `composer.Entity` onto which the `prop` must be placed. """ self._arena = arena self._arm = arm self._hand = hand self._arm.attach(self._hand) self._arena.attach_offset(self._arm, offset=workspace.arm_offset) self.control_timestep = control_timestep # Add custom camera observable. self._task_observables = cameras.add_camera_observables( arena, obs_settings, cameras.FRONT_CLOSE) self._tcp_initializer = initializers.ToolCenterPointInitializer( self._hand, self._arm, position=distributions.Uniform(*workspace.tcp_bbox), quaternion=workspaces.DOWN_QUATERNION) self._prop = prop self._prop_frame = self._arena.add_free_entity(prop) self._pedestal = Pedestal(cradle=cradle, target_radius=_TARGET_RADIUS) self._arena.attach(self._pedestal) for obs in six.itervalues(self._pedestal.observables.as_dict()): obs.configure(**obs_settings.prop_pose._asdict()) self._prop_placer = initializers.PropPlacer( props=[prop], position=distributions.Uniform(*workspace.prop_bbox), quaternion=workspaces.uniform_z_rotation, settle_physics=True, max_attempts_per_prop=50) self._pedestal_placer = initializers.PropPlacer( props=[self._pedestal], position=distributions.Uniform(*workspace.target_bbox), settle_physics=False) # Add sites for visual debugging. workspaces.add_bbox_site(body=self.root_entity.mjcf_model.worldbody, lower=workspace.tcp_bbox.lower, upper=workspace.tcp_bbox.upper, rgba=constants.GREEN, name='tcp_spawn_area') workspaces.add_bbox_site(body=self.root_entity.mjcf_model.worldbody, lower=workspace.prop_bbox.lower, upper=workspace.prop_bbox.upper, rgba=constants.BLUE, name='prop_spawn_area') workspaces.add_bbox_site(body=self.root_entity.mjcf_model.worldbody, lower=workspace.target_bbox.lower, upper=workspace.target_bbox.upper, rgba=constants.CYAN, name='pedestal_spawn_area')
def __init__(self, walker, arena, moving_target=False, target_relative=False, target_relative_dist=1.5, steps_before_moving_target=10, distance_tolerance=DEFAULT_DISTANCE_TOLERANCE_TO_TARGET, target_spawn_position=None, walker_spawn_position=None, walker_spawn_rotation=None, physics_timestep=0.005, control_timestep=0.025): """Initializes this task. Args: walker: an instance of `locomotion.walkers.base.Walker`. arena: an instance of `locomotion.arenas.floors.Floor`. moving_target: bool, Whether the target should move after receiving the walker reaches it. target_relative: bool, Whether the target be set relative to its current position. target_relative_dist: float, new target distance range if using target_relative. steps_before_moving_target: int, the number of steps before the target moves, if moving_target==True. distance_tolerance: Accepted to distance to the target position before providing reward. target_spawn_position: a sequence of 2 numbers, or a `composer.Variation` instance that generates such sequences, specifying the position at which the target is spawned at the beginning of an episode. If None, the entire arena is used to generate random target positions. walker_spawn_position: a sequence of 2 numbers, or a `composer.Variation` instance that generates such sequences, specifying the position at which the walker is spawned at the beginning of an episode. If None, the entire arena is used to generate random spawn positions. walker_spawn_rotation: a number, or a `composer.Variation` instance that generates a number, specifying the yaw angle offset (in radians) that is applied to the walker at the beginning of an episode. physics_timestep: a number specifying the timestep (in seconds) of the physics simulation. control_timestep: a number specifying the timestep (in seconds) at which the agent applies its control inputs (in seconds). """ self._arena = arena self._walker = walker self._walker.create_root_joints(self._arena.attach(self._walker)) arena_position = distributions.Uniform( low=-np.array(arena.size) / 2, high=np.array(arena.size) / 2) if target_spawn_position is not None: self._target_spawn_position = target_spawn_position else: self._target_spawn_position = arena_position if walker_spawn_position is not None: self._walker_spawn_position = walker_spawn_position else: self._walker_spawn_position = arena_position self._walker_spawn_rotation = walker_spawn_rotation self._distance_tolerance = distance_tolerance self._moving_target = moving_target self._target_relative = target_relative self._target_relative_dist = target_relative_dist self._steps_before_moving_target = steps_before_moving_target self._reward_step_counter = 0 self._target = self.root_entity.mjcf_model.worldbody.add( 'site', name='target', type='sphere', pos=(0., 0., 0.), size=(0.1,), rgba=(0.9, 0.6, 0.6, 1.0)) enabled_observables = [] enabled_observables += self._walker.observables.proprioception enabled_observables += self._walker.observables.kinematic_sensors enabled_observables += self._walker.observables.dynamic_sensors enabled_observables.append(self._walker.observables.sensors_touch) for obs in enabled_observables: obs.enabled = True walker.observables.add_egocentric_vector( 'target', observable.MJCFFeature('pos', self._target), origin_callable=lambda physics: physics.bind(walker.root_body).xpos) self.set_timesteps( physics_timestep=physics_timestep, control_timestep=control_timestep)