Skip to content

Commit 44d78c7

Browse files
Add cmake support, use setuptools, add python3.8 support
1 parent 7fddc8e commit 44d78c7

File tree

6 files changed

+219
-28
lines changed

6 files changed

+219
-28
lines changed

FORK.md

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
# Why we forked it
2+
3+
## Motivation
4+
5+
1. Don't use scons as the build tool
6+
2. Support python3.8
7+
3. Better distribute package
8+
9+
| change | description |
10+
| --------------------------------- | ---------------------------------------------------- |
11+
| `rednose/helpers/kalmanfilter.py` | Update typehint to use python3.8 compatible syntax |
12+
| `setup.py`, `pyproject.toml` | Use setuptools to build and package instead of scons |
13+
14+
## Packaging the Library
15+
16+
```bash
17+
# to build a wheel
18+
python -m build --wheel
19+
```
20+
21+
### What is packaged
22+
23+
```
24+
.
25+
├── __init__.py
26+
├── helpers
27+
│   ├── __init__.py
28+
│   ├── chi2_lookup_table.npy
29+
│   ├── chi2_lookup.py
30+
│   ├── common_ekf.cc
31+
│   ├── common_ekf.h
32+
│   ├── ekf_load.cc
33+
│   ├── ekf_load.h
34+
│   ├── ekf_sym_pyx.cpp
35+
│   ├── ekf_sym_pyx.cpython-38-darwin.so
36+
│   ├── ekf_sym_pyx.pyx
37+
│   ├── ekf_sym.cc
38+
│   ├── ekf_sym.h
39+
│   ├── ekf_sym.py
40+
│   ├── ekf.h
41+
│   ├── feature_handler.py
42+
│   ├── kalmanfilter.py
43+
│   ├── lst_sq_computer.py
44+
│   └── sympy_helpers.py
45+
├── logger
46+
│   └── logger.h
47+
└── templates
48+
├── __init__.py
49+
├── compute_pos.c
50+
├── ekf_c.c
51+
└── feature_handler.c
52+
```
53+
54+
- instead making users recompile the library `ekf_sym.cc` and `ekf_load.cc`, I think we can just ship a shared lib.
55+
this way we only need to ship the headers, the pyx ext, and the python source
56+
57+
## Using the library
58+
59+
The wheel packages c++ source, the compiled cython extension, and python library to generate code for new filters.
60+
To use the library, you must:
61+
62+
1. define the filter in python
63+
2. run the code generation step
64+
3. compile the generated code
65+
66+
```bash
67+
# example on mac
68+
export REDNOSE_ROOT=.venv/lib/python3.8/site-packages
69+
clang++ -std=c++17 \
70+
-I $REDNOSE_ROOT/rednose/helpers \
71+
-I $REDNOSE_ROOT/rednose \
72+
-I $REDNOSE_ROOT \
73+
-I /opt/homebrew/include \
74+
generated/kinematic.cpp \
75+
$REDNOSE_ROOT/rednose/helpers/ekf_load.cc \
76+
$REDNOSE_ROOT/rednose/helpers/ekf_sym.cc \
77+
-dynamiclib -o generated/libkinematic.dylib
78+
79+
# linux
80+
```
81+
82+
export REDNOSE_ROOT=.venv/lib/python3.8/site-packages
83+
g++ -std=c++17 -fPIC \
84+
-I $REDNOSE_ROOT/rednose/helpers \
85+
-I $REDNOSE_ROOT/rednose \
86+
-I $REDNOSE_ROOT \
87+
generated/kinematic.cpp \
88+
$REDNOSE_ROOT/rednose/helpers/ekf_load.cc \
89+
$REDNOSE_ROOT/rednose/helpers/ekf_sym.cc \
90+
-shared -o generated/libkinematic.so
91+
92+
```
93+
94+
This library ships a compiled cythone extension that will dynamically load an arbitrary filter at runtime. For a new
95+
filter, you are building the shared library that will be loaded.
96+
97+
### Depedencies
98+
99+
1. eigen
100+
```

MANIFEST.in

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
include LICENSE
2+
include README.*
3+
recursive-include cmake/*.cmake
4+
recursive-include rednose/templates *.c
5+
recursive-include rednose *.pyx *.pxd *.h *.hpp *.cc *.cpp *.npy
6+
global-exclude *.py[cod] __pycache__ *.so

pyproject.toml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
11
# https://beta.ruff.rs/docs/configuration/#using-pyprojecttoml
22
[tool.ruff]
33
line-length = 160
4-
target-version="py311"
4+
target-version = "py311"
55

66
[tool.ruff.lint]
77
select = ["E", "F", "W", "PIE", "C4", "ISC", "RUF100", "A"]
88
ignore = ["W292", "E741", "E402", "C408", "ISC003"]
9-
flake8-implicit-str-concat.allow-multiline=false
9+
flake8-implicit-str-concat.allow-multiline = false
1010

1111
[tool.ruff.lint.flake8-tidy-imports.banned-api]
1212
"pytest.main".msg = "pytest.main requires special handling that is easy to mess up!"
1313
"unittest".msg = "Use pytest"
1414

1515
[tool.pytest.ini_options]
1616
addopts = "--durations=10 -n auto"
17+
18+
[build-system]
19+
requires = ["setuptools>=68", "wheel", "cython>=3.0", "numpy>=1.21"]
20+
build-backend = "setuptools.build_meta"

rednose/cmake/compile-filter.cmake

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Pretty ugly but meant to be an easy way to build rednose filters. Process is as follows:
2+
# 1) Use python filter defintion to generate C++ source
3+
# 2) Compile that C++ source into a shared library
4+
function(build_rednose_filter REDNOSE_ROOT FILTER_NAME FILTER_SOURCE GENERATED_FOLDER)
5+
6+
# 1) code gen
7+
message(STATUS "Code-generating filter ${FILTER_NAME} from ${FILTER_SOURCE} into ${GENERATED_FOLDER}")
8+
execute_process(
9+
COMMAND ${Python3_EXECUTABLE} ${CMAKE_SOURCE_DIR}/${FILTER_SOURCE} t ${GENERATED_FOLDER}
10+
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
11+
)
12+
13+
# 2) compile lib
14+
add_library(${FILTER_NAME} SHARED
15+
${GENERATED_FOLDER}/${FILTER_NAME}.cpp
16+
${REDNOSE_ROOT}/rednose/helpers/ekf_load.cc
17+
${REDNOSE_ROOT}/rednose/helpers/ekf_sym.cc
18+
)
19+
20+
target_include_directories(${FILTER_NAME}
21+
PRIVATE
22+
${REDNOSE_ROOT}
23+
${REDNOSE_ROOT}/rednose
24+
${REDNOSE_ROOT}/rednose/helpers
25+
)
26+
27+
set_target_properties(${FILTER_NAME} PROPERTIES
28+
POSITION_INDEPENDENT_CODE ON
29+
LIBRARY_OUTPUT_DIRECTORY ${GENERATED_FOLDER}
30+
OUTPUT_NAME ${FILTER_NAME}
31+
)
32+
33+
# Link against dl for dynamic loading
34+
target_link_libraries(${FILTER_NAME} PRIVATE ${CMAKE_DL_LIBS})
35+
36+
# On ELF platforms, catch unresolved symbols at link time (optional but helpful)
37+
if(UNIX AND NOT APPLE)
38+
target_link_options(${FILTER_NAME} PRIVATE "-Wl,--no-undefined")
39+
endif()
40+
endfunction()

rednose/helpers/kalmanfilter.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Any
1+
from typing import Any, Dict
22

33
import numpy as np
44

@@ -8,7 +8,7 @@ class KalmanFilter:
88
initial_x = np.zeros((0, 0))
99
initial_P_diag = np.zeros((0, 0))
1010
Q = np.zeros((0, 0))
11-
obs_noise: dict[int, Any] = {}
11+
obs_noise: Dict[int, Any] = {}
1212

1313
# Should be initialized when initializating a KalmanFilter implementation
1414
filter = None

setup.py

Lines changed: 65 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,70 @@
11
import os
2-
from setuptools import setup, find_packages
2+
import platform
3+
from setuptools import setup, Extension, find_packages
4+
from Cython.Build import cythonize
5+
import numpy
6+
7+
8+
extra_compile_args = ["-O3", "-std=c++17"]
9+
extra_link_args = []
10+
include_dirs = [".", "rednose", numpy.get_include()]
11+
12+
if platform.system() == "Darwin":
13+
extra_compile_args += ["-stdlib=libc++"]
14+
extra_link_args += ["-stdlib=libc++"]
15+
include_dirs += ["/opt/homebrew/include"]
16+
17+
# debug
18+
if os.environ.get("DEBUG"):
19+
extra_compile_args += ["-O0", "-g3"]
20+
extra_link_args += ["-g"]
21+
22+
23+
extensions = [
24+
Extension(
25+
name="rednose.helpers.ekf_sym_pyx",
26+
sources=[
27+
"rednose/helpers/ekf_sym_pyx.pyx", # Cython
28+
"rednose/helpers/ekf_sym.cc", # your C++
29+
"rednose/helpers/ekf_load.cc", # your C++
30+
],
31+
include_dirs=include_dirs,
32+
language="c++",
33+
extra_compile_args=extra_compile_args,
34+
extra_link_args=extra_link_args,
35+
)
36+
]
337

4-
here = os.path.abspath(os.path.dirname(__file__))
538

639
setup(
7-
name='rednose',
8-
version='0.0.1',
9-
url='https://github.com/commaai/rednose',
10-
author='comma.ai',
11-
author_email='harald@comma.ai',
12-
packages=find_packages(),
13-
platforms='any',
14-
license='MIT',
15-
package_data={'': ['helpers/chi2_lookup_table.npy', 'templates/*']},
16-
install_requires=[
17-
'numpy',
18-
'cffi',
19-
'sympy',
20-
],
21-
extras_require={
22-
'dev': [
23-
'scipy',
24-
],
25-
},
26-
ext_modules=[],
27-
description="Kalman filter library",
28-
long_description='See https://github.com/commaai/rednose',
40+
name="rednose",
41+
version="0.0.1",
42+
url="https://github.com/commaai/rednose",
43+
author="comma.ai",
44+
author_email="harald@comma.ai",
45+
packages=find_packages(),
46+
platforms="any",
47+
license="MIT",
48+
include_package_data=True,
49+
package_data={
50+
"rednose.helpers": ["chi2_lookup_table.npy"],
51+
"rednose.templates": ["*.c"],
52+
"rednose": ["cmake/*.cmake"]
53+
},
54+
install_requires=["numpy", "cffi", "sympy"],
55+
extras_require={"dev": ["scipy"]},
56+
description="Kalman filter library",
57+
long_description="See https://github.com/commaai/rednose",
58+
ext_modules=cythonize(
59+
extensions,
60+
language_level=3,
61+
annotate=False,
62+
compiler_directives={
63+
"boundscheck": False,
64+
"wraparound": False,
65+
"cdivision": True,
66+
"binding": True,
67+
"language_level": 3,
68+
},
69+
),
2970
)

0 commit comments

Comments
 (0)