{"id":37085156,"url":"https://github.com/jasonfyw/orbital-sim","last_synced_at":"2026-01-14T10:28:04.820Z","repository":{"id":57449516,"uuid":"277302343","full_name":"jasonfyw/orbital-sim","owner":"jasonfyw","description":"A simple physics engine build over a PyGame simulation to accurately model planetary orbits in space","archived":false,"fork":false,"pushed_at":"2020-10-01T22:29:55.000Z","size":1435,"stargazers_count":36,"open_issues_count":0,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-12-21T16:45:42.693Z","etag":null,"topics":["astrodynamics","astronomy","physics","physics-2d","pygame","simulation"],"latest_commit_sha":null,"homepage":"https://pypi.org/project/orbital-sim/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jasonfyw.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-07-05T12:57:44.000Z","updated_at":"2025-06-04T08:27:14.000Z","dependencies_parsed_at":"2022-09-14T11:01:21.908Z","dependency_job_id":null,"html_url":"https://github.com/jasonfyw/orbital-sim","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/jasonfyw/orbital-sim","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jasonfyw%2Forbital-sim","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jasonfyw%2Forbital-sim/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jasonfyw%2Forbital-sim/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jasonfyw%2Forbital-sim/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jasonfyw","download_url":"https://codeload.github.com/jasonfyw/orbital-sim/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jasonfyw%2Forbital-sim/sbom","scorecard":{"id":507341,"data":{"date":"2025-08-11","repo":{"name":"github.com/jasonfyw/orbital-sim","commit":"677358f96bdbe4d0e5495f657dfa09d45500deb7"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.9,"checks":[{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":9,"reason":"1 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-h2x6-5jx5-46hf"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-19T23:33:25.245Z","repository_id":57449516,"created_at":"2025-08-19T23:33:25.245Z","updated_at":"2025-08-19T23:33:25.245Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28417214,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T10:25:19.714Z","status":"ssl_error","status_checked_at":"2026-01-14T10:22:49.371Z","response_time":107,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["astrodynamics","astronomy","physics","physics-2d","pygame","simulation"],"created_at":"2026-01-14T10:28:04.171Z","updated_at":"2026-01-14T10:28:04.814Z","avatar_url":"https://github.com/jasonfyw.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# orbital-sim\n\n![PyPI](https://img.shields.io/pypi/v/orbital-sim) ![PyPI - License](https://img.shields.io/pypi/l/orbital-sim) ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/orbital-sim)\n\nA customisable and interactive Python simulation build over PyGame that models **the orbits of celestial bodies in 2D space** using Newton’s law of universal gravitation!\n\nYou can choose from several included **preset arrangements** or create your own **simulation configuration from scratch!**\n\nPrecise positioning and movement vectors are obtained through built-in access to JPL’s HORIZONS system, a resource that provides precise data for objects in our solar system.\n\n![](media/innersolarsystem_example.gif)\n\n## Installing\n### Dependencies\norbital-sim requires the following:\n* Python 3\n* Pygame \n* Astropy\n* Astroquery\n\n### User installation\norbital-sim is available as a package on PyPI and so can be easily installed for Python 3 using `pip`:\n```\n$ pip install orbital-sim\n```\n\n## Usage\nOnce you have the package installed, you’re good to go! From here, you can either try out one of the preset configurations that come with the module, or you can delve into creating your own orbital simulation! Details for both of these are explained below.\n\n### Preset configurations\n---\n`presets.py` contains a number of orbital systems with all the celestial bodies already specified, so all that needs to be done is to import it, configure the simulation and get it running. \n\nThe following are the available presets and the bodies that are included in them – details to using them are in the next section:\n\n| Preset             | Description                                                                      |\n|------------------------|----------------------------------------------------------------------------------|\n| `InnerSolarSystem()` | The sun, Mercury, Venus, Earth and Mars                                          |\n| `SolarSystem()`      | The sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune and Pluto |\n| `EarthMoon()`        | Just the Earth and its Moon                                                      |\n\n**Importing presets**\n\nIn either your Python shell or a new Python file, import a specific preset configuration from the module:\n```python\nfrom orbitalsim.presets import PresetName\n```\n\n\n**Configuring the simulation**\n\nNext, instantiate the preset simulation and pass through any parameters if you wish to do so. You can choose to leave everything to its default value by not including anything in the parentheses:\n```python\n# A preset with default settings\ns = PresetName()\n```\n Or manually set any or all of the following parameters:\n* `dimensions` – a tuple `(x, y)` of the desired width and height\n* `scale` – the number of pixels represented by a distance of 1 AU in the simulation\n* `entity_scale` – magnification of an entity’s diameter\n* `sim_rate` – the number of days that pass in the simulation for every second in real-life\n* `start_date` – the date to start the simulation from, in format **yyyy-mm-dd**\n* `fullscreen` – a boolean for whether the window should be fullscreen or not\n\n*Tip:* go to **Setting up a custom simulation** section to find out more about these parameters.\n\nFor example:\n```python\n# A preset with all its parameters tweaked\ns = PresetName(\n    dimensions = (500, 700),\n    scale = 250,\n    entity_scale = 5,\n    sim_rate = 3,\n    start_date = '2020-07-12'\n    fullscreen = True\n)\n```\n\n**Running the simulation** \n\nOnce the simulation has been instantiated, to create the PyGame window and start the simulation, just call its `start()` function:\n```python\ns.start()\n```\n\n\n### Controlling the simulation\n---\nOnce the simulation starts, there are a number of ways to control and interact with it:\n\n| Key(s)    | Action(s)                                          |\n|-----------|----------------------------------------------------|\n| `SPACE`   | Pause/play simulation                              |\n| `↑ ↓ ← ↑` | Move window view; pan about                        |\n| `+/-`     | Zoom in and out respectively                       |\n| `r`       | Reset zoom and position                            |\n| `./,`     | Speed up and slow down the simulation respectively |\n| `l`       | Toggle labels on the entities                      |\n| `q`       | Quit the simulation                                |\n\n\n### Setting up a custom simulation\n---\nBy setting up a custom simulation, you have control over exactly what entities to add and where. You can either select existing entities in our solar system through JPL HORIZONS or create entities with custom details and characteristics. \n\nThe next few sections will detail how you may go about getting a custom simulation up and running using orbital-sim.\n\n**I. Instantiate simulation**\n\nFirst, we need to create a blank simulation that we then add stuff to. This is done by creating an instance of the `Simulation` class. Just like with the preset configurations, you can use the default parameters by not specifying them, or change certain ones to taste, up to you.\n\n```python\nimport orbitalsim\ns = orbitalsim.Simulation()\n```\n\nParameters of the `Simulation` class:\n\n| Parameter      | Default value | Description                                                                                                          |\n|----------------|---------------|----------------------------------------------------------------------------------------------------------------------|\n| `dimensions`   | `(800, 800)`   | A tuple of the width and height of the window in pixels                                                              |\n| `scale`        | `-1`           | The number of pixels represented by a distance of 1 AU in the simulation (default of -1: automatically calculated)   |\n| `entity_scale` | `10`           | Magnification of an entity’s diameter for better visibility                                                          |\n| `sim_rate`     | `3`            | The number of days that pass in the simulation for every second in real-life                                         |\n| `start_date`   | `None` *=today*| The date to start the simulation from in format **yyyy-mm-dd** (*note:* if left blank, defaults to the current day     |\n| `fullscreen`   | `False`        | Boolean for whether the PyGame window is fullscreen or not (*note:* fullscreen mode overrides `dimensions` parameter |\n\n*Note: PyGame will often encounter framerate issues on certain devices like the Retina MacBooks. If you encounter this, setting* `fullscreen = True` *will help.*\n\n**II. Adding entities using JPL HORIZONS**\n\nJPL HORIZONS assigns a **unique ID** to every object in the solar system that it tracks. You can search up entities and find their ID on [JPL HORIZON’s web interface](https://ssd.jpl.nasa.gov/horizons.cgi?s_target=1#top) by looking up a target body by keyword. *(While it is possible to refer to objects by name, this can sometimes be ambiguous due to multiple object names containing the same word)*\n\nTo add an entity that exists in the JPL HORIZONS system to the simulation, we’ll use the `add_horizons_entity` function of the `Simulation` object we just created. The function takes in two IDs: `entity_id` is the **entity to add**, `observer_id` is the **reference point** from where the position of `entity_id` will be calculated relative to.\n\n**Important:** when generating the simulation, *all entity positions are calculated from the centre of the screen (0, 0)*. Therefore, ***it is recommended that entities are added in relation to the same observer*** to ensure the distances aren’t off.\n\nFor example, the following snippet adds the entity with an ID of 3 (which happens to be Earth), with its distance calculated in relation to the sun (approximately 1 AU by definition).\n\n```python\ns.add_horizons_entity(\n    entity_id = '3',\n    observer_id = 'sun',\n    mass = 6e24,\n    diameter = 8.5e-5\n)\n```\n\nParameters to the `add_horizons_entity` function:\n\n| Parameter     | Default value | Description                                                                                                   |\n|---------------|---------------|---------------------------------------------------------------------------------------------------------------|\n| `entity_id`   | *required*    | JPL HORIZONS ID of the entity to add                                                                          |\n| `observer_id` | *required*    | JPL HORIZONS ID of the reference point from where the position and velocity of `entity_id` is calculated from (if `entity_id` and `observer_id` are the same, the object will be rendered at the centre of the screen 0,0) |\n| `mass`        | *required*    | Mass **in kg** of the entity to add (mass is not provided by JPL HORIZONS, so it has to be added manually)    |\n| `diameter`    | `1e-5`          | Diameter **in AU** of the entity to add (optional – only used for correct rendering of size)                  |\n\n**III. Adding custom entities**\n\nYou can also add a fully custom entity with the function `add_custom_entity`. With this function, you give the entity its position, movement vectors and physical characteristics. \n\n```python\ns.add_custom_entity(\n    position = (1, -0.5),\n    mass = 2e24,\n    speed = 0.2,\n    angle = 3/2 * math.pi,\n    name = 'some planet'\n)\n```\n\nSome parameters are optional but some are required. See the table below for more information. \n\n| Parameter  | Default value | Description                                                                         |\n|------------|---------------|-------------------------------------------------------------------------------------|\n| `position` | *required*    | Tuple (x, y) describing the distance in **AU** from the centre of the system (0, 0) |\n| `mass`     | *required*    | Mass of the entity in **kg**                                                        |\n| `speed`    | `0`           | Magnitude of initial velocity in **AU/day**                                         |\n| `angle`    | `0`           | Angle of initial velocity in **radians**                                            |\n| `diameter` | `1e-5`        | Diameter of the entity in **AU**                                                    |\n| `e`        | `0`           | (if applicable) Eccentricity of the orbit from **0-1**                              |\n| `a`        | `None`        | (if applicable) Semi-major axis of the orbit in **AU**                              |\n| `name`     | `''`          | A string for the entity's label name                                                |\n\n**IV. Running the simulation**\n\nOnce everything has been setup, call the `start` function of the simulation object to begin the simulation.\n\n```python\ns.start()\n```\nThat's it! That's all there is to getting a custom simulation up and running!\n\n\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjasonfyw%2Forbital-sim","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjasonfyw%2Forbital-sim","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjasonfyw%2Forbital-sim/lists"}