Code

Project: jvfeatures

jvtypes.h      jvfeatures.h      chessSeg.cpp      jvtypes.cpp      jvtest.cpp      jvfeatures.cpp     

Project: Other

migrateMailbox.scpt.txt     

Project: Infinite HMM Tutorial

run.m      iHMM_tutorial.zip      HDP_HMM.m      README.txt      ConditionalProbabilityTable.m      HDP.m      HMMProblem.m      HMM.m     

Project: RRT

RRT.h      plot_output.py      RRT.tgz      rrt_test.cpp      RRT.cpp      BidirectionalRRT.cpp      AbstractRRT.cpp     

Project: Box2D_friction_mod

WheelConstraint.h      test_TopDownCar.py      b2FrictionJoint.h      python_friction_joint.patch      test_TopDownFrictionJoint.py      TestEntries.cpp      TopDownCar.h      b2FrictionJoint.cpp      box2d_friction_joint.patch     

Project: Dirichlet Process Mixture Tutorial

EM_GM.m      DP_Demo.m      DPMM.m      DP_Tutorial.zip      DirichletProcess.m      gaussian_EM.m     

Project: Arduino_Code

plot_ardunio_data.sh      Arduino_Code.zip      convert_range2D.py      arduino-serial.c      oscilloscope.sh      oscilloscope.pde      motordriver.pde      helicopter_controller.pde      accelerometer_test.pde      ranger_plane_sweep.pde      clodbuster_controller.pde      pwm_manual.pde      ranger_test.pde      servo_test.pde     

Project: ArduCom

arducom.py      setup.py     

Project: support

geshi.php      Protector.php     

Project: Cogent

CodePane.php      NotesPane.php      PicsPane.php      Cogent.php      PubsTable.php     
Click here to download "resources/code/Box2D_friction_mod/box2d_friction_joint.patch"

resources/code/Box2D_friction_mod/box2d_friction_joint.patch

diff -rupN Box2D_v2.2.1/Box2D/Dynamics/Joints/b2FrictionJoint.cpp Box2D_v2.2.1_fjmod/Box2D/Dynamics/Joints/b2FrictionJoint.cpp
--- Box2D_v2.2.1/Box2D/Dynamics/Joints/b2FrictionJoint.cpp      2011-09-04 15:18:34.000000000 -0400
+++ Box2D_v2.2.1_fjmod/Box2D/Dynamics/Joints/b2FrictionJoint.cpp        2012-11-13 21:13:29.000000000 -0500
@@ -51,6 +51,13 @@ b2FrictionJoint::b2FrictionJoint(const b
 
        m_maxForce = def->maxForce;
        m_maxTorque = def->maxTorque;
+
+       m_muX = def->muX;
+       m_muY = def->muY;
+       m_muT = def->muT;
+       m_muXY.Set(
+                       b2Vec2(m_muX, 0),
+                       b2Vec2(0, m_muY));
 }
 
 void b2FrictionJoint::InitVelocityConstraints(const b2SolverData& data)
@@ -72,11 +79,13 @@ void b2FrictionJoint::InitVelocityConstr
        b2Vec2 vB = data.velocities[m_indexB].v;
        float32 wB = data.velocities[m_indexB].w;
 
-       b2Rot qA(aA), qB(aB);
+       // set rotation matrices corresponding to body angles
+       m_qA.Set(aA);
+       m_qB.Set(aB);
 
        // Compute the effective mass matrix.
-       m_rA = b2Mul(qA, m_localAnchorA - m_localCenterA);
-       m_rB = b2Mul(qB, m_localAnchorB - m_localCenterB);
+       m_rA = b2Mul(m_qA, m_localAnchorA - m_localCenterA);
+       m_rB = b2Mul(m_qB, m_localAnchorB - m_localCenterB);
 
        // J = [-I -r1_skew I r2_skew]
        //     [ 0       -1 0       1]
@@ -104,7 +113,8 @@ void b2FrictionJoint::InitVelocityConstr
                m_angularMass = 1.0f / m_angularMass;
        }
 
-       if (data.step.warmStarting)
+       // warm starting causes instabilities for 2D friction
+       if (false) // (data.step.warmStarting)
        {
                // Scale impulses to support a variable time step.
                m_linearImpulse *= data.step.dtRatio;
@@ -143,7 +153,7 @@ void b2FrictionJoint::SolveVelocityConst
        // Solve angular friction
        {
                float32 Cdot = wB - wA;
-               float32 impulse = -m_angularMass * Cdot;
+               float32 impulse = -m_angularMass * m_muT * Cdot; // scaled angular impulse
 
                float32 oldImpulse = m_angularImpulse;
                float32 maxImpulse = h * m_maxTorque;
@@ -158,7 +168,12 @@ void b2FrictionJoint::SolveVelocityConst
        {
                b2Vec2 Cdot = vB + b2Cross(wB, m_rB) - vA - b2Cross(wA, m_rA);
 
-               b2Vec2 impulse = -b2Mul(m_linearMass, Cdot);
+               // Compute orthogonal friction impulses in bodyB frame, and rotate back
+               b2Vec2 vb = b2MulT(m_qB, Cdot);         // velocity in constraint frame
+               b2Vec2 fb = b2Mul(m_muXY, vb);          // friction forces in constraint frame
+               b2Vec2 fw = b2Mul(m_qB, fb);            // friction forces in world frame
+               b2Vec2 impulse = -b2Mul(m_linearMass, fw);
+
                b2Vec2 oldImpulse = m_linearImpulse;
                m_linearImpulse += impulse;
 
@@ -234,6 +249,38 @@ float32 b2FrictionJoint::GetMaxTorque()
        return m_maxTorque;
 }
 
+float32 b2FrictionJoint::GetMuX() const
+{
+       return m_muX;
+}
+
+void b2FrictionJoint::SetMuX(float32 muX)
+{
+       m_muX = muX;
+       m_muXY.ex.x = m_muX;
+}
+
+float32 b2FrictionJoint::GetMuY() const
+{
+       return m_muY;
+}
+
+void b2FrictionJoint::SetMuY(float32 muY)
+{
+       m_muY = muY;
+       m_muXY.ey.y = m_muY;
+}
+
+float32 b2FrictionJoint::GetMuT() const
+{
+       return m_muT;
+}
+
+void b2FrictionJoint::SetMuT(float32 muT)
+{
+       m_muT = muT;
+}
+
 void b2FrictionJoint::Dump()
 {
        int32 indexA = m_bodyA->m_islandIndex;
diff -rupN Box2D_v2.2.1/Box2D/Dynamics/Joints/b2FrictionJoint.h Box2D_v2.2.1_fjmod/Box2D/Dynamics/Joints/b2FrictionJoint.h
--- Box2D_v2.2.1/Box2D/Dynamics/Joints/b2FrictionJoint.h        2011-09-04 15:11:18.000000000 -0400
+++ Box2D_v2.2.1_fjmod/Box2D/Dynamics/Joints/b2FrictionJoint.h  2012-11-13 21:13:29.000000000 -0500
@@ -21,6 +21,36 @@
 
 #include <Box2D/Dynamics/Joints/b2Joint.h>
 
+
+/**
+ * Explanation of 2D friction mod:
+ * The purpose of this joint is to simulate friction in the absence of
+ * contact events.  The standard use-case is top-down worlds, where we
+ * want to model objects such as blocks or wheels interacting with the
+ * (hypothetical) surface.  Gravity is set to zero in these scenarios
+ * and there is no normal force, which leaves joints as the mechanism
+ * for processing these forces inside the solver.  The underlying
+ * friction model is viscous, since impules are proportional to velocity
+ * (as with linear/angular damping).  To simulate coloumb friction, we'd
+ * have to normalize the velocity vector "Cdot" in SolveVelocityConstraints
+ * (not implemented).
+ *
+ * In order to make sense, this must assume that the linear friction
+ * components are attached to one of the bodies.  When simulating
+ * top-down car wheels, bodyA is the ground body and bodyB is a wheel.
+ * The order of these is important, since the coordinate frame for
+ * linear friction is attached to bodyB.
+ *
+ * Changes from Erin's version:
+ * > added member variables for body orientations, since needed in solver
+ * > added three friction coefficients for X, Y, and Theta, (w/ getter/setters)
+ * > scaled angular impules update by muT
+ * > rotated and scaled linear impulse by muX,muY
+ *
+ * jkscholz@gatech.edu
+ * 11/6/2012
+ */
+
 /// Friction joint definition.
 struct b2FrictionJointDef : public b2JointDef
 {
@@ -31,6 +61,9 @@ struct b2FrictionJointDef : public b2Joi
                localAnchorB.SetZero();
                maxForce = 0.0f;
                maxTorque = 0.0f;
+               muX = 0;
+               muY = 0;
+               muT = 0;
        }
 
        /// Initialize the bodies, anchors, axis, and reference angle using the world
@@ -48,6 +81,11 @@ struct b2FrictionJointDef : public b2Joi
 
        /// The maximum friction torque in N-m.
        float32 maxTorque;
+      
+       /// The orthogonal and angular friction components
+       float32 muX;
+       float32 muY;
+       float32 muT;
 };
 
 /// Friction joint. This is used for top-down friction.
@@ -79,6 +117,24 @@ public:
        /// Get the maximum friction torque in N*m.
        float32 GetMaxTorque() const;
 
+       /// Get the X friction component
+       float32 GetMuX() const;
+
+       /// Set the X friction component
+       void SetMuX(float32 muX);
+
+       /// Get the Y friction component
+       float32 GetMuY() const;
+
+       /// Set the Y friction component
+       void SetMuY(float32 muY);
+
+       /// Get the T friction component
+       float32 GetMuT() const;
+
+       /// Set the T friction component
+       void SetMuT(float32 muT);
+
        /// Dump joint to dmLog
        void Dump();
 
@@ -114,6 +170,13 @@ protected:
        float32 m_invIB;
        b2Mat22 m_linearMass;
        float32 m_angularMass;
+       b2Rot m_qA, m_qB;
+
+       /// Orthogonal friction components
+       float32 m_muX;
+       float32 m_muY;
+       float32 m_muT;
+       b2Mat22 m_muXY; // matrix representation of the linear friction components
 };
 
 #endif
diff -rupN Box2D_v2.2.1/Testbed/Tests/TestEntries.cpp Box2D_v2.2.1_fjmod/Testbed/Tests/TestEntries.cpp
--- Box2D_v2.2.1/Testbed/Tests/TestEntries.cpp  2011-09-11 23:55:26.000000000 -0400
+++ Box2D_v2.2.1_fjmod/Testbed/Tests/TestEntries.cpp    2012-11-13 21:13:29.000000000 -0500
@@ -1,28 +1,28 @@
 /*
-* Copyright (c) 2006-2009 Erin Catto http://www.box2d.org
-*
-* This software is provided 'as-is', without any express or implied
-* warranty.  In no event will the authors be held liable for any damages
-* arising from the use of this software.
-* Permission is granted to anyone to use this software for any purpose,
-* including commercial applications, and to alter it and redistribute it
-* freely, subject to the following restrictions:
-* 1. The origin of this software must not be misrepresented; you must not
-* claim that you wrote the original software. If you use this software
-* in a product, an acknowledgment in the product documentation would be
-* appreciated but is not required.
-* 2. Altered source versions must be plainly marked as such, and must not be
-* misrepresented as being the original software.
-* 3. This notice may not be removed or altered from any source distribution.
-*/
+ * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty.  In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
 
 #include "../Framework/Test.h"
 #include "../Framework/Render.h"
 
 #ifdef __APPLE__
-       #include <GLUT/glut.h>
+#include <GLUT/glut.h>
 #else
-       #include "freeglut/freeglut.h"
+#include "freeglut/freeglut.h"
 #endif
 
 #include <cstring>
@@ -73,53 +73,57 @@ using namespace std;
 #include "VaryingRestitution.h"
 #include "VerticalStack.h"
 #include "Web.h"
+#include "TopDownCar.h"
+#include "WheelConstraint.h"
 
 TestEntry g_testEntries[] =
 {
-       {"Tumbler", Tumbler::Create},
-       {"Tiles", Tiles::Create},
-       {"Dump Shell", DumpShell::Create},
-       {"Gears", Gears::Create},
-       {"Cantilever", Cantilever::Create},
-       {"Varying Restitution", VaryingRestitution::Create},
-       {"Character Collision", CharacterCollision::Create},
-       {"Edge Test", EdgeTest::Create},
-       {"Body Types", BodyTypes::Create},
-       {"Shape Editing", ShapeEditing::Create},
-       {"Car", Car::Create},
-       {"Apply Force", ApplyForce::Create},
-       {"Prismatic", Prismatic::Create},
-       {"Vertical Stack", VerticalStack::Create},
-       {"SphereStack", SphereStack::Create},
-       {"Revolute", Revolute::Create},
-       {"Pulleys", Pulleys::Create},
-       {"Polygon Shapes", PolyShapes::Create},
-       //{"Rope", Rope::Create},
-       {"Web", Web::Create},
-       {"RopeJoint", RopeJoint::Create},
-       {"One-Sided Platform", OneSidedPlatform::Create},
-       {"Pinball", Pinball::Create},
-       {"Bullet Test", BulletTest::Create},
-       {"Continuous Test", ContinuousTest::Create},
-       {"Time of Impact", TimeOfImpact::Create},
-       {"Ray-Cast", RayCast::Create},
-       {"Confined", Confined::Create},
-       {"Pyramid", Pyramid::Create},
-       {"Theo Jansen's Walker", TheoJansen::Create},
-       {"Edge Shapes", EdgeShapes::Create},
-       {"PolyCollision", PolyCollision::Create},
-       {"Bridge", Bridge::Create},
-       {"Breakable", Breakable::Create},
-       {"Chain", Chain::Create},
-       {"Collision Filtering", CollisionFiltering::Create},
-       {"Collision Processing", CollisionProcessing::Create},
-       {"Compound Shapes", CompoundShapes::Create},
-       {"Distance Test", DistanceTest::Create},
-       {"Dominos", Dominos::Create},
-       {"Dynamic Tree", DynamicTreeTest::Create},
-       {"Sensor Test", SensorTest::Create},
-       {"Slider Crank", SliderCrank::Create},
-       {"Varying Friction", VaryingFriction::Create},
-       {"Add Pair Stress Test", AddPair::Create},
-       {NULL, NULL}
+               {"TopDownCar", TopDownCar::Create},
+               {"WheelConstraint", TopDownWheel::Create},
+               {"Tumbler", Tumbler::Create},
+               {"Tiles", Tiles::Create},
+               {"Dump Shell", DumpShell::Create},
+               {"Gears", Gears::Create},
+               {"Cantilever", Cantilever::Create},
+               {"Varying Restitution", VaryingRestitution::Create},
+               {"Character Collision", CharacterCollision::Create},
+               {"Edge Test", EdgeTest::Create},
+               {"Body Types", BodyTypes::Create},
+               {"Shape Editing", ShapeEditing::Create},
+               {"Car", Car::Create},
+               {"Apply Force", ApplyForce::Create},
+               {"Prismatic", Prismatic::Create},
+               {"Vertical Stack", VerticalStack::Create},
+               {"SphereStack", SphereStack::Create},
+               {"Revolute", Revolute::Create},
+               {"Pulleys", Pulleys::Create},
+//             {"Polygon Shapes", PolyShapes::Create},
+               //{"Rope", Rope::Create},
+               {"Web", Web::Create},
+               {"RopeJoint", RopeJoint::Create},
+               {"One-Sided Platform", OneSidedPlatform::Create},
+               {"Pinball", Pinball::Create},
+               {"Bullet Test", BulletTest::Create},
+               {"Continuous Test", ContinuousTest::Create},
+               {"Time of Impact", TimeOfImpact::Create},
+//             {"Ray-Cast", RayCast::Create},
+               {"Confined", Confined::Create},
+               {"Pyramid", Pyramid::Create},
+               {"Theo Jansen's Walker", TheoJansen::Create},
+//             {"Edge Shapes", EdgeShapes::Create},
+               {"PolyCollision", PolyCollision::Create},
+               {"Bridge", Bridge::Create},
+               {"Breakable", Breakable::Create},
+               {"Chain", Chain::Create},
+               {"Collision Filtering", CollisionFiltering::Create},
+               {"Collision Processing", CollisionProcessing::Create},
+               {"Compound Shapes", CompoundShapes::Create},
+               {"Distance Test", DistanceTest::Create},
+               {"Dominos", Dominos::Create},
+               {"Dynamic Tree", DynamicTreeTest::Create},
+               {"Sensor Test", SensorTest::Create},
+               {"Slider Crank", SliderCrank::Create},
+               {"Varying Friction", VaryingFriction::Create},
+               {"Add Pair Stress Test", AddPair::Create},
+               {NULL, NULL}
 };
diff -rupN Box2D_v2.2.1/Testbed/Tests/TopDownCar.h Box2D_v2.2.1_fjmod/Testbed/Tests/TopDownCar.h
--- Box2D_v2.2.1/Testbed/Tests/TopDownCar.h     1969-12-31 19:00:00.000000000 -0500
+++ Box2D_v2.2.1_fjmod/Testbed/Tests/TopDownCar.h       2012-11-13 21:13:29.000000000 -0500
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty.  In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#ifndef TOP_DOWN_CAR_H
+#define TOP_DOWN_CAR_H
+
+#include <stdio.h>
+
+class MyCar
+{
+ public:
+  float32 wheelDims[2];
+
+  float32 halfWidth;
+  float32 halfHeight;
+  float32 defaultDensity;
+  float32 defaultFriction;
+  float32 accelerateForce;
+
+  b2Body* wheels[4];
+  b2Body* chassis;
+  b2World* world;
+  b2Body* ground;
+  b2RevoluteJoint *frontLeftJoint;
+
+  bool frontWheelDrive;
+
+ MyCar(b2World *_world, b2Body* _ground, float32 width, float32 height) :
+  halfWidth(width/2.0f),
+    halfHeight(height/2.0f),
+    defaultDensity(20.0f),
+    defaultFriction(0.68f),
+    accelerateForce(2500.0f),
+    ground(_ground),
+    world(_world),
+    frontWheelDrive(true)
+      {
+       wheelDims[0] = .125;
+       wheelDims[1] = .5;
+
+       {
+         b2BodyDef chassisBd;
+         chassisBd.type = b2_dynamicBody;
+         chassisBd.position = b2Vec2(0.0f, 0.0f);
+         // give the chassis some damping
+         //chassisBd.linearDamping = 1.0;
+         //chassisBd.angularDamping = 1.0;
+
+         chassis = world->CreateBody(&chassisBd);
+
+         b2FixtureDef chassisFixture;
+         b2PolygonShape chassisShape;
+         chassisShape.SetAsBox(halfWidth, halfHeight);
+         chassisFixture.shape = &chassisShape;
+         chassisFixture.density = 0.05 * defaultDensity;
+         chassisFixture.friction = defaultFriction;
+
+         chassis->CreateFixture(&chassisFixture);
+         chassis->ResetMassData(); // necessary?
+       }
+      
+       {
+         b2FixtureDef wheelDef;
+         b2PolygonShape wheelShape;
+         wheelShape.SetAsBox(wheelDims[0], wheelDims[1]);
+         wheelDef.shape = &wheelShape;
+         wheelDef.density = defaultDensity/4.0;
+         wheelDef.friction = defaultFriction;
+
+         wheels[0] = makeWheel(-1, 1, wheelDef);
+         wheels[1] = makeWheel(1, 1, wheelDef);
+         wheels[2] = makeWheel(-1, -1, wheelDef);
+         wheels[3] = makeWheel(1, -1, wheelDef);
+       }
+
+       {
+         //Make the thing that ties the wheels together.
+         b2DistanceJointDef rackDef;
+
+         b2Body *w0 = wheels[0];
+         b2Body *w1 = wheels[1];
+
+         float32 offset = wheelDims[1] / 2.0f * 2.0f;
+
+         b2Vec2 pos0 = w0->GetWorldCenter();
+         b2Vec2 pos1 = w1->GetWorldCenter();
+
+         pos0.y += offset;
+         pos1.y += offset;
+
+         rackDef.Initialize(w0, w1, pos0, pos1);
+
+         world->CreateJoint(&rackDef);
+       }
+
+       // for (b2Body* b = world->GetBodyList(); b; b = b->GetNext()) {
+       //      b->Dump();
+       // }
+      }
+
+  void Steer(float32 dir = 1.0)
+  {
+    frontLeftJoint->SetMotorSpeed(dir * 2.0);
+  }
+
+  void Accelerate(float32 dir = 1.0)
+  {
+    // Which two wheels do we power?
+    int offset = frontWheelDrive ? 0 : 2;
+
+    for (int i = 0; i < 2; i++) {
+      b2Body *wheel = wheels[i + offset];
+      b2Vec2 force_vector = wheel->GetTransform().q.GetYAxis();
+      force_vector *= accelerateForce * dir;
+      wheel->ApplyForce(force_vector, wheel->GetWorldCenter());
+    }
+  }
+
+
+  virtual ~MyCar()
+    {
+    }
+
+ private:
+
+  b2Body* makeWheel(float32 xmul, float32 ymul, b2FixtureDef &wheelDef)
+  {
+    b2BodyDef bd;
+    bd.type = b2_dynamicBody;
+    b2Body *wheel;
+    bd.position = b2Vec2(xmul * (halfWidth - wheelDims[0]), ymul * halfHeight);
+
+    wheel = world->CreateBody(&bd);
+    wheel->CreateFixture(&wheelDef);
+    wheel->SetLinearDamping(0.01f);
+    wheel->SetAngularDamping(5.0);
+    wheel->ResetMassData(); // necessary?
+
+    b2RevoluteJointDef jointDef;
+    jointDef.Initialize(chassis, wheel, wheel->GetWorldCenter());
+
+    // If we're doing the front wheels
+    if (ymul > 0) {
+      jointDef.lowerAngle = -0.25 * b2_pi;
+      jointDef.upperAngle = 0.25 * b2_pi;
+    }
+
+    jointDef.enableLimit = true;
+
+    b2RevoluteJoint *joint = (b2RevoluteJoint*)world->CreateJoint(&jointDef);
+    if (xmul < 0 && ymul > 0)
+      {
+       frontLeftJoint = joint;
+       frontLeftJoint->EnableMotor(true);
+       frontLeftJoint->SetMaxMotorTorque(5000.0f);
+      }
+
+    {
+      float mass = wheel->GetMass();
+
+      b2FrictionJointDef jd;
+      jd.localAnchorA.SetZero();
+      jd.localAnchorB.SetZero();
+      jd.bodyA = ground;
+      jd.bodyB = wheel;
+      jd.collideConnected = true;
+      jd.maxForce = 100.0;  //* mass
+      jd.maxTorque = 50.0; //* mass
+      jd.muX = 20.0;
+      jd.muY = 0.0;
+      world->CreateJoint(&jd);
+      
+    }
+
+    return wheel;
+  }
+
+};
+
+class TopDownCar : public Test
+{
+  MyCar *car;
+ public:
+  TopDownCar()
+    {
+      m_world->SetGravity(b2Vec2(0.0f, 0.0f));
+              
+      b2Body* ground;
+      b2BodyDef bd;
+      bd.position.Set(0.0f, 0.0f);
+      ground = m_world->CreateBody(&bd);
+
+      car = new MyCar(m_world, ground, 2.0, 4.0);
+    }
+
+  void Keyboard(unsigned char key)
+  {
+    switch (key)
+      {
+      case 'f':
+       car->frontWheelDrive = !car->frontWheelDrive;
+       break;
+
+      case 'w':
+       car->Accelerate(1.0);
+       break;
+
+      case 's':
+       car->Accelerate(-1.0);
+       break;
+
+      case 'a':
+       car->Steer(1.0f);
+       break;
+
+      case 'd':
+       car->Steer(-1.0f);
+       break;
+      }    
+  }
+
+  void KeyboardUp(unsigned char key)
+  {
+    car->Steer(0.0f);
+  }
+
+  virtual ~TopDownCar()
+    {
+      delete car;
+    }
+
+  static Test* Create()
+  {
+    return new TopDownCar;
+  }
+
+};
+
+
+#endif
diff -rupN Box2D_v2.2.1/Testbed/Tests/WheelConstraint.h Box2D_v2.2.1_fjmod/Testbed/Tests/WheelConstraint.h
--- Box2D_v2.2.1/Testbed/Tests/WheelConstraint.h        1969-12-31 19:00:00.000000000 -0500
+++ Box2D_v2.2.1_fjmod/Testbed/Tests/WheelConstraint.h  2012-11-13 21:13:29.000000000 -0500
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com
+ *
+ * This software is provided 'as-is', without any express or implied
+ * warranty.  In no event will the authors be held liable for any damages
+ * arising from the use of this software.
+ * Permission is granted to anyone to use this software for any purpose,
+ * including commercial applications, and to alter it and redistribute it
+ * freely, subject to the following restrictions:
+ * 1. The origin of this software must not be misrepresented; you must not
+ * claim that you wrote the original software. If you use this software
+ * in a product, an acknowledgment in the product documentation would be
+ * appreciated but is not required.
+ * 2. Altered source versions must be plainly marked as such, and must not be
+ * misrepresented as being the original software.
+ * 3. This notice may not be removed or altered from any source distribution.
+ */
+
+#ifndef WHEEL_CONSTRAINT_H
+#define WHEEL_CONSTRAINT_H
+
+#include <stdio.h>
+
+class MyWheel
+{
+public:
+       float32 wheelDims[2];
+
+       float32 defaultDensity;
+       float32 defaultFriction;
+       float32 accelerateForce;
+
+       b2Body* wheels[1];
+       b2World* world;
+       b2Body* ground;
+
+       MyWheel(b2World *_world, b2Body* _ground, float32 width, float32 height) :
+               defaultDensity(20.0f),
+               defaultFriction(0.68f),
+               accelerateForce(2500.0f),
+               ground(_ground),
+               world(_world)
+       {
+               wheelDims[0] = 1.0;
+               wheelDims[1] = 0.3;
+               b2FixtureDef wheelDef;
+               b2PolygonShape wheelShape;
+               wheelShape.SetAsBox(wheelDims[0], wheelDims[1]);
+               wheelDef.shape = &wheelShape;
+               wheelDef.density = defaultDensity/4.0;
+               wheelDef.friction = defaultFriction;
+
+               wheels[0] = makeWheel(width, height, wheelDef);
+
+               // for (b2Body* b = world->GetBodyList(); b; b = b->GetNext()) {
+               //      b->Dump();
+               // }
+       }
+
+       virtual ~MyWheel()
+       {
+       }
+
+       void Steer(float32 dir = 1.0)
+       {
+               float32 torque_incr = 500.0;
+               b2Body *wheel = this->wheels[0];
+               wheel->ApplyTorque(dir * torque_incr);
+       }
+
+       void Accelerate(float32 ax = 0.0, float32 ay = 0.0)
+       {
+               b2Body *wheel = this->wheels[0];
+               b2Vec2 dir = b2Vec2(accelerateForce * ax, accelerateForce * ay);
+               b2Vec2 force_vector =  wheel->GetWorldVector(dir);
+               wheel->ApplyForce(force_vector, wheel->GetWorldCenter());
+       }
+
+private:
+
+       b2Body* makeWheel(float32 xmul, float32 ymul, b2FixtureDef &wheelDef)
+       {
+               b2BodyDef bd;
+               bd.type = b2_dynamicBody;
+               b2Body *wheel;
+               bd.position = b2Vec2(xmul, ymul);
+
+               wheel = world->CreateBody(&bd);
+               wheel->CreateFixture(&wheelDef);
+               wheel->SetLinearDamping(0.0); // 0.01f
+               wheel->SetAngularDamping(0.0); // 5.0
+               wheel->ResetMassData(); // necessary?
+
+               // Add friction joint:
+               {
+                       b2FrictionJointDef jd;
+                       jd.localAnchorA.SetZero();
+                       jd.localAnchorB.SetZero();
+                       jd.bodyA = ground;
+                       jd.bodyB = wheel;
+                       jd.collideConnected = true;
+                       jd.maxForce = 100.0;  // * mass
+                       jd.maxTorque = 50.0; // * mass
+                       jd.muX = 0.001;
+                       jd.muY = 0.9;
+                       jd.muT = 1.0;
+                       world->CreateJoint(&jd);
+               }
+
+               return wheel;
+       }
+};
+
+class TopDownWheel : public Test
+{
+
+       MyWheel *wheel;
+public:
+
+       TopDownWheel()
+{
+               m_world->SetGravity(b2Vec2(0.0f, 0.0f));
+
+               b2Body* ground;
+               b2BodyDef bd;
+               bd.position.Set(0.0f, 0.0f);
+               ground = m_world->CreateBody(&bd);
+
+               wheel = new MyWheel(m_world, ground, 2.0, 4.0);
+}
+
+       void Keyboard(unsigned char key)
+       {
+               switch (key)
+               {
+               case 'w':
+                       wheel->Accelerate(1.0, 0.0);
+                       break;
+
+               case 's':
+                       wheel->Accelerate(-1.0, 0.0);
+                       break;
+
+               case 'd':
+                       wheel->Accelerate(0.0, -1.0);
+                       break;
+
+               case 'a':
+                       wheel->Accelerate(0.0, 1.0);
+                       break;
+
+               case 'q':
+                       wheel->Steer(1.0f);
+                       break;
+
+               case 'e':
+                       wheel->Steer(-1.0f);
+                       break;
+               }
+       }
+
+       void KeyboardUp(unsigned char key)
+       {
+               wheel->Steer(0.0f);
+       }
+       virtual ~TopDownWheel()
+       {
+               delete wheel;
+       }
+
+       static Test* Create()
+       {
+               return new TopDownWheel;
+       }
+
+};
+
+#endif
 

About me

Pic of me