我正在尝试使用turtle库在Python中创建一个非常简化的Solar System模型。地球,地球的航天器,火星和坐标系的中心-太阳。我发现了一个非常有用的video,它显示了在质心周围绘制椭圆的最简单方法,尽管我看到了很多缺点。例如,此处的方程式数学是不合逻辑的。
尽管,我对这个视频中不切实际的数字没有疑问(例如神秘的1000)。我只需要创建简化的轨道,它们就不必与现实世界中的轨道一样精确,因此上述视频中的代码就足够了。在开始时,我创建了一个仅火星和地球绕太阳运行的模拟:
import turtle
import math
mars = turtle.Turtle()
earth = turtle.Turtle()
def way_to_orbit(x,y, object, colors):
object.dot(50, "yellow")
object.color("white")
object.fillcolor(colors)
object.shape("circle")
object.penup()
object.setposition(x, y)
object.pendown()
def ellipse(object1, object2):
loop = True
object2_xvel = 0
object2_yvel = 1
object1_xvel = 0
object1_yvel = 1
while loop:
object2_xvel += math.cos(math.radians(object2.towards(0, 0))) * (1000 / (object2.xcor() ** 2 + object2.ycor() ** 2))
object2_yvel += math.sin(math.radians(object2.towards(0, 0))) * (1000 / (object2.xcor() ** 2 + object2.ycor() ** 2))
object2.setposition(object2.xcor() + object2_xvel, object2.ycor() + object2_yvel)
object1_xvel += math.cos(math.radians(object1.towards(0, 0))) * (1000 / (object1.xcor() ** 2 + object1.ycor() ** 2))
object1_yvel += math.sin(math.radians(object1.towards(0, 0))) * (1000 / (object1.xcor() ** 2 + object1.ycor() ** 2))
object1.setposition(object1.xcor() + object1_xvel, object1.ycor() + object1_yvel)
way_to_orbit(620, 0, mars, "red")
way_to_orbit(375, 0, earth, "blue")
ellipse(mars, earth)
turtle.done()
输出是一个有两个行星的运动模拟:
仅与行星一起输出
一切都很好,所以我决定增加航天器,绕地球运行。在这种情况下,在object2
函数中,地球(object3
)是航天器(ellipse
)的质量中心:
import turtle
import math
mars = turtle.Turtle()
earth = turtle.Turtle()
spacecraft = turtle.Turtle()
def way_to_orbit(x,y, object, colors):
object.dot(50, "yellow")
object.color("white")
object.fillcolor(colors)
object.shape("circle")
object.penup()
object.setposition(x, y)
object.pendown()
def ellipse(object1, object2, object3):
loop = True
object2_xvel = 0
object2_yvel = 1
object1_xvel = 0
object1_yvel = 1
object3_xvel = 0
object3_yvel = 1
a = 0
while loop:
object2_xvel += math.cos(math.radians(object2.towards(0, 0))) * (1000 / (object2.xcor() ** 2 + object2.ycor() ** 2))
object2_yvel += math.sin(math.radians(object2.towards(0, 0))) * (1000 / (object2.xcor() ** 2 + object2.ycor() ** 2))
object2.setposition(object2.xcor() + object2_xvel, object2.ycor() + object2_yvel)
object1_xvel += math.cos(math.radians(object1.towards(0, 0))) * (1000 / (object1.xcor() ** 2 + object1.ycor() ** 2))
object1_yvel += math.sin(math.radians(object1.towards(0, 0))) * (1000 / (object1.xcor() ** 2 + object1.ycor() ** 2))
object1.setposition(object1.xcor() + object1_xvel, object1.ycor() + object1_yvel)
# object3_xvel += math.cos(math.radians(object3.towards(object2.xcor(), object2.ycor()))) * (1000 / ((object3.xcor()**2)-(object2.xcor()**2)) + ((object3.ycor()**2)-(object2.ycor()**2)))
# object3_yvel += math.sin(math.radians(object3.towards(object2.xcor(), object2.ycor()))) * (1000 / ((object3.xcor()**2)-(object2.xcor()**2)) + ((object3.ycor()**2)-(object2.ycor()**2)))
# object3.setposition(object3.xcor() + object3_xvel, object3.ycor() + object3_yvel)
way_to_orbit(620, 0, mars, "red")
way_to_orbit(375, 0, earth, "blue")
way_to_orbit(376, 0, spacecraft, "green")
ellipse(mars, earth, spacecraft)
turtle.done()
输出是疯狂的:用航天器输出
我不知道这里发生了什么。我只希望尽可能简单地对围绕太阳和两个卫星绕行的两个物体进行运动仿真。在这种情况下,物理定律是次要的,所有这一切都是出于其他目的。
我不知道好的解决方案,但是我发现了两个问题和一个解决方案。
首先:earth
和mars
在不移动的sun
周围移动,但是spacecraft
在正在移动的earth
周围移动。您可以在计算earth
的xvel
yvel
之前使用spacecraft
xvel
yvel
移动spacercraft
-这样,您将获得像在不移动spacecraft
的情况下移动earth
一样的效果
object3.setposition(object3.xcor() + object2_xvel, object3.ycor() + object2_yvel)
第二:如果我将1000/constant
用作spacecraft
,则其移动看起来不错。正常的计算结果不准确,它们的每一步变化都很小,但最终变化太大,spacecraft
消失了。我不知道此问题的更好解决方案。
spacecraft
到earth
的距离在屏幕上正在改变,因为它以椭圆而不是圆形移动,但始终保持接近earth
。
while loop:
distance = 1000 / (object2.xcor()**2 + object2.ycor()**2)
rad = math.radians(object2.towards(0, 0))
object2_xvel += math.cos(rad) * distance
object2_yvel += math.sin(rad) * distance
object2.setposition(object2.xcor() + object2_xvel, object2.ycor() + object2_yvel)
distance = (1000 / (object1.xcor() ** 2 + object1.ycor() ** 2))
rad = math.radians(object1.towards(0, 0))
object1_xvel += math.cos(rad) * distance
object1_yvel += math.sin(rad) * distance
object1.setposition(object1.xcor() + object1_xvel, object1.ycor() + object1_yvel)
# move `spacecraft` with `earth`
object3.setposition(object3.xcor() + object2_xvel, object3.ycor() + object2_yvel)
#distance = ( (object3.xcor()**2)-(object2.xcor()**2) ) + ( (object3.ycor()**2)-(object2.ycor()**2) )
distance = 1000/3441 # constant value
rad = math.radians(object3.towards(object2.xcor(), object2.ycor()))
object3_xvel += math.cos(rad) * distance
object3_yvel += math.sin(rad) * distance
object3.setposition(object3.xcor() + object3_xvel, object3.ycor() + object3_yvel)
我设置了从spacecraft
到earth
的更大距离,因为spacecraft
椭圆非常平坦,并且通过earth
移动了
way_to_orbit(375, 0, earth, "blue")
way_to_orbit(436, 0, spacecraft, "green")
完整代码
import turtle
import math
mars = turtle.Turtle()
earth = turtle.Turtle()
spacecraft = turtle.Turtle()
def way_to_orbit(x,y, object, colors):
object.dot(50, "yellow")
object.color("white")
object.fillcolor(colors)
object.shape("circle")
object.penup()
object.setposition(x, y)
object.pendown()
def ellipse(object1, object2, object3):
loop = True
object2_xvel = 0
object2_yvel = 1
object1_xvel = 0
object1_yvel = 1
object3_xvel = 0
object3_yvel = 1
a = 0
while loop:
distance = 1000 / (object2.xcor()**2 + object2.ycor()**2)
rad = math.radians(object2.towards(0, 0))
object2_xvel += math.cos(rad) * distance
object2_yvel += math.sin(rad) * distance
object2.setposition(object2.xcor() + object2_xvel, object2.ycor() + object2_yvel)
distance = (1000 / (object1.xcor() ** 2 + object1.ycor() ** 2))
rad = math.radians(object1.towards(0, 0))
object1_xvel += math.cos(rad) * distance
object1_yvel += math.sin(rad) * distance
object1.setposition(object1.xcor() + object1_xvel, object1.ycor() + object1_yvel)
# move `spacecraft` with `earth`
object3.setposition(object3.xcor() + object2_xvel, object3.ycor() + object2_yvel)
#distance = ( (object3.xcor()**2)-(object2.xcor()**2) ) + ( (object3.ycor()**2)-(object2.ycor()**2) )
distance = 1000/3441 # constant value
rad = math.radians(object3.towards(object2.xcor(), object2.ycor()))
object3_xvel += math.cos(rad) * distance
object3_yvel += math.sin(rad) * distance
object3.setposition(object3.xcor() + object3_xvel, object3.ycor() + object3_yvel)
way_to_orbit(620, 0, mars, "red")
way_to_orbit(375, 0, earth, "blue")
way_to_orbit(436, 0, spacecraft, "green")
ellipse(mars, earth, spacecraft)
turtle.done()
[很久以前,我做了类似的事情,但移到circles
而不是eclipses
,它看起来更好。
对于spacecraft
,我使用值代替计算以获得更好的效果。每个对象向角度添加不同的值以产生不同的速度。
import turtle
import math
def move_to_orbit(x,y, item, color):
item.dot(50, "yellow")
item.color("white")
item.fillcolor(color)
item.shape("circle")
item.penup()
item.setposition(x, y)
item.pendown()
def move_on_orbits(object1, object2, object3):
object1_angle = 0
object2_angle = 0
object3_angle = 0
while True:
object1_angle += .2
rad = math.radians(object1_angle)
x = object1.xcor()
y = object1.ycor()
center_x = 0 # sun
center_y = 0 # sun
distance = ((x-center_x)**2 + (y-center_y)**2)**.5 # calculation are precise
#distance = 420 # distance to sun
x = center_x + math.cos(rad) * distance
y = center_y + math.sin(rad) * distance
object1.setposition(x, y)
object2_angle += .1
rad = math.radians(object2_angle)
x = object2.xcor()
y = object2.ycor()
center_x = 0 # sun
center_y = 0 # sun
distance = ((x-center_x)**2 + (y-center_y)**2)**.5 # calculation are precise
#distance = 175 # distance to sun
x = center_x + math.cos(rad) * distance
y = center_y + math.sin(rad) * distance
object2.setposition(x, y)
object3_angle += 2
rad = math.radians(object3_angle)
x = object3.xcor()
y = object3.ycor()
center_x = object2.xcor() # earth
center_y = object2.ycor() # earth
#distance = ((x-center_x)**2 + (y-center_y)**2)**.5 calculation are NOT precise
distance = 30 # distance to earth
x = center_x + math.cos(rad) * distance
y = center_y + math.sin(rad) * distance
object3.setposition(x, y)
mars = turtle.Turtle()
earth = turtle.Turtle()
spacecraft = turtle.Turtle()
move_to_orbit(420, 0, mars, "red")
move_to_orbit(175, 0, earth, "blue")
move_to_orbit(205, 0, spacecraft, "green")
move_on_orbits(mars, earth, spacecraft)
turtle.done()