Box2D Forums

It is currently Sat May 18, 2013 8:05 pm

All times are UTC - 8 hours [ DST ]




Post new topic Reply to topic  [ 4 posts ] 
Author Message
PostPosted: Sun Sep 04, 2011 6:51 pm 
Offline

Joined: Sun Sep 04, 2011 4:33 pm
Posts: 2
There seems to be an issue with the gear joint in 2.2.0 that is not present in 2.1.3.

Having a gear joint set up with two revolute joints and a *negative* gear ratio can result in the simulation breaking when other bodies interact with the 'bodyA' of the gear joint.

Having a *positive* ratio in the gear joint still works as expected in all the cases I've tried.

I'm also reasonably certain the issue only happens when 'bodyA' of the gear joint is interacted with, 'bodyB' seems to work as expected.

Here's a simple testbed example, just done as a replacement for the 'Gears' test. If you watch it for a few seconds the simulation will explode.

Note that the weld joint in this example is included just to make reproducing the issue a lot simpler. You could also remove the weld joint and simply use the mouse joint to 'stroke' the leftmost box with the small box and see the same problem, but there is a definite knack to doing this :0)

Code:

class Gears : public Test
{
public:
   Gears()
   {
      b2Body* ground = NULL;
      {
         b2BodyDef bd;
         ground = m_world->CreateBody(&bd);

         b2EdgeShape shape;
         shape.Set(b2Vec2(50.0f, 0.0f), b2Vec2(-50.0f, 0.0f));
         ground->CreateFixture(&shape, 0.0f);
      }

      {         
         // leftmost large box

         b2PolygonShape box1;
         box1.SetAsBox(5.f, 5.f);

         b2BodyDef bd1;
         bd1.type = b2_dynamicBody;
         bd1.position.Set(-10.0f, 10.0f);
         b2Body* body1 = m_world->CreateBody(&bd1);
         body1->CreateFixture(&box1, 5.0f);

         b2RevoluteJointDef jd1;
         jd1.bodyA = ground;
         jd1.bodyB = body1;
         jd1.localAnchorA = ground->GetLocalPoint(bd1.position);
         jd1.localAnchorB = body1->GetLocalPoint(bd1.position);
         jd1.referenceAngle = body1->GetAngle() - ground->GetAngle();
         m_joint1 = (b2RevoluteJoint*)m_world->CreateJoint(&jd1);


         // rightmost large box

         b2PolygonShape box2;
         box2.SetAsBox(5.f, 5.f);

         b2BodyDef bd2;
         bd2.type = b2_dynamicBody;
         bd2.position.Set(5.0f, 10.0f);
         b2Body* body2 = m_world->CreateBody(&bd2);
         body2->CreateFixture(&box2, 5.0f);

         b2RevoluteJointDef jd2;
         jd2.Initialize(ground, body2, bd2.position);
         m_joint2 = (b2RevoluteJoint*)m_world->CreateJoint(&jd2);




#if 1
         // small box
         // create & weld to the leftmost box to see the bug
         // if the gear ratio is also set to -1 below
         b2PolygonShape box;
         box.SetAsBox(1.f, 1.f);

         b2BodyDef boxd2;
         boxd2.type = b2_dynamicBody;
         boxd2.position.Set(-8.0f, 16.0f);
         b2Body* boxbody = m_world->CreateBody(&boxd2);
         boxbody->CreateFixture(&box, 5.0f);

         b2WeldJointDef jd3;
         jd3.Initialize(boxbody, body1, body1->GetPosition());
         m_joint3 = (b2WeldJoint*)m_world->CreateJoint(&jd3);
#else
         // small box
         // create & weld to the rightmost box to see the
         // expected behaviour regardless of gear ratio
         b2PolygonShape box;
         box.SetAsBox(1.f, 1.f);

         b2BodyDef boxd2;
         boxd2.type = b2_dynamicBody;
         boxd2.position.Set(7.0f, 16.0f);
         b2Body* boxbody = m_world->CreateBody(&boxd2);
         boxbody->CreateFixture(&box, 5.0f);

         b2WeldJointDef jd3;
         jd3.Initialize(boxbody, body2, body2->GetPosition());
         m_joint3 = (b2WeldJoint*)m_world->CreateJoint(&jd3);
#endif



         // gear joint

         b2GearJointDef jd4;
         jd4.bodyA = body1;
         jd4.bodyB = body2;
         jd4.joint1 = m_joint1;
         jd4.joint2 = m_joint2;
#if 1
         // set the ratio to -1 to see the bug if the small box is also
         // welded to the leftmost large box, above
         jd4.ratio = -1;
#else
         // set the ratio to 1 to see the expected behaviour regardless
         // of which box is welded above
         jd4.ratio = 1;
#endif
         m_joint4 = (b2GearJoint*)m_world->CreateJoint(&jd4);
      }
   }

   void Keyboard(unsigned char key)
   {
      switch (key)
      {
      case 0:
         break;
      }
   }

   void Step(Settings* settings)
   {
      Test::Step(settings);
   }

   static Test* Create()
   {
      return new Gears;
   }

   b2RevoluteJoint* m_joint1;
   b2RevoluteJoint* m_joint2;
   b2WeldJoint* m_joint3;
   b2GearJoint* m_joint4;
};



Top
 Profile  
 
PostPosted: Mon Sep 05, 2011 12:18 am 
Offline
Site Admin

Joined: Thu Sep 06, 2007 12:34 am
Posts: 2931
Thanks, I filed an issue: http://code.google.com/p/box2d/issues/detail?id=242


Top
 Profile  
 
PostPosted: Wed Sep 07, 2011 8:26 pm 
Offline
Site Admin

Joined: Thu Sep 06, 2007 12:34 am
Posts: 2931
Revision: 222
Date: 8:25:40 PM, Wednesday, September 07, 2011
Message:
Fixed issue 242. Negative gear ratio instability.
----
Modified : /trunk/Box2D/Box2D/Dynamics/Joints/b2GearJoint.cpp


Top
 Profile  
 
PostPosted: Thu Sep 08, 2011 1:45 pm 
Offline

Joined: Sun Sep 04, 2011 4:33 pm
Posts: 2
Nice one, thanks a lot for fixing this so quickly Erin


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 4 posts ] 

All times are UTC - 8 hours [ DST ]


Who is online

Users browsing this forum: Google [Bot] and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group