• 0 Vote(s) - 0 Average
• 1
• 2
• 3
• 4
• 5
elchtest mod :)
03-05-2010, 01:44 PM,
 NaN Posting Freak Posts: 2,024 Threads: 120 Joined: Jan 2010

Oh, silly me :oops:
Now I understand what sebiastisch meant with updateAction callback. I have to use btActionInterface to be able to modify btRigidBody state.
03-05-2010, 02:25 PM,
 sebiastisch Junior Member Posts: 30 Threads: 3 Joined: Feb 2010

I will have a look at your code tomorrow.
But I think, i have done a mistake, too, because the car only stops and does not roll back, after a crash (even when crashing a static wall). an yes i am updating velocity and position.
this is a bit strange, because everything else looks pretty good.

Update from the cylinder shape works better now.
Next week i will really give you a video
There are still problems with bouncy wheels and in consequence very hard hits by the ff-wheel. i also had to take the distance from the center of the wheel. when taking the distance from the wheel rotation axis, the car jumps and same for the depth of the hit.
I have also no idea, what the parameters in setcontact are for. the tread f.e. isn't even used and the road frequency thing also makes only problems.
03-06-2010, 09:19 AM,
 sebiastisch Junior Member Posts: 30 Threads: 3 Joined: Feb 2010

@NaN:
I'm looking at your code. I guess you have to add some synchronization to the pose not only the velocities, too. Then you have to decide which one of them integrates the velocities.

Further there is some possible problem with the velocities:
You are getting the vdrift velocities after a timestep and bullet assumes constant velocities. I solved it by calculating the velocitiy from the distance the car moved/rotated.

So, what are your concrete problems?

For your information: Here is my code for the cylinder collision detection.
Code:
```void CarPhysics::UpdateWheelContacts() {     double bumpwave = 1;     double bumpamp= 0.0;     double frict_no= 1.5;     double frict_tread=0;     double roll_res=0.;     double roll_drag=0;     SURFACE::CARSURFACETYPE surface = SURFACE::ASPHALT;     //Update the wheels!     UpdateBulletWheelsFromVdrift();     // some possible helpers for orientation conversion     btQuaternion bullet_ori = chassisBody->getWorldTransform().getRotation().inverse();     btQuaternion vdrift_ori = ( getbtQuaternion( car_dynamics->GetOrientation()));     btQuaternion convertRotation= vdrift_ori * bullet_ori;         if (debugGeode)             OSGroot->removeChild(debugGeode);     debugGeode = new osg::Geode();     OSGroot->addChild(debugGeode);     for (int wheel = 0; wheel < WHEEL_POSITION_SIZE; ++wheel)     {         int contactNum=0;         //For (optional) averaging         btVector3 colPoint(0,0,0);         btVector3 colNormal(0,0,0);         double colDepth=0;         double minLength=10000000000.;         double maxLength= 0;         ////////////////////////////         btManifoldArray   manifoldArray;         btBroadphasePairArray& pairArray = wheel_infos[wheel]->wheelGhost->getOverlappingPairCache()->getOverlappingPairArray(); //        int numPairs = pairArray.size();         int numPairs=  wheel_infos[wheel]->wheelGhost->getNumOverlappingObjects();         for (int i=0;i<numPairs;i++)         {             manifoldArray.clear();             const btBroadphasePair& pair = pairArray[i];             //unless we manually perform collision detection on this pair, the contacts are in the dynamics world paircache:             btBroadphasePair* collisionPair = m_dynamics_world->getPairCache()->findPair(pair.m_pProxy0,pair.m_pProxy1);             if (!collisionPair)                 continue;             if (collisionPair->m_algorithm)                 collisionPair->m_algorithm->getAllContactManifolds(manifoldArray);             for (int j=0;j<manifoldArray.size();j++)             {                 btPersistentManifold* manifold = manifoldArray[j];                 btScalar directionSign = manifold->getBody0() ==  wheel_infos[wheel]->wheelGhost ? btScalar(-1.0) : btScalar(1.0);                 if (directionSign>0.){                 //    cout << " QQQQQQQQ "<< endl;                     continue; // Punkte nur in eine Richtung holen                 }                 if (manifold->getBody0() == chassisBody)                 {                     //cout << " DAMN "<< endl;                     continue;                 }                 for (int p=0;p<manifold->getNumContacts();p++)                 {                     const btManifoldPoint&pt = manifold->getContactPoint(p);                     if (pt.getDistance()<0.f)                     {                         const btVector3& ptA = pt.getPositionWorldOnA();                         const btVector3& ptB = pt.getPositionWorldOnB();                         const btVector3& normalOnB = pt.m_normalWorldOnB;                         const float depth=(ptA-ptB).length();                         btVector3 wheelLocalHitPos= wheel_infos[wheel]->wheelRigidbody->getCenterOfMassPosition() -ptB;                         colPoint+= ptA*depth;                         colNormal+= normalOnB*depth;                         colDepth+= depth;                         contactNum++;                     }                 }             }         }         //////////////////////////////         ///Process the result         if (contactNum>0)         { //            cout << " anzahl der kontakte fÃ¼r reifen " << wheel << " : "<<contactNum << endl;             ////average             colPoint/=colDepth;             colNormal/=colDepth;             colDepth/=contactNum;             btVector3 wheelLocalHitPos= wheel_infos[wheel]->wheelRigidbody->getCenterOfMassPosition() -colPoint; // // Get the distance from rotation axis to col point (no good: car does bounce) //            btVector3 test (0,0,1); //            test.rotate(wheel_infos[wheel]->wheelRigidbody->getOrientation().getAxis(),wheel_infos[wheel]->wheelRigidbody->getOrientation().getAngle()); //            test.normalize(); //            double distanceFromWheelCenter = wheelLocalHitPos.dot(test)*contactNum;             // Fake the depth to be the distance from wheel center to the collision point             double distanceFromWheelCenter= wheelLocalHitPos.length() ;             colNormal.normalize();             car_dynamics->SetWheelContactProperties(WHEEL_POSITION(wheel),    (double)distanceFromWheelCenter  ,getMATHVECTOR(colPoint), getMATHVECTOR(colNormal),bumpwave, bumpamp, frict_no, frict_tread, roll_res, roll_drag, surface);             std::cout << "ColPoint:  " << colPoint.getX() << " " << colPoint.getY() << " " << colPoint.getZ() <<endl;             std::cout << " Collision normal: "<< colNormal.getX() << " " << colNormal.getY() << " " << colNormal.getZ() << std::endl;             cout << " distance from wheel center: " << "  "<<car.GetTireRadius((WHEEL_POSITION)wheel)<<" "<< distanceFromWheelCenter<<"  "<<colDepth<<"  "<<endl;         cout << "-----------------------------------"<<endl;         }    else         {             car_dynamics->SetWheelContactProperties(WHEEL_POSITION(wheel),    (double)1000,                     MATHVECTOR<double,3>(0), MATHVECTOR<double,3>(0,0,1),                     bumpwave, bumpamp, frict_no, frict_tread, roll_res, roll_drag, surface);         }     } }```

It is a mess, but I am still experimenting with different versions (getting the deepest hit depth, or using different normals, etc.)
Wheels are modeled as GhostObjects and therefore don't collide themselves, but save collisions. In the new bullet version, there must be a instant Collision check, which is preferable, but I did not yet try it.

My ray cast version looks almost identical to yours.

Edit:
world.stepSimulation(dt, maxsubsteps, dt);
makes bullet use your timestep and not interpolate to dt (thats what I understood).

Your implementation differs from mine, because I use bullet to trigger the physics tick in vdrift (it is all done in the updateAction function).
One StepSimulation is all, you have to do then.
Execution looks like follows:
Code:
```void CarPhysics::updateAction( btCollisionWorld* collisionWorld, btScalar deltaTimeStep) {     double dt= (double) deltaTimeStep *2.; // FIXME ... why is vdrift slower than bullet?     int num_repeats= dt/internal_dt+0.5;     /// overwrite vdrift pose/velocities with bullets calculation to integrate collision results     UpdateInternalFromBullet();     // Init deltaAngularVelocity (contains sum over all delta Velocities in substeps)     deltaAngularVelocity=getVector3d(car_dynamics->GetBody().GetAngularVelocity());     oldPosition=GetPosition();     double old_force= force_feedback;     force_feedback=0;     UpdateWheelContacts(); //TODO do this in every substep (needs collision from bullet 2.76)     /// Apply several vdrift steps (cause frequency must be very high for a vehicle     for (int i= 0; i< num_repeats; ++i )     {         ///Get the new engine and so on sounds         car.UpdateSounds(internal_dt);         ///Use the input vector to update internal car controls (inputs has to be set by setInputVector! )         // Input Handling differs and adds things to handling in Vdrift         car.HandleInputsTransparent(inputs, internal_dt);         force_feedback+= car.GetFeedback();         //Set forward the vdrift physics         car.TickPhysics(internal_dt);         deltaAngularVelocity+= getVector3d(car_dynamics->GetBody().GetAngularVelocity());     }     force_feedback/=num_repeats;     deltaAngularVelocity= deltaAngularVelocity/((double)num_repeats+1);     newPosition= GetPosition();     double dt_inv= 1. / (num_repeats*internal_dt);     deltaVelocity= (newPosition-oldPosition) * dt_inv;     // Update the Bullet angular and linear Velocities: This is the only connection from Vdrift to bullet     UpdateBulletVelocities(); }```
03-08-2010, 11:28 AM,
 NaN Posting Freak Posts: 2,024 Threads: 120 Joined: Jan 2010

@sebiastisch
Sorry for the late reply. Haven't had time to look into vdrift at the weekend.

Edit:
Why replicating your work at first place? How do you think about integrating your CarPhysics class code into CAR class?
03-08-2010, 11:11 PM,

sebiastisch Wrote:Wheels are modeled as GhostObjects and therefore don't collide themselves, but save collisions. In the new bullet version, there must be a instant Collision check, which is preferable, but I did not yet try it.

I do a discrete collision test in COLLISION_WORLD::CollideObject. The key is to call findAlgorithm on the collision dispatcher and then processCollision on the algo. I use my AABB_SPACE_PARTITIONING_NODE class to determine which pairs to test, which is faster than bullet's general broadphase algorithm (because the bullet algorithm is meant for dynamic objects and makes less assumptions).
03-08-2010, 11:24 PM,

sebiastisch Wrote:I have also no idea, what the parameters in setcontact are for. the tread f.e. isn't even used and the road frequency thing also makes only problems.

CAR::SetWheelContactProperties takes these arguments:
* wheel_index: which wheel we're talking about
* wheelheight: {the vector pointing from {the position where the tire patch would touch the road if the suspension were deflected as far as needed to cause the tire to touch the ground} to {the center of the wheel's current position based on the current suspension displacement} } dot product with {the average direction of suspension displacement}
* position: the position where the tire patch would touch the road if the suspension were deflected as far as needed to cause the tire to touch the ground

The rest of the parameters are just surface information about the road object and don't have much to do with the collision itself:

* normal: the surface normal of the road object
* bumpwave: the wavelength of an additional bump surface that displaces the top of the road object
* bumpamp: the amplitude of an additional bump surface that displaces the top of the road object (this and bumpwave are used to simulate bouncy offroad conditions without having to model the bumps with track geometry)
* frict_no: a friction coefficient multiplier to be used with tires that have no tread on this road object
* frict_tread: a friction coefficient multiplier to be used with tires that have tread on this road object (this an frict_no are used to very roughly simulate how tires with a lot of tread don't do well on some surfaces but do well on others, and vice versa)
* roll_res: the rolling resistance of the road object
* roll_drag: the rolling drag of the road object
* surface: the type of surface. This is used to determine what kind of sound to play when driving over the surface.
03-09-2010, 06:55 AM,
 sebiastisch Junior Member Posts: 30 Threads: 3 Joined: Feb 2010

@Joe

I switched to 2.76 and it looks like this now:
Code:
```///// Instant Collision Query         btDeepestContactResultCallback contRes(wheel_infos[wheel]->wheelCollisionObject,chassisBody,false);         // Query for result         m_dynamics_world->contactTest( wheel_infos[wheel]->wheelCollisionObject,contRes);```
(I wrote the callback myself.)
So there is only a collision test done (and that several times, for new positions if one wants to). Performance seems ok. What do you think?

Ok, i got those parameters totally wrong (normal, position and wheelheight).

How do I have to fill them?
Are the following assumptions right?
* normal -> has nothing to do with collision itself? just the normal on the surface at the collision point? currently I am using the collision normal between the two collision points.

* Position-> Is it correct to just take the deepest point of the collision of the wheel (with positions from getWheelPosition and orientation from getWheelOrientation)?

* Wheelheight-> It is a projection from the {colPoint to the wheel center point vector} to the {average direction of suspension displacement}. what do you mean by the latter?
I interpreted something like: ( wheelCenter-colPoint) x ( (0,0,-1).rotate(wheelOrientationFloating) )
Not sure, whether this makes sense....

I especially don't know where to get the following from:
Quote:the position where the tire patch would touch the road if the suspension were deflected as far as needed to cause the tire to touch the ground
I can only collide the wheel in the position it is and not get the point, where it would collide if it was deflected correctly.

@NaN: The problem is, that my code is not really compatible. I did not use the car class itself to implement stuff, but inherited an interface class to put it in our simulation. it contains a lot of specific Open Scene Graph things, I don't use the graphic models from vdrift, etc. I will surely help you and you can of course have my code (although you will have to wait a little, till it is readable )
Edit: Forget about the things I said about averaging the speed. I am not sure why, but the results are better when just taking the final vdrift speed (I tested it by letting a car and bullet objects fall from some hundred meters and watching which arrived at the ground first.

Edit:
This seems to work properly... Still have to get the surface normal.
Just taking the collision point (that one on the surface) works and seems to work as an approximation to the contact point with optimally deflected suspension. (values greater than the tire radius are not used, right? ) .
Code:
```        ///// Instant Collision Query         btDeepestContactResultCallback contRes(wheel_infos[wheel]->wheelCollisionObject,chassisBody,false);         // Query for result         m_dynamics_world->contactTest( wheel_infos[wheel]->wheelCollisionObject,contRes);         if (contRes.m_hitCount>0)                 {             colPoint=contRes.getPoint();             //colNormal= contRes.getNormal();             colNormal= btVector3(0,0,1);             //colDepth= contRes.getHitDepth();             // Vector from collision point to wheel center             btVector3 wheelLocalHitPos= wheel_infos[wheel]->wheelRigidbody->getCenterOfMassPosition() -colPoint;             // Get the normal of the suspension             btVector3 down (0,0,1);             down.rotate(wheel_infos[wheel]->wheelRigidbody->getOrientation().getAxis(),wheel_infos[wheel]->wheelRigidbody->getOrientation().getAngle());             //down.normalize();             //cout << "down "<< down.x()<<" "<< down.y()<<" "<< down.z()<<endl;             double projectedDepth= wheelLocalHitPos.dot(down);             double distanceFromWheelCenter = projectedDepth;             car_dynamics->SetWheelContactProperties(WHEEL_POSITION(wheel),    (double)distanceFromWheelCenter  ,getMATHVECTOR(colPoint), getMATHVECTOR(colNormal),bumpwave, bumpamp, frict_no, frict_tread, roll_res, roll_drag, surface);             std::cout << "ColPoint:  " << colPoint.getX() << " " << colPoint.getY() << " " << colPoint.getZ() <<endl;             std::cout << " Collision normal: "<< colNormal.getX() << " " << colNormal.getY() << " " << colNormal.getZ() << std::endl;             cout << " Wheelheight: " << "tire radius: "<<car.GetTireRadius((WHEEL_POSITION)wheel)<<" distance: "<<distanceFromWheelCenter<<endl;             cout << "-----------------------------------"<<endl;                 }    else                 {                     //cout << "NOOO"<<endl;                     car_dynamics->SetWheelContactProperties(WHEEL_POSITION(wheel),    (double)1000,                             MATHVECTOR<double,3>(0), MATHVECTOR<double,3>(0,0,1),                             bumpwave, bumpamp, frict_no, frict_tread, roll_res, roll_drag, surface);                 }```

@Joe: Another thing:

Shouldn't the tread change with the tire contact? I think it is not used at all (set to zero in all .car files).
03-11-2010, 02:00 AM,

sebiastisch Wrote:* normal -> has nothing to do with collision itself? just the normal on the surface at the collision point?
That is correct.

Quote:* Position-> Is it correct to just take the deepest point of the collision of the wheel (with positions from getWheelPosition and orientation from getWheelOrientation)?

As long as you're absolutely sure that's the deepest point of collision, then that's fine.

If that doesns't work, you could give this a try: if you have the deepest point of the collision in a variable called "deepest_point", the current wheel center in a variable called "center", and the normal of the surface at the collision point in a variable called "normal", here's the way I would compute this:
Code:
```float d = (-normal).dot(deepest_point); MATHPLANE <float> plane(normal[0], normal[1], normal[2], d); MATHVECTOR <float, 3> position = center - normal*plane.DistanceToPoint(center);```

Quote:* Wheelheight-> It is a projection from the {colPoint to the wheel center point vector} to the {average direction of suspension displacement}. what do you mean by the latter?
I interpreted something like: ( wheelCenter-colPoint) x ( (0,0,-1).rotate(wheelOrientationFloating) )
Not sure, whether this makes sense....
Yes, that's what I meant. The "x" that you put in there would need to be a dot product, of course.

Quote:I especially don't know where to get the following from:
Quote:the position where the tire patch would touch the road if the suspension were deflected as far as needed to cause the tire to touch the ground
I can only collide the wheel in the position it is and not get the point, where it would collide if it was deflected correctly.

Yes, that's a good point! You can't really determine the point where it would collide if it was deflected correctly by only doing a single collision check with a cylinder. With ray casts it's easy because you're basically approximating the tire as a point and testing a line segment. The line segment is the shape that a point would make as it is swept through the suspension displacement. So maybe what you need to test is a shape that represents the area that would be swept out by a cylinder moving through suspension displacement. Maybe a capsule..? I think I remember reading Bullet does support swept collisions, maybe you could use that directly to test a swept cylinder shape?

As a side note, the reason that VDrift needs the tire contact point where it would collide with the road if the suspension was deflected correctly is because VDrift doesn't simulate the wheel as a separate rigid body with its own (non-rotational) inertia. This is (in my mind) the biggest limitation of the current physics approach because it doesn't simulate unsprung weight and its effects. If you or NaN is so inclined, you could always try implementing this, although it'd be hairy....

Quote:Shouldn't the tread change with the tire contact? I think it is not used at all (set to zero in all .car files).

The tread value isn't meant to represent the area of the tire contact or anything like that, it's just supposed to be a property of the tire on a spectrum from zero (no tread racing tires) to 1 (offroad tires). It's a hack I added and sort of regret now, so I recommend just ignoring it. The effect that you're probably interested in (changing tire friction as the tire contact patch changes) is modeled pretty completely with the pacejka equation.
03-11-2010, 02:05 AM,

sebiastisch Wrote:values greater than the tire radius are not used, right?

I almost missed this question. This is important: the answer is that values greater than the tire radius are used! The suspension is immediately deflected to the spot that corresponds to the position of where the tire would touch the surface if it can. It's tough to see this in the code because there are a lot of offsets and transformations being applied, but that's the end result. This is the big limitation with not simulating unsprung weight that I mentioned earlier.

All that said, you might be OK using the cylinder shape for collision checking as long as the car's suspension displacement is smaller than the radius of a tire, and you're careful about positioning the cylinder for your collision query (position the cylinder as if the suspension was fully deflected, then apply offsets as necessary to make sure the wheelheight value you pass into SetWheelContactProperties is relative to the current wheel position, not the position where you put the cylinder).
03-11-2010, 09:43 AM,
 sebiastisch Junior Member Posts: 30 Threads: 3 Joined: Feb 2010

That is very interesting information!

It is funny that, it works very good, the way it is done now (I think a lot better than with the ray). In normal situations (wheel contacts the ground) the results should be approximately perfect, because, the suspension is deflected almost correctly (although wheels are always a little too high, i guess).

Now you mentioned it, I noticed that the wheels don't deflect, when the car is just falling.

A simple hack to fix this, is to just deflect the wheels on default. They will automatically go up, when they touch ground. When there is no ground contact, deflect them again.

As I have the wheels as rigid bodys in my bullet simulation, it would also be no problem to make them dynamic objects. The problem is on the one hand the axis kinematic (although a simple connstraint with a fixed rotation center is pretty easy and on the other the connection with vdrift. Do you really think it is that difficult to calculate the deflection by adding some damping +spring forces (I'd just assume McPhersons) and a weight?
I didn't mess with those parts in vdrift yet.

Edit: A quick fix for some problems is to just enlarge the collision cylinders for the wheels by ca. 20cm. Although this is alsoby no means satisfying solution.
03-11-2010, 09:45 AM,
 sebiastisch Junior Member Posts: 30 Threads: 3 Joined: Feb 2010

@NaN:
Do you want my CarPhysics Class ? I do not want to do the integration of bullet, but i would like to add the cylinder test for the wheels.
Maybe we can work out the dynamic unsprung weights/wheels together.
03-11-2010, 03:04 PM,
 NaN Posting Freak Posts: 2,024 Threads: 120 Joined: Jan 2010

@sebiastish

I'd love to work on the suspension. But I am kinda stuck in the bullet integration at the moment. It is like touch one thing and you have to fix four others. I'll try to finish it as soon as possible.
03-15-2010, 06:50 AM,
 sebiastisch Junior Member Posts: 30 Threads: 3 Joined: Feb 2010

OK, here it is. Sorry for the chaos, but I just don't find the time for a cleanup...

[url]
http://wwwiaim.ira.uka.de/users/brechtel...ics.tar.gz
[/url]
03-15-2010, 03:26 PM,
 NaN Posting Freak Posts: 2,024 Threads: 120 Joined: Jan 2010

@sebiastisch
Danke schÃ¶n!

The car collision shape is causing problems in my implementation.

This one works (collision shape is positioned at center of mass though):
btBoxShape* shape = new btBoxShape(boxsize * 0.5);
btRigidBody::btRigidBodyConstructionInfo info(mass, NULL, shape, btinertia);

As soon as I try to offset the position of the collision shape using btCompoundShape things go mayhem (car drives through track geometry):
btTransform localtransform;
localtransform.getIdentity();
localtransform.setOrigin(boxoffset);
btBoxShape* box = new btBoxShape(boxsize * 0.5);
btCompoundShape* shape = new btCompoundShape();
btRigidBody::btRigidBodyConstructionInfo info(mass, NULL, shape, btinertia);

Do you have any experience using btCompoundShape?

Edit:
I've got it working. Had a stupid typo in the code. I was not setting localtransform orientation.
03-16-2010, 08:13 AM,
 sebiastisch Junior Member Posts: 30 Threads: 3 Joined: Feb 2010

Gern geschehen!

The program was at first meant as a prototype...and thus looks like one

I am having some problems with the car floating around (to be more precise, the z-orientation floats), when the car should stand still.
Do you also experience that?

What do you think of the cylinder shape contact calculation. I would love to continue with this, but (as always) there is lot of "real" work to do...

Forum Jump:

Users browsing this thread: 1 Guest(s)