python custom controller

Provide easy-to-use, extensible software for modeling, simulating, controlling, and analyzing the neuromusculoskeletal system.
POST REPLY
User avatar
Andrew Stolin
Posts: 12
Joined: Thu Mar 05, 2015 9:41 am

python custom controller

Post by Andrew Stolin » Tue May 29, 2018 9:26 am

Hello,

I am trying to create a custom controller in python, and I had no luck going through the forum so far.

I have compiled opensim 4 with the python wrapper and the example file "build_simple_arm_model.py" runs fine, it uses a prescribed controller with a stepfunction on over 2 seconds that gadually increases the excitation to its maximum.

I would like to use a probe or reporter to get the information on a specific muscle at each step, and then calculate an excitation to send back to the muscle.

I have seen the tutorial "creating a controller" in the documentation but am unable to do this in python:
do you know any example creating a custom controller?

Thank you

Tags:

User avatar
Christopher Dembia
Posts: 506
Joined: Fri Oct 12, 2012 4:09 pm

Re: python custom controller

Post by Christopher Dembia » Wed May 30, 2018 4:08 pm

Our existing examples for creating controllers are for C++. Typically, defining a custom controller means creating a C++ class that derives from OpenSim's Controller class. You cannot currently create new OpenSim components in Python.

As a workaround, you could integrate forward a small amount of time (e.g., 1ms), compute controls, set them with, `model.setDefaultControls()`, and start integrating again.

User avatar
Christopher Dembia
Posts: 506
Joined: Fri Oct 12, 2012 4:09 pm

Re: python custom controller

Post by Christopher Dembia » Wed May 30, 2018 5:11 pm

Ayman mentioned to me that you may be able to create a Controller subclass in Python if you add the following line in the appropriate place in the SWIG interface files (and rebuild the bindings):

Code: Select all

%feature("director") OpenSim::Controller;
Here's an example of where we've used the SWIG director feature: https://github.com/opensim-org/opensim- ... tors.i#L21

You may want to read the SWIG documentation about the director feature.

User avatar
Andrew Stolin
Posts: 12
Joined: Thu Mar 05, 2015 9:41 am

Re: python custom controller

Post by Andrew Stolin » Thu May 31, 2018 1:16 am

Christopher, thank you very much for your answer. I will update this post as soon as possible

User avatar
Andrew Stolin
Posts: 12
Joined: Thu Mar 05, 2015 9:41 am

Re: python custom controller

Post by Andrew Stolin » Thu May 31, 2018 11:08 am

I am struggling here as I am missing a few key pieces to make sense of all this. So the small forward integration goes like this :

Code: Select all

manager = osim.Manager(arm)
state.setTime(0)
manager.initialize(state)
state = manager.integrate(0.1)
And we can get the state of activation and excitation of the muscle after the integration

Code: Select all

print(biceps.getActivation(state))
print(biceps.getExcitation(state))
As you suggested, setting the controls with arm.setDefaultControls :

1st option:
setActivation works

Code: Select all

biceps.setActivation(state, 0.1111111111111111))
setExcitation (which is what I am interested about) does not have any effect:

Code: Select all

biceps.setExcitation(state, 0.1111111111111111)
2nd option:
Or, in order to have all the controls, I see in the API (html_developer/classOpenSim_1_1ControlSet.html#details) that in python we have to use the cObj = ControlSet.safeDownCast(obj).

Code: Select all

cObj = osim.ControlSet.safeDownCast(biceps)
arm.setDefaultControls(cObj)
which does not work either.

I have seen in opensim-rl (https://github.com/stanfordnmbl/osim-rl ... nv/osim.py) that they use a prescribeControlForActuator with a Constant instead of a stepfunction :

Code: Select all

func = osim.Constant(1.0)
brain.prescribeControlForActuator("biceps", func)
Then actualise the controller with the content of getControllerSet, and change the value of the prescribedcontroller, before re-integrating. I tried:

Code: Select all

brain = osim.PrescribedController.safeDownCast(arm.getControllerSet().get(0))
func.setValue( float(1) ) # arbitrary value
arm.initializeState()
state.setTime(0)
state = manager.integrate(1.0)
It runs however I am not confident that the second integration is in continuity with the first one (that the controls do not reset), and that they are all based on arbitrary excitations (0.5 then 1).

Would you be able to confirm this?
I will try later on to spend some time learning how to create a custom controller by rebuilding the bindings as you suggested

Many thanks in advance
Attachments
test_controller.py.txt
(6.71 KiB) Downloaded 37 times

POST REPLY