mirror of
https://github.com/wassname/pyrobolearn.git
synced 2026-09-10 12:21:16 +08:00
update several classes: add copy/deepcopy methods (ongoing)
This commit is contained in:
@@ -4,10 +4,11 @@
|
||||
This file defines the `Action` class, which is returned by the policy and given to the environment.
|
||||
"""
|
||||
|
||||
import copy
|
||||
import collections
|
||||
# from abc import ABCMeta, abstractmethod
|
||||
import numpy as np
|
||||
import torch
|
||||
import collections
|
||||
from abc import ABCMeta, abstractmethod
|
||||
import gym
|
||||
|
||||
from pyrobolearn.utils.data_structures.orderedset import OrderedSet
|
||||
@@ -46,7 +47,7 @@ class Action(object):
|
||||
[2] "OpenAI gym": https://gym.openai.com/ and https://github.com/openai/gym
|
||||
"""
|
||||
|
||||
def __init__(self, actions=(), data=None, space=None, name=None):
|
||||
def __init__(self, actions=(), data=None, space=None, name=None, ticks=1):
|
||||
"""
|
||||
Initialize the action. The action contains some kind of data, or is a combination of other actions.
|
||||
|
||||
@@ -55,6 +56,7 @@ class Action(object):
|
||||
data)
|
||||
data (np.ndarray): data associated to this action
|
||||
space (gym.space): space associated with the given data
|
||||
ticks (int): number of ticks to sleep before setting the next action data.
|
||||
|
||||
Warning:
|
||||
Both arguments can not be provided to the action.
|
||||
@@ -85,19 +87,24 @@ class Action(object):
|
||||
self._distribution = None # for sampling
|
||||
self._normalizer = None
|
||||
self._noiser = None # for noise
|
||||
self._name = name
|
||||
self.name = name
|
||||
|
||||
# create ordered set which is useful if this action is a combination of multiple actions
|
||||
self._actions = OrderedSet()
|
||||
if self._data is None:
|
||||
self.add(actions)
|
||||
|
||||
# set ticks and counter
|
||||
self.cnt = 0
|
||||
self.ticks = int(ticks)
|
||||
|
||||
# reset action
|
||||
# self.reset()
|
||||
|
||||
##############################
|
||||
# Properties (Getter/Setter) #
|
||||
##############################
|
||||
|
||||
@property
|
||||
def actions(self):
|
||||
"""
|
||||
@@ -313,6 +320,8 @@ class Action(object):
|
||||
"""
|
||||
Set the name of the action.
|
||||
"""
|
||||
if name is None:
|
||||
name = self.__class__.__name__
|
||||
if not isinstance(name, str):
|
||||
raise TypeError("Expecting the name to be a string.")
|
||||
self._name = name
|
||||
@@ -370,20 +379,20 @@ class Action(object):
|
||||
"""
|
||||
return len(np.unique(self.dimension))
|
||||
|
||||
@property
|
||||
def distribution(self):
|
||||
"""
|
||||
Get the current distribution used when sampling the action
|
||||
"""
|
||||
pass
|
||||
|
||||
@distribution.setter
|
||||
def distribution(self, distribution):
|
||||
"""
|
||||
Set the distribution to the action.
|
||||
"""
|
||||
# check if distribution is discrete/continuous
|
||||
pass
|
||||
# @property
|
||||
# def distribution(self):
|
||||
# """
|
||||
# Get the current distribution used when sampling the action
|
||||
# """
|
||||
# return None
|
||||
#
|
||||
# @distribution.setter
|
||||
# def distribution(self, distribution):
|
||||
# """
|
||||
# Set the distribution to the action.
|
||||
# """
|
||||
# # check if distribution is discrete/continuous
|
||||
# pass
|
||||
|
||||
###########
|
||||
# Methods #
|
||||
@@ -440,12 +449,17 @@ class Action(object):
|
||||
Write the action values to the simulator for each action.
|
||||
This has to be overwritten by the child class.
|
||||
"""
|
||||
if self.has_data(): # write the current action
|
||||
self._write(data)
|
||||
else: # read each action
|
||||
if self.actions:
|
||||
for action, d in zip(self.actions, data):
|
||||
action._write(d)
|
||||
# if time to write
|
||||
if self.cnt % self.ticks == 0:
|
||||
|
||||
if self.has_data(): # write the current action
|
||||
self._write(data)
|
||||
else: # read each action
|
||||
if self.actions:
|
||||
for action, d in zip(self.actions, data):
|
||||
action._write(d)
|
||||
|
||||
self.cnt += 1
|
||||
|
||||
# return the data
|
||||
# return self.data
|
||||
@@ -687,24 +701,17 @@ class Action(object):
|
||||
# Operator Overloading #
|
||||
########################
|
||||
|
||||
def __repr__(self):
|
||||
def __str__(self):
|
||||
"""Return a string describing the action."""
|
||||
if self._data is None:
|
||||
lst = [self.__class__.__name__ + '(']
|
||||
for action in self.actions:
|
||||
lst.append('\t' + action.__repr__() + ',')
|
||||
lst.append('\t' + action.__str__() + ',')
|
||||
lst.append(')')
|
||||
return '\n'.join(lst)
|
||||
else:
|
||||
return '%s(%s)' % (self.name, self._data)
|
||||
|
||||
# def __str__(self):
|
||||
# """
|
||||
# String to represent the action. Need to be provided by each child class.
|
||||
# """
|
||||
# if self._data is None:
|
||||
# return [str(action) for action in self._actions]
|
||||
# return str(self)
|
||||
|
||||
def __call__(self, data=None):
|
||||
"""
|
||||
Compute/read the action and return it. It is an alias to the `self.write()` method.
|
||||
@@ -871,15 +878,16 @@ class Action(object):
|
||||
def __sub__(self, other):
|
||||
"""
|
||||
Remove the other action(s) from the current action.
|
||||
:param other:
|
||||
:return:
|
||||
|
||||
Args:
|
||||
other (Action): action to be removed.
|
||||
"""
|
||||
if not isinstance(other, Action):
|
||||
raise TypeError("Expecting another action, instead got {}".format(type(other)))
|
||||
s1 = self._actions if self._data is None else OrderedSet([self])
|
||||
s2 = other._actions if other._data is None else OrderedSet([other])
|
||||
s = s1 - s2
|
||||
if len(s) == 1: # just one element
|
||||
if len(s) == 1: # just one element
|
||||
return s[0]
|
||||
return Action(s)
|
||||
|
||||
@@ -888,7 +896,7 @@ class Action(object):
|
||||
Remove one or several actions from the combined action.
|
||||
|
||||
Args:
|
||||
other:
|
||||
other (Action): action to be removed.
|
||||
"""
|
||||
if not isinstance(other, Action):
|
||||
raise TypeError("Expecting another action, instead got {}".format(type(other)))
|
||||
@@ -896,3 +904,25 @@ class Action(object):
|
||||
raise RuntimeError("This operation is only available for a combined action")
|
||||
s = other._actions if other._data is None else OrderedSet([other])
|
||||
self._actions -= s
|
||||
|
||||
def __copy__(self):
|
||||
"""Return a shallow copy of the action. This can be overridden in the child class."""
|
||||
return self.__class__(actions=self.actions, data=self._data, space=self._space, name=self.name,
|
||||
ticks=self.ticks)
|
||||
|
||||
def __deepcopy__(self, memo={}):
|
||||
"""Return a deep copy of the action. This can be overridden in the child class.
|
||||
|
||||
Args:
|
||||
memo (dict): memo dictionary of objects already copied during the current copying pass
|
||||
"""
|
||||
actions = [copy.deepcopy(action, memo) for action in self.actions]
|
||||
data = copy.deepcopy(self._data)
|
||||
space = copy.deepcopy(self._space)
|
||||
action = self.__class__(actions=actions, data=data, space=space, name=self.name, ticks=self.ticks)
|
||||
|
||||
# update the memodict (note that `copy.deepcopy` will automatically check this dictionary and return the
|
||||
# reference if already present)
|
||||
memo[self] = action
|
||||
|
||||
return action
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
This includes notably the fixed and functional actions.
|
||||
"""
|
||||
|
||||
import numpy as np
|
||||
import copy
|
||||
|
||||
from pyrobolearn.actions import Action
|
||||
|
||||
@@ -31,6 +31,21 @@ class FixedAction(Action):
|
||||
def _write(self, data=None):
|
||||
pass
|
||||
|
||||
def __copy__(self):
|
||||
"""Return a shallow copy of the action. This can be overridden in the child class."""
|
||||
return self.__class__(value=self._data)
|
||||
|
||||
def __deepcopy__(self, memo={}):
|
||||
"""Return a deep copy of the action. This can be overridden in the child class.
|
||||
|
||||
Args:
|
||||
memo (dict): memo dictionary of objects already copied during the current copying pass
|
||||
"""
|
||||
data = copy.deepcopy(self._data)
|
||||
action = self.__class__(value=data)
|
||||
memo[self] = action
|
||||
return action
|
||||
|
||||
|
||||
class FunctionalAction(Action):
|
||||
r"""Functional Action.
|
||||
@@ -45,3 +60,18 @@ class FunctionalAction(Action):
|
||||
def _write(self, data=None):
|
||||
self.data = self.function(data)
|
||||
|
||||
def __copy__(self):
|
||||
"""Return a shallow copy of the action. This can be overridden in the child class."""
|
||||
return self.__class__(function=self.function, data=self._data)
|
||||
|
||||
def __deepcopy__(self, memo={}):
|
||||
"""Return a deep copy of the action. This can be overridden in the child class.
|
||||
|
||||
Args:
|
||||
memo (dict): memo dictionary of objects already copied during the current copying pass
|
||||
"""
|
||||
function = copy.deepcopy(self.function)
|
||||
data = copy.deepcopy(self._data)
|
||||
action = self.__class__(function=function, initial_data=data)
|
||||
memo[self] = action
|
||||
return action
|
||||
|
||||
@@ -7,6 +7,7 @@ from the gym environment, and keep it as an attribute of the class. This can the
|
||||
the various policies defined in the pyrobolearn framework.
|
||||
"""
|
||||
|
||||
import copy
|
||||
import gym
|
||||
|
||||
from pyrobolearn.actions.action import Action
|
||||
@@ -48,6 +49,21 @@ class GymAction(Action):
|
||||
def _write(self, data=None):
|
||||
pass
|
||||
|
||||
def __copy__(self):
|
||||
"""Return a shallow copy of the action. This can be overridden in the child class."""
|
||||
return self.__class__(gym_env=self.env)
|
||||
|
||||
def __deepcopy__(self, memo={}):
|
||||
"""Return a deep copy of the action. This can be overridden in the child class.
|
||||
|
||||
Args:
|
||||
memo (dict): memo dictionary of objects already copied during the current copying pass
|
||||
"""
|
||||
env = copy.deepcopy(self.env)
|
||||
action = self.__class__(gym_env=env)
|
||||
memo[self] = action
|
||||
return action
|
||||
|
||||
|
||||
# Tests
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
This includes notably the joint positions, velocities, and force/torque actions.
|
||||
"""
|
||||
|
||||
import copy
|
||||
import numpy as np
|
||||
from abc import ABCMeta
|
||||
|
||||
@@ -49,6 +50,22 @@ class JointAction(RobotAction):
|
||||
def bounds(self):
|
||||
return self.robot.get_joint_limits(self.joints)
|
||||
|
||||
def __copy__(self):
|
||||
"""Return a shallow copy of the action. This can be overridden in the child class."""
|
||||
return self.__class__(robot=self.robot, joint_ids=self.joints)
|
||||
|
||||
def __deepcopy__(self, memo={}):
|
||||
"""Return a deep copy of the action. This can be overridden in the child class.
|
||||
|
||||
Args:
|
||||
memo (dict): memo dictionary of objects already copied during the current copying pass
|
||||
"""
|
||||
robot = copy.deepcopy(self.robot, memo)
|
||||
joints = copy.deepcopy(self.joints)
|
||||
action = self.__class__(robot=robot, joint_ids=joints)
|
||||
memo[self] = action
|
||||
return action
|
||||
|
||||
|
||||
class JointPositionAction(JointAction):
|
||||
r"""Joint Position Action
|
||||
@@ -67,6 +84,25 @@ class JointPositionAction(JointAction):
|
||||
else:
|
||||
self.robot.set_joint_positions(data, self.joints, kp=self.kp, kd=self.kd, forces=self.max_force)
|
||||
|
||||
def __copy__(self):
|
||||
"""Return a shallow copy of the action. This can be overridden in the child class."""
|
||||
return self.__class__(robot=self.robot, joint_ids=self.joints, kp=self.kp, kd=self.kd, max_force=self.max_force)
|
||||
|
||||
def __deepcopy__(self, memo={}):
|
||||
"""Return a deep copy of the action. This can be overridden in the child class.
|
||||
|
||||
Args:
|
||||
memo (dict): memo dictionary of objects already copied during the current copying pass
|
||||
"""
|
||||
robot = copy.deepcopy(self.robot, memo)
|
||||
joints = copy.deepcopy(self.joints)
|
||||
kp = copy.deepcopy(self.kp)
|
||||
kd = copy.deepcopy(self.kd)
|
||||
max_force = copy.deepcopy(self.max_force)
|
||||
action = self.__class__(robot=robot, joint_ids=joints, kp=kp, kd=kd, max_force=max_force)
|
||||
memo[self] = action
|
||||
return action
|
||||
|
||||
|
||||
class JointVelocityAction(JointAction):
|
||||
r"""Joint Velocity Action
|
||||
@@ -107,6 +143,25 @@ class JointPositionAndVelocityAction(JointAction):
|
||||
self.robot.set_joint_positions(data[:self.idx], self.joints, kp=self.kp, kd=self.kd,
|
||||
velocities=data[self.idx:], forces=self.max_force)
|
||||
|
||||
def __copy__(self):
|
||||
"""Return a shallow copy of the action. This can be overridden in the child class."""
|
||||
return self.__class__(robot=self.robot, joint_ids=self.joints, kp=self.kp, kd=self.kd, max_force=self.max_force)
|
||||
|
||||
def __deepcopy__(self, memo={}):
|
||||
"""Return a deep copy of the action. This can be overridden in the child class.
|
||||
|
||||
Args:
|
||||
memo (dict): memo dictionary of objects already copied during the current copying pass
|
||||
"""
|
||||
robot = copy.deepcopy(self.robot, memo)
|
||||
joints = copy.deepcopy(self.joints)
|
||||
kp = copy.deepcopy(self.kp)
|
||||
kd = copy.deepcopy(self.kd)
|
||||
max_force = copy.deepcopy(self.max_force)
|
||||
action = self.__class__(robot=robot, joint_ids=joints, kp=kp, kd=kd, max_force=max_force)
|
||||
memo[self] = action
|
||||
return action
|
||||
|
||||
|
||||
# class JointPositionVelocityAccelerationAction(JointAction):
|
||||
# r"""Set the joint positions, velocities, and accelerations.
|
||||
@@ -136,6 +191,24 @@ class JointForceAction(JointAction):
|
||||
data = np.clip(data, self.f_min, self.f_max)
|
||||
self.robot.set_joint_torques(data, self.joints)
|
||||
|
||||
def __copy__(self):
|
||||
"""Return a shallow copy of the action. This can be overridden in the child class."""
|
||||
return self.__class__(robot=self.robot, joint_ids=self.joints, f_min=self.f_min, f_max=self.f_max)
|
||||
|
||||
def __deepcopy__(self, memo={}):
|
||||
"""Return a deep copy of the action. This can be overridden in the child class.
|
||||
|
||||
Args:
|
||||
memo (dict): memo dictionary of objects already copied during the current copying pass
|
||||
"""
|
||||
robot = copy.deepcopy(self.robot, memo)
|
||||
joints = copy.deepcopy(self.joints)
|
||||
f_min = copy.deepcopy(self.f_min)
|
||||
f_max = copy.deepcopy(self.f_max)
|
||||
action = self.__class__(robot=robot, joint_ids=joints, f_min=f_min, f_max=f_max)
|
||||
memo[self] = action
|
||||
return action
|
||||
|
||||
|
||||
class JointAccelerationAction(JointAction):
|
||||
r"""Joint Acceleration Action
|
||||
@@ -157,3 +230,21 @@ class JointAccelerationAction(JointAction):
|
||||
else:
|
||||
data = np.clip(data, self.a_min, self.a_max)
|
||||
self.robot.set_joint_accelerations(data, self.joints)
|
||||
|
||||
def __copy__(self):
|
||||
"""Return a shallow copy of the action. This can be overridden in the child class."""
|
||||
return self.__class__(robot=self.robot, joint_ids=self.joints, a_min=self.a_min, a_max=self.a_max)
|
||||
|
||||
def __deepcopy__(self, memo={}):
|
||||
"""Return a deep copy of the action. This can be overridden in the child class.
|
||||
|
||||
Args:
|
||||
memo (dict): memo dictionary of objects already copied during the current copying pass
|
||||
"""
|
||||
robot = copy.deepcopy(self.robot, memo)
|
||||
joints = copy.deepcopy(self.joints)
|
||||
a_min = copy.deepcopy(self.a_min)
|
||||
a_max = copy.deepcopy(self.a_max)
|
||||
action = self.__class__(robot=robot, joint_ids=joints, f_min=a_min, f_max=a_max)
|
||||
memo[self] = action
|
||||
return action
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
This includes notably the link positions, velocities, and force/torque actions.
|
||||
"""
|
||||
|
||||
import copy
|
||||
from abc import ABCMeta
|
||||
|
||||
from pyrobolearn.actions.robot_actions.robot_actions import RobotAction
|
||||
@@ -30,7 +31,7 @@ class LinkAction(RobotAction):
|
||||
|
||||
Args:
|
||||
robot (Robot): robot instance
|
||||
jointIds (int, int[N]): joint id or list of joint ids
|
||||
link_ids (int, int[N]): link id or list of link ids
|
||||
"""
|
||||
super(LinkAction, self).__init__(robot)
|
||||
|
||||
@@ -39,12 +40,29 @@ class LinkAction(RobotAction):
|
||||
link_ids = robot.get_link_ids()
|
||||
self.links = link_ids
|
||||
|
||||
def __copy__(self):
|
||||
"""Return a shallow copy of the action. This can be overridden in the child class."""
|
||||
return self.__class__(self.robot, self.links)
|
||||
|
||||
def __deepcopy__(self, memo={}):
|
||||
"""Return a deep copy of the action. This can be overridden in the child class.
|
||||
|
||||
Args:
|
||||
memo (dict): memo dictionary of objects already copied during the current copying pass
|
||||
"""
|
||||
robot = copy.deepcopy(self.robot, memo)
|
||||
links = copy.deepcopy(self.links)
|
||||
action = self.__class__(robot, links)
|
||||
memo[self] = action
|
||||
return action
|
||||
|
||||
|
||||
class LinkPositionAction(LinkAction):
|
||||
r"""Link position action
|
||||
|
||||
Set the link position(s) using IK.
|
||||
"""
|
||||
|
||||
def __init__(self, robot, link_ids=None):
|
||||
super(LinkPositionAction, self).__init__(robot, link_ids)
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ Dependencies:
|
||||
- `pyrobolearn.robots`
|
||||
"""
|
||||
|
||||
import copy
|
||||
from abc import ABCMeta
|
||||
|
||||
from pyrobolearn.actions import Action
|
||||
@@ -47,3 +48,18 @@ class RobotAction(Action):
|
||||
|
||||
def is_continuous(self):
|
||||
return True
|
||||
|
||||
def __copy__(self):
|
||||
"""Return a shallow copy of the action. This can be overridden in the child class."""
|
||||
return self.__class__(robot=self.robot)
|
||||
|
||||
def __deepcopy__(self, memo={}):
|
||||
"""Return a deep copy of the action. This can be overridden in the child class.
|
||||
|
||||
Args:
|
||||
memo (dict): memo dictionary of objects already copied during the current copying pass
|
||||
"""
|
||||
robot = copy.deepcopy(self.robot, memo)
|
||||
action = self.__class__(robot=robot)
|
||||
memo[self] = action
|
||||
return action
|
||||
|
||||
@@ -8,6 +8,7 @@ Dependencies:
|
||||
- `pyrobolearn.values`
|
||||
"""
|
||||
|
||||
import copy
|
||||
import itertools
|
||||
import torch
|
||||
|
||||
@@ -143,6 +144,35 @@ class ActorCritic(object):
|
||||
value = self.evaluate(state, to_numpy=to_numpy)
|
||||
return action, value
|
||||
|
||||
#############
|
||||
# Operators #
|
||||
#############
|
||||
|
||||
def __str__(self):
|
||||
"""Return a string describing the object."""
|
||||
return self.__class__.__name__
|
||||
|
||||
def __copy__(self):
|
||||
"""Return a shallow copy of the approximator. This can be overridden in the child class."""
|
||||
return self.__class__(policy=self.actor, value=self.critic)
|
||||
|
||||
def __deepcopy__(self, memo={}):
|
||||
"""Return a deep copy of the approximator. This can be overridden in the child class.
|
||||
|
||||
Args:
|
||||
memo (dict): memo dictionary of objects already copied during the current copying pass
|
||||
"""
|
||||
policy = copy.deepcopy(self.actor, memo) if isinstance(self.actor, Policy) else copy.deepcopy(self.actor)
|
||||
value = copy.deepcopy(self.critic, memo) if isinstance(self.critic, ValueApproximator) \
|
||||
else copy.deepcopy(self.critic)
|
||||
actor_critic = self.__class__(policy=policy, value=value)
|
||||
|
||||
# update the memodict (note that `copy.deepcopy` will automatically check this dictionary and return the
|
||||
# reference if already present)
|
||||
memo[self] = actor_critic
|
||||
|
||||
return actor_critic
|
||||
|
||||
|
||||
class SharedActorCritic(object):
|
||||
r"""Shared Actor Critic
|
||||
|
||||
@@ -10,6 +10,7 @@ Dependencies:
|
||||
- `pyrobolearn.actions`
|
||||
"""
|
||||
|
||||
import copy
|
||||
import collections
|
||||
import numpy as np
|
||||
import torch
|
||||
@@ -313,7 +314,8 @@ class Approximator(object):
|
||||
"""
|
||||
return self.model.is_generative()
|
||||
|
||||
def _size(self, x):
|
||||
@staticmethod
|
||||
def _size(x):
|
||||
"""Return the total size of a `State`, `Action`, numpy.array, or torch.Tensor."""
|
||||
size = 0
|
||||
if isinstance(x, (State, Action)):
|
||||
@@ -381,7 +383,8 @@ class Approximator(object):
|
||||
processor.reset()
|
||||
self.model.reset()
|
||||
|
||||
def __convert_to_numpy(self, x, to_numpy=True):
|
||||
@staticmethod
|
||||
def __convert_to_numpy(x, to_numpy=True):
|
||||
"""Convert the given argument to a numpy array if specified."""
|
||||
if to_numpy and isinstance(x, torch.Tensor):
|
||||
if x.requires_grad:
|
||||
@@ -389,7 +392,8 @@ class Approximator(object):
|
||||
return x.numpy()
|
||||
return x
|
||||
|
||||
def merge_inputs(self, x=None, to_numpy=True):
|
||||
@staticmethod
|
||||
def merge_inputs(x=None, to_numpy=True):
|
||||
"""
|
||||
Merge the inputs of the approximator.
|
||||
|
||||
@@ -503,14 +507,53 @@ class Approximator(object):
|
||||
"""Predict the output using the inner learning model given the input."""
|
||||
return self.predict(x)
|
||||
|
||||
def __repr__(self):
|
||||
"""Return a representation of the model."""
|
||||
return self.model.__str__()
|
||||
# def __repr__(self):
|
||||
# """Return a representation of the model."""
|
||||
# return self.model.__str__()
|
||||
|
||||
def __str__(self):
|
||||
"""Return a string describing the model."""
|
||||
return self.model.__str__()
|
||||
|
||||
def __copy__(self):
|
||||
"""Return a shallow copy of the approximator. This can be overridden in the child class."""
|
||||
return self.__class__(inputs=self.inputs, outputs=self.outputs, model=self.model,
|
||||
preprocessors=self.preprocessors, postprocessors=self.postprocessors)
|
||||
|
||||
def __deepcopy__(self, memo={}):
|
||||
"""Return a deep copy of the approximator. This can be overridden in the child class.
|
||||
|
||||
Args:
|
||||
memo (dict): memo dictionary of objects already copied during the current copying pass
|
||||
"""
|
||||
def get_inputs_outputs(items):
|
||||
if isinstance(items, list):
|
||||
elements = []
|
||||
for item in items:
|
||||
if isinstance(item, (Action, State)):
|
||||
elements.append(copy.deepcopy(item, memo))
|
||||
else:
|
||||
elements.append(copy.deepcopy(item))
|
||||
elif isinstance(items, (Action, State)):
|
||||
elements = copy.deepcopy(items, memo)
|
||||
else:
|
||||
elements = copy.deepcopy(items)
|
||||
return elements
|
||||
|
||||
inputs = get_inputs_outputs(self.inputs)
|
||||
outputs = get_inputs_outputs(self.outputs)
|
||||
model = copy.deepcopy(self.model, memo) if self.model is not None else None
|
||||
preprocessors = [copy.deepcopy(preprocessor, memo) for preprocessor in self.preprocessors]
|
||||
postprocessors = [copy.deepcopy(postprocessor, memo) for postprocessor in self.postprocessors]
|
||||
approximator = self.__class__(inputs=inputs, outputs=outputs, model=model,
|
||||
preprocessors=preprocessors, postprocessors=postprocessors)
|
||||
|
||||
# update the memodict (note that `copy.deepcopy` will automatically check this dictionary and return the
|
||||
# reference if already present)
|
||||
memo[self] = approximator
|
||||
|
||||
return approximator
|
||||
|
||||
|
||||
# Tests
|
||||
if __name__ == '__main__':
|
||||
|
||||
@@ -27,24 +27,24 @@ class LinearDynamicModel(ParametrizedDynamicModel):
|
||||
Cons: very limited
|
||||
"""
|
||||
|
||||
def __init__(self, states, actions, next_states=None, distributions=None, preprocessors=None, postprocessors=None):
|
||||
def __init__(self, state, action, next_state=None, distributions=None, preprocessors=None, postprocessors=None):
|
||||
"""
|
||||
Initialize the linear dynamic transition function / probability :math:`p(s_{t+1} | s_t, a_t)`.
|
||||
|
||||
Args:
|
||||
states (State): state inputs.
|
||||
actions (Action): action inputs.
|
||||
next_states (State, None): state outputs. If None, it will take the state inputs as the outputs.
|
||||
state (State): state inputs.
|
||||
action (Action): action inputs.
|
||||
next_state (State, None): state outputs. If None, it will take the state inputs as the outputs.
|
||||
distributions (torch.distributions.Distribution): distribution to use to sample the next state. If None,
|
||||
it will be deterministic.
|
||||
preprocessors (Processor, list of Processor, None): pre-processors to be applied to the given input
|
||||
postprocessors (Processor, list of Processor, None): post-processors to be applied to the output
|
||||
"""
|
||||
if next_states is None:
|
||||
next_states = states
|
||||
model = LinearApproximator(inputs=[states, actions], outputs=next_states, preprocessors=preprocessors,
|
||||
if next_state is None:
|
||||
next_state = state
|
||||
model = LinearApproximator(inputs=[state, action], outputs=next_state, preprocessors=preprocessors,
|
||||
postprocessors=postprocessors)
|
||||
super(LinearDynamicModel, self).__init__(states, actions, model=model, next_states=next_states,
|
||||
super(LinearDynamicModel, self).__init__(state, action, model=model, next_state=next_state,
|
||||
distributions=distributions)
|
||||
|
||||
|
||||
@@ -55,14 +55,14 @@ class PieceWiseLinearDynamicModel(ParametrizedDynamicModel):
|
||||
Cons: poor scalability
|
||||
"""
|
||||
|
||||
def __init__(self, states, actions, next_states=None, distributions=None, preprocessors=None, postprocessors=None):
|
||||
def __init__(self, state, action, next_state=None, distributions=None, preprocessors=None, postprocessors=None):
|
||||
"""
|
||||
Initialize the piece wise linear dynamic transition function / probability :math:`p(s_{t+1} | s_t, a_t)`.
|
||||
|
||||
Args:
|
||||
states (State): state inputs.
|
||||
actions (Action): action inputs.
|
||||
next_states (State, None): state outputs. If None, it will take the state inputs as the outputs.
|
||||
state (State): state inputs.
|
||||
action (Action): action inputs.
|
||||
next_state (State, None): state outputs. If None, it will take the state inputs as the outputs.
|
||||
distributions (torch.distributions.Distribution): distribution to use to sample the next state. If None,
|
||||
it will be deterministic.
|
||||
preprocessors (Processor, list of Processor, None): pre-processors to be applied to the given input
|
||||
@@ -70,5 +70,5 @@ class PieceWiseLinearDynamicModel(ParametrizedDynamicModel):
|
||||
"""
|
||||
# TODO
|
||||
model = None
|
||||
super(PieceWiseLinearDynamicModel, self).__init__(states, actions, model=model, next_states=next_states,
|
||||
super(PieceWiseLinearDynamicModel, self).__init__(state, action, model=model, next_state=next_state,
|
||||
distributions=distributions)
|
||||
|
||||
@@ -10,8 +10,9 @@ Dependencies:
|
||||
- `pyrobolearn.approximators` (and thus `pyrobolearn.models`)
|
||||
"""
|
||||
|
||||
from abc import ABCMeta, abstractmethod
|
||||
import copy
|
||||
import collections
|
||||
from abc import ABCMeta, abstractmethod
|
||||
import numpy as np
|
||||
import torch
|
||||
|
||||
@@ -74,24 +75,24 @@ class DynamicModel(object):
|
||||
"""
|
||||
__metaclass__ = ABCMeta
|
||||
|
||||
def __init__(self, states, actions, next_states=None, preprocessors=None, postprocessors=None):
|
||||
def __init__(self, state, action, next_state=None, preprocessors=None, postprocessors=None):
|
||||
"""
|
||||
Initialize the dynamic transition probability :math:`p(s_{t+1} | s_t, a_t)`, or dynamic transition function
|
||||
:math:`s_{t+1} = f(s_t, a_t)`.
|
||||
|
||||
Args:
|
||||
states (State): state inputs.
|
||||
actions (Action): action inputs.
|
||||
next_states (State, None): state outputs. If None, it will take the state inputs as the outputs.
|
||||
state (State): state inputs.
|
||||
action (Action): action inputs.
|
||||
next_state (State, None): state outputs. If None, it will take the state inputs as the outputs.
|
||||
preprocessors (Processor, list of Processor, None): pre-processors to be applied to the given input
|
||||
postprocessors (Processor, list of Processor, None): post-processors to be applied to the output
|
||||
"""
|
||||
# set inputs
|
||||
self.states = states
|
||||
self.actions = actions
|
||||
self.state = state
|
||||
self.action = action
|
||||
|
||||
# set outputs
|
||||
self.next_states = next_states
|
||||
self.next_state = next_state
|
||||
self.state_data = None
|
||||
|
||||
# preprocessors and postprocessors
|
||||
@@ -112,43 +113,43 @@ class DynamicModel(object):
|
||||
##############
|
||||
|
||||
@property
|
||||
def states(self):
|
||||
def state(self):
|
||||
"""Return the state instance."""
|
||||
return self._states
|
||||
return self._state
|
||||
|
||||
@states.setter
|
||||
def states(self, states):
|
||||
@state.setter
|
||||
def state(self, state):
|
||||
"""Set the states."""
|
||||
if not isinstance(states, State):
|
||||
raise TypeError("Expecting the given states to be an instance of `State`, instead got: "
|
||||
"{}".format(type(states)))
|
||||
self._states = states
|
||||
if not isinstance(state, State):
|
||||
raise TypeError("Expecting the given state to be an instance of `State`, instead got: "
|
||||
"{}".format(type(state)))
|
||||
self._state = state
|
||||
|
||||
@property
|
||||
def actions(self):
|
||||
def action(self):
|
||||
"""Return thge action instance."""
|
||||
return self._actions
|
||||
return self._action
|
||||
|
||||
@actions.setter
|
||||
def actions(self, actions):
|
||||
@action.setter
|
||||
def action(self, action):
|
||||
"""Set the actions."""
|
||||
if not isinstance(actions, Action):
|
||||
raise TypeError("Expecting the given actions to be an instance of `Action`, instead got: "
|
||||
"{}".format(type(actions)))
|
||||
self._actions = actions
|
||||
if not isinstance(action, Action):
|
||||
raise TypeError("Expecting the given action to be an instance of `Action`, instead got: "
|
||||
"{}".format(type(action)))
|
||||
self._action = action
|
||||
|
||||
@property
|
||||
def next_states(self):
|
||||
def next_state(self):
|
||||
"""Return the next state instance."""
|
||||
return self._next_states
|
||||
|
||||
@next_states.setter
|
||||
def next_states(self, states):
|
||||
@next_state.setter
|
||||
def next_state(self, states):
|
||||
"""Set the next states."""
|
||||
if states is None:
|
||||
states = self.states
|
||||
states = self.state
|
||||
elif not isinstance(states, State):
|
||||
raise TypeError("Expecting the given next_states to be an instance of `State`, instead got: "
|
||||
raise TypeError("Expecting the given next_state to be an instance of `State`, instead got: "
|
||||
"{}".format(type(states)))
|
||||
self._next_states = states
|
||||
|
||||
@@ -214,7 +215,7 @@ class DynamicModel(object):
|
||||
state_data = [state_data]
|
||||
|
||||
# go through each state and data
|
||||
for idx, (state, data) in enumerate(zip(self.states, state_data)):
|
||||
for idx, (state, data) in enumerate(zip(self.state, state_data)):
|
||||
if state.is_discrete(): # discrete state
|
||||
if isinstance(data, np.ndarray): # data state is a numpy array
|
||||
# check if given logits or not
|
||||
@@ -289,6 +290,14 @@ class DynamicModel(object):
|
||||
"""
|
||||
pass
|
||||
|
||||
#############
|
||||
# Operators #
|
||||
#############
|
||||
|
||||
def __str__(self):
|
||||
"""Return a representation string about the object."""
|
||||
return self.__class__.__name__
|
||||
|
||||
def __call__(self, states=None, actions=None, deterministic=False, to_numpy=True, set_state_data=True):
|
||||
"""
|
||||
Return predicted next state given the current state and action.
|
||||
@@ -307,6 +316,27 @@ class DynamicModel(object):
|
||||
return self.predict(states=states, actions=actions, deterministic=deterministic, to_numpy=to_numpy,
|
||||
set_state_data=set_state_data)
|
||||
|
||||
def __copy__(self):
|
||||
"""Return a shallow copy of the dynamic model. This can be overridden in the child class."""
|
||||
return self.__class__(state=self.state, action=self.action, next_state=self.next_state,
|
||||
preprocessors=self.preprocessors, postprocessors=self.postprocessors)
|
||||
|
||||
def __deepcopy__(self, memo={}):
|
||||
"""Return a deep copy of the dynamic model. This can be overridden in the child class.
|
||||
|
||||
Args:
|
||||
memo (dict): memo dictionary of objects already copied during the current copying pass
|
||||
"""
|
||||
state = copy.deepcopy(self.state, memo)
|
||||
action = copy.deepcopy(self.action, memo)
|
||||
next_state = copy.deepcopy(self.next_state, memo)
|
||||
preprocessors = [copy.deepcopy(preprocessor, memo) for preprocessor in self.preprocessors]
|
||||
postprocessors = [copy.deepcopy(postprocessor, memo) for postprocessor in self.postprocessors]
|
||||
dynamic = self.__class__(state=state, action=action, next_state=next_state, preprocessors=preprocessors,
|
||||
postprocessors=postprocessors)
|
||||
memo[self] = dynamic
|
||||
return dynamic
|
||||
|
||||
|
||||
class ParametrizedDynamicModel(DynamicModel):
|
||||
r"""Learnable Parametrized Dynamic Model
|
||||
@@ -314,23 +344,23 @@ class ParametrizedDynamicModel(DynamicModel):
|
||||
Dynamic model that can be trained.
|
||||
"""
|
||||
|
||||
def __init__(self, states, actions, model, next_states=None, distributions=None, preprocessors=None,
|
||||
def __init__(self, state, action, model, next_state=None, distributions=None, preprocessors=None,
|
||||
postprocessors=None):
|
||||
"""
|
||||
Initialize the dynamic transition probability :math:`p(s_{t+1} | s_t, a_t)`.
|
||||
|
||||
Args:
|
||||
states (State): state inputs.
|
||||
actions (Action): action inputs.
|
||||
state (State): state inputs.
|
||||
action (Action): action inputs.
|
||||
model (Approximator): approximator (inner learning model).
|
||||
next_states (State, None): state outputs. If None, it will take the state inputs as the outputs.
|
||||
next_state (State, None): state outputs. If None, it will take the state inputs as the outputs.
|
||||
distributions ((list of) torch.distributions.Distribution, None): distribution to use to sample the next
|
||||
state. If None, it will be deterministic if the model is deterministic.
|
||||
preprocessors (Processor, list of Processor, None): pre-processors to be applied to the given input
|
||||
postprocessors (Processor, list of Processor, None): post-processors to be applied to the output
|
||||
"""
|
||||
# set inner model
|
||||
super(ParametrizedDynamicModel, self).__init__(states, actions, next_states, preprocessors=preprocessors,
|
||||
super(ParametrizedDynamicModel, self).__init__(state, action, next_state, preprocessors=preprocessors,
|
||||
postprocessors=postprocessors)
|
||||
self.model = model
|
||||
self.distributions = distributions
|
||||
@@ -364,9 +394,9 @@ class ParametrizedDynamicModel(DynamicModel):
|
||||
elif isinstance(distributions, torch.distributions.Distribution):
|
||||
distributions = [distributions]
|
||||
|
||||
if len(distributions) != 0 and len(distributions) != len(self.next_states):
|
||||
if len(distributions) != 0 and len(distributions) != len(self.next_state):
|
||||
raise ValueError("Expecting the number of distributions (={}) to match the number of states (={})"
|
||||
".".format(len(distributions), len(self.next_states)))
|
||||
".".format(len(distributions), len(self.next_state)))
|
||||
self._distributions = distributions
|
||||
|
||||
@property
|
||||
@@ -489,11 +519,40 @@ class ParametrizedDynamicModel(DynamicModel):
|
||||
|
||||
# set the state data if specified
|
||||
if set_state_data:
|
||||
self.next_states.data = data
|
||||
self.next_state.data = data
|
||||
|
||||
# return next state data
|
||||
return data
|
||||
|
||||
#############
|
||||
# Operators #
|
||||
#############
|
||||
|
||||
def __copy__(self):
|
||||
"""Return a shallow copy of the dynamic model. This can be overridden in the child class."""
|
||||
return self.__class__(state=self.state, action=self.action, model=self.model, next_state=self.next_state,
|
||||
distributions=self.distributions, preprocessors=self.preprocessors,
|
||||
postprocessors=self.postprocessors)
|
||||
|
||||
def __deepcopy__(self, memo={}):
|
||||
"""Return a deep copy of the dynamic model. This can be overridden in the child class.
|
||||
|
||||
Args:
|
||||
memo (dict): memo dictionary of objects already copied during the current copying pass
|
||||
"""
|
||||
state = copy.deepcopy(self.state, memo)
|
||||
action = copy.deepcopy(self.action, memo)
|
||||
model = copy.deepcopy(self.model, memo)
|
||||
distributions = [copy.deepcopy(distribution) for distribution in self.distributions]
|
||||
next_state = copy.deepcopy(self.next_state, memo)
|
||||
preprocessors = [copy.deepcopy(preprocessor, memo) for preprocessor in self.preprocessors]
|
||||
postprocessors = [copy.deepcopy(postprocessor, memo) for postprocessor in self.postprocessors]
|
||||
dynamic = self.__class__(state=state, action=action, model=model, next_state=next_state,
|
||||
distributions=distributions, preprocessors=preprocessors,
|
||||
postprocessors=postprocessors)
|
||||
memo[self] = dynamic
|
||||
return dynamic
|
||||
|
||||
|
||||
# class GPDynamicModel(ParametrizedDynamicModel):
|
||||
# r"""Gaussian Process Dynamic Model
|
||||
|
||||
@@ -28,15 +28,15 @@ class NNDynamicModel(ParametrizedDynamicModel):
|
||||
Cons: requires lot of samples, overfitting,...
|
||||
"""
|
||||
|
||||
def __init__(self, states, actions, model, next_states=None, distributions=None, preprocessors=None,
|
||||
def __init__(self, state, action, model, next_state=None, distributions=None, preprocessors=None,
|
||||
postprocessors=None):
|
||||
"""
|
||||
Initialize the NN dynamic model.
|
||||
|
||||
Args:
|
||||
states (State): state inputs.
|
||||
actions (Action): action inputs.
|
||||
next_states (State, None): state outputs. If None, it will take the state inputs as the outputs.
|
||||
state (State): state inputs.
|
||||
action (Action): action inputs.
|
||||
next_state (State, None): state outputs. If None, it will take the state inputs as the outputs.
|
||||
model (NNApproximator, NN): neural network model.
|
||||
distributions (torch.distributions.Distribution): distribution to use to sample the next state. If None,
|
||||
it will be deterministic.
|
||||
@@ -46,11 +46,11 @@ class NNDynamicModel(ParametrizedDynamicModel):
|
||||
if model is None:
|
||||
raise TypeError("Expecting the model to be a neural network and not None.")
|
||||
elif not isinstance(model, NNApproximator):
|
||||
if next_states is None:
|
||||
next_states = states
|
||||
model = NNApproximator(inputs=[states, actions], outputs=next_states, model=model,
|
||||
if next_state is None:
|
||||
next_state = state
|
||||
model = NNApproximator(inputs=[state, action], outputs=next_state, model=model,
|
||||
preprocessors=preprocessors, postprocessors=postprocessors)
|
||||
super(NNDynamicModel, self).__init__(states, actions, model=model, next_states=next_states,
|
||||
super(NNDynamicModel, self).__init__(state, action, model=model, next_state=next_state,
|
||||
distributions=distributions)
|
||||
|
||||
|
||||
@@ -59,16 +59,16 @@ class MLPDynamicModel(NNDynamicModel):
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, states, actions, next_states=None, hidden_units=(), activation_fct='Linear',
|
||||
def __init__(self, state, action, next_state=None, hidden_units=(), activation_fct='Linear',
|
||||
last_activation_fct=None, dropout_prob=None, distributions=None, preprocessors=None,
|
||||
postprocessors=None):
|
||||
"""
|
||||
Initialize the multi-layer perceptron model.
|
||||
|
||||
Args:
|
||||
states (State): state inputs.
|
||||
actions (Action): action inputs.
|
||||
next_states (State, None): state outputs. If None, it will take the state inputs as the outputs.
|
||||
state (State): state inputs.
|
||||
action (Action): action inputs.
|
||||
next_state (State, None): state outputs. If None, it will take the state inputs as the outputs.
|
||||
hidden_units (tuple, list of int): number of hidden units in each layer
|
||||
activation_fct (str): activation function to apply on each layer
|
||||
last_activation_fct (str, None): activation function to apply on the last layer
|
||||
@@ -78,11 +78,11 @@ class MLPDynamicModel(NNDynamicModel):
|
||||
preprocessors (Processor, list of Processor, None): pre-processors to be applied to the given input
|
||||
postprocessors (Processor, list of Processor, None): post-processors to be applied to the output
|
||||
"""
|
||||
if next_states is None:
|
||||
next_states = states
|
||||
model = MLPApproximator(inputs=[states, actions], outputs=next_states, hidden_units=hidden_units,
|
||||
if next_state is None:
|
||||
next_state = state
|
||||
model = MLPApproximator(inputs=[state, action], outputs=next_state, hidden_units=hidden_units,
|
||||
activation=activation_fct, last_activation=last_activation_fct,
|
||||
dropout=dropout_prob)
|
||||
super(MLPDynamicModel, self).__init__(states, actions, model=model, next_states=next_states,
|
||||
super(MLPDynamicModel, self).__init__(state, action, model=model, next_state=next_state,
|
||||
distributions=distributions, preprocessors=preprocessors,
|
||||
postprocessors=postprocessors)
|
||||
|
||||
@@ -22,8 +22,8 @@ class PhysicalDynamicModel(DynamicModel):
|
||||
Dynamic model described by mathematical/physical equations.
|
||||
"""
|
||||
|
||||
def __init__(self, states, actions):
|
||||
super(PhysicalDynamicModel, self).__init__(states, actions)
|
||||
def __init__(self, state, action):
|
||||
super(PhysicalDynamicModel, self).__init__(state, action)
|
||||
|
||||
|
||||
class RobotDynamicModel(PhysicalDynamicModel):
|
||||
@@ -37,8 +37,8 @@ class RobotDynamicModel(PhysicalDynamicModel):
|
||||
* the states/actions have to be robot states/actions
|
||||
"""
|
||||
|
||||
def __init__(self, states, actions, robot):
|
||||
super(RobotDynamicModel, self).__init__(states, actions)
|
||||
def __init__(self, state, action, robot):
|
||||
super(RobotDynamicModel, self).__init__(state, action)
|
||||
self.robot = robot
|
||||
|
||||
##############
|
||||
|
||||
+60
-11
@@ -10,6 +10,8 @@ Dependencies:
|
||||
- (`pyrobolearn.envs.terminal_condition`)
|
||||
"""
|
||||
|
||||
import copy
|
||||
import pickle
|
||||
# import gym
|
||||
|
||||
from pyrobolearn.worlds import World, BasicWorld
|
||||
@@ -61,7 +63,7 @@ class Env(object): # gym.Env): # TODO: make it inheriting the gym.Env
|
||||
Args:
|
||||
world (World): world of the environment. The world contains all the objects (including robots), and has
|
||||
access to the simulator.
|
||||
states (State): states that are returned by the environment at each time step.
|
||||
states ((list of) State): states that are returned by the environment at each time step.
|
||||
rewards (None, Reward): The rewards can be None when for instance we are in an imitation learning setting,
|
||||
instead of a reinforcement learning one. If None, only the state is returned by the environment.
|
||||
terminal_conditions (None, callable, TerminalCondition, list of TerminalCondition): A callable function or
|
||||
@@ -71,9 +73,10 @@ class Env(object): # gym.Env): # TODO: make it inheriting the gym.Env
|
||||
physics_randomizers (None, PhysicsRandomizer, list of PhysicsRandomizer): physics randomizers. This will be
|
||||
called each time you reset the environment.
|
||||
extra_info (None, callable): Extra info returned by the environment at each time step.
|
||||
actions (Action): actions that are given to the environment. Note that this is not used here in the current
|
||||
environment as it should be the policy that performs the action. This is useful when creating policies
|
||||
after the environment (that is, the policy can uses the environment's states and actions).
|
||||
actions ((list of) Action): actions that are given to the environment. Note that this is not used here in
|
||||
the current environment as it should be the policy that performs the action. This is useful when
|
||||
creating policies after the environment (that is, the policy can uses the environment's states and
|
||||
actions).
|
||||
"""
|
||||
# Check and set parameters (see corresponding properties)
|
||||
self.world = world
|
||||
@@ -103,7 +106,8 @@ class Env(object): # gym.Env): # TODO: make it inheriting the gym.Env
|
||||
def world(self, world):
|
||||
"""Set the world."""
|
||||
if not isinstance(world, World):
|
||||
raise TypeError("Expecting the 'world' argument to be an instance of World.")
|
||||
raise TypeError("Expecting the given 'world' argument to be an instance of `World`, instead got: "
|
||||
"{}".format(type(world)))
|
||||
self._world = world
|
||||
self.sim = self._world.simulator
|
||||
|
||||
@@ -176,9 +180,8 @@ class Env(object): # gym.Env): # TODO: make it inheriting the gym.Env
|
||||
"""Set the rewards."""
|
||||
if rewards is not None:
|
||||
if not isinstance(rewards, Reward):
|
||||
raise TypeError("Expecting the 'rewards' argument to be an instance of Reward.")
|
||||
else:
|
||||
rewards = lambda: None
|
||||
raise TypeError("Expecting the given 'rewards' argument to be an instance of `Reward` or None, "
|
||||
"instead got: {}".format(type(rewards)))
|
||||
self._rewards = rewards
|
||||
|
||||
@property
|
||||
@@ -301,7 +304,12 @@ class Env(object): # gym.Env): # TODO: make it inheriting the gym.Env
|
||||
reward, done, info).
|
||||
|
||||
Args:
|
||||
action (Action, None): an action provided by the policy(ies) to the environment
|
||||
actions (None, (list of) Action, (list of) np.array): an action provided by the policy(ies) to the
|
||||
environment. Note that this is not used in this method; calling the actions should be done inside the
|
||||
policy(ies), and not in the environment. The policy decides when to execute an action. Several problems
|
||||
can appear by providing the actions in the environment instead of letting the policy executes them.
|
||||
For instance, think about when there are multiple policies, when using multiprocessing, or when the
|
||||
environment runs in real-time.
|
||||
|
||||
Returns:
|
||||
observation (object): agent's observation of the current environment
|
||||
@@ -319,7 +327,7 @@ class Env(object): # gym.Env): # TODO: make it inheriting the gym.Env
|
||||
# for action in actions:
|
||||
# action()
|
||||
# TODO: calling the actions should be done inside the policy(ies), and not in the environments. The policy
|
||||
# decided when to execute an action. Think about when there are multiple policies, when using multiprocessing,
|
||||
# decides when to execute an action. Think about when there are multiple policies, when using multiprocessing,
|
||||
# or when the environment runs in real-time.
|
||||
# if actions is not None and isinstance(actions, Action):
|
||||
# actions()
|
||||
@@ -329,7 +337,8 @@ class Env(object): # gym.Env): # TODO: make it inheriting the gym.Env
|
||||
|
||||
# compute reward
|
||||
# rewards = [reward.compute() for reward in self.rewards]
|
||||
rewards = self.rewards()
|
||||
if self.rewards is not None:
|
||||
rewards = self.rewards()
|
||||
|
||||
# compute terminating condition
|
||||
done = any([condition() for condition in self.terminal_conditions])
|
||||
@@ -370,6 +379,46 @@ class Env(object): # gym.Env): # TODO: make it inheriting the gym.Env
|
||||
for randomizer in self.physics_randomizers:
|
||||
randomizer.seed(seed)
|
||||
|
||||
#############
|
||||
# Operators #
|
||||
#############
|
||||
|
||||
def __call__(self, actions=None):
|
||||
"""Alias to `step` method."""
|
||||
return self.step(actions)
|
||||
|
||||
def __str__(self):
|
||||
"""Return a string describing the environment."""
|
||||
string = self.__class__.__name__ + '(\n\tworld=' + str(self.world) + ',\n\tstates=' + str(self.states) \
|
||||
+ ',\n\trewards=' + str(self.rewards) + '\n)'
|
||||
return string
|
||||
|
||||
def __copy__(self):
|
||||
"""Return a shallow copy of the approximator. This can be overridden in the child class."""
|
||||
return self.__class__(world=self.world, states=self.states, rewards=self.rewards,
|
||||
terminal_conditions=self.terminal_conditions,
|
||||
initial_state_generators=self.state_generators,
|
||||
physics_randomizers=self.physics_randomizers,
|
||||
extra_info=self.extra_info, actions=self.actions)
|
||||
|
||||
def __deepcopy__(self, memo={}):
|
||||
"""Return a deep copy of the environment. This can be overridden in the child class.
|
||||
|
||||
Args:
|
||||
memo (dict): memo dictionary of objects already copied during the current copying pass
|
||||
"""
|
||||
world = copy.deepcopy(self.world, memo)
|
||||
states = [copy.deepcopy(state, memo) for state in self.states]
|
||||
rewards = None if self.rewards is None else copy.deepcopy(self.rewards, memo)
|
||||
terminal_conditions = [copy.deepcopy(condition) for condition in self.terminal_conditions]
|
||||
state_generators = [copy.deepcopy(generator, memo) for generator in self.state_generators]
|
||||
physics_randomizers = [copy.deepcopy(randomizer, memo) for randomizer in self.physics_randomizers]
|
||||
extra_info = copy.deepcopy(self.extra_info)
|
||||
actions = None if self.actions is None else [copy.deepcopy(action, memo) for action in self.actions]
|
||||
return self.__class__(world=world, states=states, rewards=rewards, terminal_conditions=terminal_conditions,
|
||||
initial_state_generators=state_generators, physics_randomizers=physics_randomizers,
|
||||
extra_info=extra_info, actions=actions)
|
||||
|
||||
|
||||
class BasicEnv(Env):
|
||||
"""Basic Environment class.
|
||||
|
||||
@@ -49,18 +49,18 @@ class RandomPolicy(Policy):
|
||||
spaces = self.actions.space
|
||||
return [space.sample() for space in spaces]
|
||||
|
||||
def __init__(self, states, actions, rate=1, seed=None, preprocessors=None, postprocessors=None, *args, **kwargs):
|
||||
def __init__(self, state, action, rate=1, seed=None, preprocessors=None, postprocessors=None, *args, **kwargs):
|
||||
"""
|
||||
Initialize the Random policy.
|
||||
|
||||
Args:
|
||||
actions (Action): At each step, by calling `policy.act(state)`, the `actions` are computed by the policy,
|
||||
and should be given to the environment. As with the `states`, the type and size/shape of each action
|
||||
can be inferred and could be used to automatically build a policy. The `action` connects the policy
|
||||
with a controllable object (such as a robot) in the environment.
|
||||
states (State): By giving the `states` to the policy, it can automatically infer the type and size/shape
|
||||
of each state, and thus can be used to automatically build a policy. At each step, the `states`
|
||||
are filled by the environment, and read by the policy. The `state` connects the policy with one or
|
||||
action (Action): At each step, by calling `policy.act(state)`, the `action` is computed by the policy,
|
||||
and can be given to the environment. As with the `state`, the type and size/shape of each inner
|
||||
action can be inferred and could be used to automatically build a policy. The `action` connects the
|
||||
policy with a controllable object (such as a robot) in the environment.
|
||||
state (State): By giving the `state` to the policy, it can automatically infer the type and size/shape
|
||||
of each inner state, and thus can be used to automatically build a policy. At each step, the `state`
|
||||
is filled by the environment, and read by the policy. The `state` connects the policy with one or
|
||||
several objects (including robots) in the environment. Note that some policies don't use any state
|
||||
information.
|
||||
model (Approximator, Model, None): inner model or approximator
|
||||
@@ -72,8 +72,8 @@ class RandomPolicy(Policy):
|
||||
*args (list): list of arguments
|
||||
**kwargs (dict): dictionary of arguments
|
||||
"""
|
||||
model = self.RandomModel(actions, seed=seed)
|
||||
super(RandomPolicy, self).__init__(states, actions, model=model, rate=rate, preprocessors=preprocessors,
|
||||
model = self.RandomModel(action, seed=seed)
|
||||
super(RandomPolicy, self).__init__(state, action, model=model, rate=rate, preprocessors=preprocessors,
|
||||
postprocessors=postprocessors, *args, **kwargs)
|
||||
|
||||
def sample(self, state=None):
|
||||
@@ -84,18 +84,18 @@ class LinearPolicy(Policy):
|
||||
"""Linear Policy
|
||||
"""
|
||||
|
||||
def __init__(self, states, actions, rate=1, preprocessors=None, postprocessors=None, *args, **kwargs):
|
||||
def __init__(self, state, action, rate=1, preprocessors=None, postprocessors=None, *args, **kwargs):
|
||||
"""
|
||||
Initialize the Linear Policy.
|
||||
|
||||
Args:
|
||||
actions (Action): At each step, by calling `policy.act(state)`, the `actions` are computed by the policy,
|
||||
and should be given to the environment. As with the `states`, the type and size/shape of each action
|
||||
can be inferred and could be used to automatically build a policy. The `action` connects the policy
|
||||
with a controllable object (such as a robot) in the environment.
|
||||
states (State): By giving the `states` to the policy, it can automatically infer the type and size/shape
|
||||
of each state, and thus can be used to automatically build a policy. At each step, the `states`
|
||||
are filled by the environment, and read by the policy. The `state` connects the policy with one or
|
||||
action (Action): At each step, by calling `policy.act(state)`, the `action` is computed by the policy,
|
||||
and can be given to the environment. As with the `state`, the type and size/shape of each inner
|
||||
action can be inferred and could be used to automatically build a policy. The `action` connects the
|
||||
policy with a controllable object (such as a robot) in the environment.
|
||||
state (State): By giving the `state` to the policy, it can automatically infer the type and size/shape
|
||||
of each inner state, and thus can be used to automatically build a policy. At each step, the `state`
|
||||
is filled by the environment, and read by the policy. The `state` connects the policy with one or
|
||||
several objects (including robots) in the environment. Note that some policies don't use any state
|
||||
information.
|
||||
rate (int, float): rate (float) at which the policy operates if we are operating in real-time. If we are
|
||||
@@ -106,8 +106,8 @@ class LinearPolicy(Policy):
|
||||
*args (list): list of arguments
|
||||
**kwargs (dict): dictionary of arguments
|
||||
"""
|
||||
model = LinearApproximator(states, actions, preprocessors=preprocessors, postprocessors=postprocessors)
|
||||
super(LinearPolicy, self).__init__(states, actions, model, rate=rate, *args, **kwargs)
|
||||
model = LinearApproximator(state, action, preprocessors=preprocessors, postprocessors=postprocessors)
|
||||
super(LinearPolicy, self).__init__(state, action, model, rate=rate, *args, **kwargs)
|
||||
|
||||
|
||||
class PolicyFromQValue(Policy):
|
||||
@@ -137,7 +137,7 @@ class PolicyFromQValue(Policy):
|
||||
**kwargs (dict): dictionary of arguments
|
||||
"""
|
||||
self.value = value
|
||||
super(PolicyFromQValue, self).__init__(states=value.state, actions=value.action, model=value, rate=rate,
|
||||
super(PolicyFromQValue, self).__init__(state=value.state, action=value.action, model=value, rate=rate,
|
||||
preprocessors=preprocessors, postprocessors=postprocessors,
|
||||
*args, **kwargs)
|
||||
|
||||
@@ -214,7 +214,7 @@ if __name__ == '__main__':
|
||||
from pyrobolearn.actions import FixedAction
|
||||
|
||||
# check linear policy
|
||||
policy = LinearPolicy(states=FixedState(range(4)), actions=FixedAction(range(2)))
|
||||
policy = LinearPolicy(state=FixedState(range(4)), action=FixedAction(range(2)))
|
||||
print(policy)
|
||||
|
||||
target = copy.deepcopy(policy)
|
||||
|
||||
@@ -27,7 +27,7 @@ class CPGPolicy(Policy):
|
||||
r"""Central Pattern Generator (CPG) Network policy
|
||||
"""
|
||||
|
||||
def __init__(self, states, actions, rate=1, cpg_network=None, amplitude=np.pi/4, offset=0., init_phase=0.,
|
||||
def __init__(self, state, action, rate=1, cpg_network=None, amplitude=np.pi / 4, offset=0., init_phase=0.,
|
||||
freq=1., couple_hips=False, parent_coupling=True, child_coupling=True,
|
||||
hip_coupling_weight=None, hip_coupling_bias=0., parent_coupling_weight=None, parent_coupling_bias=0.,
|
||||
child_coupling_weight=None, child_coupling_bias=0., update_amplitudes=True, update_offsets=True,
|
||||
@@ -38,8 +38,8 @@ class CPGPolicy(Policy):
|
||||
Initialize the CPG Network Policy.
|
||||
|
||||
Args:
|
||||
states (PhaseState): phase state.
|
||||
actions (JointAction): joint action. Normally, it will be JointPositionAction.
|
||||
state (PhaseState): phase state.
|
||||
action (JointAction): joint action. Normally, it will be JointPositionAction.
|
||||
rate (int, float): rate (float) at which the policy operates if we are operating in real-time. If we are
|
||||
stepping deterministically in the simulator, it represents the number of ticks (int) to sleep before
|
||||
executing the model.
|
||||
@@ -97,23 +97,23 @@ class CPGPolicy(Policy):
|
||||
*args (list): other arguments given to the CPG network learning model.
|
||||
**kwargs (dict): other key + value arguments given to the CPG network learning model.
|
||||
"""
|
||||
super(CPGPolicy, self).__init__(states, actions, rate=rate, preprocessors=preprocessors,
|
||||
super(CPGPolicy, self).__init__(state, action, rate=rate, preprocessors=preprocessors,
|
||||
postprocessors=postprocessors, *args, **kwargs)
|
||||
|
||||
# check actions
|
||||
if not isinstance(actions, JointAction):
|
||||
if not isinstance(action, JointAction):
|
||||
raise TypeError("Expecting the actions to be an instance of JointAction, instead got: "
|
||||
"{}".format(type(actions)))
|
||||
"{}".format(type(action)))
|
||||
|
||||
# check states
|
||||
if not isinstance(states, PhaseState):
|
||||
if not isinstance(state, PhaseState):
|
||||
raise TypeError("Expecting the states to be an instance of PhaseState, instead got: "
|
||||
"{}".format(type(states)))
|
||||
"{}".format(type(state)))
|
||||
|
||||
# get useful information from the state/action
|
||||
timesteps = states.num_steps
|
||||
robot = actions.robot
|
||||
joints = set(actions.joints)
|
||||
timesteps = state.num_steps
|
||||
robot = action.robot
|
||||
joints = set(action.joints)
|
||||
|
||||
# create CPG network based on the robot kinematic structures if not provided
|
||||
if cpg_network is None:
|
||||
|
||||
@@ -27,19 +27,42 @@ class DMPPolicy(Policy):
|
||||
r"""Dynamic Movement Primitive (DMP) policy
|
||||
"""
|
||||
|
||||
def __init__(self, states, actions, model, rate=1, *args, **kwargs):
|
||||
def __init__(self, state, action, model, rate=1, preprocessors=None, postprocessors=None, *args, **kwargs):
|
||||
"""
|
||||
Initialize the DMP policy.
|
||||
|
||||
Args:
|
||||
action (Action): At each step, by calling `policy.act(state)`, the `action` is computed by the policy,
|
||||
and can be given to the environment. As with the `state`, the type and size/shape of each inner
|
||||
action can be inferred and could be used to automatically build a policy. The `action` connects the
|
||||
policy with a controllable object (such as a robot) in the environment.
|
||||
state (State): By giving the `state` to the policy, it can automatically infer the type and size/shape
|
||||
of each inner state, and thus can be used to automatically build a policy. At each step, the `state`
|
||||
is filled by the environment, and read by the policy. The `state` connects the policy with one or
|
||||
several objects (including robots) in the environment. Note that some policies don't use any state
|
||||
information.
|
||||
model (DMP): DMP model
|
||||
rate (int, float): rate (float) at which the policy operates if we are operating in real-time. If we are
|
||||
stepping deterministically in the simulator, it represents the number of ticks (int) to sleep before
|
||||
executing the model.
|
||||
preprocessors (Processor, list of Processor, None): pre-processors to be applied to the given input
|
||||
postprocessors (Processor, list of Processor, None): post-processors to be applied to the output
|
||||
*args (list): list of arguments (this is not used in this class).
|
||||
**kwargs (dict): dictionary of arguments (this is not used in this class).
|
||||
"""
|
||||
if not isinstance(model, DMP):
|
||||
raise TypeError("Expecting model to be an instance of DMP")
|
||||
super(DMPPolicy, self).__init__(states, actions, model, rate=rate, *args, **kwargs)
|
||||
super(DMPPolicy, self).__init__(state=state, action=action, model=model, rate=rate,
|
||||
preprocessors=preprocessors, postprocessors=postprocessors, *args, **kwargs)
|
||||
|
||||
# check actions
|
||||
self.is_joint_position_action = JointPositionAction in actions or JointPositionAndVelocityAction in actions
|
||||
self.is_joint_velocity_action = JointVelocityAction in actions or JointPositionAndVelocityAction in actions
|
||||
self.is_joint_acceleration_action = JointAccelerationAction in actions
|
||||
self.is_joint_position_action = JointPositionAction in action or JointPositionAndVelocityAction in action
|
||||
self.is_joint_velocity_action = JointVelocityAction in action or JointPositionAndVelocityAction in action
|
||||
self.is_joint_acceleration_action = JointAccelerationAction in action
|
||||
if not (self.is_joint_position_action or self.is_joint_velocity_action or self.is_joint_acceleration_action):
|
||||
raise ValueError("The actions do not have a joint position, velocity, or acceleration action.")
|
||||
|
||||
def inner_predict(self, state, to_numpy=False, return_logits=True, set_output_data=False):
|
||||
def inner_predict(self, state, deterministic=True, to_numpy=False, return_logits=True, set_output_data=False):
|
||||
"""Inner prediction step.
|
||||
|
||||
Args:
|
||||
@@ -106,34 +129,97 @@ class DMPPolicy(Policy):
|
||||
|
||||
class DiscreteDMPPolicy(DMPPolicy):
|
||||
r"""Discrete DMP Policy
|
||||
|
||||
See Also: see documentation in `pyrobolearn.models.dmp.discrete_dmp.py`
|
||||
|
||||
References:
|
||||
[1] "Dynamical movement primitives: Learning attractor models for motor behaviors", Ijspeert et al., 2013
|
||||
"""
|
||||
|
||||
def __init__(self, actions, states=None, num_basis=20, dt=0.01, y0=0, goal=1, forcing_terms=None,
|
||||
def __init__(self, action, state=None, num_basis=20, dt=0.01, y0=0, goal=1, forcing_terms=None,
|
||||
stiffness=None, damping=None, rate=1):
|
||||
if not isinstance(actions, Action):
|
||||
"""
|
||||
Initialize the discrete DMP policy.
|
||||
|
||||
Args:
|
||||
action:
|
||||
state:
|
||||
num_basis (int): number of basis functions
|
||||
dt (float): step integration for Euler's method
|
||||
y0 (float, np.array): initial position(s)
|
||||
goal (float, np.array): goal(s)
|
||||
forcing_terms (list, ForcingTerm): the forcing terms (which can have different basis functions)
|
||||
stiffness (float): stiffness coefficient
|
||||
damping (float): damping coefficient
|
||||
rate:
|
||||
"""
|
||||
if not isinstance(action, Action):
|
||||
raise TypeError("Expecting actions to be an instance of the 'Action' class.")
|
||||
model = DiscreteDMP(num_dmps=self._size(actions), num_basis=num_basis, dt=dt, y0=y0, goal=goal,
|
||||
model = DiscreteDMP(num_dmps=self._size(action), num_basis=num_basis, dt=dt, y0=y0, goal=goal,
|
||||
forcing_terms=forcing_terms, stiffness=stiffness, damping=damping)
|
||||
super(DiscreteDMPPolicy, self).__init__(states, actions, model, rate=rate)
|
||||
super(DiscreteDMPPolicy, self).__init__(state, action, model, rate=rate)
|
||||
|
||||
|
||||
class RhythmicDMPPolicy(DMPPolicy):
|
||||
r"""Rhythmic DMP Policy
|
||||
|
||||
See Also: see documentation in `pyrobolearn.models.dmp.rhythmic_dmp.py`
|
||||
|
||||
References:
|
||||
[1] "Dynamical movement primitives: Learning attractor models for motor behaviors", Ijspeert et al., 2013
|
||||
"""
|
||||
|
||||
def __init__(self, actions, states=None, num_basis=20, dt=0.01, y0=0, goal=1, forcing_terms=None,
|
||||
def __init__(self, action, state=None, num_basis=20, dt=0.01, y0=0, goal=1, forcing_terms=None,
|
||||
stiffness=None, damping=None, rate=1):
|
||||
model = RhythmicDMP(num_dmps=self._size(actions), num_basis=num_basis, dt=dt, y0=y0, goal=goal,
|
||||
"""
|
||||
Initialize the Rhythmic DMP policy.
|
||||
|
||||
Args:
|
||||
action:
|
||||
state:
|
||||
num_basis (int): number of basis functions
|
||||
dt (float): step integration for Euler's method
|
||||
y0 (float, np.array): initial position(s)
|
||||
goal (float, np.array): goal(s)
|
||||
forcing_terms (list, ForcingTerm): the forcing terms (which can have different basis functions)
|
||||
stiffness (float): stiffness coefficient
|
||||
damping (float): damping coefficient
|
||||
rate:
|
||||
"""
|
||||
model = RhythmicDMP(num_dmps=self._size(action), num_basis=num_basis, dt=dt, y0=y0, goal=goal,
|
||||
forcing_terms=forcing_terms, stiffness=stiffness, damping=damping)
|
||||
super(RhythmicDMPPolicy, self).__init__(states, actions, model, rate=rate)
|
||||
super(RhythmicDMPPolicy, self).__init__(state, action, model, rate=rate)
|
||||
|
||||
|
||||
class BioDiscreteDMPPolicy(DMPPolicy):
|
||||
r"""Bio Discrete DMP Policy
|
||||
|
||||
See Also: see documentation in `pyrobolearn.models.dmp.biodiscrete_dmp.py`
|
||||
|
||||
References:
|
||||
[1] "Dynamical movement primitives: Learning attractor models for motor behaviors", Ijspeert et al., 2013
|
||||
[2] "Biologically-inspired Dynamical Systems for Movement Generation: Automatic Real-time Goal Adaptation
|
||||
and Obstacle Avoidance", Hoffmann et al., 2009
|
||||
[3] "Learning and Generalization of Motor Skills by Learning from Demonstration", Pastor et al., 2009
|
||||
"""
|
||||
|
||||
def __init__(self, actions, states=None, num_basis=20, dt=0.01, y0=0, goal=1, forcing_terms=None,
|
||||
def __init__(self, action, state=None, num_basis=20, dt=0.01, y0=0, goal=1, forcing_terms=None,
|
||||
stiffness=None, damping=None, rate=1):
|
||||
model = BioDiscreteDMP(num_dmps=self._size(actions), num_basis=num_basis, dt=dt, y0=y0, goal=goal,
|
||||
"""
|
||||
Initialize the biologically-inspired DMP policy.
|
||||
|
||||
Args:
|
||||
action:
|
||||
state:
|
||||
num_basis (int): number of basis functions
|
||||
dt (float): step integration for Euler's method
|
||||
y0 (float, np.array): initial position(s)
|
||||
goal (float, np.array): goal(s)
|
||||
forcing_terms (list, ForcingTerm): the forcing terms (which can have different basis functions)
|
||||
stiffness (float): stiffness coefficient
|
||||
damping (float): damping coefficient
|
||||
rate:
|
||||
"""
|
||||
model = BioDiscreteDMP(num_dmps=self._size(action), num_basis=num_basis, dt=dt, y0=y0, goal=goal,
|
||||
forcing_terms=forcing_terms, stiffness=stiffness, damping=damping)
|
||||
super(BioDiscreteDMPPolicy, self).__init__(states, actions, model, rate=rate)
|
||||
super(BioDiscreteDMPPolicy, self).__init__(state, action, model, rate=rate)
|
||||
|
||||
@@ -54,19 +54,19 @@ class NEATPolicy(Policy):
|
||||
[3] PyTorch NEAT (built upon NEAT-Python): https://github.com/uber-research/PyTorch-NEAT
|
||||
"""
|
||||
|
||||
def __init__(self, states, actions, num_hidden=0, activation_fct='relu', network_type='feedforward',
|
||||
def __init__(self, state, action, num_hidden=0, activation_fct='relu', network_type='feedforward',
|
||||
aggregation='sum', weights_limits=(-20, 20), bias_limits=(-20, 20), rate=1, preprocessors=None,
|
||||
postprocessors=None, *args, **kwargs):
|
||||
r"""Initialize the neural network policy for the NEAT algorithm.
|
||||
|
||||
Args:
|
||||
actions (Action): At each step, by calling `policy.act(state)`, the `actions` are computed by the policy,
|
||||
and should be given to the environment. As with the `states`, the type and size/shape of each action
|
||||
can be inferred and could be used to automatically build a policy. The `action` connects the policy
|
||||
with a controllable object (such as a robot) in the environment.
|
||||
states (State): By giving the `states` to the policy, it can automatically infer the type and size/shape
|
||||
of each state, and thus can be used to automatically build a policy. At each step, the `states`
|
||||
are filled by the environment, and read by the policy. The `state` connects the policy with one or
|
||||
action (Action): At each step, by calling `policy.act(state)`, the `action` is computed by the policy,
|
||||
and can be given to the environment. As with the `state`, the type and size/shape of each inner
|
||||
action can be inferred and could be used to automatically build a policy. The `action` connects the
|
||||
policy with a controllable object (such as a robot) in the environment.
|
||||
state (State): By giving the `state` to the policy, it can automatically infer the type and size/shape
|
||||
of each inner state, and thus can be used to automatically build a policy. At each step, the `state`
|
||||
is filled by the environment, and read by the policy. The `state` connects the policy with one or
|
||||
several objects (including robots) in the environment. Note that some policies don't use any state
|
||||
information.
|
||||
num_hidden (int): number of units in the hidden layer
|
||||
@@ -82,10 +82,10 @@ class NEATPolicy(Policy):
|
||||
preprocessors (Processor, list of Processor, None): pre-processors to be applied to the given input
|
||||
postprocessors (Processor, list of Processor, None): post-processors to be applied to the output
|
||||
"""
|
||||
model = NEATApproximator(states, actions, num_hidden=num_hidden, activation_fct=activation_fct,
|
||||
model = NEATApproximator(state, action, num_hidden=num_hidden, activation_fct=activation_fct,
|
||||
network_type=network_type, aggregation=aggregation, weights_limits=weights_limits,
|
||||
bias_limits=bias_limits, preprocessors=preprocessors, postprocessors=postprocessors)
|
||||
super(NEATPolicy, self).__init__(states, actions, model, rate=rate, *args, **kwargs)
|
||||
super(NEATPolicy, self).__init__(state, action, model, rate=rate, *args, **kwargs)
|
||||
|
||||
##############
|
||||
# Properties #
|
||||
|
||||
@@ -24,18 +24,18 @@ class NNPolicy(Policy):
|
||||
Defines the neural network policy.
|
||||
"""
|
||||
|
||||
def __init__(self, states, actions, model=None, rate=1, preprocessors=None, postprocessors=None, *args, **kwargs):
|
||||
def __init__(self, state, action, model=None, rate=1, preprocessors=None, postprocessors=None, *args, **kwargs):
|
||||
"""
|
||||
Initialize the Neural network policy.
|
||||
|
||||
Args:
|
||||
actions (Action): At each step, by calling `policy.act(state)`, the `actions` are computed by the policy,
|
||||
and should be given to the environment. As with the `states`, the type and size/shape of each action
|
||||
can be inferred and could be used to automatically build a policy. The `action` connects the policy
|
||||
with a controllable object (such as a robot) in the environment.
|
||||
states (State): By giving the `states` to the policy, it can automatically infer the type and size/shape
|
||||
of each state, and thus can be used to automatically build a policy. At each step, the `states`
|
||||
are filled by the environment, and read by the policy. The `state` connects the policy with one or
|
||||
action (Action): At each step, by calling `policy.act(state)`, the `action` is computed by the policy,
|
||||
and can be given to the environment. As with the `state`, the type and size/shape of each inner
|
||||
action can be inferred and could be used to automatically build a policy. The `action` connects the
|
||||
policy with a controllable object (such as a robot) in the environment.
|
||||
state (State): By giving the `state` to the policy, it can automatically infer the type and size/shape
|
||||
of each inner state, and thus can be used to automatically build a policy. At each step, the `state`
|
||||
is filled by the environment, and read by the policy. The `state` connects the policy with one or
|
||||
several objects (including robots) in the environment. Note that some policies don't use any state
|
||||
information.
|
||||
model (NN, NNApproximator): NN model
|
||||
@@ -44,8 +44,8 @@ class NNPolicy(Policy):
|
||||
executing the model.
|
||||
preprocessors (Processor, list of Processor, None): pre-processors to be applied to the given input
|
||||
postprocessors (Processor, list of Processor, None): post-processors to be applied to the output
|
||||
*args (list): list of arguments
|
||||
**kwargs (dict): dictionary of arguments
|
||||
*args (list): list of arguments (this is not used in this class).
|
||||
**kwargs (dict): dictionary of arguments (this is not used in this class).
|
||||
"""
|
||||
if model is None:
|
||||
raise ValueError("Expecting a NN model for the NN policy")
|
||||
@@ -54,7 +54,7 @@ class NNPolicy(Policy):
|
||||
# checking the output dimension of the model and the dimension of actions
|
||||
pass
|
||||
|
||||
super(NNPolicy, self).__init__(states, actions, model, rate=rate, preprocessors=preprocessors,
|
||||
super(NNPolicy, self).__init__(state, action, model, rate=rate, preprocessors=preprocessors,
|
||||
postprocessors=postprocessors, *args, **kwargs)
|
||||
|
||||
# def act(self, state, deterministic=True):
|
||||
@@ -71,14 +71,14 @@ class MLPPolicy(NNPolicy):
|
||||
activation functions.
|
||||
"""
|
||||
|
||||
def __init__(self, states, actions, hidden_units=(), activation='linear', last_activation=None,
|
||||
def __init__(self, state, action, hidden_units=(), activation='linear', last_activation=None,
|
||||
dropout=None, rate=1, preprocessors=None, postprocessors=None):
|
||||
"""Initialize MLP policy.
|
||||
|
||||
Args:
|
||||
states (State): 1D-states that is feed to the policy (the input dimensions will be inferred from the
|
||||
state (State): 1D-states that is feed to the policy (the input dimensions will be inferred from the
|
||||
states)
|
||||
actions (Action): 1D-actions outputted by the policy and will be applied in the simulator (the output
|
||||
action (Action): 1D-actions outputted by the policy and will be applied in the simulator (the output
|
||||
dimensions will be inferred from the actions)
|
||||
hidden_units (list/tuple of int): number of hidden units in the corresponding layer
|
||||
activation (None, str, or list/tuple of str/None): activation function to be applied after each layer.
|
||||
@@ -93,10 +93,10 @@ class MLPPolicy(NNPolicy):
|
||||
preprocessors (Processor, list of Processor, None): pre-processors to be applied to the given input
|
||||
postprocessors (Processor, list of Processor, None): post-processors to be applied to the output
|
||||
"""
|
||||
model = MLPApproximator(states, actions, hidden_units=hidden_units,
|
||||
model = MLPApproximator(state, action, hidden_units=hidden_units,
|
||||
activation=activation, last_activation=last_activation,
|
||||
dropout=dropout, preprocessors=preprocessors, postprocessors=postprocessors)
|
||||
super(MLPPolicy, self).__init__(states, actions, model, rate=rate)
|
||||
super(MLPPolicy, self).__init__(state, action, model, rate=rate)
|
||||
|
||||
# def act(self, state, deterministic=True):
|
||||
# return self.model.predict(state)
|
||||
|
||||
@@ -12,8 +12,9 @@ Dependencies:
|
||||
- `pyrobolearn.exploration`
|
||||
"""
|
||||
|
||||
import collections
|
||||
import copy
|
||||
import pickle
|
||||
import collections
|
||||
import numpy as np
|
||||
import torch
|
||||
|
||||
@@ -116,19 +117,19 @@ class Policy(object):
|
||||
* `exploration.py`: describes how to explore using the policy
|
||||
"""
|
||||
|
||||
def __init__(self, states, actions, model=None, rate=1, preprocessors=None, postprocessors=None,
|
||||
distribution=None, *args, **kwargs):
|
||||
def __init__(self, state, action, model=None, rate=1, preprocessors=None, postprocessors=None, *args, **kwargs):
|
||||
# distribution=None):
|
||||
r"""
|
||||
Initialize a policy (and the inner approximator / learning model).
|
||||
|
||||
Args:
|
||||
actions (Action): At each step, by calling `policy.act(state)`, the `actions` are computed by the policy,
|
||||
and should be given to the environment. As with the `states`, the type and size/shape of each action
|
||||
can be inferred and could be used to automatically build a policy. The `action` connects the policy
|
||||
with a controllable object (such as a robot) in the environment.
|
||||
states (State): By giving the `states` to the policy, it can automatically infer the type and size/shape
|
||||
of each state, and thus can be used to automatically build a policy. At each step, the `states`
|
||||
are filled by the environment, and read by the policy. The `state` connects the policy with one or
|
||||
action (Action): At each step, by calling `policy.act(state)`, the `action` is computed by the policy,
|
||||
and can be given to the environment. As with the `state`, the type and size/shape of each inner
|
||||
action can be inferred and could be used to automatically build a policy. The `action` connects the
|
||||
policy with a controllable object (such as a robot) in the environment.
|
||||
state (State): By giving the `state` to the policy, it can automatically infer the type and size/shape
|
||||
of each inner state, and thus can be used to automatically build a policy. At each step, the `state`
|
||||
is filled by the environment, and read by the policy. The `state` connects the policy with one or
|
||||
several objects (including robots) in the environment. Note that some policies don't use any state
|
||||
information.
|
||||
model (Approximator, Model, None): inner model or approximator
|
||||
@@ -137,12 +138,11 @@ class Policy(object):
|
||||
executing the model.
|
||||
preprocessors (Processor, list of Processor, None): pre-processors to be applied to the given input
|
||||
postprocessors (Processor, list of Processor, None): post-processors to be applied to the output
|
||||
distribution:
|
||||
*args (list): list of arguments
|
||||
**kwargs (dict): dictionary of arguments
|
||||
*args (list): list of arguments (this is not used in this class).
|
||||
**kwargs (dict): dictionary of arguments (this is not used in this class).
|
||||
"""
|
||||
self.states = states
|
||||
self.actions = actions
|
||||
self.states = state
|
||||
self.actions = action
|
||||
self.model = model
|
||||
self.rate = rate
|
||||
self.cnt = 0
|
||||
@@ -258,7 +258,8 @@ class Policy(object):
|
||||
# Methods #
|
||||
###########
|
||||
|
||||
def _size(self, items):
|
||||
@staticmethod
|
||||
def _size(items):
|
||||
"""Compute the size of the given argument :attr:`items`."""
|
||||
size = 0
|
||||
if not isinstance(items, (list, tuple)):
|
||||
@@ -692,12 +693,12 @@ class Policy(object):
|
||||
return self.act(state=state, deterministic=deterministic, to_numpy=to_numpy, return_logits=return_logits,
|
||||
apply_action=apply_action)
|
||||
|
||||
def __repr__(self):
|
||||
"""Return representation of python object."""
|
||||
if self.__class__.__name__ == 'Policy':
|
||||
if self.model is not None:
|
||||
return "{}({})".format(self.__class__.__name__, self.model.__str__())
|
||||
return self.__class__.__name__
|
||||
# def __repr__(self):
|
||||
# """Return representation of python object."""
|
||||
# if self.__class__.__name__ == 'Policy':
|
||||
# if self.model is not None:
|
||||
# return "{}({})".format(self.__class__.__name__, self.model.__str__())
|
||||
# return self.__class__.__name__
|
||||
|
||||
def __str__(self):
|
||||
"""Return string describing the policy."""
|
||||
@@ -705,3 +706,29 @@ class Policy(object):
|
||||
if self.model is not None:
|
||||
return "{}({})".format(self.__class__.__name__, self.model.__str__())
|
||||
return self.__class__.__name__
|
||||
|
||||
def __copy__(self):
|
||||
"""Return a shallow copy of the policy. This can be overridden in the child class."""
|
||||
return self.__class__(states=self.states, actions=self.actions, model=self.model, rate=self.rate,
|
||||
preprocessors=self.preprocessors, postprocessors=self.postprocessors)
|
||||
|
||||
def __deepcopy__(self, memo={}):
|
||||
"""Return a deep copy of the policy. This can be overridden in the child class.
|
||||
|
||||
Args:
|
||||
memo (dict): memo dictionary of objects already copied during the current copying pass
|
||||
"""
|
||||
states = copy.deepcopy(self.states, memo)
|
||||
actions = copy.deepcopy(self.actions, memo)
|
||||
model = copy.deepcopy(self.model, memo)
|
||||
rate = copy.deepcopy(self.rate, memo)
|
||||
preprocessors = [copy.deepcopy(preprocessor, memo) for preprocessor in self.preprocessors]
|
||||
postprocessors = [copy.deepcopy(postprocessor, memo) for postprocessor in self.postprocessors]
|
||||
policy = self.__class__(states=states, actions=actions, model=model, rate=rate,
|
||||
preprocessors=preprocessors, postprocessors=postprocessors)
|
||||
|
||||
# update the memodict (note that `copy.deepcopy` will automatically check this dictionary and return the
|
||||
# reference if already present)
|
||||
memo[self] = policy
|
||||
|
||||
return policy
|
||||
|
||||
@@ -202,8 +202,9 @@ class DirectiveReward(Reward):
|
||||
if __name__ == '__main__':
|
||||
from pyrobolearn.rewards import cos
|
||||
|
||||
reward = 2*FixedReward(1, range=(-1., 1.)) + FixedReward(3)**2 - 10
|
||||
reward = 2*FixedReward(1, range=(-1., 1.)) - FixedReward(3)**2 - 10
|
||||
reward += FixedReward(2)
|
||||
print(reward)
|
||||
print("\n2*FixedReward(1, range=(-1., 1.)) + FixedReward(3)**2 - 10 + FixedReward(2) = {}".format(reward()))
|
||||
print("Is an instance of Reward? {}".format(isinstance(reward, Reward)))
|
||||
print("Inner rewards: {}".format(reward.rewards))
|
||||
|
||||
@@ -95,8 +95,9 @@ class Reward(object):
|
||||
state (None, State): state on which depends the reward function.
|
||||
action (None, Action): action on which depends the reward function.
|
||||
rewards (None, list of Reward): list of intern rewards.
|
||||
range (tuple of float): A tuple corresponding to the min and max possible rewards. By default, it is
|
||||
[-infinity, infinity]. The computed reward is automatically clipped if it goes outside the range.
|
||||
range (tuple of float, np.array of 2 float): A tuple corresponding to the min and max possible rewards.
|
||||
By default, it is [-infinity, infinity]. The computed reward is automatically clipped if it goes
|
||||
outside the range.
|
||||
"""
|
||||
# super(Reward, self).__init__(maximize=True)
|
||||
|
||||
@@ -278,18 +279,41 @@ class Reward(object):
|
||||
# Operators #
|
||||
#############
|
||||
|
||||
def __repr__(self):
|
||||
def __str__(self):
|
||||
"""Return a representation string about the reward function."""
|
||||
if not self.rewards or self.rewards is None:
|
||||
return self.__class__.__name__
|
||||
else:
|
||||
lst = [reward.__repr__() for reward in self.rewards]
|
||||
lst = [reward.__str__() for reward in self.rewards]
|
||||
return ' + '.join(lst)
|
||||
|
||||
def __call__(self): # **kwargs):
|
||||
"""Compute the reward function."""
|
||||
return self.compute() # **kwargs)
|
||||
|
||||
def __copy__(self):
|
||||
"""Return a shallow copy of the reward function. This can be overridden in the child class."""
|
||||
return self.__class__(state=self.state, action=self.action, rewards=self.rewards, range=self.range)
|
||||
|
||||
def __deepcopy__(self, memo={}):
|
||||
"""Return a deep copy of the reward function. This can be overridden in the child class.
|
||||
|
||||
Args:
|
||||
memo (dict): memo dictionary of objects already copied during the current copying pass
|
||||
"""
|
||||
state = copy.deepcopy(self.state, memo)
|
||||
action = copy.deepcopy(self.action, memo)
|
||||
rewards = [copy.deepcopy(reward, memo) for reward in self.rewards]
|
||||
range = copy.deepcopy(self.range)
|
||||
reward = self.__class__(state=state, action=action, rewards=rewards, range=range)
|
||||
|
||||
# update the memodict (note that `copy.deepcopy` will automatically check this dictionary and return the
|
||||
# reference if already present)
|
||||
memo[self] = reward
|
||||
|
||||
# return the copy
|
||||
return reward
|
||||
|
||||
# for unary and binary operators, see `__init__()` method.
|
||||
|
||||
def __build_reward(self, other):
|
||||
|
||||
@@ -23,6 +23,7 @@ class Actuator(object):
|
||||
All actuator classes inherit from this class. Actuators such as motors are often attached to the robot joints.
|
||||
Other actuators such as speakers, leds, and others are attached to links.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
@@ -35,3 +36,44 @@ class Actuator(object):
|
||||
# @simulator.setter
|
||||
# def simulator(self, simulator):
|
||||
# self.sim = simulator
|
||||
|
||||
###########
|
||||
# Methods #
|
||||
###########
|
||||
|
||||
def compute(self, *args, **kwargs): # TODO: call it actuate?
|
||||
pass
|
||||
|
||||
#############
|
||||
# Operators #
|
||||
#############
|
||||
|
||||
def __call__(self, *args, **kwargs):
|
||||
return self.compute(*args, **kwargs)
|
||||
|
||||
# def __repr__(self):
|
||||
# """Return a representation string about the class for debugging and development."""
|
||||
# return self.__class__.__name__
|
||||
|
||||
def __str__(self):
|
||||
"""Return a readable string about the class."""
|
||||
return self.__class__.__name__
|
||||
|
||||
def __copy__(self):
|
||||
"""Return a shallow copy of the actuator. This can be overridden in the child class."""
|
||||
return self.__class__()
|
||||
|
||||
def __deepcopy__(self, memo={}):
|
||||
"""Return a deep copy of the actuator. This can be overridden in the child class.
|
||||
|
||||
Args:
|
||||
memo (dict): memo dictionary of objects already copied during the current copying pass
|
||||
"""
|
||||
actuator = self.__class__()
|
||||
|
||||
# update the memodict (note that `copy.deepcopy` will automatically check this dictionary and return the
|
||||
# reference if already present)
|
||||
memo[self] = actuator
|
||||
|
||||
# return the copy
|
||||
return actuator
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
"""Define the various joint actuators used in robotics.
|
||||
"""
|
||||
|
||||
import copy
|
||||
import numpy as np
|
||||
|
||||
from pyrobolearn.robots.actuators.actuator import Actuator
|
||||
@@ -24,10 +25,26 @@ class JointActuator(Actuator):
|
||||
For instance, given a target joint position value, the actuator computes the necessary torque to be applied on
|
||||
the joint using a simple PD control (with certain gains).
|
||||
"""
|
||||
|
||||
def __init__(self, joint_id):
|
||||
super(JointActuator, self).__init__()
|
||||
self.joint_id = joint_id
|
||||
|
||||
def __copy__(self):
|
||||
"""Return a shallow copy of the actuator. This can be overridden in the child class."""
|
||||
return self.__class__(joint_id=self.joint_id)
|
||||
|
||||
def __deepcopy__(self, memo={}):
|
||||
"""Return a deep copy of the actuator. This can be overridden in the child class.
|
||||
|
||||
Args:
|
||||
memo (dict): memo dictionary of objects already copied during the current copying pass
|
||||
"""
|
||||
joint_id = copy.deepcopy(self.joint_id)
|
||||
actuator = self.__class__(joint_id=joint_id)
|
||||
memo[self] = actuator
|
||||
return actuator
|
||||
|
||||
|
||||
class PDJointActuator(JointActuator):
|
||||
r"""PD Joint Actuator
|
||||
@@ -61,10 +78,33 @@ class PDJointActuator(JointActuator):
|
||||
torque = np.clip(torque, self.min_torque, self.max_torque)
|
||||
return torque
|
||||
|
||||
def __copy__(self):
|
||||
"""Return a shallow copy of the actuator. This can be overridden in the child class."""
|
||||
return self.__class__(joint_id=self.joint_id, kp=self.kp, kd=self.kd, min_torque=self.min_torque,
|
||||
max_torque=self.max_torque, latency=self.latency)
|
||||
|
||||
def __deepcopy__(self, memo={}):
|
||||
"""Return a deep copy of the actuator. This can be overridden in the child class.
|
||||
|
||||
Args:
|
||||
memo (dict): memo dictionary of objects already copied during the current copying pass
|
||||
"""
|
||||
joint_id = copy.deepcopy(self.joint_id)
|
||||
kp = copy.deepcopy(self.kp)
|
||||
kd = copy.deepcopy(self.kd)
|
||||
min_torque = copy.deepcopy(self.min_torque)
|
||||
max_torque = copy.deepcopy(self.max_torque)
|
||||
latency = copy.deepcopy(self.latency)
|
||||
actuator = self.__class__(joint_id=joint_id, kp=kp, kd=kd, min_torque=min_torque, max_torque=max_torque,
|
||||
latency=latency)
|
||||
memo[self] = actuator
|
||||
return actuator
|
||||
|
||||
|
||||
class GearedActuator(JointActuator):
|
||||
r"""Geared Actuator
|
||||
"""
|
||||
|
||||
def __init__(self, joint_id):
|
||||
super(GearedActuator, self).__init__(joint_id)
|
||||
|
||||
@@ -72,6 +112,7 @@ class GearedActuator(JointActuator):
|
||||
class DirectDriveActuator(JointActuator):
|
||||
r"""Direct Drive Actuator
|
||||
"""
|
||||
|
||||
def __init__(self, joint_id):
|
||||
super(DirectDriveActuator, self).__init__(joint_id)
|
||||
|
||||
@@ -87,6 +128,7 @@ class SEA(JointActuator):
|
||||
[1] "Series elastic actuators", Pratt et al., 1995
|
||||
[2] "Learning agile and dynamic motor skills for legged robots", Hwangbo et al., 2019
|
||||
"""
|
||||
|
||||
def __init__(self, joint_id):
|
||||
super(SEA, self).__init__(joint_id)
|
||||
|
||||
@@ -94,6 +136,7 @@ class SEA(JointActuator):
|
||||
class HydraulicActuator(JointActuator):
|
||||
r"""Hydraulic Actuator
|
||||
"""
|
||||
|
||||
def __init__(self, joint_id):
|
||||
super(HydraulicActuator, self).__init__(joint_id)
|
||||
|
||||
@@ -105,10 +148,27 @@ class JointActuatorApproximator(JointActuator):
|
||||
actuator given for instance the joint positions. This function approximator has been trained on real data obtained
|
||||
from the real actuator and can thus be a better approximation of the way the actual actuator works.
|
||||
"""
|
||||
|
||||
def __init__(self, joint_id, approximator=None):
|
||||
super(JointActuatorApproximator, self).__init__(joint_id)
|
||||
self.approximator = approximator
|
||||
|
||||
def __copy__(self):
|
||||
"""Return a shallow copy of the actuator. This can be overridden in the child class."""
|
||||
return self.__class__(joint_id=self.joint_id, approximator=self.approximator)
|
||||
|
||||
def __deepcopy__(self, memo={}):
|
||||
"""Return a deep copy of the actuator. This can be overridden in the child class.
|
||||
|
||||
Args:
|
||||
memo (dict): memo dictionary of objects already copied during the current copying pass
|
||||
"""
|
||||
joint_id = copy.deepcopy(self.joint_id)
|
||||
approximator = copy.deepcopy(self.approximator, memo)
|
||||
actuator = self.__class__(joint_id=joint_id, approximator=approximator)
|
||||
memo[self] = actuator
|
||||
return actuator
|
||||
|
||||
|
||||
class ActuatorNet(JointActuatorApproximator):
|
||||
r"""Actuator Neural Network
|
||||
@@ -116,6 +176,7 @@ class ActuatorNet(JointActuatorApproximator):
|
||||
References:
|
||||
[1] "Learning agile and dynamic motor skills for legged robots", Hwangbo et al., 2019
|
||||
"""
|
||||
|
||||
def __init__(self, joint_id, nn_model=None):
|
||||
super(ActuatorNet, self).__init__(joint_id, approximator=nn_model)
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ class Aibo(QuadrupedRobot):
|
||||
position=(0, 0, 0.02),
|
||||
orientation=(0, 0, 0, 1),
|
||||
fixed_base=False,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/aibo/aibo.urdf'):
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -43,7 +43,7 @@ class Aibo(QuadrupedRobot):
|
||||
if fixed_base is None:
|
||||
fixed_base = False
|
||||
|
||||
super(Aibo, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(Aibo, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'aibo'
|
||||
|
||||
self.legs = [[self.get_link_ids(link) for link in links if link in self.link_names]
|
||||
|
||||
@@ -28,7 +28,7 @@ class AllegroHand(Hand):
|
||||
simulator,
|
||||
position=(0, 0, 0),
|
||||
orientation=(0, 0, 0, 1),
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
left=False,
|
||||
fixed_base=True):
|
||||
# check parameters
|
||||
@@ -46,7 +46,7 @@ class AllegroHand(Hand):
|
||||
# else:
|
||||
urdf_path = os.path.dirname(__file__) + '/urdfs/allegrohand/allegro_right_hand.urdf'
|
||||
|
||||
super(AllegroHand, self).__init__(simulator, urdf_path, position, orientation, fixed_base, scaling)
|
||||
super(AllegroHand, self).__init__(simulator, urdf_path, position, orientation, fixed_base, scale)
|
||||
self.name = 'allegro_hand'
|
||||
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ class Ant(QuadrupedRobot):
|
||||
position=(0, 0, 0.2),
|
||||
orientation=(0, 0, 0, 1),
|
||||
fixed_base=False,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/mjcfs/ant.xml'):
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -39,7 +39,7 @@ class Ant(QuadrupedRobot):
|
||||
if fixed_base is None:
|
||||
fixed_base = False
|
||||
|
||||
super(Ant, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(Ant, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'ant'
|
||||
|
||||
self.legs = [[self.get_link_ids(link) for link in links if link in self.link_names]
|
||||
|
||||
@@ -35,7 +35,7 @@ class ANYmal(QuadrupedRobot):
|
||||
position=(0, 0, .6),
|
||||
orientation=(0, 0, 0, 1),
|
||||
fixed_base=False,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/anymal/anymal.urdf'):
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -47,7 +47,7 @@ class ANYmal(QuadrupedRobot):
|
||||
if fixed_base is None:
|
||||
fixed_base = False
|
||||
|
||||
super(ANYmal, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(ANYmal, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'anymal'
|
||||
|
||||
self.legs = [[self.get_link_ids(link) for link in links if link in self.link_names]
|
||||
|
||||
@@ -31,7 +31,7 @@ class Atlas(BipedRobot, BiManipulatorRobot):
|
||||
position=(0, 0, 1.),
|
||||
orientation=(0, 0, 0, 1),
|
||||
fixed_base=False,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/atlas/atlas_v4_with_multisense.urdf'):
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -43,7 +43,7 @@ class Atlas(BipedRobot, BiManipulatorRobot):
|
||||
if fixed_base is None:
|
||||
fixed_base = False
|
||||
|
||||
super(Atlas, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(Atlas, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'atlas'
|
||||
|
||||
self.head = self.get_link_ids('head') if 'head' in self.link_names else None
|
||||
|
||||
@@ -25,7 +25,7 @@ class Ballbot(Robot):
|
||||
"""
|
||||
|
||||
def __init__(self, simulator, position=(0, 0, 0.), orientation=(0, 0, 0, 1), fixed_base=False,
|
||||
scaling=1., urdf=os.path.dirname(__file__) + '/urdfs/ballbot/ballbot.urdf'):
|
||||
scale=1., urdf=os.path.dirname(__file__) + '/urdfs/ballbot/ballbot.urdf'):
|
||||
# check parameters
|
||||
if position is None:
|
||||
position = (0., 0., 0.)
|
||||
@@ -36,7 +36,7 @@ class Ballbot(Robot):
|
||||
if fixed_base is None:
|
||||
fixed_base = False
|
||||
|
||||
super(Ballbot, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(Ballbot, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.ball = self.sim.load_urdf(os.path.dirname(__file__) + '/urdfs/ballbot/ball.urdf', position, orientation)
|
||||
self.name = 'ballbot'
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ Dependencies:
|
||||
- `pyrobolearn.utils`
|
||||
"""
|
||||
|
||||
import copy
|
||||
import numpy as np
|
||||
# import quaternion
|
||||
|
||||
@@ -67,11 +68,11 @@ class Body(object):
|
||||
return self._id
|
||||
|
||||
@id.setter
|
||||
def id(self, id_):
|
||||
def id(self, body_id):
|
||||
"""Set the unique body id."""
|
||||
# if not isinstance(id_, int):
|
||||
# raise TypeError("Expecting the given simulator to be an integer, instead got: {}".format(type(id_)))
|
||||
self._id = id_
|
||||
# if not isinstance(body_id, int):
|
||||
# raise TypeError("Expecting the given simulator to be an integer, instead got: {}".format(type(body_id)))
|
||||
self._id = body_id
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
@@ -198,6 +199,38 @@ class Body(object):
|
||||
"""Return the center of mass."""
|
||||
return self.sim.get_center_of_mass_position(self.id)
|
||||
|
||||
#############
|
||||
# Operators #
|
||||
#############
|
||||
|
||||
# def __repr__(self):
|
||||
# """Return a representation string about the class for debugging and development."""
|
||||
# return self.__class__.__name__
|
||||
|
||||
def __str__(self):
|
||||
"""Return a readable string about the class."""
|
||||
return self.__class__.__name__
|
||||
|
||||
def __copy__(self):
|
||||
"""Return a shallow copy of the body. This can be overridden in the child class."""
|
||||
return self.__class__(simulator=self.simulator, body_id=self.id, name=self.name)
|
||||
|
||||
def __deepcopy__(self, memo={}):
|
||||
"""Return a deep copy of the body. This can be overridden in the child class.
|
||||
|
||||
Args:
|
||||
memo (dict): memo dictionary of objects already copied during the current copying pass
|
||||
"""
|
||||
simulator = copy.deepcopy(self.simulator, memo)
|
||||
body = self.__class__(simulator=simulator, body_id=self.id, name=self.name)
|
||||
|
||||
# update the memodict (note that `copy.deepcopy` will automatically check this dictionary and return the
|
||||
# reference if already present)
|
||||
memo[self] = body
|
||||
|
||||
# return the copy
|
||||
return body
|
||||
|
||||
|
||||
class MovableBody(Body):
|
||||
r"""Movable Body
|
||||
|
||||
@@ -30,7 +30,7 @@ class Baxter(BiManipulatorRobot):
|
||||
position=(0, 0, 0.95),
|
||||
orientation=(0, 0, 0, 1),
|
||||
fixed_base=False,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/baxter/baxter.urdf'):
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -42,7 +42,7 @@ class Baxter(BiManipulatorRobot):
|
||||
if fixed_base is None:
|
||||
fixed_base = False
|
||||
|
||||
super(Baxter, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(Baxter, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'baxter'
|
||||
|
||||
self.head = self.get_link_ids('head') if 'head' in self.link_names else None
|
||||
|
||||
@@ -24,7 +24,7 @@ class BB8(Robot):
|
||||
"""
|
||||
|
||||
def __init__(self, simulator, position=(0, 0, 0.4), orientation=(0, 0, 0, 1), fixed_base=False,
|
||||
scaling=1., urdf=os.path.dirname(__file__) + '/urdfs/bb8/bb8.urdf'):
|
||||
scale=1., urdf=os.path.dirname(__file__) + '/urdfs/bb8/bb8.urdf'):
|
||||
# check parameters
|
||||
if position is None:
|
||||
position = (0., 0., 0.4)
|
||||
@@ -35,7 +35,7 @@ class BB8(Robot):
|
||||
if fixed_base is None:
|
||||
fixed_base = False
|
||||
|
||||
super(BB8, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(BB8, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'bb8'
|
||||
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ class Blackbird(BipedRobot):
|
||||
position=(0, 0, 1.2),
|
||||
orientation=(0, 0, 0, 1),
|
||||
fixed_base=False,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/blackbird/blackbird_biped.urdf'):
|
||||
|
||||
self.height = 1.2
|
||||
@@ -47,7 +47,7 @@ class Blackbird(BipedRobot):
|
||||
if fixed_base is None:
|
||||
fixed_base = False
|
||||
|
||||
super(Blackbird, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(Blackbird, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'blackbird'
|
||||
|
||||
# TODO: create constraints in pybullet
|
||||
|
||||
@@ -38,7 +38,7 @@ class CartPole(Robot):
|
||||
simulator,
|
||||
position=(0, 0, 0),
|
||||
orientation=(0, 0, 0, 1),
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
fixed_base=True,
|
||||
urdf=os.path.join(pybullet_data.getDataPath(), "cartpole.urdf"),
|
||||
num_links=1,
|
||||
@@ -54,7 +54,7 @@ class CartPole(Robot):
|
||||
if fixed_base is None:
|
||||
fixed_base = True
|
||||
|
||||
super(CartPole, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(CartPole, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'cartpole'
|
||||
|
||||
# create dynamically other links if necessary
|
||||
|
||||
@@ -36,7 +36,7 @@ class Cassie(BipedRobot):
|
||||
position=(0, 0, .8),
|
||||
orientation=(0, 0, 0, 1),
|
||||
fixed_base=False,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/cassie/cassie.urdf'):
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -48,7 +48,7 @@ class Cassie(BipedRobot):
|
||||
if fixed_base is None:
|
||||
fixed_base = False
|
||||
|
||||
super(Cassie, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(Cassie, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'cassie'
|
||||
|
||||
# TODO: create constraints in pybullet
|
||||
|
||||
@@ -30,7 +30,7 @@ class Centauro(WheeledRobot, QuadrupedRobot, BiManipulatorRobot):
|
||||
position=(0, 0, 1.),
|
||||
orientation=(0, 0, 0, 1),
|
||||
fixed_base=False,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/centauro/centauro_stick.urdf'
|
||||
# centauro_stick.urdf, centauro_soft_hand.urdf, centauro_heri.urdf,
|
||||
# centauro_schunk_handL.urdf, centauro_schunk_hand.urdf
|
||||
@@ -45,7 +45,7 @@ class Centauro(WheeledRobot, QuadrupedRobot, BiManipulatorRobot):
|
||||
if fixed_base is None:
|
||||
fixed_base = False
|
||||
|
||||
super(Centauro, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling=scaling)
|
||||
super(Centauro, self).__init__(simulator, urdf, position, orientation, fixed_base, scale=scale)
|
||||
self.name = 'centauro'
|
||||
|
||||
self.necks = [self.get_link_ids(link) for link in ['neck_' + str(i) for i in range(1, 4)]]
|
||||
|
||||
@@ -28,7 +28,7 @@ class Cogimon(BipedRobot, BiManipulatorRobot):
|
||||
position=(0, 0, 1.),
|
||||
orientation=(0, 0, 0, 1),
|
||||
fixed_base=False,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/cogimon/cogimon.urdf',
|
||||
lower_body=False): # cogimon_lower_body.urdf
|
||||
|
||||
@@ -44,7 +44,7 @@ class Cogimon(BipedRobot, BiManipulatorRobot):
|
||||
if lower_body:
|
||||
urdf = os.path.dirname(__file__) + '/urdfs/cogimon/cogimon_lower_body.urdf'
|
||||
|
||||
super(Cogimon, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(Cogimon, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'cogimon'
|
||||
|
||||
self.waist = self.get_link_ids('DWL') if 'DWL' in self.link_names else None
|
||||
|
||||
@@ -29,7 +29,7 @@ class Coman(BipedRobot, BiManipulatorRobot):
|
||||
position=(0, 0, 0.5),
|
||||
orientation=(0, 0, 0, 1),
|
||||
fixed_base=False,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/coman/coman.urdf'):
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -41,7 +41,7 @@ class Coman(BipedRobot, BiManipulatorRobot):
|
||||
if fixed_base is None:
|
||||
fixed_base = False
|
||||
|
||||
super(Coman, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(Coman, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'coman'
|
||||
|
||||
self.torso = [self.get_link_ids(link) for link in ['DWL', 'DWS', 'DWYTorso'] if link in self.link_names]
|
||||
|
||||
@@ -28,7 +28,7 @@ class Crab(HexapodRobot):
|
||||
position=(0, 0, 0.12),
|
||||
orientation=(0, 0, 0, 1),
|
||||
fixed_base=False,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/crab/crab.urdf'):
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -40,7 +40,7 @@ class Crab(HexapodRobot):
|
||||
if fixed_base is None:
|
||||
fixed_base = False
|
||||
|
||||
super(Crab, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(Crab, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'crab'
|
||||
|
||||
self.legs = [[self.get_link_ids(link) for link in links if link in self.link_names]
|
||||
|
||||
@@ -36,7 +36,7 @@ class Cubli(Robot):
|
||||
position=(0, 0, 0.5),
|
||||
orientation=(0, 0, 0, 1),
|
||||
fixed_base=False,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/cubli/cubli.urdf'):
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -48,7 +48,7 @@ class Cubli(Robot):
|
||||
if fixed_base is None:
|
||||
fixed_base = False
|
||||
|
||||
super(Cubli, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(Cubli, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'cubli'
|
||||
|
||||
# disable each motor joint
|
||||
@@ -72,7 +72,7 @@ if __name__ == "__main__":
|
||||
scale = 1. # Warning: this does not scale the mass...
|
||||
position = [0., 0., np.sqrt(2) / 2. * scale + 0.001]
|
||||
orientation = [0.383, 0, 0, 0.924]
|
||||
robot = Cubli(sim, position, orientation, scaling=scale)
|
||||
robot = Cubli(sim, position, orientation, scale=scale)
|
||||
|
||||
# print information about the robot
|
||||
robot.print_info()
|
||||
|
||||
@@ -29,7 +29,7 @@ class Darwin(BipedRobot, BiManipulatorRobot):
|
||||
position=(0, 0, 0.34),
|
||||
orientation=(0, 0, 0, 1),
|
||||
fixed_base=False,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/darwin/darwin.urdf'):
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -41,7 +41,7 @@ class Darwin(BipedRobot, BiManipulatorRobot):
|
||||
if fixed_base is None:
|
||||
fixed_base = False
|
||||
|
||||
super(Darwin, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(Darwin, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'darwin'
|
||||
|
||||
# self.torso = [self.get_link_ids(link) for link in ['DWL', 'DWS', 'DWYTorso'] if link in self.link_names]
|
||||
|
||||
@@ -31,7 +31,7 @@ class Edo(ManipulatorRobot):
|
||||
position=(0, 0, 0),
|
||||
orientation=(0, 0, 0, 1),
|
||||
fixed_base=True,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/edo/edo.urdf'):
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -43,7 +43,7 @@ class Edo(ManipulatorRobot):
|
||||
if fixed_base is None:
|
||||
fixed_base = True
|
||||
|
||||
super(Edo, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(Edo, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'edo'
|
||||
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ class Epuck(DifferentialWheeledRobot):
|
||||
position=(0, 0, 0),
|
||||
orientation=(0, 0, 0, 1),
|
||||
fixed_base=False,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/epuck/epuck.urdf'):
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -42,7 +42,7 @@ class Epuck(DifferentialWheeledRobot):
|
||||
if fixed_base is None:
|
||||
fixed_base = False
|
||||
|
||||
super(Epuck, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(Epuck, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'epuck'
|
||||
|
||||
self.wheels = [self.get_link_ids(link) for link in ['left_wheel', 'right_wheel']
|
||||
|
||||
@@ -28,7 +28,7 @@ class F10Racecar(AckermannWheeledRobot):
|
||||
position=(0, 0, .1),
|
||||
orientation=(0, 0, 0, 1),
|
||||
fixed_base=False,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/f10_racecar/racecar.urdf'): # racecar_differential.urdf
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -40,7 +40,7 @@ class F10Racecar(AckermannWheeledRobot):
|
||||
if fixed_base is None:
|
||||
fixed_base = False
|
||||
|
||||
super(F10Racecar, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(F10Racecar, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'racecar'
|
||||
|
||||
self.wheels = [self.get_link_ids(link) for link in ['left_front_wheel', 'right_front_wheel',
|
||||
|
||||
@@ -29,7 +29,7 @@ class Fetch(WheeledRobot, ManipulatorRobot):
|
||||
position=(0, 0, 0.1),
|
||||
orientation=(0, 0, 0, 1),
|
||||
fixed_base=False,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/fetch/fetch.urdf'):
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -41,7 +41,7 @@ class Fetch(WheeledRobot, ManipulatorRobot):
|
||||
if fixed_base is None:
|
||||
fixed_base = False
|
||||
|
||||
super(Fetch, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(Fetch, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'fetch'
|
||||
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ class Franka(ManipulatorRobot):
|
||||
simulator,
|
||||
position=(0, 0, 0),
|
||||
orientation=(0, 0, 0, 1),
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
fixed_base=True,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/franka/franka.urdf'):
|
||||
# check parameters
|
||||
@@ -44,7 +44,7 @@ class Franka(ManipulatorRobot):
|
||||
if fixed_base is None:
|
||||
fixed_base = True
|
||||
|
||||
super(Franka, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(Franka, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'franka'
|
||||
|
||||
# self.disable_motor()
|
||||
|
||||
@@ -27,7 +27,7 @@ class HalfCheetah(Robot):
|
||||
position=(-0.5, 0, 0.1),
|
||||
orientation=(0, 0.707, 0, 0.707),
|
||||
fixed_base=False,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/mjcfs/half_cheetah.xml'):
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -39,7 +39,7 @@ class HalfCheetah(Robot):
|
||||
if fixed_base is None:
|
||||
fixed_base = False
|
||||
|
||||
super(HalfCheetah, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(HalfCheetah, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'halfCheetah'
|
||||
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ __status__ = "Development"
|
||||
|
||||
class Hand(Robot):
|
||||
r"""Hand end-effector
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self,
|
||||
@@ -25,8 +24,8 @@ class Hand(Robot):
|
||||
position=(0, 0, 1.),
|
||||
orientation=(0, 0, 0, 1),
|
||||
fixed_base=False,
|
||||
scaling=1.):
|
||||
super(Hand, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
scale=1.):
|
||||
super(Hand, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
|
||||
self.fingers = [] # list of fingers where each finger is a list of links/joints
|
||||
|
||||
@@ -53,8 +52,8 @@ class TwoHand(Hand):
|
||||
position=(0, 0, 1.),
|
||||
orientation=(0, 0, 0, 1),
|
||||
fixed_base=False,
|
||||
scaling=1.):
|
||||
super(TwoHand, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
scale=1.):
|
||||
super(TwoHand, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
|
||||
self.left_fingers = [] # list of ids in self.fingers
|
||||
self.right_fingers = [] # list of ids in self.fingers
|
||||
|
||||
@@ -27,7 +27,7 @@ class Hopper(Robot):
|
||||
position=(-0.5, 0, 0.1),
|
||||
orientation=(0, 0.707, 0, 0.707),
|
||||
fixed_base=False,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/mjcfs/hopper.xml'):
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -39,7 +39,7 @@ class Hopper(Robot):
|
||||
if fixed_base is None:
|
||||
fixed_base = False
|
||||
|
||||
super(Hopper, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(Hopper, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'hopper'
|
||||
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ class Hubo(BipedRobot, BiManipulatorRobot, TwoHand):
|
||||
position=(0, 0, 1),
|
||||
orientation=(0, 0, 0, 1),
|
||||
fixed_base=False,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/hubo/hubo.urdf'):
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -50,7 +50,7 @@ class Hubo(BipedRobot, BiManipulatorRobot, TwoHand):
|
||||
if fixed_base is None:
|
||||
fixed_base = False
|
||||
|
||||
super(Hubo, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(Hubo, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'hubo'
|
||||
|
||||
self.neck = [self.get_link_ids(link) for link in ['Body_Neck', 'Body_Head_Empty', 'Body_Head']
|
||||
|
||||
@@ -28,7 +28,7 @@ class Humanoid(BipedRobot, BiManipulatorRobot):
|
||||
position=(-0.5, 0, 1.),
|
||||
orientation=(0, 0.707, 0, 0.707),
|
||||
fixed_base=False,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/mjcfs/humanoid.xml'): # humanoid_symmetric.xml
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -40,7 +40,7 @@ class Humanoid(BipedRobot, BiManipulatorRobot):
|
||||
if fixed_base is None:
|
||||
fixed_base = False
|
||||
|
||||
super(Humanoid, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(Humanoid, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'humanoid'
|
||||
|
||||
# self.waist = self.get_link_ids('DWL') if 'DWL' in self.link_names else None
|
||||
|
||||
@@ -32,7 +32,7 @@ class Husky(DifferentialWheeledRobot):
|
||||
position=(0, 0, .14),
|
||||
orientation=(0, 0, 0, 1),
|
||||
fixed_base=False,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/husky/husky.urdf'):
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -44,7 +44,7 @@ class Husky(DifferentialWheeledRobot):
|
||||
if fixed_base is None:
|
||||
fixed_base = False
|
||||
|
||||
super(Husky, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(Husky, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'husky'
|
||||
|
||||
self.wheels = [self.get_link_ids(link) for link in ['front_left_wheel_link', 'front_right_wheel_link',
|
||||
|
||||
@@ -30,7 +30,7 @@ class HyQ(QuadrupedRobot):
|
||||
position=(0, 0, .9),
|
||||
orientation=(0, 0, 0, 1),
|
||||
fixed_base=False,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/hyq/hyq.urdf'):
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -42,7 +42,7 @@ class HyQ(QuadrupedRobot):
|
||||
if fixed_base is None:
|
||||
fixed_base = False
|
||||
|
||||
super(HyQ, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(HyQ, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'hyq'
|
||||
|
||||
self.legs = [[self.get_link_ids(link) for link in links if link in self.link_names]
|
||||
|
||||
@@ -34,7 +34,7 @@ class HyQ2Max(QuadrupedRobot):
|
||||
position=(0, 0, 0.8),
|
||||
orientation=(0, 0, 0, 1),
|
||||
fixed_base=False,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/hyq2max/hyq2max.urdf'):
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -46,7 +46,7 @@ class HyQ2Max(QuadrupedRobot):
|
||||
if fixed_base is None:
|
||||
fixed_base = False
|
||||
|
||||
super(HyQ2Max, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(HyQ2Max, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'hyq2max'
|
||||
self.height = 0.9
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ class ICub(BipedRobot, BiManipulatorRobot):
|
||||
position=(0, 0, 0.7),
|
||||
orientation=(0, 0, 1, 0),
|
||||
fixed_base=False,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/icub/icub-v2.5+.urdf'):
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -42,7 +42,7 @@ class ICub(BipedRobot, BiManipulatorRobot):
|
||||
if fixed_base is None:
|
||||
fixed_base = False
|
||||
|
||||
super(ICub, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling=scaling)
|
||||
super(ICub, self).__init__(simulator, urdf, position, orientation, fixed_base, scale=scale)
|
||||
self.name = 'icub'
|
||||
|
||||
self.head = self.get_link_ids('head') if 'head' in self.link_names else None
|
||||
|
||||
@@ -29,7 +29,7 @@ class Jaco(ManipulatorRobot):
|
||||
position=(0, 0, 0),
|
||||
orientation=(0, 0, 0, 1),
|
||||
fixed_base=True,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/jaco/jaco.urdf'):
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -41,7 +41,7 @@ class Jaco(ManipulatorRobot):
|
||||
if fixed_base is None:
|
||||
fixed_base = True
|
||||
|
||||
super(Jaco, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(Jaco, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'jaco'
|
||||
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ class KR5(ManipulatorRobot):
|
||||
position=(0, 0, 0),
|
||||
orientation=(0, 0, 0, 1),
|
||||
fixed_base=True,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/kuka/kr5/kr5.urdf'):
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -43,7 +43,7 @@ class KR5(ManipulatorRobot):
|
||||
if fixed_base is None:
|
||||
fixed_base = True
|
||||
|
||||
super(KR5, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(KR5, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'kr5'
|
||||
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ class KukaIIWA(ManipulatorRobot):
|
||||
simulator,
|
||||
position=(0, 0, 0),
|
||||
orientation=(0, 0, 0, 1),
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
fixed_base=True,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/kuka/kuka_iiwa/iiwa14.urdf'):
|
||||
# check parameters
|
||||
@@ -44,7 +44,7 @@ class KukaIIWA(ManipulatorRobot):
|
||||
if fixed_base is None:
|
||||
fixed_base = True
|
||||
|
||||
super(KukaIIWA, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(KukaIIWA, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'kuka_iiwa'
|
||||
|
||||
# self.disable_motor()
|
||||
|
||||
@@ -32,7 +32,7 @@ class KukaLWR(ManipulatorRobot):
|
||||
position=(0, 0, 0),
|
||||
orientation=(0, 0, 0, 1),
|
||||
fixed_base=True,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/kuka/kuka_lwr/kuka.urdf'):
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -44,7 +44,7 @@ class KukaLWR(ManipulatorRobot):
|
||||
if fixed_base is None:
|
||||
fixed_base = True
|
||||
|
||||
super(KukaLWR, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(KukaLWR, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'kuka_lwr'
|
||||
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ class Laikago(QuadrupedRobot):
|
||||
position=(0, 0, .5),
|
||||
orientation=(0.5, 0.5, 0.5, 0.5),
|
||||
fixed_base=False,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/laikago/laikago.urdf'):
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -41,7 +41,7 @@ class Laikago(QuadrupedRobot):
|
||||
if fixed_base is None:
|
||||
fixed_base = False
|
||||
|
||||
super(Laikago, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(Laikago, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'laikago'
|
||||
|
||||
self.legs = [[self.get_link_ids(link) for link in links if link in self.link_names]
|
||||
|
||||
@@ -28,9 +28,9 @@ class LeggedRobot(Robot):
|
||||
in the standard regime are rhythmic movements.
|
||||
"""
|
||||
|
||||
def __init__(self, simulator, urdf, position=None, orientation=None, fixed_base=False, scaling=1.,
|
||||
def __init__(self, simulator, urdf, position=None, orientation=None, fixed_base=False, scale=1.,
|
||||
foot_frictions=None):
|
||||
super(LeggedRobot, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling=scaling)
|
||||
super(LeggedRobot, self).__init__(simulator, urdf, position, orientation, fixed_base, scale=scale)
|
||||
|
||||
# leg and feet ids
|
||||
self.legs = [] # list of legs where a leg is a list of links
|
||||
@@ -729,8 +729,8 @@ class BipedRobot(LeggedRobot):
|
||||
A biped robot is a robot which has 2 legs.
|
||||
"""
|
||||
|
||||
def __init__(self, simulator, urdf, position=None, orientation=None, fixed_base=False, scaling=1.):
|
||||
super(BipedRobot, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
def __init__(self, simulator, urdf, position=None, orientation=None, fixed_base=False, scale=1.):
|
||||
super(BipedRobot, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
|
||||
self.left_leg_id = 0
|
||||
self.right_leg_id = 1
|
||||
@@ -766,8 +766,8 @@ class QuadrupedRobot(LeggedRobot):
|
||||
A quadruped robot is a robot which has 4 legs.
|
||||
"""
|
||||
|
||||
def __init__(self, simulator, urdf, position=None, orientation=None, fixed_base=False, scaling=1.):
|
||||
super(QuadrupedRobot, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
def __init__(self, simulator, urdf, position=None, orientation=None, fixed_base=False, scale=1.):
|
||||
super(QuadrupedRobot, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
|
||||
self.left_front_leg_id = 0
|
||||
self.right_front_leg_id = 1
|
||||
@@ -825,8 +825,8 @@ class HexapodRobot(LeggedRobot):
|
||||
An hexapod robot is a robot which has 6 legs.
|
||||
"""
|
||||
|
||||
def __init__(self, simulator, urdf, position, orientation=None, fixed_base=False, scaling=1.):
|
||||
super(HexapodRobot, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
def __init__(self, simulator, urdf, position, orientation=None, fixed_base=False, scale=1.):
|
||||
super(HexapodRobot, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
|
||||
self.left_front_leg_id = 0
|
||||
self.right_front_leg_id = 1
|
||||
|
||||
@@ -30,7 +30,7 @@ class LittleDog(QuadrupedRobot):
|
||||
position=(0, 0, 0.2),
|
||||
orientation=(0, 0, 0, 1),
|
||||
fixed_base=False,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/littledog/littleDog.urdf'):
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -42,7 +42,7 @@ class LittleDog(QuadrupedRobot):
|
||||
if fixed_base is None:
|
||||
fixed_base = False
|
||||
|
||||
super(LittleDog, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(LittleDog, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'littledog'
|
||||
|
||||
self.legs = [[self.get_link_ids(link) for link in links if link in self.link_names]
|
||||
|
||||
@@ -26,8 +26,8 @@ class ManipulatorRobot(Robot):
|
||||
position=(0, 0, 0.),
|
||||
orientation=(0, 0, 0, 1),
|
||||
fixed_base=False,
|
||||
scaling=1.):
|
||||
super(ManipulatorRobot, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
scale=1.):
|
||||
super(ManipulatorRobot, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
|
||||
self.arms = [] # list of arms where an arm is a list of links
|
||||
self.hands = [] # list of end-effectors/hands
|
||||
@@ -124,8 +124,8 @@ class BiManipulatorRobot(ManipulatorRobot):
|
||||
"""
|
||||
|
||||
def __init__(self, simulator, urdf, position=(0, 0, 1.5), orientation=(0, 0, 0, 1), fixed_base=False,
|
||||
scaling=1.):
|
||||
super(BiManipulatorRobot, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
scale=1.):
|
||||
super(BiManipulatorRobot, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
|
||||
self.left_arm_id = 0
|
||||
self.left_hand_id = 0
|
||||
|
||||
@@ -28,7 +28,7 @@ class Manipulator2D(ManipulatorRobot):
|
||||
position=(0, 0, 0),
|
||||
orientation=(0, 0, 0, 1),
|
||||
fixed_base=False,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/manipulator2d/manipulator2d.urdf'):
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -40,7 +40,7 @@ class Manipulator2D(ManipulatorRobot):
|
||||
if fixed_base is None:
|
||||
fixed_base = False
|
||||
|
||||
super(Manipulator2D, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(Manipulator2D, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'manipulator2d'
|
||||
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ class Minitaur(QuadrupedRobot):
|
||||
position=(0, 0, .3),
|
||||
orientation=(0, 0, 0, 1),
|
||||
fixed_base=False,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
couple_legs=True,
|
||||
foot_friction=1.,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/minitaur/minitaur.urdf'):
|
||||
@@ -47,7 +47,7 @@ class Minitaur(QuadrupedRobot):
|
||||
if fixed_base is None:
|
||||
fixed_base = False
|
||||
|
||||
super(Minitaur, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(Minitaur, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'minitaur'
|
||||
|
||||
self.base_height = 0.1638
|
||||
|
||||
@@ -32,7 +32,7 @@ class MKZ(AckermannWheeledRobot):
|
||||
position=(0, 0, .4),
|
||||
orientation=(0, 0, 0, 1),
|
||||
fixed_base=False,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/mkz/mkz.urdf'):
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -44,7 +44,7 @@ class MKZ(AckermannWheeledRobot):
|
||||
if fixed_base is None:
|
||||
fixed_base = False
|
||||
|
||||
super(MKZ, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(MKZ, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'mkz'
|
||||
|
||||
self.wheels = [self.get_link_ids(link) for link in ['wheel_fl', 'wheel_fr', 'wheel_rl', 'wheel_rr']
|
||||
|
||||
@@ -28,7 +28,7 @@ class Morphex(HexapodRobot):
|
||||
position=(0, 0, 0.2),
|
||||
orientation=(0, 0, 0, 1),
|
||||
fixed_base=False,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/morphex/morphex.urdf'):
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -40,7 +40,7 @@ class Morphex(HexapodRobot):
|
||||
if fixed_base is None:
|
||||
fixed_base = False
|
||||
|
||||
super(Morphex, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(Morphex, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'morphex'
|
||||
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ class Nao(BipedRobot, BiManipulatorRobot, TwoHand):
|
||||
position=(0, 0, 0.35),
|
||||
orientation=(0, 0, 0, 1),
|
||||
fixed_base=False,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/nao/nao_v40.urdf'):
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -39,7 +39,7 @@ class Nao(BipedRobot, BiManipulatorRobot, TwoHand):
|
||||
if fixed_base is None:
|
||||
fixed_base = False
|
||||
|
||||
super(Nao, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(Nao, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'nao'
|
||||
|
||||
self.neck = self.get_link_ids('Neck') if 'Neck' in self.link_names else None
|
||||
|
||||
@@ -28,7 +28,7 @@ class OpenDog(QuadrupedRobot):
|
||||
position=(0, 0, .6),
|
||||
orientation=(0, 0, 0, 1),
|
||||
fixed_base=False,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/opendog/opendog.urdf'):
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -40,7 +40,7 @@ class OpenDog(QuadrupedRobot):
|
||||
if fixed_base is None:
|
||||
fixed_base = False
|
||||
|
||||
super(OpenDog, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(OpenDog, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'opendog'
|
||||
|
||||
self.legs = [[self.get_link_ids(link) for link in links if link in self.link_names]
|
||||
|
||||
@@ -34,7 +34,7 @@ class Pepper(WheeledRobot, BiManipulatorRobot):
|
||||
position=(0, 0, 0.9),
|
||||
orientation=(0, 0, 0, 1),
|
||||
fixed_base=False,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/pepper/pepper.urdf'):
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -46,7 +46,7 @@ class Pepper(WheeledRobot, BiManipulatorRobot):
|
||||
if fixed_base is None:
|
||||
fixed_base = False
|
||||
|
||||
super(Pepper, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling=scaling)
|
||||
super(Pepper, self).__init__(simulator, urdf, position, orientation, fixed_base, scale=scale)
|
||||
self.name = 'pepper'
|
||||
|
||||
# 2D Camera sensor
|
||||
@@ -55,16 +55,16 @@ class Pepper(WheeledRobot, BiManipulatorRobot):
|
||||
|
||||
# Note that we divide width and height by 4 (otherwise the simulator is pretty slow)
|
||||
self.camera_top = CameraSensor(self.sim, self.id, 4, width=2560 / 4, height=1080 / 4, fovy=44.30,
|
||||
near=0.3, far=100, refresh_rate=60)
|
||||
near=0.3, far=100, rate=60)
|
||||
self.camera_bottom = CameraSensor(self.sim, self.id, 9, width=2560 / 4, height=1080 / 4, fovy=44.30,
|
||||
near=0.3, far=100, refresh_rate=60)
|
||||
near=0.3, far=100, rate=60)
|
||||
|
||||
# 3D camera sensor
|
||||
# From [1]: "One 3D camera is located in the forehead. It provides image resolution up to 320x240 at
|
||||
# 20 frames per second. One ASUS Xtion 3D sensor is located behind the eyes. VFOV = 45 deg, HFOV = 58 deg,
|
||||
# focus = [80cm, 3.5m]."
|
||||
self.camera_depth = CameraSensor(self.sim, self.id, 6, width=320, height=240, fovy=45, near=0.3, far=3.5,
|
||||
refresh_rate=120)
|
||||
rate=120)
|
||||
|
||||
self.cameras = [self.camera_top, self.camera_bottom, self.camera_depth]
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ class PhantomX(HexapodRobot):
|
||||
position=(0, 0, 0.2),
|
||||
orientation=(0, 0, 0, 1),
|
||||
fixed_base=False,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/phantomx/phantomx.urdf'):
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -39,7 +39,7 @@ class PhantomX(HexapodRobot):
|
||||
if fixed_base is None:
|
||||
fixed_base = False
|
||||
|
||||
super(PhantomX, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(PhantomX, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'phantomx'
|
||||
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ class Pleurobot(QuadrupedRobot, UUVRobot, USVRobot):
|
||||
[2] https://biorob.epfl.ch/pleurobot
|
||||
"""
|
||||
|
||||
def __init__(self, simulator, position=(0, 0, 0), orientation=(0, 0, 0, 1), fixed_base=False, scaling=1.,
|
||||
def __init__(self, simulator, position=(0, 0, 0), orientation=(0, 0, 0, 1), fixed_base=False, scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/pleurobot/pleurobot.urdf'):
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -37,7 +37,7 @@ class Pleurobot(QuadrupedRobot, UUVRobot, USVRobot):
|
||||
if fixed_base is None:
|
||||
fixed_base = False
|
||||
|
||||
super(Pleurobot, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(Pleurobot, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'pleurobot'
|
||||
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ class PR2(WheeledRobot, BiManipulatorRobot):
|
||||
position=(0, 0, 0),
|
||||
orientation=(0, 0, 0, 1),
|
||||
fixed_base=False,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/pr2/pr2.urdf'):
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -41,7 +41,7 @@ class PR2(WheeledRobot, BiManipulatorRobot):
|
||||
if fixed_base is None:
|
||||
fixed_base = False
|
||||
|
||||
super(PR2, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(PR2, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'pr2'
|
||||
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ class Quadcopter(RotaryWingUAV):
|
||||
position=(0, 0, 0.2),
|
||||
orientation=(0, 0, 0, 1),
|
||||
fixed_base=False,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/quadcopter/quadcopter.urdf'):
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -80,7 +80,7 @@ class Quadcopter(RotaryWingUAV):
|
||||
if fixed_base is None:
|
||||
fixed_base = False
|
||||
|
||||
super(Quadcopter, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(Quadcopter, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'quadcopter'
|
||||
|
||||
self.gravity = 9.81
|
||||
|
||||
@@ -34,7 +34,7 @@ class Rhex(HexapodRobot):
|
||||
position=(0, 0, 0.12),
|
||||
orientation=(0, 0, 0, 1),
|
||||
fixed_base=False,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/rhex/rhex.urdf'):
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -46,7 +46,7 @@ class Rhex(HexapodRobot):
|
||||
if fixed_base is None:
|
||||
fixed_base = False
|
||||
|
||||
super(Rhex, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(Rhex, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'rhex'
|
||||
|
||||
self.legs = [[self.get_link_ids(link + str(idx))] for link, idx in zip(['leg'] * 6, range(1, 7))
|
||||
|
||||
+44
-16
@@ -10,11 +10,12 @@ Dependencies:
|
||||
- `pyrobolearn.utils`
|
||||
"""
|
||||
|
||||
import os
|
||||
import copy
|
||||
import collections
|
||||
# import rbdl
|
||||
import numpy as np
|
||||
# import quaternion
|
||||
import collections
|
||||
import os
|
||||
|
||||
from pyrobolearn.utils.transformation import *
|
||||
from pyrobolearn.robots.base import ControllableBody
|
||||
@@ -37,7 +38,7 @@ class Robot(ControllableBody):
|
||||
and has been implemented such that it is very generic.
|
||||
"""
|
||||
|
||||
def __init__(self, simulator, urdf, position=None, orientation=None, fixed_base=False, scaling=1., *args, **kwargs):
|
||||
def __init__(self, simulator, urdf, position=None, orientation=None, fixed_base=False, scale=1., *args, **kwargs):
|
||||
"""
|
||||
Initialize the robot.
|
||||
|
||||
@@ -47,7 +48,7 @@ class Robot(ControllableBody):
|
||||
position (np.float[3]): initial position.
|
||||
orientation (np.float[4]): initial orientation represented as a quaternion (x,y,z,w).
|
||||
fixed_base (bool, None): if True, the base of the robot will be fixed.
|
||||
scaling (float): scaling factor.
|
||||
scale (float): scaling factor.
|
||||
"""
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -66,18 +67,23 @@ class Robot(ControllableBody):
|
||||
if urdf[-3:] == 'xml' or urdf[-4:] == 'mjcf':
|
||||
self.id = self.sim.load_mjcf(urdf)[0] # assume the first entity is the robot
|
||||
else: # if urdf[-4:] == 'urdf':
|
||||
self.id = self.sim.load_urdf(urdf, position, orientation, use_fixed_base=fixed_base, scale=scaling)
|
||||
self.id = self.sim.load_urdf(urdf, position, orientation, use_fixed_base=fixed_base, scale=scale)
|
||||
|
||||
# self.sim.configure_debug_visualizer(self.sim.COV_ENABLE_RENDERING, 1)
|
||||
|
||||
# save the input parameters
|
||||
self.urdf = urdf
|
||||
self.fixed_base = fixed_base
|
||||
self.scale = scale
|
||||
|
||||
# rescale if specified
|
||||
if scaling != 1.0:
|
||||
if scale != 1.0:
|
||||
# we rescale manually the mass and inertia matrices of each link
|
||||
for link in range(self.num_links):
|
||||
info = self.sim.get_dynamics_info(self.id, link)
|
||||
mass, local_inertia_diagonal = info[0], np.array(info[2])
|
||||
mass *= scaling**3 # because the density is unchanged when scaling
|
||||
local_inertia_diagonal *= scaling**5 # 5 = 3+2; 3 is for the mass, and 2 is for the distance: I~mr^2
|
||||
mass *= scale ** 3 # because the density is unchanged when scaling
|
||||
local_inertia_diagonal *= scale ** 5 # 5 = 3+2; 3 is for the mass, and 2 is for the distance: I~mr^2
|
||||
self.sim.change_dynamics(self.id, link, mass=mass, local_inertia_diagonal=local_inertia_diagonal)
|
||||
|
||||
# set robot properties
|
||||
@@ -138,14 +144,34 @@ class Robot(ControllableBody):
|
||||
# Gains
|
||||
self.kp, self.kd = None, None
|
||||
|
||||
def __repr__(self):
|
||||
"""
|
||||
Return the name of the class.
|
||||
#############
|
||||
# Operators #
|
||||
#############
|
||||
|
||||
Returns:
|
||||
str: name of the class
|
||||
def __copy__(self):
|
||||
"""Return a shallow copy of the robot. This can be overridden in the child class."""
|
||||
return self.__class__(simulator=self.simulator, urdf=self.urdf, position=self.position,
|
||||
orientation=self.orientation, fixed_base=self.fixed_base, scale=self.scale)
|
||||
|
||||
def __deepcopy__(self, memo={}):
|
||||
"""Return a deep copy of the robot. This can be overridden in the child class.
|
||||
|
||||
Args:
|
||||
memo (dict): memo dictionary of objects already copied during the current copying pass
|
||||
"""
|
||||
return self.__class__.__name__
|
||||
simulator = copy.deepcopy(self.simulator, memo)
|
||||
urdf = copy.deepcopy(self.urdf)
|
||||
position = copy.deepcopy(self.position)
|
||||
orientation = copy.deepcopy(self.orientation)
|
||||
robot = self.__class__(simulator=simulator, urdf=urdf, position=position, orientation=orientation,
|
||||
fixed_base=self.fixed_base, scale=self.scale)
|
||||
|
||||
# update the memodict (note that `copy.deepcopy` will automatically check this dictionary and return the
|
||||
# reference if already present)
|
||||
memo[self] = robot
|
||||
|
||||
# return the copy
|
||||
return robot
|
||||
|
||||
##############
|
||||
# Properties #
|
||||
@@ -248,7 +274,8 @@ class Robot(ControllableBody):
|
||||
Returns:
|
||||
bool: True if the robot has a floating base.
|
||||
"""
|
||||
return self.floating_base
|
||||
# return self.floating_base
|
||||
return not self.fixed_base
|
||||
|
||||
def has_fixed_base(self):
|
||||
"""
|
||||
@@ -257,7 +284,8 @@ class Robot(ControllableBody):
|
||||
Returns:
|
||||
bool: True if the robot has a fixed base.
|
||||
"""
|
||||
return not self.has_floating_base()
|
||||
# return not self.has_floating_base()
|
||||
return self.fixed_base
|
||||
|
||||
#######
|
||||
# CoM #
|
||||
|
||||
@@ -28,7 +28,7 @@ class RRBot(ManipulatorRobot):
|
||||
position=(0, 0, 0),
|
||||
orientation=(0, 0, 0, 1),
|
||||
fixed_base=True,
|
||||
scaling=1,
|
||||
scale=1,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/rrbot/rrbot.urdf'):
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -40,7 +40,7 @@ class RRBot(ManipulatorRobot):
|
||||
if fixed_base is None:
|
||||
fixed_base = True
|
||||
|
||||
super(RRBot, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(RRBot, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'rrbot'
|
||||
|
||||
# set initial joint positions
|
||||
|
||||
@@ -31,7 +31,7 @@ class Sawyer(ManipulatorRobot, WheeledRobot):
|
||||
position=(0, 0, 0.92),
|
||||
orientation=(0, 0, 0, 1),
|
||||
fixed_base=True,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/sawyer/sawyer.urdf'):
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -43,7 +43,7 @@ class Sawyer(ManipulatorRobot, WheeledRobot):
|
||||
if fixed_base is None:
|
||||
fixed_base = True
|
||||
|
||||
super(Sawyer, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(Sawyer, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'sawyer'
|
||||
|
||||
self.head = self.get_link_ids('head') if 'head' in self.link_names else None
|
||||
|
||||
@@ -27,7 +27,7 @@ class SEAHexapod(HexapodRobot):
|
||||
position=(0, 0, 0.15),
|
||||
orientation=(0, 0, 0.707, 0.707),
|
||||
fixed_base=False,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/cmu_sea/hexapod.urdf'):
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -39,7 +39,7 @@ class SEAHexapod(HexapodRobot):
|
||||
if fixed_base is None:
|
||||
fixed_base = False
|
||||
|
||||
super(SEAHexapod, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(SEAHexapod, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'sea_hexapod'
|
||||
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ class SEASnake(Robot):
|
||||
position=(-0.5, 0, 0.1),
|
||||
orientation=(0, 0.707, 0, 0.707),
|
||||
fixed_base=False,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/cmu_sea/snake.urdf'):
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -39,7 +39,7 @@ class SEASnake(Robot):
|
||||
if fixed_base is None:
|
||||
fixed_base = False
|
||||
|
||||
super(SEASnake, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(SEASnake, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'sea_snake'
|
||||
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ class CameraSensor(LinkSensor):
|
||||
[4] http://learnwebgl.brown37.net/08_projections/projections_perspective.html
|
||||
"""
|
||||
|
||||
def __init__(self, simulator, body_id, link_id, width, height, position=None, orientation=None, refresh_rate=50,
|
||||
def __init__(self, simulator, body_id, link_id, width, height, position=None, orientation=None, rate=50,
|
||||
target_position=None, distance=10.,
|
||||
fovy=60, aspect=None, near=0.01, far=100.,
|
||||
left=None, right=None, bottom=None, top=None):
|
||||
@@ -97,7 +97,7 @@ class CameraSensor(LinkSensor):
|
||||
bottom (float): bottom screen (canvas) coordinate
|
||||
top (float): top screen (canvas) coordinate
|
||||
"""
|
||||
super(CameraSensor, self).__init__(simulator, body_id, link_id, position, orientation, refresh_rate)
|
||||
super(CameraSensor, self).__init__(simulator, body_id, link_id, position, orientation, rate)
|
||||
|
||||
self.width = width
|
||||
self.height = height
|
||||
|
||||
@@ -20,8 +20,8 @@ class ContactSensor(LinkSensor):
|
||||
This sensor return 1 if in contact with an object, and 0 otherwise.
|
||||
"""
|
||||
|
||||
def __init__(self, simulator, body_id, link_id, position, orientation, refresh_rate=1):
|
||||
super(ContactSensor, self).__init__(simulator, body_id, link_id, position, orientation, refresh_rate)
|
||||
def __init__(self, simulator, body_id, link_id, position, orientation, rate=1):
|
||||
super(ContactSensor, self).__init__(simulator, body_id, link_id, position, orientation, rate)
|
||||
|
||||
def get_contact_points(self):
|
||||
"""Get the contact points.
|
||||
|
||||
@@ -22,8 +22,8 @@ class ForceTorqueSensor(JointSensor):
|
||||
The F/T sensor allows to measure the forces and torques applied to it.
|
||||
"""
|
||||
|
||||
def __init__(self, simulator, body_id, joint_id, position, orientation, refresh_rate=1):
|
||||
super(ForceTorqueSensor, self).__init__(simulator, body_id, joint_id, position, orientation, refresh_rate)
|
||||
def __init__(self, simulator, body_id, joint_id, position, orientation, rate=1):
|
||||
super(ForceTorqueSensor, self).__init__(simulator, body_id, joint_id, position, orientation, rate)
|
||||
self.sim.enable_joint_force_torque_sensor(body_id, joint_id, enableSensor=True)
|
||||
|
||||
def _sense(self):
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
This mainly include encoders.
|
||||
"""
|
||||
|
||||
import copy
|
||||
from abc import ABCMeta, abstractmethod
|
||||
|
||||
from pyrobolearn.robots.sensors.sensor import Sensor
|
||||
@@ -25,7 +26,7 @@ class JointSensor(Sensor):
|
||||
"""
|
||||
__metaclass__ = ABCMeta
|
||||
|
||||
def __init__(self, simulator, body_id, joint_id, position=None, orientation=None, refresh_rate=1):
|
||||
def __init__(self, simulator, body_id, joint_id, position=None, orientation=None, rate=1):
|
||||
"""Initialize the sensor.
|
||||
|
||||
Args:
|
||||
@@ -34,9 +35,9 @@ class JointSensor(Sensor):
|
||||
joint_id (int): unique id of the joint
|
||||
position (vec3): local position of the sensor with respect to the given joint
|
||||
orientation (vec4): local orientation of the sensor with respect to the given joint
|
||||
refresh_rate (int): number of steps to wait before acquisition of the next sensor value.
|
||||
rate (int): number of steps to wait before acquisition of the next sensor value.
|
||||
"""
|
||||
super(JointSensor, self).__init__(simulator, body_id, position, orientation, refresh_rate)
|
||||
super(JointSensor, self).__init__(simulator, body_id, position, orientation, rate)
|
||||
self.joint_id = joint_id
|
||||
|
||||
@property
|
||||
@@ -50,6 +51,28 @@ class JointSensor(Sensor):
|
||||
def _sense(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def __copy__(self):
|
||||
"""Return a shallow copy of the sensor. This can be overridden in the child class."""
|
||||
return self.__class__(simulator=self.simulator, body_id=self.body_id, joint_id=self.joint_id,
|
||||
position=self.local_position, orientation=self.local_orientation, rate=self.rate)
|
||||
|
||||
def __deepcopy__(self, memo={}):
|
||||
"""Return a deep copy of the sensor. This can be overridden in the child class.
|
||||
|
||||
Args:
|
||||
memo (dict): memo dictionary of objects already copied during the current copying pass
|
||||
"""
|
||||
simulator = copy.deepcopy(self.simulator, memo)
|
||||
body_id = copy.deepcopy(self.body_id)
|
||||
joint_id = copy.deepcopy(self.joint_id)
|
||||
position = copy.deepcopy(self.local_position)
|
||||
orientation = copy.deepcopy(self.local_orientation)
|
||||
sensor = self.__class__(simulator=simulator, body_id=body_id, joint_id=joint_id, position=position,
|
||||
orientation=orientation, rate=self.rate)
|
||||
memo[self] = sensor
|
||||
return sensor
|
||||
|
||||
|
||||
|
||||
class Encoder(JointSensor):
|
||||
r"""Encoder joint sensor
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
These include IMU, contact, Camera, and other sensors.
|
||||
"""
|
||||
|
||||
import copy
|
||||
from abc import ABCMeta, abstractmethod
|
||||
|
||||
from pyrobolearn.utils.transformation import get_quaternion_product
|
||||
@@ -28,7 +29,7 @@ class LinkSensor(Sensor):
|
||||
|
||||
__metaclass__ = ABCMeta
|
||||
|
||||
def __init__(self, simulator, body_id, link_id=None, position=None, orientation=None, refresh_rate=1):
|
||||
def __init__(self, simulator, body_id, link_id=None, position=None, orientation=None, rate=1):
|
||||
"""Initialize the sensor.
|
||||
|
||||
Args:
|
||||
@@ -37,9 +38,9 @@ class LinkSensor(Sensor):
|
||||
link_id (int): unique id of the link
|
||||
position (vec3): local position of the sensor with respect to the given link
|
||||
orientation (vec4): local orientation of the sensor with respect to the given link
|
||||
refresh_rate (int): number of steps to wait before acquisition of the next sensor value.
|
||||
rate (int): number of steps to wait before acquisition of the next sensor value.
|
||||
"""
|
||||
super(LinkSensor, self).__init__(simulator, body_id, position, orientation, refresh_rate)
|
||||
super(LinkSensor, self).__init__(simulator, body_id, position, orientation, rate)
|
||||
self.link_id = link_id
|
||||
|
||||
@property
|
||||
@@ -63,3 +64,24 @@ class LinkSensor(Sensor):
|
||||
@abstractmethod
|
||||
def _sense(self):
|
||||
raise NotImplementedError
|
||||
|
||||
def __copy__(self):
|
||||
"""Return a shallow copy of the sensor. This can be overridden in the child class."""
|
||||
return self.__class__(simulator=self.simulator, body_id=self.body_id, link_id=self.link_id,
|
||||
position=self.local_position, orientation=self.local_orientation, rate=self.rate)
|
||||
|
||||
def __deepcopy__(self, memo={}):
|
||||
"""Return a deep copy of the sensor. This can be overridden in the child class.
|
||||
|
||||
Args:
|
||||
memo (dict): memo dictionary of objects already copied during the current copying pass
|
||||
"""
|
||||
simulator = copy.deepcopy(self.simulator, memo)
|
||||
body_id = copy.deepcopy(self.body_id)
|
||||
link_id = copy.deepcopy(self.link_id)
|
||||
position = copy.deepcopy(self.local_position)
|
||||
orientation = copy.deepcopy(self.local_orientation)
|
||||
sensor = self.__class__(simulator=simulator, body_id=body_id, link_id=link_id, position=position,
|
||||
orientation=orientation, rate=self.rate)
|
||||
memo[self] = sensor
|
||||
return sensor
|
||||
|
||||
@@ -8,6 +8,7 @@ simulation to reality. Also, note that some simulators are deterministic and thu
|
||||
add some noise to the returned sense value. The type of noise can also be selected at runtime.
|
||||
"""
|
||||
|
||||
import copy
|
||||
from abc import ABCMeta, abstractmethod
|
||||
import numpy as np
|
||||
|
||||
@@ -33,7 +34,7 @@ class Sensor(object): # sensor attached to a link or joint
|
||||
"""
|
||||
__metaclass__ = ABCMeta
|
||||
|
||||
def __init__(self, simulator, body_id, position=None, orientation=None, refresh_rate=1):
|
||||
def __init__(self, simulator, body_id, position=None, orientation=None, rate=1):
|
||||
"""Initialize the sensor.
|
||||
|
||||
Args:
|
||||
@@ -41,7 +42,7 @@ class Sensor(object): # sensor attached to a link or joint
|
||||
body_id (int): unique id of the body
|
||||
position (vec3): local position of the sensor with respect to the given link
|
||||
orientation (vec4): local orientation of the sensor with respect to the given link
|
||||
refresh_rate (int): number of steps to wait before acquisition of the next sensor value.
|
||||
rate (int): number of steps to wait before acquisition of the next sensor value.
|
||||
"""
|
||||
self.sim = simulator
|
||||
self.body_id = body_id
|
||||
@@ -54,12 +55,21 @@ class Sensor(object): # sensor attached to a link or joint
|
||||
orientation = [0., 0., 0., 1.]
|
||||
self.local_orientation = np.array(orientation)
|
||||
|
||||
self.rate = refresh_rate
|
||||
self.rate = rate
|
||||
self.cnt = -1
|
||||
|
||||
# data from last acquisition
|
||||
self.data = None
|
||||
|
||||
##############
|
||||
# Properties #
|
||||
##############
|
||||
|
||||
@property
|
||||
def simulator(self):
|
||||
"""Return the simulator instance."""
|
||||
return self.sim
|
||||
|
||||
@property
|
||||
def position(self):
|
||||
"""
|
||||
@@ -80,9 +90,11 @@ class Sensor(object): # sensor attached to a link or joint
|
||||
|
||||
@abstractmethod
|
||||
def _sense(self):
|
||||
"""Sense method to be implemented in the child class."""
|
||||
raise NotImplementedError
|
||||
|
||||
def sense(self):
|
||||
"""Get the next sensor value."""
|
||||
self.cnt += 1
|
||||
if self.cnt % self.rate == 0:
|
||||
self.data = self._sense()
|
||||
@@ -90,6 +102,39 @@ class Sensor(object): # sensor attached to a link or joint
|
||||
return self.data
|
||||
return self.data
|
||||
|
||||
#############
|
||||
# Operators #
|
||||
#############
|
||||
|
||||
# alias
|
||||
def __call__(self):
|
||||
"""Get the next sensor value."""
|
||||
return self.sense()
|
||||
|
||||
# def __repr__(self):
|
||||
# """Return a representation string about the class for debugging and development."""
|
||||
# return self.__class__.__name__
|
||||
|
||||
def __str__(self):
|
||||
"""Return a readable string about the class."""
|
||||
return self.__class__.__name__
|
||||
|
||||
def __copy__(self):
|
||||
"""Return a shallow copy of the sensor. This can be overridden in the child class."""
|
||||
return self.__class__(simulator=self.simulator, body_id=self.body_id, position=self.local_position,
|
||||
orientation=self.local_orientation, rate=self.rate)
|
||||
|
||||
def __deepcopy__(self, memo={}):
|
||||
"""Return a deep copy of the sensor. This can be overridden in the child class.
|
||||
|
||||
Args:
|
||||
memo (dict): memo dictionary of objects already copied during the current copying pass
|
||||
"""
|
||||
simulator = copy.deepcopy(self.simulator, memo)
|
||||
body_id = copy.deepcopy(self.body_id)
|
||||
position = copy.deepcopy(self.local_position)
|
||||
orientation = copy.deepcopy(self.local_orientation)
|
||||
sensor = self.__class__(simulator=simulator, body_id=body_id, position=position, orientation=orientation,
|
||||
rate=self.rate)
|
||||
memo[self] = sensor
|
||||
return sensor
|
||||
|
||||
@@ -28,7 +28,7 @@ class ShadowHand(Hand):
|
||||
simulator,
|
||||
position=(0, 0, 0),
|
||||
orientation=(0, 0, 0.707, 0.707),
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
left=True,
|
||||
fixed_base=True):
|
||||
# check parameters
|
||||
@@ -48,7 +48,7 @@ class ShadowHand(Hand):
|
||||
orientation = (0, 0, 1, 0)
|
||||
urdf_path = os.path.dirname(__file__) + '/urdfs/shadowhand/right_hand.urdf'
|
||||
|
||||
super(ShadowHand, self).__init__(simulator, urdf_path, position, orientation, fixed_base, scaling)
|
||||
super(ShadowHand, self).__init__(simulator, urdf_path, position, orientation, fixed_base, scale)
|
||||
self.name = 'shadow_hand'
|
||||
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ class SoftHand(Hand):
|
||||
simulator,
|
||||
position=(0, 0, 0),
|
||||
orientation=(0, 0, 0, 1),
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
left=True,
|
||||
fixed_base=True):
|
||||
# check parameters
|
||||
@@ -48,7 +48,7 @@ class SoftHand(Hand):
|
||||
orientation = (0, 0, 1, 0)
|
||||
urdf_path = os.path.dirname(__file__) + '/urdfs/softhand/right_hand.urdf'
|
||||
|
||||
super(SoftHand, self).__init__(simulator, urdf_path, position, orientation, fixed_base, scaling)
|
||||
super(SoftHand, self).__init__(simulator, urdf_path, position, orientation, fixed_base, scale)
|
||||
self.name = 'soft_hand'
|
||||
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ class Swimmer(Robot):
|
||||
position=(-0.5, 0, 0.1),
|
||||
orientation=(0, 0.707, 0, 0.707),
|
||||
fixed_base=False,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/mjcfs/swimmer.xml'):
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -39,7 +39,7 @@ class Swimmer(Robot):
|
||||
if fixed_base is None:
|
||||
fixed_base = False
|
||||
|
||||
super(Swimmer, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(Swimmer, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'swimmer'
|
||||
|
||||
|
||||
|
||||
@@ -20,8 +20,8 @@ class UAVRobot(Robot):
|
||||
Vehicles/Robots that operate in the air. These are also called drones.
|
||||
"""
|
||||
|
||||
def __init__(self, simulator, urdf, position=None, orientation=None, fixed_base=False, scaling=1.):
|
||||
super(UAVRobot, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
def __init__(self, simulator, urdf, position=None, orientation=None, fixed_base=False, scale=1.):
|
||||
super(UAVRobot, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
|
||||
self.propellers = [] # list of propellers id
|
||||
|
||||
@@ -36,8 +36,8 @@ class FixedWingUAV(UAVRobot):
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, simulator, urdf, position=None, orientation=None, fixed_base=False, scaling=1.):
|
||||
super(FixedWingUAV, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
def __init__(self, simulator, urdf, position=None, orientation=None, fixed_base=False, scale=1.):
|
||||
super(FixedWingUAV, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
|
||||
|
||||
class RotaryWingUAV(UAVRobot):
|
||||
@@ -45,5 +45,5 @@ class RotaryWingUAV(UAVRobot):
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, simulator, urdf, position=None, orientation=None, fixed_base=False, scaling=1.):
|
||||
super(RotaryWingUAV, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
def __init__(self, simulator, urdf, position=None, orientation=None, fixed_base=False, scale=1.):
|
||||
super(RotaryWingUAV, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
|
||||
@@ -20,5 +20,5 @@ class USVRobot(Robot):
|
||||
Vehicles/Robots that operate on the surface of water.
|
||||
"""
|
||||
|
||||
def __init__(self, simulator, urdf, position=None, orientation=None, fixed_base=False, scaling=1.):
|
||||
super(USVRobot, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
def __init__(self, simulator, urdf, position=None, orientation=None, fixed_base=False, scale=1.):
|
||||
super(USVRobot, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
|
||||
@@ -20,5 +20,5 @@ class UUVRobot(Robot):
|
||||
Vehicles/Robots that operate under water.
|
||||
"""
|
||||
|
||||
def __init__(self, simulator, urdf, position=None, orientation=None, fixed_base=False, scaling=1.):
|
||||
super(UUVRobot, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
def __init__(self, simulator, urdf, position=None, orientation=None, fixed_base=False, scale=1.):
|
||||
super(UUVRobot, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
|
||||
@@ -27,7 +27,7 @@ class Walker2D(Robot):
|
||||
position=(-0.5, 0, 0.1),
|
||||
orientation=(0, 0.707, 0, 0.707),
|
||||
fixed_base=False,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/mjcfs/walker2d.xml'):
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -39,7 +39,7 @@ class Walker2D(Robot):
|
||||
if fixed_base is None:
|
||||
fixed_base = False
|
||||
|
||||
super(Walker2D, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(Walker2D, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'walker2D'
|
||||
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ class Walkman(BipedRobot, BiManipulatorRobot):
|
||||
position=(0, 0, 1.14),
|
||||
orientation=(0, 0, 0, 1),
|
||||
fixed_base=False,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/walkman/walkman.urdf',
|
||||
lower_body=False): # 'walkman_lower_body.urdf'
|
||||
# check parameters
|
||||
@@ -49,7 +49,7 @@ class Walkman(BipedRobot, BiManipulatorRobot):
|
||||
if lower_body:
|
||||
urdf = os.path.dirname(__file__) + '/urdfs/walkman/walkman_lower_body.urdf'
|
||||
|
||||
super(Walkman, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(Walkman, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'walkman'
|
||||
|
||||
# Camera sensors: Two 2D Camera sensor (stereo-camera)
|
||||
@@ -57,16 +57,16 @@ class Walkman(BipedRobot, BiManipulatorRobot):
|
||||
# fovx = 1.3962634rad = 80 degrees, Gaussian noise = N(0, 0.007)
|
||||
# "left_camera_frame",
|
||||
self.left_camera = CameraSensor(self.sim, self.id, 11, width=800, height=800, fovy=80, near=0.02, far=300,
|
||||
refresh_rate=30) # 11
|
||||
rate=30) # 11
|
||||
self.right_camera = CameraSensor(self.sim, self.id, 13, width=800, height=800, fovy=80, near=0.02, far=300,
|
||||
refresh_rate=30) # 13
|
||||
rate=30) # 13
|
||||
|
||||
# Laser (depth) sensor: Hokuyo sensor
|
||||
# link: "head_hokuyo_frame"
|
||||
# freq=40, samples = 720, angle = [-1.570796, 1.570796] rad, range = [0.10, 30.0] m
|
||||
# Gaussian noise: N(0.0, 0.01)
|
||||
self.depth_camera = CameraSensor(self.sim, self.id, 10, width=200, height=200, fovy=80, near=0.1, far=30.0,
|
||||
refresh_rate=40)
|
||||
rate=40)
|
||||
|
||||
self.cameras = [self.left_camera, self.right_camera, self.depth_camera]
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ class WAM(ManipulatorRobot):
|
||||
position=(0, 0, 0),
|
||||
orientation=(0, 0, 0, 1),
|
||||
fixed_base=True,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/wam/wam.urdf'):
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -39,7 +39,7 @@ class WAM(ManipulatorRobot):
|
||||
if fixed_base is None:
|
||||
fixed_base = True
|
||||
|
||||
super(WAM, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(WAM, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'wam'
|
||||
|
||||
# self.disable_motor()
|
||||
|
||||
@@ -22,8 +22,8 @@ class WheeledRobot(Robot):
|
||||
This type of robots has wheels.
|
||||
"""
|
||||
|
||||
def __init__(self, simulator, urdf, position=None, orientation=None, fixed_base=False, scaling=1.):
|
||||
super(WheeledRobot, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
def __init__(self, simulator, urdf, position=None, orientation=None, fixed_base=False, scale=1.):
|
||||
super(WheeledRobot, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
|
||||
self.wheels = []
|
||||
self.wheel_directions = []
|
||||
@@ -108,9 +108,9 @@ class DifferentialWheeledRobot(WheeledRobot):
|
||||
http://www.robotplatform.com/knowledge/Classification_of_Robots/wheel_control_theory.html
|
||||
"""
|
||||
|
||||
def __init__(self, simulator, urdf, position=None, orientation=None, fixed_base=False, scaling=1.):
|
||||
def __init__(self, simulator, urdf, position=None, orientation=None, fixed_base=False, scale=1.):
|
||||
super(DifferentialWheeledRobot, self).__init__(simulator, urdf, position, orientation, fixed_base,
|
||||
scaling)
|
||||
scale)
|
||||
|
||||
|
||||
class AckermannWheeledRobot(WheeledRobot):
|
||||
@@ -130,9 +130,9 @@ class AckermannWheeledRobot(WheeledRobot):
|
||||
http://www.robotplatform.com/knowledge/Classification_of_Robots/wheel_control_theory.html
|
||||
"""
|
||||
|
||||
def __init__(self, simulator, urdf, position=None, orientation=None, fixed_base=False, scaling=1.):
|
||||
def __init__(self, simulator, urdf, position=None, orientation=None, fixed_base=False, scale=1.):
|
||||
super(AckermannWheeledRobot, self).__init__(simulator, urdf, position, orientation, fixed_base,
|
||||
scaling)
|
||||
scale)
|
||||
|
||||
self.steering = 0 # id of steering joint
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ class YoubotBase(DifferentialWheeledRobot):
|
||||
position=(0, 0, 0.085),
|
||||
orientation=(0, 0, 0, 1),
|
||||
fixed_base=False,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/youbot/youbot_base_only.urdf'):
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -43,7 +43,7 @@ class YoubotBase(DifferentialWheeledRobot):
|
||||
if fixed_base is None:
|
||||
fixed_base = False
|
||||
|
||||
super(YoubotBase, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(YoubotBase, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'youbot_base'
|
||||
|
||||
# self.wheels = [self.get_link_ids(link) for link in ['left_wheel', 'right_wheel']
|
||||
@@ -63,7 +63,7 @@ class KukaYoubotArm(ManipulatorRobot):
|
||||
position=(0, 0, 0.03),
|
||||
orientation=(0, 0, 0, 1),
|
||||
fixed_base=True,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/youbot/youbot_arm_only.urdf'):
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -75,7 +75,7 @@ class KukaYoubotArm(ManipulatorRobot):
|
||||
if fixed_base is None:
|
||||
fixed_base = True
|
||||
|
||||
super(KukaYoubotArm, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(KukaYoubotArm, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'kuka_youbot_arm'
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ class Youbot(ManipulatorRobot, DifferentialWheeledRobot):
|
||||
position=(0, 0, 0.085),
|
||||
orientation=(0, 0, 0, 1),
|
||||
fixed_base=False,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/youbot/youbot.urdf'):
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -103,7 +103,7 @@ class Youbot(ManipulatorRobot, DifferentialWheeledRobot):
|
||||
if fixed_base is None:
|
||||
fixed_base = False
|
||||
|
||||
super(Youbot, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(Youbot, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'youbot'
|
||||
|
||||
# self.wheels = [self.get_link_ids(link) for link in ['left_wheel', 'right_wheel']
|
||||
@@ -123,7 +123,7 @@ class YoubotDualArm(BiManipulatorRobot, DifferentialWheeledRobot):
|
||||
position=(0, 0, 0.085),
|
||||
orientation=(0, 0, 0, 1),
|
||||
fixed_base=False,
|
||||
scaling=1.,
|
||||
scale=1.,
|
||||
urdf=os.path.dirname(__file__) + '/urdfs/youbot/youbot_dual_arm.urdf'):
|
||||
# check parameters
|
||||
if position is None:
|
||||
@@ -135,7 +135,7 @@ class YoubotDualArm(BiManipulatorRobot, DifferentialWheeledRobot):
|
||||
if fixed_base is None:
|
||||
fixed_base = False
|
||||
|
||||
super(YoubotDualArm, self).__init__(simulator, urdf, position, orientation, fixed_base, scaling)
|
||||
super(YoubotDualArm, self).__init__(simulator, urdf, position, orientation, fixed_base, scale)
|
||||
self.name = 'youbot_dual_arm'
|
||||
|
||||
# self.wheels = [self.get_link_ids(link) for link in ['left_wheel', 'right_wheel']
|
||||
|
||||
@@ -5,10 +5,11 @@ This file defines the `State` class, which is returned by the environment, and g
|
||||
models such as policies/controllers, dynamic transition functions, value approximators, reward/cost function, and so on.
|
||||
"""
|
||||
|
||||
import numpy as np
|
||||
import torch
|
||||
import copy
|
||||
import collections
|
||||
# from abc import ABCMeta, abstractmethod
|
||||
import numpy as np
|
||||
import torch
|
||||
import gym
|
||||
|
||||
from pyrobolearn.utils.data_structures.orderedset import OrderedSet
|
||||
@@ -828,11 +829,12 @@ class State(object):
|
||||
# Operators #
|
||||
#############
|
||||
|
||||
def __repr__(self):
|
||||
def __str__(self):
|
||||
"""Return a representation string about the object."""
|
||||
if self._data is None:
|
||||
lst = [self.__class__.__name__ + '(']
|
||||
for state in self.states:
|
||||
lst.append('\t' + state.__repr__() + ',')
|
||||
lst.append('\t' + state.__str__() + ',')
|
||||
lst.append(')')
|
||||
return '\n'.join(lst)
|
||||
else:
|
||||
@@ -1012,8 +1014,9 @@ class State(object):
|
||||
def __sub__(self, other):
|
||||
"""
|
||||
Remove the other state(s) from the current state.
|
||||
:param other:
|
||||
:return:
|
||||
|
||||
Args:
|
||||
other (State): state to be removed.
|
||||
"""
|
||||
if not isinstance(other, State):
|
||||
raise TypeError("Expecting another state, instead got {}".format(type(other)))
|
||||
@@ -1029,7 +1032,7 @@ class State(object):
|
||||
Remove one or several states from the combined state.
|
||||
|
||||
Args:
|
||||
other:
|
||||
other (State): state to be removed.
|
||||
"""
|
||||
if not isinstance(other, State):
|
||||
raise TypeError("Expecting another state, instead got {}".format(type(other)))
|
||||
@@ -1062,6 +1065,29 @@ class State(object):
|
||||
"""
|
||||
return self.fuse(other, axis=0)
|
||||
|
||||
def __copy__(self):
|
||||
"""Return a shallow copy of the state. This can be overridden in the child class."""
|
||||
return self.__class__(states=self.states, data=self._data, space=self._space, name=self.name,
|
||||
window_size=self.window_size, axis=self.axis, ticks=self.ticks)
|
||||
|
||||
def __deepcopy__(self, memo={}):
|
||||
"""Return a deep copy of the state. This can be overridden in the child class.
|
||||
|
||||
Args:
|
||||
memo (dict): memo dictionary of objects already copied during the current copying pass
|
||||
"""
|
||||
states = [copy.deepcopy(state, memo) for state in self.states]
|
||||
data = copy.deepcopy(self.window[0]) if self.has_data() else None
|
||||
space = copy.deepcopy(self._space)
|
||||
state = self.__class__(states=states, data=data, space=space, name=self.name, window_size=self.window_size,
|
||||
axis=self.axis, ticks=self.ticks)
|
||||
|
||||
# update the memodict (note that `copy.deepcopy` will automatically check this dictionary and return the
|
||||
# reference if already present)
|
||||
memo[self] = state
|
||||
|
||||
return state
|
||||
|
||||
# def __invert__(self):
|
||||
# """
|
||||
# Return the
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
"""Define the reinforcement learning task.
|
||||
"""
|
||||
|
||||
import gym
|
||||
|
||||
from pyrobolearn.tasks.task import Task
|
||||
|
||||
__author__ = "Brian Delhaisse"
|
||||
@@ -26,5 +24,6 @@ class RLTask(Task):
|
||||
[1] "Reinforcement Learning: An Introduction", Sutton and Barto, 2018
|
||||
[2] "A Survey on Policy Search for Robotics", Deisenroth et al., 2013
|
||||
"""
|
||||
|
||||
def __init__(self, environment, policies):
|
||||
super(RLTask, self).__init__(environment, policies)
|
||||
|
||||
@@ -20,6 +20,7 @@ Dependencies:
|
||||
|
||||
import collections
|
||||
import copy
|
||||
import pickle
|
||||
import time
|
||||
from abc import ABCMeta
|
||||
from itertools import count
|
||||
@@ -231,6 +232,7 @@ class Task(object):
|
||||
"""
|
||||
Perform one step.
|
||||
"""
|
||||
# if we need to render the environment
|
||||
if render:
|
||||
self.env.render()
|
||||
else:
|
||||
@@ -261,8 +263,50 @@ class Task(object):
|
||||
return self.policies[idx].model
|
||||
|
||||
def save(self, filename):
|
||||
"""Save the storage on the disk."""
|
||||
pickle.dump(self, open(filename, 'wb'))
|
||||
|
||||
@staticmethod
|
||||
def load(filename):
|
||||
"""Load the storage from the disk."""
|
||||
return pickle.load(open(filename, 'r'))
|
||||
|
||||
def rollout(self): # TODO
|
||||
pass
|
||||
|
||||
#############
|
||||
# Operators #
|
||||
#############
|
||||
|
||||
def __repr__(self):
|
||||
"""Return a representation string about the reward function."""
|
||||
return self.__class__.__name__
|
||||
|
||||
def __str__(self):
|
||||
"""Return a string describing the reward function."""
|
||||
return self.__class__.__name__ + '(\n\tenvironment=' + str(self.environment) + ',\n\tpolicies=[' \
|
||||
+ ',\n\t\t'.join([str(policy) for policy in self.policies]) + ']\n)'
|
||||
|
||||
def __copy__(self):
|
||||
"""Return a shallow copy of the task. This can be overridden in the child class."""
|
||||
return self.__class__(environment=self.environment, policies=self.policies)
|
||||
|
||||
def __deepcopy__(self, memo={}):
|
||||
"""Return a deep copy of the task. This can be overridden in the child class.
|
||||
|
||||
Args:
|
||||
memo (dict): memo dictionary of objects already copied during the current copying pass
|
||||
"""
|
||||
environment = copy.deepcopy(self.environment, memo)
|
||||
policies = [copy.deepcopy(policy, memo) for policy in self.policies]
|
||||
task = self.__class__(environment=environment, policies=policies)
|
||||
|
||||
# update the memodict (note that `copy.deepcopy` will automatically check this dictionary and return the
|
||||
# reference if already present)
|
||||
memo[self] = task
|
||||
|
||||
return task
|
||||
|
||||
|
||||
# alias
|
||||
Scenario = Task
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user