New robotics environments (#912)

This commit is contained in:
Matthias Plappert
2018-02-26 17:35:07 +01:00
committed by GitHub
parent c5b624c6a6
commit 78c416ef7b
70 changed files with 2608 additions and 43 deletions

View File

@@ -15,12 +15,12 @@ If you're not sure where to start, we recommend beginning with the
A whitepaper for OpenAI Gym is available at http://arxiv.org/abs/1606.01540, and here's a BibTeX entry that you can use to cite it in a publication::
@misc{1606.01540,
Author = {Greg Brockman and Vicki Cheung and Ludwig Pettersson and Jonas Schneider and John Schulman and Jie Tang and Wojciech Zaremba},
Title = {OpenAI Gym},
Year = {2016},
Eprint = {arXiv:1606.01540},
}
@misc{1606.01540,
Author = {Greg Brockman and Vicki Cheung and Ludwig Pettersson and Jonas Schneider and John Schulman and Jie Tang and Wojciech Zaremba},
Title = {OpenAI Gym},
Year = {2016},
Eprint = {arXiv:1606.01540},
}
.. contents:: **Contents of this document**
:depth: 2
@@ -50,15 +50,15 @@ You can perform a minimal install of ``gym`` with:
.. code:: shell
git clone https://github.com/openai/gym.git
cd gym
pip install -e .
git clone https://github.com/openai/gym.git
cd gym
pip install -e .
If you prefer, you can do a minimal install of the packaged version directly from PyPI:
.. code:: shell
pip install gym
pip install gym
You'll be able to run a few environments right away:
@@ -80,13 +80,13 @@ On OSX:
.. code:: shell
brew install cmake boost boost-python sdl2 swig wget
brew install cmake boost boost-python sdl2 swig wget
On Ubuntu 14.04:
.. code:: shell
apt-get install -y python-numpy python-dev cmake zlib1g-dev libjpeg-dev xvfb libav-tools xorg-dev python-opengl libboost-all-dev libsdl2-dev swig
apt-get install -y python-numpy python-dev cmake zlib1g-dev libjpeg-dev xvfb libav-tools xorg-dev python-opengl libboost-all-dev libsdl2-dev swig
MuJoCo has a proprietary dependency we can't set up for you. Follow
the
@@ -102,7 +102,7 @@ We currently support Linux and OS X running Python 2.7 or 3.5. Some users on OSX
.. code:: shell
brew install boost-python --with-python3
brew install boost-python --with-python3
If you want to access Gym from languages other than python, we have limited support for non-python
frameworks, such as lua/Torch, using the OpenAI Gym `HTTP API <https://github.com/openai/gym-http-api>`_.
@@ -154,10 +154,10 @@ sequence.
.. code:: python
import gym
env = gym.make('Copy-v0')
env.reset()
env.render()
import gym
env = gym.make('Copy-v0')
env.reset()
env.render()
Atari
-----
@@ -166,10 +166,10 @@ The Atari environments are a variety of Atari video games. If you didn't do the
.. code:: python
import gym
env = gym.make('SpaceInvaders-v0')
env.reset()
env.render()
import gym
env = gym.make('SpaceInvaders-v0')
env.reset()
env.render()
This will install ``atari-py``, which automatically compiles the `Arcade Learning Environment <http://www.arcadelearningenvironment.org/>`_. This can take quite a while (a few minutes on a decent laptop), so just be prepared.
@@ -180,10 +180,10 @@ Box2d is a 2D physics engine. You can install it via ``pip install -e '.[box2d]
.. code:: python
import gym
env = gym.make('LunarLander-v2')
env.reset()
env.render()
import gym
env = gym.make('LunarLander-v2')
env.reset()
env.render()
Classic control
---------------
@@ -192,10 +192,10 @@ These are a variety of classic control tasks, which would appear in a typical re
.. code:: python
import gym
env = gym.make('CartPole-v0')
env.reset()
env.render()
import gym
env = gym.make('CartPole-v0')
env.reset()
env.render()
MuJoCo
------
@@ -208,10 +208,27 @@ to set it up. You'll have to also run ``pip install -e '.[mujoco]'`` if you didn
.. code:: python
import gym
env = gym.make('Humanoid-v1')
env.reset()
env.render()
import gym
env = gym.make('Humanoid-v2')
env.reset()
env.render()
Robotics
------
`MuJoCo <http://www.mujoco.org/>`_ is a physics engine which can do
very detailed efficient simulations with contacts and we use it for all robotics environments. It's not
open-source, so you'll have to follow the instructions in `mujoco-py
<https://github.com/openai/mujoco-py#obtaining-the-binaries-and-license-key>`_
to set it up. You'll have to also run ``pip install -e '.[mujoco]'`` if you didn't do the full install.
.. code:: python
import gym
env = gym.make('HandManipulateBlock-v0')
env.reset()
env.render()
Toy text
--------
@@ -220,10 +237,10 @@ Toy environments which are text-based. There's no extra dependency to install, s
.. code:: python
import gym
env = gym.make('FrozenLake-v0')
env.reset()
env.render()
import gym
env = gym.make('FrozenLake-v0')
env.reset()
env.render()
Examples
========
@@ -241,7 +258,7 @@ We are using `pytest <http://doc.pytest.org>`_ for tests. You can run them via:
.. code:: shell
pytest
pytest
.. _See What's New section below:
@@ -249,6 +266,7 @@ We are using `pytest <http://doc.pytest.org>`_ for tests. You can run them via:
What's new
==========
- 2018-02-28: Release of a set of new robotics environments.
- 2018-01-25: Made some aesthetic improvements and removed unmaintained parts of gym. This may seem like a downgrade in functionality, but it is actually a long-needed cleanup in preparation for some great new things that will be released in the next month.
+ Now your `Env` and `Wrapper` subclasses should define `step`, `reset`, `render`, `close`, `seed` rather than underscored method names.

21
bin/render.py Executable file
View File

@@ -0,0 +1,21 @@
#!/usr/bin/env python3
import argparse
import gym
parser = argparse.ArgumentParser(description='Renders a Gym environment for quick inspection.')
parser.add_argument('env_id', type=str, help='the ID of the environment to be rendered (e.g. HalfCheetah-v1')
parser.add_argument('--step', type=int, default=1)
args = parser.parse_args()
env = gym.make(args.env_id)
env.reset()
step = 0
while True:
if args.step:
env.step(env.action_space.sample())
env.render()
if step % 10 == 0:
env.reset()
step += 1

View File

@@ -7,7 +7,7 @@ from gym import error
from gym.utils import reraise
from gym.version import VERSION as __version__
from gym.core import Env, Space, Wrapper, ObservationWrapper, ActionWrapper, RewardWrapper
from gym.core import Env, GoalEnv, Space, Wrapper, ObservationWrapper, ActionWrapper, RewardWrapper
from gym.envs import make, spec
from gym import wrappers, spaces, logger

View File

@@ -1,6 +1,7 @@
from gym import logger
import numpy as np
import gym
from gym import error
from gym.utils import closer
@@ -150,6 +151,46 @@ class Env(object):
else:
return '<{}<{}>>'.format(type(self).__name__, self.spec.id)
class GoalEnv(Env):
"""A goal-based environment. It functions just as any regular OpenAI Gym environment but it
imposes a required structure on the observation_space. More concretely, the observation
space is required to contain at least three elements, namely `observation`, `desired_goal`, and
`achieved_goal`. Here, `desired_goal` specifies the goal that the agent should attempt to achieve.
`achieved_goal` is the goal that it currently achieved instead. `observation` contains the
actual observations of the environment as per usual.
"""
def reset(self):
# Enforce that each GoalEnv uses a Goal-compatible observation space.
if not isinstance(self.observation_space, gym.spaces.Dict):
raise error.Error('GoalEnv requires an observation space of type gym.spaces.Dict')
result = super(GoalEnv, self).reset()
for key in ['observation', 'achieved_goal', 'desired_goal']:
if key not in result:
raise error.Error('GoalEnv requires the "{}" key to be part of the observation dictionary.'.format(key))
return result
def compute_reward(self, achieved_goal, desired_goal, info):
"""Compute the step reward. This externalizes the reward function and makes
it dependent on an a desired goal and the one that was achieved. If you wish to include
additional rewards that are independent of the goal, you can include the necessary values
to derive it in info and compute it accordingly.
Args:
achieved_goal (object): the goal that was achieved during execution
desired_goal (object): the desired goal that we asked the agent to attempt to achieve
info (dict): an info dictionary with additional information
Returns:
float: The reward that corresponds to the provided achieved goal w.r.t. to the desired
goal. Note that the following should always hold true:
ob, reward, done, info = env.step()
assert reward == env.compute_reward(ob['achieved_goal'], ob['goal'], info)
"""
raise NotImplementedError()
# Space-related abstractions
class Space(object):
@@ -249,6 +290,9 @@ class Wrapper(Env):
def seed(self, seed=None):
return self.env.seed(seed)
def compute_reward(self, achieved_goal, desired_goal, info):
return self.env.compute_reward(achieved_goal, desired_goal, info)
def __str__(self):
return '<{}{}>'.format(type(self).__name__, self.env)

View File

@@ -291,6 +291,136 @@ register(
max_episode_steps=1000,
)
# Robotics
# ----------------------------------------
def _merge(a, b):
a.update(b)
return a
for reward_type in ['sparse', 'dense']:
suffix = 'Dense' if reward_type == 'dense' else ''
kwargs = {
'reward_type': reward_type,
}
# Fetch
register(
id='FetchSlide{}-v0'.format(suffix),
entry_point='gym.envs.robotics:FetchSlideEnv',
kwargs=kwargs,
max_episode_steps=50,
)
register(
id='FetchPickAndPlace{}-v0'.format(suffix),
entry_point='gym.envs.robotics:FetchPickAndPlaceEnv',
kwargs=kwargs,
max_episode_steps=50,
)
register(
id='FetchReach{}-v0'.format(suffix),
entry_point='gym.envs.robotics:FetchReachEnv',
kwargs=kwargs,
max_episode_steps=50,
)
register(
id='FetchPush{}-v0'.format(suffix),
entry_point='gym.envs.robotics:FetchPushEnv',
kwargs=kwargs,
max_episode_steps=50,
)
# Hand
register(
id='HandReach{}-v0'.format(suffix),
entry_point='gym.envs.robotics:HandReachEnv',
kwargs=kwargs,
max_episode_steps=50,
)
register(
id='HandManipulateBlockRotateZ{}-v0'.format(suffix),
entry_point='gym.envs.robotics:HandBlockEnv',
kwargs=_merge({'target_position': 'ignore', 'target_rotation': 'z'}, kwargs),
max_episode_steps=100,
)
register(
id='HandManipulateBlockRotateParallel{}-v0'.format(suffix),
entry_point='gym.envs.robotics:HandBlockEnv',
kwargs=_merge({'target_position': 'ignore', 'target_rotation': 'parallel'}, kwargs),
max_episode_steps=100,
)
register(
id='HandManipulateBlockRotateXYZ{}-v0'.format(suffix),
entry_point='gym.envs.robotics:HandBlockEnv',
kwargs=_merge({'target_position': 'ignore', 'target_rotation': 'xyz'}, kwargs),
max_episode_steps=100,
)
register(
id='HandManipulateBlockFull{}-v0'.format(suffix),
entry_point='gym.envs.robotics:HandBlockEnv',
kwargs=_merge({'target_position': 'random', 'target_rotation': 'xyz'}, kwargs),
max_episode_steps=100,
)
# Alias for "Full"
register(
id='HandManipulateBlock{}-v0'.format(suffix),
entry_point='gym.envs.robotics:HandBlockEnv',
kwargs=_merge({'target_position': 'random', 'target_rotation': 'xyz'}, kwargs),
max_episode_steps=100,
)
register(
id='HandManipulateEggRotate{}-v0'.format(suffix),
entry_point='gym.envs.robotics:HandEggEnv',
kwargs=_merge({'target_position': 'ignore', 'target_rotation': 'xyz'}, kwargs),
max_episode_steps=100,
)
register(
id='HandManipulateEggFull{}-v0'.format(suffix),
entry_point='gym.envs.robotics:HandEggEnv',
kwargs=_merge({'target_position': 'random', 'target_rotation': 'xyz'}, kwargs),
max_episode_steps=100,
)
# Alias for "Full"
register(
id='HandManipulateEgg{}-v0'.format(suffix),
entry_point='gym.envs.robotics:HandEggEnv',
kwargs=_merge({'target_position': 'random', 'target_rotation': 'xyz'}, kwargs),
max_episode_steps=100,
)
register(
id='HandManipulatePenRotate{}-v0'.format(suffix),
entry_point='gym.envs.robotics:HandPenEnv',
kwargs=_merge({'target_position': 'ignore', 'target_rotation': 'xyz'}, kwargs),
max_episode_steps=100,
)
register(
id='HandManipulatePenFull{}-v0'.format(suffix),
entry_point='gym.envs.robotics:HandPenEnv',
kwargs=_merge({'target_position': 'random', 'target_rotation': 'xyz'}, kwargs),
max_episode_steps=100,
)
# Alias for "Full"
register(
id='HandManipulatePen{}-v0'.format(suffix),
entry_point='gym.envs.robotics:HandPenEnv',
kwargs=_merge({'target_position': 'random', 'target_rotation': 'xyz'}, kwargs),
max_episode_steps=100,
)
# Atari
# ----------------------------------------

View File

@@ -39,5 +39,5 @@ class InvertedDoublePendulumEnv(mujoco_env.MujocoEnv, utils.EzPickle):
def viewer_setup(self):
v = self.viewer
v.cam.trackbodyid = 0
v.cam.distance = v.model.stat.extent * 0.5
v.cam.lookat[2] += 3 # v.model.stat.center[2]
v.cam.distance = self.model.stat.extent * 0.5
v.cam.lookat[2] = 0.12250000000000005 # v.model.stat.center[2]

View File

@@ -27,4 +27,4 @@ class InvertedPendulumEnv(mujoco_env.MujocoEnv, utils.EzPickle):
def viewer_setup(self):
v = self.viewer
v.cam.trackbodyid = 0
v.cam.distance = v.model.stat.extent
v.cam.distance = self.model.stat.extent

View File

@@ -0,0 +1,10 @@
from gym.envs.robotics.fetch_env import FetchEnv
from gym.envs.robotics.fetch.slide import FetchSlideEnv
from gym.envs.robotics.fetch.pick_and_place import FetchPickAndPlaceEnv
from gym.envs.robotics.fetch.push import FetchPushEnv
from gym.envs.robotics.fetch.reach import FetchReachEnv
from gym.envs.robotics.hand.reach import HandReachEnv
from gym.envs.robotics.hand.manipulate import HandBlockEnv
from gym.envs.robotics.hand.manipulate import HandEggEnv
from gym.envs.robotics.hand.manipulate import HandPenEnv

View File

@@ -0,0 +1,12 @@
This work contains code used under the following license:
# ShadowHand
The model of the [ShadowHand](https://www.shadowrobot.com/products/dexterous-hand/) is based on [models
provided by Shadow](https://github.com/shadow-robot/sr_common/tree/kinetic-devel/sr_description/hand/model).
It was adapted and refined by Vikash Kumar and OpenAI.
(C) Vikash Kumar, CSE, UW. Licensed under Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0. Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
# Fetch Robotics
The model of the [Fetch](http://fetchrobotics.com/platforms-research-development/) is based on [models provided by Fetch](https://github.com/fetchrobotics/fetch_ros/tree/indigo-devel/fetch_description).
It was adapted and refined by OpenAI.

View File

@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<mujoco>
<compiler angle="radian" coordinate="local" meshdir="../stls/fetch" texturedir="../textures"></compiler>
<option timestep="0.002">
<flag warmstart="enable"></flag>
</option>
<include file="shared.xml"></include>
<worldbody>
<geom name="floor0" pos="0.8 0.75 0" size="0.85 0.7 1" type="plane" condim="3" material="floor_mat"></geom>
<body name="floor0" pos="0.8 0.75 0">
<site name="target0" pos="0 0 0.5" size="0.02 0.02 0.02" rgba="1 0 0 1" type="sphere"></site>
</body>
<include file="robot.xml"></include>
<body pos="0.25 0.35 0.2" name="table0">
<geom size="0.25 0.35 0.2" type="box" mass="2000" material="table_mat"></geom>
<joint name="table0:slide0" type="slide" axis="1 0 0" damping="10000" pos="0 0 0"></joint>
<joint name="table0:slide1" type="slide" axis="0 1 0" damping="10000" pos="0 0 0"></joint>
<joint name="table0:slide2" type="slide" axis="0 0 1" damping="10000" pos="0 0 0"></joint>
</body>
<body name="object0" pos="0.025 0.025 0.025">
<joint name="object0:joint" type="free" damping="0.01"></joint>
<geom size="0.025 0.025 0.025" type="box" condim="3" name="object0" material="block_mat" mass="2"></geom>
<site name="object0" pos="0 0 0" size="0.02 0.02 0.02" rgba="1 0 0 1" type="sphere"></site>
</body>
<light directional="true" ambient="0.2 0.2 0.2" diffuse="0.8 0.8 0.8" specular="0.3 0.3 0.3" castshadow="false" pos="0 0 4" dir="0 0 -1" name="light0"></light>
</worldbody>
<actuator>
<position ctrllimited="true" ctrlrange="0 0.2" joint="robot0:l_gripper_finger_joint" kp="30000" name="robot0:l_gripper_finger_joint" user="1"></position>
<position ctrllimited="true" ctrlrange="0 0.2" joint="robot0:r_gripper_finger_joint" kp="30000" name="robot0:r_gripper_finger_joint" user="1"></position>
</actuator>
</mujoco>

View File

@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<mujoco>
<compiler angle="radian" coordinate="local" meshdir="../stls/fetch" texturedir="../textures"></compiler>
<option timestep="0.002">
<flag warmstart="enable"></flag>
</option>
<include file="shared.xml"></include>
<worldbody>
<geom name="floor0" pos="0.8 0.75 0" size="0.85 0.70 1" type="plane" condim="3" material="floor_mat"></geom>
<body name="floor0" pos="0.8 0.75 0">
<site name="target0" pos="0 0 0.5" size="0.02 0.02 0.02" rgba="1 0 0 1" type="sphere"></site>
</body>
<include file="robot.xml"></include>
<body pos="0.25 0.35 0.2" name="table0">
<geom size="0.25 0.35 0.2" type="box" mass="2000" material="table_mat"></geom>
<joint name="table0:slide0" type="slide" axis="1 0 0" damping="10000" pos="0 0 0"></joint>
<joint name="table0:slide1" type="slide" axis="0 1 0" damping="10000" pos="0 0 0"></joint>
<joint name="table0:slide2" type="slide" axis="0 0 1" damping="10000" pos="0 0 0"></joint>
</body>
<body name="object0" pos="0.025 0.025 0.025">
<joint name="object0:joint" type="free" damping="0.01"></joint>
<geom size="0.025 0.025 0.025" type="box" condim="3" name="object0" material="block_mat" mass="2"></geom>
<site name="object0" pos="0 0 0" size="0.02 0.02 0.02" rgba="1 0 0 1" type="sphere"></site>
</body>
<light directional="true" ambient="0.2 0.2 0.2" diffuse="0.8 0.8 0.8" specular="0.3 0.3 0.3" castshadow="false" pos="0 0 4" dir="0 0 -1" name="light0"></light>
</worldbody>
<actuator></actuator>
</mujoco>

View File

@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<mujoco>
<compiler angle="radian" coordinate="local" meshdir="../stls/fetch" texturedir="../textures"></compiler>
<option timestep="0.002">
<flag warmstart="enable"></flag>
</option>
<include file="shared.xml"></include>
<worldbody>
<geom name="floor0" pos="0.8 0.75 0" size="0.85 0.7 1" type="plane" condim="3" material="floor_mat"></geom>
<body name="floor0" pos="0.8 0.75 0">
<site name="target0" pos="0 0 0.5" size="0.02 0.02 0.02" rgba="1 0 0 1" type="sphere"></site>
</body>
<include file="robot.xml"></include>
<body pos="0.25 0.35 0.2" name="table0">
<geom size="0.25 0.35 0.2" type="box" mass="2000" rgba="1.5 1.5 1.5 1" material="table_mat"></geom>
<joint name="table0:slide0" type="slide" axis="1 0 0" damping="10000" pos="0 0 0"></joint>
<joint name="table0:slide1" type="slide" axis="0 1 0" damping="10000" pos="0 0 0"></joint>
<joint name="table0:slide2" type="slide" axis="0 0 1" damping="10000" pos="0 0 0"></joint>
</body>
<light directional="true" ambient="0.2 0.2 0.2" diffuse="0.8 0.8 0.8" specular="0.3 0.3 0.3" castshadow="false" pos="0 0 4" dir="0 0 -1" name="light0"></light>
</worldbody>
<actuator></actuator>
</mujoco>

View File

@@ -0,0 +1,123 @@
<mujoco>
<body mocap="true" name="robot0:mocap" pos="0 0 0">
<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>
<geom conaffinity="0" contype="0" pos="0 0 0" rgba="0 0.5 0 0.1" size="1 0.005 0.005" type="box"></geom>
<geom conaffinity="0" contype="0" pos="0 0 0" rgba="0 0.5 0 0.1" size="0.005 1 0.001" type="box"></geom>
<geom conaffinity="0" contype="0" pos="0 0 0" rgba="0 0.5 0 0.1" size="0.005 0.005 1" type="box"></geom>
</body>
<body childclass="robot0:fetch" name="robot0:base_link" pos="0.2869 0.2641 0">
<joint armature="0.0001" axis="1 0 0" damping="1e+11" name="robot0:slide0" pos="0 0 0" type="slide"></joint>
<joint armature="0.0001" axis="0 1 0" damping="1e+11" name="robot0:slide1" pos="0 0 0" type="slide"></joint>
<joint armature="0.0001" axis="0 0 1" damping="1e+11" name="robot0:slide2" pos="0 0 0" type="slide"></joint>
<inertial diaginertia="1.2869 1.2236 0.9868" mass="70.1294" pos="-0.0036 0 0.0014" quat="0.7605 -0.0133 -0.0061 0.6491"></inertial>
<geom mesh="robot0:base_link" name="robot0:base_link" material="robot0:base_mat" class="robot0:grey"></geom>
<body name="robot0:torso_lift_link" pos="-0.0869 0 0.3774">
<inertial diaginertia="0.3365 0.3354 0.0943" mass="10.7796" pos="-0.0013 -0.0009 0.2935" quat="0.9993 -0.0006 0.0336 0.0185"></inertial>
<joint axis="0 0 1" damping="1e+07" name="robot0:torso_lift_joint" range="0.0386 0.3861" type="slide"></joint>
<geom mesh="robot0:torso_lift_link" name="robot0:torso_lift_link" material="robot0:torso_mat"></geom>
<body name="robot0:head_pan_link" pos="0.0531 0 0.603">
<inertial diaginertia="0.0185 0.0128 0.0095" mass="2.2556" pos="0.0321 0.0161 0.039" quat="0.5148 0.5451 -0.453 0.4823"></inertial>
<joint axis="0 0 1" name="robot0:head_pan_joint" range="-1.57 1.57"></joint>
<geom mesh="robot0:head_pan_link" name="robot0:head_pan_link" material="robot0:head_mat" class="robot0:grey"></geom>
<body name="robot0:head_tilt_link" pos="0.1425 0 0.058">
<inertial diaginertia="0.0063 0.0059 0.0014" mass="0.9087" pos="0.0081 0.0025 0.0113" quat="0.6458 0.66 -0.274 0.2689"></inertial>
<joint axis="0 1 0" damping="1000" name="robot0:head_tilt_joint" range="-0.76 1.45" ref="0.06"></joint>
<geom mesh="robot0:head_tilt_link" name="robot0:head_tilt_link" material="robot0:head_mat" class="robot0:blue"></geom>
<body name="robot0:head_camera_link" pos="0.055 0 0.0225">
<inertial diaginertia="0 0 0" mass="0" pos="0.055 0 0.0225"></inertial>
<body name="robot0:head_camera_rgb_frame" pos="0 0.02 0">
<inertial diaginertia="0 0 0" mass="0" pos="0 0.02 0"></inertial>
<body name="robot0:head_camera_rgb_optical_frame" pos="0 0 0" quat="0.5 -0.5 0.5 -0.5">
<inertial diaginertia="0 0 0" mass="0" pos="0 0 0" quat="0.5 -0.5 0.5 -0.5"></inertial>
<camera euler="3.1415 0 0" fovy="50" name="head_camera_rgb" pos="0 0 0"></camera>
</body>
</body>
<body name="robot0:head_camera_depth_frame" pos="0 0.045 0">
<inertial diaginertia="0 0 0" mass="0" pos="0 0.045 0"></inertial>
<body name="robot0:head_camera_depth_optical_frame" pos="0 0 0" quat="0.5 -0.5 0.5 -0.5">
<inertial diaginertia="0 0 0" mass="0" pos="0 0 0" quat="0.5 -0.5 0.5 -0.5"></inertial>
</body>
</body>
</body>
</body>
</body>
<body name="robot0:shoulder_pan_link" pos="0.1195 0 0.3486">
<inertial diaginertia="0.009 0.0086 0.0041" mass="2.5587" pos="0.0927 -0.0056 0.0564" quat="-0.1364 0.7624 -0.1562 0.613"></inertial>
<joint axis="0 0 1" name="robot0:shoulder_pan_joint" range="-1.6056 1.6056"></joint>
<geom mesh="robot0:shoulder_pan_link" name="robot0:shoulder_pan_link" material="robot0:arm_mat"></geom>
<body name="robot0:shoulder_lift_link" pos="0.117 0 0.06">
<inertial diaginertia="0.0116 0.0112 0.0023" mass="2.6615" pos="0.1432 0.0072 -0.0001" quat="0.4382 0.4382 0.555 0.555"></inertial>
<joint axis="0 1 0" name="robot0:shoulder_lift_joint" range="-1.221 1.518"></joint>
<geom mesh="robot0:shoulder_lift_link" name="robot0:shoulder_lift_link" material="robot0:arm_mat" class="robot0:blue"></geom>
<body name="robot0:upperarm_roll_link" pos="0.219 0 0">
<inertial diaginertia="0.0047 0.0045 0.0019" mass="2.3311" pos="0.1165 0.0014 0" quat="-0.0136 0.707 0.0136 0.707"></inertial>
<joint axis="1 0 0" limited="false" name="robot0:upperarm_roll_joint"></joint>
<geom mesh="robot0:upperarm_roll_link" name="robot0:upperarm_roll_link" material="robot0:arm_mat"></geom>
<body name="robot0:elbow_flex_link" pos="0.133 0 0">
<inertial diaginertia="0.0086 0.0084 0.002" mass="2.1299" pos="0.1279 0.0073 0" quat="0.4332 0.4332 0.5589 0.5589"></inertial>
<joint axis="0 1 0" name="robot0:elbow_flex_joint" range="-2.251 2.251"></joint>
<geom mesh="robot0:elbow_flex_link" name="robot0:elbow_flex_link" material="robot0:arm_mat" class="robot0:blue"></geom>
<body name="robot0:forearm_roll_link" pos="0.197 0 0">
<inertial diaginertia="0.0035 0.0031 0.0015" mass="1.6563" pos="0.1097 -0.0266 0" quat="-0.0715 0.7035 0.0715 0.7035"></inertial>
<joint armature="2.7538" axis="1 0 0" damping="3.5247" frictionloss="0" limited="false" name="robot0:forearm_roll_joint" stiffness="10"></joint>
<geom mesh="robot0:forearm_roll_link" name="robot0:forearm_roll_link" material="robot0:arm_mat"></geom>
<body name="robot0:wrist_flex_link" pos="0.1245 0 0">
<inertial diaginertia="0.0042 0.0042 0.0018" mass="1.725" pos="0.0882 0.0009 -0.0001" quat="0.4895 0.4895 0.5103 0.5103"></inertial>
<joint axis="0 1 0" name="robot0:wrist_flex_joint" range="-2.16 2.16"></joint>
<geom mesh="robot0:wrist_flex_link" name="robot0:wrist_flex_link" material="robot0:arm_mat" class="robot0:blue"></geom>
<body name="robot0:wrist_roll_link" pos="0.1385 0 0">
<inertial diaginertia="0.0001 0.0001 0.0001" mass="0.1354" pos="0.0095 0.0004 -0.0002"></inertial>
<joint axis="1 0 0" limited="false" name="robot0:wrist_roll_joint"></joint>
<geom mesh="robot0:wrist_roll_link" name="robot0:wrist_roll_link" material="robot0:arm_mat"></geom>
<body euler="0 0 0" name="robot0:gripper_link" pos="0.1664 0 0">
<inertial diaginertia="0.0024 0.0019 0.0013" mass="1.5175" pos="-0.09 -0.0001 -0.0017" quat="0 0.7071 0 0.7071"></inertial>
<geom mesh="robot0:gripper_link" name="robot0:gripper_link" material="robot0:gripper_mat"></geom>
<body name="robot0:gipper_camera_link" pos="0.055 0 0.0225">
<body name="robot0:gripper_camera_rgb_frame" pos="0 0.02 0">
<body name="robot0:gripper_camera_rgb_optical_frame" pos="0 0 0" quat="0.5 -0.5 0.5 -0.5">
<camera euler="3.1415 0 0" fovy="50" name="gripper_camera_rgb" pos="0 0 0"></camera>
</body>
</body>
<body name="robot0:gripper_camera_depth_frame" pos="0 0.045 0">
<body name="robot0:gripper_camera_depth_optical_frame" pos="0 0 0" quat="0.5 -0.5 0.5 -0.5"></body>
</body>
</body>
<body childclass="robot0:fetchGripper" name="robot0:r_gripper_finger_link" pos="0 0.0159 0">
<inertial diaginertia="0.1 0.1 0.1" mass="4" pos="-0.01 0 0"></inertial>
<joint axis="0 1 0" name="robot0:r_gripper_finger_joint" range="0 0.05"></joint>
<geom pos="0 -0.008 0" size="0.0385 0.007 0.0135" type="box" name="robot0:r_gripper_finger_link" material="robot0:gripper_finger_mat" condim="4" friction="1 0.05 0.01"></geom>
</body>
<body childclass="robot0:fetchGripper" name="robot0:l_gripper_finger_link" pos="0 -0.0159 0">
<inertial diaginertia="0.1 0.1 0.1" mass="4" pos="-0.01 0 0"></inertial>
<joint axis="0 -1 0" name="robot0:l_gripper_finger_joint" range="0 0.05"></joint>
<geom pos="0 0.008 0" size="0.0385 0.007 0.0135" type="box" name="robot0:l_gripper_finger_link" material="robot0:gripper_finger_mat" condim="4" friction="1 0.05 0.01"></geom>
</body>
<site name="robot0:grip" pos="0.02 0 0" rgba="0 0 0 0" size="0.02 0.02 0.02"></site>
</body>
</body>
</body>
</body>
</body>
</body>
</body>
</body>
</body>
<body name="robot0:estop_link" pos="-0.1246 0.2389 0.3113" quat="0.7071 0.7071 0 0">
<inertial diaginertia="0 0 0" mass="0.002" pos="0.0024 -0.0033 0.0067" quat="0.3774 -0.1814 0.1375 0.8977"></inertial>
<geom mesh="robot0:estop_link" rgba="0.8 0 0 1" name="robot0:estop_link"></geom>
</body>
<body name="robot0:laser_link" pos="0.235 0 0.2878" quat="0 1 0 0">
<inertial diaginertia="0 0 0" mass="0.0083" pos="-0.0306 0.0007 0.0552" quat="0.5878 0.5378 -0.4578 0.3945"></inertial>
<geom mesh="robot0:laser_link" rgba="0.7922 0.8196 0.9333 1" name="robot0:laser_link"></geom>
<camera euler="1.55 -1.55 3.14" fovy="25" name="lidar" pos="0 0 0.02"></camera>
</body>
<body name="robot0:torso_fixed_link" pos="-0.0869 0 0.3774">
<inertial diaginertia="0.3865 0.3394 0.1009" mass="13.2775" pos="-0.0722 0.0057 0.2656" quat="0.9995 0.0249 0.0177 0.011"></inertial>
<geom mesh="robot0:torso_fixed_link" name="robot0:torso_fixed_link" class="robot0:blue"></geom>
</body>
<body name="robot0:external_camera_body_0" pos="0 0 0">
<camera euler="0 0.75 1.57" fovy="43.3" name="external_camera_0" pos="1.3 0 1.2"></camera>
</body>
</body>
</mujoco>

View File

@@ -0,0 +1,66 @@
<mujoco>
<asset>
<texture type="skybox" builtin="gradient" rgb1="0.44 0.85 0.56" rgb2="0.46 0.87 0.58" width="32" height="32"></texture>
<texture name="texture_block" file="block.png" gridsize="3 4" gridlayout=".U..LFRB.D.."></texture>
<material name="floor_mat" specular="0" shininess="0.5" reflectance="0" rgba="0.2 0.2 0.2 1"></material>
<material name="table_mat" specular="0" shininess="0.5" reflectance="0" rgba="0.93 0.93 0.93 1"></material>
<material name="block_mat" specular="0" shininess="0.5" reflectance="0" rgba="0.2 0.2 0.2 1"></material>
<material name="puck_mat" specular="0" shininess="0.5" reflectance="0" rgba="0.2 0.2 0.2 1"></material>
<material name="robot0:geomMat" shininess="0.03" specular="0.4"></material>
<material name="robot0:gripper_finger_mat" shininess="0.03" specular="0.4" reflectance="0"></material>
<material name="robot0:gripper_mat" shininess="0.03" specular="0.4" reflectance="0"></material>
<material name="robot0:arm_mat" shininess="0.03" specular="0.4" reflectance="0"></material>
<material name="robot0:head_mat" shininess="0.03" specular="0.4" reflectance="0"></material>
<material name="robot0:torso_mat" shininess="0.03" specular="0.4" reflectance="0"></material>
<material name="robot0:base_mat" shininess="0.03" specular="0.4" reflectance="0"></material>
<mesh file="base_link_collision.stl" name="robot0:base_link"></mesh>
<mesh file="bellows_link_collision.stl" name="robot0:bellows_link"></mesh>
<mesh file="elbow_flex_link_collision.stl" name="robot0:elbow_flex_link"></mesh>
<mesh file="estop_link.stl" name="robot0:estop_link"></mesh>
<mesh file="forearm_roll_link_collision.stl" name="robot0:forearm_roll_link"></mesh>
<mesh file="gripper_link.stl" name="robot0:gripper_link"></mesh>
<mesh file="head_pan_link_collision.stl" name="robot0:head_pan_link"></mesh>
<mesh file="head_tilt_link_collision.stl" name="robot0:head_tilt_link"></mesh>
<mesh file="l_wheel_link_collision.stl" name="robot0:l_wheel_link"></mesh>
<mesh file="laser_link.stl" name="robot0:laser_link"></mesh>
<mesh file="r_wheel_link_collision.stl" name="robot0:r_wheel_link"></mesh>
<mesh file="torso_lift_link_collision.stl" name="robot0:torso_lift_link"></mesh>
<mesh file="shoulder_pan_link_collision.stl" name="robot0:shoulder_pan_link"></mesh>
<mesh file="shoulder_lift_link_collision.stl" name="robot0:shoulder_lift_link"></mesh>
<mesh file="upperarm_roll_link_collision.stl" name="robot0:upperarm_roll_link"></mesh>
<mesh file="wrist_flex_link_collision.stl" name="robot0:wrist_flex_link"></mesh>
<mesh file="wrist_roll_link_collision.stl" name="robot0:wrist_roll_link"></mesh>
<mesh file="torso_fixed_link.stl" name="robot0:torso_fixed_link"></mesh>
</asset>
<equality>
<weld body1="robot0:mocap" body2="robot0:gripper_link" solimp="0.9 0.95 0.001" solref="0.02 1"></weld>
</equality>
<contact>
<exclude body1="robot0:r_gripper_finger_link" body2="robot0:l_gripper_finger_link"></exclude>
<exclude body1="robot0:torso_lift_link" body2="robot0:torso_fixed_link"></exclude>
<exclude body1="robot0:torso_lift_link" body2="robot0:shoulder_pan_link"></exclude>
</contact>
<default>
<default class="robot0:fetch">
<geom margin="0.001" material="robot0:geomMat" rgba="1 1 1 1" solimp="0.99 0.99 0.01" solref="0.01 1" type="mesh" user="0"></geom>
<joint armature="1" damping="50" frictionloss="0" stiffness="0"></joint>
<default class="robot0:fetchGripper">
<geom condim="4" margin="0.001" type="box" user="0" rgba="0.356 0.361 0.376 1.0"></geom>
<joint armature="100" damping="1000" limited="true" solimplimit="0.99 0.999 0.01" solreflimit="0.01 1" type="slide"></joint>
</default>
<default class="robot0:grey">
<geom rgba="0.356 0.361 0.376 1.0"></geom>
</default>
<default class="robot0:blue">
<geom rgba="0.086 0.506 0.767 1.0"></geom>
</default>
</default>
</default>
</mujoco>

View File

@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<mujoco>
<compiler angle="radian" coordinate="local" meshdir="../stls/fetch" texturedir="../textures"></compiler>
<option timestep="0.002">
<flag warmstart="enable"></flag>
</option>
<include file="shared.xml"></include>
<worldbody>
<geom name="floor0" pos="1 0.75 0" size="1.05 0.7 1" type="plane" condim="3" material="floor_mat"></geom>
<body name="floor0" pos="1 0.75 0">
<site name="target0" pos="0 0 0.5" size="0.02 0.02 0.02" rgba="1 0 0 1" type="sphere"></site>
</body>
<include file="robot.xml"></include>
<body name="table0" pos="0.625 0.45 0.2">
<joint name="table0:slide0" axis="1 0 0" type="slide" damping="0.5" pos="0 0 0"></joint>
<joint name="table0:slide1" axis="0 1 0" type="slide" damping="0.5" pos="0 0 0"></joint>
<joint name="table0:slide2" axis="0 0 1" type="slide" damping="0.5" pos="0 0 0"></joint>
<geom size="0.625 0.45 0.2" type="box" condim="3" name="table0" material="table_mat" mass="2000" friction="0.1 0.005 0.0001"></geom>
</body>
<body name="object0" pos="0.025 0.025 0.02">
<joint name="object0:joint" type="free" damping="0.01"></joint>
<geom size="0.025 0.02" type="cylinder" condim="3" name="object0" material="puck_mat" friction="0.1 0.005 0.0001" mass="2"></geom>
<site name="object0" pos="0 0 0" size="0.02 0.02 0.02" rgba="1 0 0 1" type="sphere"></site>
</body>
<light directional="true" ambient="0.2 0.2 0.2" diffuse="0.8 0.8 0.8" specular="0.3 0.3 0.3" castshadow="false" pos="0 0 4" dir="0 0 -1" name="light0"></light>
</worldbody>
<actuator></actuator>
</mujoco>

View File

@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<mujoco>
<compiler angle="radian" coordinate="local" meshdir="../stls/hand" texturedir="../textures"></compiler>
<option timestep="0.002" iterations="20" apirate="200">
<flag warmstart="enable"></flag>
</option>
<include file="shared.xml"></include>
<asset>
<include file="shared_asset.xml"></include>
<texture name="texture:object" file="block.png" gridsize="3 4" gridlayout=".U..LFRB.D.."></texture>
<texture name="texture:hidden" file="block_hidden.png" gridsize="3 4" gridlayout=".U..LFRB.D.."></texture>
<material name="material:object" texture="texture:object" specular="1" shininess="0.3" reflectance="0"></material>
<material name="material:hidden" texture="texture:hidden" specular="1" shininess="0.3" reflectance="0"></material>
<material name="material:target" texture="texture:object" specular="1" shininess="0.3" reflectance="0" rgba="1 1 1 0.5"></material>
</asset>
<worldbody>
<geom name="floor0" pos="1 1 0" size="1 1 1" type="plane" condim="3" material="floor_mat"></geom>
<body name="floor0" pos="1 1 0"></body>
<include file="robot.xml"></include>
<body name="object" pos="1 0.87 0.2">
<geom name="object" type="box" size="0.025 0.025 0.025" material="material:object" condim="4" density="567"></geom>
<geom name="object_hidden" type="box" size="0.024 0.024 0.024" material="material:hidden" condim="4" contype="0" conaffinity="0" mass="0"></geom>
<site name="object:center" pos="0 0 0" rgba="1 0 0 0" size="0.01 0.01 0.01"></site>
<joint name="object:joint" type="free" damping="0.01"></joint>
</body>
<body name="target" pos="1 0.87 0.2">
<geom name="target" type="box" size="0.025 0.025 0.025" material="material:target" condim="4" group="2" contype="0" conaffinity="0"></geom>
<site name="target:center" pos="0 0 0" rgba="1 0 0 0" size="0.01 0.01 0.01"></site>
<joint name="target:joint" type="free" damping="0.01"></joint>
</body>
<light directional="true" ambient="0.2 0.2 0.2" diffuse="0.8 0.8 0.8" specular="0.3 0.3 0.3" castshadow="false" pos="0 1 4" dir="0 0 -1" name="light0"></light>
</worldbody>
</mujoco>

View File

@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<mujoco>
<compiler angle="radian" coordinate="local" meshdir="../stls/hand" texturedir="../textures"></compiler>
<option timestep="0.002" iterations="20" apirate="200">
<flag warmstart="enable"></flag>
</option>
<include file="shared.xml"></include>
<asset>
<include file="shared_asset.xml"></include>
<texture name="texture:object" file="block.png" gridsize="3 4" gridlayout=".U..LFRB.D.."></texture>
<texture name="texture:hidden" file="block_hidden.png" gridsize="3 4" gridlayout=".U..LFRB.D.."></texture>
<material name="material:object" texture="texture:object" specular="1" shininess="0.3" reflectance="0"></material>
<material name="material:hidden" texture="texture:hidden" specular="1" shininess="0.3" reflectance="0"></material>
<material name="material:target" texture="texture:object" specular="1" shininess="0.3" reflectance="0" rgba="1 1 1 0.5"></material>
</asset>
<worldbody>
<geom name="floor0" pos="1 1 0" size="1 1 1" type="plane" condim="3" material="floor_mat"></geom>
<body name="floor0" pos="1 1 0"></body>
<include file="robot.xml"></include>
<body name="object" pos="1 0.87 0.2">
<geom name="object" type="ellipsoid" size="0.03 0.03 0.04" material="material:object" condim="4"></geom>
<geom name="object_hidden" type="ellipsoid" size="0.029 0.029 0.03" material="material:hidden" condim="4" contype="0" conaffinity="0" mass="0"></geom>
<site name="object:center" pos="0 0 0" rgba="1 0 0 0" size="0.01 0.01 0.01"></site>
<joint name="object:joint" type="free" damping="0.01"></joint>
</body>
<body name="target" pos="1 0.87 0.2">
<geom name="target" type="ellipsoid" size="0.03 0.03 0.04" material="material:target" condim="4" group="2" contype="0" conaffinity="0"></geom>
<site name="target:center" pos="0 0 0" rgba="1 0 0 0" size="0.01 0.01 0.01"></site>
<joint name="target:joint" type="free" damping="0.01"></joint>
</body>
<light directional="true" ambient="0.2 0.2 0.2" diffuse="0.8 0.8 0.8" specular="0.3 0.3 0.3" castshadow="false" pos="0 1 4" dir="0 0 -1" name="light0"></light>
</worldbody>
</mujoco>

View File

@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<mujoco>
<compiler angle="radian" coordinate="local" meshdir="../stls/hand" texturedir="../textures"></compiler>
<option timestep="0.002" iterations="20" apirate="200">
<flag warmstart="enable"></flag>
</option>
<include file="shared.xml"></include>
<asset>
<include file="shared_asset.xml"></include>
<material name="material:object" specular="0" shininess="0.5" reflectance="0.0" rgba="0.46 0.81 0.88 1.0"></material>
<material name="material:target" specular="0" shininess="0.5" reflectance="0.0" rgba="0.46 0.81 0.88 0.5"></material>
</asset>
<worldbody>
<geom name="floor0" pos="1 1 -0.2" size="1 1 1" type="plane" condim="3" material="floor_mat"></geom>
<body name="floor0" pos="1 1 0"></body>
<include file="robot.xml"></include>
<body name="object" pos="1 0.87 0.2" euler="-1 1 0">
<geom name="object" type="capsule" size="0.008 0.1" material="material:object" condim="4"></geom>
<site name="object:center" pos="0 0 0" rgba="1 0 0 0" size="0.01 0.01 0.01"></site>
<site name="object:top" pos="0 0 0.1" rgba="1 0 0 1" size="0.0081"></site>
<site name="object:bottom" pos="0 0 -0.1" rgba="0 1 0 1" size="0.0081"></site>
<joint name="object:joint" type="free" damping="0.01"></joint>
</body>
<body name="target" pos="1 0.87 0.2" euler="-1 1 0">
<geom name="target" type="capsule" size="0.008 0.1" material="material:target" condim="4" group="2" contype="0" conaffinity="0"></geom>
<site name="target:center" pos="0 0 0" rgba="1 0 0 0" size="0.01 0.01 0.01"></site>
<site name="target:top" pos="0 0 0.1" rgba="1 0 0 0.5" size="0.0081"></site>
<site name="target:bottom" pos="0 0 -0.1" rgba="0 1 0 0.5" size="0.0081"></site>
<joint name="target:joint" type="free" damping="0.01"></joint>
</body>
<light directional="true" ambient="0.2 0.2 0.2" diffuse="0.8 0.8 0.8" specular="0.3 0.3 0.3" castshadow="false" pos="0 1 4" dir="0 0 -1" name="light0"></light>
</worldbody>
</mujoco>

View File

@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<mujoco>
<compiler angle="radian" coordinate="local" meshdir="../stls/hand" texturedir="../textures"></compiler>
<option timestep="0.002" iterations="20" apirate="200">
<flag warmstart="enable"></flag>
</option>
<include file="shared.xml"></include>
<asset>
<include file="shared_asset.xml"></include>
</asset>
<worldbody>
<geom name="floor0" pos="1 1 0" size="1 1 1" type="plane" condim="3" material="floor_mat"></geom>
<body name="floor0" pos="1 1 0">
<site name="target0" pos="0 0 0" size="0.005" rgba="1 0 0 1" type="sphere"></site>
<site name="target1" pos="0 0 0" size="0.005" rgba="0 1 0 1" type="sphere"></site>
<site name="target2" pos="0 0 0" size="0.005" rgba="0 0 1 1" type="sphere"></site>
<site name="target3" pos="0 0 0" size="0.005" rgba="1 1 0 1" type="sphere"></site>
<site name="target4" pos="0 0 0" size="0.005" rgba="1 0 1 1" type="sphere"></site>
<site name="finger0" pos="0 0 0" size="0.01" rgba="1 0 0 0.2" type="sphere"></site>
<site name="finger1" pos="0 0 0" size="0.01" rgba="0 1 0 0.2" type="sphere"></site>
<site name="finger2" pos="0 0 0" size="0.01" rgba="0 0 1 0.2" type="sphere"></site>
<site name="finger3" pos="0 0 0" size="0.01" rgba="1 1 0 0.2" type="sphere"></site>
<site name="finger4" pos="0 0 0" size="0.01" rgba="1 0 1 0.2" type="sphere"></site>
</body>
<include file="robot.xml"></include>
<light directional="true" ambient="0.2 0.2 0.2" diffuse="0.8 0.8 0.8" specular="0.3 0.3 0.3" castshadow="false" pos="0 0 4" dir="0 0 -1" name="light0"></light>
</worldbody>
</mujoco>

View File

@@ -0,0 +1,159 @@
<mujoco>
<body name="robot0:hand mount" pos="1 1.25 0.15" euler="1.5708 0 3.14159">
<inertial mass="0.1" pos="0 0 0" diaginertia="0.001 0.001 0.001"></inertial>
<body childclass="robot0:asset_class" name="robot0:forearm" pos="0 0.01 0" euler="0 0 0">
<inertial pos="0.001 -0.002 0.29" quat="0.982 -0.016 0 -0.188" mass="4" diaginertia="0.01 0.01 0.0075"></inertial>
<geom class="robot0:D_Vizual" pos="0 0.01 0.04" name="robot0:V_forearm" mesh="robot0:forearm" euler="0 0 1.57"></geom>
<geom class="robot0:DC_Hand" name="robot0:C_forearm" type="mesh" mesh="robot0:forearm_cvx" pos="0 0.01 0.04" euler="0 0 1.57" rgba="0.4 0.5 0.6 0.7"></geom>
<body name="robot0:wrist" pos="0 0 0.256">
<inertial pos="0.003 0 0.016" quat="0.504 0.496 0.495 0.504" mass="0.3" diaginertia="0.001 0.001 0.001"></inertial>
<joint name="robot0:WRJ1" type="hinge" pos="0 0 0" axis="0 1 0" range="-0.489 0.14" damping="0.5" armature="0.005" user="1123"></joint>
<geom class="robot0:D_Vizual" name="robot0:V_wrist" mesh="robot0:wrist"></geom>
<geom class="robot0:DC_Hand" name="robot0:C_wrist" type="capsule" pos="0 0 0" quat="0.707 0.707 0 0" size="0.015 0.01" rgba="0.4 0.5 0.6 0.1"></geom>
<body name="robot0:palm" pos="0 0 0.034">
<inertial pos="0.006 0 0.036" quat="0.716 0.044 0.075 0.693" mass="0.3" diaginertia="0.001 0.001 0.001"></inertial>
<joint name="robot0:WRJ0" type="hinge" pos="0 0 0" axis="1 0 0" range="-0.698 0.489" damping="0.5" armature="0.005" user="1122"></joint>
<geom class="robot0:D_Vizual" name="robot0:V_palm" mesh="robot0:palm"></geom>
<geom class="robot0:DC_Hand" name="robot0:C_palm0" type="box" pos="0.011 0 0.038" size="0.032 0.0111 0.049" rgba="0.4 0.5 0.6 0.1"></geom>
<geom class="robot0:DC_Hand" name="robot0:C_palm1" type="box" pos="-0.032 0 0.014" size="0.011 0.0111 0.025" rgba="0.4 0.5 0.6 0.1"></geom>
<body name="robot0:ffknuckle" pos="0.033 0 0.095">
<inertial pos="0 0 0" quat="0.52 0.854 0.006 -0.003" mass="0.008" diaginertia="1e-05 1e-05 1e-05"></inertial>
<joint name="robot0:FFJ3" type="hinge" pos="0 0 0" axis="0 1 0" range="-0.349 0.349" user="1103"></joint>
<geom class="robot0:D_Vizual" name="robot0:V_ffknuckle" mesh="robot0:knuckle"></geom>
<body name="robot0:ffproximal" pos="0 0 0">
<inertial pos="0 0 0.023" quat="0.707 -0.004 0.004 0.707" mass="0.014" diaginertia="1e-05 1e-05 1e-05"></inertial>
<joint name="robot0:FFJ2" type="hinge" pos="0 0 0" axis="1 0 0" range="0 1.571" user="1102"></joint>
<geom class="robot0:D_Vizual" name="robot0:V_ffproximal" mesh="robot0:F3"></geom>
<geom class="robot0:DC_Hand" name="robot0:C_ffproximal" type="capsule" pos="0 0 0.0225" size="0.01 0.0225"></geom>
<body name="robot0:ffmiddle" pos="0 0 0.045">
<inertial pos="0 0 0.011" quat="0.707 0 0 0.707" mass="0.012" diaginertia="1e-05 1e-05 1e-05"></inertial>
<joint name="robot0:FFJ1" type="hinge" pos="0 0 0" axis="1 0 0" range="0 1.571" user="1101"></joint>
<geom class="robot0:D_Vizual" name="robot0:V_ffmiddle" mesh="robot0:F2"></geom>
<geom class="robot0:DC_Hand" name="robot0:C_ffmiddle" type="capsule" pos="0 0 0.0125" size="0.00805 0.0125"></geom>
<body name="robot0:ffdistal" pos="0 0 0.025">
<inertial pos="0 0 0.015" quat="0.707 -0.003 0.003 0.707" mass="0.01" diaginertia="1e-05 1e-05 1e-05"></inertial>
<joint name="robot0:FFJ0" type="hinge" pos="0 0 0" axis="1 0 0" range="0 1.571" user="1100"></joint>
<geom class="robot0:D_Vizual" name="robot0:V_ffdistal" pos="0 0 0.001" mesh="robot0:F1"></geom>
<geom class="robot0:DC_Hand" name="robot0:C_ffdistal" type="capsule" pos="0 0 0.012" size="0.00705 0.012" condim="4"></geom>
<site name="robot0:S_fftip" pos="0 0 0.026" group="3"></site>
<site class="robot0:D_Touch" name="robot0:Tch_fftip"></site>
</body>
</body>
</body>
</body>
<body name="robot0:mfknuckle" pos="0.011 0 0.099">
<inertial pos="0 0 0" quat="0.52 0.854 0.006 -0.003" mass="0.008" diaginertia="1e-05 1e-05 1e-05"></inertial>
<joint name="robot0:MFJ3" type="hinge" pos="0 0 0" axis="0 1 0" range="-0.349 0.349" user="1107"></joint>
<geom class="robot0:D_Vizual" name="robot0:V_mfknuckle" mesh="robot0:knuckle"></geom>
<body name="robot0:mfproximal" pos="0 0 0">
<inertial pos="0 0 0.023" quat="0.707 -0.004 0.004 0.707" mass="0.014" diaginertia="1e-05 1e-05 1e-05"></inertial>
<joint name="robot0:MFJ2" type="hinge" pos="0 0 0" axis="1 0 0" range="0 1.571" user="1106"></joint>
<geom class="robot0:D_Vizual" name="robot0:V_mfproximal" mesh="robot0:F3"></geom>
<geom class="robot0:DC_Hand" name="robot0:C_mfproximal" type="capsule" pos="0 0 0.0225" size="0.01 0.0225"></geom>
<body name="robot0:mfmiddle" pos="0 0 0.045">
<inertial pos="0 0 0.012" quat="0.707 0 0 0.707" mass="0.012" diaginertia="1e-05 1e-05 1e-05"></inertial>
<joint name="robot0:MFJ1" type="hinge" pos="0 0 0" axis="1 0 0" range="0 1.571" user="1105"></joint>
<geom class="robot0:D_Vizual" name="robot0:V_mfmiddle" mesh="robot0:F2"></geom>
<geom class="robot0:DC_Hand" name="robot0:C_mfmiddle" type="capsule" pos="0 0 0.0125" size="0.00805 0.0125"></geom>
<body name="robot0:mfdistal" pos="0 0 0.025">
<inertial pos="0 0 0.015" quat="0.707 -0.003 0.003 0.707" mass="0.01" diaginertia="1e-05 1e-05 1e-05"></inertial>
<joint name="robot0:MFJ0" type="hinge" pos="0 0 0" axis="1 0 0" range="0 1.571" user="1104"></joint>
<geom class="robot0:D_Vizual" name="robot0:V_mfdistal" mesh="robot0:F1"></geom>
<geom class="robot0:DC_Hand" name="robot0:C_mfdistal" type="capsule" pos="0 0 0.012" size="0.00705 0.012" condim="4"></geom>
<site name="robot0:S_mftip" pos="0 0 0.026" group="3"></site>
<site class="robot0:D_Touch" name="robot0:Tch_mftip"></site>
</body>
</body>
</body>
</body>
<body name="robot0:rfknuckle" pos="-0.011 0 0.095">
<inertial pos="0 0 0" quat="0.52 0.854 0.006 -0.003" mass="0.008" diaginertia="1e-05 1e-05 1e-05"></inertial>
<joint name="robot0:RFJ3" type="hinge" pos="0 0 0" axis="0 1 0" range="-0.349 0.349" user="1111"></joint>
<geom class="robot0:D_Vizual" name="robot0:V_rfknuckle" mesh="robot0:knuckle"></geom>
<body name="robot0:rfproximal" pos="0 0 0">
<inertial pos="0 0 0.023" quat="0.707 -0.004 0.004 0.707" mass="0.014" diaginertia="1e-05 1e-05 1e-05"></inertial>
<joint name="robot0:RFJ2" type="hinge" pos="0 0 0" axis="1 0 0" range="0 1.571" user="1110"></joint>
<geom class="robot0:D_Vizual" name="robot0:V_rfproximal" mesh="robot0:F3"></geom>
<geom class="robot0:DC_Hand" name="robot0:C_rfproximal" type="capsule" pos="0 0 0.0225" size="0.01 0.0225"></geom>
<body name="robot0:rfmiddle" pos="0 0 0.045">
<inertial pos="0 0 0.012" quat="0.707 0 0 0.707" mass="0.012" diaginertia="1e-05 1e-05 1e-05"></inertial>
<joint name="robot0:RFJ1" type="hinge" pos="0 0 0" axis="1 0 0" range="0 1.571" user="1109"></joint>
<geom class="robot0:D_Vizual" name="robot0:V_rfmiddle" mesh="robot0:F2"></geom>
<geom class="robot0:DC_Hand" name="robot0:C_rfmiddle" type="capsule" pos="0 0 0.0125" size="0.00805 0.0125"></geom>
<body name="robot0:rfdistal" pos="0 0 0.025">
<inertial pos="0 0 0.015" quat="0.707 -0.003 0.003 0.707" mass="0.01" diaginertia="1e-05 1e-05 1e-05"></inertial>
<joint name="robot0:RFJ0" type="hinge" pos="0 0 0" axis="1 0 0" range="0 1.571" user="1108"></joint>
<geom class="robot0:D_Vizual" name="robot0:V_rfdistal" mesh="robot0:F1" pos="0 0 0.001"></geom>
<geom class="robot0:DC_Hand" name="robot0:C_rfdistal" type="capsule" pos="0 0 0.012" size="0.00705 0.012" condim="4"></geom>
<site name="robot0:S_rftip" pos="0 0 0.026" group="3"></site>
<site class="robot0:D_Touch" name="robot0:Tch_rftip"></site>
</body>
</body>
</body>
</body>
<body name="robot0:lfmetacarpal" pos="-0.017 0 0.044">
<inertial pos="-0.014 0.001 0.014" quat="0.709 -0.092 -0.063 0.696" mass="0.075" diaginertia="1e-05 1e-05 1e-05"></inertial>
<joint name="robot0:LFJ4" type="hinge" pos="0 0 0" axis="0.571 0 0.821" range="0 0.785" user="1116"></joint>
<geom class="robot0:D_Vizual" name="robot0:V_lfmetacarpal" pos="-0.016 0 -0.023" mesh="robot0:lfmetacarpal"></geom>
<geom class="robot0:DC_Hand" name="robot0:C_lfmetacarpal" type="box" pos="-0.0165 0 0.01" size="0.0095 0.0111 0.025" rgba="0.4 0.5 0.6 0.2"></geom>
<body name="robot0:lfknuckle" pos="-0.017 0 0.044">
<inertial pos="0 0 0" quat="0.52 0.854 0.006 -0.003" mass="0.008" diaginertia="1e-05 1e-05 1e-05"></inertial>
<joint name="robot0:LFJ3" type="hinge" pos="0 0 0" axis="0 1 0" range="-0.349 0.349" user="1115"></joint>
<geom class="robot0:D_Vizual" name="robot0:V_lfknuckle" mesh="robot0:knuckle"></geom>
<body name="robot0:lfproximal" pos="0 0 0">
<inertial pos="0 0 0.023" quat="0.707 -0.004 0.004 0.707" mass="0.014" diaginertia="1e-05 1e-05 1e-05"></inertial>
<joint name="robot0:LFJ2" type="hinge" pos="0 0 0" axis="1 0 0" range="0 1.571" user="1114"></joint>
<geom class="robot0:D_Vizual" name="robot0:V_lfproximal" mesh="robot0:F3"></geom>
<geom class="robot0:DC_Hand" name="robot0:C_lfproximal" type="capsule" pos="0 0 0.0225" size="0.01 0.0225"></geom>
<body name="robot0:lfmiddle" pos="0 0 0.045">
<inertial pos="0 0 0.012" quat="0.707 0 0 0.707" mass="0.012" diaginertia="1e-05 1e-05 1e-05"></inertial>
<joint name="robot0:LFJ1" type="hinge" pos="0 0 0" axis="1 0 0" range="0 1.571" user="1113"></joint>
<geom class="robot0:D_Vizual" name="robot0:V_lfmiddle" mesh="robot0:F2"></geom>
<geom class="robot0:DC_Hand" name="robot0:C_lfmiddle" type="capsule" pos="0 0 0.0125" size="0.00805 0.0125"></geom>
<body name="robot0:lfdistal" pos="0 0 0.025">
<inertial pos="0 0 0.015" quat="0.707 -0.003 0.003 0.707" mass="0.01" diaginertia="1e-05 1e-05 1e-05"></inertial>
<joint name="robot0:LFJ0" type="hinge" pos="0 0 0" axis="1 0 0" range="0 1.571" user="1112"></joint>
<geom class="robot0:D_Vizual" name="robot0:V_lfdistal" mesh="robot0:F1" pos="0 0 0.001"></geom>
<geom class="robot0:DC_Hand" name="robot0:C_lfdistal" type="capsule" pos="0 0 0.012" size="0.00705 0.012" condim="4"></geom>
<site name="robot0:S_lftip" pos="0 0 0.026" group="3"></site>
<site class="robot0:D_Touch" name="robot0:Tch_lftip"></site>
</body>
</body>
</body>
</body>
</body>
<body name="robot0:thbase" pos="0.034 -0.009 0.029" axisangle="0 1 0 0.785">
<inertial pos="0 0 0" mass="0.01" diaginertia="1e-05 1e-05 1e-05"></inertial>
<joint name="robot0:THJ4" type="hinge" pos="0 0 0" axis="0 0 -1" range="-1.047 1.047" user="1121"></joint>
<geom name="robot0:V_thbase" type="box" group="1" pos="0 0 0" size="0.001 0.001 0.001"></geom>
<body name="robot0:thproximal" pos="0 0 0">
<inertial pos="0 0 0.017" quat="0.982 0 0.001 0.191" mass="0.016" diaginertia="1e-05 1e-05 1e-05"></inertial>
<joint name="robot0:THJ3" type="hinge" pos="0 0 0" axis="1 0 0" range="0 1.222" user="1120"></joint>
<geom class="robot0:D_Vizual" name="robot0:V_thproximal" mesh="robot0:TH3_z"></geom>
<geom class="robot0:DC_Hand" name="robot0:C_thproximal" type="capsule" pos="0 0 0.019" size="0.013 0.019" rgba="0.4 0.5 0.6 0.1"></geom>
<body name="robot0:thhub" pos="0 0 0.038">
<inertial pos="0 0 0" mass="0.002" diaginertia="1e-05 1e-05 1e-05"></inertial>
<joint name="robot0:THJ2" type="hinge" pos="0 0 0" axis="1 0 0" range="-0.209 0.209" user="1119"></joint>
<geom name="robot0:V_thhub" type="box" group="1" pos="0 0 0" size="0.001 0.001 0.001"></geom>
<body name="robot0:thmiddle" pos="0 0 0">
<inertial pos="0 0 0.016" quat="1 -0.001 -0.007 0.003" mass="0.016" diaginertia="1e-05 1e-05 1e-05"></inertial>
<joint name="robot0:THJ1" type="hinge" pos="0 0 0" axis="0 1 0" range="-0.524 0.524" user="1118"></joint>
<geom class="robot0:D_Vizual" name="robot0:V_thmiddle" mesh="robot0:TH2_z"></geom>
<geom class="robot0:DC_Hand" name="robot0:C_thmiddle" type="capsule" pos="0 0 0.016" size="0.011 0.016"></geom>
<body name="robot0:thdistal" pos="0 0 0.032">
<inertial pos="0 0 0.016" quat="0.999 -0.005 -0.047 0.005" mass="0.016" diaginertia="1e-05 1e-05 1e-05"></inertial>
<joint name="robot0:THJ0" type="hinge" pos="0 0 0" axis="0 1 0" range="-1.571 0" user="1117"></joint>
<geom class="robot0:D_Vizual" name="robot0:V_thdistal" mesh="robot0:TH1_z"></geom>
<geom class="robot0:DC_Hand" name="robot0:C_thdistal" type="capsule" pos="0 0 0.013" size="0.00918 0.013" condim="4"></geom>
<site name="robot0:S_thtip" pos="0 0 0.0275" group="3"></site>
<site class="robot0:D_Touch" name="robot0:Tch_thtip" size="0.005 0.011 0.016" pos="-0.005 0 0.02"></site>
</body>
</body>
</body>
</body>
</body>
</body>
</body>
</body>
</body>
</mujoco>

View File

@@ -0,0 +1,253 @@
<mujoco>
<size njmax="500" nconmax="100" nuser_jnt="1" nuser_site="1" nuser_tendon="1" nuser_sensor="1" nuser_actuator="16" nstack="600000"></size>
<visual>
<map fogstart="3" fogend="5" force="0.1"></map>
<quality shadowsize="4096"></quality>
</visual>
<default>
<default class="robot0:asset_class">
<geom friction="1 0.005 0.001" condim="3" margin="0.0005" contype="1" conaffinity="1"></geom>
<joint limited="true" damping="0.1" armature="0.001" margin="0.01" frictionloss="0.001"></joint>
<site size="0.005" rgba="0.4 0.9 0.4 1"></site>
<general ctrllimited="true" forcelimited="true"></general>
</default>
<default class="robot0:D_Touch">
<site type="box" size="0.009 0.004 0.013" pos="0 -0.004 0.018" rgba="0.8 0.8 0.8 0.15" group="4"></site>
</default>
<default class="robot0:DC_Hand">
<geom material="robot0:MatColl" contype="1" conaffinity="0" group="4"></geom>
</default>
<default class="robot0:D_Vizual">
<geom material="robot0:MatViz" contype="0" conaffinity="0" group="1" type="mesh"></geom>
</default>
<default class="robot0:free">
<joint type="free" damping="0" armature="0" limited="false"></joint>
</default>
</default>
<contact>
<pair geom1="robot0:C_ffdistal" geom2="robot0:C_thdistal" condim="1"></pair>
<pair geom1="robot0:C_ffmiddle" geom2="robot0:C_thdistal" condim="1"></pair>
<pair geom1="robot0:C_ffproximal" geom2="robot0:C_thdistal" condim="1"></pair>
<pair geom1="robot0:C_mfproximal" geom2="robot0:C_thdistal" condim="1"></pair>
<pair geom1="robot0:C_mfdistal" geom2="robot0:C_thdistal" condim="1"></pair>
<pair geom1="robot0:C_rfdistal" geom2="robot0:C_thdistal" condim="1"></pair>
<pair geom1="robot0:C_lfdistal" geom2="robot0:C_thdistal" condim="1"></pair>
<pair geom1="robot0:C_palm0" geom2="robot0:C_thdistal" condim="1"></pair>
<pair geom1="robot0:C_mfdistal" geom2="robot0:C_ffdistal" condim="1"></pair>
<pair geom1="robot0:C_rfdistal" geom2="robot0:C_mfdistal" condim="1"></pair>
<pair geom1="robot0:C_lfdistal" geom2="robot0:C_rfdistal" condim="1"></pair>
<pair geom1="robot0:C_mfproximal" geom2="robot0:C_ffproximal" condim="1"></pair>
<pair geom1="robot0:C_rfproximal" geom2="robot0:C_mfproximal" condim="1"></pair>
<pair geom1="robot0:C_lfproximal" geom2="robot0:C_rfproximal" condim="1"></pair>
<pair geom1="robot0:C_lfdistal" geom2="robot0:C_rfdistal" condim="1"></pair>
<pair geom1="robot0:C_lfdistal" geom2="robot0:C_mfdistal" condim="1"></pair>
<pair geom1="robot0:C_lfdistal" geom2="robot0:C_rfmiddle" condim="1"></pair>
<pair geom1="robot0:C_lfmiddle" geom2="robot0:C_rfdistal" condim="1"></pair>
<pair geom1="robot0:C_lfmiddle" geom2="robot0:C_rfmiddle" condim="1"></pair>
</contact>
<tendon>
<fixed name="robot0:T_WRJ1r" limited="true" range="-0.032 0.032" user="1236">
<joint joint="robot0:WRJ1" coef="0.0325"></joint>
</fixed>
<fixed name="robot0:T_WRJ1l" limited="true" range="-0.032 0.032" user="1237">
<joint joint="robot0:WRJ1" coef="-0.0325"></joint>
</fixed>
<fixed name="robot0:T_WRJ0u" limited="true" range="-0.032 0.032" user="1236">
<joint joint="robot0:WRJ0" coef="0.0175"></joint>
</fixed>
<fixed name="robot0:T_WRJ0d" limited="true" range="-0.032 0.032" user="1237">
<joint joint="robot0:WRJ0" coef="-0.0175"></joint>
</fixed>
<fixed name="robot0:T_FFJ3r" limited="true" range="-0.018 0.018" user="1204">
<joint joint="robot0:FFJ3" coef="0.01"></joint>
</fixed>
<fixed name="robot0:T_FFJ3l" limited="true" range="-0.018 0.018" user="1205">
<joint joint="robot0:FFJ3" coef="-0.01"></joint>
</fixed>
<fixed name="robot0:T_FFJ2u" limited="true" range="-0.007 0.03" user="1202">
<joint joint="robot0:FFJ2" coef="0.01"></joint>
</fixed>
<fixed name="robot0:T_FFJ2d" limited="true" range="-0.03 0.007" user="1203">
<joint joint="robot0:FFJ2" coef="-0.01"></joint>
</fixed>
<fixed name="robot0:T_FFJ1c" limited="true" range="-0.001 0.001">
<joint joint="robot0:FFJ0" coef="0.00705"></joint>
<joint joint="robot0:FFJ1" coef="-0.00805"></joint>
</fixed>
<fixed name="robot0:T_FFJ1u" limited="true" range="-0.007 0.03" user="1200">
<joint joint="robot0:FFJ0" coef="0.00705"></joint>
<joint joint="robot0:FFJ1" coef="0.00805"></joint>
</fixed>
<fixed name="robot0:T_FFJ1d" limited="true" range="-0.03 0.007" user="1201">
<joint joint="robot0:FFJ0" coef="-0.00705"></joint>
<joint joint="robot0:FFJ1" coef="-0.00805"></joint>
</fixed>
<fixed name="robot0:T_MFJ3r" limited="true" range="-0.018 0.018" user="1210">
<joint joint="robot0:MFJ3" coef="0.01"></joint>
</fixed>
<fixed name="robot0:T_MFJ3l" limited="true" range="-0.018 0.018" user="1211">
<joint joint="robot0:MFJ3" coef="-0.01"></joint>
</fixed>
<fixed name="robot0:T_MFJ2u" limited="true" range="-0.007 0.03" user="1208">
<joint joint="robot0:MFJ2" coef="0.01"></joint>
</fixed>
<fixed name="robot0:T_MFJ2d" limited="true" range="-0.03 0.007" user="1209">
<joint joint="robot0:MFJ2" coef="-0.01"></joint>
</fixed>
<fixed name="robot0:T_MFJ1c" limited="true" range="-0.001 0.001">
<joint joint="robot0:MFJ0" coef="0.00705"></joint>
<joint joint="robot0:MFJ1" coef="-0.00805"></joint>
</fixed>
<fixed name="robot0:T_MFJ1u" limited="true" range="-0.007 0.03" user="1206">
<joint joint="robot0:MFJ0" coef="0.00705"></joint>
<joint joint="robot0:MFJ1" coef="0.00805"></joint>
</fixed>
<fixed name="robot0:T_MFJ1d" limited="true" range="-0.03 0.007" user="1207">
<joint joint="robot0:MFJ0" coef="-0.00705"></joint>
<joint joint="robot0:MFJ1" coef="-0.00805"></joint>
</fixed>
<fixed name="robot0:T_RFJ3r" limited="true" range="-0.018 0.018" user="1216">
<joint joint="robot0:RFJ3" coef="0.01"></joint>
</fixed>
<fixed name="robot0:T_RFJ3l" limited="true" range="-0.018 0.018" user="1217">
<joint joint="robot0:RFJ3" coef="-0.01"></joint>
</fixed>
<fixed name="robot0:T_RFJ2u" limited="true" range="-0.007 0.03" user="1214">
<joint joint="robot0:RFJ2" coef="0.01"></joint>
</fixed>
<fixed name="robot0:T_RFJ2d" limited="true" range="-0.03 0.007" user="1215">
<joint joint="robot0:RFJ2" coef="-0.01"></joint>
</fixed>
<fixed name="robot0:T_RFJ1c" limited="true" range="-0.001 0.001">
<joint joint="robot0:RFJ0" coef="0.00705"></joint>
<joint joint="robot0:RFJ1" coef="-0.00805"></joint>
</fixed>
<fixed name="robot0:T_RFJ1u" limited="true" range="-0.007 0.03" user="1212">
<joint joint="robot0:RFJ0" coef="0.00705"></joint>
<joint joint="robot0:RFJ1" coef="0.00805"></joint>
</fixed>
<fixed name="robot0:T_RFJ1d" limited="true" range="-0.03 0.007" user="1213">
<joint joint="robot0:RFJ0" coef="-0.00705"></joint>
<joint joint="robot0:RFJ1" coef="-0.00805"></joint>
</fixed>
<fixed name="robot0:T_LFJ4u" limited="true" range="-0.007 0.03" user="1224">
<joint joint="robot0:LFJ4" coef="0.01"></joint>
</fixed>
<fixed name="robot0:T_LFJ4d" limited="true" range="-0.03 0.007" user="1225">
<joint joint="robot0:LFJ4" coef="-0.01"></joint>
</fixed>
<fixed name="robot0:T_LFJ3r" limited="true" range="-0.018 0.018" user="1222">
<joint joint="robot0:LFJ3" coef="0.01"></joint>
</fixed>
<fixed name="robot0:T_LFJ3l" limited="true" range="-0.018 0.018" user="1223">
<joint joint="robot0:LFJ3" coef="-0.01"></joint>
</fixed>
<fixed name="robot0:T_LFJ2u" limited="true" range="-0.007 0.03" user="1220">
<joint joint="robot0:LFJ2" coef="0.01"></joint>
</fixed>
<fixed name="robot0:T_LFJ2d" limited="true" range="-0.03 0.007" user="1221">
<joint joint="robot0:LFJ2" coef="-0.01"></joint>
</fixed>
<fixed name="robot0:T_LFJ1c" limited="true" range="-0.001 0.001">
<joint joint="robot0:LFJ0" coef="0.00705"></joint>
<joint joint="robot0:LFJ1" coef="-0.00805"></joint>
</fixed>
<fixed name="robot0:T_LFJ1u" limited="true" range="-0.007 0.03" user="1218">
<joint joint="robot0:LFJ0" coef="0.00705"></joint>
<joint joint="robot0:LFJ1" coef="0.00805"></joint>
</fixed>
<fixed name="robot0:T_LFJ1d" limited="true" range="-0.03 0.007" user="1219">
<joint joint="robot0:LFJ0" coef="-0.00705"></joint>
<joint joint="robot0:LFJ1" coef="-0.00805"></joint>
</fixed>
<fixed name="robot0:T_THJ4a" limited="true" range="-0.018 0.018" user="1234">
<joint joint="robot0:THJ4" coef="0.01636"></joint>
</fixed>
<fixed name="robot0:T_THJ4c" limited="true" range="-0.018 0.018" user="1235">
<joint joint="robot0:THJ4" coef="-0.01636"></joint>
</fixed>
<fixed name="robot0:T_THJ3u" limited="true" range="-0.007 0.03" user="1232">
<joint joint="robot0:THJ3" coef="0.01"></joint>
</fixed>
<fixed name="robot0:T_THJ3d" limited="true" range="-0.03 0.007" user="1233">
<joint joint="robot0:THJ3" coef="-0.01"></joint>
</fixed>
<fixed name="robot0:T_THJ2u" limited="true" range="-0.018 0.018" user="1230">
<joint joint="robot0:THJ2" coef="0.011"></joint>
</fixed>
<fixed name="robot0:T_THJ2d" limited="true" range="-0.018 0.018" user="1231">
<joint joint="robot0:THJ2" coef="-0.011"></joint>
</fixed>
<fixed name="robot0:T_THJ1r" limited="true" range="-0.018 0.018" user="1228">
<joint joint="robot0:THJ1" coef="0.011"></joint>
</fixed>
<fixed name="robot0:T_THJ1l" limited="true" range="-0.018 0.018" user="1229">
<joint joint="robot0:THJ1" coef="-0.011"></joint>
</fixed>
<fixed name="robot0:T_THJ0r" limited="true" range="-0.03 0.007" user="1226">
<joint joint="robot0:THJ0" coef="0.009"></joint>
</fixed>
<fixed name="robot0:T_THJ0l" limited="true" range="-0.007 0.03" user="1227">
<joint joint="robot0:THJ0" coef="-0.009"></joint>
</fixed>
</tendon>
<sensor>
<jointpos name="robot0:Sjp_WRJ1" joint="robot0:WRJ1"></jointpos>
<jointpos name="robot0:Sjp_WRJ0" joint="robot0:WRJ0"></jointpos>
<jointpos name="robot0:Sjp_FFJ3" joint="robot0:FFJ3"></jointpos>
<jointpos name="robot0:Sjp_FFJ2" joint="robot0:FFJ2"></jointpos>
<jointpos name="robot0:Sjp_FFJ1" joint="robot0:FFJ1"></jointpos>
<jointpos name="robot0:Sjp_FFJ0" joint="robot0:FFJ0"></jointpos>
<jointpos name="robot0:Sjp_MFJ3" joint="robot0:MFJ3"></jointpos>
<jointpos name="robot0:Sjp_MFJ2" joint="robot0:MFJ2"></jointpos>
<jointpos name="robot0:Sjp_MFJ1" joint="robot0:MFJ1"></jointpos>
<jointpos name="robot0:Sjp_MFJ0" joint="robot0:MFJ0"></jointpos>
<jointpos name="robot0:Sjp_RFJ3" joint="robot0:RFJ3"></jointpos>
<jointpos name="robot0:Sjp_RFJ2" joint="robot0:RFJ2"></jointpos>
<jointpos name="robot0:Sjp_RFJ1" joint="robot0:RFJ1"></jointpos>
<jointpos name="robot0:Sjp_RFJ0" joint="robot0:RFJ0"></jointpos>
<jointpos name="robot0:Sjp_LFJ4" joint="robot0:LFJ4"></jointpos>
<jointpos name="robot0:Sjp_LFJ3" joint="robot0:LFJ3"></jointpos>
<jointpos name="robot0:Sjp_LFJ2" joint="robot0:LFJ2"></jointpos>
<jointpos name="robot0:Sjp_LFJ1" joint="robot0:LFJ1"></jointpos>
<jointpos name="robot0:Sjp_LFJ0" joint="robot0:LFJ0"></jointpos>
<jointpos name="robot0:Sjp_THJ4" joint="robot0:THJ4"></jointpos>
<jointpos name="robot0:Sjp_THJ3" joint="robot0:THJ3"></jointpos>
<jointpos name="robot0:Sjp_THJ2" joint="robot0:THJ2"></jointpos>
<jointpos name="robot0:Sjp_THJ1" joint="robot0:THJ1"></jointpos>
<jointpos name="robot0:Sjp_THJ0" joint="robot0:THJ0"></jointpos>
<touch name="robot0:ST_Tch_fftip" site="robot0:Tch_fftip"></touch>
<touch name="robot0:ST_Tch_mftip" site="robot0:Tch_mftip"></touch>
<touch name="robot0:ST_Tch_rftip" site="robot0:Tch_rftip"></touch>
<touch name="robot0:ST_Tch_lftip" site="robot0:Tch_lftip"></touch>
<touch name="robot0:ST_Tch_thtip" site="robot0:Tch_thtip"></touch>
</sensor>
<actuator>
<position name="robot0:A_WRJ1" class="robot0:asset_class" user="2038" joint="robot0:WRJ1" ctrlrange="-0.489 0.14" kp="5" forcerange="-4.785 4.785"></position>
<position name="robot0:A_WRJ0" class="robot0:asset_class" user="2036" joint="robot0:WRJ0" ctrlrange="-0.698 0.489" kp="5" forcerange="-2.175 2.175"></position>
<position name="robot0:A_FFJ3" class="robot0:asset_class" user="2004" joint="robot0:FFJ3" ctrlrange="-0.349 0.349" kp="1" forcerange="-0.9 0.9"></position>
<position name="robot0:A_FFJ2" class="robot0:asset_class" user="2002" joint="robot0:FFJ2" ctrlrange="0 1.571" kp="1" forcerange="-0.9 0.9"></position>
<position name="robot0:A_FFJ1" class="robot0:asset_class" user="2000" joint="robot0:FFJ1" ctrlrange="0 1.571" kp="1" forcerange="-0.7245 0.7245"></position>
<position name="robot0:A_MFJ3" class="robot0:asset_class" user="2010" joint="robot0:MFJ3" ctrlrange="-0.349 0.349" kp="1" forcerange="-0.9 0.9"></position>
<position name="robot0:A_MFJ2" class="robot0:asset_class" user="2008" joint="robot0:MFJ2" ctrlrange="0 1.571" kp="1" forcerange="-0.9 0.9"></position>
<position name="robot0:A_MFJ1" class="robot0:asset_class" user="2006" joint="robot0:MFJ1" ctrlrange="0 1.571" kp="1" forcerange="-0.7245 0.7245"></position>
<position name="robot0:A_RFJ3" class="robot0:asset_class" user="2016" joint="robot0:RFJ3" ctrlrange="-0.349 0.349" kp="1" forcerange="-0.9 0.9"></position>
<position name="robot0:A_RFJ2" class="robot0:asset_class" user="2014" joint="robot0:RFJ2" ctrlrange="0 1.571" kp="1" forcerange="-0.9 0.9"></position>
<position name="robot0:A_RFJ1" class="robot0:asset_class" user="2012" joint="robot0:RFJ1" ctrlrange="0 1.571" kp="1" forcerange="-0.7245 0.7245"></position>
<position name="robot0:A_LFJ4" class="robot0:asset_class" user="2024" joint="robot0:LFJ4" ctrlrange="0 0.785" kp="1" forcerange="-0.9 0.9"></position>
<position name="robot0:A_LFJ3" class="robot0:asset_class" user="2022" joint="robot0:LFJ3" ctrlrange="-0.349 0.349" kp="1" forcerange="-0.9 0.9"></position>
<position name="robot0:A_LFJ2" class="robot0:asset_class" user="2020" joint="robot0:LFJ2" ctrlrange="0 1.571" kp="1" forcerange="-0.9 0.9"></position>
<position name="robot0:A_LFJ1" class="robot0:asset_class" user="2018" joint="robot0:LFJ1" ctrlrange="0 1.571" kp="1" forcerange="-0.7245 0.7245"></position>
<position name="robot0:A_THJ4" class="robot0:asset_class" user="2034" joint="robot0:THJ4" ctrlrange="-1.047 1.047" kp="1" forcerange="-2.3722 2.3722"></position>
<position name="robot0:A_THJ3" class="robot0:asset_class" user="2032" joint="robot0:THJ3" ctrlrange="0 1.222" kp="1" forcerange="-1.45 1.45"></position>
<position name="robot0:A_THJ2" class="robot0:asset_class" user="2030" joint="robot0:THJ2" ctrlrange="-0.209 0.209" kp="1" forcerange="-0.99 0.99"></position>
<position name="robot0:A_THJ1" class="robot0:asset_class" user="2028" joint="robot0:THJ1" ctrlrange="-0.524 0.524" kp="1" forcerange="-0.99 0.99"></position>
<position name="robot0:A_THJ0" class="robot0:asset_class" user="2026" joint="robot0:THJ0" ctrlrange="-1.571 0" kp="1" forcerange="-0.81 0.81"></position>
</actuator>
</mujoco>

View File

@@ -0,0 +1,25 @@
<mujoco>
<texture type="skybox" builtin="gradient" rgb1="0.44 0.85 0.56" rgb2="0.46 0.87 0.58" width="32" height="32"></texture>
<texture name="robot0:texplane" type="2d" builtin="checker" rgb1="0.2 0.3 0.4" rgb2="0.1 0.15 0.2" width="512" height="512"></texture>
<texture name="robot0:texgeom" type="cube" builtin="flat" mark="cross" width="127" height="127" rgb1="0.3 0.6 0.5" rgb2="0.3 0.6 0.5" markrgb="0 0 0" random="0.01"></texture>
<material name="robot0:MatGnd" reflectance="0.5" texture="robot0:texplane" texrepeat="1 1" texuniform="true"></material>
<material name="robot0:MatColl" specular="1" shininess="0.3" reflectance="0.5" rgba="0.4 0.5 0.6 1"></material>
<material name="robot0:MatViz" specular="0.75" shininess="0.1" reflectance="0.5" rgba="0.93 0.93 0.93 1"></material>
<material name="robot0:object" texture="robot0:texgeom" texuniform="false"></material>
<material name="floor_mat" specular="0" shininess="0.5" reflectance="0" rgba="0.2 0.2 0.2 0"></material>
<mesh name="robot0:forearm" file="forearm_electric.stl"></mesh>
<mesh name="robot0:forearm_cvx" file="forearm_electric_cvx.stl"></mesh>
<mesh name="robot0:wrist" scale="0.001 0.001 0.001" file="wrist.stl"></mesh>
<mesh name="robot0:palm" scale="0.001 0.001 0.001" file="palm.stl"></mesh>
<mesh name="robot0:knuckle" scale="0.001 0.001 0.001" file="knuckle.stl"></mesh>
<mesh name="robot0:F3" scale="0.001 0.001 0.001" file="F3.stl"></mesh>
<mesh name="robot0:F2" scale="0.001 0.001 0.001" file="F2.stl"></mesh>
<mesh name="robot0:F1" scale="0.001 0.001 0.001" file="F1.stl"></mesh>
<mesh name="robot0:lfmetacarpal" scale="0.001 0.001 0.001" file="lfmetacarpal.stl"></mesh>
<mesh name="robot0:TH3_z" scale="0.001 0.001 0.001" file="TH3_z.stl"></mesh>
<mesh name="robot0:TH2_z" scale="0.001 0.001 0.001" file="TH2_z.stl"></mesh>
<mesh name="robot0:TH1_z" scale="0.001 0.001 0.001" file="TH1_z.stl"></mesh>
</mujoco>

View File

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

View File

@@ -0,0 +1,21 @@
from gym import utils
from gym.envs.robotics import fetch_env
class FetchPickAndPlaceEnv(fetch_env.FetchEnv, utils.EzPickle):
def __init__(self, reward_type='sparse'):
initial_qpos = {
'robot0:slide0': 0.405,
'robot0:slide1': 0.48,
'robot0:slide2': 0.0,
'table0:slide0': 1.05,
'table0:slide1': 0.4,
'table0:slide2': 0.0,
'object0:joint': [1.25, 0.53, 0.4, 1., 0., 0., 0.],
}
fetch_env.FetchEnv.__init__(
self, 'fetch/pick_and_place.xml', has_object=True, block_gripper=False, n_substeps=20,
gripper_extra_height=0.2, target_in_the_air=True, target_offset=0.0,
obj_range=0.15, target_range=0.15, distance_threshold=0.05,
initial_qpos=initial_qpos, reward_type=reward_type)
utils.EzPickle.__init__(self)

View File

@@ -0,0 +1,21 @@
from gym import utils
from gym.envs.robotics import fetch_env
class FetchPushEnv(fetch_env.FetchEnv, utils.EzPickle):
def __init__(self, reward_type='sparse'):
initial_qpos = {
'robot0:slide0': 0.405,
'robot0:slide1': 0.48,
'robot0:slide2': 0.0,
'table0:slide0': 1.05,
'table0:slide1': 0.4,
'table0:slide2': 0.0,
'object0:joint': [1.25, 0.53, 0.4, 1., 0., 0., 0.],
}
fetch_env.FetchEnv.__init__(
self, 'fetch/push.xml', has_object=True, block_gripper=True, n_substeps=20,
gripper_extra_height=0.0, target_in_the_air=False, target_offset=0.0,
obj_range=0.15, target_range=0.15, distance_threshold=0.05,
initial_qpos=initial_qpos, reward_type=reward_type)
utils.EzPickle.__init__(self)

View File

@@ -0,0 +1,20 @@
from gym import utils
from gym.envs.robotics import fetch_env
class FetchReachEnv(fetch_env.FetchEnv, utils.EzPickle):
def __init__(self, reward_type='sparse'):
initial_qpos = {
'robot0:slide0': 0.4049,
'robot0:slide1': 0.48,
'robot0:slide2': 0.0,
'table0:slide0': 1.05,
'table0:slide1': 0.4,
'table0:slide2': 0.0,
}
fetch_env.FetchEnv.__init__(
self, 'fetch/reach.xml', has_object=False, block_gripper=True, n_substeps=20,
gripper_extra_height=0.2, target_in_the_air=True, target_offset=0.0,
obj_range=0.15, target_range=0.15, distance_threshold=0.05,
initial_qpos=initial_qpos, reward_type=reward_type)
utils.EzPickle.__init__(self)

View File

@@ -0,0 +1,23 @@
import numpy as np
from gym import utils
from gym.envs.robotics import fetch_env
class FetchSlideEnv(fetch_env.FetchEnv, utils.EzPickle):
def __init__(self, reward_type='sparse'):
initial_qpos = {
'robot0:slide0': 0.05,
'robot0:slide1': 0.48,
'robot0:slide2': 0.0,
'table0:slide0': 0.7,
'table0:slide1': 0.3,
'table0:slide2': 0.0,
'object0:joint': [1.7, 1.1, 0.4, 1., 0., 0., 0.],
}
fetch_env.FetchEnv.__init__(
self, 'fetch/slide.xml', has_object=True, block_gripper=True, n_substeps=20,
gripper_extra_height=-0.02, target_in_the_air=False, target_offset=np.array([0.4, 0.0, 0.0]),
obj_range=0.1, target_range=0.3, distance_threshold=0.05,
initial_qpos=initial_qpos, reward_type=reward_type)
utils.EzPickle.__init__(self)

View File

@@ -0,0 +1,187 @@
import numpy as np
from gym.envs.robotics import rotations, robot_env, utils
def goal_distance(goal_a, goal_b):
assert goal_a.shape == goal_b.shape
return np.linalg.norm(goal_a - goal_b, axis=-1)
class FetchEnv(robot_env.RobotEnv):
"""Superclass for all Fetch environments.
"""
def __init__(
self, model_path, n_substeps, gripper_extra_height, block_gripper,
has_object, target_in_the_air, target_offset, obj_range, target_range,
distance_threshold, initial_qpos, reward_type,
):
"""Initializes a new Fetch environment.
Args:
model_path (string): path to the environments XML file
n_substeps (int): number of substeps the simulation runs on every call to step
gripper_extra_height (float): additional height above the table when positioning the gripper
block_gripper (boolean): whether or not the gripper is blocked (i.e. not movable) or not
has_object (boolean): whether or not the environment has an object
target_in_the_air (boolean): whether or not the target should be in the air above the table or on the table surface
target_offset (float or array with 3 elements): offset of the target
obj_range (float): range of a uniform distribution for sampling initial object positions
target_range (float): range of a uniform distribution for sampling a target
distance_threshold (float): the threshold after which a goal is considered achieved
initial_qpos (dict): a dictionary of joint names and values that define the initial configuration
reward_type ('sparse' or 'dense'): the reward type, i.e. sparse or dense
"""
self.gripper_extra_height = gripper_extra_height
self.block_gripper = block_gripper
self.has_object = has_object
self.target_in_the_air = target_in_the_air
self.target_offset = target_offset
self.obj_range = obj_range
self.target_range = target_range
self.distance_threshold = distance_threshold
self.reward_type = reward_type
super(FetchEnv, self).__init__(
model_path=model_path, n_substeps=n_substeps, n_actions=4,
initial_qpos=initial_qpos)
# GoalEnv methods
# ----------------------------
def compute_reward(self, achieved_goal, goal, info):
# Compute distance between goal and the achieved goal.
d = goal_distance(achieved_goal, goal)
if self.reward_type == 'sparse':
return -(d > self.distance_threshold).astype(np.float32)
else:
return -d
# RobotEnv methods
# ----------------------------
def _step_callback(self):
if self.block_gripper:
self.sim.data.set_joint_qpos('robot0:l_gripper_finger_joint', 0.)
self.sim.data.set_joint_qpos('robot0:r_gripper_finger_joint', 0.)
self.sim.forward()
def _set_action(self, action):
assert action.shape == (4,)
action = action.copy() # ensure that we don't change the action outside of this scope
pos_ctrl, gripper_ctrl = action[:3], action[3]
pos_ctrl *= 0.05 # limit maximum change in position
rot_ctrl = [1., 0., 1., 0.] # fixed rotation of the end effector, expressed as a quaternion
gripper_ctrl = np.array([gripper_ctrl, gripper_ctrl])
assert gripper_ctrl.shape == (2,)
if self.block_gripper:
gripper_ctrl = np.zeros_like(gripper_ctrl)
action = np.concatenate([pos_ctrl, rot_ctrl, gripper_ctrl])
# Apply action to simulation.
utils.ctrl_set_action(self.sim, action)
utils.mocap_set_action(self.sim, action)
def _get_obs(self):
# positions
grip_pos = self.sim.data.get_site_xpos('robot0:grip')
dt = self.sim.nsubsteps * self.sim.model.opt.timestep
grip_velp = self.sim.data.get_site_xvelp('robot0:grip') * dt
robot_qpos, robot_qvel = utils.robot_get_obs(self.sim)
if self.has_object:
object_pos = self.sim.data.get_site_xpos('object0')
# rotations
object_rot = rotations.mat2euler(self.sim.data.get_site_xmat('object0'))
# velocities
object_velp = self.sim.data.get_site_xvelp('object0') * dt
object_velr = self.sim.data.get_site_xvelr('object0') * dt
# gripper state
object_rel_pos = object_pos - grip_pos
object_velp -= grip_velp
else:
object_pos = object_rot = object_velp = object_velr = object_rel_pos = np.zeros(0)
gripper_state = robot_qpos[-2:]
gripper_vel = robot_qvel[-2:] * dt # change to a scalar if the gripper is made symmetric
if not self.has_object:
achieved_goal = grip_pos.copy()
else:
achieved_goal = np.squeeze(object_pos.copy())
obs = np.concatenate([
grip_pos, object_pos.ravel(), object_rel_pos.ravel(), gripper_state, object_rot.ravel(),
object_velp.ravel(), object_velr.ravel(), grip_velp, gripper_vel,
])
return {
'observation': obs.copy(),
'achieved_goal': achieved_goal.copy(),
'desired_goal': self.goal.copy(),
}
def _viewer_setup(self):
body_id = self.sim.model.body_name2id('robot0:gripper_link')
lookat = self.sim.data.body_xpos[body_id]
for idx, value in enumerate(lookat):
self.viewer.cam.lookat[idx] = value
self.viewer.cam.distance = 2.5
self.viewer.cam.azimuth = 132.
self.viewer.cam.elevation = -14.
def _render_callback(self):
# Visualize target.
sites_offset = (self.sim.data.site_xpos - self.sim.model.site_pos).copy()
site_id = self.sim.model.site_name2id('target0')
self.sim.model.site_pos[site_id] = self.goal - sites_offset[0]
self.sim.forward()
def _reset_sim(self):
self.sim.set_state(self.initial_state)
# Randomize start position of object.
if self.has_object:
object_xpos = self.initial_gripper_xpos[:2]
while np.linalg.norm(object_xpos - self.initial_gripper_xpos[:2]) < 0.1:
object_xpos = self.initial_gripper_xpos[:2] + self.np_random.uniform(-self.obj_range, self.obj_range, size=2)
object_qpos = self.sim.data.get_joint_qpos('object0:joint')
assert object_qpos.shape == (7,)
object_qpos[:2] = object_xpos
self.sim.data.set_joint_qpos('object0:joint', object_qpos)
self.sim.forward()
return True
def _sample_goal(self):
if self.has_object:
goal = self.initial_gripper_xpos[:3] + self.np_random.uniform(-self.target_range, self.target_range, size=3)
goal += self.target_offset
goal[2] = self.height_offset
if self.target_in_the_air and self.np_random.uniform() < 0.5:
goal[2] += self.np_random.uniform(0, 0.45)
else:
goal = self.initial_gripper_xpos[:3] + self.np_random.uniform(-0.15, 0.15, size=3)
return goal.copy()
def _is_success(self, achieved_goal, desired_goal):
d = goal_distance(achieved_goal, desired_goal)
return (d < self.distance_threshold).astype(np.float32)
def _env_setup(self, initial_qpos):
for name, value in initial_qpos.items():
self.sim.data.set_joint_qpos(name, value)
utils.reset_mocap_welds(self.sim)
self.sim.forward()
# Move end effector into position.
gripper_target = np.array([-0.498, 0.005, -0.431 + self.gripper_extra_height]) + self.sim.data.get_site_xpos('robot0:grip')
gripper_rotation = np.array([1., 0., 1., 0.])
self.sim.data.set_mocap_pos('robot0:mocap', gripper_target)
self.sim.data.set_mocap_quat('robot0:mocap', gripper_rotation)
for _ in range(10):
self.sim.step()
# Extract information for sampling goals.
self.initial_gripper_xpos = self.sim.data.get_site_xpos('robot0:grip').copy()
if self.has_object:
self.height_offset = self.sim.data.get_site_xpos('object0')[2]

View File

@@ -0,0 +1,292 @@
import numpy as np
from gym import utils, error
from gym.envs.robotics import rotations, hand_env
from gym.envs.robotics.utils import robot_get_obs
try:
import mujoco_py
except ImportError as e:
raise error.DependencyNotInstalled("{}. (HINT: you need to install mujoco_py, and also perform the setup instructions here: https://github.com/openai/mujoco-py/.)".format(e))
def quat_from_angle_and_axis(angle, axis):
assert axis.shape == (3,)
axis /= np.linalg.norm(axis)
quat = np.concatenate([[np.cos(angle / 2.)], np.sin(angle / 2.) * axis])
quat /= np.linalg.norm(quat)
return quat
class ManipulateEnv(hand_env.HandEnv, utils.EzPickle):
def __init__(
self, model_path, target_position, target_rotation,
target_position_range, reward_type, initial_qpos={},
randomize_initial_position=True, randomize_initial_rotation=True,
distance_threshold=0.01, rotation_threshold=0.1, n_substeps=20, relative_control=False,
ignore_z_target_rotation=False,
):
"""Initializes a new Hand manipulation environment.
Args:
model_path (string): path to the environments XML file
target_position (string): the type of target position:
- ignore: target position is fully ignored, i.e. the object can be positioned arbitrarily
- fixed: target position is set to the initial position of the object
- random: target position is fully randomized according to target_position_range
target_rotation (string): the type of target rotation:
- ignore: target rotation is fully ignored, i.e. the object can be rotated arbitrarily
- fixed: target rotation is set to the initial rotation of the object
- xyz: fully randomized target rotation around the X, Y and Z axis
- z: fully randomized target rotation around the Z axis
- parallel: fully randomized target rotation around Z and axis-aligned rotation around X, Y
ignore_z_target_rotation (boolean): whether or not the Z axis of the target rotation is ignored
target_position_range (np.array of shape (3, 2)): range of the target_position randomization
reward_type ('sparse' or 'dense'): the reward type, i.e. sparse or dense
initial_qpos (dict): a dictionary of joint names and values that define the initial configuration
randomize_initial_position (boolean): whether or not to randomize the initial position of the object
randomize_initial_rotation (boolean): whether or not to randomize the initial rotation of the object
distance_threshold (float, in meters): the threshold after which the position of a goal is considered achieved
rotation_threshold (float, in radians): the threshold after which the rotation of a goal is considered achieved
n_substeps (int): number of substeps the simulation runs on every call to step
relative_control (boolean): whether or not the hand is actuated in absolute joint positions or relative to the current state
"""
self.target_position = target_position
self.target_rotation = target_rotation
self.target_position_range = target_position_range
self.parallel_quats = [rotations.euler2quat(r) for r in rotations.get_parallel_rotations()]
self.randomize_initial_rotation = randomize_initial_rotation
self.randomize_initial_position = randomize_initial_position
self.distance_threshold = distance_threshold
self.rotation_threshold = rotation_threshold
self.reward_type = reward_type
self.ignore_z_target_rotation = ignore_z_target_rotation
assert self.target_position in ['ignore', 'fixed', 'random']
assert self.target_rotation in ['ignore', 'fixed', 'xyz', 'z', 'parallel']
hand_env.HandEnv.__init__(
self, model_path, n_substeps=n_substeps, initial_qpos=initial_qpos,
relative_control=relative_control)
utils.EzPickle.__init__(self)
def _get_achieved_goal(self):
# Object position and rotation.
object_qpos = self.sim.data.get_joint_qpos('object:joint')
assert object_qpos.shape == (7,)
return object_qpos
def _goal_distance(self, goal_a, goal_b):
assert goal_a.shape == goal_b.shape
assert goal_a.shape[-1] == 7
d_pos = np.zeros_like(goal_a[..., 0])
d_rot = np.zeros_like(goal_b[..., 0])
if self.target_position != 'ignore':
delta_pos = goal_a[..., :3] - goal_b[..., :3]
d_pos = np.linalg.norm(delta_pos, axis=-1)
if self.target_rotation != 'ignore':
quat_a, quat_b = goal_a[..., 3:], goal_b[..., 3:]
if self.ignore_z_target_rotation:
# Special case: We want to ignore the Z component of the rotation.
# This code here assumes Euler angles with xyz convention. We first transform
# to euler, then set the Z component to be equal between the two, and finally
# transform back into quaternions.
euler_a = rotations.quat2euler(quat_a)
euler_b = rotations.quat2euler(quat_b)
euler_a[2] = euler_b[2]
quat_a = rotations.euler2quat(euler_a)
# Subtract quaternions and extract angle between them.
quat_diff = rotations.quat_mul(quat_a, rotations.quat_conjugate(quat_b))
angle_diff = 2 * np.arccos(np.clip(quat_diff[..., 0], -1., 1.))
d_rot = angle_diff
assert d_pos.shape == d_rot.shape
return d_pos, d_rot
# GoalEnv methods
# ----------------------------
def compute_reward(self, achieved_goal, goal, info):
if self.reward_type == 'sparse':
success = self._is_success(achieved_goal, goal).astype(np.float32)
return (success - 1.)
else:
d_pos, d_rot = self._goal_distance(achieved_goal, goal)
# We weigh the difference in position to avoid that `d_pos` (in meters) is completely
# dominated by `d_rot` (in radians).
return -(10. * d_pos + d_rot)
# RobotEnv methods
# ----------------------------
def _is_success(self, achieved_goal, desired_goal):
d_pos, d_rot = self._goal_distance(achieved_goal, desired_goal)
achieved_pos = (d_pos < self.distance_threshold).astype(np.float32)
achieved_rot = (d_rot < self.rotation_threshold).astype(np.float32)
achieved_both = achieved_pos * achieved_rot
return achieved_both
def _env_setup(self, initial_qpos):
for name, value in initial_qpos.items():
self.sim.data.set_joint_qpos(name, value)
self.sim.forward()
def _reset_sim(self):
self.sim.set_state(self.initial_state)
self.sim.forward()
initial_qpos = self.sim.data.get_joint_qpos('object:joint').copy()
initial_pos, initial_quat = initial_qpos[:3], initial_qpos[3:]
assert initial_qpos.shape == (7,)
assert initial_pos.shape == (3,)
assert initial_quat.shape == (4,)
initial_qpos = None
# Randomization initial rotation.
if self.randomize_initial_rotation:
if self.target_rotation == 'z':
angle = self.np_random.uniform(-np.pi, np.pi)
axis = np.array([0., 0., 1.])
offset_quat = quat_from_angle_and_axis(angle, axis)
initial_quat = rotations.quat_mul(initial_quat, offset_quat)
elif self.target_rotation == 'parallel':
angle = self.np_random.uniform(-np.pi, np.pi)
axis = np.array([0., 0., 1.])
z_quat = quat_from_angle_and_axis(angle, axis)
parallel_quat = self.parallel_quats[self.np_random.randint(len(self.parallel_quats))]
offset_quat = rotations.quat_mul(z_quat, parallel_quat)
initial_quat = rotations.quat_mul(initial_quat, offset_quat)
elif self.target_rotation in ['xyz', 'ignore']:
angle = self.np_random.uniform(-np.pi, np.pi)
axis = np.random.uniform(-1., 1., size=3)
offset_quat = quat_from_angle_and_axis(angle, axis)
initial_quat = rotations.quat_mul(initial_quat, offset_quat)
elif self.target_rotation == 'fixed':
pass
else:
raise error.Error('Unknown target_rotation option "{}".'.format(self.target_rotation))
# Randomize initial position.
if self.randomize_initial_position:
if self.target_position != 'fixed':
initial_pos += self.np_random.normal(size=3, scale=0.005)
initial_quat /= np.linalg.norm(initial_quat)
initial_qpos = np.concatenate([initial_pos, initial_quat])
self.sim.data.set_joint_qpos('object:joint', initial_qpos)
def is_on_palm():
self.sim.forward()
cube_middle_idx = self.sim.model.site_name2id('object:center')
cube_middle_pos = self.sim.data.site_xpos[cube_middle_idx]
is_on_palm = (cube_middle_pos[2] > 0.04)
return is_on_palm
# Run the simulation for a bunch of timesteps to let everything settle in.
for _ in range(10):
self._set_action(np.zeros(20))
try:
self.sim.step()
except mujoco_py.MujocoException:
return False
return is_on_palm()
def _sample_goal(self):
# Select a goal for the object position.
target_pos = None
if self.target_position == 'random':
assert self.target_position_range.shape == (3, 2)
offset = self.np_random.uniform(self.target_position_range[:, 0], self.target_position_range[:, 1])
assert offset.shape == (3,)
target_pos = self.sim.data.get_joint_qpos('object:joint')[:3] + offset
elif self.target_position in ['ignore', 'fixed']:
target_pos = self.sim.data.get_joint_qpos('object:joint')[:3]
else:
raise error.Error('Unknown target_position option "{}".'.format(self.target_position))
assert target_pos is not None
assert target_pos.shape == (3,)
# Select a goal for the object rotation.
target_quat = None
if self.target_rotation == 'z':
angle = self.np_random.uniform(-np.pi, np.pi)
axis = np.array([0., 0., 1.])
target_quat = quat_from_angle_and_axis(angle, axis)
elif self.target_rotation == 'parallel':
angle = self.np_random.uniform(-np.pi, np.pi)
axis = np.array([0., 0., 1.])
target_quat = quat_from_angle_and_axis(angle, axis)
parallel_quat = self.parallel_quats[self.np_random.randint(len(self.parallel_quats))]
target_quat = rotations.quat_mul(target_quat, parallel_quat)
elif self.target_rotation == 'xyz':
angle = self.np_random.uniform(-np.pi, np.pi)
axis = np.random.uniform(-1., 1., size=3)
target_quat = quat_from_angle_and_axis(angle, axis)
elif self.target_rotation in ['ignore', 'fixed']:
target_quat = self.sim.data.get_joint_qpos('object:joint')
else:
raise error.Error('Unknown target_rotation option "{}".'.format(self.target_rotation))
assert target_quat is not None
assert target_quat.shape == (4,)
target_quat /= np.linalg.norm(target_quat) # normalized quaternion
goal = np.concatenate([target_pos, target_quat])
return goal
def _render_callback(self):
# Assign current state to target object but offset a bit so that the actual object
# is not obscured.
goal = self.goal.copy()
assert goal.shape == (7,)
if self.target_position == 'ignore':
# Move the object to the side since we do not care about it's position.
goal[0] += 0.15
self.sim.data.set_joint_qpos('target:joint', goal)
self.sim.data.set_joint_qvel('target:joint', np.zeros(6))
if 'object_hidden' in self.sim.model.geom_names:
hidden_id = self.sim.model.geom_name2id('object_hidden')
self.sim.model.geom_rgba[hidden_id, 3] = 1.
self.sim.forward()
def _get_obs(self):
robot_qpos, robot_qvel = robot_get_obs(self.sim)
object_qvel = self.sim.data.get_joint_qvel('object:joint')
achieved_goal = self._get_achieved_goal().ravel() # this contains the object position + rotation
observation = np.concatenate([robot_qpos, robot_qvel, object_qvel, achieved_goal])
return {
'observation': observation.copy(),
'achieved_goal': achieved_goal.copy(),
'desired_goal': self.goal.ravel().copy(),
}
class HandBlockEnv(ManipulateEnv):
def __init__(self, target_position='random', target_rotation='xyz', reward_type='sparse'):
super(HandBlockEnv, self).__init__(
model_path='hand/manipulate_block.xml', target_position=target_position,
target_rotation=target_rotation,
target_position_range=np.array([(-0.04, 0.04), (-0.06, 0.02), (0.0, 0.06)]),
reward_type=reward_type)
class HandEggEnv(ManipulateEnv):
def __init__(self, target_position='random', target_rotation='xyz', reward_type='sparse'):
super(HandEggEnv, self).__init__(
model_path='hand/manipulate_egg.xml', target_position=target_position,
target_rotation=target_rotation,
target_position_range=np.array([(-0.04, 0.04), (-0.06, 0.02), (0.0, 0.06)]),
reward_type=reward_type)
class HandPenEnv(ManipulateEnv):
def __init__(self, target_position='random', target_rotation='xyz', reward_type='sparse'):
super(HandPenEnv, self).__init__(
model_path='hand/manipulate_pen.xml', target_position=target_position,
target_rotation=target_rotation,
target_position_range=np.array([(-0.04, 0.04), (-0.06, 0.02), (0.0, 0.06)]),
randomize_initial_rotation=False, reward_type=reward_type,
ignore_z_target_rotation=True, distance_threshold=0.05)

View File

@@ -0,0 +1,144 @@
import numpy as np
from gym import utils
from gym.envs.robotics import hand_env
from gym.envs.robotics.utils import robot_get_obs
FINGERTIP_SITE_NAMES = [
'robot0:S_fftip',
'robot0:S_mftip',
'robot0:S_rftip',
'robot0:S_lftip',
'robot0:S_thtip',
]
DEFAULT_INITIAL_QPOS = {
'robot0:WRJ1': -0.16514339750464327,
'robot0:WRJ0': -0.31973286565062153,
'robot0:FFJ3': 0.14340512546557435,
'robot0:FFJ2': 0.32028208333591573,
'robot0:FFJ1': 0.7126053607727917,
'robot0:FFJ0': 0.6705281001412586,
'robot0:MFJ3': 0.000246444303701037,
'robot0:MFJ2': 0.3152655251085491,
'robot0:MFJ1': 0.7659800313729842,
'robot0:MFJ0': 0.7323156897425923,
'robot0:RFJ3': 0.00038520700007378114,
'robot0:RFJ2': 0.36743546201985233,
'robot0:RFJ1': 0.7119514095008576,
'robot0:RFJ0': 0.6699446327514138,
'robot0:LFJ4': 0.0525442258033891,
'robot0:LFJ3': -0.13615534724474673,
'robot0:LFJ2': 0.39872030433433003,
'robot0:LFJ1': 0.7415570009679252,
'robot0:LFJ0': 0.704096378652974,
'robot0:THJ4': 0.003673823825070126,
'robot0:THJ3': 0.5506291436028695,
'robot0:THJ2': -0.014515151997119306,
'robot0:THJ1': -0.0015229223564485414,
'robot0:THJ0': -0.7894883021600622,
}
def goal_distance(goal_a, goal_b):
assert goal_a.shape == goal_b.shape
return np.linalg.norm(goal_a - goal_b, axis=-1)
class HandReachEnv(hand_env.HandEnv, utils.EzPickle):
def __init__(
self, distance_threshold=0.01, n_substeps=20, relative_control=False,
initial_qpos=DEFAULT_INITIAL_QPOS, reward_type='sparse',
):
self.distance_threshold = distance_threshold
self.reward_type = reward_type
hand_env.HandEnv.__init__(
self, 'hand/reach.xml', n_substeps=n_substeps, initial_qpos=initial_qpos,
relative_control=relative_control)
utils.EzPickle.__init__(self)
def _get_achieved_goal(self):
goal = [self.sim.data.get_site_xpos(name) for name in FINGERTIP_SITE_NAMES]
return np.array(goal).flatten()
# GoalEnv methods
# ----------------------------
def compute_reward(self, achieved_goal, goal, info):
d = goal_distance(achieved_goal, goal)
if self.reward_type == 'sparse':
return -(d > self.distance_threshold).astype(np.float32)
else:
return -d
# RobotEnv methods
# ----------------------------
def _env_setup(self, initial_qpos):
for name, value in initial_qpos.items():
self.sim.data.set_joint_qpos(name, value)
self.sim.forward()
self.initial_goal = self._get_achieved_goal().copy()
self.palm_xpos = self.sim.data.body_xpos[self.sim.model.body_name2id('robot0:palm')].copy()
def _get_obs(self):
robot_qpos, robot_qvel = robot_get_obs(self.sim)
achieved_goal = self._get_achieved_goal().ravel()
observation = np.concatenate([robot_qpos, robot_qvel, achieved_goal])
return {
'observation': observation.copy(),
'achieved_goal': achieved_goal.copy(),
'desired_goal': self.goal.copy(),
}
def _sample_goal(self):
thumb_name = 'robot0:S_thtip'
finger_names = [name for name in FINGERTIP_SITE_NAMES if name != thumb_name]
finger_name = self.np_random.choice(finger_names)
thumb_idx = FINGERTIP_SITE_NAMES.index(thumb_name)
finger_idx = FINGERTIP_SITE_NAMES.index(finger_name)
assert thumb_idx != finger_idx
# Pick a meeting point above the hand.
meeting_pos = self.palm_xpos + np.array([0.0, -0.09, 0.05])
meeting_pos += self.np_random.normal(scale=0.005, size=meeting_pos.shape)
# Slightly move meeting goal towards the respective finger to avoid that they
# overlap.
goal = self.initial_goal.copy().reshape(-1, 3)
for idx in [thumb_idx, finger_idx]:
offset_direction = (meeting_pos - goal[idx])
offset_direction /= np.linalg.norm(offset_direction)
goal[idx] = meeting_pos - 0.005 * offset_direction
if self.np_random.uniform() < 0.1:
# With some probability, ask all fingers to move back to the origin.
# This avoids that the thumb constantly stays near the goal position already.
goal = self.initial_goal.copy()
return goal.flatten()
def _is_success(self, achieved_goal, desired_goal):
d = goal_distance(achieved_goal, desired_goal)
return (d < self.distance_threshold).astype(np.float32)
def _render_callback(self):
# Visualize targets.
sites_offset = (self.sim.data.site_xpos - self.sim.model.site_pos).copy()
goal = self.goal.reshape(5, 3)
for finger_idx in range(5):
site_name = 'target{}'.format(finger_idx)
site_id = self.sim.model.site_name2id(site_name)
self.sim.model.site_pos[site_id] = goal[finger_idx] - sites_offset[site_id]
# Visualize finger positions.
achieved_goal = self._get_achieved_goal().reshape(5, 3)
for finger_idx in range(5):
site_name = 'finger{}'.format(finger_idx)
site_id = self.sim.model.site_name2id(site_name)
self.sim.model.site_pos[site_id] = achieved_goal[finger_idx] - sites_offset[site_id]
self.sim.forward()

View File

@@ -0,0 +1,49 @@
import os
import copy
import numpy as np
import gym
from gym import error, spaces
from gym.utils import seeding
from gym.envs.robotics import robot_env
class HandEnv(robot_env.RobotEnv):
def __init__(self, model_path, n_substeps, initial_qpos, relative_control):
self.relative_control = relative_control
super(HandEnv, self).__init__(
model_path=model_path, n_substeps=n_substeps, n_actions=20,
initial_qpos=initial_qpos)
# RobotEnv methods
# ----------------------------
def _set_action(self, action):
assert action.shape == (20,)
ctrlrange = self.sim.model.actuator_ctrlrange
actuation_range = (ctrlrange[:, 1] - ctrlrange[:, 0]) / 2.
if self.relative_control:
actuation_center = np.zeros_like(action)
for i in range(self.sim.data.ctrl.shape[0]):
actuation_center[i] = self.sim.data.get_joint_qpos(
self.sim.model.actuator_names[i].replace(':A_', ':'))
for joint_name in ['FF', 'MF', 'RF', 'LF']:
act_idx = self.sim.model.actuator_name2id(
'robot0:A_{}J1'.format(joint_name))
actuation_center[act_idx] += self.sim.data.get_joint_qpos(
'robot0:{}J0'.format(joint_name))
else:
actuation_center = (ctrlrange[:, 1] + ctrlrange[:, 0]) / 2.
self.sim.data.ctrl[:] = actuation_center + action * actuation_range
self.sim.data.ctrl[:] = np.clip(self.sim.data.ctrl, ctrlrange[:, 0], ctrlrange[:, 1])
def _viewer_setup(self):
body_id = self.sim.model.body_name2id('robot0:palm')
lookat = self.sim.data.body_xpos[body_id]
for idx, value in enumerate(lookat):
self.viewer.cam.lookat[idx] = value
self.viewer.cam.distance = 0.5
self.viewer.cam.azimuth = 55.
self.viewer.cam.elevation = -25.

View File

@@ -0,0 +1,162 @@
import os
import copy
import numpy as np
import gym
from gym import error, spaces
from gym.utils import seeding
try:
import mujoco_py
except ImportError as e:
raise error.DependencyNotInstalled("{}. (HINT: you need to install mujoco_py, and also perform the setup instructions here: https://github.com/openai/mujoco-py/.)".format(e))
class RobotEnv(gym.GoalEnv):
def __init__(self, model_path, initial_qpos, n_actions, n_substeps):
if model_path.startswith('/'):
fullpath = model_path
else:
fullpath = os.path.join(os.path.dirname(__file__), 'assets', model_path)
if not os.path.exists(fullpath):
raise IOError('File {} does not exist'.format(fullpath))
model = mujoco_py.load_model_from_path(fullpath)
self.sim = mujoco_py.MjSim(model, nsubsteps=n_substeps)
self.viewer = None
self.metadata = {
'render.modes': ['human', 'rgb_array'],
'video.frames_per_second': int(np.round(1.0 / self.dt))
}
self.seed()
self._env_setup(initial_qpos=initial_qpos)
self.initial_state = copy.deepcopy(self.sim.get_state())
self.goal = self._sample_goal()
obs = self._get_obs()
self.action_space = spaces.Box(-1., 1., shape=(n_actions,), dtype='float32')
self.observation_space = spaces.Dict(dict(
desired_goal=spaces.Box(-np.inf, np.inf, shape=obs['achieved_goal'].shape, dtype='float32'),
achieved_goal=spaces.Box(-np.inf, np.inf, shape=obs['achieved_goal'].shape, dtype='float32'),
observation=spaces.Box(-np.inf, np.inf, shape=obs['observation'].shape, dtype='float32'),
))
@property
def dt(self):
return self.sim.model.opt.timestep * self.sim.nsubsteps
# Env methods
# ----------------------------
def seed(self, seed=None):
self.np_random, seed = seeding.np_random(seed)
return [seed]
def step(self, action):
action = np.clip(action, self.action_space.low, self.action_space.high)
self._set_action(action)
self.sim.step()
self._step_callback()
obs = self._get_obs()
done = False
info = {
'is_success': self._is_success(obs['achieved_goal'], self.goal),
}
reward = self.compute_reward(obs['achieved_goal'], self.goal, info)
return obs, reward, done, info
def reset(self):
# Attempt to reset the simulator. Since we randomize initial conditions, it
# is possible to get into a state with numerical issues (e.g. due to penetration or
# Gimbel lock) or we may not achieve an initial condition (e.g. an object is within the hand).
# In this case, we just keep randomizing until we eventually achieve a valid initial
# configuration.
did_reset_sim = False
while not did_reset_sim:
did_reset_sim = self._reset_sim()
self.goal = self._sample_goal().copy()
obs = self._get_obs()
return obs
def close(self):
if self.viewer is not None:
self.viewer.finish()
self.viewer = None
def render(self, mode='human'):
self._render_callback()
if mode == 'rgb_array':
self._get_viewer().render()
# window size used for old mujoco-py:
width, height = 500, 500
data = self._get_viewer().read_pixels(width, height, depth=False)
# original image is upside-down, so flip it
return data[::-1, :, :]
elif mode == 'human':
self._get_viewer().render()
def _get_viewer(self):
if self.viewer is None:
self.viewer = mujoco_py.MjViewer(self.sim)
self._viewer_setup()
return self.viewer
# Extension methods
# ----------------------------
def _reset_sim(self):
"""Resets a simulation and indicates whether or not it was successful.
If a reset was unsuccessful (e.g. if a randomized state caused an error in the
simulation), this method should indicate such a failure by returning False.
In such a case, this method will be called again to attempt a the reset again.
"""
self.sim.set_state(self.initial_state)
self.sim.forward()
return True
def _get_obs(self):
"""Returns the observation.
"""
raise NotImplementedError()
def _set_action(self, action):
"""Applies the given action to the simulation.
"""
raise NotImplementedError()
def _is_success(self, achieved_goal, desired_goal):
"""Indicates whether or not the achieved goal successfully achieved the desired goal.
"""
raise NotImplementedError()
def _sample_goal(self):
"""Samples a new goal and returns it.
"""
raise NotImplementedError()
def _env_setup(self, initial_qpos):
"""Initial configuration of the environment. Can be used to configure initial state
and extract information from the simulation.
"""
pass
def _viewer_setup(self):
"""Initial configuration of the viewer. Can be used to set the camera position,
for example.
"""
pass
def _render_callback(self):
"""A custom callback that is called before rendering. Can be used
to implement custom visualizations.
"""
pass
def _step_callback(self):
"""A custom callback that is called after stepping the simulation. Can be used
to enforce additional constraints on the simulation state.
"""
pass

View File

@@ -0,0 +1,369 @@
# Copyright (c) 2009-2017, Matthew Brett and Christoph Gohlke
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# 1. Redistributions of source code must retain the above copyright notice,
# this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Many methods borrow heavily or entirely from transforms3d:
# https://github.com/matthew-brett/transforms3d
# They have mostly been modified to support batched operations.
import numpy as np
import itertools
'''
Rotations
=========
Note: these have caused many subtle bugs in the past.
Be careful while updating these methods and while using them in clever ways.
See MuJoCo documentation here: http://mujoco.org/book/modeling.html#COrientation
Conventions
-----------
- All functions accept batches as well as individual rotations
- All rotation conventions match respective MuJoCo defaults
- All angles are in radians
- Matricies follow LR convention
- Euler Angles are all relative with 'xyz' axes ordering
- See specific representation for more information
Representations
---------------
Euler
There are many euler angle frames -- here we will strive to use the default
in MuJoCo, which is eulerseq='xyz'.
This frame is a relative rotating frame, about x, y, and z axes in order.
Relative rotating means that after we rotate about x, then we use the
new (rotated) y, and the same for z.
Quaternions
These are defined in terms of rotation (angle) about a unit vector (x, y, z)
We use the following <q0, q1, q2, q3> convention:
q0 = cos(angle / 2)
q1 = sin(angle / 2) * x
q2 = sin(angle / 2) * y
q3 = sin(angle / 2) * z
This is also sometimes called qw, qx, qy, qz.
Note that quaternions are ambiguous, because we can represent a rotation by
angle about vector <x, y, z> and -angle about vector <-x, -y, -z>.
To choose between these, we pick "first nonzero positive", where we
make the first nonzero element of the quaternion positive.
This can result in mismatches if you're converting an quaternion that is not
"first nonzero positive" to a different representation and back.
Axis Angle
(Not currently implemented)
These are very straightforward. Rotation is angle about a unit vector.
XY Axes
(Not currently implemented)
We are given x axis and y axis, and z axis is cross product of x and y.
Z Axis
This is NOT RECOMMENDED. Defines a unit vector for the Z axis,
but rotation about this axis is not well defined.
Instead pick a fixed reference direction for another axis (e.g. X)
and calculate the other (e.g. Y = Z cross-product X),
then use XY Axes rotation instead.
SO3
(Not currently implemented)
While not supported by MuJoCo, this representation has a lot of nice features.
We expect to add support for these in the future.
TODO / Missing
--------------
- Rotation integration or derivatives (e.g. velocity conversions)
- More representations (SO3, etc)
- Random sampling (e.g. sample uniform random rotation)
- Performance benchmarks/measurements
- (Maybe) define everything as to/from matricies, for simplicity
'''
# For testing whether a number is close to zero
_FLOAT_EPS = np.finfo(np.float64).eps
_EPS4 = _FLOAT_EPS * 4.0
def euler2mat(euler):
""" Convert Euler Angles to Rotation Matrix. See rotation.py for notes """
euler = np.asarray(euler, dtype=np.float64)
assert euler.shape[-1] == 3, "Invalid shaped euler {}".format(euler)
ai, aj, ak = -euler[..., 2], -euler[..., 1], -euler[..., 0]
si, sj, sk = np.sin(ai), np.sin(aj), np.sin(ak)
ci, cj, ck = np.cos(ai), np.cos(aj), np.cos(ak)
cc, cs = ci * ck, ci * sk
sc, ss = si * ck, si * sk
mat = np.empty(euler.shape[:-1] + (3, 3), dtype=np.float64)
mat[..., 2, 2] = cj * ck
mat[..., 2, 1] = sj * sc - cs
mat[..., 2, 0] = sj * cc + ss
mat[..., 1, 2] = cj * sk
mat[..., 1, 1] = sj * ss + cc
mat[..., 1, 0] = sj * cs - sc
mat[..., 0, 2] = -sj
mat[..., 0, 1] = cj * si
mat[..., 0, 0] = cj * ci
return mat
def euler2quat(euler):
""" Convert Euler Angles to Quaternions. See rotation.py for notes """
euler = np.asarray(euler, dtype=np.float64)
assert euler.shape[-1] == 3, "Invalid shape euler {}".format(euler)
ai, aj, ak = euler[..., 2] / 2, -euler[..., 1] / 2, euler[..., 0] / 2
si, sj, sk = np.sin(ai), np.sin(aj), np.sin(ak)
ci, cj, ck = np.cos(ai), np.cos(aj), np.cos(ak)
cc, cs = ci * ck, ci * sk
sc, ss = si * ck, si * sk
quat = np.empty(euler.shape[:-1] + (4,), dtype=np.float64)
quat[..., 0] = cj * cc + sj * ss
quat[..., 3] = cj * sc - sj * cs
quat[..., 2] = -(cj * ss + sj * cc)
quat[..., 1] = cj * cs - sj * sc
return quat
def mat2euler(mat):
""" Convert Rotation Matrix to Euler Angles. See rotation.py for notes """
mat = np.asarray(mat, dtype=np.float64)
assert mat.shape[-2:] == (3, 3), "Invalid shape matrix {}".format(mat)
cy = np.sqrt(mat[..., 2, 2] * mat[..., 2, 2] + mat[..., 1, 2] * mat[..., 1, 2])
condition = cy > _EPS4
euler = np.empty(mat.shape[:-1], dtype=np.float64)
euler[..., 2] = np.where(condition,
-np.arctan2(mat[..., 0, 1], mat[..., 0, 0]),
-np.arctan2(-mat[..., 1, 0], mat[..., 1, 1]))
euler[..., 1] = np.where(condition,
-np.arctan2(-mat[..., 0, 2], cy),
-np.arctan2(-mat[..., 0, 2], cy))
euler[..., 0] = np.where(condition,
-np.arctan2(mat[..., 1, 2], mat[..., 2, 2]),
0.0)
return euler
def mat2quat(mat):
""" Convert Rotation Matrix to Quaternion. See rotation.py for notes """
mat = np.asarray(mat, dtype=np.float64)
assert mat.shape[-2:] == (3, 3), "Invalid shape matrix {}".format(mat)
Qxx, Qyx, Qzx = mat[..., 0, 0], mat[..., 0, 1], mat[..., 0, 2]
Qxy, Qyy, Qzy = mat[..., 1, 0], mat[..., 1, 1], mat[..., 1, 2]
Qxz, Qyz, Qzz = mat[..., 2, 0], mat[..., 2, 1], mat[..., 2, 2]
# Fill only lower half of symmetric matrix
K = np.zeros(mat.shape[:-2] + (4, 4), dtype=np.float64)
K[..., 0, 0] = Qxx - Qyy - Qzz
K[..., 1, 0] = Qyx + Qxy
K[..., 1, 1] = Qyy - Qxx - Qzz
K[..., 2, 0] = Qzx + Qxz
K[..., 2, 1] = Qzy + Qyz
K[..., 2, 2] = Qzz - Qxx - Qyy
K[..., 3, 0] = Qyz - Qzy
K[..., 3, 1] = Qzx - Qxz
K[..., 3, 2] = Qxy - Qyx
K[..., 3, 3] = Qxx + Qyy + Qzz
K /= 3.0
# TODO: vectorize this -- probably could be made faster
q = np.empty(K.shape[:-2] + (4,))
it = np.nditer(q[..., 0], flags=['multi_index'])
while not it.finished:
# Use Hermitian eigenvectors, values for speed
vals, vecs = np.linalg.eigh(K[it.multi_index])
# Select largest eigenvector, reorder to w,x,y,z quaternion
q[it.multi_index] = vecs[[3, 0, 1, 2], np.argmax(vals)]
# Prefer quaternion with positive w
# (q * -1 corresponds to same rotation as q)
if q[it.multi_index][0] < 0:
q[it.multi_index] *= -1
it.iternext()
return q
def quat2euler(quat):
""" Convert Quaternion to Euler Angles. See rotation.py for notes """
return mat2euler(quat2mat(quat))
def subtract_euler(e1, e2):
assert e1.shape == e2.shape
assert e1.shape[-1] == 3
q1 = euler2quat(e1)
q2 = euler2quat(e2)
q_diff = quat_mul(q1, quat_conjugate(q2))
return quat2euler(q_diff)
def quat2mat(quat):
""" Convert Quaternion to Euler Angles. See rotation.py for notes """
quat = np.asarray(quat, dtype=np.float64)
assert quat.shape[-1] == 4, "Invalid shape quat {}".format(quat)
w, x, y, z = quat[..., 0], quat[..., 1], quat[..., 2], quat[..., 3]
Nq = np.sum(quat * quat, axis=-1)
s = 2.0 / Nq
X, Y, Z = x * s, y * s, z * s
wX, wY, wZ = w * X, w * Y, w * Z
xX, xY, xZ = x * X, x * Y, x * Z
yY, yZ, zZ = y * Y, y * Z, z * Z
mat = np.empty(quat.shape[:-1] + (3, 3), dtype=np.float64)
mat[..., 0, 0] = 1.0 - (yY + zZ)
mat[..., 0, 1] = xY - wZ
mat[..., 0, 2] = xZ + wY
mat[..., 1, 0] = xY + wZ
mat[..., 1, 1] = 1.0 - (xX + zZ)
mat[..., 1, 2] = yZ - wX
mat[..., 2, 0] = xZ - wY
mat[..., 2, 1] = yZ + wX
mat[..., 2, 2] = 1.0 - (xX + yY)
return np.where((Nq > _FLOAT_EPS)[..., np.newaxis, np.newaxis], mat, np.eye(3))
def quat_conjugate(q):
inv_q = -q
inv_q[..., 0] *= -1
return inv_q
def quat_mul(q0, q1):
assert q0.shape == q1.shape
assert q0.shape[-1] == 4
assert q1.shape[-1] == 4
w0 = q0[..., 0]
x0 = q0[..., 1]
y0 = q0[..., 2]
z0 = q0[..., 3]
w1 = q1[..., 0]
x1 = q1[..., 1]
y1 = q1[..., 2]
z1 = q1[..., 3]
w = w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1
x = w0 * x1 + x0 * w1 + y0 * z1 - z0 * y1
y = w0 * y1 + y0 * w1 + z0 * x1 - x0 * z1
z = w0 * z1 + z0 * w1 + x0 * y1 - y0 * x1
q = np.array([w, x, y, z])
if q.ndim == 2:
q = q.swapaxes(0, 1)
assert q.shape == q0.shape
return q
def quat_rot_vec(q, v0):
q_v0 = np.array([0, v0[0], v0[1], v0[2]])
q_v = quat_mul(q, quat_mul(q_v0, quat_conjugate(q)))
v = q_v[1:]
return v
def quat_identity():
return np.array([1, 0, 0, 0])
def quat2axisangle(quat):
theta = 0;
axis = np.array([0, 0, 1]);
sin_theta = np.linalg.norm(quat[1:])
if (sin_theta > 0.0001):
theta = 2 * np.arcsin(sin_theta)
theta *= 1 if quat[0] >= 0 else -1
axis = quat[1:] / sin_theta
return axis, theta
def euler2point_euler(euler):
_euler = euler.copy()
if len(_euler.shape) < 2:
_euler = np.expand_dims(_euler,0)
assert(_euler.shape[1] == 3)
_euler_sin = np.sin(_euler)
_euler_cos = np.cos(_euler)
return np.concatenate([_euler_sin, _euler_cos], axis=-1)
def point_euler2euler(euler):
_euler = euler.copy()
if len(_euler.shape) < 2:
_euler = np.expand_dims(_euler,0)
assert(_euler.shape[1] == 6)
angle = np.arctan(_euler[..., :3] / _euler[..., 3:])
angle[_euler[..., 3:] < 0] += np.pi
return angle
def quat2point_quat(quat):
# Should be in qw, qx, qy, qz
_quat = quat.copy()
if len(_quat.shape) < 2:
_quat = np.expand_dims(_quat, 0)
assert(_quat.shape[1] == 4)
angle = np.arccos(_quat[:,[0]]) * 2
xyz = _quat[:, 1:]
xyz[np.squeeze(np.abs(np.sin(angle/2))) >= 1e-5] = (xyz / np.sin(angle / 2))[np.squeeze(np.abs(np.sin(angle/2))) >= 1e-5]
return np.concatenate([np.sin(angle),np.cos(angle), xyz], axis=-1)
def point_quat2quat(quat):
_quat = quat.copy()
if len(_quat.shape) < 2:
_quat = np.expand_dims(_quat, 0)
assert(_quat.shape[1] == 5)
angle = np.arctan(_quat[:,[0]] / _quat[:,[1]])
qw = np.cos(angle / 2)
qxyz = _quat[:, 2:]
qxyz[np.squeeze(np.abs(np.sin(angle/2))) >= 1e-5] = (qxyz * np.sin(angle/2))[np.squeeze(np.abs(np.sin(angle/2))) >= 1e-5]
return np.concatenate([qw, qxyz], axis=-1)
def normalize_angles(angles):
'''Puts angles in [-pi, pi] range.'''
angles = angles.copy()
if angles.size > 0:
angles = (angles + np.pi) % (2 * np.pi) - np.pi
assert -np.pi-1e-6 <= angles.min() and angles.max() <= np.pi+1e-6
return angles
def round_to_straight_angles(angles):
'''Returns closest angle modulo 90 degrees '''
angles = np.round(angles / (np.pi / 2)) * (np.pi / 2)
return normalize_angles(angles)
def get_parallel_rotations():
mult90 = [0, np.pi/2, -np.pi/2, np.pi]
parallel_rotations = []
for euler in itertools.product(mult90, repeat=3):
canonical = mat2euler(euler2mat(euler))
canonical = np.round(canonical / (np.pi / 2))
if canonical[0] == -2:
canonical[0] = 2
if canonical[2] == -2:
canonical[2] = 2
canonical *= np.pi / 2
if all([(canonical != rot).any() for rot in parallel_rotations]):
parallel_rotations += [canonical]
assert len(parallel_rotations) == 24
return parallel_rotations

View File

@@ -0,0 +1,96 @@
import numpy as np
from gym import error
try:
import mujoco_py
except ImportError as e:
raise error.DependencyNotInstalled("{}. (HINT: you need to install mujoco_py, and also perform the setup instructions here: https://github.com/openai/mujoco-py/.)".format(e))
def robot_get_obs(sim):
"""Returns all joint positions and velocities associated with
a robot.
"""
if sim.data.qpos is not None and sim.model.joint_names:
names = [n for n in sim.model.joint_names if n.startswith('robot')]
return (
np.array([sim.data.get_joint_qpos(name) for name in names]),
np.array([sim.data.get_joint_qvel(name) for name in names]),
)
return np.zeros(0), np.zeros(0)
def ctrl_set_action(sim, action):
"""For torque actuators it copies the action into mujoco ctrl field.
For position actuators it sets the target relative to the current qpos.
"""
if sim.model.nmocap > 0:
_, action = np.split(action, (sim.model.nmocap * 7, ))
if sim.data.ctrl is not None:
for i in range(action.shape[0]):
if sim.model.actuator_biastype[i] == 0:
sim.data.ctrl[i] = action[i]
else:
idx = sim.model.jnt_qposadr[sim.model.actuator_trnid[i, 0]]
sim.data.ctrl[i] = sim.data.qpos[idx] + action[i]
def mocap_set_action(sim, action):
"""The action controls the robot using mocaps. Specifically, bodies
on the robot (for example the gripper wrist) is controlled with
mocap bodies. In this case the action is the desired difference
in position and orientation (quaternion), in world coordinates,
of the of the target body. The mocap is positioned relative to
the target body according to the delta, and the MuJoCo equality
constraint optimizer tries to center the welded body on the mocap.
"""
if sim.model.nmocap > 0:
action, _ = np.split(action, (sim.model.nmocap * 7, ))
action = action.reshape(sim.model.nmocap, 7)
pos_delta = action[:, :3]
quat_delta = action[:, 3:]
reset_mocap2body_xpos(sim)
sim.data.mocap_pos[:] = sim.data.mocap_pos + pos_delta
sim.data.mocap_quat[:] = sim.data.mocap_quat + quat_delta
def reset_mocap_welds(sim):
"""Resets the mocap welds that we use for actuation.
"""
if sim.model.nmocap > 0 and sim.model.eq_data is not None:
for i in range(sim.model.eq_data.shape[0]):
if sim.model.eq_type[i] == mujoco_py.const.EQ_WELD:
sim.model.eq_data[i, :] = np.array(
[0., 0., 0., 1., 0., 0., 0.])
sim.forward()
def reset_mocap2body_xpos(sim):
"""Resets the position and orientation of the mocap bodies to the same
values as the bodies they're welded to.
"""
if (sim.model.eq_type is None or
sim.model.eq_obj1id is None or
sim.model.eq_obj2id is None):
return
for eq_type, obj1_id, obj2_id in zip(sim.model.eq_type,
sim.model.eq_obj1id,
sim.model.eq_obj2id):
if eq_type != mujoco_py.const.EQ_WELD:
continue
mocap_id = sim.model.body_mocapid[obj1_id]
if mocap_id != -1:
# obj1 is the mocap, obj2 is the welded body
body_idx = obj2_id
else:
# obj2 is the mocap, obj1 is the welded body
mocap_id = sim.model.body_mocapid[obj2_id]
body_idx = obj1_id
assert (mocap_id != -1)
sim.data.mocap_pos[mocap_id][:] = sim.data.body_xpos[body_idx]
sim.data.mocap_quat[mocap_id][:] = sim.data.body_xquat[body_idx]

View File

@@ -1 +1 @@
VERSION = '0.9.7'
VERSION = '0.10.0'

View File

@@ -1,3 +1,4 @@
from gym import error
from gym.wrappers.monitor import Monitor
from gym.wrappers.time_limit import TimeLimit
from gym.wrappers.dict import FlattenDictWrapper

28
gym/wrappers/dict.py Normal file
View File

@@ -0,0 +1,28 @@
import gym
import numpy as np
__all__ = ['FlattenDictWrapper']
class FlattenDictWrapper(gym.ObservationWrapper):
"""Flattens selected keys of a Dict observation space into
an array.
"""
def __init__(self, env, dict_keys):
super(FlattenDictWrapper, self).__init__(env)
self.dict_keys = dict_keys
# Figure out observation_space dimension.
size = 0
for key in dict_keys:
shape = self.env.observation_space.spaces[key].shape
size += np.prod(shape)
self.observation_space = gym.spaces.Box(-np.inf, np.inf, shape=(size,), dtype='float32')
def observation(self, observation):
assert isinstance(observation, dict)
obs = []
for key in self.dict_keys:
obs.append(observation[key].ravel())
return np.concatenate(obs)

View File

@@ -11,6 +11,7 @@ extras = {
'box2d': ['Box2D-kengz'],
'classic_control': ['PyOpenGL'],
'mujoco': ['mujoco_py>=1.50', 'imageio'],
'robotics': ['mujoco_py>=1.50', 'imageio'],
}
# Meta dependency groups.