evo
Advanced tools
@@ -45,10 +45,10 @@ # https://docs.microsoft.com/azure/devops/pipelines/languages/python | ||
| imageName: 'ubuntu-latest' | ||
| Python-3.13-ubuntu: | ||
| python.version: '3.13' | ||
| Python-3.14-ubuntu: | ||
| python.version: '3.14' | ||
| imageName: 'ubuntu-latest' | ||
| Python-3.13-mac: | ||
| python.version: '3.13' | ||
| Python-3.14-mac: | ||
| python.version: '3.14' | ||
| imageName: 'macOS-latest' | ||
| Python-3.13-windows: | ||
| python.version: '3.13' | ||
| Python-3.14-windows: | ||
| python.version: '3.14' | ||
| imageName: 'windows-latest' | ||
@@ -55,0 +55,0 @@ maxParallel: 10 |
@@ -54,3 +54,3 @@ #!/usr/bin/env python3 | ||
| def configure_blueprint() -> rr.BlueprintLike: | ||
| def configure_blueprint() -> rrb.BlueprintLike: | ||
| # Adapt the blueprint's visible time range to include a sliding window | ||
@@ -57,0 +57,0 @@ # instead of "latest" for better visibility. Can be changed also in the viewer. |
+1
-1
@@ -15,3 +15,3 @@ import logging | ||
| __version__ = "v1.32.0" | ||
| __version__ = "v1.33.0" | ||
@@ -18,0 +18,0 @@ |
@@ -233,6 +233,2 @@ """ | ||
| confirm_overwrite=not args.no_warnings) | ||
| if args.serialize_plot: | ||
| logger.debug(SEP) | ||
| plot_collection.serialize(args.serialize_plot, | ||
| confirm_overwrite=not args.no_warnings) | ||
| plot_collection.close() | ||
@@ -239,0 +235,0 @@ |
@@ -95,4 +95,2 @@ import argparse | ||
| help="path to save plot") | ||
| output_opts.add_argument("--serialize_plot", default=None, | ||
| help="path to serialize plot (experimental)") | ||
| output_opts.add_argument("--rerun", action="store_true", | ||
@@ -99,0 +97,0 @@ help="Log visualization data to rerun.") |
+1
-1
@@ -170,3 +170,3 @@ #!/usr/bin/env python | ||
| if args.plot or args.save_plot or args.serialize_plot: | ||
| if args.plot or args.save_plot: | ||
| common.plot_result(args, result, traj_ref, | ||
@@ -173,0 +173,0 @@ result.trajectories[est_name], |
+0
-1
@@ -53,3 +53,2 @@ #!/usr/bin/env python | ||
| evo_ipython - IPython shell with pre-loaded evo modules | ||
| evo_fig - (experimental) tool for re-opening serialized plots | ||
| evo_config - tool for global settings and config file manipulation | ||
@@ -56,0 +55,0 @@ ''' |
@@ -31,5 +31,2 @@ import argparse | ||
| default=None) | ||
| output_opts.add_argument("--serialize_plot", | ||
| help="path to serialize plot (experimental)", | ||
| default=None) | ||
| output_opts.add_argument( | ||
@@ -36,0 +33,0 @@ "--save_table", help="path to a file to save the results in a table", |
+1
-5
@@ -157,3 +157,3 @@ #!/usr/bin/env python | ||
| if args.plot or args.save_plot or args.serialize_plot: | ||
| if args.plot or args.save_plot: | ||
| # check if data has NaN "holes" due to different indices | ||
@@ -242,6 +242,2 @@ inconsistent = error_df.isnull().values.any() | ||
| confirm_overwrite=not args.no_warnings) | ||
| if args.serialize_plot: | ||
| logger.debug(SEP) | ||
| plot_collection.serialize(args.serialize_plot, | ||
| confirm_overwrite=not args.no_warnings) | ||
@@ -248,0 +244,0 @@ |
@@ -110,4 +110,2 @@ import argparse | ||
| help="path to save plot") | ||
| output_opts.add_argument("--serialize_plot", default=None, | ||
| help="path to serialize plot (experimental)") | ||
| output_opts.add_argument("--rerun", action="store_true", | ||
@@ -114,0 +112,0 @@ help="Log visualization data to rerun.") |
+1
-1
@@ -193,3 +193,3 @@ #!/usr/bin/env python | ||
| if args.plot or args.save_plot or args.serialize_plot: | ||
| if args.plot or args.save_plot: | ||
| common.plot_result(args, result, traj_ref, | ||
@@ -196,0 +196,0 @@ result.trajectories[est_name], |
@@ -94,5 +94,2 @@ import argparse | ||
| default=None) | ||
| output_opts.add_argument("--serialize_plot", | ||
| help="path to serialize plot (experimental)", | ||
| default=None) | ||
| output_opts.add_argument("--save_as_tum", | ||
@@ -99,0 +96,0 @@ help="save trajectories in TUM format (as *.tum)", |
+4
-6
@@ -304,3 +304,3 @@ #!/usr/bin/env python | ||
| if args.plot or args.save_plot or args.serialize_plot: | ||
| if args.plot or args.save_plot: | ||
| import numpy as np | ||
@@ -444,6 +444,2 @@ from evo.tools import plot | ||
| confirm_overwrite=not args.no_warnings) | ||
| if args.serialize_plot: | ||
| logger.info(SEP) | ||
| plot_collection.serialize(args.serialize_plot, | ||
| confirm_overwrite=not args.no_warnings) | ||
@@ -481,3 +477,5 @@ if args.save_as_tum: | ||
| datetime.datetime.now().strftime("%Y-%m-%d-%H-%M-%S")) | ||
| writers.append(Rosbag2Writer(dest_bag_path)) | ||
| writers.append( | ||
| Rosbag2Writer(dest_bag_path, | ||
| version=SETTINGS.ros2_bag_format_version)) | ||
| for writer in writers: | ||
@@ -484,0 +482,0 @@ logger.info(SEP) |
+2
-16
@@ -24,7 +24,5 @@ # -*- coding: UTF8 -*- | ||
| import os | ||
| import collections | ||
| import collections.abc | ||
| import itertools | ||
| import logging | ||
| import pickle | ||
| import typing | ||
@@ -115,13 +113,8 @@ from enum import Enum, unique | ||
| class PlotCollection: | ||
| def __init__(self, title: str = "", | ||
| deserialize: typing.Optional[PathStr] = None): | ||
| def __init__(self, title: str = ""): | ||
| self.title = " ".join(title.splitlines()) # one line title | ||
| self.figures = collections.OrderedDict() # remember placement order | ||
| self.figures: dict[str, Figure] = {} | ||
| # hack to avoid premature garbage collection when serializing with Qt | ||
| # initialized later in tabbed_{qt, tk}_window | ||
| self.root_window: typing.Optional[typing.Any] = None | ||
| if deserialize is not None: | ||
| logger.debug("Deserializing PlotCollection from %s ...", | ||
| deserialize) | ||
| self.figures = pickle.load(open(deserialize, 'rb')) | ||
@@ -234,9 +227,2 @@ def __str__(self) -> str: | ||
| def serialize(self, dest: str, confirm_overwrite: bool = True) -> None: | ||
| logger.debug("Serializing PlotCollection to " + dest + "...") | ||
| if confirm_overwrite and not user.check_and_confirm_overwrite(dest): | ||
| return | ||
| else: | ||
| pickle.dump(self.figures, open(dest, 'wb')) | ||
| def export(self, file_path: str, confirm_overwrite: bool = True) -> None: | ||
@@ -243,0 +229,0 @@ base, ext = os.path.splitext(file_path) |
@@ -222,2 +222,6 @@ """ | ||
| ), | ||
| "ros2_bag_format_version": ( | ||
| 9, | ||
| "ROS 2 bag file format version to use when writing files." | ||
| ), | ||
| "ros_map_alpha_value": ( | ||
@@ -224,0 +228,0 @@ 1.0, |
+8
-4
| Metadata-Version: 2.4 | ||
| Name: evo | ||
| Version: 1.32.0 | ||
| Version: 1.33.0 | ||
| Summary: Python package for the evaluation of odometry and SLAM | ||
@@ -19,2 +19,3 @@ Project-URL: Homepage, https://github.com/MichaelGrupp/evo | ||
| Classifier: Programming Language :: Python :: 3.13 | ||
| Classifier: Programming Language :: Python :: 3.14 | ||
| Classifier: Programming Language :: Python :: Implementation :: CPython | ||
@@ -34,3 +35,3 @@ Classifier: Topic :: Scientific/Engineering | ||
| Requires-Dist: pyyaml | ||
| Requires-Dist: rosbags>=0.10.9 | ||
| Requires-Dist: rosbags>=0.11.0 | ||
| Requires-Dist: scipy>=1.2 | ||
@@ -86,3 +87,3 @@ Requires-Dist: seaborn>=0.9 | ||
| * algorithmic options for association, alignment, scale adjustment for monocular SLAM etc. | ||
| * flexible options for output, [plotting](https://github.com/MichaelGrupp/evo/wiki/Plotting) or export (e.g. LaTeX plots or Excel tables) | ||
| * flexible options for output, [plotting](https://github.com/MichaelGrupp/evo/wiki/Plotting), [visualization](https://github.com/MichaelGrupp/evo/wiki/Rerun-integration) or export (e.g. LaTeX plots or Excel tables) | ||
| * a powerful, configurable CLI that can cover many use cases | ||
@@ -145,2 +146,6 @@ * modular `core` and `tools` libraries for custom extensions | ||
| **Rerun (optional)** | ||
| You can log data also to the [rerun](https://rerun.io/) viewer. See the related [Wiki page](https://github.com/MichaelGrupp/evo/wiki/Rerun-integration) for more details. | ||
| --- | ||
@@ -161,3 +166,2 @@ | ||
| * `evo_res` - tool for comparing one or multiple result files from `evo_ape` or `evo_rpe` | ||
| * `evo_fig` - (experimental) tool for re-opening serialized plots (saved with `--serialize_plot`) | ||
| * `evo_config` - tool for global settings and config file manipulation | ||
@@ -164,0 +168,0 @@ |
+2
-2
@@ -39,2 +39,3 @@ [project.urls] | ||
| "Programming Language :: Python :: 3.13", | ||
| "Programming Language :: Python :: 3.14", | ||
| "Programming Language :: Python :: Implementation :: CPython" | ||
@@ -63,3 +64,3 @@ ] | ||
| "pillow", | ||
| "rosbags>=0.10.9", | ||
| "rosbags>=0.11.0", | ||
| "packaging", | ||
@@ -80,4 +81,3 @@ ] | ||
| evo_config = "evo.main_config:main" | ||
| evo_fig = "evo.main_fig:main" | ||
| evo_ipython = "evo.main_ipython:main" | ||
| evo = "evo.main_evo:main" |
+5
-2
@@ -41,3 +41,3 @@ # evo | ||
| * algorithmic options for association, alignment, scale adjustment for monocular SLAM etc. | ||
| * flexible options for output, [plotting](https://github.com/MichaelGrupp/evo/wiki/Plotting) or export (e.g. LaTeX plots or Excel tables) | ||
| * flexible options for output, [plotting](https://github.com/MichaelGrupp/evo/wiki/Plotting), [visualization](https://github.com/MichaelGrupp/evo/wiki/Rerun-integration) or export (e.g. LaTeX plots or Excel tables) | ||
| * a powerful, configurable CLI that can cover many use cases | ||
@@ -100,2 +100,6 @@ * modular `core` and `tools` libraries for custom extensions | ||
| **Rerun (optional)** | ||
| You can log data also to the [rerun](https://rerun.io/) viewer. See the related [Wiki page](https://github.com/MichaelGrupp/evo/wiki/Rerun-integration) for more details. | ||
| --- | ||
@@ -116,3 +120,2 @@ | ||
| * `evo_res` - tool for comparing one or multiple result files from `evo_ape` or `evo_rpe` | ||
| * `evo_fig` - (experimental) tool for re-opening serialized plots (saved with `--serialize_plot`) | ||
| * `evo_config` - tool for global settings and config file manipulation | ||
@@ -119,0 +122,0 @@ |
@@ -12,3 +12,2 @@ { | ||
| "save_plot": "tmp/plot.pdf", | ||
| "serialize_plot": "tmp/plot.pickle", | ||
| "silent": false, | ||
@@ -15,0 +14,0 @@ "t_max_diff": 0.01, |
@@ -15,3 +15,2 @@ { | ||
| "save_results": "tmp/result.zip", | ||
| "serialize_plot": "tmp/plot.pickle", | ||
| "logfile": "tmp/log.txt", | ||
@@ -18,0 +17,0 @@ "silent": false, |
@@ -15,3 +15,2 @@ { | ||
| "save_results": "tmp/result.zip", | ||
| "serialize_plot": "tmp/plot.pickle", | ||
| "logfile": "tmp/log.txt", | ||
@@ -18,0 +17,0 @@ "silent": false, |
@@ -7,3 +7,2 @@ { | ||
| "save_table": "tmp/table.csv", | ||
| "serialize_plot": "tmp/plot.pickle", | ||
| "logfile": "tmp/log.txt", | ||
@@ -10,0 +9,0 @@ "silent": false, |
@@ -6,3 +6,2 @@ { | ||
| "save_table": "tmp/table.csv", | ||
| "serialize_plot": "tmp/plot.pickle", | ||
| "logfile": "tmp/log.txt", | ||
@@ -9,0 +8,0 @@ "silent": false, |
@@ -15,3 +15,2 @@ { | ||
| "save_table": "tmp/table.csv", | ||
| "serialize_plot": "tmp/plot.pickle", | ||
| "logfile": "tmp/log.txt", | ||
@@ -18,0 +17,0 @@ "silent": false, |
@@ -15,3 +15,2 @@ { | ||
| "save_table": "tmp/table.csv", | ||
| "serialize_plot": "tmp/plot.pickle", | ||
| "logfile": "tmp/log.txt", | ||
@@ -18,0 +17,0 @@ "silent": false, |
@@ -35,4 +35,4 @@ #!/usr/bin/env python | ||
| from evo.tools import file_interface | ||
| from evo.tools.settings import SETTINGS | ||
| class MockFileTestCase(unittest.TestCase): | ||
@@ -158,8 +158,11 @@ def __init__(self, in_memory_buffer, *args, **kwargs): | ||
| def test_write_read_integrity(self): | ||
| for reader_t, writer_t in zip([Rosbag1Reader, Rosbag2Reader], | ||
| [Rosbag1Writer, Rosbag2Writer]): | ||
| for reader_t in [Rosbag1Reader, Rosbag2Reader]: | ||
| # TODO: rosbags cannot overwrite existing paths, this forces us | ||
| # to do this here to get only a filepath: | ||
| tmp_filename = tempfile.NamedTemporaryFile(delete=True).name | ||
| bag_out = writer_t(tmp_filename) | ||
| if reader_t is Rosbag1Reader: | ||
| bag_out = Rosbag1Writer(tmp_filename) | ||
| else: | ||
| bag_out = Rosbag2Writer( | ||
| tmp_filename, version=SETTINGS.ros2_bag_format_version) | ||
| bag_out.open() | ||
@@ -166,0 +169,0 @@ traj_out = helpers.fake_trajectory(1000, 0.1) |
| #!/usr/bin/env python | ||
| # -*- coding: UTF8 -*- | ||
| # PYTHON_ARGCOMPLETE_OK | ||
| """ | ||
| plot editor | ||
| author: Michael Grupp | ||
| This file is part of evo (github.com/MichaelGrupp/evo). | ||
| evo is free software: you can redistribute it and/or modify | ||
| it under the terms of the GNU General Public License as published by | ||
| the Free Software Foundation, either version 3 of the License, or | ||
| (at your option) any later version. | ||
| evo is distributed in the hope that it will be useful, | ||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| GNU General Public License for more details. | ||
| You should have received a copy of the GNU General Public License | ||
| along with evo. If not, see <http://www.gnu.org/licenses/>. | ||
| """ | ||
| import logging | ||
| from pathlib import Path | ||
| logger = logging.getLogger(__name__) | ||
| SEP = "-" * 80 # separator line | ||
| def main() -> None: | ||
| import argparse | ||
| import argcomplete | ||
| basic_desc = "experimental tool for opening a serialized PlotCollection" | ||
| lic = "(c) evo authors" | ||
| main_parser = argparse.ArgumentParser(description="%s %s" % | ||
| (basic_desc, lic)) | ||
| main_parser.add_argument("in_file", | ||
| help="path to a serialized plot_collection") | ||
| main_parser.add_argument("-t", "--title", | ||
| help="custom title (default: file name)") | ||
| main_parser.add_argument("--save_plot", help="path to save plot", | ||
| default=None) | ||
| main_parser.add_argument("--serialize_plot", | ||
| help="path to re-serialize PlotCollection", | ||
| default=None) | ||
| main_parser.add_argument("--to_html", | ||
| help="convert to html (requires mpld3 library)", | ||
| action="store_true") | ||
| main_parser.add_argument("--no_warnings", | ||
| help="no warnings requiring user confirmation", | ||
| action="store_true") | ||
| argcomplete.autocomplete(main_parser) | ||
| args = main_parser.parse_args() | ||
| from evo.tools import log, plot, user | ||
| log.configure_logging(verbose=True) | ||
| if not args.title: | ||
| title = Path(args.in_file).name | ||
| else: | ||
| title = args.title | ||
| if not args.no_warnings: | ||
| logger.warning( | ||
| "This tool is experimental and not guranteed to work.\nOnly works " | ||
| "if the same plot settings are used as for serialization.\n" | ||
| "If not, try: evo_config show/set \n" + SEP) | ||
| plot_collection = plot.PlotCollection(title, deserialize=args.in_file) | ||
| logger.debug("Deserialized PlotCollection: " + str(plot_collection)) | ||
| plot_collection.show() | ||
| if args.serialize_plot: | ||
| logger.debug(SEP) | ||
| plot_collection.serialize(args.serialize_plot, | ||
| confirm_overwrite=not args.no_warnings) | ||
| if args.save_plot: | ||
| logger.debug(SEP) | ||
| plot_collection.export(args.save_plot, | ||
| confirm_overwrite=not args.no_warnings) | ||
| if args.to_html: | ||
| import mpld3 | ||
| logger.debug(SEP + "\nhtml export\n") | ||
| for name, fig in plot_collection.figures.items(): | ||
| html = mpld3.fig_to_html(fig) | ||
| out = name + ".html" | ||
| with open(out, 'w') as f: | ||
| logger.debug(out) | ||
| f.write(html) | ||
| if not args.no_warnings: | ||
| logger.debug(SEP) | ||
| if user.confirm("Save changes & overwrite original file " + | ||
| args.in_file + "? (y/n)"): | ||
| plot_collection.serialize(args.in_file, confirm_overwrite=False) | ||
| if __name__ == '__main__': | ||
| main() |
Alert delta unavailable
Currently unable to show alert delta for PyPI packages.
14356043
-0.04%191
-0.52%11403
-1.02%