Rope Physics

Started by
7 comments, last by unbird 13 years, 7 months ago
Im trying to implement a rope in a physics simulation. To do this im using particle physics and contact generators. Where the rope is made up of a number of particles all linked togeather with rope contacts. To cause the whole rope not to over-extend, each rope joint that links 2 particles changes the impulse on each particle.

if( length > restlength ){   move particles closer togeather}  else if( length < restlength ){   do nothing, as ropes can be coiled}


But this doesnt seem to work. The contacts seem to be gradually getting longer, allowing the particles to move further and further apart. Its happening quite slowly, but its noticeable.

I assume this is due to contending particles?

   CurrentPose                        DesiredPose    X Particle A                      X Particle A    |                                 |    |                                 |    |                                 |    |                                 X Particle B     |                                 |    |                                 |    X Particle B                      |    |                                 X Particle C    |    |    |    |    |    X Particle C


Where on the left the segments are too long and need to be corrected. Particle A is fixed in space, and so nothing is changed on A, so correcting the first segment, causes B to move closer to A, doing so by changing B's impulse. But then correcting the second segment, by changing B and C's impulse to move closer togeather, then voids B's impulse that was corrected by the first segment. And this will happen all the way down the chain.

Is this what is causing the problem? How could this be solved? Should I treat the first particle in each segment fixed, and only alter the other ends impulse?
Advertisement
How about you pass through the loops working out all the delta v's first, then loop through applying them all afterward?
------------------------------Great Little War Game
Thats actually what I do at the moment. I create a list of contacts, and then resolve them in one go.
Verlet ;)
I wonder if the integration scheme is the reason that hinders the system to find the equilibrium.
Quote:...doing so by changing B's impulse...

How exactly ? And: Without calculating forces ? Changing the impulse is like changing the velocity directly. And - though you haven't explicitly told - you seem to apply gravity, which is a force. Mixing those two approaches (impulse<->forces) is likely the problem. Anyway: Can you clarify the whole setup and/or show us some code ?

Edit: *facepalm* Changing the impulse is applying a force. Maybe you can solve your problem by directly changing the positions.
For each segment that joins 2 particles, I check to see if its length is more than its supposed to be, if it is, I create a contact object. Which stores the contact normal (particleB-ParticleA), and the particles.

void RopeContactGenerator::GetState(std::vector< ContactData>& pContacts ){	static ContactData ContactData;	Vec3 Vec = m_b->GetPosition() - m_a->GetPosition();	float CurrentLength = Vec.Length();	if( CurrentLength < m_Length )		return;	Vec3 Normal = -Vec.Normalize();	if( m_FixA ) //Is Particle A in this segment anchored?	{		ContactData.SetObjects( m_b, 0 );	}	else	{		ContactData.SetObjects( m_b, m_a );	}	ContactData.SetContactNormal( Normal );	ContactData.SetRestitution(0);	ContactData.SetPenetration( CurrentLength - m_Length );	pContacts.push_back( ContactData );}


Once Ive gone through the whole rope, lets say its 10 segments. I then go resolve the contacts by adding impulses to the particles in that contact object. Where the amount of impulse is based on the mass of each particle.

double ContactData::GetSeparatingVelocity(){    Vec3 RelativeVelocity = m_pObjects[0]->GetVelocity();    	if (m_pObjects[1]) 		RelativeVelocity -= m_pObjects[1]->GetVelocity();    	return Dot(RelativeVelocity, m_ContactNormal);}void ContactData::ResolveVelocity( double FrameLapse){    // Find the velocity in the direction of the contact    double SeparatingVelocity = GetSeparatingVelocity();    // Check if it needs to be resolved    if (SeparatingVelocity > 0)    {        // The contact is either separating, or stationary - there's        // no impulse required.        return;    }    // Calculate the new separating velocity	double DeltaVelocity = -SeparatingVelocity * (1.0 + m_Restitution);    // We apply the change in velocity to each object in proportion to    // their inverse mass (i.e. those with lower inverse mass [higher    // actual mass] get less change in velocity)..	double TotalInverseMass = m_pObjects[0]->GetInvMass();	if (m_pObjects[1]) 		TotalInverseMass += m_pObjects[1]->GetInvMass();    // If all particles have infinite mass, then impulses have no effect    if (TotalInverseMass <= 0) 		return;    // Find the amount of impulse per unit of inverse mass    Vec3 ImpulsePerUnitMass = m_ContactNormal * (DeltaVelocity / TotalInverseMass);    // Apply impulses: they are applied in the direction of the contact,    // and are proportional to the inverse mass.    m_pObjects[0]->SetVelocity(	m_pObjects[0]->GetVelocity() +								ImpulsePerUnitMass * m_pObjects[0]->GetInvMass());    if (m_pObjects[1])    {        // Particle 1 goes in the opposite direction        m_pObjects[1]->SetVelocity(	m_pObjects[1]->GetVelocity() +									ImpulsePerUnitMass * -m_pObjects[1]->GetInvMass());    }}
Aha, Game Physics Engine Development. Make sure your contact resolver looks the same (pcontacts.cpp). The trick using a contact generator for ropes (the author calls them cables) works using the penetration depth which then gets resolved in another part of the resolver, namely ParticleContact::resolveInterpenetration. Make sure that part works. Probably the resolution order is also crucial.

One other thing that caught my eye is a (probably) different restitution: The author uses 0 only for rods, maybe that's another problem.

[Edited by - unbird on August 25, 2010 10:21:21 AM]
Ah ok. I was trying to avoid resolving penetration depth as I thought the penetration correction was only for visual purposes, and that if the demo is running at a descent framerate, the change in impulses would be enough and you wouldnt really see the penetration. Maybe I understood that incorrectly.

I'll put the reslove penetration code back in and see if it helps.

In the source code I have, the author only uses zero restitution for Rods.

I dont suppose by any chance you have a working example of rope do you? I'd love to take a look at your code.
Nope, sorry, and my contact resolver isn't finished anyway (no contact cache, no incremental resolution). Mine is 2D anyway. But the examples of the book implement a simple bridge, maybe you can change it to a rope system. And: You do have the books code, don't you ?

And by the way, from what I hear, solving interpenetration seems an essential part of a rigid body system to make a simulation work. On the other hand: The contact generation approach is IMHO a simple hack for something more complex: Constrained dynamics.

Edit: Ah, sorry, you probably don't do rigid bodies yet, right ? So my answer was a bit misleading. But you do need that part of the solver.

This topic is closed to new replies.

Advertisement