jaxsim 0.2.dev56__tar.gz → 0.2.dev77__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/PKG-INFO +6 -1
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/environment.yml +5 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/setup.cfg +4 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/_version.py +2 -2
- jaxsim-0.2.dev77/src/jaxsim/mujoco/__init__.py +3 -0
- jaxsim-0.2.dev77/src/jaxsim/mujoco/__main__.py +192 -0
- jaxsim-0.2.dev77/src/jaxsim/mujoco/loaders.py +475 -0
- jaxsim-0.2.dev77/src/jaxsim/mujoco/model.py +352 -0
- jaxsim-0.2.dev77/src/jaxsim/mujoco/visualizer.py +152 -0
- jaxsim-0.2.dev77/src/jaxsim/simulation/integrators.py +393 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/simulation/ode_integration.py +3 -16
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim.egg-info/PKG-INFO +6 -1
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim.egg-info/SOURCES.txt +5 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim.egg-info/requires.txt +6 -0
- jaxsim-0.2.dev56/src/jaxsim/simulation/integrators.py +0 -646
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/.devcontainer/Dockerfile +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/.devcontainer/devcontainer.json +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/.github/workflows/ci_cd.yml +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/.github/workflows/read_the_docs.yml +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/.github/workflows/style.yml +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/.gitignore +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/.readthedocs.yaml +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/LICENSE +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/README.md +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/docs/Makefile +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/docs/conf.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/docs/guide/install.rst +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/docs/index.rst +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/docs/make.bat +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/docs/modules/high_level.rst +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/docs/modules/math.rst +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/docs/modules/parsers.rst +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/docs/modules/physics.rst +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/docs/modules/simulation.rst +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/docs/modules/typing.rst +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/docs/modules/utils.rst +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/examples/.gitattributes +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/examples/.gitignore +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/examples/PD_controller.ipynb +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/examples/Parallel_computing.ipynb +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/examples/README.md +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/examples/assets/cartpole.urdf +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/examples/pixi.lock +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/examples/pixi.toml +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/pyproject.toml +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/setup.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/__init__.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/high_level/__init__.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/high_level/common.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/high_level/joint.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/high_level/link.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/high_level/model.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/logging.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/math/__init__.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/math/adjoint.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/math/conv.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/math/cross.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/math/inertia.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/math/joint.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/math/plucker.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/math/quaternion.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/math/rotation.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/math/skew.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/parsers/__init__.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/parsers/descriptions/__init__.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/parsers/descriptions/collision.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/parsers/descriptions/joint.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/parsers/descriptions/link.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/parsers/descriptions/model.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/parsers/kinematic_graph.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/parsers/rod/__init__.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/parsers/rod/parser.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/parsers/rod/utils.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/physics/__init__.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/physics/algos/__init__.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/physics/algos/aba.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/physics/algos/aba_motors.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/physics/algos/crba.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/physics/algos/forward_kinematics.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/physics/algos/jacobian.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/physics/algos/rnea.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/physics/algos/rnea_motors.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/physics/algos/soft_contacts.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/physics/algos/terrain.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/physics/algos/utils.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/physics/model/__init__.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/physics/model/ground_contact.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/physics/model/physics_model.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/physics/model/physics_model_state.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/simulation/__init__.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/simulation/ode.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/simulation/ode_data.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/simulation/simulator.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/simulation/simulator_callbacks.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/simulation/utils.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/sixd/__init__.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/typing.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/utils/__init__.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/utils/jaxsim_dataclass.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/utils/oop.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/utils/tracing.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim/utils/vmappable.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim.egg-info/dependency_links.txt +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim.egg-info/not-zip-safe +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/src/jaxsim.egg-info/top_level.txt +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/tests/__init__.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/tests/test_ad_physics.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/tests/test_eom.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/tests/test_forward_dynamics.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/tests/test_jax_oop.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/tests/utils_idyntree.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/tests/utils_models.py +0 -0
- {jaxsim-0.2.dev56 → jaxsim-0.2.dev77}/tests/utils_rng.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: jaxsim
|
3
|
-
Version: 0.2.
|
3
|
+
Version: 0.2.dev77
|
4
4
|
Summary: A physics engine in reduced coordinates implemented with JAX.
|
5
5
|
Home-page: https://github.com/ami-iit/jaxsim
|
6
6
|
Author: Diego Ferigo
|
@@ -46,6 +46,9 @@ Requires-Dist: pytest>=6.0; extra == "testing"
|
|
46
46
|
Requires-Dist: pytest-forked; extra == "testing"
|
47
47
|
Requires-Dist: pytest-icdiff; extra == "testing"
|
48
48
|
Requires-Dist: robot-descriptions; extra == "testing"
|
49
|
+
Provides-Extra: viz
|
50
|
+
Requires-Dist: mediapy; extra == "viz"
|
51
|
+
Requires-Dist: mujoco>=3.0.0; extra == "viz"
|
49
52
|
Provides-Extra: all
|
50
53
|
Requires-Dist: black[jupyter]; extra == "all"
|
51
54
|
Requires-Dist: isort; extra == "all"
|
@@ -54,6 +57,8 @@ Requires-Dist: pytest>=6.0; extra == "all"
|
|
54
57
|
Requires-Dist: pytest-forked; extra == "all"
|
55
58
|
Requires-Dist: pytest-icdiff; extra == "all"
|
56
59
|
Requires-Dist: robot-descriptions; extra == "all"
|
60
|
+
Requires-Dist: mediapy; extra == "all"
|
61
|
+
Requires-Dist: mujoco>=3.0.0; extra == "all"
|
57
62
|
|
58
63
|
# JAXsim
|
59
64
|
|
@@ -12,13 +12,18 @@ dependencies:
|
|
12
12
|
- pptree
|
13
13
|
- rod
|
14
14
|
# Optional dependencies from setup.cfg
|
15
|
+
# [style]
|
15
16
|
- black
|
16
17
|
- isort
|
18
|
+
# [testing]
|
17
19
|
- idyntree
|
18
20
|
- pytest
|
19
21
|
- pytest-forked
|
20
22
|
- pytest-icdiff
|
21
23
|
- robot_descriptions
|
24
|
+
# [viz]
|
25
|
+
- mediapy
|
26
|
+
- mujoco >= 3.0.0
|
22
27
|
# System dependencies to run the tests
|
23
28
|
- gz-sim7
|
24
29
|
# Other packages
|
@@ -12,5 +12,5 @@ __version__: str
|
|
12
12
|
__version_tuple__: VERSION_TUPLE
|
13
13
|
version_tuple: VERSION_TUPLE
|
14
14
|
|
15
|
-
__version__ = version = '0.2.
|
16
|
-
__version_tuple__ = version_tuple = (0, 2, '
|
15
|
+
__version__ = version = '0.2.dev77'
|
16
|
+
__version_tuple__ = version_tuple = (0, 2, 'dev77')
|
@@ -0,0 +1,192 @@
|
|
1
|
+
import argparse
|
2
|
+
import pathlib
|
3
|
+
import sys
|
4
|
+
import time
|
5
|
+
|
6
|
+
import numpy as np
|
7
|
+
|
8
|
+
from . import MujocoModelHelper, MujocoVisualizer, SdfToMjcf, UrdfToMjcf
|
9
|
+
|
10
|
+
if __name__ == "__main__":
|
11
|
+
|
12
|
+
parser = argparse.ArgumentParser(
|
13
|
+
prog="jaxsim.mujoco",
|
14
|
+
description="Process URDF and SDF files for Mujoco usage.",
|
15
|
+
)
|
16
|
+
|
17
|
+
parser.add_argument(
|
18
|
+
"-d",
|
19
|
+
"--description",
|
20
|
+
required=True,
|
21
|
+
metavar="INPUT_FILE",
|
22
|
+
type=pathlib.Path,
|
23
|
+
help="Path to the URDF or SDF file.",
|
24
|
+
)
|
25
|
+
|
26
|
+
parser.add_argument(
|
27
|
+
"-m",
|
28
|
+
"--model-name",
|
29
|
+
metavar="NAME",
|
30
|
+
type=str,
|
31
|
+
default=None,
|
32
|
+
help="The target model of a SDF description if multiple models exists.",
|
33
|
+
)
|
34
|
+
|
35
|
+
parser.add_argument(
|
36
|
+
"-e",
|
37
|
+
"--export",
|
38
|
+
metavar="MJCF_FILE",
|
39
|
+
type=pathlib.Path,
|
40
|
+
default=None,
|
41
|
+
help="Path to the exported MJCF file.",
|
42
|
+
)
|
43
|
+
|
44
|
+
parser.add_argument(
|
45
|
+
"-f",
|
46
|
+
"--force",
|
47
|
+
action="store_true",
|
48
|
+
default=False,
|
49
|
+
help="Override the output MJCF file if it already exists (default: %(default)s).",
|
50
|
+
)
|
51
|
+
|
52
|
+
parser.add_argument(
|
53
|
+
"-p",
|
54
|
+
"--print",
|
55
|
+
action="store_true",
|
56
|
+
default=False,
|
57
|
+
help="Print in the stdout the exported MJCF string (default: %(default)s).",
|
58
|
+
)
|
59
|
+
|
60
|
+
parser.add_argument(
|
61
|
+
"-v",
|
62
|
+
"--visualize",
|
63
|
+
action="store_true",
|
64
|
+
default=False,
|
65
|
+
help="Visualize the description in the Mujoco viewer (default: %(default)s).",
|
66
|
+
)
|
67
|
+
|
68
|
+
parser.add_argument(
|
69
|
+
"-b",
|
70
|
+
"--base-position",
|
71
|
+
metavar=("x", "y", "z"),
|
72
|
+
nargs=3,
|
73
|
+
type=float,
|
74
|
+
default=None,
|
75
|
+
help="Override the base position (supports only floating-base models).",
|
76
|
+
)
|
77
|
+
|
78
|
+
parser.add_argument(
|
79
|
+
"-q",
|
80
|
+
"--base-quaternion",
|
81
|
+
metavar=("w", "x", "y", "z"),
|
82
|
+
nargs=4,
|
83
|
+
type=float,
|
84
|
+
default=None,
|
85
|
+
help="Override the base quaternion (supports only floating-base models).",
|
86
|
+
)
|
87
|
+
|
88
|
+
args = parser.parse_args()
|
89
|
+
|
90
|
+
# ==================
|
91
|
+
# Validate arguments
|
92
|
+
# ==================
|
93
|
+
|
94
|
+
# Expand the path of the URDF/SDF file if not absolute.
|
95
|
+
if args.description is not None:
|
96
|
+
args.description = (
|
97
|
+
(
|
98
|
+
args.description
|
99
|
+
if args.description.is_absolute()
|
100
|
+
else pathlib.Path.cwd() / args.description
|
101
|
+
)
|
102
|
+
.expanduser()
|
103
|
+
.absolute()
|
104
|
+
)
|
105
|
+
|
106
|
+
if not pathlib.Path(args.description).is_file():
|
107
|
+
msg = f"The URDF/SDF file '{args.description}' does not exist."
|
108
|
+
parser.error(msg)
|
109
|
+
sys.exit(1)
|
110
|
+
|
111
|
+
# Expand the path of the output MJCF file if not absolute.
|
112
|
+
if args.export is not None:
|
113
|
+
args.export = (
|
114
|
+
(
|
115
|
+
args.export
|
116
|
+
if args.export.is_absolute()
|
117
|
+
else pathlib.Path.cwd() / args.export
|
118
|
+
)
|
119
|
+
.expanduser()
|
120
|
+
.absolute()
|
121
|
+
)
|
122
|
+
|
123
|
+
if pathlib.Path(args.export).is_file() and not args.force:
|
124
|
+
msg = "The output file '{}' already exists, use '--force' to override."
|
125
|
+
parser.error(msg.format(args.export))
|
126
|
+
sys.exit(1)
|
127
|
+
|
128
|
+
# ================================================
|
129
|
+
# Load the URDF/SDF file and produce a MJCF string
|
130
|
+
# ================================================
|
131
|
+
|
132
|
+
match args.description.suffix.lower()[1:]:
|
133
|
+
|
134
|
+
case "urdf":
|
135
|
+
mjcf_string, assets = UrdfToMjcf().convert(urdf=args.description)
|
136
|
+
|
137
|
+
case "sdf":
|
138
|
+
mjcf_string, assets = SdfToMjcf().convert(
|
139
|
+
sdf=args.description, model_name=args.model_name
|
140
|
+
)
|
141
|
+
|
142
|
+
case _:
|
143
|
+
msg = f"The file extension '{args.description.suffix}' is not supported."
|
144
|
+
parser.error(msg)
|
145
|
+
sys.exit(1)
|
146
|
+
|
147
|
+
if args.print:
|
148
|
+
print(mjcf_string, flush=True)
|
149
|
+
|
150
|
+
# ========================================
|
151
|
+
# Write the MJCF string to the output file
|
152
|
+
# ========================================
|
153
|
+
|
154
|
+
if args.export is not None:
|
155
|
+
with open(args.export, "w+", encoding="utf-8") as file:
|
156
|
+
file.write(mjcf_string)
|
157
|
+
|
158
|
+
# =======================================
|
159
|
+
# Visualize the MJCF in the Mujoco viewer
|
160
|
+
# =======================================
|
161
|
+
|
162
|
+
if args.visualize:
|
163
|
+
|
164
|
+
mj_model_helper = MujocoModelHelper.build_from_xml(
|
165
|
+
mjcf_description=mjcf_string, assets=assets
|
166
|
+
)
|
167
|
+
|
168
|
+
viz = MujocoVisualizer(model=mj_model_helper.model, data=mj_model_helper.data)
|
169
|
+
|
170
|
+
with viz.open() as viewer:
|
171
|
+
|
172
|
+
with viewer.lock():
|
173
|
+
if args.base_position is not None:
|
174
|
+
mj_model_helper.set_base_position(
|
175
|
+
position=np.array(args.base_position)
|
176
|
+
)
|
177
|
+
|
178
|
+
if args.base_quaternion is not None:
|
179
|
+
mj_model_helper.set_base_orientation(
|
180
|
+
orientation=np.array(args.base_quaternion)
|
181
|
+
)
|
182
|
+
|
183
|
+
viz.sync(viewer=viewer)
|
184
|
+
|
185
|
+
while viewer.is_running():
|
186
|
+
time.sleep(0.500)
|
187
|
+
|
188
|
+
# =============================
|
189
|
+
# Exit the program with success
|
190
|
+
# =============================
|
191
|
+
|
192
|
+
sys.exit(0)
|