Нужно сделать матиматический маятник с затухающими колебаниями JavaScript

У нас есть колебание математического маятника, но они не затухают. Нужно сохранить такой же вид кода, но добавить затухающие колебание. Желательно сделать, чтобы здесь использовался логарифмический декремент затухания или же реализовать через уравнение затухающих колебаний:

логарифмический декремент заутухания логарифмический декремент уравнения

let canvas = document.getElementById('Pendulum');
let ctx = canvas.getContext('2d');

const X = canvas.width;
const Y = canvas.height;
const X0 = Math.floor(X/2);
const Y0 = 0;
const GRID = 50;

drawGrid(GRID);

const R = 20;
const SCALE = 100;
const g = 9.81;

let l, phi0, omega, t = 0, T, lambda;

let raf;

//===============================================
function drawGrid() {
    ctx.clearRect(0, 0, X, Y);
    ctx.strokeStyle = "#00FF00";
    ctx.lineWidth = 0.5;
    let x, y;
    for (x=0; x<X; x+=GRID) {
        ctx.beginPath();
        ctx.moveTo(x, 0);
        ctx.lineTo(x, Y);
        ctx.closePath();
        ctx.stroke();
    }
    for (y=0; y<Y; y+=GRID) {
        ctx.beginPath();
        ctx.moveTo(0, y);
        ctx.lineTo(X, y);
        ctx.closePath();
        ctx.stroke();
    }
    ctx.strokeStyle = "#000000";
    ctx.beginPath();
    ctx.moveTo(X0, 0);
    ctx.lineTo(X0, Y);
    ctx.closePath();
    ctx.stroke();
}

//================================================
function drawPendulum(length, angle) {
    let x, y;
    ctx.lineWidth = 1;
    ctx.strokeStyle = "#000000";
    ctx.fillStyle = "#00FF00";
    x = X0 + Math.floor(length*SCALE*Math.sin(angle));
    y = Math.floor(length*SCALE*Math.cos(angle));
    ctx.beginPath();
    ctx.moveTo(X0, 0);
    ctx.lineTo(x, y);
    ctx.closePath();
    ctx.stroke();
    ctx.beginPath();
    ctx.arc(x, y, R, 0, Math.PI*2);
    ctx.closePath();
    ctx.fill();
    ctx.stroke();
}

//================================================
function oscilations() {
    let phi;
    drawGrid(GRID); 
    t += .05;
    phi = phi0 * Math.cos(omega*t);
    drawPendulum(l, phi);
    raf = window.requestAnimationFrame(oscilations);
}

//================================================
function go() {
    l = Number(document.getElementById('Length').value);
    phi0 = Number(document.getElementById('Angle').value) 
           * Math.PI/180;
    omega = Math.sqrt(g/1);
    drawPendulum(1, phi0);
    document.getElementById('stopButton').disabled = false;
    document.getElementById('goButton').disabled = true;
    document.getElementById('beginButton').disabled = false;
    oscilations();
}

//================================================
function stop() {
    window.cancelAnimationFrame(raf);
    document.getElementById('goButton').disabled = false;
    document.getElementById('stopButton').disabled = true; 
}

//================================================
function begin() {
    window.cancelAnimationFrame(raf);
    drawGrid(GRID);
    drawPendulum(l, phi0);
    document.getElementById('goButton').disabled = false;
    document.getElementById('stopButton').disabled = true;
}
header {
 border: 1px solid black;
}
.Container {
 display: grid;
 border: 1px solid black;
}
.box {
 border: 2px solid black;
 width: 400px;
 height: 66px;
 position: relative;
 left: 807px;
 top: -600px;
 color: red;
}

#Pendulum {
 display: inline-grid;
 border: 1px solid black;
}
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <link rel="stylesheet" href="styles.css" 
          type="text/css">
    <title></title>
</head>
<body>
    <header>
        <script type="text/javascript" src="whowroteit.js" >
        </script>
    </header>

    <div class="Container">
        <canvas id="Pendulum" width="800" height="600">
            <script type="text/javascript" src="pendulum.js">
            </script>
        </canvas>
    </div>
    <div class="box">
        <div claas = "Control1">
            <label lengthText = "length">Длина, м: </label>
            <input type="text" id="Length" value="4" />
        </div>
        <div class="Control2">
            <label angleText = "angle">Начальный кут, градусы: </label>
            <input type="text" id="Angle" value="10" />
        </div>
        <div class = "Control3">
            <button id = "goButton" onclick = "go();">Пуск</button>
            <button id = "stopButton" onclick = "stop();">Стоп</button>
            <button id = "beginButton" onclick = "begin();">Сначала</button>
        </div>
    </div>
</body>
</html>


Ответы (2 шт):

Автор решения: MBo

Применить затухание можно, введя экспоненциальный член, как, собственно, и показано на заглавной картинке

phi = phi0 * Math.cos(omega*t) * Math.exp(-lambda*t);

Лямбда для создания хорошо видимого эффекта в данных условиях должна быть порядка 0.1

→ Ссылка
Автор решения: Опан

Любой природный маятник колеблется, как результат того, что он имеет изначальную энергию, которая периодически преобразовывается из потенциальной в кинетическую и наоборот. Поэтому для имитации колебаний нужно использовать две основные переменные - p и k, значения которых будут соответствовать текущим уровням этих энергий. В тоже время, p показывает текущую степень отклонения маятника, а k показывает текущую скорость движения маятника.

Ещё для того, чтобы маятник затухал, необходимо учитывать его трение об ось. Поэтому используется коефициент трения kt, который показывает, какая часть от общей энергии поглощается трением при каждом шаге движения маятника. (в данном случае, одна тысячная) После того, как вся энергия постепенно иссякает, маятник останавливается.

let p = -1; // Текущий уровень потенциальной энергии
let k = 0; // Текущий уровень киннетической энергии
let razmah = 30; // Размах колебаний
let kt = 0.001 // Коефициент трения
setInterval(function(){
    document.querySelector('.mayatnik').style.transform = 'rotateZ(' + Math.floor(razmah * p) + 'deg) translateY(100px)';
    p += k;
    k +=(0 - p) / 30;
    razmah /= 1 + kt;
}, 100);
.mayatnik{
    height: 200px;
}
.osnovanie{
    position: absolute;
    left: 50%;
    width: 10px;
    height: 200px;
    border-radius: 5px;
    background: #811;
}
.kruglyashka{
    position: absolute;
    border-radius: 50%;
    background: black;
    width: 25px;
    height: 25px;
    left: calc(50% - 7px);
    top: 160px;
}
<div class=mayatnik>
    <div class=osnovanie></div>
    <div class=kruglyashka></div>
</div>

→ Ссылка