简体   繁体   English

模拟旋转angular转速

[英]Simulation of the rotation angular speed

I would like to be able to simulate the movement of the body on a "carousel" with respect to physics.我希望能够在物理方面模拟“旋转木马”上的身体运动。 (centripetal, centrifugal force, angular speed). (向心,离心力,angular转速)。 Below is some sample code.下面是一些示例代码。

 <.DOCTYPE html> <html> <head> <script> var rotate = Math;PI / 180; var ballRotation = 1. function drawthis() { var friction = 0;5. context,setTransform(1, 0, 0, 1, 0; 0). context,clearRect(0, 0. cvs,width. cvs;height). context,translate(350; 350). context;rotate(rotate). context;beginPath(). context,arc(1, 1, 12, 0. 2 * Math,PI; false). context;fill(). context;beginPath(). context,arc(0, 0, 150, 0. Math,PI * 2; false). context;lineWidth = 6. context;stroke(); motion = ballRotation - friction; rotate += motion; requestAnimationFrame(drawthis). } function init() { cvs = document;getElementById("canvas"). context = cvs;getContext("2d"). context,clearRect(0, 0. context,width. context;height). context;fillStyle = "#ff0000"; requestAnimationFrame(drawthis); } </script> </head> <body onload="init()"> <canvas id="canvas" width="800" height="800"></canvas> </body> </html>

I mean something like this我的意思是这样的

Ball on a turn table转台上的球

Below you will find a simple simulation of a point sliding on a turning wheel.下面你会发现一个点在转轮上滑动的简单模拟。 The point represents the contact point of a ball.该点表示球的接触点。

The simulation ignores the fact that the ball can roll, or has mass.模拟忽略了球可以滚动或有质量的事实。

The ball slides via a simple friction model, where friction is a scalar value applied to the difference between the balls speed vector, and the speed of the wheel at the point under the ball.球通过简单的摩擦力滑动 model,其中摩擦力是一个标量值,应用于球速度矢量与球下方点的车轮速度之间的差值。

There is only 1 force involved.只涉及 1 个力。 It is the force tangential to the vector from the ball to the wheel center, subtracted by the ball movement vector and then multiplied by the friction coefficient.它是与从球到轮中心的矢量相切的力,减去球运动矢量,然后乘以摩擦系数。

For details on how this is calculated see comments in the function ball.update()有关如何计算的详细信息,请参阅 function ball.update()中的注释

Notes笔记

  • That if the ball starts at the dead center of the wheel nothing will happen.如果球从车轮的死点开始,什么都不会发生。

  • I could not workout if it was the path of the ball you wanted or just the simulation of the ball, so I added both.如果它是你想要的球的路径或者只是球的模拟,我无法锻炼,所以我添加了两者。

  • The ball resets after it leaves the wheel.球离开轮子后会重置。

  • The wheel is marked with text and center cross so its rotation can be seen.车轮标有文字和中心十字,因此可以看到它的旋转。

 const ROTATE = Math.PI / 50; const WHEEL_SIZE = 0.6; Math.rand = (min, max) => Math.random() * (max - min) + min; Math.randPow = (min, max, p) => Math.random() ** p * (max - min) + min; var friction = 0.35; const ctx = canvas.getContext("2d"); requestAnimationFrame(mainLoop); ctx.font = "30px arial"; ctx.textAlign = "center"; scrollBy(0, canvas.height / 2 - canvas.height / 2 * WHEEL_SIZE); function mainLoop() { ctx.setTransform(1, 0, 0, 1, 0, 0); ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height); wheel.update(); ball.update(wheel, arrow); wheel.draw(); path.draw(); ball.draw(); arrow.draw(ball); requestAnimationFrame(mainLoop); } const path = Object.assign([],{ draw() { ctx.setTransform(1, 0, 0, 1, 0, 0); ctx.strokeStyle = "#F00"; ctx.lineWidth = 1; ctx.beginPath(); for (const p of this) { ctx.lineTo(px, py) } ctx.stroke(); }, reset() { this.length = 0 }, add(point) { this.push({x: point.x, y: point.y}); if (this.length > 1000) { // prevent long lines from slowing render this.shift() } } }); const arrow = { dx: 0,dy: 0, draw(ball) { if (this.dx || this.dy) { const dir = Math.atan2(this.dy, this.dx); // len is converted from frame 1/60th second to seconds const len = Math.hypot(this.dy, this.dx) * 60; const aXx = Math.cos(dir); const aXy = Math.sin(dir); ctx.setTransform(aXx, aXy, -aXy, aXx, ball.x, ball.y); ctx.beginPath(); ctx.lineTo(0,0); ctx.lineTo(len, 0); ctx.moveTo(len - 4, -2); ctx.lineTo(len, 0); ctx.lineTo(len - 4, 2); ctx.strokeStyle = "#FFF"; ctx.lineWidth = 2; ctx.stroke(); } } }; const ball = { x: canvas.width / 2 + 4, y: canvas.height / 2, dx: 0, // delta pos Movement vector dy: 0, update(wheel, arrow) { // get distance from center const dist = Math.hypot(wheel.x - this.x, wheel.y - this.y); // zero force arrow arrow.dx = 0; arrow.dy = 0; // check if on wheel if (dist < wheel.radius) { // get tangent vector direction const tangent = Math.atan2(this.y - wheel.y, this.x - wheel.x) + Math.PI * 0.5 * Math.sign(wheel.dr); // get tangent as vector // which is distance times wheel rotation in radians. const tx = Math.cos(tangent) * dist * wheel.dr; const ty = Math.sin(tangent) * dist * wheel.dr; // get difference between ball vector and tangent vector scaling by friction const fx = arrow.dx = (tx - this.dx) * friction; const fy = arrow.dy = (ty - this.dy) * friction; // Add the force vector this.dx += fx; this.dy += fy; } else if (dist > wheel.radius * 1.7) { // reset ball // to ensure ball is off center use random polar coord const dir = Math.rand(0, Math.PI * 2); const dist = Math.randPow(1, 20, 2); // add bias to be close to center this.x = canvas.width / 2 + Math.cos(dir) * dist; this.y = canvas.height / 2 + Math.sin(dir) * dist; this.dx = 0; this.dy = 0; path.reset(); } // move the ball this.x += this.dx; this.y += this.dy; path.add(ball); }, draw() { ctx.fillStyle = "#0004"; ctx.setTransform(1, 0, 0, 1, this.x + 5, this.y + 5); ctx.beginPath(); ctx.arc(0, 0, 10, 0, 2 * Math.PI); ctx.fill(); ctx.fillStyle = "#f00"; ctx.setTransform(1, 0, 0, 1, this.x, this.y); ctx.beginPath(); ctx.arc(0, 0, 12, 0, 2 * Math.PI); ctx.fill(); ctx.fillStyle = "#FFF8"; ctx.setTransform(1, 0, 0, 1, this.x - 5, this.y - 5); ctx.beginPath(); ctx.ellipse(0, 0, 2, 3, -Math.PI * 0.75, 0, 2 * Math.PI); ctx.fill(); }, } const wheel = { x: canvas.width / 2, y: canvas.height / 2, r: 0, dr: ROTATE, // delta rotate radius: Math.min(canvas.height, canvas.width) / 2 * WHEEL_SIZE, text: "wheel", update() { this.r += this.dr }, draw() { const aXx = Math.cos(this.r); const aXy = Math.sin(this.r); ctx.setTransform(aXx, aXy, -aXy, aXx, this.x, this.y); ctx.fillStyle = "#CCC"; ctx.strokeStyle = "#000"; ctx.lineWidth = 6; ctx.beginPath(); ctx.arc(0, 0, this.radius, 0, 2 * Math.PI); ctx.stroke(); ctx.fill(); ctx.strokeStyle = ctx.fillStyle = "#aaa"; ctx.lineWidth = 2; ctx.beginPath(); ctx.lineTo(-20,0); ctx.lineTo(20,0); ctx.moveTo(0,-20); ctx.lineTo(0,20); ctx.stroke(); ctx.fillText(this.text, 0, this.radius - 16); }, }
 <canvas id="canvas" width="300" height="300"></canvas>

Centripetal force向心力

Centripetal is the force towards the center of the turning wheel.向心力是朝向转轮中心的力。 However because the ball is sliding the force calculated is not a centripetal force.然而,由于球在滑动,计算的力不是向心力。

You can calculate the centripetal force by scaling the vector from the ball to the center by the dot product of the "vector to center" dot "force vector"您可以通过“向量到中心”点“力向量”的点积来缩放从球到中心的向量来计算向心力

The force vector on the ball is shown as a white arrow.球上的力矢量显示为白色箭头。 The arrows size is the force as acceleration in pixels per second.箭头大小是以每秒像素为单位的加速度。

The vector is towards the center but will never point directly at the center of the wheel.矢量朝向中心,但永远不会直接指向轮子的中心。

Approximation近似

This simulation is an approximation.这个模拟是一个近似值。 You will need an understanding of calculus and differential equations to get closer to reality.您需要了解微积分和微分方程才能更接近现实。

Using a more complex simulation would only be noticeable if the friction was very close or at 1 and it is easier then to just fix the ball to the wheel, scaling the position from center by an inverse power of the friction coefficient.只有当摩擦力非常接近或为 1 时,使用更复杂的模拟才会引人注目,并且更容易将球固定到车轮上,通过摩擦系数的反幂从中心缩放 position。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM