Page 1 of 1

how can I remove a prescribedForce from my model?

Posted: Sun Dec 02, 2012 11:32 pm
by porsasina
Hi everyone,
I am trying to find an optimal force pattern which minimizes a cost function in my model. As all optimization routines, it is obvious that it is an iterative procedure. Here is a the algorithm that I am using:

1- create a prescribedForce object
2- while (not minimum)
2-1- add the prescribedForce to the model
2-2- run forward dynamics and calculate the cost
2-3- create a new prescribedForce (which has smaller cost value)
end of while

when I implement this algorithm, it only runs for the first iteration. After that when it reaches to line (2-1) it returns this error:
ModelComponent: Cannot include subcomponent after createSystem().

below you can find a brief version of my cost function, which adds the prescribed force to the model and runs the forward dynamics:

Code: Select all

float calcCost(GAGenome & genome, Model & OsimModel) {
		// Creating a prescribed force using the inputs (genome)
		double time[73], armForceVec[73];
		for (int ii=0; ii<73; ii++){ // mesh size = 5 degree 360/5 = 72
			time [ii]     = ii*realValues.phenotype(18)/72;
			armForceVec [ii] = realValues.phenotype(19)*sin( (2*PI*time [ii]/realValues.phenotype(18)) + realValues.phenotype(20) );
		}
		const BodySet& theBodySet = OsimModel.getBodySet();
		OpenSim::Body& torso = theBodySet.get(12);
		PiecewiseLinearFunction *armForceY = new PiecewiseLinearFunction(73, time, armForceVec);
		PrescribedForce *prescribedForce = new PrescribedForce(&torso);
		prescribedForce->setName("armForce");
		prescribedForce->setForceFunctions(new Constant(0.0), armForceY, new Constant(0.0));
		prescribedForce->setPointFunctions(new Constant(0.00307226), new Constant(0.36175710), new Constant(0.0));

		/*
		.
		.
		.
		create a controller for the muscles
		.
		.
		.
		*/

		OsimModel.addForce(prescribedForce);
		OsimModel.addController(muscleController);

		/*
		.
		.
		.
		run the forward dynamics and calculate the cost
		.
		.
		.
		*/

		OsimModel.removeController(muscleController);
		return(cost);

}
I know that I have to remove the old prescribedForce at the end of each iteration, just before returning the cost value. Just like removing the controller. But unfortunately it seems that there is no way to remove a prescribedForce from the model. Am I right? any suggestions?
Can I somehow EDIT an existing prescribedForce at each iteration? how?

please note that OsimModel is an input to the function calcCost. I cannot load a new model from a *.osim file at each iteration because it will lead to a great amount of memory leak.

Thanks
Sina

Re: how can I remove a prescribedForce from my model?

Posted: Mon Dec 03, 2012 11:40 am
by aymanh
Hi Sina,

I think the best approach would be to "Edit" the force rather than removing it and adding it again with each iteration. Removal and addition will require you to call initSystem again (to propagate the changes to the SimTK::System underneath) that's why you can't add the force again in your objective function. What are you modifying in your PrescribedForce?

-Ayman

Re: how can I remove a prescribedForce from my model?

Posted: Mon Dec 03, 2012 3:18 pm
by porsasina
Hi dear Ayman and thanks for your reply
I want to edit the "ForceFunctions". here is my code:

Code: Select all

      double time[73], armForceVec[73];
		// @ each iteration I have to edit time[73] and armForceVec[73]
		const BodySet& theBodySet = OsimModel.getBodySet();
		OpenSim::Body& torso = theBodySet.get(12);
		PiecewiseLinearFunction *armForceY = new PiecewiseLinearFunction(73, time, armForceVec);
		PrescribedForce *prescribedForce = new PrescribedForce(&torso);
		prescribedForce->setName("armForce");
		prescribedForce->setForceFunctions(new Constant(0.0), armForceY, new Constant(0.0));
		prescribedForce->setPointFunctions(new Constant(0.00307226), new Constant(0.36175710), new Constant(0.0));
		OsimModel.addForce(prescribedForce);
at each iteration, I have to modify two arrayes: time[73] and armForceVec[73]

thanks Ayman

-Sina

Re: how can I remove a prescribedForce from my model?

Posted: Mon Dec 03, 2012 6:50 pm
by porsasina
HI Ayman,
Here is what I tried to do. I made an osim file(test.osim) which has a prescribedforce named armForce under the ForceSet tag:

Code: Select all

<ForceSet name="">
	<objects>
		<PrescribedForce name="armForce">
			<isDisabled> false </isDisabled>
			<body> torso </body>
			<pointIsGlobal> false </pointIsGlobal>
			<forceIsGlobal> true </forceIsGlobal>
			<FunctionSet name="forceFunctions">
				<objects/>
				<groups/>
			</FunctionSet>
			<FunctionSet name="pointFunctions">
				<objects/>
				<groups/>
			</FunctionSet>
			<FunctionSet name="torqueFunctions">
				<objects/>
				<groups/>
			</FunctionSet>
		</PrescribedForce>
	</objects>
	<groups/>
</ForceSet>
I want load this osim model into my c++ code to modify the forceFunctions. I tried:

Code: Select all

testModel.getForceSet().get("armForce").setForceFunctions(new Constant(0.0), armForceY, new Constant(0.0))
which returns this error: error C2039: 'setForceFunctions' : is not a member of 'OpenSim::Force'

But when I run the following line, it prints PrescribedForce on the screen

Code: Select all

cout << testModel.getForceSet().get("armForce").getType() << "\n";
I am completely confused!! It would be great if you could help me to understand how can i modify the prescribed force.
Thanks,
Sina

Re: how can I remove a prescribedForce from my model?

Posted: Mon Dec 03, 2012 10:23 pm
by sherm
Hi, Sina. I can give Ayman a break on this one ...

When you get an element from a ForceSet it is a Force (the base class) not a PrescribedForce (the concrete class). If you then want to call a method of PrescribedForce you must first downcast the generic Force to a more-specific PrescribedForce. C++ has a dynamic_cast operator for this purpose.

You will need something like this:

Code: Select all

// downcast the abstract Force to the concrete PrescribedForce
dynamic_cast<PrescribedForce>(testModel.getForceSet().get("armForce"))
        .setForceFunctions(...);
Apologies if I got the syntax wrong, but that is the approach.

Regards,
Sherm

Re: how can I remove a prescribedForce from my model?

Posted: Tue Dec 04, 2012 11:59 am
by aymanh
Thanks Sherm for the clear explanation.

I might just add that for other users not writing in C++, they can use the alternate syntax:

Code: Select all

PrescribedForce.safeDownCast(testModel.getForceSet().get("armForce"))
Which ends up executing the same function (can be used in C++ as well).

Looking into the PrescribedForce code, it looks like all you need is to call
setForceFunctions(...) and setPointFunctions(...) repeatedly in your objective function and it would take care of deleting the old functions and releasing their resources for you.

Hope this helps and please let us know if you continue to have questions.

Best regards,
-Ayman

Re: how can I remove a prescribedForce from my model?

Posted: Tue Dec 04, 2012 5:18 pm
by porsasina
Hi Sherm and Ayman,
Thanks. It was a great help and I appreciate it.
Sina

Re: how can I remove a prescribedForce from my model?

Posted: Tue Dec 04, 2012 6:17 pm
by porsasina
just to finish this post, this is the final code which works.
I had to replace testModel.getForceSet() with testModel.updForceSet()

Code: Select all

PiecewiseLinearFunction *armForceY = new PiecewiseLinearFunction(73, time, armForceVec);
PrescribedForce& armForce = dynamic_cast<PrescribedForce&>(testModel.updForceSet().get("armForce"));
armForce.setForceFunctions(new Constant(0.0), armForceY, new Constant(0.0));
Thanks again.
Sina