update several classes: add copy/deepcopy methods (ongoing)

This commit is contained in:
Brian Delhaisse
2019-05-08 07:43:45 +02:00
parent 9e68606c9a
commit 749b98e800
102 changed files with 1431 additions and 445 deletions
+68 -38
View File
@@ -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
+31 -1
View File
@@ -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
+16
View File
@@ -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
+30
View File
@@ -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
+49 -6
View File
@@ -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__':
+13 -13
View File
@@ -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)
+97 -38
View File
@@ -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
+16 -16
View File
@@ -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)
+4 -4
View File
@@ -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
View File
@@ -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.
+22 -22
View File
@@ -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)
+11 -11
View File
@@ -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:
+102 -16
View File
@@ -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)
+10 -10
View File
@@ -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 #
+16 -16
View File
@@ -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)
+49 -22
View File
@@ -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
+2 -1
View File
@@ -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))
+28 -4
View File
@@ -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):
+42
View File
@@ -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
+61
View File
@@ -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)
+2 -2
View File
@@ -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]
+2 -2
View File
@@ -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'
+2 -2
View File
@@ -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]
+2 -2
View File
@@ -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]
+2 -2
View File
@@ -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
+2 -2
View File
@@ -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'
+37 -4
View File
@@ -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
+2 -2
View File
@@ -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
+2 -2
View File
@@ -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'
+2 -2
View File
@@ -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
+2 -2
View File
@@ -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
+2 -2
View File
@@ -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
+2 -2
View File
@@ -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)]]
+2 -2
View File
@@ -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
+2 -2
View File
@@ -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]
+2 -2
View File
@@ -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]
+3 -3
View File
@@ -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()
+2 -2
View File
@@ -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]
+2 -2
View File
@@ -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'
+2 -2
View File
@@ -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']
+2 -2
View File
@@ -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',
+2 -2
View File
@@ -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'
+2 -2
View File
@@ -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()
+2 -2
View File
@@ -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'
+4 -5
View File
@@ -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
+2 -2
View File
@@ -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'
+2 -2
View File
@@ -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']
+2 -2
View File
@@ -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
+2 -2
View File
@@ -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',
+2 -2
View File
@@ -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]
+2 -2
View File
@@ -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
+2 -2
View File
@@ -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
+2 -2
View File
@@ -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'
+2 -2
View File
@@ -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'
+2 -2
View File
@@ -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()
+2 -2
View File
@@ -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'
+2 -2
View File
@@ -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]
+8 -8
View File
@@ -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
+2 -2
View File
@@ -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]
+4 -4
View File
@@ -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
+2 -2
View File
@@ -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'
+2 -2
View File
@@ -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
+2 -2
View File
@@ -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']
+2 -2
View File
@@ -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'
+2 -2
View File
@@ -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
+2 -2
View File
@@ -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]
+5 -5
View File
@@ -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]
+2 -2
View File
@@ -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'
+2 -2
View File
@@ -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'
+2 -2
View File
@@ -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'
+2 -2
View File
@@ -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
+2 -2
View File
@@ -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
View File
@@ -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 #
+2 -2
View File
@@ -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
+2 -2
View File
@@ -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
+2 -2
View File
@@ -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'
+2 -2
View File
@@ -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'
+2 -2
View File
@@ -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
+2 -2
View File
@@ -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.
+2 -2
View File
@@ -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):
+26 -3
View File
@@ -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
+25 -3
View File
@@ -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
+48 -3
View File
@@ -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
+2 -2
View File
@@ -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'
+2 -2
View File
@@ -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'
+2 -2
View File
@@ -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'
+6 -6
View File
@@ -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)
+2 -2
View File
@@ -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)
+2 -2
View File
@@ -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)
+2 -2
View File
@@ -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'
+5 -5
View File
@@ -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]
+2 -2
View File
@@ -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()
+6 -6
View File
@@ -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
+8 -8
View File
@@ -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']
+33 -7
View File
@@ -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
+1 -2
View File
@@ -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)
+44
View File
@@ -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