You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

VPython太阳系模型轨道旋转异常问题求助

解决VPython太阳系模型的行星轨道旋转问题

嘿,我来帮你搞定这个行星公转的问题!你遇到的核心问题是误用了物体的rotate()方法,同时旋转轴的设置也不对,导致行星运动异常。

问题根源分析

你之前调用的Mercury.rotate()是用来旋转行星自身的姿态(比如让行星自转),而不是改变它的位置来实现绕太阳的轨道运动。另外,你设置的旋转轴vec(Mercury.pos.y, Mercury.pos.x, 0)会随着行星位置变化而改变方向,这就导致旋转逻辑混乱,出现转四分之一圈就异常、抖动的情况。

两种可行的解决方案

方案1:用三角函数计算轨道位置(最直观)

我们可以给每个行星定义轨道半径和公转速度,在循环中通过三角函数计算每个时刻的位置,让行星绕太阳做稳定的圆周运动:

GlowScript 2.7 VPython
from visual import *

# 创建太阳
Sun = sphere(pos=vec(0, 0, 0), radius=10, color=color.yellow)

# 定义行星参数:轨道半径、公转速度(弧度/帧)、天体对象
planets = [
    {"obj": sphere(pos=vec(25, 0, 0), radius=2, color=color.green), "radius": 25, "speed": 0.05},
    {"obj": sphere(pos=vec(40, 0, 0), radius=2.5, color=color.red), "radius": 40, "speed": 0.03},
    {"obj": sphere(pos=vec(50, 0, 0), radius=2.65, color=color.blue), "radius": 50, "speed": 0.02},
    {"obj": sphere(pos=vec(70, 0, 0), radius=2.3, color=color.orange), "radius": 70, "speed": 0.015},
    {"obj": sphere(pos=vec(90, 0, 0), radius=3, color=color.orange), "radius": 90, "speed": 0.008},
    {"obj": sphere(pos=vec(105, 0, 0), radius=2.9, color=color.orange), "radius": 105, "speed": 0.006},
    {"obj": sphere(pos=vec(117.5, 0, 0), radius=2.9, color=color.cyan), "radius": 117.5, "speed": 0.004},
    {"obj": sphere(pos=vec(135, 0, 0), radius=2.8, color=color.blue), "radius": 135, "speed": 0.003},
    {"obj": sphere(pos=vec(165, 0, 0), radius=1.5, color=color.white), "radius": 165, "speed": 0.002}
]

# 创建轨道环
for p in planets:
    p["ring"] = ring(pos=vec(0,0,0), axis=vec(0,1,0), radius=p["radius"], thickness=0.1)

# 初始化每个行星的公转角度
for p in planets:
    p["angle"] = 0

# 主循环
while True:
    rate(50)  # 控制帧率,避免过快
    for p in planets:
        # 更新公转角度
        p["angle"] += p["speed"]
        # 计算新位置:绕y轴做圆周运动,x=半径*cos(角度),z=半径*sin(角度)
        p["obj"].pos = vec(p["radius"] * cos(p["angle"]), 0, p["radius"] * sin(p["angle"]))
        # 如果需要添加自转,可以加上这行
        # p["obj"].rotate(angle=0.1, axis=vec(0,1,0))

print("Error! Escaped While Loop!")

方案2:用VPython的rotate()函数更新位置向量

如果你更习惯用VPython的旋转函数,可以直接对行星的位置向量进行旋转,固定绕y轴(太阳的垂直轴)旋转:

GlowScript 2.7 VPython
from visual import *

# 声明天体对象
Sun = sphere(pos = vec(0, 0, 0), radius = 10, color = color.yellow)
Mercury = sphere(pos = vec(25, 0, 0), radius = 2, color = color.green)
Venus = sphere(pos = vec(40, 0, 0), radius = 2.5, color = color.red)
Earth = sphere(pos = vec(50, 0, 0), radius = 2.65, color = color.blue)
Mars = sphere(pos = vec(70, 0, 0), radius = 2.3, color = color.orange)
Jupiter = sphere(pos = vec(90, 0, 0), radius = 3, color = color.orange)
Saturn = sphere(pos = vec(105, 0, 0), radius = 2.9, color = color.orange)
Uranus = sphere(pos = vec(117.5, 0, 0), radius = 2.9, color = color.cyan)
Neptune = sphere(pos = vec(135, 0, 0), radius = 2.8, color = color.blue)
Pluto = sphere(pos = vec(165, 0, 0), radius = 1.5, color = color.white)

# 声明轨道环
Mercury.ring = ring(pos = vec(0, 0, 0), axis = vec(0, 1, 0), radius=25, thickness=0.1)
Venus.ring = ring(pos = vec(0, 0, 0), axis = vec(0, 1, 0), radius=40, thickness=0.1)
Earth.ring = ring(pos = vec(0, 0, 0), axis = vec(0, 1, 0), radius=50, thickness=0.1)
Mars.ring = ring(pos = vec(0, 0, 0), axis = vec(0, 1, 0), radius=70, thickness=0.1)
Jupiter.ring = ring(pos = vec(0, 0, 0), axis = vec(0, 1, 0), radius=90, thickness=0.1)
Saturn.ring = ring(pos = vec(0, 0, 0), axis = vec(0, 1, 0), radius=105, thickness=0.1)
Uranus.ring = ring(pos = vec(0, 0, 0), axis = vec(0, 1, 0), radius=117.5, thickness=0.1)
Neptune.ring = ring(pos = vec(0, 0, 0), axis = vec(0, 1, 0), radius=135, thickness=0.1)
Pluto.ring = ring(pos = vec(0, 0, 0), axis = vec(0, 1, 0), radius=165, thickness=0.1)

# 主循环
while True:
    rate(50)
    # 绕y轴(vec(0,1,0))旋转位置向量,原点是太阳
    Mercury.pos = rotate(Mercury.pos, angle=0.05, axis=vec(0,1,0), origin=vec(0,0,0))
    Venus.pos = rotate(Venus.pos, angle=0.03, axis=vec(0,1,0), origin=vec(0,0,0))
    Earth.pos = rotate(Earth.pos, angle=0.02, axis=vec(0,1,0), origin=vec(0,0,0))
    Mars.pos = rotate(Mars.pos, angle=0.015, axis=vec(0,1,0), origin=vec(0,0,0))
    Jupiter.pos = rotate(Jupiter.pos, angle=0.008, axis=vec(0,1,0), origin=vec(0,0,0))
    Saturn.pos = rotate(Saturn.pos, angle=0.006, axis=vec(0,1,0), origin=vec(0,0,0))
    Uranus.pos = rotate(Uranus.pos, angle=0.004, axis=vec(0,1,0), origin=vec(0,0,0))
    Neptune.pos = rotate(Neptune.pos, angle=0.003, axis=vec(0,1,0), origin=vec(0,0,0))
    Pluto.pos = rotate(Pluto.pos, angle=0.002, axis=vec(0,1,0), origin=vec(0,0,0))

print("Error! Escaped While Loop!")

关键注意点

  • 公转是位置的变化,不是物体自身的旋转,所以要更新的是行星的pos属性,而不是调用物体的rotate()方法(那是用来做自转的)。
  • 旋转轴要固定为vec(0,1,0)(y轴),这样所有行星都会绕着太阳的垂直轴做稳定的圆周运动,不会出现方向混乱。
  • 调整angle参数(公转速度)可以让行星的公转周期符合真实比例,数值越小,公转越慢。

内容的提问来源于stack exchange,提问作者Connor

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:25:39