winding rope on a windlass

Post Reply
VanDelayyyy
Posts: 16
Joined: Thu Jun 26, 2008 6:48 pm

winding rope on a windlass

Post by VanDelayyyy »

hi all..

I'm implementing a windlass using the softdemo rope sample as my model. I would appreciate some feedback on my approach if anyone out there can help.

I create a cylinder (aka windlass) and a box (aka ground) then create a rope between them as follows (using my custom XML schema!):

O <cylinder>
|
+y |
^ |
| |
| |
| |
| |
+z <------+x |
-------------------- <ground>

I then create an anchor tying the .. my understanding from the code is that this will create a constraint which tries to keep the rope segment at its current position in the space of the object it is attached to. The cylinder anchor lies on the surface of the cylinder.

If i then apply a torque to the cylinder at each simulation step which is sufficient to move the block, then i expect that the cylinder will rotate and the rope anchor will cause the rope to start winding around the cylinder. I notice that there is an applyTorque() member on btRigidBody which takes a btVector3. I assume the vector is in body space. If so, the cylinder axis is parallel to the x-axis and, if the right-hand-rule holds, applying a torque of (100, 0, 0) will result in counter-clockwise rotation of the cylinder (assuming the torque is sufficient to lift the rope.. i assume it's in Newtons) looking at it down the positive x-axis. Since each step rotates the cylinder, i assume that the body position shifts also such that this torque continues to rotate the body counterclockwise. This ideally causes the rope anchor to rotate as well, winding the rope around the cylinder. If i anchor a block to the other end of the rope then i would expect it to be pulled if the torque is sufficient.

I've tried coding this by adding a new function to softdemo.cpp:

static void
Init_Windlass(SoftDemo* pdemo)
{
pdemo->m_softBodyWorldInfo.m_sparsesdf.RemoveReferences(0);
struct Functors
{
static btSoftBody*
CtorRope(
SoftDemo* pdemo,
const btVector3& from,
const btVector3& to,
int linkCount)
{
btSoftBody* pRope = btSoftBodyHelpers::CreateRope(
pdemo->m_softBodyWorldInfo,
from,
to,
linkCount,
1);
pRope->setTotalMass(50);
pdemo->getSoftDynamicsWorld()->addSoftBody(pRope);
return(pRope);
}
};

btTransform tr;

// ground
const float groundHalfExtent = 0.5f;
btCollisionShape* groundShape = new btBoxShape(btVector3(200,groundHalfExtent,200));
pdemo->m_collisionShapes.push_back(groundShape);
tr.setIdentity();
tr.setOrigin(btVector3(0,-2*groundHalfExtent,0));
btRigidBody* ground = pdemo->localCreateRigidBody(0.f,tr,groundShape);

// windlass
float windlassHeight = 20.0f;
float windlassHalfExtent = 5.0f;
float windlassRadius = 4.0f;

tr.setIdentity();
tr.setOrigin(btVector3(0,windlassHeight,0));
windlass = pdemo->localCreateRigidBody(
1.0,
tr,
new btCylinderShapeX(btVector3(
windlassHalfExtent,
windlassRadius,
windlassHalfExtent)));

// create rope from ground to windlass
btSoftBody* windlassRope = Functors::CtorRope(
pdemo,
btVector3(0,0,0),
btVector3(0,windlassHeight-windlassHalfExtent,0),
10);

// constrain rope to bottom of windlass
windlassRope->appendAnchor(windlassRope->m_nodes.size()-1,windlass);

// windlass axle
btTransform windlassPivot;
windlassPivot.setIdentity();
windlassPivot.getBasis().setEulerZYX(0,M_PI_2,0);
windlassPivot.setOrigin(btVector3(btScalar(0.), btScalar(0.), btScalar(0.)));

btTransform groundPivot;
groundPivot.setIdentity();
groundPivot.getBasis().setEulerZYX(0,M_PI_2,0); // rotate about y 90deg.
groundPivot.setOrigin(btVector3(btScalar(0.), btScalar(windlassHeight), btScalar(0.)));

btHingeConstraint* windlassGroundHinge = new btHingeConstraint(*windlass, *ground, windlassPivot, groundPivot);
pdemo->getDynamicsWorld()->addConstraint(windlassGroundHinge, true);
}

and adding the following to SoftDemo::clientMoveAndDisplay() before the call to stepSimulation():

windlass->applyTorque(btVector3(100,0,0));

but the rope only seems to oscillate gently in the digital breeze. Can anyone out there provide a hint as to where i'm going wrong?

thanks in advance!
VanDelayyyy



I'm sorry the answer we were looking for was "Moops".
--------- G. Costanza ---------->
Nathanael
Posts: 78
Joined: Mon Nov 13, 2006 1:44 am

Re: winding rope on a windlass

Post by Nathanael »

The rope you created is 50Kg and the cylinder 10Kg, not a fair match under gravity! :wink:
In addition, the last parameter of ::CreateRope is 'fixed', its used to attached node to the world (bit mask, 1:first node , 2:last node).

try:

Code: Select all

btSoftBody*	pRope = btSoftBodyHelpers::CreateRope(
				pdemo->m_softBodyWorldInfo,
				from,
				to,
				linkCount,
				0/* no world attachment*/);
			pRope->setTotalMass(0.01); // Light rope
			pRope->m_cfg.piterations=2; // Look better
Hope it help,
Nathanael.

btw: you can drag bodies by clicking on them, no need for addTorque to test.
VanDelayyyy
Posts: 16
Joined: Thu Jun 26, 2008 6:48 pm

Re: winding rope on a windlass

Post by VanDelayyyy »

Thanks Nathanael - it's working now.
VanDelayyyy
Posts: 16
Joined: Thu Jun 26, 2008 6:48 pm

Re: winding rope on a windlass

Post by VanDelayyyy »

well.. it was working until i tried to wind a heavier object around the cylinder :>(. The rope happily wound for a bit then sliced right through the cylinder. I suspect that the collision detection is allowing the rope to penetrate too deeply until it reaches a point of no return and drops through to the other side. The greater the block mass (it can be seen in a range from 1 to 1000 in a simple demo - i can supply code if it will help), the quicker the rope slices. In this case, the block is quite heavy so cheating by making it really light looks fake.. though a styrofoam pyramid would bring out the Spinal Tap crowd :idea: .

I suspect this is a FAQ, perhaps related to the "Handling Collisions Manually" thread. I notice that the btDynamicsWorld class has a number of collision-related methods so perhaps this is where i should look. Maybe a continuous collision detection algorithm? If anyone knows of a good, clean, Bullet-style approach to keep the rope segments from penetrating the cylinder regardless of the block weight (i'm going to trust that the block doesn't actually get heavy enough to slice the cylinder) it would be appreciated!

thanks in advance!
VanDelayyyy

------------

Ian Faith: Nigel gave me a drawing that said 18 inches. Now, whether or not he knows the difference between feet and inches is not my problem. I do what I'm told.
David St. Hubbins: But you're not as confused as him are you. I mean, it's not your job to be as confused as Nigel.

-- Spinal Tap
Nathanael
Posts: 78
Joined: Mon Nov 13, 2006 1:44 am

Re: winding rope on a windlass

Post by Nathanael »

Try increasing rope mass, masses ratio are really the weak point of the type of solver used for soft/rigid interaction.
Also, increase ...m_cfg.piterations , try 16.

I'm interested to try it myself, can you post the code?

Nat.
VanDelayyyy
Posts: 16
Joined: Thu Jun 26, 2008 6:48 pm

Re: winding rope on a windlass

Post by VanDelayyyy »

Here is code snippet.. increasing the rope mass did reduce the slicing. I checked it out in a more complex simulation and modifying the relative masses and bumping the iterations appears to resolve the problem - thanks Once Again!


const float ccMass = 10000.0f;
const float ropeMass = 1000.0f; // seems if this is made too light (i.e. 100.0) slicing increases
const float windlassMass = 1000.0f;
const int simIterations = 16;

static void Init_Windlass(SoftDemo* pdemo)
{
const float windlassHeight = 40.0f;
const float ccHeight = 2.0f;

btRigidBody* windlass = NULL;
btRigidBody* cc = NULL;

pdemo->m_softBodyWorldInfo.m_sparsesdf.RemoveReferences(0);
struct Functors
{
static btSoftBody*
CtorRope(
SoftDemo* pdemo,
const btVector3& from,
const btVector3& to,
int linkCount)
{
// do not fix either end of rope and incorporate Nathanael's changes
btSoftBody* pRope = btSoftBodyHelpers::CreateRope(
pdemo->m_softBodyWorldInfo,
from,
to,
linkCount,
0); // both ends of rope can move
pRope->setTotalMass(ropeMass); // light to thwart gravity
pRope->m_cfg.piterations = simIterations; // smooth rope movement
pdemo->getSoftDynamicsWorld()->addSoftBody(pRope);
return(pRope);
}
};

// ground
const float groundHalfExtent = 0.5f;
btCollisionShape* groundShape = new btBoxShape(btVector3(200,groundHalfExtent,200));
pdemo->m_collisionShapes.push_back(groundShape);

btTransform tr;
tr.setIdentity();
tr.setOrigin(btVector3(0,-2*groundHalfExtent,0));
btRigidBody* ground = pdemo->localCreateRigidBody(0.f,tr,groundShape);

// attach the rope to a small, light, movable cube
const float ccHalfExtent = 1.0f;
btCollisionShape* ccShape = new btBoxShape(btVector3(ccHalfExtent,ccHalfExtent,ccHalfExtent));
pdemo->m_collisionShapes.push_back(ccShape);
tr.setIdentity();
tr.setOrigin(btVector3(0,ccHeight,0));
cc = pdemo->localCreateRigidBody(ccMass,tr,ccShape);


// windlass
float windlassHalfExtent = 15.0f;
float windlassRadius = 5.0f;

tr.setIdentity();
tr.setOrigin(btVector3(0,windlassHeight,0));
windlass = pdemo->localCreateRigidBody(
windlassMass,
tr,
new btCylinderShapeX(btVector3(
windlassHalfExtent,
windlassRadius,
windlassHalfExtent)));

// create rope from cube to windlass
btSoftBody* windlassRope = Functors::CtorRope(
pdemo,
btVector3(0,ccHeight+ccHalfExtent,0),
btVector3(0,windlassHeight-windlassRadius,0),
10);

// constrain rope to bottom of windlass
windlassRope->appendAnchor(windlassRope->m_nodes.size()-1,windlass);

// constrain rope to cube
windlassRope->appendAnchor(0,cc);

// windlass axle
btTransform windlassPivot;
windlassPivot.setIdentity();
windlassPivot.getBasis().setEulerZYX(0,M_PI_2,0);
windlassPivot.setOrigin(btVector3(btScalar(0.), btScalar(0.), btScalar(0.)));

btTransform groundPivot;
groundPivot.setIdentity();
groundPivot.getBasis().setEulerZYX(0,M_PI_2,0); // rotate about y 90deg.
groundPivot.setOrigin(btVector3(btScalar(0.), btScalar(windlassHeight), btScalar(0.)));

btHingeConstraint* windlassGroundHinge = new btHingeConstraint(*windlass, *ground, windlassPivot, groundPivot);
pdemo->getDynamicsWorld()->addConstraint(windlassGroundHinge, true);
}
VanDelayyyy
Posts: 16
Joined: Thu Jun 26, 2008 6:48 pm

Re: winding rope on a windlass

Post by VanDelayyyy »

For those that are interested i've posted the (rather barebones) implementation at http://www.vandelayyyy.org . It's by no means complete, but i had to set a line-in-the-sand to get something out. Thanks again to Nathanael for his help.. but you can blame me for the shortcomings :>). If anyone has suggestions about how it could be improved please let me know.. and yes, i know the cannon has certain advantages..


-----------
I'd rather be a failure at something I love than a success at something I hate.
G. Burns
cobolt_dink
Posts: 72
Joined: Fri Apr 04, 2008 6:07 pm

Re: winding rope on a windlass

Post by cobolt_dink »

How does it work? I seem to just end up pulling the rope off the counter weight.
VanDelayyyy
Posts: 16
Joined: Thu Jun 26, 2008 6:48 pm

Re: winding rope on a windlass

Post by VanDelayyyy »

It's actually just a sandbox to find a set of workable parameters for load/launch of a barebones trebuchet. The default parameters (if you desist from fingerpoken mit de mousen) should show this if you start the executable and just let it run - if not, please let me know. The parameters are just there to play with if you want. I provide it for those that are interested in ropes/windlasses..



------
Marry me and I'll never look at another horse!
Groucho Marx
cobolt_dink
Posts: 72
Joined: Fri Apr 04, 2008 6:07 pm

Re: winding rope on a windlass

Post by cobolt_dink »

Ah I see it works when you leave it alone.

Any chance of releasing the source? In the future I think I will need to set something up like attaching a rope to a rigid body and letting the rope control where the rigid body can go.
Post Reply