best way to change the length of a rope

Post Reply
Drager
Posts: 8
Joined: Tue Sep 21, 2010 4:49 pm

best way to change the length of a rope

Post by Drager »

Hello,

I am using the CreateRope function (btSoftbody) to create a rope, where the player is connected to one end and a other object is connected to the other.

Now I would like to make the player able, to change the length of the rope (increase or decrase).
I tried the scale function of btSoftbody, but this gave very strange results (jumping player etc.)
I tried scaling of 0.99 for decreasing and 1.0 / 0.99 for increasing, but this gaves strange results.
(It works fine, if the rope is only connected to one anchor, but I would like to move the player, when increasing / decreasing)

Now I am trying to add and remove nodes of the rope, but this seems very difficult to get the right position for the new node.

Is there any easy way to change the length of a rope, while connected to two objects?

Thanks

Michael
priest_wd
Posts: 10
Joined: Wed Sep 22, 2010 3:33 pm

Re: best way to change the length of a rope

Post by priest_wd »

hello Michael

I have the same problem. I'm trying to build a "ship to shore gantry crane simulator", so I need the rope to be attached to my cockpit and to the spreader in the other side. But I can't figure out how to change the length of the rope either.

What I did was to create a rope with the maximun length I will use, then attach the superior node to a KINEMATIC_OBJECT far above the position on y-axis of the cockpit, then move the kinematic object and the cockpit together so it can look like the rope is attached to the cockpit. When i want to extend the rope, i move the kinematic object in y-axis.

Other way i think is to create your own rope. You can make it with an array of rigidbodies and constraints between them, so you can scale the rigid bodies. Right now i'm doing it this way.

well, it doesnt look like the more efficient way, but i hope it can help you in some way. XD

What I dont have a clue right now is how to make a rope or a constraint stronger, i mean, when i attach a rope to a static object and attach in the other side a heavy object, the rope seems to scale itself, like an elastic rope, and what i need is more like an iron chain. Same goes for the constraints. Do you have any idea of how to fix it? I'll be gratefull.

By the way, sorry for my bad english :S

Greetings!
Drager
Posts: 8
Joined: Tue Sep 21, 2010 4:49 pm

Re: best way to change the length of a rope

Post by Drager »

Hi Priest,

Thanks for your answer, I will try the idea with a rigid body rope.

I dont know how to make it more non elastic, but I read in an other thread this idea, perhaps it will help you:
"Perhaps a generic6dof joint with movements blocked but rotations allowed?"

Michael
priest_wd
Posts: 10
Joined: Wed Sep 22, 2010 3:33 pm

Re: best way to change the length of a rope

Post by priest_wd »

Hello!

I used a generic6dof joint and it works fine! Many thanks!
Drager
Posts: 8
Joined: Tue Sep 21, 2010 4:49 pm

Re: best way to change the length of a rope

Post by Drager »

Hi,

Changing the length with a rigid rope worked, thanks.

Also I added generic6dof joint, and set the lower and upper limit to 0.
But still I can stretch the rope.
Is there a trick you used?

I noticed, increasing the mass of rigid bodies helps, but I want a light rope.
Any ideas?
priest_wd
Posts: 10
Joined: Wed Sep 22, 2010 3:33 pm

Re: best way to change the length of a rope

Post by priest_wd »

Hi.

Well, when I played with the examples, I noticed that avoiding the use of "setCollisionFlags" or "setActivationState" (I dont remember wich one) when creating the rigidbody, it seems to solve the problem. Tell me if it works

Greetings!
Drager
Posts: 8
Joined: Tue Sep 21, 2010 4:49 pm

Re: best way to change the length of a rope

Post by Drager »

Hi,

Thanks for your answer! I tried both, but none worked for me.

I now made a trade-off, by slightly increase the total rope mass, and also increasing the localInertia of each rigid body.
Increasing the localInertia also decreased the ropes flexibility, but also gives some strange results if increasing too much.

This worked for me, but I am not satisfied with this solution.
You got any more ideas? Otherwise I leave it that way.

Thanks,

Michael
priest_wd
Posts: 10
Joined: Wed Sep 22, 2010 3:33 pm

Re: best way to change the length of a rope

Post by priest_wd »

Hi!

Check this topic:

http://www.bulletphysics.org/Bullet/php ... f=9&t=3402

I tried modifying parameters for the softness/rigidness (m_ERP and m_limitSoftness attributes) in the getRotationalLimitMotor() method from a btGeneric6DofConstraint object as one of the guys said. It didnt work for me... maybe 'im doing it wrong.

The other guy says that both objects work perfect with the constraint when they are "dynamic". When I create an object in bullet, i dont see any parameter like "dynamic", i guess they mean "btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK" or simply an object with mass.

I'm still fighting with this issue of springy constraints.. so ... i'll keep you posted if i find anything
User avatar
Erwin Coumans
Site Admin
Posts: 4221
Joined: Sun Jun 26, 2005 6:43 pm
Location: California, USA
Contact:

Re: best way to change the length of a rope

Post by Erwin Coumans »

If you are using soft body ropes, you could try to change the rest length of the links.

You should be able to access the rest length using: softbody->m_links.m_rl

Thanks,
Erwin
wittmeis
Posts: 4
Joined: Tue Nov 30, 2010 10:14 am

Re: best way to change the length of a rope

Post by wittmeis »

Hi,

we had the same problem for our tendon-driven robot simuator and implemented set/getSegmentLength methods using the link resting length. Here's the code - it needs some tweaking to get it to work with the default Bullet version as we are using some custom extension classes:

Code: Select all

 void
btMuscle::setSegmentLength(const unsigned int& idxFirstLink,
    const unsigned int& idxLastLink, const btScalar& length)
{
   // if length equals current length -> return
   if (length - getSegmentLength(idxFirstLink, idxLastLink) == 0.0)
   {
       return;
   }

   // maxSegmentsKiteLine: maximum number of rope segments
   // maxSegmentSizeKiteLine: maximum length of one segment
   if (length > maxSegmentsKiteLine * maxSegmentSizeKiteLine)
  { /// too long to accommodate with maxSegmentSize-sized segments
    btScalar segmentSize = length / maxSegmentsKiteLine;
    for (int i = idxFirstLink; i <= idxLastLink; i++)
    {
      softBody->m_nodes[i + 1].m_x
          = lerp(softBody->m_nodes[i].m_x, softBody->m_nodes[i + 1].m_x,
              segmentSize / softBody->m_links[i].m_rl);
      softBody->m_nodes[i + 1].m_q
          = lerp(softBody->m_nodes[i].m_q, softBody->m_nodes[i + 1].m_q,
              segmentSize / softBody->m_links[i].m_rl);
      softBody->m_links[i].m_rl = segmentSize;
    }
    softBody->updateNormals();
    softBody->updateBounds();
    updateConstants();
    softBody->setTotalMass(mass);
    return;
  }
  else
  {
    for (int i = idxFirstLink; i <= idxLastLink; i++)
    {
      if (softBody->m_links[i].m_rl > maxSegmentSizeKiteLine)
      {
        softBody->m_nodes[i + 1].m_x = lerp(softBody->m_nodes[i].m_x,
            softBody->m_nodes[i + 1].m_x, maxSegmentSizeKiteLine
                / softBody->m_links[i].m_rl);
        softBody->m_nodes[i + 1].m_q = lerp(softBody->m_nodes[i].m_q,
            softBody->m_nodes[i + 1].m_q, maxSegmentSizeKiteLine
                / softBody->m_links[i].m_rl);
        softBody->m_links[i].m_rl = maxSegmentSizeKiteLine;
      }
    }
  }

  btScalar deltaLength = length - getSegmentLength(idxFirstLink, idxLastLink);

  btSoftBody::Link &lastLink = softBody->m_links[idxLastLink];

  btSoftBody::Node &beforeLastNode = *(lastLink.m_n[0]);

  btSoftBody::Node &lastNode = *(lastLink.m_n[1]);

  btScalar nodeDistance = lastLink.m_rl;

  btScalar scale = 1 + deltaLength / nodeDistance;

  if (nodeDistance + deltaLength <= maxSegmentSizeKiteLine && nodeDistance
      + deltaLength > 0)
  { /// change link length
    lastNode.m_x = lerp(beforeLastNode.m_x, lastNode.m_x, scale);
    lastNode.m_q = lerp(beforeLastNode.m_q, lastNode.m_q, scale);
    lastLink.m_rl += deltaLength;
  }
  else if (nodeDistance + deltaLength > maxSegmentSizeKiteLine)
  { /// Need to add node
    if (nodeDistance + deltaLength > 2 * maxSegmentSizeKiteLine)
    {
      std::cerr
          << " *** WARNING *** The kite length is growing too fast. This could lead to trouble!"
          << std::endl;
    }
    btVector3 m_x = lerp(beforeLastNode.m_x, lastNode.m_x, scale);
    // Fix the previous last node
    lastNode.m_x = lerp(beforeLastNode.m_x, lastNode.m_x,
        maxSegmentSizeKiteLine / nodeDistance);
    lastNode.m_q = lerp(beforeLastNode.m_q, lastNode.m_q,
        maxSegmentSizeKiteLine / nodeDistance);
    lastLink.m_rl = maxSegmentSizeKiteLine;
    // Add new node
    softBody->appendNode(m_x, 1 / lastNode.m_im);
    softBody->m_springAnchor->setSpringStartNode(softBody->m_nodes.size() - 1);
    softBody->m_springAnchor->setSpringEndNode(softBody->m_nodes.size() - 1);
    softBody->appendLink(softBody->m_nodes.size() - 2, softBody->m_nodes.size()
        - 1);
    softBody->m_links[softBody->m_links.size() - 1].m_rl = nodeDistance
        + deltaLength - maxSegmentSizeKiteLine;
  }
  /// Need to remove a node
  else
  {
    if (idxFirstLink != idxLastLink)
    {
      softBody->m_springAnchor->setSpringEndNode(softBody->m_nodes.size() - 2);
      softBody->m_springAnchor->setSpringStartNode(softBody->m_nodes.size() - 2);

      softBody->m_ndbvt.remove(lastNode.m_leaf);

      for (int i = idxLastLink + 1; i < softBody->m_nodes.size() - 1; i++)
      {
        softBody->m_nodes.swap(i, i + 1);
      }
      softBody->m_nodes.pop_back();
      for (int i = idxLastLink; i < softBody->m_links.size() - 1; i++)
      {
        softBody->m_links.swap(i, i + 1);
      }
      softBody->m_links.pop_back();

      std::cout << "Recursive call" << std::endl;
      setSegmentLength(idxFirstLink, idxLastLink - 1, length);
    }
    else
    {
      std::cerr
          << " *** WARNING *** Attempt to have a zero-length or smaller kite. Request ignored!"
          << std::endl;
    }
  }
  softBody->updateNormals();
  softBody->updateBounds();
  updateConstants();
  softBody->setTotalMass(mass);
}

Code: Select all

btScalar
btMuscle::getSegmentLength(const unsigned int& idxFirstLink,
    const unsigned int& idxLastLink)
{
  btScalar length = 0.0;

  if (idxFirstLink >= 0 && idxFirstLink < softBody->m_links.size()
      && idxLastLink >= 0 && idxLastLink < softBody->m_links.size()
      && idxFirstLink <= idxLastLink)
  {
    for (int i = idxFirstLink; i <= idxLastLink; i++)
    {
      length += softBody->m_links[i].m_rl;
    }
  }
  return length;
}
Post Reply