【问题标题】:Solar System in PythonPython中的太阳系
【发布时间】:2020-03-25 11:00:17
【问题描述】:

我正在尝试使用turtle 库在 Python 中创建一个非常简化的太阳系模型。地球,地球的宇宙飞船,火星和坐标系的中心——太阳。我发现了一个非常有用的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)是ellipse函数中航天器(object3)的质心:

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()

输出很疯狂: 用航天器输出

我不知道这里发生了什么。我只想要一个尽可能简单的移动模拟,即围绕太阳运行的 2 个物体和其中一个物体的卫星。在这种情况下,物理定律是次要的,所有这些都是为了其他目的。

  1. 那么,如何修复海龟模拟航天器/卫星的路径?
  2. 有没有更简单或更快的方法在 Python 中创建此类模拟?
  3. 谁能帮我解释一下视频中用于椭圆绘制的方法?

【问题讨论】:

  • 首先使用print() 查看变量中的值 - 它应该有助于理解问题。也许要围绕行星旋转,您必须:将坐标移动到(0,0)(从太空船的位置减去行星的位置),围绕(0,0)旋转,移回旧位置(将行星的位置添加到太空船的位置),

标签: python simulation turtle-graphics astronomy


【解决方案1】:

我不知道好的解决方案,但我发现了两个问题和一个解决方案。

首先:earth 和 mars 在不移动的 sun 周围移动,但 spacecraft 在移动的 earth 周围移动。在计算xvel yvel 为spacercraft 之前,您可以使用earth xvel yvel 移动spacecraft - 这样您将获得效果,就像移动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()

【讨论】:

    猜你喜欢
    • 2018-08-19
    • 1970-01-01
    • 2019-04-08
    • 1970-01-01
    • 2016-07-11
    • 2012-11-03
    • 2013-04-19
    • 2023-04-04
    • 2011-01-04
    相关资源
    最近更新 更多