Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/339.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 摆锤模拟_Python_Pygame_Physics_Physics Engine - Fatal编程技术网

Python 摆锤模拟

Python 摆锤模拟,python,pygame,physics,physics-engine,Python,Pygame,Physics,Physics Engine,我试图在Pygame中编写单摆模拟。重点是我试图直接模拟摆锤上的力(重力和张力),而不是求解描述运动的微分方程。首先我写了一个函数,得到一个向量,旋转轴系统一个角度,然后返回这个向量在新的旋转轴系统中的分量;此函数的代码很好,工作正常 在模拟的每一个记号中,我通过摆锤和绳子之间的角度旋转重力向量,并得到新的分量——一个在绳子的方向上,另一个与绳子正交。张力和绳索方向上的分量相互抵消,因此只有正交分量才重要。在我计算它之后,我将加速度向量旋转回法向坐标系,然后积分。然而,结果的行为并不像预期的那样

我试图在Pygame中编写单摆模拟。重点是我试图直接模拟摆锤上的力(重力和张力),而不是求解描述运动的微分方程。首先我写了一个函数,得到一个向量,旋转轴系统一个角度,然后返回这个向量在新的旋转轴系统中的分量;此函数的代码很好,工作正常

在模拟的每一个记号中,我通过摆锤和绳子之间的角度旋转重力向量,并得到新的分量——一个在绳子的方向上,另一个与绳子正交。张力和绳索方向上的分量相互抵消,因此只有正交分量才重要。在我计算它之后,我将加速度向量旋转回法向坐标系,然后积分。然而,结果的行为并不像预期的那样。原因可能是什么

代码如下:

from __future__ import division
import copy
import pygame
import random
import math
import numpy as np
import time

clock = pygame.time.Clock()
pygame.init()
size = (width, height) = (600,500)
screen = pygame.display.set_mode(size)

def rotate(vector,theta):
    #rotate the vector by theta radians around the x-axis
    Vx,Vy = vector[0],vector[1]
    cos,sin = math.cos(theta),math.sin(theta)
    newX,newY = Vx*cos-Vy*sin, Vy*cos+Vx*sin #the newX axis is the result of rotating x axis by theta
    return [newX,newY]

class pendulum:
    def __init__(self,x,y,x0,y0):
        self.x = x
        self.y = y
        self.x0 = x0
        self.y0 = y0
        self.velocity = [0,0]
        self.a= [0,0]
        self.angle = 0
    def CalcForce(self):
        self.angle = math.atan2(-(self.y-self.y0),self.x-self.x0)
        gravity = rotate(g,self.angle)
        self.a[1]=gravity[1]
        self.a[0] = 0 #This component is cancelled by the tension
        self.a = rotate(self.a,-self.angle)
    def move(self):
       #print pylab.dot(self.velocity,[self.x-self.x0,self.y-self.y0])
        self.velocity[0]+=self.a[0]
        self.velocity[1]+=self.a[1]
        self.x+=self.velocity[0]
        self.y+=self.velocity[1]
    def draw(self):
        pygame.draw.circle(screen, (0,0,0), (self.x0,self.y0), 5)
        pygame.draw.line(screen, (0,0,0), (self.x0,self.y0), (int(self.x), int(self.y)),3)
        pygame.draw.circle(screen, (0,0,255), (int(self.x),int(self.y)), 14,0)
g = [0,0.4]
p = pendulum(350,100,300,20)

while 1:
    screen.fill((255,255,255))
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
    p.CalcForce()
    p.move()
    p.draw()
    clock.tick(60)
    pygame.display.flip()

谢谢。

如果你想做一个模拟,我认为你做得很艰难。我从运动方程开始,看,这里。点的意思是相对于时间的微分——因此方程是
d^2/dt^2\theta=…
,那么你应该在时间方向上实现一个有限差分方案,并逐步通过时间。在每一步(用
i
标记),您可以根据摆锤的长度和
\theta\u i
计算摆锤的x和y坐标。看看有限差分法的原理。

如果你想做一个模拟,我认为你做得很艰难。我从运动方程开始,看,这里。点的意思是相对于时间的微分——因此方程是
d^2/dt^2\theta=…
,那么你应该在时间方向上实现一个有限差分方案,并逐步通过时间。在每一步(用
i
标记),您可以根据摆锤的长度和
\theta\u i
计算摆锤的x和y坐标。查看关于有限差分的讨论。

这里有很多问题。我会给你准备一些,留一些给你

我修正的是:1)既然你们已经导入了numpy,你们应该使用它,并用向量来写东西;2) 写下每一件事并让它立即生效是对自己不合理的要求;因此,您需要绘制中间结果,等等,就像这里我也绘制了
a
,这样您就可以看到它是否有意义;3) 你的整个“旋转”方法令人困惑;而不是考虑组成部分;我在这里直接计算(它更短,更容易阅读和理解,等等);4) 在使用时间步长的所有模拟中,应明确使用dt,以便在不更改其他参数的情况下更改时间步长

现在,如果你看它,你可以看到它看起来几乎是合理的。请注意,加速度永远不会向上移动,所以球在摆动时只是下落。这样做的原因是你没有把绳子的张力包括在球上的力中。我把那部分留给你

import pygame
import math
import numpy as np

clock = pygame.time.Clock()
pygame.init()
size = (width, height) = (600,500)
screen = pygame.display.set_mode(size)


class pendulum:
    def __init__(self,x,y,x0,y0):
        self.x0 = np.array((x0, y0))
        self.x = np.array((x, y), dtype=float)
        self.v = np.zeros((2,), dtype=float)
        self.a = np.zeros((2,), dtype=float)
    def CalcForce(self):
        dx = self.x0 - self.x
        angle = math.atan2(-dx[0], dx[1])
        a = g[1]*math.sin(angle)  # tangential accelation due to gravity
        self.a[0] = at*math.cos(angle)
        self.a[1] = at*math.sin(angle)
    def move(self):
        #print np.dot(self.a, self.x-self.x0) #is a perp to string?
        self.x += dt*self.v
        self.v += dt*self.a
    def draw(self):
        pygame.draw.circle(screen, (0,0,0), self.x0, 5)
        pygame.draw.line(screen, (0,0,0), self.x0, self.x.astype(int),3)
        pygame.draw.circle(screen, (0,0,255), self.x.astype(int), 14,0)
        pygame.draw.line(screen, (255, 0, 0), (self.x+200*self.a).astype(int), self.x.astype(int), 4)
dt = .001
g = [0,0.4]
p = pendulum(350,100,300,20)

while 1:
    screen.fill((255,255,255))
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
    for i in range(100): # don't plot every timestep
        p.CalcForce()
        p.move()
        p.draw()
    clock.tick(60)
    pygame.display.flip()

这里有很多问题。我会给你准备一些,留一些给你

我修正的是:1)既然你们已经导入了numpy,你们应该使用它,并用向量来写东西;2) 写下每一件事并让它立即生效是对自己不合理的要求;因此,您需要绘制中间结果,等等,就像这里我也绘制了
a
,这样您就可以看到它是否有意义;3) 你的整个“旋转”方法令人困惑;而不是考虑组成部分;我在这里直接计算(它更短,更容易阅读和理解,等等);4) 在使用时间步长的所有模拟中,应明确使用dt,以便在不更改其他参数的情况下更改时间步长

现在,如果你看它,你可以看到它看起来几乎是合理的。请注意,加速度永远不会向上移动,所以球在摆动时只是下落。这样做的原因是你没有把绳子的张力包括在球上的力中。我把那部分留给你

import pygame
import math
import numpy as np

clock = pygame.time.Clock()
pygame.init()
size = (width, height) = (600,500)
screen = pygame.display.set_mode(size)


class pendulum:
    def __init__(self,x,y,x0,y0):
        self.x0 = np.array((x0, y0))
        self.x = np.array((x, y), dtype=float)
        self.v = np.zeros((2,), dtype=float)
        self.a = np.zeros((2,), dtype=float)
    def CalcForce(self):
        dx = self.x0 - self.x
        angle = math.atan2(-dx[0], dx[1])
        a = g[1]*math.sin(angle)  # tangential accelation due to gravity
        self.a[0] = at*math.cos(angle)
        self.a[1] = at*math.sin(angle)
    def move(self):
        #print np.dot(self.a, self.x-self.x0) #is a perp to string?
        self.x += dt*self.v
        self.v += dt*self.a
    def draw(self):
        pygame.draw.circle(screen, (0,0,0), self.x0, 5)
        pygame.draw.line(screen, (0,0,0), self.x0, self.x.astype(int),3)
        pygame.draw.circle(screen, (0,0,255), self.x.astype(int), 14,0)
        pygame.draw.line(screen, (255, 0, 0), (self.x+200*self.a).astype(int), self.x.astype(int), 4)
dt = .001
g = [0,0.4]
p = pendulum(350,100,300,20)

while 1:
    screen.fill((255,255,255))
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
    for i in range(100): # don't plot every timestep
        p.CalcForce()
        p.move()
        p.draw()
    clock.tick(60)
    pygame.display.flip()

你看到了什么意外的行为?运动不是周期性的运动。可能是无关的,但我看到你对向量使用整数而不是浮点数。这可能会引起问题。你仍然在通过数值积分来解微分方程:)顺便说一句,你假设张力抵消了重力的径向分量。这只适用于鲍勃不移动的两个极端点。在摆锤移动的任何点上,张力高于径向重力分量,差值为向心力。没有它,鲍勃就不会沿着圆形轨迹运动。你看到了什么意外的行为?运动不是周期性的运动。可能是不相关的,但我看到你对向量使用的是整数而不是浮点数。这可能会引起问题。你仍然在通过数值积分来解微分方程:)顺便说一句,你假设张力抵消了重力的径向分量。这只适用于鲍勃不移动的两个极端点。在摆锤移动的任何点上,张力高于径向重力分量,差值为向心力。没有它,鲍勃就不会沿着一条圆形轨迹运动。是的,我明白,但正如我所说的,我的目标不是求解描述运动的微分方程。你不需要求解它。你用它来给你运动。是的,我理解,但正如我所说,我的目的不是去解描述运动的微分方程。你不需要解它。你在用它来给你做运动,很乐意帮忙。值得指出的是,您的方法是有效的,但比标准模拟要困难一些。也就是说,你需要一个系统动力学的方程,但是用哪一个呢?标准方法是在ma上做一些工作