27.05.2020, 10:30
|
Новичок на форуме
|
|
Регистрация: 27.05.2020
Сообщений: 8
|
|
Помогите создать математический маятник основанный на физических приципах
Задать параметры маятника: массу, длину стержня, параметры сопротивления среды. Управляющее воздействие пока принять нулевым. Выписать уравнение движения и его конечно-разностную форму, удобную для программной реализации.
При помощи элементов управления (кнопки, слайдеры) обеспечить начальное отклонение маятника от вертикального положения на произвольный допустимый угол.
Дальнейшее свободное движение маятник должен совершать в соответствии с физическими принципами - конечно-разностной формой системы заданных дифференциальных уравнений. Имитировать режим реального времени требуется контролем постоянства интервала времени между последовательными расчетными состояниями маятника
Код:
|
<!DOCTYPE html>
<html>
<meta charset="UTF-8">
<title>Mayatnik</title>
<h1 style = 'text-align: center'> Маятник </h1>
<head>
<link href="http://nitinhayaran.github.io/jRange/jquery.range.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="http://nitinhayaran.github.io/jRange/jquery.range.js"></script>
<style>
#canvas
{
display: block;
margin: 0 auto;
padding: 0;
}
#polzunok
{
width: 300px;
height: 40px;
display: block;
margin: 0 auto;
}
.quantity-block
{
display: block;
margin:1px 1px 3px 360px;
padding: 10px 10px 5px 0px;
font-size: 20px;
}
.button
{
background-color: white;
color: black;
border: 2px solid #555555;
padding: 15px 20px;
text-align: center;
text-decoration: none;
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
margin: 4px 520px;
cursor: pointer;
height: 100%;
width: 250px;
border-radius: 8px;
}
</style>
</head>
<div id="center">
<canvas id=canvas width="350" height="350" style="background: #eee"></canvas>
</div>
<div class = "quantity-block">
<label > Масса шарика: </label>
<input name="massa" type="number" />
<label > Длина маятника: </label>
<input name="dlina" type="number" />
<br>
 
<label > Коэффициент сопротивления окружающей среды: </label>
<input name="kf" type="number" />
<br>
 
 
 
 
<label > Текущий угол отклонения: </label>
<input name="angle0" type="number" />
<br>
</div>
<h2 style='text-align: center'> Изменение начальногоугла маятника(в градусах)</h2>
<div id ="polzunok">
<input class="range-slider" type="hidden" value="0" />
</div>
<script type = "text/javascript">
$('.range-slider').jRange({
from: -90 ,
to: +90,
step: 1,
scale: [-90,0,+90],
format: '%s',
width: 300,
showLabels: true,
snap: true
});
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
requestAnimationFrame(draw);
function draw() {
var g =9.8;
var angle = $("#polzunok")[0].children[0].value / 180 * Math.PI+(Math.PI*1/2);
var size = Math.min(canvas.width, canvas.height);
var ox = (canvas.width / 2) >> 0;
var rPend = size * 0.45;
var rBall = size * 0.05;
var x = (ox - rPend * Math.cos(angle)) | 0;
var y = (rPend * Math.sin(angle) + 2) | 0;
context.clearRect(0, 0, canvas.width, canvas.height);
drawBg(context, canvas.width, canvas.height);
drawBase(context, canvas.width);
drawLine(context, ox, x, y);
drawBall(context, x, y, rBall);
requestAnimationFrame(draw);
}
function drawBg(context, w, h) {
context.fillStyle = "rgba(255,255,255,0.51)";
context.fillRect(0, 0, w, h);
context.fillStyle = "black";
}
function drawBase(context, w) {
context.save();
context.moveTo(0, 2);
context.lineTo(w, 2);
context.lineWidth = 3;
context.stroke();
context.restore();
}
function drawLine(context, ox, x, y) {
context.save();
context.moveTo(ox, 0);
context.lineTo(x, y);
context.lineWidth = 3;
context.stroke();
context.restore();
}
function drawBall(context, x, y, rBall) {
context.save();
context.beginPath();
context.arc(x, y, rBall, 0, Math.PI * 2);
context.fill();
context.restore();
}
requestAnimationFrame(draw);
function main ()
{
let intervalID = setInterval("qwert()", 1);
}
</script>
<a href="#" class="button" onclick="main()" >Моделировать </button>
</div>
</html> |
|
|
28.05.2020, 04:11
|
|
Профессор
|
|
Регистрация: 20.12.2009
Сообщений: 1,714
|
|
Elizaveta99, эту систему дифференциальных уравнении можно решить методом Эйлера-Коши.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Маятник</title>
<style>
body {
text-align: center;
max-width: 50em;
margin: 0 auto;
padding: 8px;
}
h1, h2 {
text-align: center;
}
#canvas {
display: block;
margin: 0 auto;
padding: 0;
background: #f1f5f5;
pointer-events: none;
}
.quantity-block {
display: grid;
grid-template-columns: 1fr 1fr;
align-items: flex-start;
gap: 1em;
padding: 10px;
}
.quantity-block label {
text-align: end;
}
.button {
background-color: white;
color: black;
border: 2px solid #555555;
padding: 15px 20px;
text-align: center;
cursor: pointer;
border-radius: 8px;
}
input, select, button {
font: inherit;
}
</style>
</head>
<body>
<h1>Маятник</h1>
<canvas id="canvas" width="350" height="350"></canvas>
<div class="quantity-block">
<label> Масса шарика</label>
<input name="m" type="number" value="1" step="any">
<label>Длина маятника</label>
<input name="l" type="number" value="0.5" step="any">
<label>Коэффициент сопротивления окружающей среды</label>
<input name="kf" type="number" value="2" step="any">
<label>Начальный угол маятника</label>
<input name="α" type="range" value="1" min="-1.57" max="1.57" step="any">
</div>
<button class="button" onclick="toggleSimulation();">Моделировать</button>
<script>
var canvas = $("#canvas");
var context = canvas.getContext("2d");
context.lineWidth = 3;
var WIDTH = canvas.width;
var HEIGHT = canvas.height;
var α = 0;
var ω = 0;
var m = 0.1;
var g = 9.8;
var l = 0.5;
var kf = 1;
var M = 0;
var isSimulationOn = false;
var lastT = performance.now();
function $(selector, context) {
return (context || document).querySelector(selector);
}
function $$(selector, context) {
return Array.from((context || document).querySelectorAll(selector));
}
function draw(t) {
requestAnimationFrame(draw);
var dt = Math.min(1 / 24, (t - lastT) / 1000);
lastT = t;
if(isSimulationOn) {
α += dt * ω;
ω += dt * (- g / l * Math.sin(α) - kf * l / m * ω * ω * Math.sign(ω) + M / m / l / l);
}
var angle = α + Math.PI / 2;
var size = Math.min(WIDTH, HEIGHT);
var ox = WIDTH / 2;
var rPend = size * 0.45 * Math.tanh(0.5 * l);
var rBall = size * 0.05 * Math.tanh(0.5 * m);
var x = ox - rPend * Math.cos(angle);
var y = rPend * Math.sin(angle) + 2;
context.clearRect(0, 0, WIDTH, HEIGHT);
// draw a ball
context.beginPath();
context.arc(x, y, rBall, 0, Math.PI * 2);
context.fill();
// draw a base and a string
context.moveTo(0, 2);
context.lineTo(WIDTH, 2);
context.moveTo(ox, 0);
context.lineTo(x, y);
context.stroke();
}
function updateVariables() {
$$(".quantity-block input[name]").forEach(function (input) {
assignVariable(input.name, input.value);
});
}
function assignVariable(name, value) {
if (name in window) {
window[name] = Number(value);
if (name === "α") ω = 0;
if (name === "l" || name === "m") window[name] = Math.max(0.01, window[name]);
}
}
function toggleSimulation() {
isSimulationOn = !isSimulationOn;
$(".button").textContent = isSimulationOn ? "Остановить" : "Моделировать"
updateVariables();
}
$(".quantity-block").addEventListener("input", function (event) {
var input = event.target;
if (input.matches("input[name]")) {
assignVariable(input.name, input.value);
}
});
requestAnimationFrame(draw);
toggleSimulation();
</script>
</body>
</html>
Последний раз редактировалось Malleys, 29.05.2020 в 08:02.
Причина: Добавил визуализацию массы и длины маятника, а также проверку вводимых значении
|
|
29.05.2020, 06:19
|
Новичок на форуме
|
|
Регистрация: 27.05.2020
Сообщений: 8
|
|
Здравствуйте, код прекрасный, но он не реагирует на изменение длинны маятника, не отображает ее в canvas это как-то можно исправить или я чего-то не правильно нажимаю?
|
|
29.05.2020, 07:37
|
|
Профессор
|
|
Регистрация: 20.12.2009
Сообщений: 1,714
|
|
Сообщение от Elizaveta99
|
но он не реагирует на изменение длинны маятника, не отображает ее в canvas это как-то можно исправить или я чего-то не правильно нажимаю?
|
Длина применяется и участвует в вычислении, что отражается на скорости колебания. (Например, длина маятника 10 метров является причиной того, что маятник дольше падает, чем, например, при длине в 1 метр) Однако на картинке длина маятника при отрисовке не учитывается, но можно сделать...
ЕЩЁ Добавил в пример выше визуализацию массы и длины маятника (вычисляется пропорционально значению гиперболического тангенса, чтобы всё влезло на картинку), а также проверку вводимых значении, чтобы они были не менее 0.01 (метод Эйлера-Коши плохо работает со значениями очень близкими к 0)
Последний раз редактировалось Malleys, 29.05.2020 в 08:00.
|
|
29.05.2020, 08:32
|
Новичок на форуме
|
|
Регистрация: 27.05.2020
Сообщений: 8
|
|
Спасибо вам большое, очень помогли
|
|
30.05.2020, 10:00
|
Новичок на форуме
|
|
Регистрация: 27.05.2020
Сообщений: 8
|
|
А вы бы не могли объяснить как подключить сюда пид регулятор что- бы удерживать желаемый угол, под которым маятник будет колебаться?
|
|
|
|