像许多关于这个主题的帖子一样,我也正忙于为自己编写一个准确的模拟器,用于在 2D 引力场中的物体运动。
我很早就决定选择Velocity Verlet积分,因为我希望我的物体保持稳定的轨道并节省能量,即使时间步长相当大。那么,问题可能是什么?
好吧,到目前为止,一切似乎都正常运行,除了一个组件。当我尝试计算某个距离的稳定轨道的正确速度时,所得速度会将它们发送到奇数椭圆轨道,每次都会迅速增加幅度。
因此,首先,以下是确定对象在场景中的下一个位置、速度和加速度的方法:(目标 C)
加速度:
-(CGVector)determineAccelerationFor:(SKObject *)object
{ // Ok, let's find Acceleration!
CGVector forceVector = (CGVector){0,0}; // Blank vector that we will add forces to
for (SKObject *i in self.sceneObjects)
{
if (![i isEqual:object]) // Just make sure we're not counting ourselves here
{
CGPoint distance = [self getDistanceBetween:i.position And:object.position];
float hypotenuse = sqrtf(powf(distance.x, 2)+ powf(distance.y, 2));
float force = ((self.gravity * object.mass * i.mass)/powf(hypotenuse, 3));
float xMagnitude = (force * distance.x);
float yMagnitude = (force * distance.y);
forceVector.dx += xMagnitude;
forceVector.dy += yMagnitude;
}
}
CGVector acceleration = (CGVector){forceVector.dx/object.mass, forceVector.dy/object.mass};
return acceleration;
}
酷,所以基本上,我只是拿一个物体,将每个其他物体施加在它上面的所有其他力相加,然后将 X 和 Y 因子除以当前物体的质量以获得加速度!
接下来是速度。在这里,我使用以下等式:
它的方法也很简单:
-(CGVector)determineVelocityWithCurrentVelocity:(CGVector)v OldAcceleration:(CGVector)ao NewAcceleration:(CGVector)a
{
float xVelocity = (v.dx + ((ao.dx + a.dx)/2) * self.timeStep);
float yVelocity = (v.dy + ((ao.dy + a.dy)/2) * self.timeStep);
CGVector velocity = (CGVector){xVelocity,yVelocity};
return velocity;
}
最后,定位!这个方程是:
并通过以下方法确定!
-(CGPoint)determinePositionWithCurrentPosition:(CGPoint)x CurrentVelocity:(CGVector)v OldAcceleration:(CGVector)ao
{
float xPosition = (x.x + v.dx * self.timeStep + ((ao.dx * powf(self.timeStep, 2))/2));
float yPosition = (x.y + v.dy * self.timeStep + ((ao.dy * powf(self.timeStep, 2))/2));
CGPoint position = (CGPoint){xPosition,yPosition};
return position;
}
这都是从下面的方法调用的!!
-(void)refreshPhysics:(SKObject *)object
{
CGPoint position = [self determinePositionWithCurrentPosition:object.position CurrentVelocity:object.velocity OldAcceleration:object.acceleration]; // Determine new Position
SKAction *moveTo = [SKAction moveTo:position duration:0.0];
[object runAction:moveTo]; // Move to new position
CGVector acceleration = [self determineAccelerationFor:object]; // Determine acceleration off new position
CGVector velocity = [self determineVelocityWithCurrentVelocity:object.velocity OldAcceleration:object.acceleration NewAcceleration:acceleration];
NSLog(@"%@ Old Velocity: %f, %f",object.name,object.velocity.dx,object.velocity.dy);
NSLog(@"%@ New Velocity: %f, %f\n\n",object.name,velocity.dx,velocity.dy);
[object setAcceleration:acceleration];
[object setVelocity:velocity];
}
好的,以上这些方法决定了对象在场景中的移动方式。现在回到最初的问题,实现稳定轨道的永远存在的问题!
为了确定一个物体维持轨道的速度,我使用以下等式:
我实现如下:
-(void)setObject:(SKObject *)object ToOrbit:(SKObject *)parent
{
float defaultSeparation = 200;
// Move Object to Position at right of parent
CGPoint defaultOrbitPosition = (CGPoint){parent.position.x + (parent.size.width/2)+ defaultSeparation,parent.position.y};
[object setPosition:defaultOrbitPosition];
// Determine Orbital Velocity
float velocity = sqrtf((self.gravity * parent.mass)/(parent.size.width/2+defaultSeparation));
CGVector vector = (CGVector){0,velocity};
[object setVelocity:vector];
}
出于某种原因,尽管如此,我得到了糟糕的结果。这是一些输出:
信息:
重力(常数)= 1000(用于测试目的)
质量(父)= 5000 单位
质量(卫星)= 1 个单位
分离 = 224 像素
它确定为了让卫星绕父轨道运行,速度为:
149.403580 像素/timeStep
是必须的。这在我的计算器上进行了检查。
所以这让我对可能出了什么问题感到有些困惑。我记录了有关新速度和位置的所有输出,它确实使用了我设置的速度,但这似乎并没有什么不同。如果有人可以帮助发现这里出了什么问题,我将不胜感激。
如果有人认为我遗漏了某些内容,请告诉我,我将立即对其进行编辑。谢谢!