Build an Aerie-compatible JAR file¶
+This isn’t yet supported! But this page will be populated as soon as it is.
+diff --git a/README.md b/README.md index 235aeb0..6698aea 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,23 @@ # pymerlin -A python modeling framework for Aerie. +pymerlin is a discrete event simulation framework, built for use in the [Aerie](https://github.com/NASA-AMMOS/aerie>) ecosystem. + +To learn more about Aerie, read the [Aerie Docs](https://nasa-ammos.github.io/aerie-docs). ### TODO: - [ ] Daemon tasks -- [ ] More interesting cells and resources -- [x] Conditions on discrete cells -- [ ] Conditions on continuous cells +- [x] More interesting cells and resources +- [x] Conditions on static cells +- [x] Conditions on autonomous cells - [x] Child tasks - [ ] Spiceypy - [ ] JPL time - [ ] pip-installable models - [ ] build Aerie-compatible jars and provide docker-compose file with python +- [ ] checkpoint restart ## Prerequisites @@ -50,8 +53,13 @@ hybrid system, which may be more difficult to characterize. ## Building pymerlin.jar +If any changes are made to the java code, rebuild the jar and place it in the correct location as follows: + ```shell -cd pymerlin-java +cd java ./gradlew assemble mv pymerlin/build/libs/pymerlin.jar ../pymerlin/_internal/jars -``` \ No newline at end of file +``` + +The jar lives inside of the `pymerlin` python source directory because that ensures that it will be packaged +(and accessible) in a distribution. \ No newline at end of file diff --git a/docs-src/2_guides/build-jar.md b/docs-src/2_guides/build-jar.md new file mode 100644 index 0000000..e8c0de7 --- /dev/null +++ b/docs-src/2_guides/build-jar.md @@ -0,0 +1,3 @@ +# Build an Aerie-compatible JAR file + +This isn't yet supported! But this page will be populated as soon as it is. \ No newline at end of file diff --git a/docs-src/2_guides/index.md b/docs-src/2_guides/index.md index c443d6c..3ad956d 100644 --- a/docs-src/2_guides/index.md +++ b/docs-src/2_guides/index.md @@ -9,4 +9,5 @@ powermodel telecom scheduling spice +build-jar ``` diff --git a/docs-src/3_explanation/command-errors.md b/docs-src/3_explanation/command-errors.md index 06ff992..367855a 100644 --- a/docs-src/3_explanation/command-errors.md +++ b/docs-src/3_explanation/command-errors.md @@ -9,14 +9,14 @@ A command error, sometimes called a command file error, describes the situation The consequence of a command error can range from lost opportunities (e.g. a spacecraft does not record data of a particular event of interest), to loss of mission (the spacecraft is permanently incapacitated). The flight system’s fault protection subsystem is designed to minimize the consequence of command error by putting the spacecraft into a “safe mode” when certain automatic fault detection, isolation, and recovery (FDIR) mechanisms are triggered. There are, however, command errors that FDIRs are powerless against: -- CFDP 2 delayed packets (Clipper) -- Incorrect inputs to maneuvers (Mars Climate Orbiter) -- Unexpected failure modes of FSW (MSL sol 200) -- Incorrect observation timings (I don’t have a specific example here) -- Incorrect Earth vector values (Viking) -- Concurrent communication of multiple spacecraft in a constellation (MMS) -- Unintentional sequence deletes (MSL) -- Sequences that don’t set a new parameter that was added in a new FSW version (MSL) +- CFDP 2 delayed packets +- Incorrect inputs to maneuvers +- Unexpected failure modes of FSW +- Incorrect observation timings +- Incorrect Earth vector values +- Concurrent communication of multiple spacecraft in a constellation +- Unintentional sequence deletes +- Sequences that don’t set a new parameter that was added in a new FSW version ## Avoiding Command Errors In order to reduce the risk of command error, the ground system may perform certain checks before allowing a message to be sent to the spacecraft. These checks range from constraints on the syntax of command files, to some abstract interpretation of the command files, to simulation of these command files. Some desirable characteristics of a ground system check: diff --git a/docs-src/architecture.md b/docs-src/architecture.md index a4ef72c..0e8b063 100644 --- a/docs-src/architecture.md +++ b/docs-src/architecture.md @@ -13,4 +13,21 @@ The main tenet of pymerlin is approachability, and its aim is to enable rapid pr While where possible, performance will be considered, it is expected that someone who wants to seriously engineer the performance of their simulation will port their code to Java - which has the double benefit of removing socket communication overhead, as well as giving the engineer a single Java process to instrument and analyze, rather than a -hybrid system, which may be more difficult to characterize. \ No newline at end of file +hybrid system, which may be more difficult to characterize. + +## Round trips +Some objects that the mission model provides to the simulation driver are _pass-through_ objects - i.e. the driver +merely returns these objects to the mission model when it is appropriate to do so. These objects need not be converted +to Java types - it is sufficient to pass a handle to the simulation driver, as long as the handle can be used to look +up the original object when needed. This is why certain global variables exist in `_globals.py` - they are used to cache +python objects and pass only their id to the Java process. + +:::{warning} +As implemented, this can be a source of a memory leak. Some careful cleanup is required to make this approach viable +for larger use cases +::: + +For resources and activity arguments (i.e. things that are represented as "SerializedValue" on the Java side), it is +important _not_ to make use of the python cache. This will help with integrating a python mission model with the rest +of the Aerie system by allowing the python code to handle inputs generated elsewhere in the system, and provide outputs +that can be understood by the rest of the system. \ No newline at end of file diff --git a/docs-src/developer.md b/docs-src/developer.md index 93bb2de..b8c0c4b 100644 --- a/docs-src/developer.md +++ b/docs-src/developer.md @@ -7,4 +7,12 @@ For pymerlin development, you'll need: Additional libraries: - build (for packaging) - twine (for publishing) -- pytest (for running tests) \ No newline at end of file +- pytest (for running tests) + +## Building pymerlin.jar + +```shell +cd java +./gradlew assemble +mv pymerlin/build/libs/pymerlin.jar ../pymerlin/_internal/jars +``` \ No newline at end of file diff --git a/docs-src/documentation.md b/docs-src/documentation.md index 5bdd255..6cfdb24 100644 --- a/docs-src/documentation.md +++ b/docs-src/documentation.md @@ -12,4 +12,17 @@ make clean html This documentation is built using [sphinx](https://www.sphinx-doc.org/en/master/) with the [MyST](https://mystmd.org/) plugin, using the [Furo](https://pradyunsg.me/furo/) theme. Python docstrings are automatically parsed and included in -this documentation using the [sphinx-autodoc2](https://sphinx-autodoc2.readthedocs.io) extension. \ No newline at end of file +this documentation using the [sphinx-autodoc2](https://sphinx-autodoc2.readthedocs.io) extension. + +## Style + +Refer to [https://developers.google.com/style](https://developers.google.com/style) for guidance. Any particularly salient points should be reproduced in this document. + +pymerlin is always lowercase. It may be styled as regular text or in a code block like this: `pymerlin` depending on the +context. + +## Referencing Aerie + +pymerlin documentation should be self-contained for users who are not using an Aerie deployment - this means that +some concepts will be repeated across pymerlin and Aerie documentation. In these scenarios, the relevant Aerie +documentation page should be linked in a "Further reading" section at the bottom of the page. \ No newline at end of file diff --git a/docs-src/index.md b/docs-src/index.md index 37331a9..f65056f 100644 --- a/docs-src/index.md +++ b/docs-src/index.md @@ -4,17 +4,13 @@ hide-toc: true # pymerlin -pymerlin is a discrete event simulation framework, built for use in the [Aerie](https://github.com/NASA-AMMOS/aerie>) ecosystem. - -To learn more about Aerie, read the [Aerie Docs](https://nasa-ammos.github.io/aerie-docs). - -Ready to get started? Check out the [Quickstart](./quickstart.md) guide. - ```{include} ../README.md :start-after: :end-before: ``` +Ready to get started? Check out the [Quickstart](./quickstart.md) guide. + ## Source code You can access the source code at: [https://github.com/mattdailis/pymerlin](https://github.com/mattdailis/pymerlin). diff --git a/docs-src/quickstart.md b/docs-src/quickstart.md index 4c8b6b9..fd99312 100644 --- a/docs-src/quickstart.md +++ b/docs-src/quickstart.md @@ -23,4 +23,4 @@ Check that the installation succeeded by running: python3 -c "import pymerlin; pymerlin.checkout()" ``` -If that succeeds, you're ready to get started with the [tutorial](1_tutorials/1_gettingstarted). \ No newline at end of file +If you see `pymerlin checkout successful: All systems GO 🚀`, you're ready to get started with the [tutorial](1_tutorials/1_gettingstarted). \ No newline at end of file diff --git a/docs/.buildinfo b/docs/.buildinfo index b6ec24d..610d8f2 100644 --- a/docs/.buildinfo +++ b/docs/.buildinfo @@ -1,4 +1,4 @@ # Sphinx build info version 1 # This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done. -config: dc8fc5ce81b9f5652bf3b83679e73bfb +config: 8c5ea12c0d4f9c266bf0fec544c2a925 tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/docs/1_tutorials/1_gettingstarted.html b/docs/1_tutorials/1_gettingstarted.html index 24982cb..d368ed6 100644 --- a/docs/1_tutorials/1_gettingstarted.html +++ b/docs/1_tutorials/1_gettingstarted.html @@ -6,7 +6,7 @@ -
This isn’t yet supported! But this page will be populated as soon as it is.
+Refer to https://developers.google.com/style for guidance. Any particularly salient points should be reproduced in this document.
+pymerlin is always lowercase. It may be styled as regular text or in a code block like this: pymerlin
depending on the
+context.
pymerlin documentation should be self-contained for users who are not using an Aerie deployment - this means that +some concepts will be repeated across pymerlin and Aerie documentation. In these scenarios, the relevant Aerie +documentation page should be linked in a “Further reading” section at the bottom of the page.
+If that succeeds, you’re ready to get started with the tutorial.
+If you see pymerlin checkout successful: All systems GO 🚀
, you’re ready to get started with the tutorial.
pymerlin
", "pymerlin.duration
", "pymerlin.model_actions
", "Architecture", "Common Errors", "Contributing", "Developing pymerlin", "Documentation", "pymerlin", "Install", "License", "Publishing to pypi", "Quickstart"], "titleterms": {"The": 15, "activ": 11, "an": 11, "api": [16, 17, 18, 19], "approach": 20, "architectur": 20, "autonom": 11, "avoid": 11, "background": 13, "build": 22, "chang": 11, "circular": 21, "class": 18, "co": 10, "code": [22, 25], "command": 11, "commit": 22, "common": 21, "content": [17, 18, 19], "contribut": [22, 25], "creat": 0, "data": [3, 18], "develop": 23, "discret": 15, "do": 11, "document": 24, "durat": 18, "error": [11, 21], "event": 15, "feedback": 25, "fidel": 12, "file": 11, "first": 0, "function": [17, 19], "further": [2, 10], "geometri": 8, "get": [0, 25], "go": 2, "good": 22, "got": 22, "guarante": 11, "guid": 4, "guidelin": 22, "help": 25, "how": [5, 11, 25], "import": 21, "importerror": 21, "instal": [0, 26, 29], "integr": 11, "jupyt": 5, "licens": 27, "make": 11, "method": 11, "mission": 0, "model": [0, 3, 6, 9], "model_act": 19, "modul": [18, 19], "over": 20, "packag": 17, "partial": 11, "perform": 20, "plan": [11, 14], "power": 6, "pr": 22, "practic": 22, "problem": 22, "provid": 25, "publish": 28, "pull": 22, "pymerlin": [0, 5, 17, 18, 19, 22, 23, 25], "pypi": 28, "question": 22, "quickstart": 29, "re": 11, "read": 10, "refer": 16, "request": 22, "resourc": 0, "review": 22, "safeti": 11, "schedul": [7, 14], "simul": [10, 15], "sourc": 25, "spacecraft": 11, "spice": 8, "start": 0, "submit": 22, "submodul": 17, "telecom": 9, "theori": 15, "tune": 12, "tutori": 1, "us": [5, 8], "usabl": 11, "v": 11, "valid": 11, "volum": 3, "you": 11, "your": 0}})
\ No newline at end of file
+Search.setIndex({"alltitles": {"API": [[18, "api"], [19, "api"], [20, "api"]], "API Reference": [[17, "api-reference"]], "Activity Planning": [[12, "activity-planning"]], "Approachability over performance": [[21, "approachability-over-performance"]], "Architecture": [[21, "architecture"]], "Avoiding Command Errors": [[12, "avoiding-command-errors"]], "Background": [[14, "background"]], "Build an Aerie-compatible JAR file": [[3, "build-an-aerie-compatible-jar-file"]], "Building pymerlin": [[23, "building-pymerlin"]], "Building pymerlin.jar": [[24, "building-pymerlin-jar"]], "Classes": [[19, "classes"]], "Co-Simulation": [[11, "co-simulation"]], "Command Errors": [[12, "command-errors"]], "Common Errors": [[22, "common-errors"]], "Contributing": [[23, "contributing"]], "Creating a Mission Model": [[0, "creating-a-mission-model"]], "Data": [[19, "data"]], "Developing pymerlin": [[24, "developing-pymerlin"]], "Discrete Event Simulation": [[16, "discrete-event-simulation"]], "Documentation": [[25, "documentation"]], "Functions": [[18, "functions"], [20, "functions"]], "Further Reading": [[11, "further-reading"]], "Getting Started": [[0, "getting-started"]], "Going further": [[2, "going-further"]], "Good Commit, PR, and Code Review Practices": [[23, "good-commit-pr-and-code-review-practices"]], "Got a Question or Problem?": [[23, "got-a-question-or-problem"]], "Guides": [[5, "guides"]], "How do you guarantee the safety of an autonomous spacecraft?": [[12, "how-do-you-guarantee-the-safety-of-an-autonomous-spacecraft"]], "How to get help, contribute, or provide feedback": [[26, "how-to-get-help-contribute-or-provide-feedback"]], "How to use pymerlin in Jupyter": [[6, "how-to-use-pymerlin-in-jupyter"]], "ImportError - circular import": [[22, "importerror-circular-import"]], "Install": [[27, "install"]], "Installation": [[30, "installation"]], "Installing pymerlin": [[0, "installing-pymerlin"]], "Integrated vs Partial validation": [[12, "integrated-vs-partial-validation"]], "License": [[28, "license"]], "Making changes to command files": [[12, "making-changes-to-command-files"]], "Methods of Validation": [[12, "methods-of-validation"]], "Modeling Data Volume": [[4, "modeling-data-volume"]], "Modeling Power": [[7, "modeling-power"]], "Modeling Telecom": [[10, "modeling-telecom"]], "Module Contents": [[19, "module-contents"], [20, "module-contents"]], "Package Contents": [[18, "package-contents"]], "Planning and Scheduling": [[15, "planning-and-scheduling"]], "Publishing to pypi": [[29, "publishing-to-pypi"]], "Pull Request Guidelines": [[23, "pull-request-guidelines"]], "Quickstart": [[30, "quickstart"]], "Re-usable command files": [[12, "re-usable-command-files"]], "Referencing Aerie": [[25, "referencing-aerie"]], "Round trips": [[21, "round-trips"]], "Scheduling": [[8, "scheduling"]], "Source code": [[26, "source-code"]], "Style": [[25, "style"]], "Submitting a Pull Request": [[23, "submitting-a-pull-request"]], "Submodules": [[18, "submodules"]], "The Theory": [[16, "the-theory"]], "Tuning Fidelity": [[13, "tuning-fidelity"]], "Tutorials": [[1, "tutorials"]], "Using spice for geometry": [[9, "using-spice-for-geometry"]], "Your First Resource": [[0, "your-first-resource"]], "pymerlin": [[18, "module-pymerlin"], [26, "pymerlin"]], "pymerlin.duration": [[19, "module-pymerlin.duration"]], "pymerlin.model_actions": [[20, "module-pymerlin.model_actions"]]}, "docnames": ["1_tutorials/1_gettingstarted", "1_tutorials/index", "1_tutorials/tutorial2", "2_guides/build-jar", "2_guides/datamodel", "2_guides/index", "2_guides/jupyter", "2_guides/powermodel", "2_guides/scheduling", "2_guides/spice", "2_guides/telecom", "3_explanation/co-simulation", "3_explanation/command-errors", "3_explanation/fidelity", "3_explanation/index", "3_explanation/planning", "3_explanation/simulation", "apidocs/index", "apidocs/pymerlin/pymerlin", "apidocs/pymerlin/pymerlin.duration", "apidocs/pymerlin/pymerlin.model_actions", "architecture", "common-errors", "contribute", "developer", "documentation", "index", "install", "license", "publishing", "quickstart"], "envversion": {"sphinx": 61, "sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2}, "filenames": ["1_tutorials/1_gettingstarted.md", "1_tutorials/index.md", "1_tutorials/tutorial2.md", "2_guides/build-jar.md", "2_guides/datamodel.md", "2_guides/index.md", "2_guides/jupyter.md", "2_guides/powermodel.md", "2_guides/scheduling.md", "2_guides/spice.md", "2_guides/telecom.md", "3_explanation/co-simulation.md", "3_explanation/command-errors.md", "3_explanation/fidelity.md", "3_explanation/index.md", "3_explanation/planning.md", "3_explanation/simulation.md", "apidocs/index.rst", "apidocs/pymerlin/pymerlin.rst", "apidocs/pymerlin/pymerlin.duration.rst", "apidocs/pymerlin/pymerlin.model_actions.rst", "architecture.md", "common-errors.md", "contribute.md", "developer.md", "documentation.md", "index.md", "install.md", "license.md", "publishing.md", "quickstart.md"], "indexentries": {"__eq__() (pymerlin.duration.duration method)": [[19, "pymerlin.duration.Duration.__eq__", false]], "__ge__() (pymerlin.duration.duration method)": [[19, "pymerlin.duration.Duration.__ge__", false]], "__gt__() (pymerlin.duration.duration method)": [[19, "pymerlin.duration.Duration.__gt__", false]], "__le__() (pymerlin.duration.duration method)": [[19, "pymerlin.duration.Duration.__le__", false]], "__lt__() (pymerlin.duration.duration method)": [[19, "pymerlin.duration.Duration.__lt__", false]], "__repr__() (pymerlin.duration.duration method)": [[19, "pymerlin.duration.Duration.__repr__", false]], "_yield_with() (in module pymerlin.model_actions)": [[20, "pymerlin.model_actions._yield_with", false]], "call() (in module pymerlin.model_actions)": [[20, "pymerlin.model_actions.call", false]], "checkout() (in module pymerlin)": [[18, "pymerlin.checkout", false]], "delay() (in module pymerlin.model_actions)": [[20, "pymerlin.model_actions.delay", false]], "duration (class in pymerlin.duration)": [[19, "pymerlin.duration.Duration", false]], "from_string() (pymerlin.duration.duration static method)": [[19, "pymerlin.duration.Duration.from_string", false]], "hour (in module pymerlin.duration)": [[19, "pymerlin.duration.HOUR", false]], "hours (in module pymerlin.duration)": [[19, "pymerlin.duration.HOURS", false]], "microsecond (in module pymerlin.duration)": [[19, "pymerlin.duration.MICROSECOND", false]], "microseconds (in module pymerlin.duration)": [[19, "pymerlin.duration.MICROSECONDS", false]], "millisecond (in module pymerlin.duration)": [[19, "pymerlin.duration.MILLISECOND", false]], "milliseconds (in module pymerlin.duration)": [[19, "pymerlin.duration.MILLISECONDS", false]], "minute (in module pymerlin.duration)": [[19, "pymerlin.duration.MINUTE", false]], "minutes (in module pymerlin.duration)": [[19, "pymerlin.duration.MINUTES", false]], "module": [[18, "module-pymerlin", false], [19, "module-pymerlin.duration", false], [20, "module-pymerlin.model_actions", false]], "negate() (pymerlin.duration.duration method)": [[19, "pymerlin.duration.Duration.negate", false]], "of() (pymerlin.duration.duration static method)": [[19, "pymerlin.duration.Duration.of", false]], "plus() (pymerlin.duration.duration method)": [[19, "pymerlin.duration.Duration.plus", false]], "pymerlin": [[18, "module-pymerlin", false]], "pymerlin.duration": [[19, "module-pymerlin.duration", false]], "pymerlin.model_actions": [[20, "module-pymerlin.model_actions", false]], "second (in module pymerlin.duration)": [[19, "pymerlin.duration.SECOND", false]], "seconds (in module pymerlin.duration)": [[19, "pymerlin.duration.SECONDS", false]], "spawn() (in module pymerlin.model_actions)": [[20, "pymerlin.model_actions.spawn", false]], "times() (pymerlin.duration.duration method)": [[19, "pymerlin.duration.Duration.times", false]], "wait_until() (in module pymerlin.model_actions)": [[20, "pymerlin.model_actions.wait_until", false]], "zero (in module pymerlin.duration)": [[19, "pymerlin.duration.ZERO", false]]}, "objects": {"": [[18, 0, 0, "-", "pymerlin"]], "pymerlin": [[18, 1, 1, "", "checkout"], [19, 0, 0, "-", "duration"], [20, 0, 0, "-", "model_actions"]], "pymerlin.duration": [[19, 2, 1, "", "Duration"], [19, 4, 1, "", "HOUR"], [19, 4, 1, "", "HOURS"], [19, 4, 1, "", "MICROSECOND"], [19, 4, 1, "", "MICROSECONDS"], [19, 4, 1, "", "MILLISECOND"], [19, 4, 1, "", "MILLISECONDS"], [19, 4, 1, "", "MINUTE"], [19, 4, 1, "", "MINUTES"], [19, 4, 1, "", "SECOND"], [19, 4, 1, "", "SECONDS"], [19, 4, 1, "", "ZERO"]], "pymerlin.duration.Duration": [[19, 3, 1, "", "__eq__"], [19, 3, 1, "", "__ge__"], [19, 3, 1, "", "__gt__"], [19, 3, 1, "", "__le__"], [19, 3, 1, "", "__lt__"], [19, 3, 1, "", "__repr__"], [19, 3, 1, "", "from_string"], [19, 3, 1, "", "negate"], [19, 3, 1, "", "of"], [19, 3, 1, "", "plus"], [19, 3, 1, "", "times"]], "pymerlin.model_actions": [[20, 1, 1, "", "_yield_with"], [20, 1, 1, "", "call"], [20, 1, 1, "", "delay"], [20, 1, 1, "", "spawn"], [20, 1, 1, "", "wait_until"]]}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "function", "Python function"], "2": ["py", "class", "Python class"], "3": ["py", "method", "Python method"], "4": ["py", "data", "Python data"]}, "objtypes": {"0": "py:module", "1": "py:function", "2": "py:class", "3": "py:method", "4": "py:data"}, "terms": {"": [0, 9, 12, 13, 19, 23], "0": [0, 19], "00": [0, 19, 20], "000": 19, "000000": 19, "01": [0, 20], "01pre": 16, "03": 16, "1": [0, 19], "12": 30, "170215": 16, "2": [10, 12, 19], "200": 12, "2017": 16, "2018": 16, "2021": 28, "21": [24, 30], "24": 19, "2ab": 10, "3": [16, 24], "30": 19, "3120": 30, "3rd": 16, "5": 19, "600": 19, "63": 19, "7": 19, "8601": 19, "9": 24, "A": [8, 12, 16, 19, 20, 28], "AND": 28, "AS": 28, "As": [0, 12, 19, 21, 23], "At": 23, "BE": 28, "BUT": 28, "Be": 23, "But": [0, 3], "FOR": 28, "For": [0, 12, 19, 21, 23, 24], "IN": 28, "If": [0, 12, 19, 23, 30], "In": [0, 12, 16, 19, 23, 25], "It": [11, 12, 13, 25], "NO": 28, "NOT": 28, "No": 23, "Not": 12, "OF": 28, "OR": 28, "One": 12, "THE": 28, "TO": 28, "That": 12, "The": [0, 9, 10, 12, 14, 19, 21, 22, 23, 28], "Then": 0, "There": [11, 12, 13, 16], "These": [0, 12, 21, 23], "To": [12, 16, 19, 23, 26], "WITH": 28, "With": 0, "__eq__": 19, "__ge__": 19, "__gt__": 19, "__init__": 0, "__le__": 19, "__lt__": 19, "__main__": 0, "__name__": 0, "__repr__": 19, "_global": 21, "_intern": 24, "_yield_with": 20, "abil": [12, 13, 23], "abl": [0, 10, 11, 12, 16], "about": [0, 12, 14, 22, 23, 26], "abov": [0, 12, 23, 28], "absenc": [12, 16], "absolut": 12, "abstract": 12, "accept": 23, "access": 26, "accomplish": [0, 12], "accuraci": 19, "achiev": 12, "across": [12, 13, 25], "act": 16, "action": [12, 16, 20, 28], "activ": [0, 13, 14, 21, 22, 30], "activitytyp": 0, "actual": [0, 12, 23], "ad": [12, 23], "add": [0, 16, 23], "addit": [0, 13, 16, 24], "address": 12, "adher": 12, "adoptium": 30, "advanc": 16, "advantag": 0, "advers": 12, "aeri": [0, 13, 16, 21, 23, 26], "affect": 12, "after": [0, 12, 23, 30], "again": 16, "against": [12, 19], "aid": 23, "aim": 21, "all": [0, 12, 16, 23, 28, 30], "alloc": [10, 12, 16], "allow": [0, 12, 16, 21, 23], "almost": [0, 19], "along": 0, "alreadi": 0, "also": [0, 12, 13], "although": 0, "altogeth": 19, "alwai": [19, 23, 25], "ammo": 16, "an": [0, 10, 14, 16, 19, 22, 23, 25, 28], "an9804": 10, "analysi": 12, "analyz": 21, "ani": [0, 10, 12, 16, 19, 23, 25, 28], "anoth": [12, 16, 22], "anticip": 12, "apart": 0, "api": 29, "appear": [0, 23], "appli": [12, 16], "appropri": 21, "approv": [12, 23], "approxim": [13, 19], "ar": [0, 11, 12, 13, 16, 19, 20, 21, 23, 25, 30], "arbitrari": 16, "arbitrarili": 16, "aren": 12, "argument": [0, 12, 21], "aris": [11, 12, 28], "arithmet": 19, "around": [19, 22], "assembl": 24, "assess": 12, "assign": 19, "associ": 28, "assum": 12, "astronom": 19, "async": [0, 20], "attent": [12, 23], "attribut": 16, "author": [12, 28], "auto": 0, "autodoc2": 25, "autom": 12, "automat": [12, 13, 23, 25], "autonom": 14, "autonomi": 12, "avail": [0, 10], "avoid": [14, 16], "awai": 0, "await": 20, "awar": [0, 12], "b": [8, 10, 23], "back": 0, "bandwidth": 10, "base": [0, 19], "basi": 19, "basic": 0, "batteri": 12, "bear": 0, "becam": 12, "becaus": 19, "becom": [19, 23], "been": [0, 10, 12, 23], "befor": [12, 16, 23], "begin": 0, "behavior": [0, 12, 13], "being": [0, 19], "benefit": 21, "best": [12, 13], "better": [12, 23], "between": [0, 10, 12, 13, 16, 19, 21, 23], "bind": 9, "bisect": 23, "block": 25, "board": [0, 12], "bodi": [10, 19], "bonu": 0, "boolean": 0, "borrow": 16, "both": [0, 12, 16, 22], "bottom": 25, "bound": 12, "bracket": 23, "branch": 23, "bridg": 21, "brief": 0, "budget": 10, "build": [0, 29], "built": [0, 25, 26], "bulletproof": 12, "burden": 12, "busi": 10, "button": 23, "c": [28, 30], "cach": 21, "calcul": 9, "calendar": 19, "calendr": 19, "california": 28, "call": [0, 12, 13, 16, 19, 20], "camera": 0, "can": [0, 12, 13, 14, 16, 17, 19, 20, 21, 22, 23, 26], "cannot": [0, 12, 22], "capabl": 12, "cardin": 12, "care": 21, "carlo": 13, "carol": 12, "carri": 12, "case": [0, 12, 19, 21], "catch": 13, "categori": [0, 12], "caus": 12, "causal": 19, "caution": 12, "cd": [24, 25], "celesti": 19, "cell": [0, 16], "certain": [12, 16, 20, 21], "cfdp": 12, "challeng": 11, "chang": [0, 14, 16, 23], "channel": 23, "character": 21, "characterist": 12, "charg": 28, "chat": 23, "check": [12, 18, 23, 26, 30], "checkout": [18, 23, 30], "child": [16, 20], "china": 19, "choic": [16, 19], "choos": 12, "cite": 12, "claim": [19, 28], "class": [0, 17], "clean": [23, 25], "cleanup": 21, "clear": [12, 23], "climat": 12, "clipper": 12, "clock": [0, 19], "clone": 23, "close": [12, 23], "co": 14, "code": [0, 19, 21, 25], "collectdata": 0, "collinear": 19, "com": [10, 16, 25, 26], "combin": [12, 19, 23], "come": [0, 11, 12, 13], "command": [13, 14, 23, 29, 30], "comment": 23, "common": 0, "commun": [10, 12, 13, 21], "compar": 12, "complac": 12, "complet": 12, "complex": 0, "complic": [19, 23], "compon": 12, "compos": 13, "comput": [0, 12, 16], "concept": [13, 16, 19, 25], "concurr": [12, 16], "condit": [12, 16, 20, 28], "config": 0, "configur": [0, 13, 19], "conflict": [12, 16, 23], "connect": 28, "consensu": 12, "consequ": 12, "consid": 21, "constant": 0, "constel": 12, "constitu": 12, "constrain": 12, "constraint": 12, "construct": [0, 19], "constructor": 0, "contain": [12, 25], "content": [0, 12, 16, 27], "context": 25, "continu": [0, 16, 23], "contract": 28, "contrib": 0, "contribut": 25, "contributor": 23, "control": 12, "conveni": 22, "convent": 23, "convers": 0, "convert": [19, 21], "coordin": 12, "copi": 28, "copyright": 28, "core": 0, "coro": 20, "correct": 12, "correctli": [0, 12], "correspond": 12, "cost": 12, "could": [0, 12], "counter": 0, "coupl": [0, 19], "cours": 0, "cover": [0, 19], "creat": [1, 19, 23], "current": [0, 16, 19, 23], "custom": [0, 19], "cycl": 13, "d": [0, 16, 23], "dai": [13, 19], "damag": 28, "danger": 12, "data": [0, 12, 17], "datamodel": 0, "date": 19, "de": 19, "deadlin": 12, "deal": [19, 23, 28], "decid": 12, "decis": 12, "declar": [0, 12], "decreas": 0, "def": 0, "defer": 19, "defin": [0, 12, 19, 22], "definit": [0, 12, 19], "delai": [12, 20], "deleg": 0, "delet": [12, 23], "delimit": 19, "deliv": 12, "depend": [10, 12, 13, 16, 19, 25], "deploy": [0, 25], "depth": 12, "deriv": [0, 19], "describ": [12, 16, 22, 23, 30], "descript": [12, 23], "design": [0, 11, 12, 23], "desir": [12, 13], "detail": [0, 13, 17], "detect": 12, "determin": 10, "develop": [23, 25], "deviat": 12, "did": 12, "differ": [0, 10, 12, 13, 19], "difficult": [12, 21], "direct": 0, "directli": [0, 12, 19, 21], "directori": 25, "discoveri": 10, "discret": [0, 14, 19, 26], "discuss": 23, "disposit": 12, "dist": 29, "distanc": [10, 19], "distinct": 19, "distinguish": [0, 19], "distribut": [16, 28], "do": [0, 14, 18, 21, 22, 28], "doc": [16, 25, 26], "docstr": 25, "document": [0, 23, 28], "doe": [0, 12, 23], "domain": 19, "don": [0, 12, 23], "done": [12, 19], "doubl": [0, 21], "doublevaluemapp": 0, "download": 30, "draft": 12, "driver": 21, "drop": 19, "due": 22, "duplic": [16, 23], "durat": [0, 12, 17, 18, 20], "duration_str": 19, "dure": [12, 13], "duti": 13, "dynam": [12, 16], "e": [0, 12, 19, 21], "each": [0, 22, 23], "earli": 12, "earth": [12, 19], "easi": 12, "easier": 23, "easiest": 0, "ecosystem": 26, "edit": 23, "effect": [0, 12, 23], "effort": 23, "either": [12, 23], "element": 19, "elsewher": 21, "emit": [0, 16], "en": 16, "enabl": [12, 16, 21], "encount": 22, "endpoint": 23, "engin": [13, 21], "enhanc": 16, "enough": [12, 13], "ensur": [0, 19, 23], "enter": 12, "enumer": [0, 12], "envelop": 12, "environ": [12, 30], "environment": 12, "epagomen": 19, "ephemerid": 19, "err": 12, "error": [0, 13, 14], "errorbehavior": 0, "errorregistrar": 0, "estim": 19, "evalu": 16, "even": [12, 16, 19, 23], "event": [0, 12, 14, 19, 26, 28], "eventu": 0, "everi": [12, 16, 23], "evid": 19, "evolut": 16, "evolv": 0, "exact": 19, "exampl": [0, 12, 19, 20], "except": 19, "execut": 12, "exhaust": 12, "exist": [11, 12, 16, 19, 21, 29], "expect": [0, 12, 21], "explicitli": 0, "expos": 0, "express": [16, 28], "extend": 0, "extens": 25, "extern": 13, "f": [16, 23], "fact": 12, "factori": 19, "fail": 12, "failur": 12, "fall": [12, 23], "fals": [12, 20], "familiar": 12, "famous": 12, "far": [12, 19], "fashion": 12, "fast": 12, "fault": 12, "fdir": 12, "feasibl": 12, "featur": 23, "few": [0, 12, 23], "fewer": 12, "fidel": 14, "field": 19, "file": [0, 14, 22, 23, 28, 29], "final": 0, "find": [0, 17], "fine": 12, "firesat": 0, "first": [1, 12, 16, 30], "fit": 28, "fix": [12, 19, 23], "flight": 12, "float": 19, "focu": 12, "focus": [0, 12], "follow": [0, 12, 16, 23, 25, 28, 30], "forc": 23, "forget": 16, "form": [0, 12], "formul": 16, "forward": 16, "found": 12, "framework": [0, 26], "free": [12, 28], "free_replicated_data_typ": 16, "frequent": 19, "from": [0, 12, 16, 19, 22, 23, 28, 29], "from_str": 19, "front": 23, "fsw": 12, "fulli": 0, "function": [0, 16, 17, 19], "fundament": [0, 19], "furnish": 28, "furo": 25, "further": [1, 12, 14, 16, 19, 25], "futur": 16, "g": [12, 19], "gener": [0, 13, 16, 21, 23], "get": [1, 11, 30], "git": 23, "github": [16, 23, 26], "give": [12, 19, 21, 23], "given": [0, 16], "global": 21, "go": [0, 1, 12, 30], "goe": 27, "gold": 19, "gone": 12, "good": 19, "googl": 25, "gov": 0, "gradlew": 24, "grain": 12, "grant": 28, "great": [11, 19], "greatest": 12, "gregorian": 19, "ground": 12, "guarante": [14, 16], "guardrail": 12, "guid": [0, 26], "guidanc": 25, "guidelin": 26, "ha": [0, 10, 12, 19, 21, 23], "had": 12, "handl": 21, "hardwar": 12, "have": [0, 12, 13, 16, 21, 22, 23, 30], "haven": 0, "healthi": 12, "heater": 12, "held": 19, "help": [21, 23], "helper": 0, "here": [12, 14, 17, 19, 22, 23, 27], "herebi": 28, "hierarch": 23, "high": 12, "higher": 24, "histori": [16, 23], "hold": 12, "holder": 28, "horizon": 13, "host": 16, "hour": 19, "how": [0, 13, 14, 23, 30], "howev": [12, 19], "html": [10, 25], "http": [10, 16, 25, 26, 30], "human": 12, "hybrid": [16, 21], "hybrid_system": 16, "i": [0, 2, 3, 4, 6, 7, 9, 10, 12, 13, 15, 16, 18, 19, 21, 22, 23, 25, 26, 28], "id": [0, 21], "idea": 23, "ident": 12, "identifi": 12, "ii": 11, "imag": 0, "imbu": 12, "impact": 12, "imper": 12, "implement": [0, 11, 12, 16, 21], "impli": [12, 28], "implicitli": 0, "import": [0, 12, 21, 30], "importantli": 12, "imposs": 12, "incapacit": 12, "includ": [0, 12, 19, 23, 25, 28, 29], "incorrect": 12, "increas": [0, 12], "increment": 19, "increment_count": 0, "indefinit": 12, "independ": [12, 16], "indic": 12, "individu": [12, 13], "info": 23, "inform": [12, 23], "initi": [0, 16, 19, 22], "input": [12, 21], "inspect": 12, "instal": [1, 18], "instant": 19, "instanti": 0, "instead": [11, 19], "institut": 28, "instruct": 23, "instrument": [0, 21], "integ": [0, 19], "integr": [0, 13, 14, 21, 23], "intend": [0, 12], "intens": 12, "intent": 12, "intention": 19, "interact": [12, 23], "intercalari": 19, "interest": [0, 12], "interestingli": 0, "interfac": [16, 23], "intern": 19, "interpret": 12, "interspers": 12, "introduc": [0, 12, 16], "invalid": 12, "invok": 19, "involv": 12, "io": 16, "isn": 3, "iso": 19, "isol": 12, "issu": [0, 23], "its": [12, 13, 16, 21], "itself": [0, 12], "jar": 21, "java": [0, 19, 21, 24, 30], "jdk": 24, "jpl": [0, 9], "jre": 30, "just": [0, 19], "justifi": 12, "keep": [0, 12, 16], "kei": [10, 12, 29], "kernel": 19, "keyword": 20, "kind": [12, 28], "know": [0, 12], "known": 19, "komputasi": 16, "label": 20, "lack": 12, "languag": 12, "larg": [12, 13], "larger": 21, "largest": 19, "last": 0, "later": 0, "latest": 23, "latitud": 19, "lead": 12, "leak": 21, "learn": [0, 14, 26], "least": 23, "left": 23, "less": [12, 19], "let": 0, "level": [0, 12], "leverag": 11, "liabil": 28, "liabl": 28, "lib": 24, "librari": 24, "lightweight": 12, "like": [0, 12, 16, 19, 22, 23, 25], "limit": [10, 12, 28], "line": [0, 23], "linear": [0, 23], "link": [0, 10, 19, 25], "list": 16, "live": 25, "ll": [0, 24], "local": 23, "log": 0, "logic": 0, "long": [12, 19, 21], "longest": 12, "look": [0, 19, 21], "loss": 12, "lost": [12, 23], "love": 23, "low": 12, "lower": 12, "lowercas": 25, "lunar": 19, "m": 29, "machin": 30, "made": [0, 23], "mag": 10, "mai": [12, 13, 19, 21, 22, 25], "main": [0, 21, 22], "maintain": 0, "major": 12, "make": [0, 14, 21, 22, 23, 25, 29, 30], "manag": [13, 16], "maneuv": 12, "mani": [0, 11, 12, 13], "map": 19, "mapper": 0, "mar": 12, "mark": 12, "martian": 19, "match": [0, 12], "mathwork": 10, "matt": 12, "mattdaili": 26, "maxim": 12, "maximum": 19, "mayb": 12, "mean": [12, 16, 20, 21, 22, 25], "measur": [0, 19], "mechan": 12, "media": 10, "megabit": 0, "member": 0, "memori": 21, "mental": 12, "mention": 12, "merchant": 28, "mere": [13, 21, 23], "merg": [23, 28], "merlin": [0, 16, 19, 21], "messag": [12, 23], "met": 23, "method": [14, 19], "micro": 19, "microsecond": 19, "might": 22, "millisecond": 19, "mind": [0, 12], "minim": [12, 16], "minut": 19, "mirror": 12, "miss": 12, "mission": [1, 11, 12, 13, 16, 21, 22], "missionmodel": 0, "mit": 28, "mitig": 12, "mm": 12, "mode": 12, "model": [1, 11, 12, 13, 16, 21, 22], "model_act": [17, 18], "modifi": [0, 28], "modul": [18, 22], "mont": 13, "month": 19, "moon": 19, "more": [0, 12, 13, 14, 16, 21, 23, 26], "most": [0, 12, 22], "move": 16, "msl": 12, "much": [0, 13], "multipl": [12, 19], "multipli": 19, "must": [0, 12, 20, 23], "muszynski": 12, "mutabl": 16, "mutableresourc": 0, "mv": 24, "mvsteen": 16, "my": 23, "myst": 25, "naif": 9, "name": [0, 12, 22], "nasa": [0, 9, 16], "neatli": 23, "necessari": 19, "necessarili": 13, "need": [0, 12, 13, 19, 21, 22, 24], "needless": 16, "negat": 19, "net": 30, "new": [0, 12, 23], "newest": 12, "next": 0, "nice": 11, "nomin": 12, "none": 19, "noninfring": 28, "note": [12, 19, 23], "notic": 28, "notion": [13, 16, 19], "now": [0, 12], "number": [12, 19], "numer": 12, "object": [0, 21], "observ": [12, 13], "obstruct": 10, "obtain": 28, "occult": 10, "occur": [0, 16, 22], "off": [12, 13], "often": [12, 19], "old": 12, "onboard": 12, "onc": [12, 16, 23, 30], "one": [0, 12, 19, 22, 23], "ones": [0, 12], "onli": [19, 21], "onto": 23, "open": 23, "oper": [10, 12, 13, 16, 19], "opportun": [0, 12], "optim": 12, "option": 23, "orbit": [9, 12, 19], "order": [12, 16, 19], "ordin": 19, "org": [16, 30], "origin": [12, 21, 23], "other": [0, 10, 12, 19, 22, 28], "otherwis": 28, "our": [0, 23, 26], "out": [23, 26, 28], "outcom": 12, "output": 21, "outsid": 19, "outstand": 23, "over": [0, 23], "overhead": 21, "overview": 0, "own": [0, 19], "packag": [0, 17, 19, 24], "packet": 12, "padawan": 0, "page": [0, 3, 25], "pai": 23, "pair": 12, "palat": 12, "panel": 12, "paradigm": 12, "parallel": 16, "param": [19, 20], "paramet": [0, 12, 13, 19], "paraphras": 16, "parent": 16, "pars": 25, "part": [0, 12], "partial": [14, 22], "particular": [12, 19, 28], "particularli": 25, "partit": 16, "pass": [0, 12, 21, 23], "passag": 19, "patch": 23, "path": [10, 21], "pdf": [10, 16], "perceiv": 12, "perform": [0, 10, 12, 13, 16, 19], "perhap": 12, "period": 19, "perman": 12, "permiss": 28, "permit": 28, "persist": 12, "person": 28, "peski": 0, "phase": 13, "phenomena": 16, "piec": 12, "piecewis": 0, "pip": 30, "place": 12, "plai": [10, 11, 13], "plan": [0, 13, 14], "pleas": [0, 23], "plu": 19, "plugin": 25, "point": [0, 10, 12, 19, 25], "polanskei": 12, "polynomi": 0, "popul": 3, "popular": 9, "port": [0, 21], "portion": 28, "posit": 12, "possibl": [0, 12, 21, 23], "power": 12, "powerless": 12, "practic": [12, 22], "pre": 0, "precis": [12, 13, 19], "predict": 12, "prefer": 23, "prefix": 16, "preliminari": 16, "presenc": 19, "present": 23, "preserv": 19, "prevent": 0, "previou": [12, 23], "primari": 0, "primarili": 0, "primit": 0, "print": 0, "prior": 22, "problem": 19, "process": [0, 11, 12, 13, 21], "profil": [0, 12], "progress": 0, "project": [23, 30], "promot": 12, "properti": [10, 12, 16, 19], "protect": 12, "prototyp": 21, "prove": 12, "proven": 12, "provid": [0, 9, 12, 13, 17, 19, 20, 21, 28], "prudent": 12, "ptolemi": 11, "public": 0, "publish": [24, 28], "pull": 0, "purpos": [10, 12, 28], "push": 23, "put": [12, 16], "py": [0, 21, 22], "py4j": 21, "pymerlin": [1, 11, 13, 17, 21, 25, 30], "pypirc": 29, "pyspark": 21, "pytest": 24, "python": [0, 9, 21, 22, 24, 25, 30], "python3": [29, 30], "qualiti": 16, "quantiti": [0, 19], "queri": [16, 23], "quickli": [12, 13], "quickstart": [0, 26], "rang": [12, 19], "rapid": 21, "rare": 12, "rate": 0, "rather": 21, "re": [11, 14, 19, 21, 23, 30], "reach": 23, "read": [0, 14, 16, 23, 25, 26], "readabl": 23, "readi": [23, 26, 30], "real": 23, "reason": [12, 23], "rebas": 23, "recal": 12, "receiv": [10, 12], "recent": 12, "recharg": 12, "recommend": [12, 22], "record": [0, 12], "recording_r": 0, "recordingr": 0, "recoveri": 12, "reduc": 12, "refer": [19, 22, 25], "referenc": [12, 19], "regard": 16, "regist": 0, "registrar": 0, "regular": [19, 25], "reject": 12, "rel": 13, "relat": 23, "releas": 30, "relev": 25, "reli": [19, 23], "reliabl": [12, 13], "remind": 0, "remov": 21, "render": 0, "repeat": 25, "repo": 23, "repositori": [23, 29], "repres": [0, 12, 19, 21], "represent": [12, 19], "reproduc": 25, "requir": [12, 13, 16, 21, 23], "resembl": 12, "resolut": 19, "resourc": [1, 12, 16, 21, 23], "respect": 12, "respons": 12, "rest": 21, "restrict": [0, 12, 23, 28], "result": [12, 19], "retrospect": 19, "return": [19, 20, 21], "reusabl": 12, "review": 12, "rf": 29, "right": 28, "risk": 12, "rm": [23, 29], "role": 10, "root": 29, "rough": 19, "run": [12, 13, 16, 21, 22, 24, 25, 29, 30], "safe": [12, 23], "safeti": 14, "salient": 25, "same": [12, 16, 19], "scalar": 19, "scenario": 25, "schedul": [0, 13, 14, 16], "scienc": 13, "scrutini": 12, "search": 23, "second": [0, 19], "section": [12, 22, 25, 30], "see": [0, 12, 23, 26, 30], "seem": 22, "seemingli": 19, "segment": 0, "self": [0, 25], "sell": 28, "semant": [12, 16], "send": 23, "sens": 12, "sent": 12, "separ": [12, 16, 19, 22, 23], "sequenc": 12, "serial": [0, 16], "serializedvalu": 21, "serious": 21, "set": [0, 12, 19], "set_valu": 0, "sever": 13, "shall": 28, "share": 12, "short": 13, "should": [0, 12, 16, 19, 22, 23, 25], "shown": 0, "side": [12, 21, 23], "sider": 19, "sift": 12, "sign": 19, "signal": 12, "similar": [12, 19], "simluat": 11, "simpl": 0, "simpli": 19, "simul": [0, 12, 13, 14, 19, 21, 22, 26], "sinc": [0, 19], "singl": [0, 12, 16, 21, 23], "situat": 12, "skeleton": 12, "skew": 12, "skip": 12, "sky": 19, "slack": 23, "small": [12, 13], "smaller": 12, "so": [0, 12, 21, 28], "socket": 21, "softwar": [0, 12, 28], "sol": 12, "solar": [12, 19], "solid": 0, "some": [0, 10, 11, 12, 14, 16, 21, 22, 23, 25], "someon": 21, "someth": [0, 12], "sometim": [12, 13], "somewhat": 12, "soon": 3, "sort": 12, "sound": 12, "sourc": 21, "spacecraft": [0, 14, 19], "span": [13, 19], "spark": 21, "spawn": [16, 20], "special": 0, "specif": [12, 19], "specifi": [0, 12], "sphinx": 25, "spice": 19, "spiceypi": 9, "squash": 23, "ssr": 0, "sss": 10, "stai": [0, 12], "standard": 19, "star": 19, "start": [1, 21, 26, 30], "state": [0, 12, 16], "statement": 0, "static": [0, 19], "statu": 20, "step": [0, 12, 16], "still": 12, "stopwatch": 0, "store": 0, "stori": 23, "straightforward": 12, "strategi": 23, "streamlin": 0, "strength": 13, "strict": 13, "strictli": 0, "string": 0, "strive": 12, "structur": [0, 17], "subject": [12, 28], "sublicens": 28, "submiss": [23, 26], "submit": 12, "subprocess": 21, "substanti": 28, "subsystem": [12, 13], "succeed": 30, "success": [18, 30], "suffici": [13, 21], "suffix": 16, "suggest": 23, "summari": 23, "sun": [12, 19], "supersed": 12, "support": [3, 12], "sure": [12, 23, 29, 30], "surviv": 12, "swap": 12, "sygyzi": 19, "symmetri": 19, "synod": 19, "syntact": 12, "syntax": 12, "system": [10, 11, 12, 13, 16, 19, 21, 30], "syzygi": 19, "t": [0, 3, 12, 16, 23], "take": [0, 12, 19, 20], "target": 23, "task": [16, 20], "team": 12, "teas": 0, "technologi": 28, "tele": 10, "telecommun": 10, "telemetri": 12, "tell": 23, "temperatur": 12, "tempor": 19, "temurin": 30, "tenet": 21, "term": 19, "termin": 30, "tertiari": 19, "test": [0, 24], "text": 25, "than": [0, 21, 23], "thei": [0, 12, 20, 21, 23], "them": [0, 10, 11, 12, 22, 23], "theme": 25, "theori": 14, "therefor": 12, "thi": [0, 2, 3, 4, 6, 7, 12, 15, 16, 18, 19, 20, 21, 22, 23, 25, 28, 30], "thing": [0, 12, 18, 21], "think": 0, "third": 0, "those": [0, 12, 30], "though": [12, 23], "through": [0, 12, 21, 23], "tightli": 12, "time": [0, 12, 13, 16, 19, 23], "timelin": 0, "todai": [0, 23], "todo": [0, 16], "togeth": [11, 12], "tool": [11, 13], "toolkit": [9, 19], "top": 0, "tort": 28, "toward": [10, 12], "track": [0, 16], "tractabl": 12, "trade": 13, "tradition": [0, 16, 19], "train": 0, "trajectori": 12, "transact": 16, "transaction": 16, "transform": 0, "transmit": 12, "transmitt": 10, "trigger": 12, "trivial": 12, "true": [12, 20], "trust": 12, "try": [11, 12], "tune": 14, "turn": 12, "tutori": [0, 2, 4, 6, 7, 15, 30], "twine": [24, 29], "two": [0, 11, 12, 16, 19, 22, 23], "ty": 12, "type": [0, 12, 19, 21], "typic": [12, 13], "u": 0, "ui": 0, "ultim": 0, "uncertainti": 12, "uncondition": 12, "under": [0, 12], "underli": 19, "understand": 12, "understood": 21, "undesir": 12, "unexpect": 12, "unfortun": 19, "unintent": 12, "uniqu": 0, "unit": [0, 19], "unless": 16, "unlik": [0, 19], "unresolv": 23, "unsaf": 12, "unsurpris": 19, "until": [0, 12, 16], "up": [0, 12, 21, 23], "updat": [0, 23], "upgrad": 12, "upload": [16, 29], "us": [0, 12, 19, 21, 22, 23, 25, 26, 28], "usabl": 14, "user": [0, 23, 25], "usual": 12, "v": [14, 23], "valid": 14, "valu": [0, 12, 16, 19], "variabl": [0, 16, 21], "variat": 13, "variou": 0, "ve": 16, "vector": 12, "veri": 12, "verif": 12, "verifi": 12, "version": [0, 12, 16, 23], "via": [0, 12, 23], "viabl": 21, "view": [0, 12], "vike": 12, "virtual": 30, "volum": 0, "voyag": 12, "wa": [12, 18, 19], "wai": [12, 16, 19, 22], "wait_until": 20, "want": [0, 12, 21, 23], "warranti": 28, "wast": [12, 16], "we": [0, 12, 16, 19, 22, 23], "week": [13, 19], "welcom": [0, 25], "well": [0, 10, 12, 19, 21], "went": 23, "were": 12, "what": [0, 12, 16, 22, 23], "when": [0, 11, 12, 21, 23], "whenev": 16, "where": [12, 16, 19, 21], "whether": [10, 12, 28], "which": [0, 12, 19, 20, 21, 23], "while": [12, 16, 21], "who": [21, 25], "whole": 12, "whom": 28, "whose": [0, 19], "why": 21, "wiki": 16, "wikipedia": [16, 19], "within": [0, 12, 19], "without": [0, 12, 21, 28], "word": 0, "wordpress": 16, "work": [12, 16, 19, 23], "wors": 19, "worst": 12, "would": [11, 12, 23], "wp": 16, "write": [0, 12, 16, 23], "written": [0, 12], "wrong": 12, "www": [10, 30], "x": [12, 16], "y": 12, "year": 19, "yet": 3, "yield": 19, "you": [0, 14, 17, 19, 22, 23, 24, 26, 30], "your": [1, 16, 18, 19, 22, 23, 29, 30], "zero": 19}, "titles": ["Getting Started", "Tutorials", "Going further", "Build an Aerie-compatible JAR file", "Modeling Data Volume", "Guides", "How to use pymerlin in Jupyter", "Modeling Power", "Scheduling", "Using spice for geometry", "Modeling Telecom", "Co-Simulation", "Command Errors", "Tuning Fidelity", "Background", "Planning and Scheduling", "Discrete Event Simulation", "API Reference", "pymerlin
", "pymerlin.duration
", "pymerlin.model_actions
", "Architecture", "Common Errors", "Contributing", "Developing pymerlin", "Documentation", "pymerlin", "Install", "License", "Publishing to pypi", "Quickstart"], "titleterms": {"The": 16, "activ": 12, "aeri": [3, 25], "an": [3, 12], "api": [17, 18, 19, 20], "approach": 21, "architectur": 21, "autonom": 12, "avoid": 12, "background": 14, "build": [3, 23, 24], "chang": 12, "circular": 22, "class": 19, "co": 11, "code": [23, 26], "command": 12, "commit": 23, "common": 22, "compat": 3, "content": [18, 19, 20], "contribut": [23, 26], "creat": 0, "data": [4, 19], "develop": 24, "discret": 16, "do": 12, "document": 25, "durat": 19, "error": [12, 22], "event": 16, "feedback": 26, "fidel": 13, "file": [3, 12], "first": 0, "function": [18, 20], "further": [2, 11], "geometri": 9, "get": [0, 26], "go": 2, "good": 23, "got": 23, "guarante": 12, "guid": 5, "guidelin": 23, "help": 26, "how": [6, 12, 26], "import": 22, "importerror": 22, "instal": [0, 27, 30], "integr": 12, "jar": [3, 24], "jupyt": 6, "licens": 28, "make": 12, "method": 12, "mission": 0, "model": [0, 4, 7, 10], "model_act": 20, "modul": [19, 20], "over": 21, "packag": 18, "partial": 12, "perform": 21, "plan": [12, 15], "power": 7, "pr": 23, "practic": 23, "problem": 23, "provid": 26, "publish": 29, "pull": 23, "pymerlin": [0, 6, 18, 19, 20, 23, 24, 26], "pypi": 29, "question": 23, "quickstart": 30, "re": 12, "read": 11, "refer": 17, "referenc": 25, "request": 23, "resourc": 0, "review": 23, "round": 21, "safeti": 12, "schedul": [8, 15], "simul": [11, 16], "sourc": 26, "spacecraft": 12, "spice": 9, "start": 0, "style": 25, "submit": 23, "submodul": 18, "telecom": 10, "theori": 16, "trip": 21, "tune": 13, "tutori": 1, "us": [6, 9], "usabl": 12, "v": 12, "valid": 12, "volum": 4, "you": 12, "your": 0}})
\ No newline at end of file
diff --git a/pymerlin/__init__.py b/pymerlin/__init__.py
index 4d54ef5..76ffda4 100644
--- a/pymerlin/__init__.py
+++ b/pymerlin/__init__.py
@@ -28,8 +28,7 @@ def __init__(self, registrar: Registrar):
async def test_activity(mission: TestMissionModel):
mission.counter.emit(lambda x: x + 1)
-
- profiles, spans, events = simulate(TestMissionModel, Schedule.build(("00:00:00", Directive("test_activity"))), "00:00:01")
+ profiles, spans, events = simulate(TestMissionModel, Schedule.build(("00:00:00", test_activity())), "00:00:01")
if profiles != {'counter': [ProfileSegment(extent=Duration.from_string("+00:00:01.000000"), dynamics=1.0)]}:
print("Profiles didn't check out: ", profiles)
success = False
diff --git a/pymerlin/_internal/_cell_type.py b/pymerlin/_internal/_cell_type.py
index e86bd5b..8534ac7 100644
--- a/pymerlin/_internal/_cell_type.py
+++ b/pymerlin/_internal/_cell_type.py
@@ -21,11 +21,11 @@ def duplicate(self, state):
_globals.next_cell_id += 1
return cell_id
- def apply(self, state, effect):
- # TODO pass reference to effect.apply? Do we get a reference back? How expensive is that?
- current_state = _globals.cell_values_by_id[state]
- new_state = effect.apply(current_state)
- _globals.cell_values_by_id[state] = new_state
+ def apply(self, state_id, effect_id):
+ current_state = _globals.cell_values_by_id[state_id]
+ effect = _globals.effects_by_id[effect_id]
+ new_state = effect(current_state)
+ _globals.cell_values_by_id[state_id] = new_state
def step(self, state, java_duration):
if self.evolution is None:
diff --git a/pymerlin/_internal/_effect_trait.py b/pymerlin/_internal/_effect_trait.py
index 8afc770..33808ca 100644
--- a/pymerlin/_internal/_effect_trait.py
+++ b/pymerlin/_internal/_effect_trait.py
@@ -1,18 +1,23 @@
-from pymerlin._internal._registrar import FunctionalEffect
+from pymerlin._internal import _globals
class EffectTrait:
def empty(self):
- return FunctionalEffect(lambda x: x)
+ return 0
def sequentially(self, prefix, suffix):
return suffix
- def concurrently(self, left, right):
+ def concurrently(self, left_id, right_id):
def try_both(x):
- res1 = left.apply(right.apply(x))
- res2 = right.apply(left.apply(x))
+ left = _globals.effects_by_id[left_id]
+ right = _globals.effects_by_id[right_id]
+ res1 = left(right(x))
+ res2 = right(left(x))
if res1 != res2:
raise Exception("Concurrent composition of non-commutative effects")
return res1
- return FunctionalEffect(try_both)
+ effect_id = _globals.next_effect_id
+ _globals.effects_by_id[effect_id] = try_both
+ _globals.next_effect_id += 1
+ return effect_id
class Java:
implements = ["gov.nasa.jpl.aerie.merlin.protocol.model.EffectTrait"]
diff --git a/pymerlin/_internal/_framework.py b/pymerlin/_internal/_framework.py
index 31996fc..0f0b7a4 100644
--- a/pymerlin/_internal/_framework.py
+++ b/pymerlin/_internal/_framework.py
@@ -48,7 +48,7 @@ def simulate_helper(gateway, model_type, config, schedule, duration):
for offset, directive in schedule.entries:
type_name = directive.type if type(directive) == Directive else directive.func.__name__
if type_name not in valid_types:
- raise Exception("Unknown activity type: " + directive.type)
+ raise Exception("Unknown activity type: " + type_name)
merlin = gateway.entry_point.getMerlin()
if type(duration) is str:
duration = Duration.from_string(duration)
diff --git a/pymerlin/_internal/_globals.py b/pymerlin/_internal/_globals.py
index 9d041a1..a88bd61 100644
--- a/pymerlin/_internal/_globals.py
+++ b/pymerlin/_internal/_globals.py
@@ -12,3 +12,8 @@
# TODO figure out when we can clear this dictionary. As written it's a memory leak
# TODO consider allowing mutable objects in this dictionary, for performance purposes. This would require a way to clone these objects
cell_values_by_id = {}
+
+# Consider deduplication, since effects should be immutable
+effects_by_id = {}
+effects_by_id[0] = lambda x: x
+next_effect_id = 1
diff --git a/pymerlin/_internal/_registrar.py b/pymerlin/_internal/_registrar.py
index d25188c..2aab79e 100644
--- a/pymerlin/_internal/_registrar.py
+++ b/pymerlin/_internal/_registrar.py
@@ -37,9 +37,15 @@ def __init__(self):
self.topic = None
def emit(self, event):
- if callable(event):
- event = FunctionalEffect(event)
- _globals._current_context[0].emit(event, self.topic)
+ # if callable(event):
+ # event = FunctionalEffect(event)
+ # _globals._current_context[0].emit(event, self.topic)
+
+ if not callable(event):
+ raise Exception("Expecting effect to be callable")
+ _globals.effects_by_id[_globals.next_effect_id] = event
+ _globals._current_context[0].emit(_globals.next_effect_id, self.topic)
+ _globals.next_effect_id += 1
def set_value(self, new_value):
self.emit(set_value(new_value))
@@ -51,28 +57,19 @@ def get(self):
return _globals.cell_values_by_id[_globals._current_context[0].get(self.id)]
-class set_value:
- def __init__(self, new_value):
- # def apply(cell):
- # return new_value
- self.new_value = new_value
-
- def apply(self, state):
- return self.new_value
-
- class Java:
- implements = ["java.util.function.Function"]
-
-
-class FunctionalEffect:
- def __init__(self, f):
- self.f = f
+def set_value(new_value):
+ return lambda x: new_value
- def apply(self, state):
- return self.f(state)
- class Java:
- implements = ["java.util.function.Function"]
+# class FunctionalEffect:
+# def __init__(self, f):
+# self.f = f
+#
+# def apply(self, state):
+# return self.f(state)
+#
+# class Java:
+# implements = ["java.util.function.Function"]
def add_number(addend):
diff --git a/pymerlin/_internal/_serialized_value.py b/pymerlin/_internal/_serialized_value.py
index f2181f6..4c8deda 100644
--- a/pymerlin/_internal/_serialized_value.py
+++ b/pymerlin/_internal/_serialized_value.py
@@ -21,10 +21,10 @@ def onString(self, value):
return str(value)
def onMap(self, value):
- return {k: from_serialized_value(self.gateway, v) for k, v in value.items()}
+ return MapConverter().convert({k: from_serialized_value(self.gateway, v) for k, v in value.items()}, self.gateway._gateway_client)
def onList(self, value):
- return [from_serialized_value(self.gateway, v) for v in value]
+ return ListConverter().convert([from_serialized_value(self.gateway, v) for v in value], self.gateway._gateway_client)
class Java:
implements = ["gov.nasa.jpl.aerie.merlin.protocol.types.SerializedValue$Visitor"]
diff --git a/tests/test_simulation.py b/tests/test_simulation.py
index 647b14a..4dbaeb0 100644
--- a/tests/test_simulation.py
+++ b/tests/test_simulation.py
@@ -65,6 +65,12 @@ async def clear_list(mission, item):
mission.list.emit([])
+def test_checkout():
+ from pymerlin import checkout
+ checkout()
+
+
+@pytest.mark.skip("")
def test_empty():
"""
Empty schedule should result in no spans