Bullet Physics Raycast Vehicle acts weird when backing up & turning

Started by
1 comment, last by Aressera 5 months, 1 week ago

Hello all, so I'm working on a Car implementation for my Game, and so far going forward and turning, all is well and the vehicle can go in circles, however when it comes to backing up and turning, the Vehicle Un-naturally just flips over… I've tried to tighten the suspension stiffness, mess with the size of the body and size of wheels, and positioning of wheels on the car, but I can't mitigate this unwanted behavior!

The code below is what's driving the Raycast Vehicle Physics, One thing to note, I apply Steer to my front wheels, and I apply engine for to my back wheels. I've tried applying engine force on front wheels aswell, but the same issue occurs, and it just results in more aggressive steering,

Also note that the vehicle is driving on a flat test plane, with a small Pyramid to step over (Static Rigid Bodys)

#include "VehiclePhysics.h"
#include "engine_core/singletons/PhysicsWorldSingleton.h"

VehiclePhysics::VehiclePhysics()
{
    PhysicsWorldSingleton *physicsWorld = PhysicsWorldSingleton::getInstance();

    // Vehicle tuning:
    tuning.m_suspensionStiffness = 90.0f;
    tuning.m_suspensionCompression = 0.83f;
    tuning.m_suspensionDamping = 0.88f;
    tuning.m_maxSuspensionTravelCm = 100.0f;
    tuning.m_frictionSlip = 10.5f;
    tuning.m_maxSuspensionForce = 6000.0f;

    // Vehicle setup
    btBoxShape *vehicleChassisShape = new btBoxShape(btVector3(0.8f, 0.25f, 1.5f));
    btDefaultMotionState *vehicleMotionState = new btDefaultMotionState();
    btTransform localTransform;

    localTransform.setIdentity();
    localTransform.setOrigin(btVector3(0, 1, -10));
    
    vehicleMotionState->setWorldTransform(localTransform);

    //* VEHICLE MASS !
    btScalar vehicleMass = 1000;

    btVector3 vehicleInertia(0, 0, 0);
    vehicleChassisShape->calculateLocalInertia(vehicleMass, vehicleInertia);
    btRigidBody::btRigidBodyConstructionInfo vehicleRigidBodyCI(vehicleMass, vehicleMotionState, vehicleChassisShape, vehicleInertia);

    vehicleRigidBody = new btRigidBody(vehicleRigidBodyCI);
    physicsWorld->dynamicsWorld->addRigidBody(vehicleRigidBody);

    // vehicleRigidBody->getWorldTransform
    // ^ use for rotation camera thingy

    //*  
    
    // Raycaster and the actual vehicle
    vehicleRayCaster = new btDefaultVehicleRaycaster(physicsWorld->dynamicsWorld);
    vehicle = new btRaycastVehicle(tuning, vehicleRigidBody, vehicleRayCaster);

    btVector3 wheelDirection = btVector3(0, -1, 0);
    btVector3 wheelAxle = btVector3(-0.75, 0, 0); //used to be -1
    btScalar suspensionRestLength = 0.6;
    btScalar wheelRadius = 0.35;
    btScalar wheelWidth = 0.3;
    btScalar suspensionStiffness = 40.0;
    btScalar dampingRelaxation = 4.3;
    btScalar dampingCompression = 2.4;
    btScalar frictionSlip = 10;
    btScalar rollInfluence = 0.2;

    //* Adding WHEELS to vehicle physics model !

    auto halfExtents = vehicleChassisShape->getHalfExtentsWithoutMargin();
    btScalar connectionHeight(5);

    btVector3 wheelConnectionPoint(halfExtents.x() - wheelRadius, connectionHeight, halfExtents.z() - wheelWidth);

    // Adds the front wheels
    vehicle->addWheel(wheelConnectionPoint * btVector3(2, 0, 1), wheelDirection, wheelAxle, suspensionRestLength, wheelRadius, tuning, true);

    vehicle->addWheel(wheelConnectionPoint * btVector3(-2, 0, 1), wheelDirection, wheelAxle, suspensionRestLength, wheelRadius, tuning, true);

    // Adds the rear wheels
    vehicle->addWheel(wheelConnectionPoint * btVector3(2, 0, -1), wheelDirection, wheelAxle, suspensionRestLength, wheelRadius, tuning, false);

    vehicle->addWheel(wheelConnectionPoint * btVector3(-2, 0, -1), wheelDirection, wheelAxle, suspensionRestLength, wheelRadius, tuning, false);

    for (int i = 0; i < vehicle->getNumWheels(); i++)
    {
        btWheelInfo &wheel = vehicle->getWheelInfo(i);
        
        // Larger 
        //wheel.m_chassisConnectionPointCS = wheelConnectionPoint;
        
         wheel.m_suspensionStiffness = suspensionStiffness;
         wheel.m_wheelsDampingRelaxation = dampingRelaxation;
         wheel.m_wheelsDampingCompression = dampingCompression;
         wheel.m_wheelsDampingCompression = btScalar(0.3) * 2 * btSqrt(wheel.m_suspensionStiffness); // btScalar(0.8);
         wheel.m_wheelsDampingRelaxation = btScalar(0.5) * 2 * btSqrt(wheel.m_suspensionStiffness);  // 1;
        
        // Larger friction slips will result in better handling
        wheel.m_frictionSlip = frictionSlip;
        wheel.m_rollInfluence = rollInfluence;

    }

    vehicleRigidBody->setActivationState(DISABLE_DEACTIVATION);

//! Experimental
// vehicleRigidBody->setLinearVelocity(btVector3(0, 0, 0));
// vehicleRigidBody->setAngularVelocity(btVector3(0, 0, 0));

    physicsWorld->dynamicsWorld->addVehicle(vehicle);

    // Vehicle setup:
    engineForce = 0.0;
    vehicleSteering = 0.0;
    steeringIncrement = 0.04;
    steeringClamp = 0.45;
    brakeForce = 0.0;
}

void VehiclePhysics::ApplyEngineForce(float force)
{
    engineForce = force;

    // Rear Wheel Drive

    vehicle->applyEngineForce(engineForce, 2);
    vehicle->applyEngineForce(engineForce, 3);
    // TODO: Add any Bullet physics code here that applies this force
}

void VehiclePhysics::ApplySteer(float steerIncr)
{
    if (steerIncr != 0)
    {
        // Increment or decrement steering based on steerIncr
        vehicleSteering += steerIncr;

        // Clamp the steering value to make sure it's within [-steeringClamp, steeringClamp]
        if (vehicleSteering > steeringClamp) {
            vehicleSteering = steeringClamp;
        } else if (vehicleSteering < -steeringClamp) {
            vehicleSteering = -steeringClamp;
        }
    }
    else
    {
        // Tend the steering value back to zero if steerIncr is 0
        if (vehicleSteering > steeringIncrement) {
            vehicleSteering -= steeringIncrement;
        } else if (vehicleSteering < -steeringIncrement) {
            vehicleSteering += steeringIncrement;
        } else {
            vehicleSteering = 0; // Close enough to zero we can set it directly
        }
    }

    // Apply the steering value to the front wheels
    vehicle->setSteeringValue(vehicleSteering, 0);
    vehicle->setSteeringValue(vehicleSteering, 1);
}


void VehiclePhysics::Brake(float force)
{
    brakeForce = force;
    vehicle->setBrake(brakeForce, 2);
    vehicle->setBrake(brakeForce, 3);

    // TODO: Add Bullet code here to apply brake
}

void VehiclePhysics::Update()
{
    // TODO: Code to update vehicle's state
}

btTransform VehiclePhysics::GetTransform() const
{
    // Returns the current transform (position & rotation) of the vehicle
    return vehicleRigidBody->getWorldTransform();
}

void VehiclePhysics::printState()
{
    btVector3 velocity = vehicleRigidBody->getLinearVelocity();
    btVector3 position = vehicleRigidBody->getWorldTransform().getOrigin();

    printf("Vehicle Velocity (XYZ): %.2f, %.2f, %.2f | Position (XYZ): %.2f, %.2f, %.2f | Steer: %.2f \n",
           velocity.getX(), velocity.getY(), velocity.getZ(),
           position.getX(), position.getY(), position.getZ(), vehicle->getSteeringValue(0));
}
Advertisement

Why do your wheels spin the wrong way? Check the axis directions.

This topic is closed to new replies.

Advertisement