pax_global_header 0000666 0000000 0000000 00000000064 14201250233 0014502 g ustar 00root root 0000000 0000000 52 comment=e0801613128c419b79cbf17de615e0454ccca78b
poliastro-0.16.2/ 0000775 0000000 0000000 00000000000 14201250233 0013604 5 ustar 00root root 0000000 0000000 poliastro-0.16.2/.circleci/ 0000775 0000000 0000000 00000000000 14201250233 0015437 5 ustar 00root root 0000000 0000000 poliastro-0.16.2/.circleci/config.yml 0000664 0000000 0000000 00000002757 14201250233 0017442 0 ustar 00root root 0000000 0000000 version: 2.1
jobs:
quality: &test-template
docker:
- image: python:3.8
environment:
PIP_PREFER_BINARY: true
PIP_PROGRESS_BAR: "off"
TOXENV: check
steps:
- checkout
- run: python -m pip install tox
- run: tox
py38-fast:
<<: *test-template
environment:
TOXENV: py38-fast
py38-online:
<<: *test-template
environment:
TOXENV: py38-online
py38-slow:
<<: *test-template
environment:
TOXENV: py38-slow
py38-images:
<<: *test-template
environment:
TOXENV: py38-images
py38-coverage:
<<: *test-template
environment:
TOXENV: py38-coverage
steps:
- checkout
- run: python -m pip install tox
- run: tox
- run: python -m pip install codecov && codecov
py39:
<<: *test-template
docker:
- image: python:3.9
environment:
TOXENV: py39
py310:
<<: *test-template
docker:
- image: python:3.10
environment:
TOXENV: py310
workflows:
version: 2
build_and_test:
jobs:
- quality
- py38-fast:
requires:
- quality
- py38-online:
requires:
- quality
- py38-slow:
requires:
- quality
- py38-images:
requires:
- quality
- py38-coverage:
requires:
- quality
- py39:
requires:
- quality
- py310:
requires:
- quality
poliastro-0.16.2/.coveragerc 0000664 0000000 0000000 00000000126 14201250233 0015724 0 ustar 00root root 0000000 0000000 [paths]
source = src
[run]
branch = True
source = src
[report]
omit =
contrib/*
poliastro-0.16.2/.dockerignore 0000664 0000000 0000000 00000000012 14201250233 0016251 0 ustar 00root root 0000000 0000000 .git
.tox
poliastro-0.16.2/.github/ 0000775 0000000 0000000 00000000000 14201250233 0015144 5 ustar 00root root 0000000 0000000 poliastro-0.16.2/.github/FUNDING.yml 0000664 0000000 0000000 00000000152 14201250233 0016757 0 ustar 00root root 0000000 0000000 # These are supported funding model platforms
open_collective: poliastro
github: [numfocus, astrojuanlu]
poliastro-0.16.2/.github/ISSUE_TEMPLATE/ 0000775 0000000 0000000 00000000000 14201250233 0017327 5 ustar 00root root 0000000 0000000 poliastro-0.16.2/.github/ISSUE_TEMPLATE/bug.md 0000664 0000000 0000000 00000002703 14201250233 0020430 0 ustar 00root root 0000000 0000000 ---
name: Bug, problem, error
about: Bug reports, inconsistent results, unexpected errors
title: ''
labels: support
assignees: ''
---
đ **Problem**
đ„ **Please paste the output of following commands**
* `conda info -a` (only if you have conda)
* `conda list` (only if you have conda)
* `pip freeze`
```bash
# Paste your output here:
```
```bash
# Paste your output here:
```
đĄ **Possible solutions**
đ **Steps to solve the problem**
* Comment below about what you've started working on.
* Add, commit, push your changes
* Submit a pull request and add this in comments - `Addresses #`
* Ask for a review in comments section of pull request
* Celebrate your contribution to this project đ
poliastro-0.16.2/.github/ISSUE_TEMPLATE/feature_request.md 0000664 0000000 0000000 00000000666 14201250233 0023064 0 ustar 00root root 0000000 0000000 ---
name: Feature request
about: Ideas for the library, enhancements, support new use cases
title: ''
labels: enhancement
assignees: ''
---
đĄ **Feature request**
đŻ **Goal**
poliastro-0.16.2/.github/ISSUE_TEMPLATE/new_release.md 0000664 0000000 0000000 00000005134 14201250233 0022145 0 ustar 00root root 0000000 0000000 ---
name: New release
about: Checklist for new release (development only)
title: Release X.Y.Z checklist
labels: development
assignees: astrojuanlu
---
## Preparing the release
* [ ] Rerun all notebooks (pay special attention to new features)
* [ ] Review documentation, optionally improving the user guide or adding new notebooks showcasing new functionality
* [ ] Write the changelog and list of contributors
- Commits since last release branch https://github.com/poliastro/poliastro/compare/X.Y.Z...main
- Issues closed in this milestone https://github.com/poliastro/poliastro/milestone/N?closed=1 (note that there might be issues without milestone!)
- Pull requests merged since last branching https://github.com/poliastro/poliastro/pulls?q=is%3Apr+is%3Amerged+merged%3A%3E%3D2019-02-09+sort%3Aupdated-asc
- List of contributors: `git shortlog --summary --email ${BRANCHING_COMMIT}..`
## Before the beta release
* [ ] New branch
* [ ] Bump version **to X.Yb1** in:
- `README.md`
- `__init__.py`
* [ ] Check all the badges in `README` point to the appropriate git **branch** (manually replace `main` by new branch)
* [ ] Check that docs badges and URLs point to appropriate **tag** (manually replace `latest` by new tag)
* [ ] `git commit -m 'Bump to next beta version'`
* [ ] Generate sdist and bdist_wheel with `python -m build`
* [ ] `twine upload dist/* --repository-url https://test.pypi.org/legacy/`
* [ ] Tag
* [ ] Bump main to next development version
## Beta release
* [ ] Push branch to GitHub **and tags**
* [ ] Check on Test PyPI that the badges will work
* [ ] Upload sdist and bdist_wheel to PyPI - *this step cannot be undone if the release is removed!* `twine upload dist/* --repository-url https://upload.pypi.org/legacy/`
* [ ] Check Read the Docs
## Before final release
* [ ] Backport any bugs
* [ ] Update release date in changelog
* [ ] Bump version **to X.Y.Z** in:
- `README.md`
- `__init__.py`
- Sphinx `conf.py`
* [ ] Check that docs badges and URLs point to appropriate **tag** (replace `vX.Yb1` by `vX.Y.Z`)
* [ ] Commit
* [ ] Generate sdist and bdist_wheel
* [ ] `twine upload dist/* --repository-url https://test.pypi.org/legacy/`
* [ ] Tag
## Final release
* [ ] Push tag to GitHub
* [ ] Upload sdist and bdist_wheel to PyPI - *this step cannot be undone if the release is removed!* `twine upload dist/* --repository-url https://upload.pypi.org/legacy/`
* [ ] Check Read the Docs
* [ ] Create GitHub release
* [ ] Add Zenodo badge to GitHub release
* [ ] Send announcement email with subject "ANN: poliastro X.Y.Z released đ"
* [ ] Cherry pick release date to main
* [ ] Close milestone
poliastro-0.16.2/.github/no-response.yml 0000664 0000000 0000000 00000001417 14201250233 0020142 0 ustar 00root root 0000000 0000000 # Configuration for probot-no-response - https://github.com/probot/no-response
# Number of days of inactivity before an Issue is closed for lack of response
daysUntilClose: 14
# Label requiring a response
responseRequiredLabel: support
# Comment to post when closing an Issue for lack of response. Set to `false` to disable
closeComment: >
This issue has been automatically closed because there has been no response
to our request for more information from the original author. With only the
information that is currently in the issue, we don't have enough information
to take action. Moreover, the problems discussed in the issue may not be
directly from poliastro. If you still face this problem, reopen the issue or
comment on it. We would be happy to help again!
poliastro-0.16.2/.github/workflows/ 0000775 0000000 0000000 00000000000 14201250233 0017201 5 ustar 00root root 0000000 0000000 poliastro-0.16.2/.github/workflows/validation_trigger.yml 0000664 0000000 0000000 00000001634 14201250233 0023605 0 ustar 00root root 0000000 0000000 # This workflow triggers poliastro/validation CI from poliastro/poliastro
# everytime a new commit is introduced in poliastro:main branch
name: Validation test cases
on:
# A collection of events which trigger the validation action
push:
branches: [ main ]
release:
# Enable manually to execute the actions
workflow_dispatch:
jobs:
# Validate poliastro's new features
validation:
runs-on: ubuntu-latest
environment: validation-env
# Steps to be followed during validation job
steps:
- name: Trigger poliastro/validation
run: |
curl -XPOST -u "${{ secrets.VALIDATION_USER }}:${{ secrets.VALIDATION_PASS }}" \
-H "Accept: application/vnd.github.v3+json" \
-H "Content-Type: application/json" https://api.github.com/repos/poliastro/validation/actions/workflows/ci_actions.yml/dispatches \
--data '{"ref": "main"}' \
--fail
poliastro-0.16.2/.gitignore 0000664 0000000 0000000 00000003757 14201250233 0015610 0 ustar 00root root 0000000 0000000
# Created by https://www.gitignore.io/api/python,jupyternotebooks
# Edit at https://www.gitignore.io/?templates=python,jupyternotebooks
### JupyterNotebooks ###
# gitignore template for Jupyter Notebooks
# website: http://jupyter.org/
.ipynb_checkpoints
*/.ipynb_checkpoints/*
# IPython
profile_default/
ipython_config.py
# Remove previous ipynb_checkpoints
# git rm -r .ipynb_checkpoints/
### Python ###
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# pyenv
.python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# celery beat schedule file
celerybeat-schedule
# SageMath parsed files
*.sage.py
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# Mr Developer
.mr.developer.cfg
.project
.pydevproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# End of https://www.gitignore.io/api/python,jupyternotebooks
*.nja
.idea
.cache
.venv
# General
.DS_Store
poliastro-0.16.2/.importlinter 0000664 0000000 0000000 00000000562 14201250233 0016340 0 ustar 00root root 0000000 0000000 [importlinter]
# Include Astropy to properly analyze external submodules,
# see https://github.com/seddonym/import-linter/issues/111
root_packages =
poliastro
astropy
include_external_packages=True
[importlinter:contract:1]
name=poliastro.core does not import astropy.units
type=forbidden
source_modules=
poliastro.core
forbidden_modules=
astropy.units
poliastro-0.16.2/.isort.cfg 0000664 0000000 0000000 00000000164 14201250233 0015504 0 ustar 00root root 0000000 0000000 [settings]
multi_line_output=3
include_trailing_comma=True
force_grid_wrap=0
combine_as_imports=True
line_length=88
poliastro-0.16.2/.mailmap 0000664 0000000 0000000 00000010756 14201250233 0015236 0 ustar 00root root 0000000 0000000 <38282384+aOrionis@users.noreply.github.com>
Abdul Moiz
Abhishek Anant
Aditya Vikram Singh
Andrea Carballo
Angel RamĂrez Quispe
Bibiana Rivadeneira
Bibiana Rivadeneira Bibo
Dhruv Sondhi
Greg Lindahl
Himanshu Garg Himanshu Garg <43913398+Himanshu-Garg@users.noreply.github.com>
Himanshu Garg Himanshu-Garg
Iago Alonso
Isabel GonzĂĄlez
Ismael Jiménez
Ismael Jiménez
Javier Tegedor
Javier Tegedor
Johana Murcia <84646578+JohaMR@users.noreply.github.com> JohaMR <84646578+JohaMR@users.noreply.github.com>
Jonathan Erskine <38688728+jmerskine1@users.noreply.github.com>
Jorge MartĂnez Garrido
Jorge MartĂnez Garrido Jorge MartĂnez
Jorge MartĂnez Garrido Jorge M.G
Jorge MartĂnez Garrido
Jos van 't Hof <1447984+Josvth@users.noreply.github.com>
Juan Luis Cano RodrĂguez
Juan Luis Cano RodrĂguez
Juan Luis Cano RodrĂguez
Juan Luis Cano RodrĂguez
Juliana Nieto <64213327+junietoc@users.noreply.github.com> junietoc <64213327+junietoc@users.noreply.github.com>
Manuel López-Ibåñez <2620021+MLopez-Ibanez@users.noreply.github.com> MLopez-Ibanez <2620021+MLopez-Ibanez@users.noreply.github.com>
MarĂa Eugenia Cruz
Matt Rossman
Michael Pilosov <40366263+mathematicalmichael@users.noreply.github.com>
Nickolai Belakovski
Pablo Castro
Priyanshu Rohilla
Radhika Jadhav
Rishabh Nanawati
Ritiek Malhotra
Sarthak Jain
Syed Osama Hussain
Syed Osama Hussain <37876153+Syed-Osama-Hussain@users.noreply.github.com>
Tomek Mrugalski
Tomek Mrugalski
Tomek Mrugalski
Venkitesh
Yash Gondhalekar
Yash Gondhalekar Yash-10 <68844397+Yash-10@users.noreply.github.com>
Zac Miller
Zeke Sikelianos <5767468+zkl2@users.noreply.github.com>
poliastro-0.16.2/.pre-commit-config.yaml 0000664 0000000 0000000 00000001421 14201250233 0020063 0 ustar 00root root 0000000 0000000 ci:
autoupdate_commit_msg: "chore: [pre-commit.ci] pre-commit autoupdate"
autoupdate_schedule: monthly
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.0.1
hooks:
- id: check-added-large-files
- id: check-case-conflict
- id: check-merge-conflict
- id: check-symlinks
- id: check-json
- id: check-yaml
- id: check-toml
- id: check-xml
- id: debug-statements
- id: mixed-line-ending
- repo: https://github.com/PyCQA/isort
rev: 5.9.3
hooks:
- id: isort
args: ["--project=poliastro", "--section-default=THIRDPARTY"]
files: |
(?x)(
^src/|
^tests/
)
- repo: https://github.com/psf/black
rev: 21.10b0
hooks:
- id: black-jupyter
files: |
(?x)(
^src/|
^tests/
)
poliastro-0.16.2/.readthedocs.yml 0000664 0000000 0000000 00000000321 14201250233 0016666 0 ustar 00root root 0000000 0000000 version: 2
build:
os: "ubuntu-20.04"
tools:
python: "3.8"
python:
install:
- method: pip
path: .
extra_requirements:
- dev
- cesium
sphinx:
fail_on_warning: true
poliastro-0.16.2/CODE_OF_CONDUCT.md 0000664 0000000 0000000 00000006074 14201250233 0016412 0 ustar 00root root 0000000 0000000 # Code of Conduct for the poliastro community
The community of participants in poliastro is made up of members from
around the globe with a diverse set of skills, personalities, and
experiences. It is through these differences that our community
experiences success and continued growth. We expect everyone in our
community to follow these guidelines when interacting with others both
inside and outside of our community. Our goal is to keep ours a
positive, inclusive, successful, and growing community.
As members of the community,
- We pledge to treat all people with respect and provide a harassment-
and bullying-free environment, regardless of sex, sexual orientation
and/or gender identity, disability, physical appearance, body size,
race, nationality, ethnicity, and religion. In particular, sexual
language and imagery, sexist, racist, or otherwise exclusionary
jokes are not appropriate.
- We pledge to respect the work of others by recognizing
acknowledgment/citation requests of original authors. As authors, we
pledge to be explicit about how we want our own work to be cited or
acknowledged.
- We pledge to welcome those interested in joining the community, and
realize that including people with a variety of opinions and
backgrounds will only serve to enrich our community. In particular,
discussions relating to pros/cons of various technologies,
programming languages, and so on are welcome, but these should be
done with respect, taking proactive measure to ensure that all
participants are heard and feel confident that they can freely
express their opinions.
- We pledge to welcome questions and answer them respectfully, paying
particular attention to those new to the community. We pledge to
provide respectful criticisms and feedback in forums, especially in
discussion threads resulting from code contributions.
- We pledge to be conscientious of the perceptions of the wider
community and to respond to criticism respectfully. We will strive
to model behaviors that encourage productive debate and
disagreement, both within our community and where we are criticized.
We will treat those outside our community with the same respect as
people within our community.
- We pledge to help the entire community follow the code of conduct,
and to not remain silent when we see violations of the code of
conduct. We will take action when members of our community violate
this code such as contacting
(all emails sent to this address will be treated with the strictest
confidence) or talking privately with the person.
This code of conduct applies to all community situations online and
offline, including mailing lists, forums, social media, conferences,
meetings, associated social events, and one-to-one interactions.
Parts of this code of conduct have been adapted from the Astropy code of
conduct.
The Code of Conduct for the poliastro community is licensed under a
Creative Commons Attribution 4.0 International License. We encourage
other communities related to ours to use or adapt this code as they see
fit.
poliastro-0.16.2/CONTRIBUTING.md 0000664 0000000 0000000 00000016306 14201250233 0016043 0 ustar 00root root 0000000 0000000 # Contributing
poliastro is a community project, all contributions are more than welcome!
## What you can do
### Report bugs
Not only things can break, but also different people have
different use cases for the project. If you find anything that doesn't
work as expected or have suggestions, please open a new issue on our
[issue tracker](https://github.com/poliastro/poliastro/issues).
### Participate in the chat
Most of the project discussions happen in [the project chat](http://chat.poliastro.space/),
where announcements are first made, newcomers ask questions,
and in general project users exchange all sorts of information.
[Join today!](http://chat.poliastro.space/)
### Improve the Documentation
Documentation can always be expanded and improved.
The docs are stored in text files under the `docs/source` directory,
and the Python classes and methods also feature inline docs
in the form of docstrings.
### Contribute your research scripts
We would love to give your Astrodynamics scripts a home!
Please head to [our `contrib/` directory](https://github.com/poliastro/poliastro/tree/main/contrib)
for further information.
### Fix bugs and add new features
Code contributions are welcome! If you are looking for a place to start,
check out the ["good-first-issue" label](https://github.com/poliastro/poliastro/labels/good%20first%20issue)
on our issue tracker. Those tasks should be easier to fix than the others
and require less knowledge about the library.
## How to contribute
### Work from GitHub
GitHub makes it very easy to make small contributions
directly from your browser, without having to install any additional software.
To get familiar with the process, you can do
[this interactive GitHub training](https://lab.github.com/githubtraining/introduction-to-github).
Once you have finished it, you can edit the poliastro source files
straight from GitHub and open pull requests from your browser.
### Work locally
For more complex contributions, it will be more effective
to set up a local development environment and work from your own computer.
The most important thing is to understand how Git works. Git is a decentralized
version control system that preserves the history of the software, helps
tracking changes and allows for multiple versions of the code to exist
at the same time. To learn more, you can have a look at
[this Getting Started guide](https://docs.github.com/en/get-started/getting-started-with-git).
Finally, you might want to have an Integrated Development Environment (IDE)
that makes editing the source files easier.
If you are hesitant on what IDE or editor to use,
have a look at [PyCharm](https://www.jetbrains.com/pycharm/),
[Visual Studio Code](https://code.visualstudio.com/),
or [Spyder](https://www.spyder-ide.org/).
### Work from a cloud environment
There are some cloud options that give you
the flexibility of a powerful IDE with a terminal,
all from your web browser so you don't have to install anything.
Two popular cloud environments for development are
[the GitHub web editor](https://github.dev/poliastro/poliastro)
and [Gitpod](https://gitpod.io/#https://github.com/poliastro/poliastro/).
## Command line instructions
In the sections below you can read step-by-step guides to
perform common development tasks on the command line.
All these instructions are meant for UNIX-like operating systems,
for example:
- Linux (any distribution will work)
- macOS
- Windows Subsystem for Linux (WSL)
### Set up a development environment
To set up a development environment you will need Git and Python
up and running. You should only need to do this once!
Start by setting up Git:
1. [Install Git](https://git-scm.com/) on your computer.
2. [Sign up to GitHub](https://github.com/).
3. [Fork poliastro](https://help.github.com/articles/fork-a-repo/).
4. [Clone your fork](https://help.github.com/articles/cloning-a-repository/)
(remote name will be `origin`)
5. Add an `upstream` remote with `git remote add upstream https://github.com/poliastro/poliastro.git`
and fetch its information with `git fetch upstream`
6. Set your `main` branch to track `upstream` using `git branch --set-upstream-to=upstream/main`
Next, configure your Python environment:
6. Install Python for development.
7. Create a Python virtual environment using `python -m venv .venv`
8. Activate it using `source .venv/bin/activate`
9. Upgrade the development dependencies using `python -m pip install -U pip setuptools wheel flit tox`
10. Install the code in development mode using `python -m pip install -e .`
(this means that the installed code will change as soon as you change it in the
download location).
And with this, you will be ready to start contributing!
### Pull request workflow
Every time you want to contribute some code or documentation to poliastro,
you will need to follow these steps:
1. Make sure that your `main` branch is up to date: `git switch main`
(or `git checkout main`) and `git pull --rebase upstream main`
2. Create a new branch using `git switch --create descriptive-name-of-my-change`.
3. Make your changes!
4. Commit your changes using `git commit -m 'Add new awesome feature'`.
5. [Push to your fork](https://help.github.com/articles/pushing-to-a-remote/).
6. [Open a pull request!](https://help.github.com/articles/creating-a-pull-request/)
One branch corresponds to one pull request. This means that,
if you keep committing and pushing changes to the same branch,
the pull request will update automatically (you don't need to open a new one!).
When your pull request is merged, you can:
7. Update your `main` branch again: `git switch main` and `git pull --rebase upstream main`
8. Delete your local branch: `git branch --delete descriptive-name-of-my-change`
9. Refresh your fork: `git fetch --prune origin` and `git push origin main`
Remember that, whenever you want to start a new pull request,
you need to start from step 1.
### Build the documentation
To build the docs, run:
```console
(.venv) $ cd docs
(.venv) $ make html
```
After this, the new docs will be inside `build/html`. You can open them
by running an HTTP server:
```console
$ cd build/html
$ python -m http.server
Serving HTTP on 0.0.0.0 port 8000 ...
```
And point your browser to .
### Make code changes
You want to contribute new features or fix existing behavior? You are awesome!
Before rushing out though, make sure if the new feature you propose
is within the scope of the library (best thing is to ask in
[the chat](http://chat.poliastro.space/))
or that the fix you want to apply has a corresponding issue in the issue tracker.
Apart from all the steps described above, you need to have these extra things in mind:
1. Add tests to your code. You have lots of examples in the `tests/` directory
to get inspiration from. All new features and fixes should be tested,
and in the ideal case the coverage rate should increase or stay the same.
2. To check if your code is correct, run `tox -e reformat,check,py39-fast`
(`py39` stands for Python 3.9, you can replace it by `py38`).
3. Notice that you can run a subset of the tests by
passing extra arguments to pytest, for example running
`tox -e py39-fast -- -k "anomaly"`
Automatic services will ensure your code works
on all the supported operating systems and Python versions.
poliastro-0.16.2/COPYING 0000664 0000000 0000000 00000002154 14201250233 0014641 0 ustar 00root root 0000000 0000000 The MIT License (MIT)
Copyright (c) 2012-2021 Juan Luis Cano RodrĂguez and the poliastro development team
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
poliastro-0.16.2/MANIFEST.in 0000664 0000000 0000000 00000000246 14201250233 0015344 0 ustar 00root root 0000000 0000000 include COPYING
include AUTHORS
recursive-include tests *.py *.html
prune docs/source/examples/.ipynb_checkpoints
global-exclude *.py[cod] __pycache__ *.so *.dylib
poliastro-0.16.2/Makefile 0000664 0000000 0000000 00000000565 14201250233 0015252 0 ustar 00root root 0000000 0000000 DOCKER_BASE_IMAGE := "poliastro:dev"
DOCKER_CONTAINER_NAME := "poliastro-dev"
image: Dockerfile pyproject.toml
docker build \
-t poliastro:dev \
.
docker:
docker run \
-it \
--rm \
--name ${DOCKER_CONTAINER_NAME} \
--volume $(shell pwd):/code \
--user $(shell id -u):$(shell id -g) \
${DOCKER_BASE_IMAGE} \
bash
.PHONY: docker image
poliastro-0.16.2/README.md 0000664 0000000 0000000 00000020514 14201250233 0015065 0 ustar 00root root 0000000 0000000 [](https://www.poliastro.space/)
Name: | poliastro
:------------:|:--------------
**Website**: |
**Author**: | Juan Luis Cano RodrĂguez [](http://orcid.org/0000-0002-2187-161X)
**Version**: | 0.16.2
[](https://circleci.com/gh/poliastro/poliastro/?branch=0.16.x)
[](https://codecov.io/github/poliastro/poliastro?branch=0.16.x)
[](https://results.pre-commit.ci/latest/github/poliastro/poliastro/0.16.x)
[](https://docs.poliastro.space/en/v0.16.2/?badge=v0.16.2)
[](https://github.com/poliastro/poliastro/raw/0.16.x/COPYING)
[](https://zenodo.org/badge/latestdoi/11178845)
[](http://www.astropy.org/)
[](https://groups.io/g/poliastro-dev)
[](http://chat.poliastro.space/)
[](#backers)
[](#sponsors)
poliastro is an open source (MIT) pure Python library
for interactive Astrodynamics and Orbital Mechanics,
with a focus on ease of use, speed, and quick visualization.
It provides a simple and intuitive API,
and handles physical quantities with units.
Some features include
orbit propagation, solution of the Lambert\'s problem,
conversion between position and velocity vectors and classical orbital elements
and orbit plotting, among others.
It focuses on interplanetary applications,
but can also be used to analyze artificial satellites in Low-Earth Orbit (LEO).
```python
from poliastro.examples import molniya
molniya.plot()
```

# Documentation
[](https://docs.poliastro.space/en/v0.16.2/?badge=v0.16.2)
Complete documentation, including a user guide and an API reference, can
be read on the wonderful [Read the Docs](https://readthedocs.org/).
# Examples
[](https://mybinder.org/v2/gh/poliastro/poliastro/0.16.x?labpath=index.ipynb)
In the examples directory you can find several Jupyter notebooks with
specific applications of poliastro. You can launch a cloud Jupyter
server using [binder](https://mybinder.org/) to edit the notebooks
without installing anything. Try it out!
# Requirements
poliastro requires the following Python packages:
- NumPy, for basic numerical routines
- Astropy, for physical units and time handling
- numba, for accelerating the code
- jplephem, for the planetary ephemerides using SPICE kernels
- matplotlib, for orbit plotting
- plotly, for 2D and 3D interactive orbit plotting
- SciPy, for root finding and numerical propagation
poliastro is supported on Linux, macOS and Windows on Python 3.8 to 3.10.
[](https://circleci.com/gh/poliastro/poliastro/?branch=0.16.x)
# Installation
The easiest and fastest way to get the package up and running is to
install poliastro using [conda](http://conda.io):
```bash
$ conda install poliastro --channel conda-forge
```
Please check out the [documentation for alternative installation
methods](https://docs.poliastro.space/en/stable/installation.html#alternative-installation-methods).
# Problems and suggestions
If for any reason you get an unexpected error message or an incorrect
result, or you want to let the developers know about your use case,
please open a new issue in the [issue
tracker](https://github.com/poliastro/poliastro/issues) and we will try
to answer promptly.
# Contributing
poliastro is a community project, hence all contributions are more than
welcome! For more information, head to
[CONTRIBUTING.md](https://github.com/poliastro/poliastro/blob/0.16.x/CONTRIBUTING.md).
# Support
[](https://groups.io/g/poliastro-dev)
[](http://chat.poliastro.space/)
Release announcements and general discussion take place on our [Mailing
List](https://groups.io/g/poliastro-dev) .
For further clarifications and discussions, feel free to join Poliastro
[Chat Room](http://chat.poliastro.space/).
# Citing
If you use poliastro on your project, please [drop me a
line](mailto:hello@juanlu.space).
You can also use the DOI to cite it in your publications. This is the
latest one:
[](https://zenodo.org/badge/latestdoi/11178845)
And this is an example citation format:
Juan Luis Cano RodrĂguez et al.. (2015). poliastro: poliastro 0.4.0. Zenodo. 10.5281/zenodo.17462
# License
[](https://github.com/poliastro/poliastro/raw/0.16.x/COPYING)
poliastro is released under the MIT license, hence allowing commercial
use of the library. Please refer to the [COPYING](https://github.com/poliastro/poliastro/blob/0.16.x/COPYING) file.
# Credits
## Contributors
This project exists thanks to all the people who contribute!

## Backers
Thank you to all our backers! [Become a backer](https://opencollective.com/poliastro#backer).
[](https://opencollective.com/poliastro#backer)
## Sponsors
Support us by becoming a sponsor. Your logo will show up here with a link to your website.
[Become a sponsor](https://opencollective.com/poliastro#sponsor).
[](https://opencollective.com/poliastro/sponsor/0/website)
# FAQ
## What's up with the name?
poliastro comes from Polimi, which is the shortened name of the
Politecnico di Milano, the Italian university where I was studying while
writing this software. It's my tiny tribute to a place I came to love.
*Grazie mille!*
## Can I do \ with poliastro?
poliastro has been historically focused on interplanetary applications,
but we have been adding more features for artificial satellites in LEO.
Therefore, you might find that some features are currently lacking,
in particular propagation of General Perturbations orbital data
such as TLE/3LE, OMM, and the like.
Besides, poliastro is a community project that strives to be easy to use,
while at the same time producing correct results
[that are validated](https://github.com/poliastro/validation/)
against other [commonly used Astrodynamics software](https://docs.poliastro.space/en/v0.16.1/related.html)
such as GMAT and Orekit.
Therefore, you might find that its API is very different from
these projects,
and also that some advanced features are missing
(such as detailed spherical harmonics modeling of the Earth beyond J2 and J3).
We encourage you to [open an issue](https://github.com/poliastro/validation/issues/new)
so we can discuss future feature additions!
## What\'s the future of the project?
poliastro is actively maintained and receiving an influx of new
contributors thanks to the generous sponsorship of Google and the
European Space Agency. The best way to get an idea of the roadmap is to
see the [Milestones](https://github.com/poliastro/poliastro/milestones)
of the project.
poliastro-0.16.2/binder/ 0000775 0000000 0000000 00000000000 14201250233 0015047 5 ustar 00root root 0000000 0000000 poliastro-0.16.2/binder/environment.yml 0000664 0000000 0000000 00000000100 14201250233 0020125 0 ustar 00root root 0000000 0000000 name: python 3.10
dependencies:
- python=3.10
- jupytext>=1.13.3 poliastro-0.16.2/codemeta.json 0000664 0000000 0000000 00000013300 14201250233 0016255 0 ustar 00root root 0000000 0000000 {
"@context": "https://doi.org/10.5063/schema/codemeta-2.0",
"@type": "SoftwareSourceCode",
"license": "https://spdx.org/licenses/MIT",
"codeRepository": "https://github.com/poliastro/poliastro",
"datePublished": "2013-07-07",
"dateModified": "2020-05-08",
"downloadUrl": "https://github.com/poliastro/poliastro.git",
"issueTracker": "https://github.com/poliastro/poliastro/issues",
"name": "poliastro",
"version": "0.14.0",
"description": "poliastro is an open-source pure Python package dedicated to problems arising in Astrodynamics and Orbital Mechanics, such as orbit propagation, solution of Lambert's problem, conversion between position and velocity vectors, and classical orbital elements and orbit plotting, focusing on interplanetary applications.",
"releaseNotes": "https://docs.poliastro.space/en/v0.14.0/changelog.html#poliastro-0-14-0-2020-05-08",
"programmingLanguage": [
"Python3"
],
"softwareRequirements": [
"NumPy",
"Astropy",
"numba",
"jplephem",
"matplotlib",
"plotly",
"SciPy"
],
"author": [
{
"@type": "Person",
"givenName": "Juan Luis",
"familyName": "Cano Rodr\\u00edguez",
"affiliation": {
"@type": "Organization",
"name": "Satellogic"
}
},
{
"@type": "Person",
"givenName": "Antonio",
"familyName": "Hidalgo"
},
{
"@type": "Person",
"givenName": "Shreyas",
"familyName": "Bapat",
"affiliation": {
"@type": "Organization",
"name": "IIT Mandi"
}
},
{
"@type": "Person",
"givenName": "Jorge",
"affiliation": {
"@type": "Organization",
"name": "poliastro"
}
},
{
"@type": "Person",
"givenName": "Nikita",
"familyName": "Astrakhantsev",
"affiliation": {
"@type": "Organization",
"name": "University of Zurich"
}
},
{
"@type": "Person",
"givenName": "Chatziargyriou",
"familyName": "Eleftheria"
},
{
"@type": "Person",
"givenName": "Daniel",
"familyName": "Lubi\\u00e1n"
},
{
"@type": "Person",
"givenName": "Alberto Lorenzo ",
"familyName": "M\\u00e1rquez",
"affiliation": {
"@type": "Organization",
"name": "Dassault Syst\\u00e8mes"
}
},
{
"@type": "Person",
"givenName": "Abhishek ",
"familyName": "Chaurasia"
},
{
"@type": "Person",
"givenName": "Emily",
"familyName": "Selwood"
},
{
"@type": "Person",
"givenName": "Meu"
},
{
"@type": "Person",
"givenName": "Pablo Rodr\\u00edguez ",
"familyName": "Robles",
"affiliation": {
"@type": "Organization",
"name": "Technical University of Munich (TUM)"
}
},
{
"@type": "Person",
"givenName": "Tomek",
"familyName": "Mrugalski",
"affiliation": {
"@type": "Organization",
"name": "Internet Systems Consortium"
}
},
{
"@type": "Person",
"givenName": "Helge",
"familyName": "Eichhorn"
},
{
"@type": "Person",
"givenName": "Greg",
"familyName": "Lindahl"
},
{
"@type": "Person",
"givenName": "Andrej",
"familyName": "Rode"
},
{
"@type": "Person",
"givenName": "Himanshu ",
"familyName": "Garg"
},
{
"@type": "Person",
"givenName": "aOrionis"
},
{
"@type": "Person",
"givenName": "Ian",
"familyName": "DesJardin"
},
{
"@type": "Person",
"givenName": "Hrishikesh",
"familyName": "Goyal"
},
{
"@type": "Person",
"givenName": "priyanshu",
"familyName": "rohilla"
},
{
"@type": "Person",
"givenName": "AntoniiaK"
},
{
"@type": "Person",
"givenName": "Angala"
},
{
"@type": "Person",
"givenName": "Ahmada",
"familyName": "Yusril"
},
{
"@type": "Person",
"givenName": "Sarthak",
"familyName": "Jain",
"affiliation": {
"@type": "Organization",
"name": "IIT Indore"
}
},
{
"@type": "Person",
"givenName": "Syed Osama Hussain"
},
{
"@type": "Person",
"givenName": "Ole Streicher",
"affiliation": {
"@type": "Organization",
"name": "Leibniz Institute for Astrophysics"
}
},
{
"@type": "Person",
"givenName": "Iv\\u00e1n Castro Fern\\u00e1ndez"
},
{
"@type": "Person",
"givenName": "Fabian P. Schmidt"
},
{
"@type": "Person",
"givenName": "Divyansh",
"familyName": "Raina"
}
]
} poliastro-0.16.2/contrib/ 0000775 0000000 0000000 00000000000 14201250233 0015244 5 ustar 00root root 0000000 0000000 poliastro-0.16.2/contrib/README.md 0000664 0000000 0000000 00000003360 14201250233 0016525 0 ustar 00root root 0000000 0000000 # Community contributions
The `contrib` directory contains community contributions
that are not yet ready to be part of the poliastro API,
but are nonetheless useful for Astrodynamics Python users.
If you have a small script or set of them
related to Astrodynamics and Orbital Mechanics
but you feel they are "ugly", "not polished",
or you are just not sure "if anybody will find it useful",
we would be thrilled if you shared it with us here!
If you want to upload your code here,
please follow these steps:
- If it's only one script,
or comment at the top
specifying your name, email,
what the script does,
what extra libraries are needed (if any),
and cite any scientific references related to your work.
- If it's a series of scripts,
create a new `lower_case` named directory
having a `README.md` specifying your name, email,
what the scripts do,
and cite any scientific references related to your work,
as well as a `requirements.txt` or conda `environment.yml`
specifying any required dependencies.
And if you have any questions,
please [join our chat](http://chat.poliastro.space)
or [open an issue](https://github.com/poliastro/poliastro/issues/new)!
Note that:
- You don't need to use `git` or the command line!
The GitHub UI helps you
[add files to the repository](https://docs.github.com/en/github/managing-files-in-a-repository/adding-a-file-to-a-repository).
- We are interested in contributions that can be used from Python,
so either they should be pure Python
or be written in a compiled language with a Python wrapper.
- All contributions will be permissively licensed with the MIT license,
the one that poliastro uses.
If you don't agree with this,
we ask you to find a different place to share your contribution.
poliastro-0.16.2/contrib/relative.py 0000664 0000000 0000000 00000073414 14201250233 0017442 0 ustar 00root root 0000000 0000000 # -*- coding: utf-8 -*-
##############################################################################
##############################################################################
## ##
## FILE SUMMARY: RELATIVE ORBIT CLASS FOR PLOTTING AND VISUALISATION ##
## ##
## ##
## ##
## FILE DESCRIPTION: ##
## ##
## This file is a prototype file for a newly proposed "Relative Orbit" ##
## object in poliastro. The class 'relative' is defined by 02x instances ##
## of the 'twobody' object - one chief, and one deputy spacecraft, and ##
## it takes in the classical elements from each of them. The class then ##
## automatically computes the states of relative motion by linearizing ##
## the equations of motion based on the Clohessy-Wiltshire equations. ##
## ##
## The user may then either sample the state vectors of the relative ##
## motion over time by providing an epoch input, and plot the relative ##
## trajectory in a 3D and interactive matplotlib plot. ##
## ##
## The accuracy of this algorithm has been validated in AGI's STK 10. ##
## ##
## ##
## ##
## BY: SAMUEL Y.W. LOW (sammmlow@gmail.com) ##
## ##
## LAST MODIFIED: 02-05-2021 00:53 (GMT) ##
## ##
## IN CONTRIBUTION TO: POLIASTRO 0.15.dev0 ##
## ##
## ##
## ##
## REFERENCES: ##
## ##
## [1] Clohessy, W. H., Wiltshire, R. S. (1960). Terminal guidance ##
## system for satellite rendezvous. Journal of the Aerospace ##
## Sciences, 27(9), 653-658. doi:10.2514/8.8704 ##
## ##
## [2] Montenbruck, O., Gill, E. (2013). Satellite Orbits Models, ##
## Methods and Applications. Springer, Berlin. ##
## ##
## [3] D'Amico, S., &; Montenbruck, O. (2006). Proximity operations of ##
## formation-flying spacecraft using an eccentricity/inclination ##
## vector separation. Journal of Guidance, Control, and Dynamics, ##
## 29(3), 554-563. doi:10.2514/1.15114 ##
## ##
## [4] D'Amico, S. (2010) Autonomous Formation Flying in Low Earth Orbit ##
## PhD Dissertation, TU Delft. ##
## ##
## ##
## ##
##############################################################################
##############################################################################
# Import numpy.
import numpy as np
# Import matplotlib (possibly change to plotly for poliastro?)
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
# Import the relevant AstroPy libraries.
from astropy import time, units as u
# In order to plot astropy quantities, this library needs to be turned on.
from astropy.visualization import quantity_support
# Import the relevant PoliAstro libraries
from poliastro.bodies import Earth, Sun
from poliastro.twobody import Orbit
from poliastro.twobody.angles import nu_to_E, E_to_M
# Below is the definition of the relative orbits class (RelativeOrb).
# For the actual example script of how to use the class, scroll to the bottom!
##############################################################################
##############################################################################
## ##
## THE RELATIVE ORBIT CLASS: ##
## SCROLLDOWN TO THE BOTTOM FOR THE ACTUAL SCRIPT! ##
## ##
##############################################################################
##############################################################################
# Let us define a relative orbits class that can be defined by two orbits!
class RelativeOrb:
def __init__(self, satC, satD):
"""
When this class is initialized, it requires two poliastro twobody
objects: a chief orbiter (satC) and a deputy orbiter (satD). After
initialisation, a number of computations must be made.
First, the relative orbit is defined by the separation of the relative
inclination vector [ix,iy], and relative eccentricity vector [ex,ey].
Second, it is also defined by the difference between the semi-major
axis. These differential terms that are not time-dependent can be
initialized at the beginning.
The above are time-independent and thus can be computed before any
propagation is performed. The time-dependent components of relative
states (which is actually just 'du') will be initialized but not
computed until propagation.
Since the equations of motion are realized by linearizing about the
chief orbiter motion, all relative elements are defined in the order
of deputy-minus-chief, and absolute orbit elements are taken as the
chief elements. See D'Amico's paper [3] for more details, although I
have slightly modified his equations to take into account effects at
low-inclination orbits that was not captured in his paper.
Computed parameters on initialisation
-------------------------------------
- ix --> Relative inclination vector x-component
- iy --> Relative inclination vector y-component
- ex --> Relative eccentricity vector x-component
- ey --> Relative eccentricity vector y-component
- da --> Relative semi-major axis (normalized over the Chief SMA)
- dR --> Relative in-track separation due to RAAN differential
- M --> Linearized relative motion state transition matrix
"""
# Initialize the chief and deputy satellites that were class inputs.
self.satC = satC
self.satD = satD
# Retrieve the angular orbit parameters from the chief and deputy.
aD, aC = satD.a, satC.a # Semi-major axis (u.km)
iD, iC = satD.inc, satC.inc # Inclination (u.rad)
eD, eC = satD.ecc, satC.ecc # Eccentricity (u.one)
wD, wC = satD.argp, satC.argp # Arg of Periapsis (u.rad)
rD, rC = satD.raan, satC.raan # Right Ascension (u.rad)
# Compute auxiliary relative elements used in state transition matrix.
self.ix = ( iD - iC ).to_value(u.rad)
self.iy = ( ( np.sin(iC) * (rD - rC) ) ).to_value(u.rad)
self.ex = ( ( eD * np.cos(wD) ) - ( eC * np.cos(wC) ) ).to_value(u.one)
self.ey = ( ( eD * np.sin(wD) ) - ( eC * np.sin(wC) ) ).to_value(u.one)
self.da = ( ( aD - aC ) / aC ).to_value(u.one)
self.dR = ( ( rD - rC ) * np.cos(iC) ).to_value(u.rad)
# With the above, we can already define the state transition matrix
# from classical orbit elements to VVLH frame relative state vectors.
self.M = [[ self.da, 0.0, -1*self.ex, -1*self.ey ],
[ self.dR, -1.5*self.da, 0.0, 0.0 ],
[ 0.0, 0.0, -1*self.iy, self.ix ],
[ 0.0, 0.0, -1*self.ey, self.ex ],
[ -1.5*self.da, 0.0, 0.0, 0.0 ],
[ 0.0, 0.0, self.ix, self.iy ]]
# Finally, define the output of the relative trajectory propagation.
self.relPosArray = np.array([]).astype( type(1*u.km) )
self.relVelArray = np.array([]).astype( type(1*u.km/u.s) )
# Method to return a list of the computed eccentricity vector separation.
def get_eccentricity_separation(self):
"""
Returns the eccentricity separation vector [ex, ey] (dimensionless)
"""
return [ self.ex, self.ey ]
# Method to return a list of the computed inclination vector separation.
def get_inclination_separation(self):
"""
Returns the inclination separation vector [ix, iy] (dimensionless)
"""
return [ self.ix, self.iy ]
# Internal method to return a direction cosine matrix about the X-axis
def _dcmX(self, t):
"""
Input theta is the scalar angle (in radians, non Astropy unit).
Output is a 3x3 direction cosine matrix.
"""
dcm = np.array([[ 1.0, 0.0, 0.0 ],
[ 0.0, np.cos(t), np.sin(t) ],
[ 0.0, -1*np.sin(t), np.cos(t) ]])
return dcm
# Internal method to return a direction cosine matrix about the Z-axis
def _dcmZ(self, t):
"""
Input theta is the scalar angle (in radians, non Astropy unit).
Output is a 3x3 direction cosine matrix.
"""
dcm = np.array([[ np.cos(t), np.sin(t), 0.0 ],
[ -1*np.sin(t), np.cos(t), 0.0 ],
[ 0.0, 0.0, 1.0 ]])
return dcm
# Internal method to solve Kepler's equation for eccentric anomaly.
def _solve_kepler(self, M, ecc):
"""
Input a float mean anomaly (rad) and eccentricity, and solves for
the eccentric anomaly.
"""
E1 = M.to_value(u.rad) # Initialise eccentric anomaly
e = ecc.to_value(u.one) # Initialise the float eccentricity
residual = 1.0 # Initialise convergence residual
while residual >= 0.000001:
fn = E1 - (e*np.sin(E1)) - M.to_value(u.rad)
fd = 1 - (e*np.cos(E1))
E2 = E1 - (fn/fd)
residual = abs(E2-E1) # Compute residual
E1 = E2 # Update the eccentric anomaly
return E2 * u.rad
# Method to solve for the orbit position, velocity and true anomaly.
# (Requires the _dcmZ, _dcmX, and _solve_kepler internal methods)
def _solve_posn(self, a, e, i, w, R, M, mu):
"""
Inputs: Keplerian elements and gravitational constant (Astropy units).
- a -> Semi-major axis (u.km)
- e -> Eccentricity (u.one)
- i -> Inclination (u.deg)
- w -> Argument of Perigee (u.deg)
- R -> Right Angle of Asc Node (u.deg)
- M -> Mean Anomaly (u.deg)
- mu -> Gravitational constant (u.m^3 / u.s^2)
Output: Inertial position vector, velocity vector, and true anomaly
- pos -> inertial position (1x3 vector, u.km)
- vel -> inertial velocity (1x3 vector, u.km/u.s)
- trueAnom -> true anomaly (float, u.rad)
"""
# Ensure the conversion of the attractor's gravitational constant.
mu = mu.to(u.km**3/u.s**2)
# The general flow of the program, is to first solve for the radial
# position and velocity (in the inertial frame) via Kepler's equation.
# Thereafter, we obtain the inertial coordinates in the Hill frame,
# by performing a 3-1-3 Euler Angle rotation using an appropriate DCM.
# First, let us solve for the eccentric anomaly.
eccAnom = self._solve_kepler(M,e)
# With the eccentric anomaly, we can solve for position and velocity
# in the local orbital frame, using the polar equation for an ellipse.
pos_X = a * ( np.cos(eccAnom) - e)
pos_Y = a * np.sqrt( 1 - e**2 ) * np.sin(eccAnom)
pos_norm = np.sqrt( pos_X**2 + pos_Y**2 )
vel_const = np.sqrt( mu * a ) / pos_norm
vel_X = vel_const * ( -1 * np.sin(eccAnom) )
vel_Y = vel_const * ( np.sqrt( 1 - e**2 ) * np.cos(eccAnom) )
# To perform the conversion from local orbit plane to an ECI frame, we
# need perform the 313 Euler angle rotation in the following sequence:
# Right Angle of Ascending Node -> Inclination -> Argument of Latitude.
# Now, let us get us the DCM that converts to the hill-frame.
DCM_HN = np.matmul( self._dcmZ(w),
np.matmul( self._dcmX(i),
self._dcmZ(R) ) )
# Notice that the hill frame computation does not include a rotation
# of the true anomaly, and that's because the true anomaly has already
# been accounted for when computing pos_X and pos_Y using information
# from the eccentric anomaly. Including true anomaly in the DCM
# rotation would double-count that anomaly rotation.
# The current coordinates are in the local hill frame, and thus
# conversion from hill to inertial would be the transpose of HN.
DCM_NH = np.transpose(DCM_HN)
# For the matrix multiplication below, we will
# With the hill frame, we can now convert it to the ECI frame.
pos = np.matmul(DCM_NH, np.array([ pos_X.to_value(u.km),
pos_Y.to_value(u.km),
0.0 ]))
vel = np.matmul(DCM_NH, np.array([ vel_X.to_value(u.km/u.s),
vel_Y.to_value(u.km/u.s),
0.0 ]))
# Finally, let us not forget to compute the true anomaly.
trueAnom = np.arctan2( pos_Y.to_value(u.km), pos_X.to_value(u.km) )
# Position vector 1x3 (m), velocity vetor 1x3 (m), true anomaly (rad)
return pos * u.km, vel * (u.km/u.s), trueAnom * u.rad
# Propagate method, that must be called in order to store values for plots.
def propagate(self, duration=43200, step=60):
"""
Core method for relative trajectory generation. Inputs duration and
time step (integers), and updates the six state arrays of the object
(XYZ position and XYZ velocity) for N samples.
Input:
- duration - integer number of seconds (optional, default = 12 hours)
- step - integer time step size (optional, default = 1 minute)
Returns two numpy arrays
- Nx3 matrix of all position vectors
- Nx3 matrix of all velocity vector
"""
# Check if the orbit is an ellipse (closed)
if self.satC.ecc < 1 and self.satD.ecc < 1:
# Get the initial mean anomaly of the chief.
mC = E_to_M( nu_to_E( self.satC.nu, self.satC.ecc ), self.satC.ecc)
# Get the mean anomaly of the deputy.
mD = E_to_M( nu_to_E( self.satD.nu, self.satD.ecc ), self.satD.ecc)
# Get the mean motion of the chief.
nC = self.satC.n
# Get the mean motion of the deputy.
nD = self.satD.n
# Initialise relative position and velocity component arrays.
relPosArrayX, relPosArrayY, relPosArrayZ = [], [], []
relVelArrayX, relVelArrayY, relVelArrayZ = [], [], []
# Get the gravitational constant in u.km**3 / u.s**2
mu = self.satC.attractor.k.to( u.km**3 / u.s**2 )
# Initialise pi in terms of astropy units
pi = np.pi * 1 * u.rad
# Get a time step in Astropy units (seconds)
ts = step * u.s
# For each sample...
for t in range( 0, duration, step ):
# Update the mean anomaly of the chief (loop over pi).
mC = ( ( mC + pi + ( nC * ts ) ) % ( 2 * pi ) ) - pi
# Update the mean anomaly of the deputy (loop over pi).
mD = ( ( mD + pi + ( nD * ts ) ) % ( 2 * pi ) ) - pi
# Compute the chief position, velocity and true anomaly.
pC, vC, nuC = self._solve_posn(self.satC.a,
self.satC.ecc,
self.satC.inc,
self.satC.argp,
self.satC.raan,
mC, mu)
# Compute the deputy position, velocity and true anomaly.
pD, vD, nuD = self._solve_posn(self.satD.a,
self.satD.ecc,
self.satD.inc,
self.satD.argp,
self.satD.raan,
mD, mu)
# Get the argument of latitude of the chief.
uC = nuC + self.satC.argp
uC = ( uC + pi ) % ( 2 * pi ) - pi # Loop over pi
# Get the argument of latitude of the deputy.
uD = nuD + self.satD.argp
uD = ( uD + pi ) % ( 2 * pi ) - pi # Loop over pi
# Get the relative argument of latitude.
du = uD - uC
du = ( du + pi ) % ( 2 * pi ) - pi # Loop over pi
# Save the chief initial argument of latitude.
if t == 0:
uC0 = uC
# Compute the deputy elapsed argument of latitude.
uD_elapsed = uD - uC0
uD_elapsed = ( uD_elapsed + pi ) % ( 2 * pi ) - pi
uD_elapsed = uD_elapsed.to_value(u.rad)
# Compute the velocity magnitude
vCMag = np.sqrt( vC[0]**2 + vC[1]**2 + vC[2]**2 )
# Initialize the time-dependent input vector
uVect = np.array([ 1.0, uD_elapsed, np.cos(uC), np.sin(uC) ])
# Update Row 1 Column 0 of the state transition matrix.
self.M[1][0] = du.to_value(u.rad) + self.dR
# We may now compute the normalized relative state vectors
relPos = np.matmul( self.M[:3], uVect )
relVel = np.matmul( self.M[3:], uVect )
# Un-normalize the relative position vectors
relPosArrayX.append( (relPos[0] * self.satC.a).to_value(u.km) )
relPosArrayY.append( (relPos[1] * self.satC.a).to_value(u.km) )
relPosArrayZ.append( (relPos[2] * self.satC.a).to_value(u.km) )
# Un-normalize the relative velocity vectors
relVelArrayX.append( (relVel[0] * vCMag).to_value(u.km/u.s) )
relVelArrayY.append( (relVel[1] * vCMag).to_value(u.km/u.s) )
relVelArrayZ.append( (relVel[2] * vCMag).to_value(u.km/u.s) )
# Save the entire relativeEphem matrix.
self.relPosArrayX = np.array(relPosArrayX) * ( 1 * u.km )
self.relPosArrayY = np.array(relPosArrayY) * ( 1 * u.km )
self.relPosArrayZ = np.array(relPosArrayZ) * (-1 * u.km )
self.relVelArrayX = np.array(relVelArrayX) * ( 1 * u.km / u.s )
self.relVelArrayY = np.array(relVelArrayY) * ( 1 * u.km / u.s )
self.relVelArrayZ = np.array(relVelArrayZ) * (-1 * u.km / u.s )
# To allow for chaining...
return self
# Or if the orbit is a para/hyperbola...
else:
print('Error! Formations for non-closed orbits not supported!')
return self
def plot(self):
"""
Function to plot the relative trajectory. You must run the propagate()
method of the instance before the plot() method works.
"""
# Check if the user has propagated the relative orbit
if len(self.relPosArrayX) == 0 or len(self.relVelArrayX) == 0:
print('The relative trajectories have not been propagated yet!')
print('Have you forgotten to run the "propagate()" method?')
# Else, proceed with the propagation!
else:
with quantity_support():
# Initialise the matplotlib frame object.
figMain = plt.figure()
axOrbR = figMain.add_subplot(1,1,1, projection='3d')
# Initialise the plot labels.
axOrbR_label = 'Relative Position of Deputy'
# Plot the relative orbit position in local VVLH frame.
axOrbR.plot( self.relPosArrayZ, # X-track
self.relPosArrayY, # In-track
self.relPosArrayX, # Radial
label = axOrbR_label)
# Set the relative orbit position axes labels.
axOrbR.set_xlabel('Hill Frame Cross-Track Axis (km)')
axOrbR.set_ylabel('Hill Frame In-Track Axis (km)')
axOrbR.set_zlabel('Hill Frame Radial Axis (km)')
# Get the current axes limits on relative orbit plots.
axOrbR_axes_limits = [axOrbR.get_xlim()[0],
axOrbR.get_xlim()[1],
axOrbR.get_ylim()[0],
axOrbR.get_ylim()[1],
axOrbR.get_zlim()[0],
axOrbR.get_zlim()[1]]
# Using axOrbR_axes_limits above, we can find the minimum and
# maximum axes limits and the span of values.
axOrbR_axes_min = min(axOrbR_axes_limits)
axOrbR_axes_max = max(axOrbR_axes_limits)
axOrbR_axes_span = axOrbR_axes_max - axOrbR_axes_min
# Scale all axes equally for relative orbit plots
axOrbR.set_xlim( axOrbR_axes_min, axOrbR_axes_max )
axOrbR.set_ylim( axOrbR_axes_min, axOrbR_axes_max )
axOrbR.set_zlim( axOrbR_axes_min, axOrbR_axes_max )
# It is important that the XYZ axes in the VVLH (relative
# orbit) frame is scaled the same, else it is difficult to
# interpret the relative separations on different scales.
# Plot the chief satellite as a tri-axial quiver in VVLH frame.
axOrbR0 = axOrbR_axes_span * 0.1
axOrbR.quiver( 0,0,0,1,0,0, length = axOrbR0,
color = 'r', arrow_length_ratio=0.3 )
axOrbR.quiver( 0,0,0,0,1,0, length = axOrbR0,
color = 'r', arrow_length_ratio=0.3 )
axOrbR.quiver( 0,0,0,0,0,1, length = axOrbR0,
color = 'r', arrow_length_ratio=0.3 )
# Set tight layout.
plt.tight_layout()
plt.show()
def plot_v(self):
"""
Function to plot the relative velocity. You must run the propagate()
method of the instance before the plot_v() method works.
"""
# Check if the user has propagated the relative orbit
if len(self.relPosArrayX) == 0 or len(self.relVelArrayX) == 0:
print('The relative trajectories have not been propagated yet!')
print('Have you forgotten to run the "propagate()" method?')
# Else, proceed with the propagation!
else:
with quantity_support():
# Initialise the matplotlib frame object.
figMain = plt.figure()
axOrbV = figMain.add_subplot(1,1,1, projection='3d')
# Initialise the plot labels.
axOrbV_label = 'Relative Velocity of Deputy'
# Plot the relative orbit in local VVLH frame.
axOrbV.plot( self.relVelArrayZ, # X-track
self.relVelArrayY, # In-track
self.relVelArrayX, # Radial
label = axOrbV_label)
# Set the relative orbit position axes labels.
axOrbV.set_xlabel('Hill Frame Cross-Track Velocity (km/s)')
axOrbV.set_ylabel('Hill Frame In-Track Velocity (km/s)')
axOrbV.set_zlabel('Hill Frame Radial Velocity (km/s)')
# Get the current axes limits on relative orbit plots.
axOrbV_axes_limits = [axOrbV.get_xlim()[0],
axOrbV.get_xlim()[1],
axOrbV.get_ylim()[0],
axOrbV.get_ylim()[1],
axOrbV.get_zlim()[0],
axOrbV.get_zlim()[1]]
# Using axOrbV_axes_limits above, we can find the minimum and
# maximum axes limits and the span of values.
axOrbV_axes_min = min(axOrbV_axes_limits)
axOrbV_axes_max = max(axOrbV_axes_limits)
axOrbV_axes_span = axOrbV_axes_max - axOrbV_axes_min
# Scale all axes equally for relative orbit plots
axOrbV.set_xlim( axOrbV_axes_min, axOrbV_axes_max )
axOrbV.set_ylim( axOrbV_axes_min, axOrbV_axes_max )
axOrbV.set_zlim( axOrbV_axes_min, axOrbV_axes_max )
# Plot the chief satellite in-track velocity quiver in VVLH.
axOrbV0 = axOrbV_axes_span * 0.1
axOrbV.quiver( 0,0,0,1,0,0, length = axOrbV0,
color = 'r', arrow_length_ratio=0.3 )
axOrbV.quiver( 0,0,0,0,1,0, length = axOrbV0,
color = 'r', arrow_length_ratio=0.3 )
axOrbV.quiver( 0,0,0,0,0,1, length = axOrbV0,
color = 'r', arrow_length_ratio=0.3 )
# Set tight layout.
plt.tight_layout()
plt.show()
##############################################################################
##############################################################################
## ##
## END OF THE RELATIVE ORBITS CLASS DEFINITION. CLASS INSTANTIATION BELOW. ##
## ##
##############################################################################
##############################################################################
# The 'if __name__ == "__main__" statement allows others to import the
# RelativeOrb class without calling the rest of the script below:
if __name__ == "__main__":
# Initialize an example Satellite A as the chief spacecraft.
satC = Orbit.from_classical( attractor = Earth,
a = 6918.140 * u.km,
ecc = 1e-6 * u.one,
inc = 10.0 * u.deg,
raan = 70.0 * u.deg,
argp = 90.0 * u.deg,
nu = 1.65 * u.deg)
# Initialize an example Satellite B as the deputy spacecraft.
satD = Orbit.from_classical( attractor = Earth,
a = 6918.140 * u.km,
ecc = 0.012 * u.one,
inc = 11.4 * u.deg,
raan = 72.35 * u.deg,
argp = 135.0 * u.deg,
nu = -46.5725 * u.deg)
# Instantiate the relative orbits object.
relativeSat = RelativeOrb( satC, satD )
# Propagate the relative orbit
relativeSat.propagate()
# Plot the relative trajectory in local Hill Frame (VVLH) of the chief.
relativeSat.plot()
poliastro-0.16.2/contrib/rv2tle.py 0000775 0000000 0000000 00000025377 14201250233 0017055 0 ustar 00root root 0000000 0000000 """
Author: jtegedor
Python implementation of RV2TLE program for computation of mean orbital elements
from state vector, for an Earth-orbitting satellite
Original C++ implementation available in http://sat.belastro.net/satelliteorbitdetermination.com/.
GitHub repository with MIT license here: https://github.com/interplanetarychris/scottcampbell-satfit
Variables names have been kept similar to the original implementation, for easier comparison
"""
from astropy import coordinates as coord, units as u
from astropy.coordinates import TEME
from astropy.time import Time
from poliastro.twobody import Orbit
from poliastro.bodies import Earth
from poliastro.examples import iss
from poliastro.twobody import angles
import numpy as np
import math
from sgp4.api import Satrec, SGP4_ERRORS, WGS84
def unitv(v):
"""
Compute unitary vector of numpy array v
"""
return v / np.linalg.norm(v)
def acose(x):
"""
Custom implementation of numpy.acose
Returns either 0 or math.pi if input value out of [-1, 1]
"""
result = 0.0
if x > 1:
result = 0
elif x < -1:
result = math.pi
else:
result = math.acos(x)
return result
def fmod2p(x):
"""
Custom implementation of math.fmod
Returns a value between 0 and 2 * math.pi
"""
rval = math.fmod(x, 2 * math.pi)
if rval < 0:
rval += 2 * math.pi
return rval
def rvel(r, v):
"""
Convert state vector to mean orbital elements
"""
# Needed constants
XJ3 = -2.53881e-6
XKE = 0.0743669161331734132 # = (G*M)^(1/2)*(er/min)^(3/2) where G
CK2 = 5.413079e-4
A3OVK2 = -1 * XJ3 / CK2
# Position in Earth radii, velocity in km / (Earth radii) / min
rr2 = r.value / 6378.135
vv2 = v.value * 60 / 6378.135
vk = 1.0 / XKE * vv2 # smult
h = np.cross(rr2, vk) # cross
pl = np.dot(h, h)
vz = np.array([0.0, 0.0, 1.0])
n = np.cross(vz, h)
n = unitv(n)
rk = np.linalg.norm(rr2)
rdotk = np.dot(rr2, vv2) / rk
rfdotk = np.linalg.norm(h) * XKE / rk
temp = np.dot(rr2, n) / rk
uk = acose(temp)
if rr2[2] < 0.0:
uk = 2 * math.pi - uk
vz = np.cross(vk, h)
vy = -1 / rk * rr2
vec = vz + vy
ek = np.linalg.norm(vec)
if (ek > 1.0):
print(ek)
return # open orbit
xnodek = math.atan2(n[1], n[0])
if (xnodek < 0.0):
xnodek += 2 * math.pi
temp = np.sqrt(h[0] ** 2 + h[1] ** 2)
xinck = math.atan2(temp, h[2])
temp = np.dot(vec, n) / ek
wk = acose(temp)
if (vec[2] < 0):
wk = fmod2p(2 * math.pi - wk)
aodp = pl / (1.0 - ek ** 2)
xn = XKE * aodp ** (-1.5)
# In the first loop the osculating elements rk, uk, xnodek, xinck, rdotk,
# and rfdotk are used as anchors to find the corresponding final SGP4
# mean elements r, u, xnodeo, xincl, rdot, and rfdot. Several other final
# mean values based on these are also found: betal, cosio, sinio, theta2,
# cos2u, sin2u, x3thm1, x7thm1, x1mth2. In addition, the osculating values
# initially held by aodp, pl, and xn are replaced by intermediate
# (not osculating and not mean) values used by SGP4. The loop converges
# on the value of pl in about four iterations.
# seed value for first loop
xincl = xinck
u = uk
for _ in range(0, 99):
a2 = pl
betal = math.sqrt(pl / aodp)
temp1 = CK2 / pl
temp2 = temp1 / pl
cosio = math.cos(xincl)
sinio = math.sin(xincl)
sin2u = math.sin(2 * u)
cos2u = math.cos(2 * u)
theta2 = cosio * cosio
x3thm1 = 3 * theta2 - 1
x1mth2 = 1 - theta2
x7thm1 = 7 * theta2 - 1
r = (rk - 0.5 * temp1 * x1mth2 * cos2u) \
/ (1 - 1.5 * temp2 * betal * x3thm1)
u = uk + .25 * temp2 * x7thm1 * sin2u
xnodeo = xnodek - 1.5 * temp2 * cosio * sin2u
xincl = xinck - 1.5 * temp2 * cosio * sinio * cos2u
rdot = rdotk + xn * temp1 * x1mth2 * sin2u
rfdot = rfdotk - xn * temp1 * (x1mth2 * cos2u + 1.5 * x3thm1)
pl = (r * rfdot / XKE) ** 2
# vis-viva equation
adop = 1 / (2 / r - (rdot ** 2 + rfdot ** 2) / (XKE ** 2))
xn = XKE * aodp ** (-1.5)
if math.fabs(a2 - pl) < 1e-13:
break
# The next values are calculated from constants and a combination of mean
# and intermediate quantities from the first loop. These values all remain
# fixed and are used in the second loop.
# preliminary values for the second loops
ecose = 1 - r / adop
esine = r * rdot / (XKE * np.sqrt(aodp)) # needed for Kepler's eqn
elsq = 1 - pl / adop # intermediate eccentricity squared
xlcof = .125 * A3OVK2 * sinio * (3 + 5 * cosio) / (1 + cosio)
aycof = 0.25 * A3OVK2 * sinio
temp1 = esine / (1 + np.sqrt(1 - elsq))
cosu = math.cos(u)
sinu = math.sin(u)
# The second loop normally converges in about six iterations to the final
# mean value for the eccentricity, eo. The mean perigee, omegao, is also
# determined. Cosepw and sinepw are found to high accuracy and
# are used to calculate an intermediate value for the eccentric anomaly,
# temp2. Temp2 is then used in Kepler's equation to find an intermediate
# value for the true longitude, capu.
# seed values for loop
eo = np.sqrt(elsq)
omegao = wk
axn = eo * math.cos(omegao)
for _ in range(0, 99):
a2 = eo
beta = 1 - eo ** 2
aynl = aycof / (aodp * beta)
ayn = eo * math.sin(omegao) + aynl
cosepw = r * cosu / aodp + axn - ayn * temp1
sinepw = r * sinu / aodp + ayn + axn * temp1
axn = cosepw * ecose + sinepw * esine
ayn = sinepw * ecose - cosepw * esine
omegao = fmod2p(math.atan2(ayn - aynl, axn))
# use weighted average to tame instability at high eccentricities
eo = 0.9 * eo + 0.1 * (axn / math.cos(omegao))
if eo > 0.999:
eo = 0.999
if math.fabs(a2 - eo) < 1e-13:
break
capu = math.atan2(sinepw, cosepw) - esine # Kepler's equation
xll = temp * xlcof * axn
# xll adjusts the intermediate true longitude
# capu, to the mean true longitude, xl
xl = capu - xll
xmo = fmod2p(xl - omegao) # mean anomaly
# The third loop usually converges after three iterations to the
# mean semi-major axis, a1, which is then used to find the mean motion, xno.
a0 = aodp
a1 = a0
beta2 = np.sqrt(beta)
temp = 1.5 * CK2 * x3thm1 / (beta * beta2)
for _ in range(0, 99):
a2 = a1
d0 = temp / (a0 ** 2)
a0 = aodp * (1.0 - d0)
d1 = temp / (a1 ** 2)
a1 = a0 / (1 - d1 / 3 - d1 ** 2 - 134 * d1 ** 3 / 81)
if math.fabs(a2 - a1) < 1e-3:
break
xno = XKE * a1 ** (-1.5)
return xincl, xnodeo, eo, omegao, xmo, xno
def el2rv(inc, raan, ecc, argp, mean_anomaly, mean_motion, epoch):
"""
Converts mean orbital elements to state vector
"""
time_tle = epoch.jd - 2433281.5
sat = Satrec()
sat.sgp4init(WGS84, 'i', 0, time_tle, 0.0, 0.0, 0.0, ecc, argp, inc, mean_anomaly, mean_motion, raan)
errorCode, rTEME, vTEME = sat.sgp4(epoch.jd1, epoch.jd2)
if errorCode != 0:
raise RuntimeError(SGP4_ERRORS[errorCode])
pTEME = coord.CartesianRepresentation(rTEME * u.km)
vTEME = coord.CartesianDifferential(vTEME * u.km / u.s)
svTEME = TEME(pTEME.with_differentials(vTEME), obstime=epoch)
svITRS = svTEME.transform_to(coord.ITRS(obstime=epoch))
orb = Orbit.from_coords(Earth, svITRS)
return orb.r, orb.v
def rv2el(rr, vv, epoch):
"""
Computes mean orbital elements from state vector
"""
epoch_time = Time(epoch, format='datetime', scale='utc')
# SPG4 k-elements from state vector
inck, raank, ecck, argpk, mAnomalyk, mMotionk = rvel(rr, vv)
# SPG4 propagation of k-elements to rr', vv'
pos, vel = el2rv(inck, raank, ecck, argpk, mAnomalyk, mMotionk, epoch_time)
inc2, raan2, ecc2, argp2, mAnomaly2, mMotion2 = rvel(pos, vel) # SPG4 x-elements from state vectors
# First correction
incz = 2 * inck - inc2
raanz = 2 * raank - raan2
eccz = 2 * ecck - ecc2
argpz = 2 * argpk - argp2
mAnomalyz = 2 * mAnomalyk - mAnomaly2
mMotionz = 2 * mMotionk - mMotion2
# second correction is a small adjustment to z-elements
pos, vel = el2rv(incz, raanz, eccz, argpz, mAnomalyz, mMotionz, epoch_time)
inc3, raan3, ecc3, argp3, mAnomaly3, mMotion3 = rvel(pos, vel)
inc = incz + inck - inc3
raan = raanz + raank - raan3
ecc = eccz + ecck - ecc3
argp = argpz + argpk - argp3
mAnomaly = mAnomalyz + mAnomalyk - mAnomaly3
mMotion = mMotionz + mMotionk - mMotion3
return inc, raan, ecc, argp, mAnomaly, mMotion
if __name__ == "__main__":
# Display some initial data
print(f" Orbit: {iss}")
print(" State vector [poliastro]")
print(f" r = {iss.r}")
print(f" v = {iss.v}")
print()
# Reference epoch
epoch = Time(iss.epoch, format='datetime', scale='utc')
# Store poliastro orbital elements (osculating)
ecc_anomaly = angles.nu_to_E(iss.nu, iss.ecc)
mean_anomaly = angles.E_to_M(ecc_anomaly, iss.ecc)
# Compute orbital elements required by spg4 (mean)
inc, raan, ecc, argp, m_ano, m_mot = rv2el(iss.r, iss.v, iss.epoch)
# Display differences
print(" Poliastro(osc) rv2el(mean)")
print(f"Ecc : {iss.ecc:10.5f}{'':15}{ecc:10.5f}")
print(f"Incl [deg] : {math.degrees(iss.inc.value):10.5f}{'':15}{math.degrees(inc):10.5f}")
print(f"n [deg/min] : {math.degrees(iss.n.to(u.rad/u.minute).value):10.5f}{'':15}{math.degrees(m_mot):10.5f}")
print(f"RAAN [deg] : {math.degrees(iss.raan.value):10.5f}{'':15}{math.degrees(raan):10.5f}")
print(f"Argp + M [deg] : {math.degrees(iss.argp.value+mean_anomaly.value):10.5f}{'':15}{math.degrees(argp+m_ano):10.5f}")
print()
# Obtain state vector from spg4 and mean elements
sat = Satrec()
sat.sgp4init(WGS84, 'i', 0, epoch.jd - 2433281.5, 0.0, 0.0, 0.0, ecc, argp, inc, m_ano, m_mot, raan)
errorCode, rTEME, vTEME = sat.sgp4(epoch.jd1, epoch.jd2)
if errorCode != 0:
raise RuntimeError(SGP4_ERRORS[errorCode])
# Convert state vector from TEME (True Equator Mean Equinox) to ITRS
pTEME = coord.CartesianRepresentation(rTEME * u.km)
vTEME = coord.CartesianDifferential(vTEME * u.km / u.s)
svTEME = TEME(pTEME.with_differentials(vTEME), obstime=iss.epoch)
svITRS = svTEME.transform_to(coord.ITRS(obstime=iss.epoch))
sv = Orbit.from_coords(Earth, svITRS)
# Display results
print("State vector [rv2el]")
print(f" r = {sv.r}")
print(f" v = {sv.v}")
print()
print("State vector differences [poliastro - rv2el]")
print(f" dr = {iss.r - sv.r}")
print(f" dv = {iss.v - sv.v}")
print()
poliastro-0.16.2/docs/ 0000775 0000000 0000000 00000000000 14201250233 0014534 5 ustar 00root root 0000000 0000000 poliastro-0.16.2/docs/Makefile 0000664 0000000 0000000 00000015654 14201250233 0016207 0 ustar 00root root 0000000 0000000 # Makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
SRCDIR = source
EXAMPLESDIR = examples
BUILDDIR = build
# User-friendly check for sphinx-build
ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
endif
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(SRCDIR)
# the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) $(SRCDIR)
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
help:
@echo "Please use \`make ' where is one of"
@echo " examples to make Jupyter notebook examples from *.md"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " singlehtml to make a single large HTML file"
@echo " pickle to make pickle files"
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " qthelp to make HTML files and a qthelp project"
@echo " devhelp to make HTML files and a Devhelp project"
@echo " epub to make an epub"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " latexpdf to make LaTeX files and run them through pdflatex"
@echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
@echo " text to make text files"
@echo " man to make manual pages"
@echo " texinfo to make Texinfo files"
@echo " info to make Texinfo files and run them through makeinfo"
@echo " gettext to make PO message catalogs"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " xml to make Docutils-native XML files"
@echo " pseudoxml to make pseudoxml-XML files for display purposes"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
clean:
rm -rf $(BUILDDIR)/* $(SRCDIR)/$(EXAMPLESDIR)/*.ipynb
examples:
@echo "Building Jupyter notebook examples..."
cd $(SRCDIR)/$(EXAMPLESDIR) && jupytext --to ipynb --execute *.mystnb
@echo "Finished!"
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
singlehtml:
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/poliastro.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/poliastro.qhc"
devhelp:
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@echo "Build finished."
@echo "To view the help file:"
@echo "# mkdir -p $$HOME/.local/share/devhelp/poliastro"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/poliastro"
@echo "# devhelp"
epub:
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make' in that directory to run these through (pdf)latex" \
"(use \`make latexpdf' here to do that automatically)."
latexpdf:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through pdflatex..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
latexpdfja:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through platex and dvipdfmx..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
text:
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."
man:
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
texinfo:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
@echo "Run \`make' in that directory to run these through makeinfo" \
"(use \`make info' here to do that automatically)."
info:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo "Running Texinfo files through makeinfo..."
make -C $(BUILDDIR)/texinfo info
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
gettext:
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
@echo
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."
xml:
$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
@echo
@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
pseudoxml:
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
@echo
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."
poliastro-0.16.2/docs/source/ 0000775 0000000 0000000 00000000000 14201250233 0016034 5 ustar 00root root 0000000 0000000 poliastro-0.16.2/docs/source/_ext/ 0000775 0000000 0000000 00000000000 14201250233 0016773 5 ustar 00root root 0000000 0000000 poliastro-0.16.2/docs/source/_ext/sphinx_github_role.py 0000664 0000000 0000000 00000005357 14201250233 0023253 0 ustar 00root root 0000000 0000000 """
sphinx-github-role
A github role for Sphinx
Taken from https://github.com/astrojuanlu/sphinx-github-role/blob/0ccf5c07d3/src/sphinx_github_role/__init__.py
"""
from __future__ import annotations
import re
from typing import TYPE_CHECKING, Any
from docutils import nodes
from sphinx.util.docutils import ReferenceRole
if TYPE_CHECKING:
from docutils.nodes import Node, system_message
from sphinx.application import Sphinx
from sphinx.config import Config
__version__ = "0.1"
_DEFAULTS = [None, None]
def setup_github_role(_: Sphinx, config: Config) -> None:
if "github_default_org_project" in config.values:
try:
default_organization, default_project = config["github_default_org_project"]
except (TypeError, ValueError) as exc:
raise ValueError(
"Invalid github_default_org_project configuration: "
f"'{config['github_default_org_project']}'"
) from exc
if not default_organization and default_project:
raise ValueError(
"GitHub default organization cannot be empty if default project is set"
)
_DEFAULTS[0] = default_organization
_DEFAULTS[1] = default_project
class GitHub(ReferenceRole):
# For example: org/proj#1
gh_re = re.compile(
r"""((?P.+)/)? # Optional organization
(?P.+)? # Optional project
\#(?P\d+) # Issue or pull request id""",
re.VERBOSE,
)
# The /issues/{num} and /pull/{num} URLs automatically redirect
gh_tpl = "https://github.com/{org}/{proj}/issues/{num}"
def run(self) -> tuple[list[Node], list[system_message]]:
# breakpoint()
match = self.gh_re.fullmatch(self.target)
try:
parts = match.groupdict()
except AttributeError as exc:
raise ValueError(f"Malformed link '{self.rawtext}'") from exc
parts["org"] = parts["org"] or _DEFAULTS[0]
parts["proj"] = parts["proj"] or _DEFAULTS[1]
if not parts["org"] or not parts["proj"]:
raise ValueError(
"Incomplete configuration or GitHub reference: "
f"default organization = '{_DEFAULTS[0]}', "
f"default project = '{_DEFAULTS[1]}', "
f"role text = '{self.rawtext}'"
)
node = nodes.reference(
self.rawtext,
self.title,
refuri=self.gh_tpl.format(**parts),
)
return [node], []
def setup(app: Sphinx) -> dict[str, Any]:
app.add_config_value("github_default_org_project", ("", ""), None)
app.add_role("github", GitHub())
app.connect("config-inited", setup_github_role)
return {"version": __version__, "parallel_read_safe": True}
poliastro-0.16.2/docs/source/_static/ 0000775 0000000 0000000 00000000000 14201250233 0017462 5 ustar 00root root 0000000 0000000 poliastro-0.16.2/docs/source/_static/cesium.gif 0000664 0000000 0000000 00004510465 14201250233 0021455 0 ustar 00root root 0000000 0000000 GIF89aw !ù
!ÿNETSCAPE2.0 , § 0T'Fw"B6bS SNTum9DGdG4;W\ŹÊĐŃlk%5fčiȘ
b}ą¶ÆÍLȘ!-Bbł)RZa^Yq±ŹĂBLb]QźÂĐč16ÄÍĐĐÒÒTTLQMI?\nążY/Ł»u}uš§žxĄŒŹÁÍx DE~
PsiVP% +pBBtą ĆËÊ`YO2