Measuring Contact Force in Forward Simulation

Provide easy-to-use, extensible software for modeling, simulating, controlling, and analyzing the neuromusculoskeletal system.
User avatar
Kenechukwu Mbanisi
Posts: 51
Joined: Fri Feb 10, 2017 2:50 pm

Measuring Contact Force in Forward Simulation

Post by Kenechukwu Mbanisi » Wed Aug 23, 2017 9:28 am

Hello there,

I am trying to study how the contact forces are applied on OpenSim. I have used contact spheres to model object-ground contact. It's modeled as an ElasticFoundationForce.

What I want to do is to be able to measure the contact force generated during simulation at every time-step. My goal is to eventually use this as a means of measuring the external force on my model for a force feedback controller.

Can I get any pointers on what methods/functions to use in obtaining this in the C++ API?

Thank you.

Kenechukwu


User avatar
Kenechukwu Mbanisi
Posts: 51
Joined: Fri Feb 10, 2017 2:50 pm

Re: Measuring Contact Force in Forward Simulation

Post by Kenechukwu Mbanisi » Mon Aug 28, 2017 5:39 pm

Thank you very much, Dimitar.

I went through the example code and I have made a simple example using my model.

Code: Select all

class forceReport : public PeriodicEventReporter {
public:
	forceReport(const MultibodySystem& system,
		const CompliantContactSubsystem& contactForces,
		Real reportInterval)
		: PeriodicEventReporter(reportInterval), m_system(system), m_contactForces(contactForces) {}

	void handleEvent(const State& state) const override {
		m_system.realize(state, Stage::Dynamics);
		const int ncont = m_contactForces.getNumContactForces(state);
		for (int i = 0; i < ncont; ++i) {
			const ContactForce& force = m_contactForces.getContactForce(state, i);
			std::cout << force << std::endl;
		}
}
private:
	const MultibodySystem& m_system;
	const CompliantContactSubsystem& m_contactForces;
};

int main()
{
	try {
		Model osimModel("my_model.osim");
		State& s = osimModel.initSystem();
		MultibodySystem system = osimModel.updMultibodySystem();

		ContactTrackerSubsystem tracker(system);
		CompliantContactSubsystem contactForces(system, tracker);

		osimModel.buildSystem();
		State& s_new = osimModel.initializeState();
		
		system.addEventReporter(new forceReport(system, contactForces, 0.1));
		
		const State& s_new = system.realizeTopology();
		
		SimTK::RungeKuttaMersonIntegrator integrator(osimModel.getMultibodySystem());
		integrator.setAccuracy(1.0e-3);
		Manager manager(osimModel, integrator);
		manager.setInitialTime(0.0); manager.setFinalTime(1.0);
		manager.integrate(s_new);
I find that the code throws an exception at the "system.realizeTopology()" line:

Code: Select all

Exception thrown at 0x00007FFC4183472C (OpenSim_SimTKcommon.dll) in exampleController.exe: 0xC0000005: Access violation reading location 0x000003E0EFE6D1D0.
It seems like it is failing to realize the topology of the system. I am not sure what I am doing wrong here. Any pointers would be helpful.

Thank you.

Kenechukwu

User avatar
Thomas Uchida
Posts: 1792
Joined: Wed May 16, 2012 11:40 am

Re: Measuring Contact Force in Forward Simulation

Post by Thomas Uchida » Mon Aug 28, 2017 10:08 pm

I haven't compiled your code to investigate in detail, but at first glance it looks like

Code: Select all

// this line
MultibodySystem system = osimModel.updMultibodySystem();
// should be
MultibodySystem& system = osimModel.updMultibodySystem();
In the first case, it looks like you are constructing a new MultibodySystem rather than fetching a writable reference to the MultibodySystem associated with osimModel.

User avatar
Kenechukwu Mbanisi
Posts: 51
Joined: Fri Feb 10, 2017 2:50 pm

Re: Measuring Contact Force in Forward Simulation

Post by Kenechukwu Mbanisi » Tue Aug 29, 2017 9:53 am

Thank you Tom.

I made that correction as well as some other few modifications. The system realizes to topology now, but the concern is that it throws an unknown exception at the "manager.integrate(s_new)" line.

Code: Select all

class forceReport : public PeriodicEventReporter {

public:
	forceReport(const MultibodySystem& system,
		const CompliantContactSubsystem& contactForces,
		Real reportInterval)
		: PeriodicEventReporter(reportInterval), m_system(system), m_contactForces(contactForces) {}

	void handleEvent(const State& state) const override {
		m_system.realize(state, Stage::Dynamics);

		const int ncont = m_contactForces.getNumContactForces(state);
		std::cout << ncont << std::endl;
		for (int i = 0; i < ncont; ++i) {
			const ContactForce& force = m_contactForces.getContactForce(state, i);
			std::cout << force << std::endl;
		}
}
private:
	const MultibodySystem& m_system;
	const CompliantContactSubsystem& m_contactForces;
};

int main()
{
	try {
		Model osimModel("my_model.osim");		
		State& s = osimModel.initSystem();		
		MultibodySystem& system = osimModel.updMultibodySystem();	

		ContactTrackerSubsystem tracker(system);		
		CompliantContactSubsystem contactForces(system, tracker);
				
		State& s_new = osimModel.initializeState();

		forceReport* conforceReporter = new forceReport(system, contactForces, 0.1);
		system.addEventReporter(conforceReporter);
		system.realizeTopology();				

		SimTK::RungeKuttaMersonIntegrator integrator(system);
		integrator.setAccuracy(1.0e-3);
		Manager manager(osimModel, integrator);

		manager.setInitialTime(0.0); manager.setFinalTime(1.0);
		manager.integrate(s_new);
	}
I have added the code and the model here. Any pointers here would be very much appreciated.

Kenechukwu
Attachments
my_model with codes.zip
(397.28 KiB) Downloaded 69 times

User avatar
Thomas Uchida
Posts: 1792
Joined: Wed May 16, 2012 11:40 am

Re: Measuring Contact Force in Forward Simulation

Post by Thomas Uchida » Tue Aug 29, 2017 3:38 pm

I don't think you should need State& s_new = osimModel.initializeState();. Is it possible to remove that line and call manager.integrate(system); instead?

User avatar
Kenechukwu Mbanisi
Posts: 51
Joined: Fri Feb 10, 2017 2:50 pm

Re: Measuring Contact Force in Forward Simulation

Post by Kenechukwu Mbanisi » Tue Aug 29, 2017 4:47 pm

Hello Tom,

Thanks for the comment. I just tried that; it seems that the integrate method only takes values of type "SimTK::State&".

Here's the error I get: "a reference of type 'SimTK::State&' cannot be initialized with a value of type 'SimTK::MultibodySystem' "

I thought that it would be useful to initialize the state after we add the new subsystems to the multibodysystem.

Kenechukwu

User avatar
Thomas Uchida
Posts: 1792
Joined: Wed May 16, 2012 11:40 am

Re: Measuring Contact Force in Forward Simulation

Post by Thomas Uchida » Tue Aug 29, 2017 5:39 pm

Ah, sorry; you're right. Is there a reason you want to use the Manager rather than the TimeStepper as in ExampleContactPlayground.cpp? I will try to build your code and investigate in more detail later tonight.

User avatar
Thomas Uchida
Posts: 1792
Joined: Wed May 16, 2012 11:40 am

Re: Measuring Contact Force in Forward Simulation

Post by Thomas Uchida » Wed Aug 30, 2017 12:23 am

You can use a TimeStepper (https://simtk.org/api_docs/simbody/3.5/ ... epper.html) and make a couple small changes:

Code: Select all

Model& model = Model("my_model.osim");
model.initSystem();
MultibodySystem& system = model.updMultibodySystem();
ContactTrackerSubsystem tracker(system);
CompliantContactSubsystem contactForces(system, tracker);
forceReport* myForceReport = new forceReport(system, contactForces, 0.1);
system.addEventReporter(myForceReport);
const State& state = system.realizeTopology();

SimTK::RungeKuttaMersonIntegrator integrator(model.getSystem());
SimTK::TimeStepper ts(model.getSystem(), integrator);
ts.initialize(state);
ts.stepTo(10.);
I'm guessing that you want to model contact between the seat and the driver. If so, it looks like you will need to add a degree of freedom to get meaningful forces from the CompliantContactSubsystem (the pelvis is currently welded to the seat).

User avatar
Kenechukwu Mbanisi
Posts: 51
Joined: Fri Feb 10, 2017 2:50 pm

Re: Measuring Contact Force in Forward Simulation

Post by Kenechukwu Mbanisi » Wed Aug 30, 2017 10:37 am

Thank you Tom.

With your comments, I was able to have the code compile and run successfully, however, as you noted, the contact observer doesn't measure any active contacts during simulation. I ran the same model in the OpenSim GUI using the forward dynamics and force reporter tools and I was able to observe contact forces through the various contact interfaces in the model (the hip/femur to seat and the foot to ground).
As you stated, there'll be no contact forces from the contact interfaces connected to the pelvis (because its welded to the seat), but we're trying to measure the forces from the other interfaces.

Please see images here: (I had some trouble uploading images directly onto this window)
Full model after 1s of simulation showing the contact forces: https://goo.gl/2iK7fu

Plot of contact force on the femur (force "a"): https://goo.gl/x8mc37

Plot of contact force on the foot (force "b"): https://goo.gl/wH4qVA

I am guessing that my definition of the Compliant Contact Subsystem might be inaccurate because no contact forces or surfaces are being observed.

POST REPLY