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
5 changes: 5 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
recursive-include rednose/helpers *.h *.cc *.pyx *.pxd
recursive-include rednose/templates *
include rednose/helpers/chi2_lookup_table.npy
include rednose/site_scons/rednose_filter.py
recursive-include rednose/logger *.h
40 changes: 27 additions & 13 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,16 +1,30 @@
# https://beta.ruff.rs/docs/configuration/#using-pyprojecttoml
[tool.ruff]
line-length = 160
target-version="py311"
[project]
name = "rednose"
version = "0.1.0"
description = "Kalman filter library"
requires-python = ">=3.11,<3.13"
license = {text = "MIT"}
authors = [{name = "comma.ai"}]
dependencies = [
"numpy",
"cffi",
"sympy",
"scons",
"Cython",
]

[tool.ruff.lint]
select = ["E", "F", "W", "PIE", "C4", "ISC", "RUF100", "A"]
ignore = ["W292", "E741", "E402", "C408", "ISC003"]
flake8-implicit-str-concat.allow-multiline=false
[project.optional-dependencies]
dev = ["scipy", "pytest", "pytest-xdist", "ruff"]

[tool.ruff.lint.flake8-tidy-imports.banned-api]
"pytest.main".msg = "pytest.main requires special handling that is easy to mess up!"
"unittest".msg = "Use pytest"
[build-system]
requires = ["setuptools", "Cython", "numpy"]
build-backend = "setuptools.build_meta"

[tool.pytest.ini_options]
addopts = "--durations=10 -n auto"
[tool.setuptools]
include-package-data = true

[tool.setuptools.package-data]
"rednose.helpers" = ["chi2_lookup_table.npy", "*.h", "*.cc", "*.pyx", "*.pxd"]
"rednose.logger" = ["*.h"]
"rednose.templates" = ["*"]
"rednose.site_scons" = ["*.py"]
8 changes: 8 additions & 0 deletions rednose/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import os

BASEDIR = os.path.dirname(os.path.abspath(__file__))
HELPERS_PATH = os.path.join(BASEDIR, "helpers")
TEMPLATE_DIR = os.path.join(BASEDIR, "templates")
# For consumers that need the parent dir in include paths
INCLUDE_PATH = os.path.abspath(os.path.join(BASEDIR, "../"))
SITE_SCONS_TOOLS = os.path.join(BASEDIR, "site_scons")
Empty file added rednose/logger/__init__.py
Empty file.
Empty file added rednose/site_scons/__init__.py
Empty file.
48 changes: 48 additions & 0 deletions rednose/site_scons/rednose_filter.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import platform

from SCons.Script import Dir, File


def compile_single_filter(env, target, filter_gen_script, output_dir, extra_gen_artifacts, script_deps):
generated_src_files = [File(f) for f in [f'{output_dir}/{target}.cpp', f'{output_dir}/{target}.h']]
extra_generated_files = [File(f'{output_dir}/{x}') for x in extra_gen_artifacts]
generator_file = File(filter_gen_script)

env.Command(generated_src_files + extra_generated_files,
[generator_file] + script_deps, f"{File(generator_file).relpath} {target} {Dir(output_dir).relpath}")

generated_cc_file = File(generated_src_files[:1])

return generated_cc_file


class BaseRednoseCompileMethod:
def __init__(self, base_py_deps, base_cc_deps):
self.base_py_deps = base_py_deps
self.base_cc_deps = base_cc_deps


class CompileFilterMethod(BaseRednoseCompileMethod):
def __call__(self, env, target, filter_gen_script, output_dir, extra_gen_artifacts=[], gen_script_deps=[]):
objects = compile_single_filter(env, target, filter_gen_script, output_dir, extra_gen_artifacts, self.base_py_deps + gen_script_deps)
linker_flags = env.get("LINKFLAGS", [])
if platform.system() == "Darwin":
linker_flags = ["-undefined", "dynamic_lookup"]
lib_target = env.SharedLibrary(f'{output_dir}/{target}', [self.base_cc_deps, objects], LINKFLAGS=linker_flags)

return lib_target


def generate(env):
templates = env.Glob("$REDNOSE_ROOT/rednose/templates/*")
sympy_helpers = env.File("$REDNOSE_ROOT/rednose/helpers/sympy_helpers.py")
ekf_sym = env.File("$REDNOSE_ROOT/rednose/helpers/ekf_sym.py")

gen_script_deps = templates + [sympy_helpers, ekf_sym]
filter_lib_deps = []

env.AddMethod(CompileFilterMethod(gen_script_deps, filter_lib_deps), "RednoseCompileFilter")


def exists(env):
return True
71 changes: 45 additions & 26 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,48 @@
import os
from setuptools import setup, find_packages
import subprocess
import platform
import numpy as np
from setuptools import setup
from Cython.Build import cythonize
from setuptools import Extension

here = os.path.abspath(os.path.dirname(__file__))
rednose_dir = os.path.dirname(os.path.abspath(__file__))

setup(
name='rednose',
version='0.0.1',
url='https://github.com/commaai/rednose',
author='comma.ai',
author_email='harald@comma.ai',
packages=find_packages(),
platforms='any',
license='MIT',
package_data={'': ['helpers/chi2_lookup_table.npy', 'templates/*']},
install_requires=[
'numpy',
'cffi',
'sympy',
],
extras_require={
'dev': [
'scipy',
],
},
ext_modules=[],
description="Kalman filter library",
long_description='See https://github.com/commaai/rednose',
)
cpp_args = ["-std=c++17", "-fPIC", "-O2"]

# Find eigen include path
eigen_include = []
if platform.system() == "Darwin":
try:
brew_prefix = subprocess.check_output(['brew', '--prefix'], encoding='utf8').strip()
eigen_include = [os.path.join(brew_prefix, 'include')]
except (subprocess.CalledProcessError, FileNotFoundError):
pass
else:
# Standard Linux locations
for p in ['/usr/include', '/usr/local/include']:
if os.path.isdir(os.path.join(p, 'eigen3')):
eigen_include = [p]
break

extensions = [
Extension(
"rednose.helpers.ekf_sym_pyx",
sources=[
"rednose/helpers/ekf_sym_pyx.pyx",
"rednose/helpers/ekf_load.cc",
"rednose/helpers/ekf_sym.cc",
],
language="c++",
extra_compile_args=cpp_args,
include_dirs=[
rednose_dir, # for "rednose/helpers/..." includes
os.path.join(rednose_dir, "rednose"), # for "logger/logger.h" includes
os.path.join(rednose_dir, "rednose", "helpers"), # for local includes like "ekf_sym.h"
np.get_include(),
] + eigen_include,
libraries=["dl"],
),
]

setup(ext_modules=cythonize(extensions, language_level="3"))
Loading