Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
# Testing
.pytest_cache/
.coverage
htmlcov/
coverage.xml
.tox/
.nox/

# Claude settings
.claude/

# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# Virtual environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# IDEs
.vscode/
.idea/
*.swp
*.swo
*~

# OS
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db

# Jupyter
.ipynb_checkpoints

# MyPy
.mypy_cache/
.dmypy.json
dmypy.json

# Logs
*.log
2,494 changes: 2,494 additions & 0 deletions poetry.lock

Large diffs are not rendered by default.

73 changes: 73 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
[tool.poetry]
name = "structvio"
version = "0.1.0"
description = "StructVIO Visual-inertial Odometry with Structural Regularity"
authors = ["Your Name <your.email@example.com>"]
readme = "README.md"
packages = [{include = "scripts"}]

[tool.poetry.dependencies]
python = "^3.8"
numpy = "^1.20.0"
evo = "^1.12.0"

[tool.poetry.group.dev.dependencies]
pytest = "^7.4.0"
pytest-cov = "^4.1.0"
pytest-mock = "^3.11.1"

[tool.poetry.scripts]

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

[tool.pytest.ini_options]
testpaths = ["tests"]
python_files = ["test_*.py", "*_test.py"]
python_classes = ["Test*"]
python_functions = ["test_*"]
addopts = [
"--strict-markers",
"--strict-config",
"--verbose",
"--cov=scripts",
"--cov-report=term-missing",
"--cov-report=html:htmlcov",
"--cov-report=xml:coverage.xml",
"--cov-fail-under=80"
]
markers = [
"unit: marks tests as unit tests (fast)",
"integration: marks tests as integration tests (slow)",
"slow: marks tests as slow tests"
]

[tool.coverage.run]
source = ["scripts"]
omit = [
"*/tests/*",
"*/venv/*",
"*/.venv/*",
"*/site-packages/*",
"*/__pycache__/*"
]

[tool.coverage.report]
exclude_lines = [
"pragma: no cover",
"def __repr__",
"if self.debug:",
"if settings.DEBUG",
"raise AssertionError",
"raise NotImplementedError",
"if 0:",
"if __name__ == .__main__.:",
"class .*\\bProtocol\\):",
"@(abc\\.)?abstractmethod"
]
show_missing = true
precision = 2

[tool.coverage.html]
directory = "htmlcov"
Empty file added tests/__init__.py
Empty file.
110 changes: 110 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
"""
Shared pytest fixtures for the StructVIO testing suite.
"""
import tempfile
import shutil
import os
from pathlib import Path
import pytest
import numpy as np


@pytest.fixture
def temp_dir():
"""Create a temporary directory that is cleaned up after the test."""
temp_path = tempfile.mkdtemp()
yield Path(temp_path)
shutil.rmtree(temp_path)


@pytest.fixture
def sample_data_dir(temp_dir):
"""Create a sample data directory with test files."""
data_dir = temp_dir / "sample_data"
data_dir.mkdir()
return data_dir


@pytest.fixture
def mock_structvio_output():
"""Generate mock StructVIO output data for testing."""
return [
"# timestamp_sec timestamp_nsec frame_id tx ty tz qx qy qz qw vx vy vz bax bay baz bgx bgy bgz",
"0 100000000 1 0.0 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0",
"0 200000000 2 0.1 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0",
"0 300000000 3 0.2 0.0 0.0 0.0 0.0 0.0 1.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0 0.0"
]


@pytest.fixture
def mock_euroc_groundtruth():
"""Generate mock EuRoC groundtruth data for testing."""
return [
"#timestamp,p_RS_R_x [m],p_RS_R_y [m],p_RS_R_z [m],q_RS_w [],q_RS_x [],q_RS_y [],q_RS_z []",
"1403636579763555584,5.717570e-01,-1.110223e-16,8.200000e-02,6.123233995736766e-17,1.000000e+00,0.000000e+00,0.000000e+00",
"1403636579813555456,5.717570e-01,-2.220446e-16,8.200000e-02,6.123233995736766e-17,1.000000e+00,0.000000e+00,0.000000e+00"
]


@pytest.fixture
def mock_tum_trajectory():
"""Generate mock TUM trajectory data for testing."""
return [
"# timestamp tx ty tz qx qy qz qw",
"1403636579.763555584 0.5717570 0.0 0.082 0.0 0.0 0.0 1.0",
"1403636579.813555456 0.5717570 0.0 0.082 0.0 0.0 0.0 1.0"
]


@pytest.fixture
def mock_trajectory_file(temp_dir, mock_structvio_output):
"""Create a mock trajectory file for testing."""
trajectory_file = temp_dir / "test_trajectory.txt"
with open(trajectory_file, 'w') as f:
f.write('\n'.join(mock_structvio_output))
return trajectory_file


@pytest.fixture
def mock_groundtruth_file(temp_dir, mock_euroc_groundtruth):
"""Create a mock groundtruth file for testing."""
gt_file = temp_dir / "groundtruth.csv"
with open(gt_file, 'w') as f:
f.write('\n'.join(mock_euroc_groundtruth))
return gt_file


@pytest.fixture
def mock_numpy_arrays():
"""Provide mock numpy arrays for testing mathematical operations."""
return {
'positions': np.array([[0.0, 0.0, 0.0], [0.1, 0.0, 0.0], [0.2, 0.0, 0.0]]),
'orientations': np.array([[1.0, 0.0, 0.0, 0.0], [1.0, 0.0, 0.0, 0.0], [1.0, 0.0, 0.0, 0.0]]),
'timestamps': np.array([0.1, 0.2, 0.3])
}


@pytest.fixture
def original_cwd():
"""Preserve and restore the current working directory."""
original_dir = os.getcwd()
yield original_dir
os.chdir(original_dir)


@pytest.fixture
def empty_file(temp_dir):
"""Create an empty file for testing file operations."""
empty_file_path = temp_dir / "empty.txt"
empty_file_path.touch()
return empty_file_path


@pytest.fixture
def invalid_trajectory_file(temp_dir):
"""Create an invalid trajectory file for error testing."""
invalid_file = temp_dir / "invalid_trajectory.txt"
with open(invalid_file, 'w') as f:
f.write("This is not valid trajectory data\n")
f.write("123 abc def\n")
return invalid_file
Empty file added tests/integration/__init__.py
Empty file.
Loading