Skip to content

Commit 672356f

Browse files
authored
Merge pull request #2166 from opensim-org/fix_correction_controller_with_GUI_use_case
Fix correction controller with GUI use case
2 parents 3a0505e + 4b23484 commit 672356f

File tree

3 files changed

+103
-82
lines changed

3 files changed

+103
-82
lines changed

Applications/Forward/test/subject01_Setup_Forward_Controller.xml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,8 @@
6060
indicates the controller will controll all the acuators in the model-->
6161
<actuator_list> </actuator_list>
6262
<!--Flag (true or false) indicating whether or not the controller is
63-
enabled (ON) should-->
64-
<enable_controller> true </enable_controller>
63+
disabled.-->
64+
<isDisabled> false </isDisabled>
6565
<!--XML file containing the controls for the controlSet.-->
6666
<controls_file> subject01_walk1_controls.xml </controls_file>
6767
</ControlSetController>
@@ -70,12 +70,12 @@
7070
indicates the controller will controll all the acuators in the model-->
7171
<actuator_list> </actuator_list>
7272
<!--Flag (true or false) indicating whether or not the controller is
73-
enabled (ON) should-->
74-
<enable_controller> true </enable_controller>
73+
disabled.-->
74+
<isDisabled> false </isDisabled>
7575
<!--Gain for position errors-->
76-
<kp> 25.00000000 </kp>
76+
<kp> 16.00000000 </kp>
7777
<!--Gain for velocity errors-->
78-
<kv> 10.00000000 </kv>
78+
<kv> 8.00000000 </kv>
7979
</CorrectionController>
8080
</objects>
8181
<groups/>

Applications/Forward/test/testForward.cpp

Lines changed: 60 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -33,60 +33,34 @@
3333
using namespace OpenSim;
3434
using namespace std;
3535

36-
void testPendulum(); // test manager/integration process
37-
void testPendulumExternalLoad(); // test application of external loads point in pendulum
38-
void testPendulumExternalLoadWithPointInGround(); // test application of external loads point in ground
39-
void testArm26(); // now add computation of controls and generation of muscle forces
40-
void testGait2354(); // controlled muscles and ground reactions forces
41-
void testGait2354WithController(); // included additional controller
36+
void testPendulum();
37+
void testPendulumExternalLoad();
38+
void testPendulumExternalLoadWithPointInGround();
39+
void testArm26();
40+
void testGait2354();
41+
void testGait2354WithController();
42+
void testGait2354WithControllerGUI();
43+
4244

4345
int main() {
4446
Object::renameType("Thelen2003Muscle", "Thelen2003Muscle_Deprecated");
4547

46-
SimTK::Array_<std::string> failures;
47-
48-
// test manager/integration process
49-
try { testPendulum(); cout << "\nPendulum test PASSED " << endl; }
50-
catch (const std::exception& e)
51-
{ cout << e.what() <<endl; failures.push_back("testPendulum"); }
52-
53-
// test application of external loads
54-
try { testPendulumExternalLoad();
55-
cout << "\nPendulum with external load test PASSED " << endl; }
56-
catch (const std::exception& e)
57-
{ cout << e.what() <<endl; failures.push_back("testPendulumExternalLoad"); }
58-
59-
// test application of external loads
60-
try { testPendulumExternalLoadWithPointInGround();
61-
cout << "\nPendulum with external load and point in ground PASSED " << endl; }
62-
catch (const std::exception& e)
63-
{ cout << e.what() <<endl; failures.push_back("testPendulumExternalLoadWithPointInGround"); }
64-
65-
// now add computation of controls and generation of muscle forces
66-
try { testArm26();
67-
cout << "\narm26 test PASSED " << endl; }
68-
catch (const std::exception& e)
69-
{ cout << e.what() <<endl; failures.push_back("testArm26"); }
70-
71-
// include applied ground reactions forces
72-
try { testGait2354();
73-
cout << "\ngait2354 test PASSED " << endl; }
74-
catch (const std::exception& e)
75-
{ cout << e.what() <<endl; failures.push_back("testGait2354"); }
76-
77-
// finally include a controller
78-
try { testGait2354WithController();
79-
cout << "\ngait2354 with correction controller test PASSED " << endl; }
80-
catch (const std::exception& e)
81-
{ cout << e.what() <<endl; failures.push_back("testGait2354WithController"); }
82-
83-
if (!failures.empty()) {
84-
cout << "Done, with failure(s): " << failures << endl;
85-
return 1;
86-
}
87-
88-
cout << "Done" << endl;
89-
return 0;
48+
SimTK_START_TEST("testForward");
49+
// test manager/integration process
50+
SimTK_SUBTEST(testPendulum);
51+
// test application of external loads point in pendulum
52+
SimTK_SUBTEST(testPendulumExternalLoad);
53+
// test application of external loads with point moving in ground
54+
SimTK_SUBTEST(testPendulumExternalLoadWithPointInGround);
55+
// now add computation of controls and generation of muscle forces
56+
SimTK_SUBTEST(testArm26);
57+
// controlled muscles and ground reactions forces
58+
SimTK_SUBTEST(testGait2354);
59+
// included additional controller
60+
SimTK_SUBTEST(testGait2354WithController);
61+
// implements steps GUI takes to provide a model
62+
SimTK_SUBTEST(testGait2354WithControllerGUI);
63+
SimTK_END_TEST();
9064
}
9165

9266
void testPendulum() {
@@ -249,3 +223,39 @@ void testGait2354WithController() {
249223
CHECK_STORAGE_AGAINST_STANDARD(results, *standard, rms_tols,
250224
__FILE__, __LINE__, "testGait2354WithController failed");
251225
}
226+
227+
void testGait2354WithControllerGUI() {
228+
229+
// The following lines are the steps from ForwardToolModel.java that
230+
// associates the a previous (orgiModel) model with the ForwardTool
231+
// instead of the Tool loading the model specified in the setup
232+
ForwardTool forward("subject01_Setup_Forward_Controller.xml");
233+
Model origModel(forward.getModelFilename());
234+
235+
Model* model = new Model(origModel);
236+
model->initSystem();
237+
238+
const std::string resultsDir{ "ResultsCorrectionControllerGUI" };
239+
240+
forward.setResultsDir(resultsDir);
241+
forward.updateModelForces(*model, "");
242+
forward.setModel(*model);
243+
244+
model->initSystem();
245+
246+
forward.run();
247+
248+
// For good measure we'll make sure we still get the identical results
249+
Storage results(resultsDir+"/subject01_states.sto");
250+
//Storage standard("std_subject01_walk1_states.sto");
251+
Storage standard("ResultsCorrectionController/subject01_states.sto");
252+
253+
int nstates = forward.getModel().getNumStateVariables();
254+
int nq = forward.getModel().getNumCoordinates();
255+
std::vector<double> rms_tols(2 * nstates, SimTK::SqrtEps);
256+
257+
CHECK_STORAGE_AGAINST_STANDARD(results, standard, rms_tols,
258+
__FILE__, __LINE__, "testGait2354WithControllerGUI failed");
259+
260+
delete model;
261+
}

OpenSim/Tools/CorrectionController.cpp

Lines changed: 37 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -223,29 +223,27 @@ void CorrectionController::computeControls(const SimTK::State& s, SimTK::Vector&
223223

224224
SimTK::Vector actControls(1, 0.0);
225225

226-
for(int i=0; i< getActuatorSet().getSize(); i++){
227-
auto act =
228-
dynamic_cast<const CoordinateActuator*>(&getActuatorSet().get(i));
229-
SimTK_ASSERT( act, "CorrectionController::computeControls dynamic cast failed");
230-
231-
Coordinate *aCoord = act->getCoordinate();
232-
if( aCoord->isConstrained(s) ) {
226+
int i = 0;
227+
auto coordinateActuators = getComponentList<CoordinateActuator>();
228+
for(auto& act : coordinateActuators) {
229+
const Coordinate* coord = act.getCoordinate();
230+
if(coord->isConstrained(s) ) {
233231
actControls = 0.0;
234232
}
235-
else
236-
{
237-
double qval = aCoord->getValue(s);
238-
double uval = aCoord->getSpeedValue(s);
233+
else {
234+
double qval = coord->getValue(s);
235+
double uval = coord->getSpeedValue(s);
239236

240237
// COMPUTE EXCITATIONS
241-
double oneOverFmax = 1.0 / act->getOptimalForce();
238+
double oneOverFmax = 1.0 / act.getOptimalForce();
242239
double pErr = qval - yDesired[2*i];
243240
double vErr = uval - yDesired[2*i+1];
244241
double pErrTerm = _kp*oneOverFmax*pErr;
245242
double vErrTerm = _kv*oneOverFmax*vErr;
246243
actControls = -vErrTerm - pErrTerm;
247244
}
248-
getActuatorSet()[i].addInControls(actControls, controls);
245+
act.addInControls(actControls, controls);
246+
++i;
249247
}
250248
}
251249

@@ -257,16 +255,23 @@ void CorrectionController::extendConnectToModel(Model& model)
257255
// create an actuator for each generalized coordinate in the model
258256
// add these actuators to the model and set their indexes
259257
const CoordinateSet& cs = _model->getCoordinateSet();
258+
auto actuators = model.updComponentList<CoordinateActuator>();
259+
260260
for(int i=0; i<cs.getSize(); i++) {
261-
std::cout << " CorrectionController::extendConnectToModel(): "
262-
<< cs.get(i).getName()+"_corrector" << " added "
263-
<< std::endl;
264-
std::string name = cs.get(i).getName()+"_corrector";
265-
CoordinateActuator *actuator = NULL;
266-
if(_model->getForceSet().contains(name)){
267-
actuator = (CoordinateActuator *)&_model->getForceSet().get(name);
261+
const Coordinate& coord = cs[i];
262+
const std::string name = coord.getName() + "_corrector";
263+
264+
CoordinateActuator* actuator = nullptr;
265+
266+
for (auto& ca : actuators) {
267+
if (ca.getName() == name) {
268+
actuator = &ca;
269+
break;
270+
}
268271
}
269-
else{
272+
273+
if(!actuator) {
274+
// create the corrector actuator if it doe not already exist
270275
actuator = new CoordinateActuator();
271276
actuator->setCoordinate(&cs.get(i));
272277
actuator->setName(name);
@@ -275,16 +280,22 @@ void CorrectionController::extendConnectToModel(Model& model)
275280
// the controller is removed, so are all the actuators it added.
276281
adoptSubcomponent(actuator);
277282
setNextSubcomponentInSystem(*actuator);
278-
}
279283

280-
actuator->setOptimalForce(1.0);
284+
std::cout << " CorrectionController::extendConnectToModel(): "
285+
<< name << " added " << std::endl;
286+
287+
actuator->setOptimalForce(1.0);
288+
}
281289

282-
updActuators().adoptAndAppend(actuator);
290+
// Add to the Controller's list of Actuators (no ownership).
291+
addActuator(*actuator);
283292
}
293+
284294
setNumControls(getActuatorSet().getSize());
285295

286-
printf(" CorrectionController::extendConnectToModel() num Actuators= %d kv=%f kp=%f \n",
287-
_model->getForceSet().getSize(), _kv, _kp );
296+
printf(" CorrectionController::extendConnectToModel() "
297+
"num Actuators= %d kv=%f kp=%f \n",
298+
getNumControls(), _kv, _kp );
288299
}
289300

290301
// for any initialization requiring a state or the complete system

0 commit comments

Comments
 (0)