motornet.plants#
Module contents#
This module contains the classes and subclasses used to create the plants that a model will be trained to control.
Plants are implemented as subclasses of the motornet.plants.plants.Plant
object. They all contain a single
motornet.plants.skeletons.Skeleton
and motornet.plants.muscles.Muscle
subclass defining the
biomechanical properties of that Plant object. The Plant object itself implements the numerical integration
routines, some of the geometry state calculation routines (in conjunction with the Skeleton object), applies moment
arms to produce generalized forces, and generally handles communication between the Skeleton and Muscle objects.
Note
While Plant objects are technically implemented in the motornet.plants.plants
module, it is possible
(and recommended) to call them using the motornet.plants.Plant
path, which is more concise and strictly
equivalent.
motornet.plants.muscles#
motornet.plants.skeletons#
motornet.plants#
- class motornet.plants.plants.CompliantTendonArm26(timestep=0.0002, skeleton=None, **kwargs)#
Bases:
motornet.plants.plants.RigidTendonArm26
This is the compliant-tendon version of the
RigidTendonArm26
class. Note that the default integration method is Runge-Kutta 4, instead of Euler.- Parameters
timestep – Float, size of a single timestep (in sec).
skeleton – A
motornet.plants.skeletons.Skeleton
object class or subclass. This defines the type of skeleton that the muscles will wrap around. If no skeleton is passed, this will default to the skeleton used in the parentRigidTendonArm26
class.**kwargs – All contents are passed to the parent
RigidTendonArm26
class. This also allows for some backward compatibility.
- class motornet.plants.plants.Plant(skeleton, muscle_type, timestep: float = 0.01, integration_method: str = 'euler', excitation_noise_sd: float = 0.0, proprioceptive_delay: Optional[float] = None, visual_delay: Optional[float] = None, pos_lower_bound: Optional[Union[float, list, tuple]] = None, pos_upper_bound: Optional[Union[float, list, tuple]] = None, vel_lower_bound: Optional[Union[float, list, tuple]] = None, vel_upper_bound: Optional[Union[float, list, tuple]] = None, name: str = 'Plant')#
Bases:
object
Base class for Plant objects.
- Parameters
skeleton – A
motornet.plants.skeletons.Skeleton
object class or subclass. This defines the type of skeleton that the muscles will wrap around.muscle_type – A
motornet.plants.muscles.Muscle
object class or subclass. This defines the type of muscle that will be added each time theadd_muscle()
method is called.name – String, the name of the object instance.
timestep – Float, size of a single timestep (in sec).
integration_method – String, “euler” to specify that numerical integration should be done using the Euler method, or “rk4”, “rungekutta4”, “runge-kutta4”, or “runge-kutta-4” to specify the Runge-Kutta 4 method instead. This argument is case-insensitive.
excitation_noise_sd – Float, defines the amount of stochastic noise that will be added to the excitation input during the
call()
. Specifically, this value represents the standard deviation of a gaussian distribution centred around zero, from which a noise term is drawn randomly at every timestep.proprioceptive_delay – Float, the delay between a proprioceptive signal being produced by the plant and the network receiving it as input. If this is not a multiple of the timestep size, this will be rounded up to match the closest multiple value. What qualifies as “proprioceptive feedback” is defined at the network level.
visual_delay – Float, the delay between a visual signal being produced by the plant and the network receiving it as input. If this is not a multiple of the timestep size, this will be rounded up to match the closest multiple value. What qualifies as “visual feedback” is defined at the network level.
pos_upper_bound – Float, list or tuple, indicating the upper boundary of the skeleton’s joint position. This should be a n-elements vector or list, with n the number of joints of the skeleton. For instance, for a two degrees-of-freedom arm, we would have n=2.
pos_lower_bound – Float, list or tuple, indicating the lower boundary of the skeleton’s joint position. This should be a n-elements vector or list, with n the number of joints of the skeleton. For instance, for a two degrees-of-freedom arm, we would have n=2.
vel_upper_bound – Float, list or tuple, indicating the upper boundary of the skeleton’s joint velocity. This should be a n-elements vector or list, with n the number of joints of the skeleton. For instance, for a two degrees-of-freedom arm, we would have n=2.
vel_lower_bound – Float, list or tuple, indicating the lower boundary of the skeleton’s joint velocity. This should be a n-elements vector or list, with n the number of joints of the skeleton. For instance, for a two degrees-of-freedom arm, we would have n=2.
- add_muscle(path_fixation_body: list, path_coordinates: list, name: Optional[str] = None, **kwargs)#
Adds a muscle to the plant.
- Parameters
path_fixation_body – List, containing the index of the fixation body (or fixation bone) for each fixation point in the muscle. The index 0 always stands for the worldspace, i.e. a fixation point outside of the skeleton.
path_coordinates – A List of lists. There should be as many lists in the main list as there are fixation points for that muscle. Each nested list within the main list should contain a series of n coordinate float values, with n being the dimensionality of the worldspace. For instance, in a 2D environment, we would need two coordinate values. The coordinate system of each bone is centered on that bone’s origin point. Its first dimension is always alongside the length of the bone, and the next dimension(s) proceed(s) from there on orthogonally to that first dimension.
name – String, the name to give to the muscle being added. If
None
is given, the name defaults to “muscle_m”, with m being a counter for the number of muscles.**kwargs – This is used to pass the set of properties required to build the type of muscle specified at initialization. What it should contain varies depending on the muscle type being used. A TypeError will be raised by this method if a muscle property pertaining to the muscle type specified is missing.
- Raises
TypeError – If an argument is missing to build the type of muscle specified at initialization.
- draw_fixed_states(position, velocity=None, batch_size=1)#
Creates a joint state tensor corresponding to the specified position, tiled batch_size times.
- Parameters
position – The position to tile in the state tensor.
velocity – The velocity to tile in the state tensor. If None, this will default to 0 (null velocity).
batch_size – Integer, the desired batch size.
- Returns
A tensor containing batch_size joint states.
- draw_random_uniform_states(batch_size: int = 1)#
Draws joint states according to a random uniform distribution, bounded by the position and velocity boundary attributes defined at initialization.
- Parameters
batch_size – Integer, the desired batch size.
- Returns
A tensor containing batch_size joint states.
- get_geometry(joint_state)#
Computes the geometry state from the joint state.
- Parameters
joint_state – Tensor, the joint state from which the geometry state is computed.
- Returns
The geometry state corresponding to the joint state provided.
- get_initial_state(batch_size=1, joint_state=None)#
Gets initial states (joint, cartesian, muscle, geometry) that are biomechanically compatible with each other.
- Parameters
batch_size – Integer, the desired batch size.
joint_state – The joint state from which the other state values are inferred. If None, random initial joint states are drawn, from which the other state values are inferred.
- Returns
A list containing the joint state, and cartesian, muscle, and geometry states, in that order. If a joint_state input was provided, the joint state in the returned list will be the same as the input.
- Raises
ValueError – If the batch_size value is not specified and either the joint_state input is None or the size of joint_state input’s first dimension is equal to 1.
- get_muscle_cfg()#
Gets the wrapping configuration of muscles added through the
add_muscle()
method.- Returns
A dictionary containing a key for each muscle name, associated to a nested dictionary containing information fo that muscle.
- get_save_config()#
Gets the plant object’s configuration as a dictionary.
- Returns
A dictionary containing the skeleton and muscle configurations as nested dictionary objects, and parameters of the plant’s configuration. Specifically, the size of the timestep (sec), the name of each muscle added via the
add_muscle()
method, the number of muscles, the visual and proprioceptive delay, the standard deviation of the excitation noise, and the muscle wrapping configuration as returned byget_muscle_cfg()
.
- integrate(muscle_input, joint_state, muscle_state, geometry_state, endpoint_load, joint_load)#
Integrates the plant over one timestep. To do so, it first calls the
update_ode()
method to obtain state derivatives from evaluation of the Ordinary Differential Equations. Then it performs the numerical integration over one timestep using theintegration_step()
method.- Parameters
muscle_input – Tensor, the input to the muscles (motor command). Typically, this should be the output of the controller network’s forward pass.
joint_state – Tensor, the initial state for joint configuration.
muscle_state – Tensor, the initial state for muscle configuration.
geometry_state – Tensor, the initial state for geometry configuration.
endpoint_load – Tensor, the load(s) to apply at the skeleton’s endpoint.
joint_load – Tensor, the load(s) to apply at the joints.
- Returns
A list containing the new joint, muscle, and geometry states following integration, in that order.
- integration_step(dt, state_derivative, states)#
Performs one numerical integration step for the
motornet.plants.muscles.Muscle
object class or subclass, and then for themotornet.plants.skeletons.Skeleton
object class or subclass.- Parameters
dt – Float, size of a single timestep (in sec).
state_derivative – Dictionary, contains the derivatives of the joint, muscle, and geometry states as tensor arrays, mapped to a “joint”, “muscle”, and “geometry” key, respectively. This is usually obtained using the
update_ode()
method.states – A Dictionary containing the joint, muscle, and geometry states as Tensor, mapped to a “joint”, “muscle”, and “geometry” key, respectively.
- Returns
A dictionary containing the updated joint, muscle, and geometry states following integration.
- joint2cartesian(joint_state)#
Computes the cartesian state given the joint state.
- Parameters
joint_state – Tensor, the current joint configuration.
- Returns
The current cartesian configuration (position, velocity) as a tensor.
- print_muscle_wrappings()#
Prints the wrapping configuration of the muscles added using the
add_muscle()
method in a readable format.
- setattr(name: str, value)#
Changes the value of an attribute held by this object.
- Parameters
name – String, attribute to set to a new value.
value – Value that the attribute should take.
- state2target(state, n_timesteps: int = 1)#
Converts a tensor formatted as a state to a tensor formatted as a target that can be passed to a
tensorflow.keras.Model.fit()
call.- Parameters
state – Tensor, the state to be converted to a target.
n_timesteps – Integer, the number of timesteps desired for creating the target tensor.
- Returns
A tensor that can be used as a target input to the
tensorflow.keras.Model.fit()
method.
- update_ode(excitation, states, endpoint_load, joint_load)#
Computes state derivatives by evaluating the Ordinary Differential Equations of the
motornet.plants.muscles.Muscle
object class or subclass, and then of themotornet.plants.skeletons.Skeleton
object class or subclass.- Parameters
excitation – Tensor, the input to the muscles (motor command). Typically, this should be the output of the controller network’s forward pass.
states – Dictionary, contains the joint, muscle, and geometry states as tensor arrays, mapped to a “joint”, “muscle”, and “geometry” key, respectively.
endpoint_load – Tensor, the load(s) to apply at the skeleton’s endpoint.
joint_load – Tensor, the load(s) to apply at the joints.
- Returns
A list containing the new joint, muscle, and geometry states following integration, in that order.
- class motornet.plants.plants.ReluPointMass24(timestep: float = 0.01, max_isometric_force: float = 500, mass: float = 1, **kwargs)#
Bases:
motornet.plants.plants.Plant
This object implements a 2D point-mass skeleton attached to 4
motornet.plants.muscles.ReluMuscle
muscles in a “X” configuration. The outside attachement points are the corners of a (2, 2) -> (2, -2) -> (-2, -2) -> (-2, 2) frame, and the point-mass is constrained to a (1, 1) -> (1, -1) -> (-1, -1) -> (-1, 1) space.- Parameters
timestep – Float, size of a single timestep (in sec).
max_isometic_force – Float, the maximum force (N) that each muscle can produce.
mass – Float, the mass (kg) of the point-mass.
**kwargs – The kwargs inputs are passed as-is to the parent
motornet.plants.Plant
class.
- class motornet.plants.plants.RigidTendonArm26(muscle_type, skeleton=None, timestep=0.01, **kwargs)#
Bases:
motornet.plants.plants.Plant
This pre-built plant class is an implementation of a 6-muscles, “lumped-muscle” model from [1]. Because lumped-muscle models are functional approximations of biological reality, this class’ geometry does not rely on the default geometry methods, but on its own, custom-made geometry. The moment arm approximation is based on a set of polynomial functions. The default integration method is Euler.
If no skeleton input is provided, this object will use a
motornet.plants.skeletons.TwoDofArm
skeleton, with the following parameters:m1 = 1.82
m2 = 1.43
l1g = 0.135
l2g = 0.165
i1 = 0.051
i2 = 0.057
l1 = 0.309
l2 = 0.333
The default shoulder and elbow lower limits are defined as 0, and their default upper limits as 135 and 155 degrees, respectively. These parameters come from [1].
The kwargs inputs are passed as-is to the parent
Plant
class.References
[1] Kistemaker DA, Wong JD, Gribble PL. The central nervous system does not minimize energy cost in arm movements. J Neurophysiol. 2010 Dec;104(6):2985-94. doi: 10.1152/jn.00483.2010. Epub 2010 Sep 8. PMID: 20884757.
- Parameters
muscle_type – A
motornet.plants.muscles.Muscle
object class or subclass. This defines the type of muscle that will be added each time theadd_muscle()
method is called.skeleton – A
motornet.plants.skeletons.Skeleton
object class or subclass. This defines the type of skeleton that the muscles will wrap around. See above for details on what this argument defaults to if no argument is passed.timestep – Float, size of a single timestep (in sec).
**kwargs – All contents are passed to the parent
Plant
class. Also allows for some backward compatibility.