Box2D Forums

It is currently Sat May 25, 2013 8:56 pm

All times are UTC - 8 hours [ DST ]




Post new topic Reply to topic  [ 5 posts ] 
Author Message
 Post subject: Wheel/Line joint?
PostPosted: Wed Apr 04, 2012 11:29 am 
Offline

Joined: Tue Apr 03, 2012 5:30 am
Posts: 8
Does anyone have a working example of the line/wheel joint? The following should, according to every bit of documentation/code I can find on the subject, create a unicycle-like structure with a motor driving the wheel. The motor does not work, however (it does nothing, regardless of whether it's enabled and regardless of what speed the motor is set to):

Code:
  private final Vec2  gravity = new Vec2(0.0f, -10.0f);
  private final World world;
  private Fixture     wheel_fixture;
  private Fixture     floor_fixture;
  private Fixture     roof_fixture;
  private Fixture     left_fixture;
  private Fixture     right_fixture;
  private Fixture     box_fixture;
  private LineJoint   joint;

  public Wheel()
  {
    this.world = new World(this.gravity, true);

    /*
     * Ground.
     */

    {
      final BodyDef bd = new BodyDef();
      bd.position.x = 20.0f;
      bd.position.y = 2.0f;
      bd.type = BodyType.STATIC;
      final Body b = this.world.createBody(bd);
      final PolygonShape s = new PolygonShape();

      s.setAsBox(20f, 0.5f, new Vec2(0.0f, 0.0f), 0.0f);
      final FixtureDef floor = new FixtureDef();
      floor.density = 1.0f;
      floor.friction = 0.5f;
      floor.shape = s;
      this.floor_fixture = b.createFixture(floor);

      s.setAsBox(20f, 0.5f, new Vec2(0.0f, 17.0f), 0.0f);
      final FixtureDef roof = new FixtureDef();
      roof.density = 1.0f;
      roof.friction = 0.5f;
      roof.shape = s;
      this.roof_fixture = b.createFixture(roof);

      s.setAsBox(0.5f, 20.0f, new Vec2(-18.0f, 0.0f), 0.0f);
      final FixtureDef left = new FixtureDef();
      left.density = 1.0f;
      left.friction = 0.5f;
      left.shape = s;
      this.left_fixture = b.createFixture(left);

      s.setAsBox(0.5f, 20.0f, new Vec2(18.0f, 0.0f), 0.0f);
      final FixtureDef right = new FixtureDef();
      right.density = 1.0f;
      right.friction = 0.5f;
      right.shape = s;
      this.right_fixture = b.createFixture(right);
    }

    /*
     * Wheel.
     */

    {
      final CircleShape wheel_shape = new CircleShape();
      wheel_shape.m_radius = 2.0f;

      final FixtureDef wheel_fixture_def = new FixtureDef();
      wheel_fixture_def.density = 1.0f;
      wheel_fixture_def.friction = 0.5f;
      wheel_fixture_def.shape = wheel_shape;

      final BodyDef wheel_body = new BodyDef();
      wheel_body.position.x = 20.0f;
      wheel_body.position.y = 10.0f;
      wheel_body.type = BodyType.DYNAMIC;

      final Body b = this.world.createBody(wheel_body);
      this.wheel_fixture = b.createFixture(wheel_fixture_def);
    }

    /*
     * Box above wheel.
     */

    {
      final PolygonShape box_shape = new PolygonShape();
      box_shape.setAsBox(1f, 1f, new Vec2(0.0f, 0.0f), 0.0f);

      final BodyDef box_body = new BodyDef();
      box_body.position.x = 20.0f;
      box_body.position.y = 15.0f;
      box_body.type = BodyType.DYNAMIC;
      box_body.fixedRotation = true;

      final FixtureDef box_fixture_def = new FixtureDef();
      box_fixture_def.density = 1.0f;
      box_fixture_def.friction = 0.5f;
      box_fixture_def.shape = box_shape;

      final Body b = this.world.createBody(box_body);
      this.box_fixture = b.createFixture(box_fixture_def);
    }

    /*
     * Joint.
     */

    {
      final LineJointDef jd = new LineJointDef();
      jd.initialize(
        this.box_fixture.getBody(),
        this.wheel_fixture.getBody(),
        this.wheel_fixture.getBody().getWorldCenter(),
        new Vec2(0.0f, 1.0f));
      jd.enableLimit = true;
      jd.enableMotor = true;
      jd.maxMotorForce = 1000.0f;
      jd.motorSpeed = 1.0f;

      this.joint = (LineJoint) this.world.createJoint(jd);
    }
  }


Is this joint broken in jbox2d?


Top
 Profile  
 
 Post subject: Re: Wheel/Line joint?
PostPosted: Wed Apr 04, 2012 9:11 pm 
Offline

Joined: Tue Jun 24, 2008 8:25 pm
Posts: 1518
Location: Tokyo
As always I can't speak for the java port, but I know the C++ version has a max motor torque setting which you seem to be missing.


Top
 Profile  
 
 Post subject: Re: Wheel/Line joint?
PostPosted: Thu Apr 05, 2012 2:14 am 
Offline

Joined: Tue Apr 03, 2012 5:30 am
Posts: 8
"Max torque" doesn't seem to exist in the java version, only "max force".

I've stepped through the code in the debugger and it seems as though something's off when it comes to calculating the impulse to apply for the motor: In LineJoint.java:solveVelocityConstraints, it calculates an impulse to apply as a vector. The x component calculated is always zero and the y component is a negative value (of about -66). This seems wrong!


Top
 Profile  
 
 Post subject: Re: Wheel/Line joint?
PostPosted: Thu Apr 05, 2012 3:40 am 
Offline

Joined: Tue Apr 03, 2012 5:30 am
Posts: 8
Yes, it seems the java version is broken. I've rewritten the above program using the C++ version and it works as expected:

Code:
#define GL_GLEXT_PROTOTYPES 1

#include <assert.h>
#include <stdio.h>

#include <GL/glut.h>
#include <GL/gl.h>
#include <GL/glext.h>
#include <err.h>

#include <Box2D/Box2D.h>

static b2World *world;
static b2Vec2 gravity;
static b2Fixture *floor_fixture;
static b2Fixture *roof_fixture;
static b2Fixture *left_fixture;
static b2Fixture *right_fixture;
static b2Fixture *wheel_fixture;
static b2Fixture *box_fixture;
static b2WheelJoint *joint;

static void
init (void)
{
  gravity.x = 0.0f;
  gravity.y = -10.0f;
  world = new b2World(gravity);

  /*
   * Ground
   */

  {
    b2BodyDef bd;
    b2PolygonShape s;
    b2Vec2 v;

    bd.position.x = 20.0f;
    bd.position.y = 2.0f;
    bd.type = b2_staticBody;

    b2Body *b = world->CreateBody(&bd);

    v.x = 0.0f;
    v.y = 0.0f;
    s.SetAsBox(20.0f, 0.5f, v, 0.0f);
   
    b2FixtureDef floor;
    floor.density = 1.0f;
    floor.friction = 0.5f;
    floor.shape = &s;
    floor_fixture = b->CreateFixture(&floor);

    v.x = 0.0f;
    v.y = 17.0f;
    s.SetAsBox(20.0f, 0.5f, v, 0.0f);
 
    b2FixtureDef roof;
    roof.density = 1.0f;
    roof.friction = 0.5f;
    roof.shape = &s;
    roof_fixture = b->CreateFixture(&roof);

    v.x = -18.0f;
    v.y = 0.0f;
    s.SetAsBox(0.5f, 20.0f, v, 0.0f);
 
    b2FixtureDef left;
    left.density = 1.0f;
    left.friction = 0.5f;
    left.shape = &s;
    left_fixture = b->CreateFixture(&left);

    v.x = 18.0f;
    v.y = 0.0f;
    s.SetAsBox(0.5f, 20.0f, v, 0.0f);
 
    b2FixtureDef right;
    right.density = 1.0f;
    right.friction = 0.5f;
    right.shape = &s;
    right_fixture = b->CreateFixture(&right);
  }

  /*
   * Wheel
   */

  {
    b2CircleShape wheel_shape;
    wheel_shape.m_radius = 2.0f;

    b2FixtureDef wheel_fixture_def;
    wheel_fixture_def.density = 1.0f;
    wheel_fixture_def.friction = 0.5f;
    wheel_fixture_def.shape = &wheel_shape;

    b2BodyDef wheel_body;
    wheel_body.position.x = 20.0f;
    wheel_body.position.y = 10.0f;
    wheel_body.type = b2_dynamicBody;

    b2Body *b = world->CreateBody(&wheel_body);
    wheel_fixture = b->CreateFixture(&wheel_fixture_def);
  }

  /*
   * Box above wheel.
   */

  {
    b2PolygonShape box_shape;
    b2Vec2 v;

    v.x = 0.0f;
    v.y = 0.0f;
    box_shape.SetAsBox(1.0f, 1.0f, v, 0.0f);

    b2BodyDef box_body;
    box_body.position.x = 20.0f;
    box_body.position.y = 15.0f;
    box_body.type = b2_dynamicBody;
    box_body.fixedRotation = true;

    b2FixtureDef box_fixture_def;
    box_fixture_def.density = 1.0f;
    box_fixture_def.friction = 0.5f;
    box_fixture_def.shape = &box_shape;

    b2Body *b = world->CreateBody(&box_body);
    box_fixture = b->CreateFixture(&box_fixture_def);
  }

  /*
   * Joint.
   */

  {
    b2Vec2 v;
    b2WheelJointDef jd;

    v.x = 0.0f;
    v.y = 1.0f;

    jd.Initialize(
      box_fixture->GetBody(),
      wheel_fixture->GetBody(),
      wheel_fixture->GetBody()->GetWorldCenter(),
      v);

    jd.motorSpeed = 100.0f;
    jd.maxMotorTorque = 1000.0f;
    jd.enableMotor = true;

    joint = (b2WheelJoint *) world->CreateJoint(&jd);
  }
}

static void drawCircle(float radius)
{
  glBegin(GL_LINES);
  {
    for (int index = 0; index < 180; ++index) {
      double x0 = radius * cos(index);
      double y0 = radius * sin(index);
      glVertex3d(x0, y0, 0.0f);
      double x1 = radius * cos(index + 0.1);
      double y1 = radius * sin(index + 0.1);
      glVertex3d(x1, y1, 0.0f);
    }
  }
  glEnd();
}

static void drawFixture(b2Fixture *fix)
{
  b2Body *b = fix->GetBody();
  b2Shape *s = fix->GetShape();

  glPushMatrix();
  {
    b2Vec2 p = b->GetWorldCenter();
    glColor3d(1.0f, 0.0f, 0.0f);
    glTranslated(p.x, p.y, 0.0);
    drawCircle(0.125f);
  }
  glPopMatrix();

  glPushMatrix();
  {
    glColor3d(0.0f, 1.0f, 0.0f);

    b2Shape::Type type = s->GetType();

    switch (s->GetType()) {
      case b2Shape::e_circle:
      {
        b2CircleShape *c = (b2CircleShape *) s;
        b2Vec2 p = b->GetWorldPoint(c->m_p);
 
        glTranslated(p.x, p.y, 0.0);
        glRotated(b->GetAngle() * (180 / 3.14), 0, 0, 1);
 
        drawCircle(c->m_radius);
        glBegin(GL_LINES);
        {
          glVertex3d(0.0, 0.0, 0.0);
          glVertex3d(0.0, 1.0, 0.0);
        }
        glEnd();
      }
      case b2Shape::e_polygon:
      {
        b2PolygonShape *ps = (b2PolygonShape *) s;
 
        glBegin(GL_LINE_LOOP);
        {
          b2Vec2 *vs = ps->m_vertices;
          for (int index = 0; index < ps->GetVertexCount(); ++index) {
            b2Vec2 v = b->GetWorldPoint(vs[index]);
            glVertex3d(v.x, v.y, 0.0);
          }
        }
        glEnd();
      }
    }
  }
  glPopMatrix();
}

static void
display (void)
{
  world->Step(1.0 / 60.0, 8, 4);

  glClearColor(0.2, 0.2, 0.2, 1.0);
  glClear(GL_COLOR_BUFFER_BIT);

  glMatrixMode(GL_PROJECTION);
  glLoadIdentity();
  glOrtho(0, 40, 0, 20, 0, 100);

  glMatrixMode(GL_MODELVIEW);
  glLoadIdentity();

  drawFixture(floor_fixture);
  drawFixture(roof_fixture);
  drawFixture(left_fixture);
  drawFixture(right_fixture);
  drawFixture(wheel_fixture);
  drawFixture(box_fixture);
  drawJoint(joint);

  glutSwapBuffers();
  glutPostRedisplay();
}

int
main (int argc, char *argv[])
{
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
  glutInitWindowSize(640, 480);
  glutCreateWindow("B2D");
  glutDisplayFunc(display);
  init();
  glutMainLoop();

  return 0;
}


I'll file a bug.


Top
 Profile  
 
 Post subject: Re: Wheel/Line joint?
PostPosted: Tue Apr 10, 2012 10:37 am 
Offline

Joined: Mon Jun 08, 2009 12:21 pm
Posts: 353
Which build of jbox2d are you using?


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

All times are UTC - 8 hours [ DST ]


Who is online

Users browsing this forum: No registered users and 3 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