Step 3: Actuating the robot with cable

You can download the file associated with this step at: 

http://sofamacbuilder.lille.inria.fr/defrost/scenes/Tutorial/step3-ActuatingTheRobotWithCable/Finger.py

In the previous step, we showed how to model and simulate a soft robot with a finger shape and made of a deformable material (silicone). In this step, we will explain how to actuate it using a cable attached to the fingertip. The cable can then be used to pull or release the fingertip.

 

 

In SOFA, actuation is represented through constraints. To model cables, the SoftRobot plugin provides a CableConstraint behavior component.

In the previously created scene, locate the end of the createScene() function then add a child node named "cable" to the finger node with the createChild function.

       

        cable = finger.createChild('cable')
 

It is now possible to add different behaviors to this node. In SOFA, behaviors are implemented as the composition of simple components that are added to the scene nodes. The first component to add is of type MechanicalObject. The MechanicalObject component is important in SOFA as it stores the state (position, velocity,..) of the points simulated models. In our case, these points are used to sample the geometrical curve of the cable inside the soft finger model.

These initial points are specified using the position argument passed to the createObject function.
 

 

       cable.createObject('MechanicalObject',   position=(

                               "-17.5 12.5 2.5 " +" -32.5 12.5 2.5 " + " -47.5 12.5 2.5 "  + " -62.5 12.5 2.5 " +

                               "-77.5 12.5 2.5" +  "-83.5 12.5 4.5" "-85.5 12.5 6.5" +"-85.5 12.5 8.5" +

                               "-83.5 12.5 10.5" + "-77.5 12.5 12.5" + "-62.5 12.5 12.5" + "-47.5 12.5 12.5" +

                               "-32.5 12.5 12.5" + "-17.5 12.5 12.5" ))
 

The second component to add to the cable node is of type CableConstraint. It is created in the following way:

     cable.createObject('CableConstraint',
                                              name="aCableActuator",

                                              indices='0 1 2 3 4 5 6 7 8 9 10 11 12 13',

                                              pullPoint="0 12.5 12.5")
 

where indices allows to select a subpart of the points defined in the mechanical object and the sequence of the crossing points of the cable. Here we use all of them and we start from point 0 to the point 13. The last point of the list is supposed to be anchored in the model while the others will be sliding points. The pullPoint parameter is the fixed point from which the cable is pulled.
 

If you try the SOFA scene now, you should see pink lines illustrating the cable location but the mechanical behavior of the cable is not connected to the finger's one. To create a bidirectional link between the behavior of the cable and the finger's one, we use a component called BarycentricMapping. This component will map the constraints between the cable’s mechanical DoFs and the one of the finger. One can do this by adding the following line:      

    
       cable.createObject('BarycentricMapping')     
 

It is now time to add some interactivity to your simulated cable. This is done by adding a Controller component to the cable node. With SOFA, it is possible to implement controllers in Python using a component called a PythonScriptController, resulting in the following line to your scene:
 

      cable.createObject('PythonScriptController',

filename="controller.py",

classname="controller")
 

The desired interaction is implemented in a separated file called controller.py which contains:
 

      #!/usr/bin/env python

      # -*- coding: utf-8 -*-

      import Sofa

 

      class controller(Sofa.PythonScriptController):

               def initGraph(self, node):

                        self.node = node

 

               def onKeyPressed(self,c):

                        inputvalue = self.node.getObject('aCable').findData('inputValue')

                        if (c == "+"):

                                displacement = inputvalue.value[0][0] + 1.

                                inputvalue.value = str(displacement)

                        elif (c == "-"):

                                displacement = inputvalue.value[0][0] - 1.

                                inputvalue.value = str(displacement)
 

At this step, pressing CTRL and +/-  changes the displacement of the CableConstraint and results in pulling/releasing the fingertip.