Skip to content
This repository was archived by the owner on Jun 2, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .github/workflows/pylint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.11"]
python-version: ["3.12"]
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
Expand All @@ -29,4 +29,3 @@ jobs:
- name: Analysing the code with pylint
run: |
pylint --init-hook="import sys; sys.path.append('.')" src

31 changes: 31 additions & 0 deletions .github/workflows/pytest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Pytest

on:
push:
branches: ["main"]
pull_request:
branches:
- main
- release
- feature/*

jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ["3.12"]
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v3
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -e .
pip install pytest
- name: Pytest run
run: |
pytest
33 changes: 18 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@
## Repo health

[![Pylint](https://github.com/kbrddestroyer/Python.Astro/actions/workflows/pylint.yml/badge.svg?branch=main)](https://github.com/kbrddestroyer/Python.Astro/actions/workflows/pylint.yml)
[![Pytest](https://github.com/kbrddestroyer/Python.Astro/actions/workflows/pytest.yml/badge.svg?branch=main&event=push)](https://github.com/kbrddestroyer/Python.Astro/actions/workflows/pytest.yml)

## About this repo

Astro is python-based mathematical simulation of Newtonian gravity between multiple physical objects in 2D space.

Overview:
> Please, open an issue if you see any errors in this repository.

## Some basic physics

Expand All @@ -35,31 +36,31 @@ $$

## Integration algorithms

$$
\begin{align}
\Delta r = \vec v_1\Delta t_1 + \vec v_2\Delta t_2 + ... + \vec v_n\Delta t_n \\
\Delta r = \lim_{\Delta t \to 0} \sum^n_{i=1}v_i\Delta t_i \\
\Delta r = \int^{t_1}_{t_0} v(t)dt \\
\end{align}
$$

Now when we have current velocity, we need the way of shift precise calculation.
The most obvious way is to use Euler's integration, but then we'll face an issue, that this way is highly dependent on
simulation's refresh rate and ∆t between ticks. Fortunately, there's plenty of methods we can use instead.
I've used [leapfrog algorithm](https://en.wikipedia.org/wiki/Leapfrog_integration).

### How it works?



## Code logic

- Universe - singleton class, that's capable of most calculations and kinetics acceleration
- Kinetic - object that has physical parameters, such as mass, acceleration and velocity. It's also used in visualization, converting own parameters to display self in pygame window. Also it can break into fragments if the external forces are much greater than it's own gravity.
- Spawner can be added into unifile. Spawnables must contain no parameters in constructor.
- Universe Utils file specifies global mathematical operations, such as distance calculating, force between two kinetics and universe-to-display convertations
- Simulation - controls tickrate and Universe update rate. Parameters can be tweaked to achieve different simulation speed.

Universe yses leapfrog integration for kinetic position and velocity calculations.

> Graphics and visuals will be added soon
- Simulation - controls tick rate and Universe update rate. Parameters can be tweaked to achieve different simulation speed.

## Installing

1. Fetch the dependencies. `pip install -e .`
2. Optionally install jupiter
2. Optionally install Jupiter and Notebook with `pip install jupiter notebook`

## Usage

Expand All @@ -79,12 +80,14 @@ Asteriod spawn params can be changed inside kinetic module in `AsteroidSpawner`

Simply run `python src/main.py` to launch your `unifile.py` simulation

## Testing
### 3. Testing

Jupiter notebook contains some basic computing and graphic plotting. It shows orbit parameters, speed and energy drift of a kinetic object.

> Currently there's no unit tests. Even basic. This must be changed asap

Codestyle checks are performed with `pylint`, simply run `pylint src`

> This file will change soon.
### 4. Jupiter graphics

- Launch Jupiter with `jupiter notebook` command
- Open `README.ipynb` file
- Launch the notebook
File renamed without changes.
25 changes: 25 additions & 0 deletions src/config/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
class Configuration:
# region SIMULATION

TIME_UNIT = 1.0
TIME_MULTIPLIER = 3

DELTA_TIME = TIME_UNIT * TIME_MULTIPLIER

# endregion

# region UNIVERSE

G_CONST = 6.6743e-11
UNIT_SIZE = 2e6

# endregion

# region ASTEROIDS

MASS = (1e9, 1.e12)
POSITION = (10, 1600, 10, 1000)
BASE_VELOCITY_MUL = 1e6
DENSITY = 5.6e12

# endregion
3 changes: 2 additions & 1 deletion src/graphics/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ def __init__(self):
self.__render_queue = []
self.__remove_queue = []

def set_caption(self, cap : str):
@staticmethod
def set_caption(cap : str):
pygame.display.set_caption(cap)

def register(self, obj):
Expand Down
14 changes: 9 additions & 5 deletions src/physics/kinetic.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
from copy import copy
import math
import random

import pygame

import simulation
from graphics.manager import Manager
from astro.basics import Object
from utils.vector import Vector
from utils import name_generator
from config.config import Configuration

from . import universe
from .universe_utils import UNIT_SIZE, astro_to_gui_distance, G_CONST
Expand Down Expand Up @@ -195,11 +197,13 @@ def astro_radius(self, radius):

@staticmethod
def astro_to_gui_pos(astro_pos : Vector) -> Tuple[int, int]:
if astro_pos.magnitude == 0:
return (0, 0)
return (astro_pos.normalized * astro_to_gui_distance(astro_pos.magnitude)).to_tuple()

def try_scatter(self):
if self.current_acceleration.magnitude:
if self.current_acceleration.magnitude / 3 > G_CONST * self.mass / (self.astro_radius ** 2):
if self.current_acceleration.magnitude / 30 > G_CONST * self.mass / (self.astro_radius ** 2):
self.scatter()

def scatter(self):
Expand Down Expand Up @@ -284,10 +288,10 @@ def tick(self, delta_time : float):


class Asteroid(Kinetic):
MASS = (1e9, 1.e12)
POSITION = (10, 1600, 10, 1000)
BASE_VELOCITY_MUL = 1e6
DENSITY = 5.6e12
MASS = Configuration.MASS
POSITION = Configuration.POSITION
BASE_VELOCITY_MUL = Configuration.BASE_VELOCITY_MUL
DENSITY = Configuration.DENSITY

@staticmethod
def generate_radius(mass):
Expand Down
3 changes: 2 additions & 1 deletion src/physics/universe.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
import math

from typing import TYPE_CHECKING
from physics import kinetic
from graphics import manager
from utils.utility import Singleton
from utils.vector import Vector
from physics import kinetic

from . import universe_utils

Expand Down Expand Up @@ -45,6 +45,7 @@ def registered(self, obj):

def clear(self):
self.__registry.clear()
self.__remove_queue.clear()

def update(self):
for obj in self.__remove_queue:
Expand Down
6 changes: 3 additions & 3 deletions src/physics/universe_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,15 @@
import math
import typing


from utils.vector import Vector
from config.config import Configuration

if typing.TYPE_CHECKING:
from physics.kinetic import Kinetic


G_CONST = 6.6743e-11 # Newtonian gravity constant
UNIT_SIZE = 2e6 # Unit to meter
G_CONST = Configuration.G_CONST
UNIT_SIZE = Configuration.UNIT_SIZE


def generate_v1(k1 : Kinetic, k2 : Kinetic) -> Vector:
Expand Down
15 changes: 7 additions & 8 deletions src/simulation.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,15 @@

import typing

from graphics import manager
from physics import universe
from utils.utility import Singleton
from graphics.manager import Manager
from physics.universe import Universe

from config.config import Configuration

if typing.TYPE_CHECKING:
from typing import Callable

TIME_UNIT = 1.0
TIME_DELTA = TIME_UNIT * 3


@Singleton
class Simulation:
Expand All @@ -24,8 +23,8 @@ class Simulation:
def __init__(self):
self.__running = True

self._manager = Manager()
self._universe = Universe()
self._manager = manager.Manager()
self._universe = universe.Universe()

@property
def manager(self):
Expand All @@ -42,7 +41,7 @@ def start(self, init : Callable = None):
init()

while self.__running:
self.tick(TIME_DELTA)
self.tick(Configuration.DELTA_TIME)
self._manager.update()

def tick(self, delta_time : float = 0):
Expand Down
7 changes: 6 additions & 1 deletion src/utils/vector.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,15 @@ def __add__(self, other):
return Vector(self.x + other.x, self.y + other.y)
raise NotImplementedError(type(other))

def __eq__(self, other):
if isinstance(other, Vector):
return self.x == other.x and self.y == other.y
raise NotImplementedError(type(other))

def __sub__(self, other):
if isinstance(other, Vector):
return Vector(self.x - other.x, self.y - other.y)
raise NotImplementedError
raise NotImplementedError(type(other))

@staticmethod
def vector_sum(v1 : Vector, v2 : Vector):
Expand Down
Loading
Loading