how can I remove a prescribedForce from my model?

Provide easy-to-use, extensible software for modeling, simulating, controlling, and analyzing the neuromusculoskeletal system.
POST REPLY
User avatar
Sina Porsa
Posts: 99
Joined: Thu Feb 03, 2011 7:21 pm

how can I remove a prescribedForce from my model?

Post by Sina Porsa » Sun Dec 02, 2012 11:32 pm

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

User avatar
Ayman Habib
Posts: 2252
Joined: Fri Apr 01, 2005 12:24 pm

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

Post by Ayman Habib » Mon Dec 03, 2012 11:40 am

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

User avatar
Sina Porsa
Posts: 99
Joined: Thu Feb 03, 2011 7:21 pm

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

Post by Sina Porsa » Mon Dec 03, 2012 3:18 pm

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

User avatar
Sina Porsa
Posts: 99
Joined: Thu Feb 03, 2011 7:21 pm

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

Post by Sina Porsa » Mon Dec 03, 2012 6:50 pm

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

User avatar
Michael Sherman
Posts: 808
Joined: Fri Apr 01, 2005 6:05 pm

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

Post by Michael Sherman » Mon Dec 03, 2012 10:23 pm

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

User avatar
Ayman Habib
Posts: 2252
Joined: Fri Apr 01, 2005 12:24 pm

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

Post by Ayman Habib » Tue Dec 04, 2012 11:59 am

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

User avatar
Sina Porsa
Posts: 99
Joined: Thu Feb 03, 2011 7:21 pm

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

Post by Sina Porsa » Tue Dec 04, 2012 5:18 pm

Hi Sherm and Ayman,
Thanks. It was a great help and I appreciate it.
Sina

User avatar
Sina Porsa
Posts: 99
Joined: Thu Feb 03, 2011 7:21 pm

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

Post by Sina Porsa » Tue Dec 04, 2012 6:17 pm

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

POST REPLY