如何真实地模拟汽车转向物理

时间:2019-07-06 18:50:38

标签: javascript physics

我正在用Javascript进行汽车模拟,并且我正在使用该网站来帮助我进行物理研究:http://www.asawicki.info/Mirror/Car%20Physics%20for%20Games/Car%20Physics%20for%20Games.html

模拟的当前进度可以在我的网站上看到: https://cloudynet.tk/projects/car-sim/code.html

我遇到的问题是汽车转向物理学。我设法使低速转向正常工作,但是高速转向(引入了侧向力)很难实现。我了解滑移角如何影响横向力,但在我的仿真中,它的效果不是很好。我想知道横向力的实现是正确的还是代码有问题?另外,我不太了解纵向力和横向力是影响单个速度矢量还是分成两个“方向”矢量。

这是我当前的物理功能(可以在网站上查看整个代码):

applyPhysics() {
    // Get car direction vector

    let direction = new Vector(1, 0);
    direction = Vector.rotate(direction, this.carAngle);

    // LONGITUDINAL FORCES

    // Traction forces
    let tractionForce = direction.copy(); // Traction force (engine power)
    if (this.engineForce) {
        tractionForce.mult(this.engineForce);
    }
    else if (this.brakingForce) {
        tractionForce.mult(-this.brakingForce);
    }

    // Frictional forces

    let dragForce = this.velocity.copy(); // Air resistance force
    dragForce.mult(this.velocity.getMag())
    dragForce.mult(-this.drag);

    let rollingResistanceForce = this.velocity.copy(); // Rolling resistance force (friction with ground)
    rollingResistanceForce.mult(-this.rrDrag);

    let netLongitudinalForce = tractionForce.copy(); // Total longitudinal force
    netLongitudinalForce.add(dragForce)
    netLongitudinalForce.add(rollingResistanceForce);

    // Calculate acceleration
    this.acceleration = netLongitudinalForce.copy();
    this.acceleration.div(this.mass);
    if (this.acceleration.getMag() < 0.001)
        this.acceleration = new Vector();

    // Calculate velocity
    let accelerationDelta = this.acceleration.copy();
    accelerationDelta.mult(dt);
    this.velocity.add(accelerationDelta);

    this.velDir = this.velocity.getDir();
    this.sideslipAngle = this.carAngle - this.velDir; // Calculate side slip angle

    if (this.speed > 20) { // High speed-turning
        // LATERAL FORCES

        let peakSlipAngle = 5;

        // Calculate slip angle for back wheel
        var c = this.wheels.baseline/2;
        var omegaC = this.angularVelocity*c;
        var longV = Math.cos(this.carAngle) * this.velocity.getMag();
        var latV = Math.sin(this.carAngle) * this.velocity.getMag();
        this.wheels.back.slipAngle = Math.atan(((latV - omegaC)/Math.abs(longV)) || 0);
        var backSlipDeg = deg(this.wheels.back.slipAngle)

        this.wheels.back.lateralForce = 5000*Math.sign(this.wheels.back.slipAngle);
        if (backSlipDeg < peakSlipAngle && backSlipDeg > -peakSlipAngle) {
            this.wheels.back.lateralForce = 5000*backSlipDeg/peakSlipAngle;
        } else {
            this.wheels.back.lateralForce = 5000*(1-((Math.abs(backSlipDeg)-peakSlipAngle)/500))*Math.sign(this.wheels.back.slipAngle);
        }

        // Calculate slip angle for front wheel
        var b = this.wheels.baseline/2;
        var omegaB = this.angularVelocity*b;
        var longV = Math.cos(this.wheels.front.slipAngle) * this.velocity.getMag();
        var latV = Math.sin(this.wheels.front.slipAngle) * this.velocity.getMag();
        this.wheels.front.slipAngle = Math.atan((((latV - omegaB)/Math.abs(longV)) || 0)-this.steeringAngle*Math.sign(longV));
        var frontSlipDeg = deg(this.wheels.front.slipAngle);

        this.wheels.front.lateralForce = 5000*Math.sign(this.wheels.front.slipAngle);
        if (frontSlipDeg < peakSlipAngle && frontSlipDeg > -peakSlipAngle) {
            this.wheels.front.lateralForce = 5000*frontSlipDeg/peakSlipAngle;
        } else {
            this.wheels.front.lateralForce = 5000*(1-((Math.abs(frontSlipDeg)-peakSlipAngle)/500))*Math.sign(this.wheels.front.slipAngle);
        }

        // Calculate cornering force
        this.corneringForce = this.wheels.back.lateralForce + Math.cos(this.steeringAngle) * this.wheels.front.lateralForce;

        // Calculate centripetal force
        this.centripetalForce = this.mass * (this.velocity.getMag() ** 2) / this.wheels.baseline/Math.sin(this.steeringAngle);

        var lateralDirection = new Vector(0, -1);
        lateralDirection = Vector.rotate(lateralDirection, this.carAngle);

        let lateralForce = lateralDirection.copy();
        lateralForce.mult(this.corneringForce);

        this.latAcceleration = lateralForce.copy();
        this.latAcceleration.div(this.mass);
        if (this.latAcceleration.getMag() < 0.001)
            this.latAcceleration = new Vector();

        let latAccelerationDelta = this.latAcceleration.copy();
        latAccelerationDelta.mult(dt);
        this.latVelocity.add(latAccelerationDelta);

        // Calculate position
        let latVelocityDelta = this.latVelocity.copy();
        latVelocityDelta.mult(dt);
        this.pos.add(latVelocityDelta);
    } else {
        this.velocity = Vector.rotate(this.velocity, this.carAngle - this.velDir); // Correct velocity based on car orientation
    }

    // Calculate position
    let velocityDelta = this.velocity.copy();
    velocityDelta.mult(dt);
    this.pos.add(velocityDelta);

    // Calculate speed
    this.speed = this.velocity.getMag();
}

0 个答案:

没有答案