Skip to content

Commit 9c6c60c

Browse files
committed
remove-acados-cython
1 parent 88a4d10 commit 9c6c60c

11 files changed

Lines changed: 107 additions & 1271 deletions

File tree

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import os
2+
import sys
3+
import ctypes
4+
import platform
5+
6+
def get_acados_dir():
7+
# current file: openpilot/selfdrive/controls/lib/acados_setup.py
8+
# acados is at openpilot/third_party/acados
9+
current_dir = os.path.dirname(os.path.abspath(__file__))
10+
op_dir = os.path.abspath(os.path.join(current_dir, '..', '..', '..'))
11+
return os.path.join(op_dir, 'third_party', 'acados')
12+
13+
def get_acados_lib_path():
14+
acados_dir = get_acados_dir()
15+
if sys.platform.startswith('linux'):
16+
machine = platform.machine()
17+
if machine == 'x86_64':
18+
return os.path.join(acados_dir, 'x86_64', 'lib')
19+
elif machine == 'aarch64':
20+
return os.path.join(acados_dir, 'larch64', 'lib')
21+
elif sys.platform.startswith('darwin'):
22+
return os.path.join(acados_dir, 'Darwin', 'lib')
23+
24+
# Fallback
25+
return os.path.join(acados_dir, 'x86_64', 'lib')
26+
27+
def acados_preload():
28+
lib_path = get_acados_lib_path()
29+
if not os.path.exists(lib_path):
30+
return
31+
32+
if sys.platform.startswith('linux'):
33+
libs = ['libblasfeo.so', 'libhpipm.so', 'libqpOASES_e.so.3.1']
34+
mode = ctypes.RTLD_GLOBAL
35+
elif sys.platform.startswith('darwin'):
36+
libs = ['libblasfeo.dylib', 'libhpipm.dylib', 'libqpOASES_e.3.1.dylib']
37+
mode = ctypes.RTLD_GLOBAL
38+
else:
39+
libs = []
40+
mode = 0
41+
42+
for lib in libs:
43+
full_path = os.path.join(lib_path, lib)
44+
if os.path.exists(full_path):
45+
try:
46+
ctypes.CDLL(full_path, mode=mode)
47+
except OSError:
48+
pass
49+
50+
def prepare_acados_ocp_json(json_file):
51+
import json
52+
import tempfile
53+
54+
with open(json_file) as f:
55+
data = json.load(f)
56+
57+
data['acados_lib_path'] = get_acados_lib_path()
58+
59+
fd, path = tempfile.mkstemp(suffix='.json', text=True)
60+
with os.fdopen(fd, 'w') as f:
61+
json.dump(data, f, indent=4)
62+
63+
return path

selfdrive/controls/lib/lateral_mpc_lib/SConscript

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Import('env', 'envCython', 'arch', 'msgq_python', 'common_python', 'np_version')
1+
Import('env', 'arch', 'msgq_python', 'common_python', 'np_version')
22

33
gen = "c_generated_code"
44

@@ -75,23 +75,3 @@ else:
7575
lib_solver = lenv.SharedLibrary(f"{gen}/acados_ocp_solver_lat",
7676
build_files,
7777
LIBS=['m', 'acados', 'hpipm', 'blasfeo', 'qpOASES_e'])
78-
79-
# generate cython stuff
80-
acados_ocp_solver_pyx = File("#third_party/acados/acados_template/acados_ocp_solver_pyx.pyx")
81-
acados_ocp_solver_common = File("#third_party/acados/acados_template/acados_solver_common.pxd")
82-
libacados_ocp_solver_pxd = File(f'{gen}/acados_solver.pxd')
83-
libacados_ocp_solver_c = File(f'{gen}/acados_ocp_solver_pyx.c')
84-
85-
lenv2 = envCython.Clone()
86-
lenv2["LIBPATH"] += [lib_solver[0].dir.abspath]
87-
lenv2["RPATH"] += [lenv2.Literal('\\$$ORIGIN')]
88-
lenv2.Command(libacados_ocp_solver_c,
89-
[acados_ocp_solver_pyx, acados_ocp_solver_common, libacados_ocp_solver_pxd],
90-
f'cython' + \
91-
f' -o {libacados_ocp_solver_c.get_labspath()}' + \
92-
f' -I {libacados_ocp_solver_pxd.get_dir().get_labspath()}' + \
93-
f' -I {acados_ocp_solver_common.get_dir().get_labspath()}' + \
94-
f' {acados_ocp_solver_pyx.get_labspath()}')
95-
lib_cython = lenv2.Program(f'{gen}/acados_ocp_solver_pyx.so', [libacados_ocp_solver_c], LIBS=['acados_ocp_solver_lat'])
96-
lenv2.Depends(lib_cython, lib_solver)
97-
lenv2.Depends(libacados_ocp_solver_c, np_version)

selfdrive/controls/lib/lateral_mpc_lib/lat_mpc.py

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,8 @@
77
# WARNING: imports outside of constants will not trigger a rebuild
88
from openpilot.selfdrive.modeld.constants import ModelConstants
99

10-
if __name__ == '__main__': # generating code
11-
from openpilot.third_party.acados.acados_template import AcadosModel, AcadosOcp, AcadosOcpSolver
12-
else:
13-
from openpilot.selfdrive.controls.lib.lateral_mpc_lib.c_generated_code.acados_ocp_solver_pyx import AcadosOcpSolverCython
10+
from openpilot.third_party.acados.acados_template import AcadosModel, AcadosOcp, AcadosOcpSolver
11+
from openpilot.selfdrive.controls.lib.acados_setup import acados_preload, prepare_acados_ocp_json
1412

1513
LAT_MPC_DIR = os.path.dirname(os.path.abspath(__file__))
1614
EXPORT_DIR = os.path.join(LAT_MPC_DIR, "c_generated_code")
@@ -132,7 +130,14 @@ class LateralMpc:
132130
def __init__(self, x0=None):
133131
if x0 is None:
134132
x0 = np.zeros(X_DIM)
135-
self.solver = AcadosOcpSolverCython(MODEL_NAME, ACADOS_SOLVER_TYPE, N)
133+
acados_preload()
134+
# Fixup JSON for current architecture
135+
json_path = prepare_acados_ocp_json(JSON_FILE)
136+
try:
137+
self.solver = AcadosOcpSolver(gen_lat_ocp(), json_file=json_path, generate=False, build=False)
138+
finally:
139+
if os.path.exists(json_path):
140+
os.remove(json_path)
136141
self.reset(x0)
137142

138143
def reset(self, x0=None):
@@ -196,4 +201,4 @@ def run(self, x0, p, y_pts, heading_pts, yaw_rate_pts):
196201
if __name__ == "__main__":
197202
ocp = gen_lat_ocp()
198203
AcadosOcpSolver.generate(ocp, json_file=JSON_FILE)
199-
# AcadosOcpSolver.build(ocp.code_export_directory, with_cython=True)
204+

selfdrive/controls/lib/longitudinal_mpc_lib/SConscript

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Import('env', 'envCython', 'arch', 'msgq_python', 'common_python', 'pandad_python', 'np_version')
1+
Import('env', 'arch', 'msgq_python', 'common_python', 'pandad_python', 'np_version')
22

33
gen = "c_generated_code"
44

@@ -80,23 +80,3 @@ else:
8080
lib_solver = lenv.SharedLibrary(f"{gen}/acados_ocp_solver_long",
8181
build_files,
8282
LIBS=['m', 'acados', 'hpipm', 'blasfeo', 'qpOASES_e'])
83-
84-
# generate cython stuff
85-
acados_ocp_solver_pyx = File("#third_party/acados/acados_template/acados_ocp_solver_pyx.pyx")
86-
acados_ocp_solver_common = File("#third_party/acados/acados_template/acados_solver_common.pxd")
87-
libacados_ocp_solver_pxd = File(f'{gen}/acados_solver.pxd')
88-
libacados_ocp_solver_c = File(f'{gen}/acados_ocp_solver_pyx.c')
89-
90-
lenv2 = envCython.Clone()
91-
lenv2["LIBPATH"] += [lib_solver[0].dir.abspath]
92-
lenv2["RPATH"] += [lenv2.Literal('\\$$ORIGIN')]
93-
lenv2.Command(libacados_ocp_solver_c,
94-
[acados_ocp_solver_pyx, acados_ocp_solver_common, libacados_ocp_solver_pxd],
95-
f'cython' + \
96-
f' -o {libacados_ocp_solver_c.get_labspath()}' + \
97-
f' -I {libacados_ocp_solver_pxd.get_dir().get_labspath()}' + \
98-
f' -I {acados_ocp_solver_common.get_dir().get_labspath()}' + \
99-
f' {acados_ocp_solver_pyx.get_labspath()}')
100-
lib_cython = lenv2.Program(f'{gen}/acados_ocp_solver_pyx.so', [libacados_ocp_solver_c], LIBS=['acados_ocp_solver_long'])
101-
lenv2.Depends(lib_cython, lib_solver)
102-
lenv2.Depends(libacados_ocp_solver_c, np_version)

selfdrive/controls/lib/longitudinal_mpc_lib/long_mpc.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,8 @@
1010
from openpilot.selfdrive.modeld.constants import index_function
1111
from openpilot.selfdrive.controls.radard import _LEAD_ACCEL_TAU
1212

13-
if __name__ == '__main__': # generating code
14-
from openpilot.third_party.acados.acados_template import AcadosModel, AcadosOcp, AcadosOcpSolver
15-
else:
16-
from openpilot.selfdrive.controls.lib.longitudinal_mpc_lib.c_generated_code.acados_ocp_solver_pyx import AcadosOcpSolverCython
13+
from openpilot.third_party.acados.acados_template import AcadosModel, AcadosOcp, AcadosOcpSolver
14+
from openpilot.selfdrive.controls.lib.acados_setup import acados_preload, prepare_acados_ocp_json
1715

1816
from casadi import SX, vertcat
1917

@@ -225,12 +223,17 @@ class LongitudinalMpc:
225223
def __init__(self, mode='acc', dt=DT_MDL):
226224
self.mode = mode
227225
self.dt = dt
228-
self.solver = AcadosOcpSolverCython(MODEL_NAME, ACADOS_SOLVER_TYPE, N)
226+
acados_preload()
227+
json_path = prepare_acados_ocp_json(JSON_FILE)
228+
try:
229+
self.solver = AcadosOcpSolver(gen_long_ocp(), json_file=json_path, generate=False, build=False)
230+
finally:
231+
if os.path.exists(json_path):
232+
os.remove(json_path)
229233
self.reset()
230234
self.source = SOURCES[2]
231235

232236
def reset(self):
233-
# self.solver = AcadosOcpSolverCython(MODEL_NAME, ACADOS_SOLVER_TYPE, N)
234237
self.solver.reset()
235238
# self.solver.options_set('print_level', 2)
236239
self.v_solution = np.zeros(N+1)
@@ -454,4 +457,3 @@ def run(self):
454457
if __name__ == "__main__":
455458
ocp = gen_long_ocp()
456459
AcadosOcpSolver.generate(ocp, json_file=JSON_FILE)
457-
# AcadosOcpSolver.build(ocp.code_export_directory, with_cython=True)
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import os
2+
import sys
3+
import platform
4+
from openpilot.selfdrive.controls.lib.acados_setup import get_acados_lib_path, get_acados_dir
5+
6+
def test_get_acados_lib_path_linux_x86_64(monkeypatch):
7+
monkeypatch.setattr(sys, 'platform', 'linux')
8+
monkeypatch.setattr(platform, 'machine', lambda: 'x86_64')
9+
expected = os.path.join(get_acados_dir(), 'x86_64', 'lib')
10+
assert get_acados_lib_path() == expected
11+
12+
def test_get_acados_lib_path_linux_aarch64(monkeypatch):
13+
monkeypatch.setattr(sys, 'platform', 'linux')
14+
monkeypatch.setattr(platform, 'machine', lambda: 'aarch64')
15+
expected = os.path.join(get_acados_dir(), 'larch64', 'lib')
16+
assert get_acados_lib_path() == expected
17+
18+
def test_get_acados_lib_path_darwin(monkeypatch):
19+
monkeypatch.setattr(sys, 'platform', 'darwin')
20+
expected = os.path.join(get_acados_dir(), 'Darwin', 'lib')
21+
assert get_acados_lib_path() == expected

0 commit comments

Comments
 (0)