Adding a Coordinate Actuator to the muscles of the arm
- sariah Mghames
- Posts: 23
- Joined: Thu Jun 30, 2016 5:56 am
Adding a Coordinate Actuator to the muscles of the arm
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
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
- Dimitar Stanev
- Posts: 1096
- Joined: Fri Jan 31, 2014 5:14 am
Re: Adding a Coordinate Actuator to the muscles of the arm
Hi,
https://simtk.org/api_docs/opensim/api_ ... ml#details
Best
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.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.
https://simtk.org/api_docs/opensim/api_ ... ml#details
Best
- sariah Mghames
- Posts: 23
- Joined: Thu Jun 30, 2016 5:56 am
Re: Adding a Coordinate Actuator to the muscles of the arm
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
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
- Dimitar Stanev
- Posts: 1096
- Joined: Fri Jan 31, 2014 5:14 am
Re: Adding a Coordinate Actuator to the muscles of the arm
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
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
- sariah Mghames
- Posts: 23
- Joined: Thu Jun 30, 2016 5:56 am
Re: Adding a Coordinate Actuator to the muscles of the arm
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,
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,
- Dimitar Stanev
- Posts: 1096
- Joined: Fri Jan 31, 2014 5:14 am
Re: Adding a Coordinate Actuator to the muscles of the arm
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.
- sariah Mghames
- Posts: 23
- Joined: Thu Jun 30, 2016 5:56 am
Re: Adding a Coordinate Actuator to the muscles of the arm
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
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
- sariah Mghames
- Posts: 23
- Joined: Thu Jun 30, 2016 5:56 am
Re: Adding a Coordinate Actuator to the muscles of the arm
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,
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,
- sariah Mghames
- Posts: 23
- Joined: Thu Jun 30, 2016 5:56 am
Re: Adding a Coordinate Actuator to the muscles of the arm
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.
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.
- Dimitar Stanev
- Posts: 1096
- Joined: Fri Jan 31, 2014 5:14 am
Re: Adding a Coordinate Actuator to the muscles of the arm
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
}