英文:
Air Resistance In this simulation causes the velocity to rise drastically
问题
我遇到的问题是,我正在尝试为这个基本物理模拟(Java [Processing])中的对象添加拖力,但一旦我添加了适当的公式,对象的速度在相反方向上急剧增加。当然,问题在于拖动力由于某种原因被计算得过高,但我不确定为什么会发生这种情况,因为我正在使用真实世界的方程。
void setup() {size(1280, 720);}
class Circle {
float x, y, r, m, dx, dy, ax, ay, fx, fy;
Circle(float xPos, float yPos, float Radius, float Mass) {
x = xPos;
y = yPos;
r = Radius;
m = Mass;
}
void ADD_DRAG() {
fx -= 0.5 * 1.225 * dx * dx * 0.5 * r * PI;
fy -= 0.5 * 1.225 * dy * dy * 0.5 * r * PI;
}
void update() {
ADD_DRAG();
ax = fx / m;
ay = fy / m;
dx += ax / frameRate;
dy += ay / frameRate;
x += dx / frameRate;
y += dy / frameRate;
}
}
Circle[] SceneObjects = {new Circle(50, 50, 20, 20000), new Circle(50, 50, 2, 20)};
void draw() {
background(51);
for (Circle c : SceneObjects) {
c.update();
circle(c.x * 3, c.y * 3, c.r * 3);
}
}
void mouseClicked() {
if (SceneObjects[1].fx != 2000)
SceneObjects[1].fx = 2000;
else
SceneObjects[1].fx = 0;
}
这是代码,本质上有一个 Circle 类,它存储对象的属性,然后应用的力在每个绘制循环中更新。mouseClicked 函数只是用于通过向对象添加力进行测试。非常感谢任何帮助!我使用的数学公式有:
- 重新排列 F=ma 得到
ax = fx / m;
- 加速度 * 时间 = 速度 得到
dx += ax / frameRate;
(其中 frameRate 是时间的倒数) - 距离 = 速度 * 时间,用于
x += dx / frameRate;
(与上述类似) - 对于拖力,我使用的是这个方程 https://www.grc.nasa.gov/WWW/K-12/rocket/drageq.html,并添加了常数,如空气密度等。
英文:
The issue I have is that I'm attempting to add drag to an object in this basic physics simulation (Java [Processing]), but once I add the appropriate formula, it causes the objects velocity to increase drastically in the opposite direction. Of course the problem is that drag for some reason is being calculated too high but I'm not sure why thats happening as I'm using the real world equation.
void setup(){size(1280,720);}
class Circle{
float x,y,r,m,dx,dy,ax,ay,fx,fy;
Circle(float xPos, float yPos, float Radius, float Mass){
x = xPos;
y = yPos;
r = Radius;
m = Mass;
}
void ADD_DRAG(){
fx -= 0.5 * 1.225 * dx * dx * 0.5 * r * PI;
fy -= 0.5 * 1.225 * dy * dy * 0.5 * r * PI;
}
void update(){
ADD_DRAG();
ax = fx / m;
ay = fy / m;
dx += ax / frameRate;
dy += ay / frameRate;
x += dx / frameRate;
y += dy / frameRate;
}
}
Circle[] SceneObjects = {new Circle(50,50,20,20000),new Circle(50,50,2,20)};
void draw(){
background(51);
for (Circle c : SceneObjects){
c.update();
circle(c.x * 3,c.y * 3,c.r * 3);
}
}
void mouseClicked(){
if(SceneObjects[1].fx != 2000)
SceneObjects[1].fx = 2000;
else
SceneObjects[1].fx = 0;
}
This is the code, essentially there is a Circle class which stores the objects properties and then the forces applies are updated each draw loop. The mouseClicked void is just for testing by adding a force to the objects. All and any help is appreciated, thanks!
Maths I am Using:
Rearranged F=ma for ax = fx / m;
Acceleration * time = Speed for dx += ax / frameRate;
(frameRate is 1/time)
Distance = Speed * time = for x += dx / frameRate;
(same as above)
For drag im using this equation https://www.grc.nasa.gov/WWW/K-12/rocket/drageq.html with the constants eg air density etc added as seen.
答案1
得分: 2
有几个地方出了问题。
你没有给我们数字(或者一个最小完整示例),但向量代数有误。
是的,加速度是 f = -kv2,以及 |v|2 = vx2 + vy2,但这并不意味着你可以将 f 分解成 fx=kvx2 和 fy=kvy2。不仅你的大小计算错误,而且你的加速度现在(通常情况下)与运动的方向不对齐;你的抛物线运动会倾向于朝着坐标轴之间的对角线弯曲(例如 x=y)。
另外,你的代码总是给出负 x 和负 y 方向的加速度。如果你的抛物体碰巧从那个方向开始运动,你的版本的空气阻力会使它加速。
最后,你的时间间隔可能过大。
有一个更好的方法。微分方程是 v' = -k v|v|,而精确解是 v = (1/kt) z,(选择合适的起始时间)其中 z 是单位方向向量。(我不知道如何在字母上方放一个符号。)这导致 v(t) = (1/t)v(t=1.0)
所以你可以要么计算一个虚构的时间 t0,并使用 1/(kt) 计算每个新速度,要么可以根据前一个速度计算新速度:vn+1 = vn/(kd vn + 1),其中 d 是时间间隔。(然后当然你还需要适当地将 v 分解为 vx 和 vy。)
如果你对向量代数不熟悉,这可能会看起来很困惑,但是如果不学习基础知识,你无法使空气阻力模拟正常工作。
英文:
There are a couple of things wrong here.
You haven't given us numbers (or a minimal complete example), but the vector algebra is off.
Yes, the acceleration is f = -kv<sup>2</sup>, and |v|<sup>2</sup> = v<sub>x</sub><sup>2</sup> + v<sub>y</sub><sup>2</sup>, but that doesn't mean that you can decompose f into f<sub>x</sub>=kv<sub>x</sub><sup>2</sup> and f<sub>y</sub>=kv<sub>y</sub><sup>2</sup>. Not only is your magnitude off, but your acceleration is now not (in general) aligned with the motion; the path of your projectile will tend to curve toward a diagonal between the axes (e.g. x=y).
Also, your code always gives acceleration in the negative x and negative y directions. If your projectile happens to start out going that way, your version of air resistance will speed it up.
Finally, your time interval may simply be too large.
There is a better way. The differential equation is v' = -k v|v|, and the exact solution is v = (1/kt) z, (with appropriate choice of the starting time) where z is the unit direction vector. (I don't know how to put a caret over a letter.) This leads to v(t) = (1/t)v(t=1.0)
So you can either work out a fictional time t<sub>0</sub> and calculate each new velocity using 1/(kt), or you can calculate the new velocity from the previous velocity: v<sub>n+1</sub> =v<sub>n</sub>/(kd v<sub>n</sub> + 1), where d is the time interval. (And then of course you have to decompose v into v<sub>x</sub> and v<sub>y</sub> properly.)
If you're not familiar with vector algebra, this may seem confusing, but you can't get an air-resistance sim to work without learning the basics.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论