diff --git a/.flake8 b/.flake8 deleted file mode 100644 index c77f18b6..00000000 --- a/.flake8 +++ /dev/null @@ -1,22 +0,0 @@ -[flake8] -ignore = - # Whitespace before ':' - E203, - # Module level import not at top of file - E402, - # Line break occurred before a binary operator - W503, - # Line break occurred after a binary operator - W504 - # line break before binary operator - E203 - # line too long - E501 - # No lambdas — too strict - E731 - # Local variable name is assigned to but never used - F841 -per-file-ignores = - # imported but unused - __init__.py: F401 -max-line-length = 120 diff --git a/.github/workflows/pre-commit.yaml b/.github/workflows/pre-commit.yaml index 2b11178b..1d1b74a2 100644 --- a/.github/workflows/pre-commit.yaml +++ b/.github/workflows/pre-commit.yaml @@ -3,7 +3,7 @@ name: pre-commit on: pull_request: push: - branches: [main] + branches: [dev_v0.0.8] jobs: pre-commit: diff --git a/.github/workflows/pytest.yaml b/.github/workflows/pytest.yaml new file mode 100644 index 00000000..d0c101ad --- /dev/null +++ b/.github/workflows/pytest.yaml @@ -0,0 +1,26 @@ +name: pytest + +on: + push: + branches: [dev_v0.0.8] + +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] + + steps: + - uses: actions/checkout@v2 + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + - name: Install dependencies + run: | + pip install uv + uv pip install --system -e ".[dev]" + - name: Test with pytest + run: | + pytest diff --git a/.gitignore b/.gitignore index 426cc468..244dafcc 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,7 @@ docs/_build/ docs/build/ _build/ .doctrees/ + + +# ruff +.ruff_cache/* diff --git a/.isort.cfg b/.isort.cfg deleted file mode 100644 index c168c36f..00000000 --- a/.isort.cfg +++ /dev/null @@ -1,7 +0,0 @@ -[tool.isort] -include_trailing_comma = true -known_first_party = [] -line_length = 120 -multi_line_output = 3 -profile = "black" -use_parentheses = true diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 18eca0ba..fe86c1fe 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -18,31 +18,14 @@ repos: exclude: /README\.rst$|\.pot?$|\.ipynb$ args: ['--no-sort-keys', "--autofix"] -- repo: https://github.com/pycqa/isort - rev: 6.0.1 +- repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.6.2 hooks: - - id: isort - name: isort (python) - args: ["--profile", "black", "--filter-files", '--line-length', '120'] + - id: ruff + args: [--fix] + exclude: __init__.py$ + - id: ruff-format exclude: __init__.py$ -- repo: https://github.com/ambv/black - rev: 25.1.0 - hooks: - - id: black - language_version: python3.12 - args: ['--line-length=120'] - files: "\\.py$" -- repo: https://github.com/myint/autoflake - rev: v2.3.1 - hooks: - - id: autoflake - args: ['--in-place', '--remove-all-unused-imports', '--remove-unused-variable'] - exclude: __init__.py$ - language_version: python3.12 -- repo: https://github.com/pycqa/flake8 - rev: 7.3.0 - hooks: - - id: flake8 - repo: https://github.com/kynan/nbstripout rev: 0.8.1 hooks: diff --git a/docs/conf.py b/docs/conf.py index bae517bb..5841ae21 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -10,7 +10,7 @@ project = "py123d" copyright = "2025, 123D Contributors" author = "123D Contributors" -release = "v0.0.7" +release = "v0.0.8" # -- General configuration --------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration @@ -23,7 +23,6 @@ "sphinx.ext.intersphinx", "sphinx.ext.napoleon", "sphinx_copybutton", - "sphinx_inline_tabs", "sphinx_autodoc_typehints", "myst_parser", ] diff --git a/notebooks/01_scene_tutorial.ipynb b/notebooks/01_scene_tutorial.ipynb index 225aea5e..3b7b9717 100644 --- a/notebooks/01_scene_tutorial.ipynb +++ b/notebooks/01_scene_tutorial.ipynb @@ -49,11 +49,11 @@ "from py123d.api.scene.arrow.arrow_scene_builder import ArrowSceneBuilder\n", "from py123d.api.scene.scene_filter import SceneFilter\n", "\n", - "\n", "# from py123d.common.multithreading.worker_ray import RayDistributed\n", "# from py123d.common.multithreading.worker_ray import RayDistributed\n", "from py123d.common.multithreading.worker_sequential import Sequential\n", "from py123d.datatypes.sensors.pinhole_camera import PinholeCameraType\n", + "\n", "# from py123d.datatypes.sensors.pinhole_camera_type import PinholeCameraType\n", "\n", "# splits = [\"kitti360_train\"]\n", @@ -83,7 +83,7 @@ "\n", "# worker = RayDistributed()\n", "scenes = scene_builder.get_scenes(scene_filter, worker)\n", - "print(f\"Found {len(scenes)} scenes\")\n" + "print(f\"Found {len(scenes)} scenes\")" ] }, { @@ -101,7 +101,6 @@ "metadata": {}, "outputs": [], "source": [ - "\n", "scene = scenes[0]\n", "\n", "log_metadata = scene.get_log_metadata()\n", @@ -128,7 +127,6 @@ "source": [ "from py123d.visualization.viser.viser_viewer import ViserViewer\n", "\n", - "\n", "visualization_server = ViserViewer(scenes, scene_index=0)" ] }, @@ -139,8 +137,10 @@ "metadata": {}, "outputs": [], "source": [ - "from py123d.geometry import EulerAngles\n", "import numpy as np\n", + "\n", + "from py123d.geometry import EulerAngles\n", + "\n", "euler_angles = EulerAngles(roll=0.0, pitch=0.0, yaw=np.pi)\n", "euler_angles.roll\n", "# 0.0\n", diff --git a/notebooks/bev_matplotlib.ipynb b/notebooks/bev_matplotlib.ipynb index db3aa151..a5716ca4 100644 --- a/notebooks/bev_matplotlib.ipynb +++ b/notebooks/bev_matplotlib.ipynb @@ -9,8 +9,6 @@ "source": [ "from py123d.api.scene.arrow.arrow_scene_builder import ArrowSceneBuilder\n", "from py123d.api.scene.scene_filter import SceneFilter\n", - "\n", - "\n", "from py123d.common.multithreading.worker_sequential import Sequential\n", "# from py123d.datatypes.sensors.pinhole_camera_type import PinholeCameraType" ] @@ -24,11 +22,12 @@ "source": [ "# splits = [\"kitti360_train\"]\n", "# splits = [\"nuscenes-mini_val\", \"nuscenes-mini_train\"]\n", - "splits = [\"nuplan-mini_test\", \"nuplan-mini_train\", \"nuplan-mini_val\"]\n", + "# splits = [\"nuplan-mini_test\", \"nuplan-mini_train\", \"nuplan-mini_val\"]\n", "# splits = [\"carla_test\"]\n", "# splits = [\"wopd_val\"]\n", "# splits = [\"av2-sensor_train\"]\n", "# splits = [\"pandaset_test\", \"pandaset_val\", \"pandaset_train\"]\n", + "splits = None\n", "log_names = None\n", "scene_uuids = None\n", "\n", @@ -45,7 +44,7 @@ "scene_builder = ArrowSceneBuilder()\n", "worker = Sequential()\n", "scenes = scene_builder.get_scenes(scene_filter, worker)\n", - "print(f\"Found {len(scenes)} scenes\")\n" + "print(f\"Found {len(scenes)} scenes\")" ] }, { @@ -59,25 +58,22 @@ "\n", "import matplotlib.pyplot as plt\n", "import numpy as np\n", + "import shapely.geometry as geom\n", "\n", "from py123d.api.map.map_api import MapAPI\n", + "from py123d.api.scene.scene_api import SceneAPI\n", "from py123d.datatypes.map_objects.map_layer_types import MapLayer\n", - "from py123d.datatypes.map_objects.map_objects import Lane, LaneGroup\n", + "from py123d.datatypes.map_objects.map_objects import LaneGroup\n", "from py123d.geometry import Point2D\n", - "from py123d.visualization.color.color import BLACK, DARK_GREY, DARKER_GREY, LIGHT_GREY, NEW_TAB_10, TAB_10\n", + "from py123d.visualization.color.color import BLACK, DARKER_GREY, NEW_TAB_10, TAB_10\n", "from py123d.visualization.color.config import PlotConfig\n", "from py123d.visualization.color.default import CENTERLINE_CONFIG, MAP_SURFACE_CONFIG, ROUTE_CONFIG\n", "from py123d.visualization.matplotlib.observation import (\n", " add_box_detections_to_ax,\n", " add_default_map_on_ax,\n", " add_ego_vehicle_to_ax,\n", - " add_traffic_lights_to_ax,\n", ")\n", "from py123d.visualization.matplotlib.utils import add_shapely_linestring_to_ax, add_shapely_polygon_to_ax\n", - "from py123d.api.scene.scene_api import SceneAPI\n", - "\n", - "\n", - "import shapely.geometry as geom\n", "\n", "LEFT_CONFIG: PlotConfig = PlotConfig(\n", " fill_color=TAB_10[2],\n", @@ -154,7 +150,6 @@ " patch = geom.box(x_min, y_min, x_max, y_max)\n", " map_objects_dict = map_api.query(geometry=patch, layers=layers, predicate=\"intersects\")\n", "\n", - "\n", " for layer, map_objects in map_objects_dict.items():\n", " for map_object in map_objects:\n", " try:\n", @@ -192,7 +187,6 @@ " # line_color=NEW_TAB_10[line_type % (len(NEW_TAB_10) - 1)],\n", " # line_color_alpha=1.0,\n", " # line_width=1.5,\n", - " # line_style=\"-\",\n", " # zorder=10,\n", " # )\n", " add_shapely_linestring_to_ax(ax, map_object.polyline_3d.linestring, ROAD_LINE_CONFIG)\n", @@ -207,12 +201,11 @@ "\n", "\n", "def _plot_scene_on_ax(ax: plt.Axes, scene: SceneAPI, iteration: int = 0, radius: float = 80) -> plt.Axes:\n", - "\n", " ego_vehicle_state = scene.get_ego_state_at_iteration(iteration)\n", " box_detections = scene.get_box_detections_at_iteration(iteration)\n", " map_api = scene.get_map_api()\n", "\n", - " point_2d = ego_vehicle_state.bounding_box.center.point_2d\n", + " point_2d = ego_vehicle_state.bounding_box.center_se2.point_2d\n", " if map_api is not None:\n", " # add_debug_map_on_ax(ax, scene.get_map_api(), point_2d, radius=radius, route_lane_group_ids=None)\n", "\n", @@ -230,10 +223,7 @@ " return ax\n", "\n", "\n", - "def plot_scene_at_iteration(\n", - " scene: SceneAPI, iteration: int = 0, radius: float = 80\n", - ") -> Tuple[plt.Figure, plt.Axes]:\n", - "\n", + "def plot_scene_at_iteration(scene: SceneAPI, iteration: int = 0, radius: float = 80) -> Tuple[plt.Figure, plt.Axes]:\n", " size = 10\n", "\n", " fig, ax = plt.subplots(figsize=(size, size))\n", @@ -277,7 +267,7 @@ ], "metadata": { "kernelspec": { - "display_name": "py123d", + "display_name": "py123d_dev", "language": "python", "name": "python3" }, diff --git a/notebooks/bev_render.ipynb b/notebooks/bev_render.ipynb index 4fb28d29..e519ac78 100644 --- a/notebooks/bev_render.ipynb +++ b/notebooks/bev_render.ipynb @@ -9,9 +9,8 @@ "source": [ "from py123d.api.scene.arrow.arrow_scene_builder import ArrowSceneBuilder\n", "from py123d.api.scene.scene_filter import SceneFilter\n", - "\n", "from py123d.common.multithreading.worker_sequential import Sequential\n", - "# from py123d.datatypes.sensors.pinhole_camera import PinholeCameraType " + "# from py123d.datatypes.sensors.pinhole_camera import PinholeCameraType" ] }, { @@ -49,8 +48,8 @@ "worker = Sequential()\n", "scenes = scene_builder.get_scenes(scene_filter, worker)\n", "\n", - "scenes = [scene for scene in scenes if scene.uuid in scene_uuids]\n", - "print(f\"Found {len(scenes)} scenes\")\n" + "scenes = [scene for scene in scenes if scene.uuid in scene_uuids]\n", + "print(f\"Found {len(scenes)} scenes\")" ] }, { diff --git a/notebooks/camera_matplotlib.ipynb b/notebooks/camera_matplotlib.ipynb index f03c8d37..4ee3ca0b 100644 --- a/notebooks/camera_matplotlib.ipynb +++ b/notebooks/camera_matplotlib.ipynb @@ -9,7 +9,6 @@ "source": [ "from py123d.api.scene.arrow.arrow_scene_builder import ArrowSceneBuilder\n", "from py123d.api.scene.scene_filter import SceneFilter\n", - "\n", "from py123d.common.multithreading.worker_sequential import Sequential\n", "from py123d.datatypes.sensors.pinhole_camera import PinholeCameraType" ] @@ -60,8 +59,9 @@ "outputs": [], "source": [ "from matplotlib import pyplot as plt\n", + "\n", "from py123d.api.scene.abstract_scene import AbstractScene\n", - "from py123d.visualization.matplotlib.camera import add_box_detections_to_camera_ax, add_camera_ax\n", + "from py123d.visualization.matplotlib.camera import add_box_detections_to_camera_ax\n", "\n", "iteration = 0\n", "scene = scenes[0]\n", diff --git a/notebooks/camera_render.ipynb b/notebooks/camera_render.ipynb index dca62416..4f6f616e 100644 --- a/notebooks/camera_render.ipynb +++ b/notebooks/camera_render.ipynb @@ -9,7 +9,6 @@ "source": [ "from py123d.api.scene.arrow.arrow_scene_builder import ArrowSceneBuilder\n", "from py123d.api.scene.scene_filter import SceneFilter\n", - "\n", "from py123d.common.multithreading.worker_sequential import Sequential\n", "from py123d.datatypes.sensors.pinhole_camera import PinholeCameraType\n", "\n", @@ -51,8 +50,8 @@ "worker = Sequential()\n", "scenes = scene_builder.get_scenes(scene_filter, worker)\n", "\n", - "scenes = [scene for scene in scenes if scene.uuid in scene_uuids]\n", - "print(f\"Found {len(scenes)} scenes\")\n" + "scenes = [scene for scene in scenes if scene.uuid in scene_uuids]\n", + "print(f\"Found {len(scenes)} scenes\")" ] }, { @@ -62,11 +61,11 @@ "metadata": {}, "outputs": [], "source": [ + "import imageio\n", "from matplotlib import pyplot as plt\n", + "\n", "from py123d.api.scene.abstract_scene import AbstractScene\n", - "from py123d.visualization.matplotlib.camera import add_box_detections_to_camera_ax, add_camera_ax\n", - "import imageio\n", - "import numpy as np\n", + "from py123d.visualization.matplotlib.camera import add_box_detections_to_camera_ax\n", "\n", "iteration = 0\n", "scene = scenes[0]\n", diff --git a/pyproject.toml b/pyproject.toml index a977a8a6..abc145af 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -10,19 +10,20 @@ classifiers = [ "Development Status :: 3 - Alpha", "Intended Audience :: Developers", "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", "License :: OSI Approved :: Apache Software License", ] name = "py123d" -version = "v0.0.7" +version = "v0.0.8" authors = [{ name = "Daniel Dauner", email = "daniel.dauner@gmail.com" }] description = "TODO" readme = "README.md" -requires-python = ">=3.9" +requires-python = ">=3.8" license = {text = "Apache-2.0"} dependencies = [ - "bokeh", "geopandas", - "joblib", "matplotlib", "numpy", "opencv-python", @@ -32,23 +33,20 @@ dependencies = [ "pyarrow", "pyogrio", "pyquaternion", - "pytest", - "rasterio", "ray", - "rtree", "scipy", - "setuptools", "shapely>=2.0.0", "tqdm", "notebook", - "pre-commit", "hydra_colorlog", "hydra-core", - "lxml", "trimesh", "viser", "laspy[lazrs]", "DracoPy", + "omegaconf", + "typing-extensions", + "requests", ] [project.scripts] @@ -57,16 +55,16 @@ py123d-conversion = "py123d.script.run_conversion:main" [project.optional-dependencies] dev = [ - "black", - "isort", - "flake8", + "pyright", + "ruff", "pre-commit", + "pytest", + "pytest-cov", ] docs = [ "Sphinx", "sphinx-rtd-theme", "sphinx-autobuild", - "sphinx-inline-tabs", "sphinx-copybutton", "myst-parser", "furo", @@ -75,39 +73,12 @@ docs = [ ] nuplan = [ "nuplan-devkit @ git+https://github.com/motional/nuplan-devkit/@nuplan-devkit-v1.2", - "ujson", - "tornado", - "sympy", - "SQLAlchemy==1.4.27", - "selenium", - "nest_asyncio", - "cachetools", - "aioboto3", - "aiofiles", - "casadi", - "control", - "pyinstrument", - "Fiona", - "guppy3", - "retry", ] nuscenes = [ - "lanelet2", - "nuscenes-devkit==1.2.0", -] -nuscenes_expanded = [ "nuscenes-devkit==1.2.0", - "pycocotools==2.0.10", - "laspy==2.6.1", - "embreex==2.17.7.post6", - "lanelet2==1.2.2", - "protobuf==4.25.3", - "pycollada==0.9.2", - "vhacdx==0.0.8.post2", - "yourdfpy==0.0.58", + "lanelet2", ] waymo = [ - "protobuf==4.21.0", "tensorflow==2.13.0", "waymo-open-dataset-tf-2-12-0==1.6.6", ] @@ -121,3 +92,37 @@ where = ["src"] [project.urls] "Homepage" = "https://github.com/DanielDauner/py123d" "Bug Tracker" = "https://github.com/DanielDauner/py123d/issues" + + +[tool.ruff] +line-length = 120 +lint.select = [ + "E", # pycodestyle errors. + "F", # Pyflakes rules. + "PLC", # Pylint convention warnings. + "PLE", # Pylint errors. + "PLR", # Pylint refactor recommendations. + "PLW", # Pylint warnings. + "I", # Import sorting. +] +lint.ignore = [ + "E731", # Do not assign a lambda expression, use a def. + "E741", # Ambiguous variable name. (l, O, or I) + "E501", # Line too long. + "E402", # Module level import not at top of file + "PLR2004", # Magic value used in comparison. + "PLR0915", # Too many statements. + "PLR0913", # Too many arguments. + "PLC0414", # Import alias does not rename variable. (this is used for exporting names) + "PLC0415", # Import should be at the top-level of a file. + "PLC1901", # Use falsey strings. + "PLR5501", # Use `elif` instead of `else if`. + "PLR0911", # Too many return statements. + "PLR0912", # Too many branches. + "PLW0603", # Global statement updates are discouraged. + "PLW2901", # For loop variable overwritten. + "PLW0642", # Reassigned self in instance method. +] + +fixable = ["ALL"] +unfixable = [] diff --git a/src/py123d/api/map/gpkg/gpkg_map_api.py b/src/py123d/api/map/gpkg/gpkg_map_api.py index adb7ba01..e8f6699d 100644 --- a/src/py123d/api/map/gpkg/gpkg_map_api.py +++ b/src/py123d/api/map/gpkg/gpkg_map_api.py @@ -315,7 +315,6 @@ def _get_lane_group(self, id: str) -> Optional[LaneGroup]: lane_group: Optional[LaneGroup] = None lane_group_row = get_row_with_value(self._gpd_dataframes[MapLayer.LANE_GROUP], "id", id) if lane_group_row is not None: - object_id: str = lane_group_row["id"] lane_ids: List[str] = ast.literal_eval(lane_group_row.lane_ids) left_boundary: Polyline3D = Polyline3D.from_linestring(lane_group_row["left_boundary"]) @@ -349,7 +348,6 @@ def _get_intersection(self, id: str) -> Optional[Intersection]: intersection: Optional[Intersection] = None intersection_row = get_row_with_value(self._gpd_dataframes[MapLayer.INTERSECTION], "id", id) if intersection_row is not None: - object_id: str = intersection_row["id"] lane_group_ids: List[str] = ast.literal_eval(intersection_row.lane_group_ids) outline: Optional[Polyline3D] = ( @@ -375,7 +373,6 @@ def _get_crosswalk(self, id: str) -> Optional[Crosswalk]: crosswalk: Optional[Crosswalk] = None crosswalk_row = get_row_with_value(self._gpd_dataframes[MapLayer.CROSSWALK], "id", id) if crosswalk_row is not None: - object_id: str = crosswalk_row["id"] outline: Polyline3D = Polyline3D.from_linestring(crosswalk_row["outline"]) geometry: geom.Polygon = crosswalk_row["geometry"] @@ -394,7 +391,6 @@ def _get_walkway(self, id: str) -> Optional[Walkway]: walkway: Optional[Walkway] = None walkway_row = get_row_with_value(self._gpd_dataframes[MapLayer.WALKWAY], "id", id) if walkway_row is not None: - object_id: str = walkway_row["id"] outline: Polyline3D = Polyline3D.from_linestring(walkway_row["outline"]) geometry: geom.Polygon = walkway_row["geometry"] @@ -413,7 +409,6 @@ def _get_carpark(self, id: str) -> Optional[Carpark]: carpark: Optional[Carpark] = None carpark_row = get_row_with_value(self._gpd_dataframes[MapLayer.CARPARK], "id", id) if carpark_row is not None: - object_id: str = carpark_row["id"] outline: Polyline3D = Polyline3D.from_linestring(carpark_row["outline"]) geometry: geom.Polygon = carpark_row["geometry"] @@ -432,7 +427,6 @@ def _get_generic_drivable(self, id: str) -> Optional[GenericDrivable]: generic_drivable: Optional[GenericDrivable] = None generic_drivable_row = get_row_with_value(self._gpd_dataframes[MapLayer.GENERIC_DRIVABLE], "id", id) if generic_drivable_row is not None: - object_id: str = generic_drivable_row["id"] outline: Polyline3D = Polyline3D.from_linestring(generic_drivable_row["outline"]) geometry: geom.Polygon = generic_drivable_row["geometry"] @@ -451,7 +445,6 @@ def _get_road_edge(self, id: str) -> Optional[RoadEdge]: road_edge: Optional[RoadEdge] = None road_edge_row = get_row_with_value(self._gpd_dataframes[MapLayer.ROAD_EDGE], "id", id) if road_edge_row is not None: - object_id: str = road_edge_row["id"] polyline: Polyline3D = Polyline3D.from_linestring(road_edge_row["geometry"]) road_edge_type: RoadEdgeType = RoadEdgeType(road_edge_row["road_edge_type"]) @@ -470,7 +463,6 @@ def _get_road_line(self, id: str) -> Optional[RoadLine]: road_line: Optional[RoadLine] = None road_line_row = get_row_with_value(self._gpd_dataframes[MapLayer.ROAD_LINE], "id", id) if road_line_row is not None: - object_id: str = road_line_row["id"] polyline: Polyline3D = Polyline3D.from_linestring(road_line_row["geometry"]) road_line_type: RoadLineType = RoadLineType(road_line_row["road_line_type"]) diff --git a/src/py123d/api/map/gpkg/gpkg_utils.py b/src/py123d/api/map/gpkg/gpkg_utils.py index e165fc3c..9d8e8548 100644 --- a/src/py123d/api/map/gpkg/gpkg_utils.py +++ b/src/py123d/api/map/gpkg/gpkg_utils.py @@ -54,7 +54,6 @@ def get_row_with_value( geo_series: Optional[gpd.GeoSeries] = None matching_rows = get_all_rows_with_value(elements, column_label, desired_value) if matching_rows is not None: - assert len(matching_rows) > 0, f"Could not find the desired key = {desired_value}" assert len(matching_rows) == 1, ( f"{len(matching_rows)} matching keys found. Expected to only find one." "Try using get_all_rows_with_value" diff --git a/src/py123d/api/map/map_api.py b/src/py123d/api/map/map_api.py index c26a40ea..bfd1d131 100644 --- a/src/py123d/api/map/map_api.py +++ b/src/py123d/api/map/map_api.py @@ -33,7 +33,7 @@ def get_available_map_layers(self) -> List[MapLayer]: """ @abc.abstractmethod - def get_map_object(self, object_id: str, layer: MapLayer) -> Optional[BaseMapObject]: + def get_map_object(self, object_id: Union[str, int], layer: MapLayer) -> Optional[BaseMapObject]: """Returns a :class:`~p123d.datatypes.map_objects.base_map_object.BaseMapObject` by its ID and :class:`~p123d.datatypes.map_objects.map_layer_types.MapLayer`. diff --git a/src/py123d/api/scene/arrow/arrow_scene_builder.py b/src/py123d/api/scene/arrow/arrow_scene_builder.py index cccac275..12b55fed 100644 --- a/src/py123d/api/scene/arrow/arrow_scene_builder.py +++ b/src/py123d/api/scene/arrow/arrow_scene_builder.py @@ -172,7 +172,6 @@ def _get_scene_extraction_metadatas(log_path: Union[str, Path], filter: SceneFil scene_extraction_metadatas_ = [] for scene_extraction_metadata in scene_metadatas: - add_scene = True start_idx = scene_extraction_metadata.initial_idx if filter.pinhole_camera_types is not None: diff --git a/src/py123d/api/scene/scene_filter.py b/src/py123d/api/scene/scene_filter.py index 118005a1..a875e91c 100644 --- a/src/py123d/api/scene/scene_filter.py +++ b/src/py123d/api/scene/scene_filter.py @@ -52,8 +52,7 @@ def __post_init__(self): def _resolve_enum_arguments( serial_enum_cls: SerialIntEnum, input: Optional[List[Union[int, str, SerialIntEnum]]], - ) -> Optional[List[SerialIntEnum]]: - + ): if input is None: return None return [serial_enum_cls.from_arbitrary(value) for value in input] diff --git a/src/py123d/common/multithreading/ray_execution.py b/src/py123d/common/multithreading/ray_execution.py index b11badc5..eb769ca9 100644 --- a/src/py123d/common/multithreading/ray_execution.py +++ b/src/py123d/common/multithreading/ray_execution.py @@ -83,7 +83,8 @@ def _ray_map_items(task: Task, *item_lists: Iterable[List[Any]], log_dir: Option assert len(item_lists) > 0, "No map arguments received for mapping" assert all(isinstance(items, list) for items in item_lists), "All map arguments must be lists" assert all( - len(cast(List, items)) == len(item_lists[0]) for items in item_lists # type: ignore + len(cast(List, items)) == len(item_lists[0]) + for items in item_lists # type: ignore ), "All lists must have equal size" fn = task.fn # Wrap function in remote decorator and create ray objects diff --git a/src/py123d/common/utils/mixin.py b/src/py123d/common/utils/mixin.py index be2a86d8..3813ef12 100644 --- a/src/py123d/common/utils/mixin.py +++ b/src/py123d/common/utils/mixin.py @@ -1,9 +1,8 @@ from __future__ import annotations -from typing import Self - import numpy as np import numpy.typing as npt +from typing_extensions import Self class ArrayMixin: diff --git a/src/py123d/conversion/dataset_converter_config.py b/src/py123d/conversion/dataset_converter_config.py index 099a9bd4..ea1cfe77 100644 --- a/src/py123d/conversion/dataset_converter_config.py +++ b/src/py123d/conversion/dataset_converter_config.py @@ -6,7 +6,6 @@ @dataclass class DatasetConverterConfig: - force_log_conversion: bool = False force_map_conversion: bool = False @@ -41,7 +40,6 @@ class DatasetConverterConfig: include_route: bool = False def __post_init__(self): - assert self.pinhole_camera_store_option in [ "path", "jpeg_binary", diff --git a/src/py123d/conversion/datasets/av2/av2_map_conversion.py b/src/py123d/conversion/datasets/av2/av2_map_conversion.py index 8335ad23..da51ed62 100644 --- a/src/py123d/conversion/datasets/av2/av2_map_conversion.py +++ b/src/py123d/conversion/datasets/av2/av2_map_conversion.py @@ -262,7 +262,6 @@ def _get_lane_group_ids_of_lanes_ids(lane_ids: List[str]) -> List[int]: return list(set(lane_group_ids_)) for lane_group_id, lane_group_set in lane_group_set_dict.items(): - lane_group_dict[lane_group_id] = {} lane_group_dict[lane_group_id]["id"] = lane_group_id lane_group_dict[lane_group_id]["lane_ids"] = [int(lane_id) for lane_id in lane_group_set] diff --git a/src/py123d/conversion/datasets/av2/av2_sensor_converter.py b/src/py123d/conversion/datasets/av2/av2_sensor_converter.py index 713a311b..252b4fe9 100644 --- a/src/py123d/conversion/datasets/av2/av2_sensor_converter.py +++ b/src/py123d/conversion/datasets/av2/av2_sensor_converter.py @@ -123,7 +123,6 @@ def convert_log(self, log_index: int, log_writer: AbstractLogWriter) -> None: # 3. Process source log data if log_needs_writing: - sensor_df = build_sensor_dataframe(source_log_path) synchronization_df = build_synchronization_dataframe(sensor_df) @@ -209,7 +208,6 @@ def _get_av2_lidar_metadata( metadata: Dict[LiDARType, LiDARMetadata] = {} if dataset_converter_config.include_lidars: - # Load calibration feather file calibration_file = source_log_path / "calibration" / "egovehicle_SE3_sensor.feather" calibration_df = pd.read_feather(calibration_file) diff --git a/src/py123d/conversion/datasets/av2/utils/av2_helper.py b/src/py123d/conversion/datasets/av2/utils/av2_helper.py index a2937778..0cfb7f15 100644 --- a/src/py123d/conversion/datasets/av2/utils/av2_helper.py +++ b/src/py123d/conversion/datasets/av2/utils/av2_helper.py @@ -17,7 +17,7 @@ def get_dataframe_from_file(file_path: Path) -> pd.DataFrame: return pq.read_table(file_path) elif file_path.suffix == ".feather": - import pyarrow.feather as feather + from pyarrow import feather return feather.read_feather(file_path) else: diff --git a/src/py123d/conversion/datasets/kitti360/kitti360_converter.py b/src/py123d/conversion/datasets/kitti360/kitti360_converter.py index 2f4a0ea4..0485160f 100644 --- a/src/py123d/conversion/datasets/kitti360/kitti360_converter.py +++ b/src/py123d/conversion/datasets/kitti360/kitti360_converter.py @@ -352,7 +352,6 @@ def _get_kitti360_fisheye_mei_camera_metadata( fisheye_cam_metadatas: Dict[FisheyeMEICameraType, FisheyeMEICameraMetadata] = {} if dataset_converter_config.include_fisheye_mei_cameras: - fisheye_camera02_path = kitti360_folders[DIR_CALIB] / "image_02.yaml" fisheye_camera03_path = kitti360_folders[DIR_CALIB] / "image_03.yaml" @@ -362,7 +361,6 @@ def _get_kitti360_fisheye_mei_camera_metadata( fisheye_result = {"image_02": fisheye02, "image_03": fisheye03} for fcam_type, fcam_name in KITTI360_FISHEYE_MEI_CAMERA_TYPES.items(): - distortion_params = fisheye_result[fcam_name]["distortion_parameters"] distortion = FisheyeMEIDistortion( k1=distortion_params["k1"], diff --git a/src/py123d/conversion/datasets/kitti360/kitti360_map_conversion.py b/src/py123d/conversion/datasets/kitti360/kitti360_map_conversion.py index ab7012f9..29f91431 100644 --- a/src/py123d/conversion/datasets/kitti360/kitti360_map_conversion.py +++ b/src/py123d/conversion/datasets/kitti360/kitti360_map_conversion.py @@ -6,13 +6,17 @@ import numpy as np import shapely.geometry as geom -from py123d.conversion.datasets.kitti360.utils.kitti360_helper import KITTI360_MAP_Bbox3D +from py123d.conversion.datasets.kitti360.utils.kitti360_helper import ( + KITTI360_MAP_Bbox3D, +) from py123d.conversion.map_writer.abstract_map_writer import AbstractMapWriter from py123d.conversion.utils.map_utils.road_edge.road_edge_2d_utils import ( get_road_edge_linear_rings, split_line_geometry_by_max_length, ) -from py123d.conversion.utils.map_utils.road_edge.road_edge_3d_utils import lift_road_edges_to_3d +from py123d.conversion.utils.map_utils.road_edge.road_edge_3d_utils import ( + lift_road_edges_to_3d, +) from py123d.datatypes.map_objects.map_layer_types import RoadEdgeType from py123d.datatypes.map_objects.map_objects import ( Carpark, diff --git a/src/py123d/conversion/datasets/kitti360/utils/kitti360_helper.py b/src/py123d/conversion/datasets/kitti360/utils/kitti360_helper.py index 89cfcd1a..beb66b1d 100644 --- a/src/py123d/conversion/datasets/kitti360/utils/kitti360_helper.py +++ b/src/py123d/conversion/datasets/kitti360/utils/kitti360_helper.py @@ -42,14 +42,12 @@ def global2local(globalId: int) -> Tuple[int, int]: class KITTI360Bbox3D: - # global id(only used for sequence 0004) dynamic_global_id = 2000000 static_global_id = 1000000 # Constructor def __init__(self): - # the ID of the corresponding object self.semanticId = -1 self.instanceId = -1 diff --git a/src/py123d/conversion/datasets/nuplan/nuplan_converter.py b/src/py123d/conversion/datasets/nuplan/nuplan_converter.py index 5a589e7d..70259bd1 100644 --- a/src/py123d/conversion/datasets/nuplan/nuplan_converter.py +++ b/src/py123d/conversion/datasets/nuplan/nuplan_converter.py @@ -203,7 +203,6 @@ def convert_log(self, log_index: int, log_writer: AbstractLogWriter) -> None: if log_needs_writing: step_interval: float = int(TARGET_DT / NUPLAN_DEFAULT_DT) for nuplan_lidar_pc in nuplan_log_db.lidar_pc[::step_interval]: - lidar_pc_token: str = nuplan_lidar_pc.token log_writer.write( timestamp=TimePoint.from_us(nuplan_lidar_pc.timestamp), @@ -380,7 +379,6 @@ def _extract_nuplan_cameras( image = image_class[0] filename_jpg = nuplan_sensor_root / image.filename_jpg if filename_jpg.exists() and filename_jpg.is_file(): - # NOTE: This part of the modified from the MTGS code # In MTGS, a slower method is used to find the nearest ego pose. # The code below uses a direct SQL query to find the nearest ego pose, in a given window. diff --git a/src/py123d/conversion/datasets/nuplan/nuplan_map_conversion.py b/src/py123d/conversion/datasets/nuplan/nuplan_map_conversion.py index d72f081a..a27f42dc 100644 --- a/src/py123d/conversion/datasets/nuplan/nuplan_map_conversion.py +++ b/src/py123d/conversion/datasets/nuplan/nuplan_map_conversion.py @@ -68,7 +68,6 @@ def _write_nuplan_lanes(nuplan_gdf: Dict[str, gpd.GeoDataFrame], map_writer: Abs all_geometries = nuplan_gdf["lanes_polygons"].geometry.to_list() for idx, lane_id in enumerate(all_ids): - # 1. predecessor_ids, successor_ids predecessor_ids = get_all_rows_with_value( nuplan_gdf["lane_connectors"], @@ -135,7 +134,6 @@ def _write_nuplan_lane_connectors(nuplan_gdf: Dict[str, gpd.GeoDataFrame], map_w all_speed_limits_mps = nuplan_gdf["lane_connectors"].speed_limit_mps.to_list() for idx, lane_id in enumerate(all_ids): - # 1. predecessor_ids, successor_ids lane_connector_row = get_row_with_value(nuplan_gdf["lane_connectors"], "fid", str(lane_id)) predecessor_ids = [lane_connector_row["entry_lane_fid"]] @@ -186,7 +184,6 @@ def _write_nuplan_lane_groups(nuplan_gdf: Dict[str, gpd.GeoDataFrame], map_write # all_geometries = nuplan_gdf["lane_groups_polygons"].geometry.to_list() for lane_group_id in ids: - # 1. lane_ids lane_ids = get_all_rows_with_value( nuplan_gdf["lanes_polygons"], @@ -244,7 +241,6 @@ def _write_nuplan_lane_connector_groups(nuplan_gdf: Dict[str, gpd.GeoDataFrame], # all_geometries = nuplan_gdf["lane_group_connectors"].geometry.to_list() for idx, lane_group_connector_id in enumerate(ids): - # 1. lane_ids lane_ids = get_all_rows_with_value( nuplan_gdf["lane_connectors"], "lane_group_connector_fid", lane_group_connector_id diff --git a/src/py123d/conversion/datasets/nuscenes/nuscenes_map_conversion.py b/src/py123d/conversion/datasets/nuscenes/nuscenes_map_conversion.py index 8a0cb348..ce17b87a 100644 --- a/src/py123d/conversion/datasets/nuscenes/nuscenes_map_conversion.py +++ b/src/py123d/conversion/datasets/nuscenes/nuscenes_map_conversion.py @@ -221,7 +221,6 @@ def _extract_nuscenes_lane_groups( lane_group_lane_dict[lane.lane_group_id].append(lane.object_id) for lane_group_id, lane_ids in lane_group_lane_dict.items(): - if len(lane_ids) > 1: lane_centerlines: List[Polyline2D] = [lanes_dict[lane_id].centerline for lane_id in lane_ids] ordered_lane_indices = order_lanes_left_to_right(lane_centerlines) diff --git a/src/py123d/conversion/datasets/nuscenes/utils/nuscenes_map_utils.py b/src/py123d/conversion/datasets/nuscenes/utils/nuscenes_map_utils.py index a512dc18..4d229d68 100644 --- a/src/py123d/conversion/datasets/nuscenes/utils/nuscenes_map_utils.py +++ b/src/py123d/conversion/datasets/nuscenes/utils/nuscenes_map_utils.py @@ -158,7 +158,6 @@ def order_lanes_left_to_right(polylines: List[Polyline2D]) -> List[int]: # Step 1: Compute the average direction vector across all lanes all_directions = [] for polyline in polylines: - polyline_array = polyline.array if len(polyline_array) < 2: continue diff --git a/src/py123d/conversion/datasets/pandaset/pandaset_converter.py b/src/py123d/conversion/datasets/pandaset/pandaset_converter.py index d46ce762..be374d65 100644 --- a/src/py123d/conversion/datasets/pandaset/pandaset_converter.py +++ b/src/py123d/conversion/datasets/pandaset/pandaset_converter.py @@ -132,7 +132,6 @@ def convert_log(self, log_index: int, log_writer: AbstractLogWriter) -> None: # 3. Process source log data if log_needs_writing: - # Read files from pandaset timesteps = read_json(source_log_path / "meta" / "timestamps.json") gps: List[Dict[str, float]] = read_json(source_log_path / "meta" / "gps.json") @@ -144,7 +143,6 @@ def convert_log(self, log_index: int, log_writer: AbstractLogWriter) -> None: # Write data to log writer for iteration, timestep_s in enumerate(timesteps): - ego_state = _extract_pandaset_sensor_ego_state(gps[iteration], lidar_poses[iteration]) log_writer.write( timestamp=TimePoint.from_s(timestep_s), @@ -177,7 +175,6 @@ def _get_pandaset_camera_metadata( if dataset_config.include_pinhole_cameras: all_cameras_folder = source_log_path / "camera" for camera_folder in all_cameras_folder.iterdir(): - camera_name = camera_folder.name assert camera_name in PANDASET_CAMERA_MAPPING.keys(), f"Camera name {camera_name} is not recognized." @@ -297,7 +294,6 @@ def _extract_pandaset_box_detections(source_log_path: Path, iteration: int) -> B # Fill bounding box detections and return box_detections: List[BoxDetectionSE3] = [] for box_idx in range(num_boxes): - # Skip duplicate box detections from front lidar if sibling exists in top lidar if sensor_ids[box_idx] == 1 and sibling_ids[box_idx] in top_lidar_uuids: continue @@ -335,9 +331,7 @@ def _extract_pandaset_sensor_camera( iteration_str = f"{iteration:02d}" if dataset_converter_config.include_pinhole_cameras: - for camera_name, camera_type in PANDASET_CAMERA_MAPPING.items(): - image_abs_path = source_log_path / f"camera/{camera_name}/{iteration_str}.jpg" assert image_abs_path.exists(), f"Camera image file {str(image_abs_path)} does not exist." diff --git a/src/py123d/conversion/datasets/pandaset/utils/pandaset_utlis.py b/src/py123d/conversion/datasets/pandaset/utils/pandaset_utlis.py index ba0bfd36..4b34d159 100644 --- a/src/py123d/conversion/datasets/pandaset/utils/pandaset_utlis.py +++ b/src/py123d/conversion/datasets/pandaset/utils/pandaset_utlis.py @@ -66,7 +66,6 @@ def rotate_pandaset_pose_to_iso_coordinates(pose: PoseSE3) -> PoseSE3: def main_lidar_to_rear_axle(pose: PoseSE3) -> PoseSE3: - F = np.array( [ [0.0, 1.0, 0.0], # new X = old Y (forward) diff --git a/src/py123d/conversion/datasets/wopd/utils/womp_boundary_utils.py b/src/py123d/conversion/datasets/wopd/utils/womp_boundary_utils.py index a920ae0b..5c9b7a8c 100644 --- a/src/py123d/conversion/datasets/wopd/utils/womp_boundary_utils.py +++ b/src/py123d/conversion/datasets/wopd/utils/womp_boundary_utils.py @@ -147,10 +147,8 @@ def _filter_perpendicular_hits( perpendicular_hits: List[PerpendicularHit], lane_point_3d: Point3D, ) -> List[PerpendicularHit]: - filtered_hits = [] for hit in perpendicular_hits: - # 1. filter hits too far in the vertical direction z_distance = np.abs(hit.hit_point_3d.z - lane_point_3d.z) if z_distance > MAX_Z_DISTANCE: @@ -226,7 +224,6 @@ def fill_lane_boundaries( for sign in [1.0, -1.0]: boundary_points_3d: List[Optional[Point3D]] = [] for lane_query_se2, lane_query_3d in zip(lane_queries_se2, lane_queries_3d): - perpendicular_hits = _collect_perpendicular_hits( lane_query_se2=lane_query_se2, lane_token=current_lane_token, @@ -250,12 +247,10 @@ def fill_lane_boundaries( elif first_hit.hit_polyline_type == "road-line": boundary_point_3d = first_hit.hit_point_3d elif first_hit.hit_polyline_type == "lane": - for hit in perpendicular_hits: if hit.hit_polyline_type == "road-edge": continue if hit.hit_polyline_type == "lane": - lane_data_dict[lane_id].predecessor_ids has_same_predecessor = ( diff --git a/src/py123d/conversion/datasets/wopd/wopd_converter.py b/src/py123d/conversion/datasets/wopd/wopd_converter.py index 2cff87ed..453a8c82 100644 --- a/src/py123d/conversion/datasets/wopd/wopd_converter.py +++ b/src/py123d/conversion/datasets/wopd/wopd_converter.py @@ -277,7 +277,6 @@ def _get_wopd_lidar_metadata( lidar_index = WOPDLiDARIndex if keep_polar_features else DefaultLiDARIndex if dataset_converter_config.lidar_store_option is not None: for laser_calibration in initial_frame.context.laser_calibrations: - lidar_type = WOPD_LIDAR_TYPES[laser_calibration.name] extrinsic: Optional[PoseSE3] = None if laser_calibration.extrinsic: @@ -332,7 +331,6 @@ def _extract_wopd_box_detections( detections_token: List[str] = [] for detection_idx, detection in enumerate(frame.laser_labels): - detection_quaternion = EulerAngles( roll=DEFAULT_ROLL, pitch=DEFAULT_PITCH, @@ -392,7 +390,6 @@ def _extract_wopd_cameras( camera_data_list: List[CameraData] = [] if dataset_converter_config.include_pinhole_cameras: - # NOTE @DanielDauner: The extrinsic matrix in frame.context.camera_calibration is fixed to model the ego to camera transformation. # The poses in frame.images[idx] are the motion compensated ego poses when the camera triggers. camera_extrinsic: Dict[str, PoseSE3] = {} diff --git a/src/py123d/conversion/datasets/wopd/wopd_map_conversion.py b/src/py123d/conversion/datasets/wopd/wopd_map_conversion.py index 6287c2e7..c7301428 100644 --- a/src/py123d/conversion/datasets/wopd/wopd_map_conversion.py +++ b/src/py123d/conversion/datasets/wopd/wopd_map_conversion.py @@ -26,7 +26,6 @@ def convert_wopd_map(frame: dataset_pb2.Frame, map_writer: AbstractMapWriter) -> None: - # We first extract all road lines, road edges, and lanes, and write them to the map writer. # NOTE: road lines and edges are used needed to extract lane boundaries. road_lines = _write_and_get_waymo_road_lines(frame, map_writer) @@ -89,7 +88,6 @@ def _write_and_get_waymo_road_edges(frame: dataset_pb2.Frame, map_writer: Abstra def _write_and_get_waymo_lanes( frame: dataset_pb2.Frame, road_lines: List[RoadLine], road_edges: List[RoadEdge], map_writer: AbstractMapWriter ) -> List[Lane]: - # 1. Load lane data from Waymo frame proto lane_data_dict: Dict[int, WaymoLaneData] = {} for map_feature in frame.map_features: @@ -127,7 +125,6 @@ def _get_majority_neighbor(neighbors: List[Dict[str, int]]) -> Optional[int]: lanes: List[Lane] = [] for lane_data in lane_data_dict.values(): - # Skip lanes without boundaries if lane_data.left_boundary is None or lane_data.right_boundary is None: continue @@ -154,7 +151,6 @@ def _get_majority_neighbor(neighbors: List[Dict[str, int]]) -> Optional[int]: def _write_waymo_lane_groups(lanes: List[Lane], map_writer: AbstractMapWriter) -> None: - # NOTE: WOPD does not provide lane groups, so we create a lane group for each lane. for lane in lanes: map_writer.write_lane_group( @@ -172,7 +168,6 @@ def _write_waymo_lane_groups(lanes: List[Lane], map_writer: AbstractMapWriter) - def _write_waymo_misc_surfaces(frame: dataset_pb2.Frame, map_writer: AbstractMapWriter) -> None: - for map_feature in frame.map_features: if map_feature.HasField("driveway"): # NOTE: We currently only handle classify driveways as carparks. diff --git a/src/py123d/conversion/log_writer/arrow_log_writer.py b/src/py123d/conversion/log_writer/arrow_log_writer.py index 8a7a3b29..324aad69 100644 --- a/src/py123d/conversion/log_writer/arrow_log_writer.py +++ b/src/py123d/conversion/log_writer/arrow_log_writer.py @@ -54,21 +54,21 @@ def _get_logs_root() -> Path: - from py123d.script.utils.dataset_path_utils import get_dataset_paths + from py123d.script.utils.dataset_path_utils import get_dataset_paths # noqa: PLC0415 DATASET_PATHS = get_dataset_paths() return Path(DATASET_PATHS.py123d_logs_root) def _get_sensors_root() -> Path: - from py123d.script.utils.dataset_path_utils import get_dataset_paths + from py123d.script.utils.dataset_path_utils import get_dataset_paths # noqa: PLC0415 DATASET_PATHS = get_dataset_paths() return Path(DATASET_PATHS.py123d_sensors_root) def _store_option_to_arrow_type( - store_option: Literal["path", "jpeg_binary", "png_binary", "laz_binary"], + store_option: Literal["path", "jpeg_binary", "png_binary", "laz_binary", "draco_binary", "mp4"], ) -> pa.DataType: """Maps the store option literal to the corresponding Arrow data type.""" data_type_map = { diff --git a/src/py123d/conversion/sensor_io/camera/mp4_camera_io.py b/src/py123d/conversion/sensor_io/camera/mp4_camera_io.py index 5c156cdf..bf6941e8 100644 --- a/src/py123d/conversion/sensor_io/camera/mp4_camera_io.py +++ b/src/py123d/conversion/sensor_io/camera/mp4_camera_io.py @@ -1,8 +1,3 @@ -# TODO: add method of handling camera mp4 io -def load_image_from_mp4_file() -> None: - raise NotImplementedError - - from functools import lru_cache from pathlib import Path from typing import Optional, Union diff --git a/src/py123d/conversion/utils/map_utils/opendrive/opendrive_map_conversion.py b/src/py123d/conversion/utils/map_utils/opendrive/opendrive_map_conversion.py index 5449ba9e..1ce4defb 100644 --- a/src/py123d/conversion/utils/map_utils/opendrive/opendrive_map_conversion.py +++ b/src/py123d/conversion/utils/map_utils/opendrive/opendrive_map_conversion.py @@ -193,7 +193,6 @@ def _write_intersections( lane_group_helper_dict: Dict[str, OpenDriveLaneGroupHelper], map_writer: AbstractMapWriter, ) -> None: - def _find_lane_group_helpers_with_junction_id(junction_id: int) -> List[OpenDriveLaneGroupHelper]: return [ lane_group_helper @@ -230,7 +229,6 @@ def _write_crosswalks(object_helper_dict: Dict[int, OpenDriveObjectHelper], map_ def _write_road_lines(lanes: List[Lane], lane_groups: List[LaneGroup], map_writer: AbstractMapWriter) -> None: - # NOTE @DanielDauner: This method of extracting road lines is very simplistic and needs improvement. # The OpenDRIVE format provides lane boundary types that could be used here. # Additionally, the logic of inferring road lines is somewhat flawed, e.g, assuming constant types/colors of lines. @@ -245,7 +243,6 @@ def _write_road_lines(lanes: List[Lane], lane_groups: List[LaneGroup], map_write running_id = 0 for lane in lanes: - on_intersection = lane_group_on_intersection.get(lane.lane_group_id, False) if on_intersection: # Skip road lines on intersections @@ -281,7 +278,6 @@ def _write_road_edges( generic_drivables: List[GenericDrivable], map_writer: AbstractMapWriter, ) -> None: - road_edges_ = get_road_edges_3d_from_drivable_surfaces( lanes=lanes, lane_groups=lane_groups, diff --git a/src/py123d/conversion/utils/map_utils/opendrive/parser/geometry.py b/src/py123d/conversion/utils/map_utils/opendrive/parser/geometry.py index d5374d00..bc8ed734 100644 --- a/src/py123d/conversion/utils/map_utils/opendrive/parser/geometry.py +++ b/src/py123d/conversion/utils/map_utils/opendrive/parser/geometry.py @@ -47,7 +47,6 @@ def parse(cls, geometry_element: Element) -> XODRGeometry: return cls(**args) def interpolate_se2(self, s: float, t: float = 0.0) -> npt.NDArray[np.float64]: - interpolated_se2 = self.start_se2.copy() interpolated_se2[PoseSE2Index.X] += s * np.cos(self.hdg) interpolated_se2[PoseSE2Index.Y] += s * np.sin(self.hdg) @@ -78,7 +77,6 @@ def parse(cls, geometry_element: Element) -> XODRGeometry: return cls(**args) def interpolate_se2(self, s: float, t: float = 0.0) -> npt.NDArray[np.float64]: - kappa = self.curvature radius = 1.0 / kappa if kappa != 0 else float("inf") @@ -142,7 +140,6 @@ def interpolate_se2(self, s: float, t: float = 0.0) -> npt.NDArray[np.float64]: return interpolated_se2 def _compute_spiral_position(self, s: float, gamma: float) -> Tuple[float, float]: - # Transform to normalized Fresnel spiral parameter # Standard Fresnel spiral has κ(u) = u, so we need to scale # Our spiral: κ(s) = κ₀ + γs diff --git a/src/py123d/conversion/utils/map_utils/opendrive/parser/objects.py b/src/py123d/conversion/utils/map_utils/opendrive/parser/objects.py index 8c1b17af..bd844895 100644 --- a/src/py123d/conversion/utils/map_utils/opendrive/parser/objects.py +++ b/src/py123d/conversion/utils/map_utils/opendrive/parser/objects.py @@ -32,7 +32,6 @@ def __post_init__(self): @classmethod def parse(cls, object_element: Optional[Element]) -> XODRObject: - args = {} args["id"] = int(object_element.get("id")) args["name"] = object_element.get("name") diff --git a/src/py123d/conversion/utils/map_utils/opendrive/parser/opendrive.py b/src/py123d/conversion/utils/map_utils/opendrive/parser/opendrive.py index 3dfac7f1..7ee2fce9 100644 --- a/src/py123d/conversion/utils/map_utils/opendrive/parser/opendrive.py +++ b/src/py123d/conversion/utils/map_utils/opendrive/parser/opendrive.py @@ -23,7 +23,6 @@ class XODR: @classmethod def parse(cls, root_element: Element) -> XODR: - args = {} args["header"] = Header.parse(root_element.find("header")) @@ -111,7 +110,6 @@ class Controller: @classmethod def parse(cls, controller_element: Optional[Element]) -> Junction: - args = {} args["name"] = controller_element.get("name") args["id"] = float(controller_element.get("id")) diff --git a/src/py123d/conversion/utils/map_utils/opendrive/parser/reference.py b/src/py123d/conversion/utils/map_utils/opendrive/parser/reference.py index b94a7af0..236ba5a0 100644 --- a/src/py123d/conversion/utils/map_utils/opendrive/parser/reference.py +++ b/src/py123d/conversion/utils/map_utils/opendrive/parser/reference.py @@ -20,7 +20,6 @@ @dataclass class XODRPlanView: - geometries: List[XODRGeometry] def __post_init__(self): @@ -72,7 +71,6 @@ def interpolate_se2(self, s: float, t: float = 0.0, lane_section_end: bool = Fal @dataclass class XODRReferenceLine: - reference_line: Union[XODRReferenceLine, XODRPlanView] width_polynomials: List[XODRPolynomial] elevations: List[XODRElevation] @@ -119,17 +117,15 @@ def from_reference_line( @staticmethod def _find_polynomial(s: float, polynomials: List[XODRPolynomial], lane_section_end: bool = False) -> XODRPolynomial: - out_polynomial = polynomials[-1] for polynomial in polynomials[::-1]: if lane_section_end: if polynomial.s < s: out_polynomial = polynomial break - else: - if polynomial.s <= s: - out_polynomial = polynomial - break + elif polynomial.s <= s: + out_polynomial = polynomial + break # s_values = np.array([poly.s for poly in polynomials]) # side = "left" if lane_section_end else "right" @@ -139,7 +135,6 @@ def _find_polynomial(s: float, polynomials: List[XODRPolynomial], lane_section_e return out_polynomial def interpolate_se2(self, s: float, t: float = 0.0, lane_section_end: bool = False) -> npt.NDArray[np.float64]: - width_polynomial = self._find_polynomial(s, self.width_polynomials, lane_section_end=lane_section_end) t_offset = width_polynomial.get_value(s - width_polynomial.s) se2 = self.reference_line.interpolate_se2(self.s_offset + s, t=t_offset + t, lane_section_end=lane_section_end) @@ -147,7 +142,6 @@ def interpolate_se2(self, s: float, t: float = 0.0, lane_section_end: bool = Fal return se2 def interpolate_3d(self, s: float, t: float = 0.0, lane_section_end: bool = False) -> npt.NDArray[np.float64]: - se2 = self.interpolate_se2(s, t, lane_section_end=lane_section_end) elevation_polynomial = self._find_polynomial(s, self.elevations, lane_section_end=lane_section_end) diff --git a/src/py123d/conversion/utils/map_utils/opendrive/utils/collection.py b/src/py123d/conversion/utils/map_utils/opendrive/utils/collection.py index 7a4368c5..32090d2b 100644 --- a/src/py123d/conversion/utils/map_utils/opendrive/utils/collection.py +++ b/src/py123d/conversion/utils/map_utils/opendrive/utils/collection.py @@ -33,7 +33,6 @@ def collect_element_helpers( Dict[str, OpenDriveLaneGroupHelper], Dict[int, OpenDriveObjectHelper], ]: - # 1. Fill the road and junction dictionaries road_dict: Dict[int, XODRRoad] = {road.id: road for road in opendrive.roads} junction_dict: Dict[int, Junction] = {junction.id: junction for junction in opendrive.junctions} @@ -182,7 +181,6 @@ def _update_connection_from_junctions( connecting_road = road_dict[connection.connecting_road] for lane_link in connection.lane_links: - incoming_lane_id: Optional[str] = None connecting_lane_id: Optional[str] = None @@ -247,7 +245,6 @@ def _post_process_connections( successor_centerline = lane_helper_dict[successor_lane_id].center_polyline_se2 distance = np.linalg.norm(centerline[-1, :2] - successor_centerline[0, :2]) if distance > connection_distance_threshold: - logger.debug( f"OpenDRIVE: Removing connection {lane_id} -> {successor_lane_id} with distance {distance}" ) @@ -273,7 +270,6 @@ def _collect_lane_groups( junction_dict: Dict[int, Junction], road_dict: Dict[int, XODRRoad], ) -> None: - lane_group_helper_dict: Dict[str, OpenDriveLaneGroupHelper] = {} def _collect_lane_helper_of_id(lane_group_id: str) -> List[OpenDriveLaneHelper]: @@ -309,7 +305,6 @@ def _collect_lane_group_ids_of_road(road_id: int) -> List[str]: def _collect_crosswalks(opendrive: XODR) -> Dict[int, OpenDriveObjectHelper]: - object_helper_dict: Dict[int, OpenDriveObjectHelper] = {} for road in opendrive.roads: if len(road.objects) == 0: diff --git a/src/py123d/conversion/utils/map_utils/opendrive/utils/lane_helper.py b/src/py123d/conversion/utils/map_utils/opendrive/utils/lane_helper.py index 27098773..e7083a98 100644 --- a/src/py123d/conversion/utils/map_utils/opendrive/utils/lane_helper.py +++ b/src/py123d/conversion/utils/map_utils/opendrive/utils/lane_helper.py @@ -21,7 +21,6 @@ @dataclass class OpenDriveLaneHelper: - lane_id: str open_drive_lane: XODRLane s_inner_offset: float @@ -172,7 +171,6 @@ def shapely_polygon(self) -> shapely.Polygon: @dataclass class OpenDriveLaneGroupHelper: - lane_group_id: str lane_helpers: List[OpenDriveLaneHelper] @@ -182,7 +180,6 @@ class OpenDriveLaneGroupHelper: junction_id: Optional[int] = None def __post_init__(self): - predecessor_lane_group_ids = [] successor_lane_group__ids = [] for lane_helper in self.lane_helpers: @@ -262,7 +259,6 @@ def lane_section_to_lane_helpers( road_types: List[XODRRoadType], interpolation_step_size: float, ) -> Dict[str, OpenDriveLaneHelper]: - lane_helpers: Dict[str, OpenDriveLaneHelper] = {} for lanes, t_sign, side in zip([lane_section.left_lanes, lane_section.right_lanes], [1.0, -1.0], ["left", "right"]): @@ -295,7 +291,6 @@ def lane_section_to_lane_helpers( def _get_speed_limit_mps(s: float, road_types: List[XODRRoadType]) -> Optional[float]: - # NOTE: Likely not correct way to extract speed limit from CARLA maps, but serves as a placeholder speed_limit_mps: Optional[float] = None s_road_types = [road_type.s for road_type in road_types] + [float("inf")] diff --git a/src/py123d/conversion/utils/map_utils/opendrive/utils/objects_helper.py b/src/py123d/conversion/utils/map_utils/opendrive/utils/objects_helper.py index 97033812..899a7491 100644 --- a/src/py123d/conversion/utils/map_utils/opendrive/utils/objects_helper.py +++ b/src/py123d/conversion/utils/map_utils/opendrive/utils/objects_helper.py @@ -16,7 +16,6 @@ @dataclass class OpenDriveObjectHelper: - object_id: int outline_3d: npt.NDArray[np.float64] @@ -34,7 +33,6 @@ def shapely_polygon(self) -> shapely.Polygon: def get_object_helper(object: XODRObject, reference_line: XODRReferenceLine) -> OpenDriveObjectHelper: - object_helper: Optional[OpenDriveObjectHelper] = None # 1. Extract object position in frenet frame of the reference line diff --git a/src/py123d/conversion/utils/map_utils/road_edge/road_edge_3d_utils.py b/src/py123d/conversion/utils/map_utils/road_edge/road_edge_3d_utils.py index f777dff4..3852149d 100644 --- a/src/py123d/conversion/utils/map_utils/road_edge/road_edge_3d_utils.py +++ b/src/py123d/conversion/utils/map_utils/road_edge/road_edge_3d_utils.py @@ -162,7 +162,6 @@ def lift_road_edges_to_3d( road_edges_3d: List[Polyline3D] = [] if len(road_edges_2d) >= 1 and len(boundaries) >= 1: - # 1. Build comprehensive spatial index with all boundary segments # NOTE @DanielDauner: We split each boundary polyline into small segments. # The spatial indexing uses axis-aligned bounding boxes, where small geometries lead to better performance. @@ -275,7 +274,6 @@ def _resolve_conflicting_lane_groups( road_edges_3d: List[Polyline3D] = [] for non_conflicting_set in non_conflicting_sets: - # Collect 2D polygons of non-conflicting lane group set and their neighbors merge_lane_group_data: Dict[MapObjectIDType, geom.Polygon] = {} for lane_group_id in non_conflicting_set: diff --git a/src/py123d/datatypes/map_objects/base_map_objects.py b/src/py123d/datatypes/map_objects/base_map_objects.py index 72ac5fb9..f1d70d7b 100644 --- a/src/py123d/datatypes/map_objects/base_map_objects.py +++ b/src/py123d/datatypes/map_objects/base_map_objects.py @@ -1,11 +1,12 @@ from __future__ import annotations import abc -from typing import Optional, TypeAlias, Union +from typing import Optional, Union import numpy as np import shapely.geometry as geom import trimesh +from typing_extensions import TypeAlias from py123d.datatypes.map_objects.map_layer_types import MapLayer from py123d.geometry import Point3DIndex, Polyline2D, Polyline3D diff --git a/src/py123d/datatypes/map_objects/map_objects.py b/src/py123d/datatypes/map_objects/map_objects.py index f722a985..60298905 100644 --- a/src/py123d/datatypes/map_objects/map_objects.py +++ b/src/py123d/datatypes/map_objects/map_objects.py @@ -436,7 +436,6 @@ def layer(self) -> MapLayer: class Walkway(BaseMapSurfaceObject): - __slots__ = () def __init__( diff --git a/src/py123d/datatypes/map_objects/utils.py b/src/py123d/datatypes/map_objects/utils.py index 88eb47b5..7d5557d1 100644 --- a/src/py123d/datatypes/map_objects/utils.py +++ b/src/py123d/datatypes/map_objects/utils.py @@ -18,8 +18,7 @@ def get_trimesh_from_boundaries( def _interpolate_polyline(polyline_3d: Polyline3D, num_samples: int) -> npt.NDArray[np.float64]: """Helper function to interpolate a polyline to a fixed number of samples.""" - if num_samples < 2: - num_samples = 2 + num_samples = max(num_samples, 2) distances = np.linspace(0, polyline_3d.length, num=num_samples, endpoint=True, dtype=np.float64) return polyline_3d.interpolate(distances) diff --git a/src/py123d/datatypes/sensors/fisheye_mei_camera.py b/src/py123d/datatypes/sensors/fisheye_mei_camera.py index 808304ea..ffbeccf4 100644 --- a/src/py123d/datatypes/sensors/fisheye_mei_camera.py +++ b/src/py123d/datatypes/sensors/fisheye_mei_camera.py @@ -1,11 +1,11 @@ from __future__ import annotations from dataclasses import dataclass +from enum import IntEnum from typing import Any, Dict, Optional import numpy as np import numpy.typing as npt -from zmq import IntEnum from py123d.common.utils.enums import SerialIntEnum from py123d.common.utils.mixin import ArrayMixin @@ -76,7 +76,6 @@ class FisheyeMEIDistortionIndex(IntEnum): class FisheyeMEIDistortion(ArrayMixin): - __slots__ = ("_array",) _array: npt.NDArray[np.float64] diff --git a/src/py123d/datatypes/time/time_point.py b/src/py123d/datatypes/time/time_point.py index 1564fe95..be927d8e 100644 --- a/src/py123d/datatypes/time/time_point.py +++ b/src/py123d/datatypes/time/time_point.py @@ -4,7 +4,7 @@ class TimePoint: """Time instance in a time series.""" - __slots__ = "_time_us" + __slots__ = ("_time_us",) _time_us: int # [micro seconds] time since epoch in micro seconds @classmethod diff --git a/src/py123d/datatypes/vehicle_state/ego_state.py b/src/py123d/datatypes/vehicle_state/ego_state.py index c25013a5..c6afc059 100644 --- a/src/py123d/datatypes/vehicle_state/ego_state.py +++ b/src/py123d/datatypes/vehicle_state/ego_state.py @@ -106,11 +106,6 @@ def from_rear_axle( tire_steering_angle=tire_steering_angle, ) - @property - def rear_axle(self) -> PoseSE3: - """The :class:`~py123d.geometry.PoseSE3` of the rear axle in SE3.""" - return self._rear_axle_se3 - @property def rear_axle_se3(self) -> PoseSE3: """The :class:`~py123d.geometry.PoseSE3` of the rear axle in SE3.""" @@ -159,11 +154,6 @@ def center_se2(self) -> PoseSE2: """The :class:`~py123d.geometry.PoseSE2` of the vehicle center in SE2.""" return self.center_se3.pose_se2 - @property - def bounding_box(self) -> BoundingBoxSE3: - """The :class:`~py123d.geometry.BoundingBoxSE3` of the ego vehicle.""" - return self.bounding_box_se3 - @property def bounding_box_se3(self) -> BoundingBoxSE3: """The :class:`~py123d.geometry.BoundingBoxSE3` of the ego vehicle.""" @@ -177,7 +167,7 @@ def bounding_box_se3(self) -> BoundingBoxSE3: @property def bounding_box_se2(self) -> BoundingBoxSE2: """The :class:`~py123d.geometry.BoundingBoxSE2` of the ego vehicle.""" - return self.bounding_box.bounding_box_se2 + return self.bounding_box_se3.bounding_box_se2 @property def box_detection(self) -> BoxDetectionSE3: @@ -194,7 +184,7 @@ def box_detection_se3(self) -> BoxDetectionSE3: track_token=EGO_TRACK_TOKEN, num_lidar_points=None, ), - bounding_box_se3=self.bounding_box, + bounding_box_se3=self.bounding_box_se3, velocity=self.dynamic_state_se3.velocity, ) diff --git a/src/py123d/geometry/occupancy_map.py b/src/py123d/geometry/occupancy_map.py index a92a888c..8ee6ed32 100644 --- a/src/py123d/geometry/occupancy_map.py +++ b/src/py123d/geometry/occupancy_map.py @@ -108,6 +108,7 @@ def query( Literal[ "intersects", "within", + "dwithin", "contains", "overlaps", "crosses", diff --git a/src/py123d/geometry/polyline.py b/src/py123d/geometry/polyline.py index a165a71e..90974f5e 100644 --- a/src/py123d/geometry/polyline.py +++ b/src/py123d/geometry/polyline.py @@ -42,7 +42,7 @@ def from_linestring(cls, linestring: geom.LineString) -> Polyline2D: :return: A Polyline2D instance. """ if linestring.has_z: - linestring_ = geom_creation.linestrings(*linestring.xy) + linestring_ = geom_creation.linestrings(*linestring.xy) # pyright: ignore[reportUnknownMemberType] else: linestring_ = linestring @@ -51,7 +51,7 @@ def from_linestring(cls, linestring: geom.LineString) -> Polyline2D: return instance @classmethod - def from_array(cls, polyline_array: npt.NDArray[np.float32]) -> Polyline2D: + def from_array(cls, array: npt.NDArray[np.float64], copy: bool = True) -> Polyline2D: """Creates a :class:`Polyline2D` from a (N, 2) or (N, 3) shaped numpy array. \ Assumes [...,:2] slices are XY coordinates. @@ -60,12 +60,12 @@ def from_array(cls, polyline_array: npt.NDArray[np.float32]) -> Polyline2D: :raises ValueError: If the input array is not of the expected shape. :return: A :class:`Polyline2D` instance. """ - assert polyline_array.ndim == 2 + assert array.ndim == 2 linestring_: Optional[geom.LineString] = None - if polyline_array.shape[-1] == len(Point2DIndex): - linestring_ = geom.LineString(polyline_array) - elif polyline_array.shape[-1] == len(Point3DIndex): - linestring_ = geom.LineString(polyline_array[:, Point3DIndex.XY]) + if array.shape[-1] == len(Point2DIndex): + linestring_ = geom.LineString(array) + elif array.shape[-1] == len(Point3DIndex): + linestring_ = geom.LineString(array[:, Point3DIndex.XY]) # pyright: ignore[reportUnknownMemberType] else: raise ValueError("Array must have shape (N, 2) or (N, 3) for Point2D or Point3D respectively.") diff --git a/src/py123d/geometry/transform/transform_euler_se3.py b/src/py123d/geometry/transform/transform_euler_se3.py index 4454f066..625831a2 100644 --- a/src/py123d/geometry/transform/transform_euler_se3.py +++ b/src/py123d/geometry/transform/transform_euler_se3.py @@ -12,7 +12,6 @@ def translate_euler_se3_along_z(pose_se3: EulerStateSE3, distance: float) -> EulerStateSE3: - R = pose_se3.rotation_matrix z_axis = R[:, 2] @@ -22,7 +21,6 @@ def translate_euler_se3_along_z(pose_se3: EulerStateSE3, distance: float) -> Eul def translate_euler_se3_along_y(pose_se3: EulerStateSE3, distance: float) -> EulerStateSE3: - R = pose_se3.rotation_matrix y_axis = R[:, 1] @@ -32,7 +30,6 @@ def translate_euler_se3_along_y(pose_se3: EulerStateSE3, distance: float) -> Eul def translate_euler_se3_along_x(pose_se3: EulerStateSE3, distance: float) -> EulerStateSE3: - R = pose_se3.rotation_matrix x_axis = R[:, 0] @@ -42,7 +39,6 @@ def translate_euler_se3_along_x(pose_se3: EulerStateSE3, distance: float) -> Eul def translate_euler_se3_along_body_frame(pose_se3: EulerStateSE3, vector_3d: Vector3D) -> EulerStateSE3: - R = pose_se3.rotation_matrix world_translation = R @ vector_3d.array @@ -54,7 +50,6 @@ def translate_euler_se3_along_body_frame(pose_se3: EulerStateSE3, vector_3d: Vec def convert_absolute_to_relative_euler_se3_array( origin: Union[EulerStateSE3, npt.NDArray[np.float64]], se3_array: npt.NDArray[np.float64] ) -> npt.NDArray[np.float64]: - if isinstance(origin, EulerStateSE3): origin_array = origin.array t_origin = origin.point_3d.array @@ -95,7 +90,6 @@ def convert_absolute_to_relative_euler_se3_array( def convert_relative_to_absolute_euler_se3_array( origin: EulerStateSE3, se3_array: npt.NDArray[np.float64] ) -> npt.NDArray[np.float64]: - if isinstance(origin, EulerStateSE3): origin_array = origin.array t_origin = origin.point_3d.array @@ -132,7 +126,6 @@ def convert_relative_to_absolute_euler_se3_array( def convert_absolute_to_relative_points_3d_array( origin: Union[EulerStateSE3, npt.NDArray[np.float64]], points_3d_array: npt.NDArray[np.float64] ) -> npt.NDArray[np.float64]: - if isinstance(origin, EulerStateSE3): t_origin = origin.point_3d.array R_origin = origin.rotation_matrix @@ -154,7 +147,6 @@ def convert_absolute_to_relative_points_3d_array( def convert_relative_to_absolute_points_3d_array( origin: Union[EulerStateSE3, npt.NDArray[np.float64]], points_3d_array: npt.NDArray[np.float64] ) -> npt.NDArray[np.float64]: - if isinstance(origin, EulerStateSE3): origin_array = origin.array elif isinstance(origin, np.ndarray): diff --git a/src/py123d/script/run_conversion.py b/src/py123d/script/run_conversion.py index 52ed5cd6..e1504b4a 100644 --- a/src/py123d/script/run_conversion.py +++ b/src/py123d/script/run_conversion.py @@ -32,7 +32,6 @@ def main(cfg: DictConfig) -> None: dataset_converters: List[AbstractDatasetConverter] = build_dataset_converters(cfg.datasets) for dataset_converter in dataset_converters: - worker = build_worker(cfg) logger.info(f"Processing dataset: {dataset_converter.__class__.__name__}") @@ -55,7 +54,6 @@ def main(cfg: DictConfig) -> None: def _convert_maps(args: List[Dict[str, int]], cfg: DictConfig, dataset_converter: AbstractDatasetConverter) -> List: - map_writer = build_map_writer(cfg.map_writer) for arg in args: dataset_converter.convert_map(arg["map_index"], map_writer) @@ -63,7 +61,6 @@ def _convert_maps(args: List[Dict[str, int]], cfg: DictConfig, dataset_converter def _convert_logs(args: List[Dict[str, int]], cfg: DictConfig, dataset_converter: AbstractDatasetConverter) -> None: - setup_dataset_paths(cfg.dataset_paths) def _internal_convert_log(args: Dict[str, int], dataset_converter_: AbstractDatasetConverter) -> int: diff --git a/src/py123d/script/run_viser.py b/src/py123d/script/run_viser.py index df14382c..0d76b33d 100644 --- a/src/py123d/script/run_viser.py +++ b/src/py123d/script/run_viser.py @@ -18,7 +18,6 @@ @hydra.main(config_path=CONFIG_PATH, config_name=CONFIG_NAME, version_base=None) def main(cfg: DictConfig) -> None: - # Initialize dataset paths setup_dataset_paths(cfg.dataset_paths) diff --git a/src/py123d/script/utils/dataset_path_utils.py b/src/py123d/script/utils/dataset_path_utils.py index 393c05f4..d557246c 100644 --- a/src/py123d/script/utils/dataset_path_utils.py +++ b/src/py123d/script/utils/dataset_path_utils.py @@ -15,7 +15,7 @@ def setup_dataset_paths(cfg: DictConfig) -> None: :return: None """ - global _global_dataset_paths + global _global_dataset_paths # noqa: PLW0603 if _global_dataset_paths is None: # Make it immutable @@ -23,8 +23,6 @@ def setup_dataset_paths(cfg: DictConfig) -> None: OmegaConf.set_readonly(cfg, True) # Prevents any modifications _global_dataset_paths = cfg - return None - def get_dataset_paths() -> DictConfig: """Get the global dataset paths from anywhere in your code. diff --git a/src/py123d/visualization/matplotlib/camera.py b/src/py123d/visualization/matplotlib/camera.py index a69a1413..949c5266 100644 --- a/src/py123d/visualization/matplotlib/camera.py +++ b/src/py123d/visualization/matplotlib/camera.py @@ -75,7 +75,6 @@ def add_box_detections_to_camera_ax( ego_state_se3: EgoStateSE3, return_image: bool = False, ) -> plt.Axes: - box_detection_array = np.zeros((len(box_detections.box_detections), len(BoundingBoxSE3Index)), dtype=np.float64) default_labels = np.array( [detection.metadata.default_label for detection in box_detections.box_detections], dtype=object @@ -120,12 +119,7 @@ def add_box_detections_to_camera_ax( return ax -def _transform_annotations_to_camera( - boxes: npt.NDArray[np.float32], - # sensor2lidar_rotation: npt.NDArray[np.float32], - # sensor2lidar_translation: npt.NDArray[np.float32], - extrinsic: npt.NDArray[np.float32], -) -> npt.NDArray[np.float32]: +def _transform_annotations_to_camera(boxes: npt.NDArray, extrinsic: npt.NDArray) -> npt.NDArray: """ Helper function to transform bounding boxes into camera frame TODO: Refactor @@ -187,7 +181,7 @@ def _rotation_3d_in_axis(points: npt.NDArray[np.float32], angles: npt.NDArray[np np.stack([rot_sin, zeros, rot_cos]), ] ) - elif axis == 2 or axis == -1: + elif axis in [2, -1]: rot_mat_T = np.stack( [ np.stack([rot_cos, -rot_sin, zeros]), @@ -209,7 +203,7 @@ def _rotation_3d_in_axis(points: npt.NDArray[np.float32], angles: npt.NDArray[np def _plot_rect_3d_on_img( - image: npt.NDArray[np.float32], + image: npt.NDArray[np.uint8], box_corners: npt.NDArray[np.float32], labels: List[DefaultBoxDetectionLabel], thickness: int = 3, diff --git a/src/py123d/visualization/matplotlib/observation.py b/src/py123d/visualization/matplotlib/observation.py index 85e0628d..884e6c39 100644 --- a/src/py123d/visualization/matplotlib/observation.py +++ b/src/py123d/visualization/matplotlib/observation.py @@ -1,3 +1,4 @@ +import traceback from typing import List, Optional, Union import matplotlib.pyplot as plt @@ -5,8 +6,6 @@ import shapely.geometry as geom from py123d.api.map.map_api import MapAPI -from py123d.api.scene.scene_api import SceneAPI -from py123d.conversion.registry.box_detection_label_registry import DefaultBoxDetectionLabel from py123d.datatypes.detections.box_detections import BoxDetectionWrapper from py123d.datatypes.detections.traffic_light_detections import TrafficLightDetectionWrapper from py123d.datatypes.map_objects.map_layer_types import MapLayer @@ -72,8 +71,6 @@ def add_default_map_on_ax( map_object: Lane add_shapely_linestring_to_ax(ax, map_object.centerline.linestring, CENTERLINE_CONFIG) except Exception: - import traceback - print(f"Error adding map object of type {layer.name} and id {map_object.object_id}") traceback.print_exc() @@ -89,39 +86,6 @@ def add_box_detections_to_ax(ax: plt.Axes, box_detections: BoxDetectionWrapper) add_bounding_box_to_ax(ax, box_detection.bounding_box_se2, plot_config) -def add_box_future_detections_to_ax(ax: plt.Axes, scene: SceneAPI, iteration: int) -> None: - - # TODO: Refactor this function - initial_agents = scene.get_box_detections_at_iteration(iteration) - agents_poses = { - agent.metadata.track_token: [agent.center_se3] - for agent in initial_agents - if agent.metadata.default_label == DefaultBoxDetectionLabel.VEHICLE - } - frequency = 1 - for iteration in range(iteration + frequency, scene.number_of_iterations, frequency): - agents = scene.get_box_detections_at_iteration(iteration) - for agent in agents: - if agent.metadata.track_token in agents_poses: - agents_poses[agent.metadata.track_token].append(agent.center_se3) - - for track_token, poses in agents_poses.items(): - if len(poses) < 2: - continue - poses = np.array([pose.point_2d.array for pose in poses]) - num_poses = poses.shape[0] - alphas = 1 - np.linspace(0.2, 1.0, num_poses) # Start low, end high - for i in range(num_poses - 1): - ax.plot( - poses[i : i + 2, 0], - poses[i : i + 2, 1], - color=BOX_DETECTION_CONFIG[DefaultBoxDetectionLabel.VEHICLE].fill_color.hex, - alpha=alphas[i + 1], - linewidth=BOX_DETECTION_CONFIG[DefaultBoxDetectionLabel.VEHICLE].line_width * 5, - zorder=BOX_DETECTION_CONFIG[DefaultBoxDetectionLabel.VEHICLE].zorder, - ) - - def add_ego_vehicle_to_ax(ax: plt.Axes, ego_vehicle_state: Union[EgoStateSE3, EgoStateSE2]) -> None: add_bounding_box_to_ax(ax, ego_vehicle_state.bounding_box, EGO_VEHICLE_CONFIG) @@ -130,7 +94,8 @@ def add_traffic_lights_to_ax( ax: plt.Axes, traffic_light_detections: TrafficLightDetectionWrapper, map_api: MapAPI ) -> None: for traffic_light_detection in traffic_light_detections: - lane: Lane = map_api.get_map_object(str(traffic_light_detection.lane_id), MapLayer.LANE) + lane = map_api.get_map_object(traffic_light_detection.lane_id, MapLayer.LANE) + assert isinstance(lane, Lane), f"Lane with id {traffic_light_detection.lane_id} not found." if lane is not None: add_shapely_linestring_to_ax( ax, @@ -146,7 +111,6 @@ def add_bounding_box_to_ax( bounding_box: Union[BoundingBoxSE2, BoundingBoxSE3], plot_config: PlotConfig, ) -> None: - add_shapely_polygon_to_ax(ax, bounding_box.shapely_polygon, plot_config) if plot_config.marker_style is not None: @@ -169,9 +133,10 @@ def add_bounding_box_to_ax( linestyle=plot_config.line_style, ) elif plot_config.marker_style == "^": - marker_size = min(plot_config.marker_size, min(bounding_box.length, bounding_box.width)) + min_extent = min(bounding_box.length, bounding_box.width) + marker_size = min(plot_config.marker_size, min_extent) marker_polygon = get_pose_triangle(marker_size) - global_marker_polygon = shapely_geometry_local_coords(marker_polygon, bounding_box.center) + global_marker_polygon = shapely_geometry_local_coords(marker_polygon, bounding_box.center_se2) add_shapely_polygon_to_ax(ax, global_marker_polygon, plot_config, disable_smoothing=True) else: raise ValueError(f"Unknown marker style: {plot_config.marker_style}") diff --git a/src/py123d/visualization/matplotlib/plots.py b/src/py123d/visualization/matplotlib/plots.py index 4419082b..99741006 100644 --- a/src/py123d/visualization/matplotlib/plots.py +++ b/src/py123d/visualization/matplotlib/plots.py @@ -1,8 +1,8 @@ from pathlib import Path from typing import Optional, Tuple, Union -import matplotlib.animation as animation import matplotlib.pyplot as plt +from matplotlib import animation from tqdm import tqdm from py123d.api.scene.scene_api import SceneAPI @@ -15,15 +15,15 @@ def _plot_scene_on_ax(ax: plt.Axes, scene: SceneAPI, iteration: int = 0, radius: float = 80) -> plt.Axes: - ego_vehicle_state = scene.get_ego_state_at_iteration(iteration) box_detections = scene.get_box_detections_at_iteration(iteration) traffic_light_detections = scene.get_traffic_light_detections_at_iteration(iteration) route_lane_group_ids = scene.get_route_lane_group_ids(iteration) map_api = scene.get_map_api() - point_2d = ego_vehicle_state.bounding_box.center.pose_se2.point_2d + assert ego_vehicle_state is not None, "Ego vehicle state is required to plot the scene." if map_api is not None: + point_2d = ego_vehicle_state.bounding_box_se2.center_se2.pose_se2.point_2d add_default_map_on_ax(ax, map_api, point_2d, radius=radius, route_lane_group_ids=route_lane_group_ids) if traffic_light_detections is not None: add_traffic_lights_to_ax(ax, traffic_light_detections, map_api) @@ -39,7 +39,6 @@ def _plot_scene_on_ax(ax: plt.Axes, scene: SceneAPI, iteration: int = 0, radius: def plot_scene_at_iteration(scene: SceneAPI, iteration: int = 0, radius: float = 80) -> Tuple[plt.Figure, plt.Axes]: - fig, ax = plt.subplots(figsize=(10, 10)) _plot_scene_on_ax(ax, scene, iteration, radius) return fig, ax diff --git a/src/py123d/visualization/matplotlib/utils.py b/src/py123d/visualization/matplotlib/utils.py index e0a81566..bffdfd40 100644 --- a/src/py123d/visualization/matplotlib/utils.py +++ b/src/py123d/visualization/matplotlib/utils.py @@ -1,11 +1,11 @@ from typing import Union -import matplotlib.patches as patches import matplotlib.pyplot as plt import numpy as np -import shapely.affinity as affinity import shapely.geometry as geom +from matplotlib import patches from matplotlib.path import Path +from shapely import affinity from py123d.geometry import PoseSE2, PoseSE3 from py123d.visualization.color.config import PlotConfig diff --git a/src/py123d/visualization/viser/elements/detection_elements.py b/src/py123d/visualization/viser/elements/detection_elements.py index bc94505e..c77679c4 100644 --- a/src/py123d/visualization/viser/elements/detection_elements.py +++ b/src/py123d/visualization/viser/elements/detection_elements.py @@ -68,7 +68,6 @@ def add_box_detections_to_viser_server( def _get_bounding_box_meshes(scene: SceneAPI, iteration: int, initial_ego_state: EgoStateSE3) -> trimesh.Trimesh: - ego_vehicle_state = scene.get_ego_state_at_iteration(iteration) box_detections = scene.get_box_detections_at_iteration(iteration) @@ -129,7 +128,6 @@ def _get_bounding_box_meshes(scene: SceneAPI, iteration: int, initial_ego_state: def _get_bounding_box_outlines( scene: SceneAPI, iteration: int, initial_ego_state: EgoStateSE3 ) -> npt.NDArray[np.float64]: - ego_vehicle_state = scene.get_ego_state_at_iteration(iteration) box_detections = scene.get_box_detections_at_iteration(iteration) diff --git a/src/py123d/visualization/viser/elements/map_elements.py b/src/py123d/visualization/viser/elements/map_elements.py index 88a76182..b3a02aa7 100644 --- a/src/py123d/visualization/viser/elements/map_elements.py +++ b/src/py123d/visualization/viser/elements/map_elements.py @@ -23,10 +23,9 @@ def add_map_to_viser_server( viser_config: ViserConfig, map_handles: Dict[MapLayer, viser.GlbHandle], ) -> None: - global last_query_position + global last_query_position # noqa: PLW0603 if viser_config.map_visible: - map_trimesh_dict: Optional[Dict[MapLayer, trimesh.Trimesh]] = None if len(map_handles) == 0 or viser_config._force_map_update: @@ -71,7 +70,6 @@ def _get_map_trimesh_dict( current_ego_state: Optional[EgoStateSE3], viser_config: ViserConfig, ) -> Dict[MapLayer, trimesh.Trimesh]: - # Dictionary to hold the output trimesh meshes. output_trimesh_dict: Dict[MapLayer, trimesh.Trimesh] = {} diff --git a/src/py123d/visualization/viser/elements/render_elements.py b/src/py123d/visualization/viser/elements/render_elements.py index a8d91a64..6f247c9f 100644 --- a/src/py123d/visualization/viser/elements/render_elements.py +++ b/src/py123d/visualization/viser/elements/render_elements.py @@ -57,7 +57,6 @@ def get_ego_bev_view_position( def _pitch_se3_by_degrees(pose_se3: PoseSE3, degrees: float) -> PoseSE3: - quaternion = EulerAngles(0.0, np.deg2rad(degrees), pose_se3.yaw).quaternion return PoseSE3( diff --git a/src/py123d/visualization/viser/elements/sensor_elements.py b/src/py123d/visualization/viser/elements/sensor_elements.py index 25014a43..b39399b2 100644 --- a/src/py123d/visualization/viser/elements/sensor_elements.py +++ b/src/py123d/visualization/viser/elements/sensor_elements.py @@ -33,7 +33,6 @@ def add_camera_frustums_to_viser_server( viser_config: ViserConfig, camera_frustum_handles: Dict[PinholeCameraType, viser.CameraFrustumHandle], ) -> None: - if viser_config.camera_frustum_visible: scene_center_array = initial_ego_state.center.point_3d.array ego_pose = scene.get_ego_state_at_iteration(scene_interation).rear_axle_se3.array @@ -62,8 +61,6 @@ def _add_camera_frustums_to_viser_server(camera_type: PinholeCameraType) -> None wxyz=camera_quaternion, ) - return None - # NOTE; In order to speed up adding camera frustums, we use multithreading and resize the images. with concurrent.futures.ThreadPoolExecutor(max_workers=len(viser_config.camera_frustum_types)) as executor: future_to_camera = { @@ -118,8 +115,6 @@ def _add_fisheye_frustums_to_viser_server(fisheye_camera_type: FisheyeMEICameraT wxyz=fcam_quaternion, ) - return None - # NOTE; In order to speed up adding camera frustums, we use multithreading and resize the images. with concurrent.futures.ThreadPoolExecutor( max_workers=len(viser_config.fisheye_mei_camera_frustum_types) @@ -166,7 +161,6 @@ def add_lidar_pc_to_viser_server( lidar_pc_handles: Dict[LiDARType, Optional[viser.PointCloudHandle]], ) -> None: if viser_config.lidar_visible: - scene_center_array = initial_ego_state.center.point_3d.array ego_pose = scene.get_ego_state_at_iteration(scene_interation).rear_axle_se3.array ego_pose[PoseSE3Index.XYZ] -= scene_center_array @@ -269,9 +263,6 @@ def _rescale_image(image: npt.NDArray[np.uint8], scale: float) -> npt.NDArray[np return downscaled_image -import numpy as np - - def calculate_fov(metadata: FisheyeMEICameraMetadata) -> tuple[float, float]: """ Calculate horizontal and vertical FOV in degrees. diff --git a/src/py123d/visualization/viser/viser_config.py b/src/py123d/visualization/viser/viser_config.py index 2bd4871f..2907a45d 100644 --- a/src/py123d/visualization/viser/viser_config.py +++ b/src/py123d/visualization/viser/viser_config.py @@ -33,7 +33,6 @@ @dataclass class ViserConfig: - # Server server_host: str = "localhost" server_port: int = 8080 @@ -98,7 +97,6 @@ def __post_init__(self): def _resolve_enum_arguments( serial_enum_cls: SerialIntEnum, input: Optional[List[Union[int, str, SerialIntEnum]]] ) -> List[SerialIntEnum]: - if input is None: return None assert isinstance(input, list), f"input must be a list of {serial_enum_cls.__name__}" diff --git a/src/py123d/visualization/viser/viser_viewer.py b/src/py123d/visualization/viser/viser_viewer.py index f097dc6e..ed020dcb 100644 --- a/src/py123d/visualization/viser/viser_viewer.py +++ b/src/py123d/visualization/viser/viser_viewer.py @@ -101,12 +101,14 @@ def next(self) -> None: def set_scene(self, scene: SceneAPI) -> None: num_frames = scene.number_of_iterations - initial_ego_state: EgoStateSE3 = scene.get_ego_state_at_iteration(0) + initial_ego_state = scene.get_ego_state_at_iteration(0) + assert initial_ego_state is not None and isinstance(initial_ego_state, EgoStateSE3) + server_playing = True server_rendering = False with self._viser_server.gui.add_folder("Playback"): - gui_info = self._viser_server.gui.add_markdown(content=_get_scene_info_markdown(scene)) + self._viser_server.gui.add_markdown(content=_get_scene_info_markdown(scene)) gui_timestep = self._viser_server.gui.add_slider( "Timestep", @@ -395,7 +397,7 @@ def _(event: viser.GuiEvent) -> None: def _get_scene_info_markdown(scene: SceneAPI) -> str: markdown = f""" - Dataset: {scene.log_metadata.split} - - Location: {scene.log_metadata.location if scene.log_metadata.location else 'N/A'} + - Location: {scene.log_metadata.location if scene.log_metadata.location else "N/A"} - UUID: {scene.scene_uuid} """ return markdown diff --git a/tests/unit/conversion/registry/test_box_detection_label_registry.py b/tests/unit/conversion/registry/test_box_detection_label_registry.py index 384b0b96..393e3527 100644 --- a/tests/unit/conversion/registry/test_box_detection_label_registry.py +++ b/tests/unit/conversion/registry/test_box_detection_label_registry.py @@ -2,7 +2,6 @@ class TestBoxDetectionLabelRegistry: - def test_correct_type(self): """Test that all registered box detection labels are of correct type.""" for label_class in BOX_DETECTION_LABEL_REGISTRY.values(): diff --git a/tests/unit/conversion/registry/test_lidar_registry.py b/tests/unit/conversion/registry/test_lidar_registry.py index eca6bd59..c93bc538 100644 --- a/tests/unit/conversion/registry/test_lidar_registry.py +++ b/tests/unit/conversion/registry/test_lidar_registry.py @@ -6,7 +6,6 @@ class TestLiDARRegistry: - def test_registered_types(self): """Test that all registered LiDAR types are of correct type.""" for lidar_class in LIDAR_INDEX_REGISTRY.values(): diff --git a/tests/unit/datatypes/detections/test_box_detections.py b/tests/unit/datatypes/detections/test_box_detections.py index cdcee382..59509efa 100644 --- a/tests/unit/datatypes/detections/test_box_detections.py +++ b/tests/unit/datatypes/detections/test_box_detections.py @@ -12,7 +12,6 @@ class DummyBoxDetectionLabel(BoxDetectionLabel): - CAR = 1 PEDESTRIAN = 2 BICYCLE = 3 @@ -35,7 +34,6 @@ def to_default(self): class TestBoxDetectionMetadata: - def test_initialization(self): metadata = BoxDetectionMetadata(**sample_metadata_args) assert isinstance(metadata, BoxDetectionMetadata) @@ -94,7 +92,6 @@ def test_missing_args(self): class TestBoxDetectionSE2: - def setup_method(self): self.metadata = BoxDetectionMetadata(**sample_metadata_args) self.bounding_box_se2 = BoundingBoxSE2( @@ -143,7 +140,6 @@ def test_optional_velocity(self): class TestBoxBoxDetectionSE3: - def setup_method(self): self.metadata = BoxDetectionMetadata(**sample_metadata_args) self.bounding_box_se3 = BoundingBoxSE3( @@ -231,7 +227,6 @@ def test_optional_velocity(self): class TestBoxDetectionWrapper: - def setup_method(self): self.metadata1 = BoxDetectionMetadata( label=DummyBoxDetectionLabel.CAR, diff --git a/tests/unit/datatypes/map_objects/mock_map_api.py b/tests/unit/datatypes/map_objects/mock_map_api.py index a5cdf27f..9158df1f 100644 --- a/tests/unit/datatypes/map_objects/mock_map_api.py +++ b/tests/unit/datatypes/map_objects/mock_map_api.py @@ -20,7 +20,6 @@ class MockMapAPI(MapAPI): - def __init__( self, lanes: List[Lane] = [], @@ -35,7 +34,6 @@ def __init__( road_lines: List[RoadLine] = [], add_map_api_links: bool = False, ): - self._layers: Dict[MapLayer, List[BaseMapObject]] = { MapLayer.LANE: lanes, MapLayer.LANE_GROUP: lane_groups, diff --git a/tests/unit/datatypes/map_objects/test_map_objects.py b/tests/unit/datatypes/map_objects/test_map_objects.py index ed36ffc3..252500cd 100644 --- a/tests/unit/datatypes/map_objects/test_map_objects.py +++ b/tests/unit/datatypes/map_objects/test_map_objects.py @@ -427,7 +427,6 @@ def test_lane_group_links(self): class TestLaneGroup: - def setup_method(self): lanes, lane_groups, intersections = _get_linked_map_object_setup() self.lanes = lanes @@ -610,7 +609,6 @@ def test_no_links(self): class TestIntersection: - def setup_method(self): lanes, lane_groups, intersections = _get_linked_map_object_setup() self.lanes = lanes diff --git a/tests/unit/datatypes/metadata/test_log_metadata.py b/tests/unit/datatypes/metadata/test_log_metadata.py index 7afb0bac..8d8348b8 100644 --- a/tests/unit/datatypes/metadata/test_log_metadata.py +++ b/tests/unit/datatypes/metadata/test_log_metadata.py @@ -8,7 +8,6 @@ class TestLogMetadata: - def test_init_minimal(self): """Test LogMetadata initialization with minimal required fields.""" log_metadata = LogMetadata( diff --git a/tests/unit/datatypes/metadata/test_map_metadata.py b/tests/unit/datatypes/metadata/test_map_metadata.py index a5ad7279..2af85186 100644 --- a/tests/unit/datatypes/metadata/test_map_metadata.py +++ b/tests/unit/datatypes/metadata/test_map_metadata.py @@ -2,7 +2,6 @@ class TestMapMetadata: - def test_map_metadata_initialization(self): """Test that MapMetadata can be initialized with required fields.""" metadata = MapMetadata( diff --git a/tests/unit/datatypes/sensors/test_fisheye_mei_camera.py b/tests/unit/datatypes/sensors/test_fisheye_mei_camera.py index 7cf5d635..0731b56d 100644 --- a/tests/unit/datatypes/sensors/test_fisheye_mei_camera.py +++ b/tests/unit/datatypes/sensors/test_fisheye_mei_camera.py @@ -14,7 +14,6 @@ class TestFisheyeMEICameraType: - def test_camera_type_values(self): """Test that camera type enum has expected values.""" assert FisheyeMEICameraType.FCAM_L.value == 0 @@ -39,7 +38,6 @@ def test_camera_type_comparison(self): class TestFisheyeMEIDistortion: - def test_distortion_initialization(self): """Test distortion parameter initialization.""" distortion = FisheyeMEIDistortion(k1=0.1, k2=0.2, p1=0.3, p2=0.4) @@ -88,7 +86,6 @@ def test_distortion_index_mapping(self): class TestFisheyeMEIProjection: - def test_projection_initialization(self): """Test projection parameter initialization.""" projection = FisheyeMEIProjection(gamma1=1.0, gamma2=2.0, u0=3.0, v0=4.0) @@ -137,7 +134,6 @@ def test_projection_index_mapping(self): class TestFisheyeMEICameraMetadata: - def test_metadata_initialization(self): """Test metadata initialization with all parameters.""" distortion = FisheyeMEIDistortion(k1=0.1, k2=0.2, p1=0.3, p2=0.4) @@ -277,7 +273,6 @@ def test_aspect_ratio_calculation(self): class TestFisheyeMEICamera: - def test_camera_initialization(self): """Test FisheyeMEICamera initialization.""" diff --git a/tests/unit/datatypes/sensors/test_pinhole_camera.py b/tests/unit/datatypes/sensors/test_pinhole_camera.py index e0811a9e..f05ab970 100644 --- a/tests/unit/datatypes/sensors/test_pinhole_camera.py +++ b/tests/unit/datatypes/sensors/test_pinhole_camera.py @@ -13,7 +13,6 @@ class TestPinholeCameraType: - def test_camera_type_values(self): """Test that camera type enum has expected values.""" assert PinholeCameraType.PCAM_F0 == PinholeCameraType.PCAM_F0 @@ -45,7 +44,6 @@ def test_camera_type_unique_values(self): class TestPinholeIntrinsics: - def test_intrinsics_creation(self): """Test creating PinholeIntrinsics instance.""" intrinsics = PinholeIntrinsics(fx=500.0, fy=500.0, cx=320.0, cy=240.0, skew=0.0) @@ -175,7 +173,6 @@ def test_intrinsics_non_centered_principal_point(self): class TestPinholeDistortion: - def test_distortion_creation(self): """Test creating PinholeDistortion instance.""" distortion = PinholeDistortion(k1=0.1, k2=0.01, p1=0.001, p2=0.001, k3=0.001) @@ -274,7 +271,6 @@ def test_distortion_tolist(self): class TestPinholeMetadata: - def test_metadata_from_dict_with_none_intrinsics(self): """Test creating metadata from dict with None intrinsics.""" data_dict = { @@ -394,7 +390,6 @@ def test_metadata_non_square_pixels(self): class TestPinholeCamera: - def test_pinhole_camera_creation(self): """Test creating PinholeCamera instance.""" diff --git a/tests/unit/datatypes/time/test_time.py b/tests/unit/datatypes/time/test_time.py index 1a15a73c..69ab6166 100644 --- a/tests/unit/datatypes/time/test_time.py +++ b/tests/unit/datatypes/time/test_time.py @@ -4,7 +4,6 @@ class TestTimePoint: - def test_from_ns(self): """Test constructing TimePoint from nanoseconds.""" tp = TimePoint.from_ns(1000000) diff --git a/tests/unit/datatypes/vehicle_state/test_ego_state.py b/tests/unit/datatypes/vehicle_state/test_ego_state.py index e4e8d46c..671505ec 100644 --- a/tests/unit/datatypes/vehicle_state/test_ego_state.py +++ b/tests/unit/datatypes/vehicle_state/test_ego_state.py @@ -215,7 +215,6 @@ def test_rear_axle_properties(self): """Test rear_axle properties.""" ego_state = EgoStateSE3(rear_axle_se3=self.rear_axle_pose, vehicle_parameters=self.vehicle_params) - assert ego_state.rear_axle == self.rear_axle_pose assert ego_state.rear_axle_se3 == self.rear_axle_pose assert ego_state.rear_axle_se2 is not None @@ -244,7 +243,7 @@ def test_bounding_box_properties(self): bbox_se2 = ego_state.bounding_box_se2 assert bbox_se2 is not None - assert ego_state.bounding_box == bbox_se3 + assert ego_state.bounding_box_se3 == bbox_se3 def test_box_detection_properties(self): """Test box detection properties.""" diff --git a/tests/unit/datatypes/vehicle_state/test_vehicle_parameters.py b/tests/unit/datatypes/vehicle_state/test_vehicle_parameters.py index d678b6f7..f04b5cff 100644 --- a/tests/unit/datatypes/vehicle_state/test_vehicle_parameters.py +++ b/tests/unit/datatypes/vehicle_state/test_vehicle_parameters.py @@ -2,7 +2,6 @@ class TestVehicleParameters: - def setup_method(self): self.params = VehicleParameters( vehicle_name="test_vehicle", diff --git a/tests/unit/geometry/test_bounding_box.py b/tests/unit/geometry/test_bounding_box.py index bb5b5513..c58ae8f7 100644 --- a/tests/unit/geometry/test_bounding_box.py +++ b/tests/unit/geometry/test_bounding_box.py @@ -1,5 +1,3 @@ -import unittest - import numpy as np import pytest import shapely.geometry as geom @@ -213,7 +211,3 @@ def test_zero_dimensions(self): assert bbox.length == 0.0 assert bbox.width == 0.0 assert bbox.height == 0.0 - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/unit/geometry/test_occupancy_map.py b/tests/unit/geometry/test_occupancy_map.py index 37094349..a50190b4 100644 --- a/tests/unit/geometry/test_occupancy_map.py +++ b/tests/unit/geometry/test_occupancy_map.py @@ -1,5 +1,3 @@ -import unittest - import numpy as np import pytest import shapely.geometry as geom @@ -279,8 +277,3 @@ def test_single_geometry_map(self): assert len(occ_map) == 1 assert occ_map.ids == ["single"] assert occ_map["single"] == self.square1 - - -if __name__ == "__main__": - - unittest.main() diff --git a/tests/unit/geometry/test_point.py b/tests/unit/geometry/test_point.py index b7dfb558..d293f8b5 100644 --- a/tests/unit/geometry/test_point.py +++ b/tests/unit/geometry/test_point.py @@ -1,4 +1,3 @@ -import unittest from unittest.mock import MagicMock, patch import numpy as np @@ -183,7 +182,3 @@ def test_iter(self): assert x == self.x_coord assert y == self.y_coord assert z == self.z_coord - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/unit/geometry/test_rotation.py b/tests/unit/geometry/test_rotation.py index 3b7d6d1d..a7fc2e09 100644 --- a/tests/unit/geometry/test_rotation.py +++ b/tests/unit/geometry/test_rotation.py @@ -1,5 +1,3 @@ -import unittest - import numpy as np import pytest @@ -178,7 +176,3 @@ def test_rotation_matrix_property(self): rot_matrix = self.quaternion.rotation_matrix assert rot_matrix.shape == (3, 3) np.testing.assert_array_almost_equal(rot_matrix, np.eye(3)) - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/unit/geometry/test_vector.py b/tests/unit/geometry/test_vector.py index d8f48ce8..71379c57 100644 --- a/tests/unit/geometry/test_vector.py +++ b/tests/unit/geometry/test_vector.py @@ -1,5 +1,3 @@ -import unittest - import numpy as np import pytest @@ -167,7 +165,3 @@ def test_hash(self): vector_dict = {self.vector: "test"} assert self.vector in vector_dict assert vector_dict[self.vector] == "test" - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/unit/geometry/transform/test_transform_consistency.py b/tests/unit/geometry/transform/test_transform_consistency.py index fcd64726..b4476a4f 100644 --- a/tests/unit/geometry/transform/test_transform_consistency.py +++ b/tests/unit/geometry/transform/test_transform_consistency.py @@ -1,5 +1,3 @@ -import unittest - import numpy as np import numpy.typing as npt @@ -486,7 +484,3 @@ def test_transform_large_rotations(self) -> None: ) np.testing.assert_array_almost_equal(test_2d_points, recovered_2d_points, decimal=self.decimal) np.testing.assert_array_almost_equal(test_3d_points, recovered_3d_points, decimal=self.decimal) - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/unit/geometry/transform/test_transform_euler_se3.py b/tests/unit/geometry/transform/test_transform_euler_se3.py index 6ccbc21e..2901918d 100644 --- a/tests/unit/geometry/transform/test_transform_euler_se3.py +++ b/tests/unit/geometry/transform/test_transform_euler_se3.py @@ -15,7 +15,6 @@ class TestTransformEulerSE3: - def setup_method(self): self.decimal = 6 # Decimal places for np.testing.assert_array_almost_equal self.num_consistency_tests = 10 # Number of random test cases for consistency checks diff --git a/tests/unit/geometry/transform/test_transform_se2.py b/tests/unit/geometry/transform/test_transform_se2.py index 28f20983..ec8836aa 100644 --- a/tests/unit/geometry/transform/test_transform_se2.py +++ b/tests/unit/geometry/transform/test_transform_se2.py @@ -1,9 +1,8 @@ import numpy as np import numpy.typing as npt -from py123d.geometry import PoseSE2, Vector2D -from py123d.geometry.geometry_index import PoseSE2Index -from py123d.geometry.transform.transform_se2 import ( +from py123d.geometry import PoseSE2, PoseSE2Index, Vector2D +from py123d.geometry.transform import ( convert_absolute_to_relative_points_2d_array, convert_absolute_to_relative_se2_array, convert_points_2d_array_between_origins, @@ -18,7 +17,6 @@ class TestTransformSE2: - def setup_method(self): self.decimal = 6 # Decimal places for np.testing.assert_array_almost_equal diff --git a/tests/unit/geometry/transform/test_transform_se3.py b/tests/unit/geometry/transform/test_transform_se3.py index e982e09b..1564384a 100644 --- a/tests/unit/geometry/transform/test_transform_se3.py +++ b/tests/unit/geometry/transform/test_transform_se3.py @@ -1,5 +1,3 @@ -import unittest - import numpy as np import numpy.typing as npt @@ -25,7 +23,6 @@ class TestTransformSE3: - def setup_method(self): euler_se3_a = EulerStateSE3( x=1.0, @@ -92,17 +89,16 @@ def _get_random_quat_se3_array(self, size: int) -> npt.NDArray[np.float64]: def test_sanity(self): for quat_se3, euler_se3 in zip(self.quat_se3, self.euler_se3): - for quat_se3, euler_se3 in zip(self.quat_se3, self.euler_se3): - np.testing.assert_allclose( - quat_se3.point_3d.array, - euler_se3.point_3d.array, - atol=1e-6, - ) - np.testing.assert_allclose( - quat_se3.rotation_matrix, - euler_se3.rotation_matrix, - atol=1e-6, - ) + np.testing.assert_allclose( + quat_se3.point_3d.array, + euler_se3.point_3d.array, + atol=1e-6, + ) + np.testing.assert_allclose( + quat_se3.rotation_matrix, + euler_se3.rotation_matrix, + atol=1e-6, + ) def test_random_sanity(self): for _ in range(10): @@ -123,7 +119,6 @@ def test_random_sanity(self): np.testing.assert_allclose(euler_rotation_matrices, quat_rotation_matrices, atol=1e-6) def test_convert_absolute_to_relative_points_3d_array(self): - random_points_3d = np.random.rand(10, 3) for quat_se3, euler_se3 in zip(self.quat_se3, self.euler_se3): rel_points_quat = convert_absolute_to_relative_points_3d_array(quat_se3, random_points_3d) @@ -133,7 +128,6 @@ def test_convert_absolute_to_relative_points_3d_array(self): np.testing.assert_allclose(rel_points_quat, rel_points_euler, atol=1e-6) def test_convert_absolute_to_relative_se3_array(self): - for quat_se3, euler_se3 in zip(self.quat_se3, self.euler_se3): random_euler_se3_array = self._get_random_euler_se3_array(np.random.randint(1, 10)) random_quat_se3_array = self._convert_euler_se3_array_to_quat_se3_array(random_euler_se3_array) @@ -155,7 +149,6 @@ def test_convert_absolute_to_relative_se3_array(self): np.testing.assert_allclose(quat_rotation_matrices, euler_rotation_matrices, atol=1e-6) def test_convert_relative_to_absolute_points_3d_array(self): - random_points_3d = np.random.rand(10, 3) for quat_se3, euler_se3 in zip(self.quat_se3, self.euler_se3): rel_points_quat = convert_relative_to_absolute_points_3d_array(quat_se3, random_points_3d) @@ -165,7 +158,6 @@ def test_convert_relative_to_absolute_points_3d_array(self): np.testing.assert_allclose(rel_points_quat, rel_points_euler, atol=1e-6) def test_convert_relative_to_absolute_se3_array(self): - for quat_se3, euler_se3 in zip(self.quat_se3, self.euler_se3): random_euler_se3_array = self._get_random_euler_se3_array(np.random.randint(1, 10)) random_quat_se3_array = self._convert_euler_se3_array_to_quat_se3_array(random_euler_se3_array) @@ -300,7 +292,3 @@ def test_translate_se3_along_body_frame(self): np.testing.assert_allclose(translated_quat.point_3d.array, translated_euler.point_3d.array, atol=1e-6) np.testing.assert_allclose(translated_quat.rotation_matrix, translated_euler.rotation_matrix, atol=1e-6) np.testing.assert_allclose(quat_se3.quaternion.array, translated_quat.quaternion.array, atol=1e-6) - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/unit/geometry/utils/test_bounding_box_utils.py b/tests/unit/geometry/utils/test_bounding_box_utils.py index 93ddfc16..d9475469 100644 --- a/tests/unit/geometry/utils/test_bounding_box_utils.py +++ b/tests/unit/geometry/utils/test_bounding_box_utils.py @@ -1,5 +1,3 @@ -import unittest - import numpy as np import numpy.typing as npt import shapely @@ -25,7 +23,6 @@ class TestBoundingBoxUtils: - def setup_method(self): self._num_consistency_checks = 10 self._max_pose_xyz = 100.0 @@ -260,7 +257,3 @@ def test_bbse3_array_to_corners_array_zero_dim(self): corners_array = bbse3_array_to_corners_array(bounding_box_se3_array) expected_corners = np.zeros((0, 8, 3), dtype=np.float64) np.testing.assert_allclose(corners_array, expected_corners, atol=1e-6) - - -if __name__ == "__main__": - unittest.main() diff --git a/tests/unit/geometry/utils/test_rotation_utils.py b/tests/unit/geometry/utils/test_rotation_utils.py index 5483e976..92c4d1b7 100644 --- a/tests/unit/geometry/utils/test_rotation_utils.py +++ b/tests/unit/geometry/utils/test_rotation_utils.py @@ -1,4 +1,3 @@ -import unittest from typing import Tuple import numpy as np @@ -64,7 +63,6 @@ def _get_rotation_matrix_helper(euler_array: npt.NDArray[np.float64]) -> npt.NDA class TestRotationUtils: - def setup_method(self): pass @@ -300,7 +298,6 @@ def _test_by_shape(shape: Tuple[int, ...]) -> None: get_q_bar_matrices(invalid_quat) def test_get_q_matrices(self): - def _test_by_shape(shape: Tuple[int, ...]) -> None: for _ in range(10): N = np.prod(shape) @@ -397,7 +394,6 @@ def _test_by_shape(shape: Tuple[int, ...]) -> None: get_quaternion_array_from_euler_array(invalid_euler) def test_get_quaternion_array_from_rotation_matrices(self): - def _test_by_shape(shape: Tuple[int, ...]) -> None: for _ in range(10): N = np.prod(shape) @@ -781,7 +777,3 @@ def _test_by_shape(shape: Tuple[int, ...]) -> None: normalized_angle = normalize_angle(angle) assert normalized_angle >= -np.pi - 1e-8 assert normalized_angle <= np.pi + 1e-8 - - -if __name__ == "__main__": - unittest.main()