Jump to content
  • Advertisement
Sign in to follow this  
maya18222

Rope Physics

This topic is 2859 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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?

Share this post


Link to post
Share on other sites
Advertisement
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.

Share this post


Link to post
Share on other sites
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());
}
}

Share this post


Link to post
Share on other sites
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]

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!