Skip to content

Commit

Permalink
implement world and test
Browse files Browse the repository at this point in the history
  • Loading branch information
chanwutk committed Aug 10, 2023
1 parent b4f39e4 commit 4ed842b
Show file tree
Hide file tree
Showing 19 changed files with 508 additions and 236 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/clean-up-and-format.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ on:
- 'main'
- 'dev'

permissions:
contents: write

jobs:
clean-up:
name: Clean Up Python Notebooks
Expand Down
82 changes: 81 additions & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,86 @@ on:
push:

jobs:
test-workflow:
name: Test Workflow
runs-on: ubuntu-latest
services:
mobilitydb:
image: mobilitydb/mobilitydb:14-3.2-1
ports:
- 25440:5432
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
steps:
- name: Checkout
uses: actions/checkout@v3
with:
token: ${{ secrets.GH_PAT || github.token }}
submodules: recursive

- name: Setup Micromamba
uses: mamba-org/setup-micromamba@v1
with:
environment-file: environment.yml
init-shell: none
cache-downloads: false

- name: Check Python Versions
shell: micromamba-shell {0}
run: |
python --version
python3 --version
which python
which python3
which pip
which pip3
which poetry
- name: Install Dependencies
shell: micromamba-shell {0}
run: poetry install --no-interaction --without dev --with test

- name: Install lap (Hack)
shell: micromamba-shell {0}
run: |
pip install --upgrade pip
pip install lap
- name: Check Installed Packages
shell: micromamba-shell {0}
run: pip list

- name: Extend MobilityDB with User-Defined functions
shell: micromamba-shell {0}
run: |
pushd scripts/pg-extender
python ../generate_pg_extender.py
cat install.sql
psql -h localhost -p 25440 -d mobilitydb -U docker -c "SET client_min_messages TO WARNING;" -c "\i install.sql;"
popd
env:
PGPASSWORD: docker

- name: Ingest data
shell: micromamba-shell {0}
run: python ./scripts/ingest_road.py
env:
AP_PORT: 25440

- name: Unit Test
shell: micromamba-shell {0}
run: pytest --cov=spatialyze --cov-report=xml tests/workflow
env:
AP_PORT: 25440

- uses: actions/upload-artifact@v3
with:
name: workflow-coverage
path: ./coverage.xml

test-video-processor:
name: Test Video Processor
runs-on: ubuntu-latest
Expand Down Expand Up @@ -220,7 +300,7 @@ jobs:

upload-coverage:
name: Upload Coverage
needs: [test-video-processor, test-engine-and-interface]
needs: [test-video-processor, test-engine-and-interface, test-workflow]
runs-on: ubuntu-latest
steps:
- name: Checkout
Expand Down
24 changes: 12 additions & 12 deletions scripts/pg-extender/install.sql
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
\i overlap.sql;
\i in_view.sql;
\i ahead.sql;
\i angleBetween.sql;
\i angleExcluding.sql;
\i convertCamera.sql;
\i distance.sql;
\i sameRegion.sql;
\i facingRelative.sql;
\i ahead.sql;
\i geoContained.sql;
\i geoContainedMargin.sql;
\i headingAtTimestamp.sql;
\i in_view.sql;
\i minDistance.sql;
\i objectBBox.sql;
\i operators.sql;
\i overlap.sql;
\i roadCoords.sql;
\i roadDirection.sql;
\i angleBetween.sql;
\i headingAtTimestamp.sql;
\i objectBBox.sql;
\i viewAngle.sql;
\i geoContained.sql;
\i roadSegment.sql;
\i angleExcluding.sql;
\i roadCoords.sql;
\i convertCamera.sql;
\i sameRegion.sql;
\i viewAngle.sql;
9 changes: 5 additions & 4 deletions spatialyze/data_types/camera_config.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
from dataclasses import dataclass
from typing import List, Tuple
from typing import Tuple

import numpy.typing as npt

Float3 = Tuple[float, float, float]
Float33 = Tuple[Float3, Float3, Float3]
Float4 = Tuple[float, float, float, float]


Expand All @@ -14,9 +15,9 @@ class CameraConfig:
filename: str
camera_translation: npt.NDArray # float[3]
camera_rotation: npt.NDArray # float[4]
camera_intrinsic: List[List[float]] # float[3][3]
ego_translation: List[float] # float[3]
ego_rotation: List[float] # float[4]
camera_intrinsic: "list[list[float]] | Float33" # float[3][3]
ego_translation: "list[float] | Float3" # float[3]
ego_rotation: "list[float] | Float4" # float[4]
timestamp: str
cameraHeading: float
egoHeading: float
23 changes: 22 additions & 1 deletion spatialyze/geospatial_video.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,23 @@
import json
from typing import Any

from .video_processor.camera_config import CameraConfig, camera_config


class GeospatialVideo:
pass
def __init__(self, video: "str", camera: "list[CameraConfig] | str") -> None:
self.video = video
if isinstance(camera, str):
with open(camera, "r") as f:
camera_configs = json.load(f)
assert isinstance(camera_configs, list), camera_configs
self.camera = [_camera_config(c) for c in camera_configs]
else:
self.camera = camera


def _camera_config(c: "Any"):
assert isinstance(c, list), c
assert len(c) == 13, c
c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13 = c
return camera_config(c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12, c13, 0)
8 changes: 1 addition & 7 deletions spatialyze/predicate.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@
from typing import (
Any,
Callable,
Generic,
Literal,
TypeVar,
)
from typing import Any, Callable, Generic, Literal, TypeVar

BinOp = Literal["add", "sub", "mul", "div", "matmul"]
BoolOp = Literal["and", "or"]
Expand Down
6 changes: 4 additions & 2 deletions spatialyze/road_network.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from spatialyze.database import Database
from spatialyze.utils.ingest_road import ingest_location
from .database import Database
from .utils.ingest_road import ROAD_TYPES, add_segment_type, ingest_location


class RoadNetwork:
Expand All @@ -9,3 +9,5 @@ def __init__(self, location: "str", road_network_dir: "str"):

def ingest(self, database: "Database"):
ingest_location(database, self.road_network_dir, self.location)
add_segment_type(database, ROAD_TYPES)
database._commit()
2 changes: 1 addition & 1 deletion spatialyze/video_processor/camera_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def camera_config(
camera_heading: float,
ego_heading: float,
location: str,
road_direction: float,
road_direction: float = 0,
):
_frame = CameraConfig()
_frame.camera_id = camera_id
Expand Down
6 changes: 2 additions & 4 deletions spatialyze/video_processor/stages/in_view/in_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ def __repr__(self) -> str:
def _run(self, payload: "Payload") -> "tuple[bitarray, None]":
indices, view_areas = get_views(payload, self.distance)

keep = bitarray(len(payload.keep))
if self.predicate is None:
results = database.execute(
sql.SQL(
Expand All @@ -84,12 +85,10 @@ def _run(self, payload: "Payload") -> "tuple[bitarray, None]":
)
)

keep = bitarray(len(payload.keep))
keep.setall(0)
for (index,) in results:
keep[index] = 1
elif self.predicate is False:
keep = bitarray(len(payload.keep))
keep.setall(0)
elif self.predicate is not True:
exists = sql.SQL(
Expand Down Expand Up @@ -120,7 +119,6 @@ def _run(self, payload: "Payload") -> "tuple[bitarray, None]":
)
)

keep = bitarray(len(payload.keep))
keep.setall(0)
for index, *encoded_segment_types in results:
segment_types = {
Expand Down Expand Up @@ -249,7 +247,7 @@ def visit_BoolOpNode(self, node: BoolOpNode):
# print('annihilated', visited)
return lit(annihilator)
if all(isinstance(e, LiteralNode) for e in visited.exprs):
assert len({e.value for e in visited.exprs}) == 1
assert len({e.value for e in visited.exprs}) == 1, visited.exprs
# print('all', visited)
return lit(visited.exprs[0].value)
exprs = [e for e in visited.exprs if not isinstance(e, LiteralNode)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ def _run(self, payload: "Payload"):

def rotate(vectors: "npt.NDArray", rotation: "Quaternion") -> "npt.NDArray":
"""Rotate 3D Vector by rotation quaternion.
Params:
vectors: (3 x N) 3-vectors each specified as any ordered
sequence of 3 real numbers corresponding to x, y, and z values.
Expand Down
11 changes: 11 additions & 0 deletions spatialyze/video_processor/utils/associate_segment_mapping.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from ..stages.segment_trajectory.from_tracking_3d import SegmentTrajectoryMetadatum
from ..stages.tracking_3d.tracking_3d import Tracking3DResult


def associate_segment_mapping(
tracking_result: "Tracking3DResult",
segment_mapping_meta: "list[SegmentTrajectoryMetadatum] | None",
):
if segment_mapping_meta is None:
return None
return segment_mapping_meta[tracking_result.frame_idx].get(tracking_result.object_id)
65 changes: 65 additions & 0 deletions spatialyze/video_processor/utils/format_trajectory.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
from ..camera_config import CameraConfig
from ..stages.segment_trajectory.construct_segment_trajectory import SegmentPoint
from ..stages.tracking_3d.tracking_3d import Tracking3DResult
from ..types import Float3


def format_trajectory(
video_name: "str",
obj_id: "str",
track: "list[tuple[Tracking3DResult, CameraConfig, SegmentPoint | None]]",
base=None,
):
timestamps: "list[str]" = []
pairs: "list[Float3]" = []
itemHeadings: "list[int]" = []
translations: "list[Float3]" = []
camera_id = None
object_type = None
# road_types: "list[str]" = []
# roadpolygons: "list[list[Float2]]" = []
### TODO (fge): remove investigation code
info_found = []
# if obj_id in investigation_ids:
# print(f"obj_id, {obj_id}:", [e[1].filename for e in track])
for tracking_result_3d, ego_info, segment_mapping in track:
if ego_info:
if (
"sweeps/CAM_FRONT/n008-2018-08-30-15-16-55-0400__CAM_FRONT__1535657125362404.jpg"
in ego_info.filename
):
info_found.append(
[
obj_id,
tracking_result_3d.bbox_left,
tracking_result_3d.bbox_top,
tracking_result_3d.bbox_w,
tracking_result_3d.bbox_h,
]
)
camera_id = ego_info.camera_id
object_type = tracking_result_3d.object_type
timestamps.append(ego_info.timestamp)
pairs.append(tracking_result_3d.point)
if not segment_mapping or (segment_mapping.segment_type == "intersection"):
itemHeadings.append(None)
else:
itemHeadings.append(segment_mapping.segment_heading)
translations.append(ego_info.ego_translation)
# road_types.append(segment_mapping.road_polygon_info.road_type if base else detection_info.road_type)
# roadpolygons.append(None if base else detection_info.road_polygon_info.polygon)
if len(timestamps) == 0 or camera_id is None or object_type is None:
return None
# if obj_id in investigation_ids:
# print(f"pairs for obj {obj_id}:", [(e[0], e[1]) for e in pairs])
# print(f"itemHeadings for obj {obj_id}:", itemHeadings)

return (
video_name + "_obj_" + str(obj_id),
camera_id,
object_type,
timestamps,
pairs,
itemHeadings,
translations,
), info_found
36 changes: 36 additions & 0 deletions spatialyze/video_processor/utils/get_tracks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
from ..camera_config import CameraConfig
from ..stages.segment_trajectory.construct_segment_trajectory import SegmentPoint
from ..stages.segment_trajectory.from_tracking_3d import SegmentTrajectoryMetadatum
from ..stages.tracking_3d.tracking_3d import Metadatum as Tracking3DMetadatum
from ..stages.tracking_3d.tracking_3d import Tracking3DResult
from .associate_segment_mapping import associate_segment_mapping


def get_tracks(
sortmeta: "list[Tracking3DMetadatum]",
ego_meta: "list[CameraConfig]",
segment_mapping_meta: "list[SegmentTrajectoryMetadatum] | None" = None,
base=None,
) -> "dict[str, list[tuple[Tracking3DResult, CameraConfig, SegmentPoint | None]]]":
trajectories: "dict[str, list[tuple[Tracking3DResult, CameraConfig, SegmentPoint | None]]]" = {}
for i in range(len(sortmeta)):
frame = sortmeta[i]
for obj_id, tracking_result in frame.items():
if obj_id not in trajectories:
trajectories[obj_id] = []
associated_ego_info = ego_meta[i]
associated_segment_mapping = associate_segment_mapping(
tracking_result, segment_mapping_meta
)
trajectories[obj_id].append(
(tracking_result, associated_ego_info, associated_segment_mapping)
)

for trajectory in trajectories.values():
last = len(trajectory) - 1
for i, t in enumerate(trajectory):
if i > 0:
t[0].prev = trajectory[i - 1][0]
if i < last:
t[0].next = trajectory[i + 1][0]
return trajectories
Loading

0 comments on commit 4ed842b

Please sign in to comment.