Tutorial Description -------------------- .. todo:: Add author/responsible The goal of the experiment is to build a model to simulate a simple knee reflex. A knee reflex tries to compensate for a sudden muscle stretch by activating the muscle under stretch appropriately based on its' muscle stretching speed to compensate the stretch. To achieve this we will be using the NRP-OpenSim interface. The first step would be to clone the experiment "Opensim Muscle Tutorial - Knee Jerk Experiment". After cloning click on the experiment and click files to view all the simulation files that we are going to be editing. The file explorer can be used to download and upload all the files. .. image:: ./image.png Model Creation -------------- In order to create a musculoskeletal model in NRP, it involves two stages: 1. Gazebo Modeling : Physical Model 2. Opensim Modeling : Muscle Model Gazebo Modeling ^^^^^^^^^^^^^^^ The model used in this experiment is a simple two link thigh and shank bodies with one rotational degree of freedom to represent the knee joint. The properties of the model are as described below, +----------+-----------+----------+----------------+ | *Body* |*Length(m)*|*Mass(kg)*|*Inertia(kg-m2)*| +----------+-----------+----------+----------------+ | thigh | 0.5 | 5 | 1 | +----------+-----------+----------+----------------+ | shank | 0.5 | 5 | 1 | +----------+-----------+----------+----------------+ With the properties described in the above table, one can setup up the basic sdf model. In order to attach and make the opensim plugin to work in NRP, the following tag needs to be added in the sdf file. You can download and edit the model.sdf file from the robot folder through the file explorer. ``model://opensim_knee_jerk_tut/muscles.osim`` ```` The muscles tag points to the location where the description of muscles is setup. More details on writing this file can be found in the following section. The plugin is needed to link the necessary libraries that interface :abbr:`NRP (Neurorobotics Platform)` with Opensim functionality. Opensim Modeling ^^^^^^^^^^^^^^^^ The next step is to describe the muscles in the model. This is achieved by writing a ``*.osim`` file. This file follows the same syntax as described by the standard opensim osim file description format. For more details checkout the `link ` __ under ``The Muscle Actuator`` subheading. The osim file should contain only the muscles description and the wrapping objects. The bodies/links will be used from the model description defined in sdf file earlier. *Hence make sure to use the same names for the bodies in both files* In the current tutorial, a single muscle named *vastus* is used with the following properties, +-------------------------+-------------------------+-------------------------+ | *Property* | *Value* | *Units* | +-------------------------+-------------------------+-------------------------+ | Isometric Force | 500 | N | +-------------------------+-------------------------+-------------------------+ | Optimal Fiber Length | 0.19 | m | +-------------------------+-------------------------+-------------------------+ | Tendon Slack Length | 0.19 | m | +-------------------------+-------------------------+-------------------------+ | Origin | [0. 0.25 0.05] | m | +-------------------------+-------------------------+-------------------------+ | Insertion | [0. 0.08 -0.15] | m | +-------------------------+-------------------------+-------------------------+ The above table translated to the osim file looks like, .. code-block:: XML thigh 0.050000000000000003 0 0 shank 0.037499999999999999 0.17499999999999999 0 500 0.19 0.19 **Note: The above snippet is only an example. Do not copy and paste** The muscles.osim file used for this tutorial also describes a muscle wrapping object. This constraint makes sure that the muscle does not penetrate the bones during the motion of the joint. Gazebo-ROS-OpenSim Inerface --------------------------- Once you have setup the models using the above described steps, you should be able to create new experiments with the usual :abbr:`NRP (Neurorobotics Platform)` procedure to create a model. Assuming you are familiar with the process, we continue the tutorial. If you are in doubt please refer to the following `link `_. In order to be able to write controllers and access the muscles in the simulation, there exists a set of muscle topics and messages that can be used. Subscribers ^^^^^^^^^^^ The states of the muscles initialized and described in the ``*.osim(muscles.osim)`` is automatically published on a ros topic with the name `` /gazebo_muscle_interface/robot/muscle_states `` The above topic uses the ros-msg type ``MuscleStates`` which is an array containing ``MuscleState`` whose format which looks like, +-------------------------+-------------------------+ | *Type* | *Name* | +-------------------------+-------------------------+ | string | name | +-------------------------+-------------------------+ | float32 | force | +-------------------------+-------------------------+ | float32 | length | +-------------------------+-------------------------+ | float32 | lengthening_speed | +-------------------------+-------------------------+ | geometry_msgs/Vector3[] | path_points | +-------------------------+-------------------------+ Publishers ^^^^^^^^^^ To control the muscle state, the muscle activation needs to be set by the controller. During initialization every muscle described in the ``*.osim(muscles.osim)`` is generated with a individual ros-publisher of the topic, `` /gazebo_muscle_interface/robot/**MUSCLE_NAME**/cmd_activation `` The above topic accepts messages of type Float64. Reflex-Control -------------- Now that the full experimental model is setup, we can develop the controller to simulate the knee reflex. .. code-block:: python # Muscle Properties m_optimal_fiber_length = 0.19 m_max_contraction_velocity = 10.0 # Get muscle state muscle_states =dict((m.name, m) for m in muscle_states_msg.value.muscles) # Muscle Lengthening speed m_speed = muscle_states['vastus'].lengthening_speed # Maximum muscle speed m_max_speed = m_optimal_fiber_length*m_max_contraction_velocity #: Knee jerk reflex control # Reflex gain reflex_gain = 2. m_reflex_activation = min(1., 0.2*reflex_gain*(abs(m_speed) + m_speed)/m_max_speed) # Send muscle activation knee_jerk.send_message(m_reflex_activation)