def check_margins(trojan1: CelestialBody, trojan2: CelestialBody,\
    central: CelestialBody, margin: float) -> bool:
    """
    Checks to see if two planets in a Trojan pair are within a given percent 
    margin of a 1:1 period resonance.

    Parameters
    ----------
    - trojan1 (CelestialBody): One member of the co-orbital pair.
    - trojan2 (CelestialBody): The other member of the co-orbital pair.
    - central (CelestialBody): The central body in the system.
    - margin (float): The allowed percent deviation from a 1:1 period resonance.

    Returns
    -------
    - in_margin (bool): True if within the margin, false if not.
    """

    # Get the orbital periods of each planet.
    P1 = trojan1.period(central)
    P2 = trojan2.period(central)

    # Compute the percent difference between the periods.
    diff = abs(P1 - P2)
    avg = np.average([P1, P2])
    p_diff = (diff / avg) * 100

    # Will return true if the percent difference exceeds the margin.
    return not (p_diff > margin)
示例#2
0
 def test_ShouldMoveThreeBodiesOfEqualMassTowardsCenterOfMass(self):
     body1 = CelestialBody("N",6e24,Vector(0,10e10,0),self.zero,self.zero)
     body2 = CelestialBody("M",6e24,Vector(-6e10,-8e10,0),self.zero,self.zero)
     body3 = CelestialBody("L",6e24,Vector(6e10,-8e10,0),self.zero,self.zero)
     system = System("Tri-body", [body1,body2,body3])
     system.update(1)
     self.assertTrue(Vector.sumOfVectors([body1.velocity, body2.velocity,body3.velocity]) == Vector(0,0,0))
     self.assertTrue(Vector.absolute(body1.position) == Vector.absolute(body2.position))
     self.assertTrue(Vector.absolute(body1.position) == Vector.absolute(body3.position))
示例#3
0
 def test_ShouldAccelerateASmallBodyWithSmallStartingVelocityTowardsABigOne(self):
     body1 = CelestialBody("N",6e24,Vector(0,0,0),self.zero,self.zero)
     body2 = CelestialBody("M",1e3,Vector(1e7,0,0),Vector(0,1000,0),self.zero)
     system = System("Dual Body", [body1,body2])
     distance = 1e7
     for _ in range(1,101):
         system.update(1)
         new_distance = CelestialBody.calcDistance(body1,body2)
         self.assertTrue(new_distance < distance)
         distance = new_distance
示例#4
0
 def test_ShouldAllowEscapeOfSmallBodyWithHighVelocity(self):
     body1 = CelestialBody("N",6e24,Vector(0,0,0),self.zero,self.zero)
     body2 = CelestialBody("M",1e3,Vector(1e7,0,0),Vector(0,3e8,0),self.zero)
     system = System("Dual Body", [body1,body2])
     distance = 1e7
     for _ in range(1,101):
         system.update(1)
         new_distance = CelestialBody.calcDistance(body1,body2)
         self.assertTrue(new_distance > distance)
         distance = new_distance
    def test_ShouldGiveSameOutputNoMatterTheTickFrequency(self):
        body = CelestialBody("Sun", 1E26, self.nonZero, self.nonZero2,
                             self.nonZero3)
        for _ in range(1, 11):
            body.update(0.1)

        print(body.position)
        print(body.velocity)

        self.assertAlmostEqual(body.position, Vector(14.5, 9.5, 8.5))
        self.assertAlmostEqual(body.velocity, Vector(15, 10, 5))
示例#6
0
 def test_ShouldMoveTwoStationaryBodiesDirectlyTowardsEachOther(self):
     body1 = CelestialBody("N",1e25,Vector(-100,0,0),self.zero,self.zero)
     body2 = CelestialBody("M",1e25,Vector(100,0,0),self.zero,self.zero)
     system = System("Dual Body", [body1,body2])
     system.update(10)
     self.assertTrue(body1.velocity == Vector.mult(-1,body2.velocity))
     self.assertTrue(body1.velocity != body2.velocity)
     self.assertTrue(Vector.add(body1.velocity,body2.velocity) == self.zero)
     self.assertTrue(Vector.add(body1.position,body2.position) == self.zero)
     self.assertTrue(body1.position.y == body2.position.y)
     self.assertTrue(body1.position.z == body2.position.z)
     self.assertTrue(body1.position.y == 0)
     self.assertTrue(body1.position.z == 0)
示例#7
0
 def test_ShouldConserveMomentum(self):
     body1 = CelestialBody("N", 6e24, Vector(0, 10e10, 0), Vector(3,6,9), self.zero)
     body2 = CelestialBody("M", 6e24, Vector(-6e10, -8e10, 0), Vector(5,12,3), self.zero)
     body3 = CelestialBody("L", 6e24, Vector(6e10, -8e10, 0), Vector(9,2,19), self.zero)
     bodies = [body1,body2,body3]
     system = System("Tri-body", bodies)
     totalMomentumBefore = Vector(0,0,0)
     for body in bodies:
         totalMomentumBefore = Vector.add(totalMomentumBefore, body.calcMomentum())
     system.update(600)
     totalMomentumAfter = Vector(0,0,0)
     for body in bodies:
         totalMomentumAfter = Vector.add(totalMomentumAfter, body.calcMomentum())
     self.assertTrue(totalMomentumBefore == totalMomentumAfter)
示例#8
0
 def test_ShouldMoveAtConstantVelocitySingleMovingBody(self):
     body = CelestialBody("N", 1e25, self.zero, Vector(10, 15, 50),
                          self.zero)
     system = System("Single Body", [body])
     system.update(10)
     self.assertTrue(body.velocity == Vector(10, 15, 50))
     self.assertTrue(body.position == Vector(100, 150, 500))
示例#9
0
    def __init__(self, dat_name, time_step=20000, satelite=False):
        self.t = time_step
        self.time = 0
        self.energies = ([], [])
        with open(dat_name + '.json') as json_dat:
            dat = json.load(json_dat)

        self.bodies = [CelestialBody(*[body] + dat[body]) for body in dat]
        self.sat_target = self.bodies[4]
        self.sat_reached = 0
        self.sat_time = 0
        for body in self.bodies:
            body.update_acc(self.bodies, first=True)
示例#10
0
 def test_ShouldAccelerateASmallBodyTowardsABigOne(self):
     body1 = CelestialBody("N",1e30,Vector(-100,0,0),self.zero,self.zero)
     body2 = CelestialBody("M",1e23,Vector(100,0,0),self.zero,self.zero)
     system = System("Dual Body", [body1,body2])
     system.update(10)
     self.assertTrue(body1.calcSpeed() - body2.calcSpeed() < 0)
     self.assertTrue(body1.position.x + body2.position.x < 0)
     self.assertTrue(body1.position.y == body2.position.y)
     self.assertTrue(body1.position.z == body2.position.z)
     self.assertTrue(body1.position.y == 0)
     self.assertTrue(body1.position.z == 0)
def parse_line(line: str) -> CelestialBody:
    """
    Parses a single line of text to produce a CelestialBody object.

    Parameter
    ---------
    - line (string): A line of text containing the information necessary to 
    construct a CelestialBody object.

    Returns
    -------
    - body (CelestialBody): The CelestialBody object constructed from the 
    parameters given by the input line.
    """

    params: List[str] = line.split(" ")

    # Variables used to construct the CelestialBody object.
    body_type: CelestialType = -1
    body_is_trojan: bool = False
    body_name: str = ""
    body_mass: float = 0.0
    body_radius: float = 0.0
    body_position: np.array = np.zeros(3)
    body_velocity: np.array = np.zeros(3)

    # The parsing function cannot detect missing parameters.
    for i, param in enumerate(params):
        if i == 0:
            # Each line should start by specifying the body type.
            if params[0] == "STAR":
                body_type = CelestialType.STAR
            elif params[0] == "GIANT":
                body_type = CelestialType.GIANT
            elif params[0] == "TERRESTRIAL":
                body_type = CelestialType.TERRESTRIAL
            else:
                raise Exception("Each line must start with a valid object type"\
                    + " specification.")
        else:
            tokens = param.split("=")
            if tokens[0] == "trojan":
                body_is_trojan = tokens[1] == "True"
            elif tokens[0] == "name":
                body_name = tokens[1]
            elif tokens[0] == "mass":
                body_mass = float(tokens[1])
            elif tokens[0] == "radius":
                body_radius = float(tokens[1])
            elif tokens[0] == "position":
                vals = tokens[1].split(",")
                if len(vals) != 3:
                    raise Exception("Position must be specified by three"\
                        + " comma-separated floats")
                body_position = np.array([float(vals[0]), float(vals[1]),\
                    float(vals[2])])
            elif tokens[0] == "velocity":
                vals = tokens[1].split(",")
                if len(vals) != 3:
                    raise Exception("Velocity must be specified by three"\
                        + " comma-separated floats")
                body_velocity = np.array([float(vals[0]), float(vals[1]),\
                    float(vals[2])])
            else:
                raise Exception("Invalid token detected while parsing input"\
                    + " file.")

    body = CelestialBody(type=body_type, trojan=body_is_trojan, name=body_name,\
        mass=body_mass, radius=body_radius, position=body_position,\
        velocity=body_velocity)

    return body
示例#12
0
 def test_ShouldNeverMoveSingleStationaryBody(self):
     body = CelestialBody("N",1e25,Vector(4,7,9),self.zero,self.zero)
     system = System("Single Body", [body])
     system.update(10000)
     self.assertTrue(body.position == Vector(4,7,9))
示例#13
0
 def test_ShouldReturnKineticEnergyWhenGivenMassAndVelocity(self):
     body = CelestialBody("Sun", 1E26, self.nonZero, Vector(4e4, 0, 0),
                          self.nonZero3)
     print(body.calcKineticEnergy())
     self.assertTrue(
         System.nearly_equal(body.calcKineticEnergy(), 8e34, 1e-4))
示例#14
0
 def test_ShouldNotMoveAtZeroVelocityAndAcceleration(self):
     body = CelestialBody("Sun", 1E26, self.zero, self.zero, self.zero)
     body.update(10000)
     self.assertTrue(body.position == self.zero)
示例#15
0
 def test_ShouldMoveAtIncreasingRateOfChangeOfPositionWithConstantAcceleration(
         self):
     body = CelestialBody("Sun", 1E26, self.nonZero, self.nonZero2,
                          self.nonZero3)
     body.update(1)
     self.assertTrue(body.position == Vector(14.5, 9.5, 8.5))
示例#16
0
 def test_ShouldMoveAtIncreasingVelocityWithConstantAcceleration(self):
     body = CelestialBody("Sun", 1E26, self.nonZero, self.nonZero2,
                          self.nonZero3)
     body.update(1)
     self.assertTrue(body.velocity == Vector(15, 10, 5))
示例#17
0
 def test_ShouldMoveInSmallTimeIntervalAtZeroAcceleration(self):
     body = CelestialBody("Sun", 1E26, self.nonZero, self.nonZero2,
                          self.zero)
     body.update(0.25)
     self.assertTrue(body.position == Vector(5, 4.25, 5.5))
示例#18
0
 def test_ShouldReturnMomentumWhenGivenMassAndVelocity(self):
     body = CelestialBody("Sun", 1E26, self.nonZero, Vector(4e4, 0, 0),
                          self.nonZero3)
     self.assertTrue(body.calcMomentum() == Vector(4e30, 0, 0))
示例#19
0
pygame.display.set_caption("Orbital Simulator")

# Set up the drawing window
WIDTH = 1000
HEIGHT = 1000

screen = pygame.display.set_mode((WIDTH, HEIGHT))
alpha_surf = pygame.Surface(screen.get_size(),
                            pygame.SRCALPHA)  # alpha surface for trails
FramePerSec = pygame.time.Clock()
font = pygame.font.SysFont('Arial', 20)

# Adding Planets
# earth
planetsList.append(
    CelestialBody("Earth", Vector2(500, 500 + normalize_distance(147100000)),
                  5.97219e24, 0, (0, 0, 255), normalize_distance(30.29), 0, 5))
# moon
# mercury
planetsList.append(
    CelestialBody("Mercury", Vector2(500, 500 + normalize_distance(46000000)),
                  3.285e23, 1, (200, 100, 30), normalize_distance(58.98), 0,
                  3))
# venus
planetsList.append(
    CelestialBody("Venus", Vector2(500, 500 + normalize_distance(107476000)),
                  4.867e24, 2, (234, 213, 191), normalize_distance(35.26), 0,
                  4))
# mars
planetsList.append(
    CelestialBody("Mars", Vector2(500, 500 + normalize_distance(206600000)),
                  6.39e23, 3, (200, 20, 20), normalize_distance(26.50), 0, 4))