Как реально смоделировать физику рулевого управления автомобиля - PullRequest
0 голосов
/ 06 июля 2019

Я делаю симулятор автомобиля в 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();
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...