ขอสงวนสิทธิ์เพียงเล็กน้อยก่อน: ฉันไม่เคยศึกษาดาราศาสตร์หรือวิทยาศาสตร์ที่แน่นอนสำหรับเรื่องนั้น (ไม่ใช่แม้แต่เรื่องไอที) ดังนั้นฉันจึงพยายามเติมช่องว่างนี้ด้วยการศึกษาด้วยตนเอง ดาราศาสตร์เป็นหนึ่งในพื้นที่ที่ได้รับความสนใจจากฉันและความคิดของฉันเกี่ยวกับการศึกษาด้วยตนเองนั้นมุ่งไปที่วิธีการประยุกต์ ตรงประเด็น - นี่คือแบบจำลองการโคจรที่ฉันตั้งใจทำงานเมื่อฉันมีเวลา / อารมณ์ เป้าหมายหลักของฉันคือการสร้างระบบสุริยะที่สมบูรณ์ในการเคลื่อนที่และความสามารถในการวางแผนการเปิดตัวยานอวกาศไปยังดาวเคราะห์ดวงอื่น
คุณมีอิสระที่จะเลือกโครงการนี้ได้ทุกเมื่อและสนุกไปกับการทดลอง!
ปรับปรุง !!! (Nov10)
- velocity เป็น deltaV ที่เหมาะสมและให้การเคลื่อนไหวเพิ่มเติมจะคำนวณผลรวมเวกเตอร์ของ velocity
- คุณสามารถวางวัตถุแบบคงที่ได้มากเท่าที่คุณต้องการในทุก ๆ ครั้งที่วัตถุในการตรวจสอบการเคลื่อนไหวสำหรับเวกเตอร์แรงโน้มถ่วงจากทุกแหล่ง (และตรวจสอบการชนกัน)
- ปรับปรุงประสิทธิภาพการคำนวณอย่างมาก
- การแก้ไขเพื่อบัญชีสำหรับ mod แบบโต้ตอบใน matplotlib ดูเหมือนว่านี่เป็นตัวเลือกเริ่มต้นสำหรับ ipython เท่านั้น python3 ปกติต้องการคำสั่งนั้นอย่างชัดเจน
โดยทั่วไปตอนนี้เป็นไปได้ที่จะ "ส่ง" ยานอวกาศจากพื้นผิวโลกและวางแผนภารกิจสู่ดวงจันทร์ด้วยการแก้ไขเวกเตอร์ deltaV ผ่านทาง giveMotion () ในแถวถัดไปกำลังพยายามที่จะใช้ตัวแปรเวลาทั่วโลกเพื่อเปิดใช้งานการเคลื่อนไหวพร้อมกันเช่นดวงจันทร์โคจรรอบโลกในขณะที่ยานอวกาศพยายามใช้แรงโน้มถ่วงช่วยในการจัดทำ
ความคิดเห็นและข้อเสนอแนะสำหรับการปรับปรุงยินดีต้อนรับเสมอ!
ทำใน Python3 พร้อมกับ matplotlib library
import matplotlib.pyplot as plt
import math
plt.ion()
G = 6.673e-11 # gravity constant
gridArea = [0, 200, 0, 200] # margins of the coordinate grid
gridScale = 1000000 # 1 unit of grid equals 1000000m or 1000km
plt.clf() # clear plot area
plt.axis(gridArea) # create new coordinate grid
plt.grid(b="on") # place grid
class Object:
_instances = []
def __init__(self, name, position, radius, mass):
self.name = name
self.position = position
self.radius = radius # in grid values
self.mass = mass
self.placeObject()
self.velocity = 0
Object._instances.append(self)
def placeObject(self):
drawObject = plt.Circle(self.position, radius=self.radius, fill=False, color="black")
plt.gca().add_patch(drawObject)
plt.show()
def giveMotion(self, deltaV, motionDirection, time):
if self.velocity != 0:
x_comp = math.sin(math.radians(self.motionDirection))*self.velocity
y_comp = math.cos(math.radians(self.motionDirection))*self.velocity
x_comp += math.sin(math.radians(motionDirection))*deltaV
y_comp += math.cos(math.radians(motionDirection))*deltaV
self.velocity = math.sqrt((x_comp**2)+(y_comp**2))
if x_comp > 0 and y_comp > 0: # calculate degrees depending on the coordinate quadrant
self.motionDirection = math.degrees(math.asin(abs(x_comp)/self.velocity)) # update motion direction
elif x_comp > 0 and y_comp < 0:
self.motionDirection = math.degrees(math.asin(abs(y_comp)/self.velocity)) + 90
elif x_comp < 0 and y_comp < 0:
self.motionDirection = math.degrees(math.asin(abs(x_comp)/self.velocity)) + 180
else:
self.motionDirection = math.degrees(math.asin(abs(y_comp)/self.velocity)) + 270
else:
self.velocity = self.velocity + deltaV # in m/s
self.motionDirection = motionDirection # degrees
self.time = time # in seconds
self.vectorUpdate()
def vectorUpdate(self):
self.placeObject()
data = []
for t in range(self.time):
motionForce = self.mass * self.velocity # F = m * v
x_net = 0
y_net = 0
for x in [y for y in Object._instances if y is not self]:
distance = math.sqrt(((self.position[0]-x.position[0])**2) +
(self.position[1]-x.position[1])**2)
gravityForce = G*(self.mass * x.mass)/((distance*gridScale)**2)
x_pos = self.position[0] - x.position[0]
y_pos = self.position[1] - x.position[1]
if x_pos <= 0 and y_pos > 0: # calculate degrees depending on the coordinate quadrant
gravityDirection = math.degrees(math.asin(abs(y_pos)/distance))+90
elif x_pos > 0 and y_pos >= 0:
gravityDirection = math.degrees(math.asin(abs(x_pos)/distance))+180
elif x_pos >= 0 and y_pos < 0:
gravityDirection = math.degrees(math.asin(abs(y_pos)/distance))+270
else:
gravityDirection = math.degrees(math.asin(abs(x_pos)/distance))
x_gF = gravityForce * math.sin(math.radians(gravityDirection)) # x component of vector
y_gF = gravityForce * math.cos(math.radians(gravityDirection)) # y component of vector
x_net += x_gF
y_net += y_gF
x_mF = motionForce * math.sin(math.radians(self.motionDirection))
y_mF = motionForce * math.cos(math.radians(self.motionDirection))
x_net += x_mF
y_net += y_mF
netForce = math.sqrt((x_net**2)+(y_net**2))
if x_net > 0 and y_net > 0: # calculate degrees depending on the coordinate quadrant
self.motionDirection = math.degrees(math.asin(abs(x_net)/netForce)) # update motion direction
elif x_net > 0 and y_net < 0:
self.motionDirection = math.degrees(math.asin(abs(y_net)/netForce)) + 90
elif x_net < 0 and y_net < 0:
self.motionDirection = math.degrees(math.asin(abs(x_net)/netForce)) + 180
else:
self.motionDirection = math.degrees(math.asin(abs(y_net)/netForce)) + 270
self.velocity = netForce/self.mass # update velocity
traveled = self.velocity/gridScale # grid distance traveled per 1 sec
self.position = (self.position[0] + math.sin(math.radians(self.motionDirection))*traveled,
self.position[1] + math.cos(math.radians(self.motionDirection))*traveled) # update pos
data.append([self.position[0], self.position[1]])
collision = 0
for x in [y for y in Object._instances if y is not self]:
if (self.position[0] - x.position[0])**2 + (self.position[1] - x.position[1])**2 <= x.radius**2:
collision = 1
break
if collision != 0:
print("Collision!")
break
plt.plot([x[0] for x in data], [x[1] for x in data])
Earth = Object(name="Earth", position=(50.0, 50.0), radius=6.371, mass=5.972e24)
Moon = Object(name="Moon", position=(100.0, 100.0), radius=1.737, mass = 7.347e22) # position not to real scale
Craft = Object(name="SpaceCraft", position=(49.0, 40.0), radius=1, mass=1.0e4)
Craft.giveMotion(deltaV=8500.0, motionDirection=100, time=130000)
Craft.giveMotion(deltaV=2000.0, motionDirection=90, time=60000)
plt.show(block=True)
มันทำงานอย่างไร
ทุกอย่างเดือดลงไปสองสิ่ง:
- การสร้างวัตถุเช่นเดียว
Earth = Object(name="Earth", position=(50.0, 50.0), radius=6.371, mass=5.972e24)
กับพารามิเตอร์ของตำแหน่งบนกริด (1 หน่วยของกริดคือ 1,000 กม. โดยค่าเริ่มต้น แต่สามารถเปลี่ยนแปลงได้เช่นกัน) รัศมีในหน่วยกริดและมวลหน่วยเป็นกิโลกรัม - การให้วัตถุ deltaV บางตัวเช่น
Craft.giveMotion(deltaV=8500.0, motionDirection=100, time=130000)
เห็นได้ชัดว่าจำเป็นต้องCraft = Object(...)
สร้างขึ้นในตำแหน่งแรกตามที่กล่าวไว้ในจุดก่อนหน้า พารามิเตอร์ที่นี่มีหน่วยเป็นdeltaV
m / s (โปรดทราบว่าตอนนี้การเร่งความเร็วเป็นแบบทันที)motionDirection
คือทิศทางของ deltaV เป็นองศา (จากตำแหน่งปัจจุบันจินตนาการถึงวงกลม 360 องศารอบวัตถุดังนั้นทิศทางคือจุดหนึ่งในวงกลมนั้น) และพารามิเตอร์สุดท้ายtime
คือกี่วินาที หลังจากวิถีการเคลื่อนที่แบบกดของ deltaV ของวัตถุจะถูกตรวจสอบgiveMotion()
เริ่มต้นครั้งต่อไปจากตำแหน่งสุดท้ายของหน้าที่giveMotion()
แล้ว
คำถาม:
- นี่เป็นอัลกอริทึมที่ถูกต้องในการคำนวณวงโคจรหรือไม่?
- การปรับปรุงที่ชัดเจนที่จะทำคืออะไร?
- ฉันกำลังพิจารณาตัวแปร "timeScale" ที่จะเพิ่มประสิทธิภาพการคำนวณเนื่องจากอาจไม่จำเป็นต้องคำนวณเวกเตอร์และตำแหน่งใหม่ทุกวินาที มีความคิดเห็นเกี่ยวกับวิธีการนำไปปฏิบัติหรือเป็นความคิดที่ดีหรือไม่? (การสูญเสียความถูกต้องเทียบกับการปรับปรุงประสิทธิภาพ)
โดยทั่วไปเป้าหมายของฉันคือการเริ่มต้นการอภิปรายในหัวข้อและดูว่ามันนำไปสู่ และถ้าเป็นไปได้เรียนรู้ (หรือดีกว่า - สอน) สิ่งใหม่และน่าสนใจ
ทดลองใช้ฟรี!
ลองใช้:
Earth = Object(name="Earth", position=(50.0, 100.0), radius=6.371, mass=5.972e24)
Moon = Object(name="Moon", position=(434.0, 100.0), radius=1.737, mass = 7.347e22)
Craft = Object(name="SpaceCraft", position=(43.0, 100.0), radius=1, mass=1.0e4)
Craft.giveMotion(deltaV=10575.0, motionDirection=180, time=322000)
Craft.giveMotion(deltaV=400.0, motionDirection=180, time=50000)
ด้วยการเบิร์นสองครั้ง - หนึ่งเกรดที่วงโคจรของโลกและหนึ่ง retrograde ที่วงโคจรของดวงจันทร์ฉันบรรลุวงโคจรของดวงจันทร์ที่มั่นคง สิ่งเหล่านี้ใกล้เคียงกับค่าที่คาดหวังทางทฤษฎีหรือไม่?
การออกกำลังกายที่แนะนำ: ลองทำใน 3 เบิร์น - วงโคจรโลกที่เสถียรจากพื้นผิวโลก, โปรเกรดการเผาไหม้ไปถึงดวงจันทร์, การเบิร์นเรเกรดถอยหลังเข้าคลองเพื่อทำให้วงโคจรรอบ ๆ ดวงจันทร์คงที่ จากนั้นลองย่อ deltaV ให้เล็กที่สุด
หมายเหตุ: ฉันวางแผนที่จะอัปเดตโค้ดด้วยความคิดเห็นที่ครอบคลุมสำหรับผู้ที่ไม่คุ้นเคยกับไวยากรณ์ python3