<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-gb">
	<link rel="self" type="application/atom+xml" href="https://pybullet.org/Bullet/phpBB3/app.php/feed/topic/13431" />

	<title>Real-Time Physics Simulation Forum</title>
	
	<link href="https://pybullet.org/Bullet/phpBB3/index.php" />
	<updated>2022-05-09T18:00:43+00:00</updated>

	<author><name><![CDATA[Real-Time Physics Simulation Forum]]></name></author>
	<id>https://pybullet.org/Bullet/phpBB3/app.php/feed/topic/13431</id>

		<entry>
		<author><name><![CDATA[gwendal_]]></name></author>
		<updated>2022-05-09T18:00:43+00:00</updated>

		<published>2022-05-09T18:00:43+00:00</published>
		<id>https://pybullet.org/Bullet/phpBB3/viewtopic.php?p=44010#p44010</id>
		<link href="https://pybullet.org/Bullet/phpBB3/viewtopic.php?p=44010#p44010"/>
		<title type="html"><![CDATA[Using bullet physics car and heightfield, car get stuck how can I fix?]]></title>

		
		<content type="html" xml:base="https://pybullet.org/Bullet/phpBB3/viewtopic.php?p=44010#p44010"><![CDATA[
I've been working on implementing a car in my game using bullet physics. The physics of the car uses `btRaycastVehicle` and the code is mostly based on the <a href="https://github.com/bulletphysics/bullet3/blob/master/examples/ForkLift/ForkLiftDemo.cpp" class="postlink">ForkLift Demo</a>. At this point, the vehicle seems to work properly on a flat ground but then I've started working on a non flat terrain and I saw the class `btHeightfieldTerrainShape` which take an array of heights to construct a shape.<br>So I've managed to use this class and the vehicle can be used on it but it sometimes get stuck on terrain's hollows even if the height to climb is really small.  <br><br>I'm using MLCP constraint solver and tested PGS solver but does not help.  <br>Here is the concerned code :<br><br><strong class="text-strong">Vehicle.hpp</strong><br><div class="codebox"><p>Code: </p><pre><code>#define USE_MLCP_SOLVER// I removed other #define because all were just floats class Vehicle {public:    // theses bools are set to true when the corresponding key is pressed    bool m_foward = false, m_backward = false, m_leftward = false, m_rightward = false;    bool m_reset = false;     Vehicle(Vao *chassisVao, Vao *wheelVao, const float *heights, uint32_t gridsize, float amplitude);     ~Vehicle();     // this function runs the logic of the physics simulation, it gets executed each frame    void stepSimulation(uint32_t frameTime);     // this function instantiate objects to rendered, it gets executed each frame    void prepareRendering(std::vector&lt;const Entity *&gt; &amp;entities); private:    // members are declared here ---&gt;  &lt;---     // create physics world and vehicle    void initPhysics(const float *heights, uint32_t gridsize, float amplitude);     // cleanup things    void exitPhysics(void);     // reset vehicle position, rotation, momentum, etc..    void resetVehicle(void);     // helper function to create rigid body    btRigidBody* localCreateRigidBody(btScalar mass, const btTransform&amp; startTransform, btCollisionShape* shape);};</code></pre></div><br><strong class="text-strong">Vehicle.cpp</strong><br><div class="codebox"><p>Code: </p><pre><code>#include "Vehicle.hpp" Vehicle::Vehicle(Vao *chassisVao, Vao *wheelVao, const float *heights, uint32_t gridsize, float amplitude) {    initPhysics(heights, gridsize, amplitude);     if (chassisVao) {        m_chassisEntity = new Entity(chassisVao);    }    for (int i = 0; i &lt; 4; ++i) {        m_wheelEntities.push_back(Entity(wheelVao));    }} Vehicle::~Vehicle() {    exitPhysics();     if (m_chassisEntity) {        delete m_chassisEntity;    }    m_wheelEntities.clear();} void Vehicle::initPhysics(const float *heights, uint32_t gridsize, float amplitude) {    // setup dynamics world    m_collisionConfiguration = new btDefaultCollisionConfiguration();    m_dispatcher = new btCollisionDispatcher(m_collisionConfiguration);    btVector3 worldMin(-1000, -1000, -1000);    btVector3 worldMax(1000, 1000, 1000);    m_overlappingPairCache = new btAxisSweep3(worldMin, worldMax); #ifdef USE_MLCP_SOLVER    btDantzigSolver* mlcp = new btDantzigSolver();    // btSolveProjectedGaussSeidel* mlcp = new btSolveProjectedGaussSeidel();    btMLCPSolver* sol = new btMLCPSolver(mlcp);    m_solver = sol;#else    m_solver = new btSequentialImpulseConstraintSolver();#endif     m_world = new btDiscreteDynamicsWorld(m_dispatcher, m_overlappingPairCache, m_solver, m_collisionConfiguration);#ifdef USE_MLCP_SOLVER    m_world-&gt;getSolverInfo().m_minimumSolverBatchSize = 1;#else    m_world-&gt;getSolverInfo().m_minimumSolverBatchSize = 128;#endif    m_world-&gt;getSolverInfo().m_globalCfm = 0.00001;     // create ground object    // btVector3 groundExtents(100, 3, 100);    // btCollisionShape* groundShape = new btBoxShape(groundExtents);    btCollisionShape* groundShape = new btHeightfieldTerrainShape(gridsize + 1, gridsize + 1, heights, 0.0f, amplitude, 1, false);    m_collisionShapes.push_back(groundShape);    btTransform tr;    tr.setIdentity();    tr.setOrigin(btVector3(gridsize * 0.5f, WHEEL_RADIUS, gridsize * 0.5f));    localCreateRigidBody(0, tr, groundShape);        // create vehicle        // BEGIN - create chassis shape    btVector3 vehicleExtents(1.76f, 1.1f, 4.0f);    btCollisionShape* chassisShape = new btBoxShape(vehicleExtents);    m_collisionShapes.push_back(chassisShape);     btCompoundShape* compound = new btCompoundShape();    m_collisionShapes.push_back(compound);    btTransform localTrans;    localTrans.setIdentity();    //localTrans effectively shifts the center of mass with respect to the chassis    localTrans.setOrigin(btVector3(0, 1, 0));    compound-&gt;addChildShape(localTrans, chassisShape);     tr.setOrigin(btVector3(0, 0, 0));    m_carChassis = localCreateRigidBody(800, tr, compound);        // END - create chassis shape         // BEGIN - create vehicle    m_vehicleRayCaster = new btDefaultVehicleRaycaster(m_world);    m_vehicle = new btRaycastVehicle(m_tuning, m_carChassis, m_vehicleRayCaster);    m_carChassis-&gt;setActivationState(DISABLE_DEACTIVATION); // never deactivate the vehicle    m_world-&gt;addVehicle(m_vehicle);     // choose coordinate system    m_vehicle-&gt;setCoordinateSystem(0, 1, 2);     btVector3 wheelDirection(0, -1, 0);    btVector3 wheelAxis(-1, 0, 0);    btVector3 connectionPoint(0.5f * vehicleExtents.x(), WHEEL_RADIUS, 0.5f * vehicleExtents.z() - WHEEL_RADIUS);    m_vehicle-&gt;addWheel(connectionPoint, wheelDirection, wheelAxis, SUSPENSION_REST_LENGTH, WHEEL_RADIUS, m_tuning, true);    connectionPoint = btVector3(-0.5f * vehicleExtents.x(), WHEEL_RADIUS, 0.5f * vehicleExtents.z() - WHEEL_RADIUS);    m_vehicle-&gt;addWheel(connectionPoint, wheelDirection, wheelAxis, SUSPENSION_REST_LENGTH, WHEEL_RADIUS, m_tuning, true);    connectionPoint = btVector3(0.5f * vehicleExtents.x(), WHEEL_RADIUS, -0.5f * vehicleExtents.z() + WHEEL_RADIUS);    m_vehicle-&gt;addWheel(connectionPoint, wheelDirection, wheelAxis, SUSPENSION_REST_LENGTH, WHEEL_RADIUS, m_tuning, false);    connectionPoint = btVector3(-0.5f * vehicleExtents.x(), WHEEL_RADIUS, -0.5f * vehicleExtents.z() + WHEEL_RADIUS);    m_vehicle-&gt;addWheel(connectionPoint, wheelDirection, wheelAxis, SUSPENSION_REST_LENGTH, WHEEL_RADIUS, m_tuning, false);     for (int i = 0; i &lt; m_vehicle-&gt;getNumWheels(); i++) {        btWheelInfo&amp; wheel = m_vehicle-&gt;getWheelInfo(i);        wheel.m_suspensionStiffness = SUSPENSION_STIFFNESS;        wheel.m_wheelsDampingRelaxation = SUSPENSION_DAMPING;        wheel.m_wheelsDampingCompression = SUSPENSION_COMPRESSION;        wheel.m_frictionSlip = WHEEL_FRICTION;        wheel.m_rollInfluence = ROLL_IN_INFLUENCE;    }     resetVehicle();}void Vehicle::stepSimulation(uint32_t frameTime) {    float speed = m_vehicle-&gt;getCurrentSpeedKmHour();        m_vehicleEngineForce = 0.0f;    m_vehicleBreakingForce = 0.0f;    /* ---&gt;    Processing input sets m_vehicleEngineForce, m_vehicleBreakingForce, m_vehicleSteering    &lt;--- */     m_vehicle-&gt;applyEngineForce(m_vehicleEngineForce, 2);    m_vehicle-&gt;setBrake(m_vehicleBreakingForce, 2);    m_vehicle-&gt;applyEngineForce(m_vehicleEngineForce, 3);    m_vehicle-&gt;setBrake(m_vehicleBreakingForce, 3);     m_vehicle-&gt;setSteeringValue(m_vehicleSteering, 0);    m_vehicle-&gt;setSteeringValue(m_vehicleSteering, 1);     m_world-&gt;stepSimulation(frameTime * 0.001f, 2);    btMLCPSolver *solver = (btMLCPSolver *) m_world-&gt;getConstraintSolver();    int numFallbacks = solver-&gt;getNumFallbacks();    if (numFallbacks) {        std::cerr &lt;&lt; "MLCP solver failed " &lt;&lt; numFallbacks &lt;&lt; " times, falling back to btSequentialImpulseSolver" &lt;&lt; std::endl;    }    solver-&gt;setNumFallbacks(0);}</code></pre></div>And here is a video to illustrate : <a href="https://youtu.be/FpapLssTGkA" class="postlink">link</a><br><br>Thank you<p>Statistics: Posted by <a href="https://pybullet.org/Bullet/phpBB3/memberlist.php?mode=viewprofile&amp;u=14325">gwendal_</a> — Mon May 09, 2022 6:00 pm</p><hr />
]]></content>
	</entry>
	</feed>
