Adding a Coordinate Actuator to the muscles of the arm

Provide easy-to-use, extensible software for modeling, simulating, controlling, and analyzing the neuromusculoskeletal system.
User avatar
sariah Mghames
Posts: 23
Joined: Thu Jun 30, 2016 5:56 am

Adding a Coordinate Actuator to the muscles of the arm

Post by sariah Mghames » Sun Sep 11, 2016 9:13 pm

Dear all,

I am working on the arm26 model which has 6 muscles(actuators) that control the elbow movement.
My aim is to add an external actuator at the elbow. In this case, if i understand right i can use either a coordinate actuator( defining elbow as the coordinate) or a torque actuator( defining forearm and upper arm as bodies A and B)
I choosed to add a coordinate actuator. I am coding in cpp but the concept is still confusing to me.
I have already a ControlSet defined and control values of the 6 muscles (actuators) appended to it.

I should define a ForceSet for the coordinate actuator that i want to add and append the force to it. Is it possible to append the force of the new actuator to the existing controlSet instead of creating a ForceSet ? ( we know that the magnitude of the force/torque is different than the controls( excitations from 0 to 1) of the muscles.

And after creating a forceSet, i think I should update the actuators ( updActuators() ) . In this case i should expect to have 7 for model.getNumcontrols() ?
And also, for : model->getForceSet().get(a).getName().c-str() I can get the names of the muscles if a is from 0 to 5 and the name of the added coordinate actuator if a was 6 ( my question is getForceSet() will include also the muscles not only the added coordinate actuator ?)

Thanks in advance for any help,
Sariah

User avatar
Dimitar Stanev
Posts: 1096
Joined: Fri Jan 31, 2014 5:14 am

Re: Adding a Coordinate Actuator to the muscles of the arm

Post by Dimitar Stanev » Sun Sep 11, 2016 11:49 pm

Hi,
I should define a ForceSet for the coordinate actuator that i want to add and append the force to it. Is it possible to append the force of the new actuator to the existing controlSet instead of creating a ForceSet ? ( we know that the magnitude of the force/torque is different than the controls( excitations from 0 to 1) of the muscles.
You should create your CoordinateActuator on the heap (new) and then call model.addForce() which will take ownership of the new actuator. After you build your model (model.buildSystem()), at the end of the force set, there will be an extra generalized force, which is controlled by the control signal applied to this actuator and the value of the optimal force (torque = control * optimalForce with control >0 or control < 0). In generally you should always use the add method of model and make sure to check the inheritance diagram of your component from doxygen so you can know what is the abstract type of your component. In the feature there will be no distinction between individual components (e.g. addAnalysis, addForce, addController) but a unified addComponent.

https://simtk.org/api_docs/opensim/api_ ... ml#details

Best

User avatar
sariah Mghames
Posts: 23
Joined: Thu Jun 30, 2016 5:56 am

Re: Adding a Coordinate Actuator to the muscles of the arm

Post by sariah Mghames » Mon Sep 12, 2016 3:10 am

Thanks alot for your help,

So if I add the force to the model : model.addForce( Force *force);
and I defined a controller to be : controller = new ControlSetController();
then I set : controller->setActuators(model->updActuators());

and at the end of the ForceSet definition , I add the controller to the model: model->addController(controller) ;

The controller object will have the 6 muscles of the arm26 and the added coordinate actuator , does it make sense? dimension 7x1

Sorry if my question was answered in the previous reply and i didn't get it,
Thanks again, Sariah

User avatar
Dimitar Stanev
Posts: 1096
Joined: Fri Jan 31, 2014 5:14 am

Re: Adding a Coordinate Actuator to the muscles of the arm

Post by Dimitar Stanev » Mon Sep 12, 2016 4:56 am

Yes,

Your controller will have 7 actuators of which 6 are muscles and one is a coordinate actuator. So it will provide a control values for all seven actuators, where the bound of the muscles will be [0, 1] and for the coordinate actuator [-inf, +inf].

Best

User avatar
sariah Mghames
Posts: 23
Joined: Thu Jun 30, 2016 5:56 am

Re: Adding a Coordinate Actuator to the muscles of the arm

Post by sariah Mghames » Mon Sep 12, 2016 8:12 am

Thanks again,

When we realize the system to the position and velocity stages after adding the additional actuator, how does the forward dynamics knows that the first 6 controls should be used to evaluate f(a,l,ldot) of muscles torques without using the 7th ( which is already a torque/force). We have different orders of control inputs in 1 vector. Is it simply by defining the 1st 6inputs (excitations) to be of type controlLinear added to a controlSet and the 7th( force) to be of type force added to a forceSet ? only

Thanks for your help,

User avatar
Dimitar Stanev
Posts: 1096
Joined: Fri Jan 31, 2014 5:14 am

Re: Adding a Coordinate Actuator to the muscles of the arm

Post by Dimitar Stanev » Mon Sep 12, 2016 8:23 am

Everything is done automatically by calling the appropriate virtual methods in the hierarchy, so you don't have to worry. It gets the control vector and sets the control value of each actuator (base class both for muscle and for coordinate actuator). Then internally each actuator reads the control value and evaluates its force (because each actuator is a Force). In the case of the muscles torque_muscles = R(q) * f_muscle(control) and in case of the coordinate actuator troque_ca = optimalForce * control.

User avatar
sariah Mghames
Posts: 23
Joined: Thu Jun 30, 2016 5:56 am

Re: Adding a Coordinate Actuator to the muscles of the arm

Post by sariah Mghames » Thu Sep 15, 2016 6:29 am

Thank you Dimitar,

Before I add the coordinate actuator to the vector of exciations(controls, 6x1 for arm26), I tried to input the controls values(excitations only) from simulink input signal and not from controls.xml file that was provided previously for an S function in simulink. However, setting all the controls Values input(excitations, vector 6x1) to 0 should keep the model 's state to its initial conditions provided ( the 0/initial angle for the arm is the vertical downward position). The problem I am facing is that the elbow angle and shoulder elevation are not kept to their initial 0 positions( I am getting motion).

The steps followed are: 1) update controls values of the model ( from pointer to simulink input port signal)
2) update the model's state
3) realize the state to velocity stage
4) computeActuation(state)
5) realize the state to velocity stage
6) realize state to acceleration stage

Although my question is very general, it can be related to a misunderstanding of 1 procedure that i should update when reading excitations from input port of simulink.

Thanks in advance for any help,
Sariah

User avatar
sariah Mghames
Posts: 23
Joined: Thu Jun 30, 2016 5:56 am

Re: Adding a Coordinate Actuator to the muscles of the arm

Post by sariah Mghames » Fri Sep 16, 2016 3:27 am

In fact, now I found that even if I don't set the excitations signals from simulink input port, and instead I keep using the excitations defined in the controls.xml file , I got the same results ( motion output even when i set all the excitations to 0 in the xml file)

I suspected then that the PD values defined in the controls xml file are controlling the excitations when the excitations are not 0, but trying to setting the PD to 0 or even changing the values does not affect the position output when the excitations are different than 0 ( exciatations corresponding to elbow angle of 90 degree, 0 being the vertical downward).

Are the excitations in the controls.xml file usually controlled by a PD ? I found from my investigations that they aren't

Thanks,

User avatar
sariah Mghames
Posts: 23
Joined: Thu Jun 30, 2016 5:56 am

Re: Adding a Coordinate Actuator to the muscles of the arm

Post by sariah Mghames » Sun Sep 18, 2016 10:45 pm

Hi again,

I was able somehow to deal with the previous problem listed, however now that i am adding a coordinate actuator to the 6 muscles of the arm26 ( at elbow level), the forceset size is not updated to 7 , always im getting the size of 6, here below what i am doing briefly(in cpp and the control values should be provided from real time input signal, no xml file):

ControlSetController *controller;
controller = new ControlSetController();

std::string r_elbow_flex_actuator ; //coordinateActuator name
CoordinateActuator actuatorPlus(r_elbow_flex_actuator) ;
Coordinate* r_elbow_flex ;
actuatorPlus.setCoordinate(r_elbow_flex) ;
double optimalforce = 1 ;
actuatorPlus.setOptimalForce(optimalforce);
ForceSet actuatorForces(model) ; //create a forceset for the coordinateActuator actuatorPlus

Force *Torque = 0;
model->addForce(Torque);
actuatorForces.append(Torque);
controller->setActuators(model->updActuators())
model->updForceSet() ;

// Create a control set and add the controls to the set
ControlSet actuatorControls;
actuatorControls.setSize(6);
Array<ControlLinear> control;
control.ensureCapacity(6);
Array<double> controlValues(0.0, 6);


/* loop through actuators and setting the actuators name and appending to the actuators set*/
for(int_T a=0 ; a<6 ; a++){
control[a].setName(model->getForceSet().get(a).getName().c_str());
ssPrintf("input controls [%d] = %s\n",a, model->getForceSet().get(a).getName().c_str());
actuatorControls.append(&control[a]);
}

ssPrintf("forceset size = %d\n", model->getForceSet().getSize() ); // here i am getting always 6
Torque->setName(model->getActuators().get(6).getName().c_str()); // the bug i am getting because of this line, since there is no get(6), max it recognizes get(5)


// Make a copy and set it on the ControlSetController as it takes ownership of the ControlSet passed in
actuatorControls.setMemoryOwner(false);
actuatorForces.setMemoryOwner(false);
actuatorControls.setControlValues(0.0, controlValues);
actuatorControls.setControlValues(1.0, controlValues);

controller->setControlSet((ControlSet*)Object::SafeCopy(&actuatorControls));

model->addController(controller);

state = model->initSystem(); // even if initsystem is written up after creating the forceset, the same bug obtained
model->getMultibodySystem().realize(state, SimTK::Stage::Position ); .....................................


If anyone could point me out what is missing to let the model recognize the additional coordinateActuator, it will be of major help.
Thank you.

User avatar
Dimitar Stanev
Posts: 1096
Joined: Fri Jan 31, 2014 5:14 am

Re: Adding a Coordinate Actuator to the muscles of the arm

Post by Dimitar Stanev » Mon Sep 19, 2016 11:53 pm

Code: Select all

CoordinateActuator* elbow = new CoordinateActuator();
elbow->setCoordinate("elbow_joint_name");
elbow->setName('coordAct');            // Name
elbow->setOptimalForce(10.0);         // Maximum generalized force
elbow->setMinControl(-inf);              // Minimum control signal allowed
elbow->setMaxControl(inf);               // Maximum control signal allowed

model.addForce(elbow);                    //you don't need to create a force set you just add the object
//make sure to create the object in the heap (new) so that the model will take ownership and free it later (otherwise your program will crash)

FeedforwardController* controller = new FeedforwardController (); // see below
model.addController(controller); 

// build model
model.buildSystem();
State s = model.initializeState();

// integrate

RungeKuttaMersonIntegrator integrator(model.getMultibodySystem());
Manager manager(model, integrator);

manager.setInitialTime(t0);
manager.setFinalTime(tf);
manager.integrate(s);

// store your simulation results

Storage stateStorage(manager.getStateStorage());
model.updSimbodyEngine().convertRadiansToDegrees(stateStorage);
stateStorage.print(dir + "/" + m_model->getName() + "_state.sto");
        

Code: Select all

class FeedforwardController : public OpenSim::Controller
{
    OpenSim_DECLARE_CONCRETE_OBJECT(FeedforwardController, Controller);

public:

    FeedforwardController();

    ~FeedforwardController();

protected:

    /**
    * This function is called at every time step for every actuator.
    *
    * @param s Current state of the system
    * @param controls Controls being calculated
    */
    void computeControls(const SimTK::State& s, SimTK::Vector &controls)
        const override
        {
        \\here set the controls of the actuators as you like.
        }
        
}; // end of class 
} 

POST REPLY