FEATURED · 精选文章

【algorithm】Acado 实战使用车辆横纵的控制

发布时间 / 2026/8/21 12:31:27
来源 / 创域科博编辑部
栏目 / 资讯中心
【algorithm】Acado 实战使用车辆横纵的控制 目录前提正文官网教程我的目录和生成器说明目录和文件生成器说明横纵控制模型前提本文是之前acado使用的后续文章使用了简单的车辆运动学来说明acado 如何使用generator生成代码并被调用这一模块是在自动驾驶公司量产基于MPC控制使用的过的模型之前的基础使用和说明见https://blog.csdn.net/weixin_46479223/article/details/133743263?spm1011.2415.3001.5331正文官网教程在描述基于车辆模型的例子之前用一个针对acado使用的训练例子来重点记录使用流程当然可以按照官方教程中的例子来看一下如何使用在acado文件夹下有个教程doc文件夹子编译一下可以生成html格式和官网一样的教程本地使用。如下图展示。官网针对生成器有很详细的说明,但这里我们我的目录和生成器说明目录和文件tree -L 3 如下这里的 src_codegen 是我建立的使用生成器的例子和本次例子相关的文件额外截图标记如下图├── build │ ├── CMakeCache.txt │ ├── CMakeFiles │ │ ├──3.28.3│ │ ├── cmake.check_cache │ │ ├── CMakeConfigureLog.yaml │ │ ├── CMakeDirectoryInformation.cmake │ │ ├── main.dir │ │ ├── Makefile2 │ │ ├── Makefile.cmake │ │ ├── MyACADOProject_2obj.dir │ │ ├── MyACADOProject_codegen.dir │ │ ├── MyACADOProject.dir │ │ ├── MyACADOProject_mpcclose.dir │ │ ├── MyACADOProject_mpc.dir │ │ ├── MyACADOProject_racket.dir │ │ ├── pkgRedirects │ │ ├── progress.marks │ │ └── TargetDirectories.txt │ ├── cmake_install.cmake │ ├── export_mpcclose │ │ ├── acado_auxiliary_functions.c │ │ ├── acado_auxiliary_functions.h │ │ ├── acado_auxiliary_functions.o │ │ ├── acado_common.h │ │ ├── acado_integrator.c │ │ ├── acado_integrator.o │ │ ├── acado_qpoases_interface.cpp │ │ ├── acado_qpoases_interface.hpp │ │ ├── acado_qpoases_interface.o │ │ ├── acado_solver.c │ │ ├── acado_solver.o │ │ ├── libacado_exported_rti.a │ │ ├── Makefile │ │ ├── qpoases │ │ ├── test │ │ ├── test.c │ │ └── test.o │ ├── Makefile │ ├── mpc_plot.plt │ ├── MyACADOProject │ ├── MyACADOProject_2obj │ ├── MyACADOProject_codegen │ ├── MyACADOProject_mpc │ ├── MyACADOProject_mpcclose │ ├── Process Output │ ├── ref.txt │ ├── road.txt │ ├── scalar3_ws_pareto.txt │ ├── scalar3_ws_weights.txt │ └── Simulated Differential States ├── cmake │ └── FindACADO.cmake ├── CMakeLists.txt ├── include ├── src │ ├── racket.cpp │ └── racket _discret.cpp ├── src2 │ └── mpc.cpp ├── src3 │ └── twoobj.cpp ├── src4 │ └── mpcclose.cpp └── src_codegen └── mpc_codegen.cppMyACADOProject_codegen 是通过正常的make cmake 生成的二进制对于我其他的例子已经是能运行求解问题给出答案的文件但是对于生成器不同对于生成器需要运行他而后生成一些文件这时候才是真正的用于整个工程使用的源文件在export_mpcclose中这里我再给出我的生成器代码 和对应的cmakelist我的cmakelist还包含了其他的我的案例可以先忽略。此外 cmake文件下的配置文件 FindACADO 一定要放置他是用来寻找acado的配置的文件否则需要再cmakelist中自己辛苦来配置。生成器说明我的mpc_codegen如下#includeacado_toolkit.hpp#includeacado_code_generation.hppintmain(){USING_NAMESPACE_ACADO// States and control (quarter-car, road input set to 0 for simplicity)DifferentialState xB;DifferentialState xW;DifferentialState vB;DifferentialState vW;Control F;constdoublemB350.0;constdoublemW50.0;constdoublekS20000.0;constdoublekT200000.0;DifferentialEquation f;fdot(xB)vB;fdot(xW)vW;fdot(vB)(-kS*xBkS*xWF)/mB;// Road excitation R is assumed 0 herefdot(vW)(-kT*xB-(kTkS)*xW-F)/mW;// Least-squares stage costFunction h;hxB;hxW;hvB;hvW;hF;DMatrixQ(5,5);Q.setZero();Q(0,0)10.0;Q(1,1)10.0;Q(2,2)1.0;Q(3,3)1.0;Q(4,4)1.0e-8;DVectorr(5);r.setAll(0.0);// Terminal LSQ (required by the code generator)Function hN;hNxB;hNxW;hNvB;hNvW;DMatrixQN(4,4);QN.setZero();QN(0,0)10.0;QN(1,1)10.0;QN(2,2)1.0;QN(3,3)1.0;// MPC timing: prediction grid aligned with controller samplingconstdoubleTs0.025;constintN40;// horizon length in stepsconstdoubletStart0.0;constdoubletEndN*Ts;// prediction window lengthOCPocp(tStart,tEnd,N);ocp.subjectTo(f);// For code generation, use the standard LSQ form.// (With this setup the implicit reference is zero.)ocp.minimizeLSQ(Q,h);ocp.minimizeLSQEndTerm(QN,hN);// Constraintsocp.subjectTo(-200.0F200.0);// Export nonlinear MPC codeOCPexportmpc(ocp);mpc.set(HESSIAN_APPROXIMATION,GAUSS_NEWTON);mpc.set(DISCRETIZATION_TYPE,MULTIPLE_SHOOTING);mpc.set(INTEGRATOR_TYPE,INT_RK4);mpc.set(NUM_INTEGRATOR_STEPS,1);// QP solver (requires qpOASES sources available to build the exported code)mpc.set(QP_SOLVER,QP_QPOASES);mpc.set(HOTSTART_QP,YES);// Convenience outputsmpc.set(GENERATE_TEST_FILE,YES);mpc.set(GENERATE_MAKE_FILE,YES);mpc.set(GENERATE_MATLAB_INTERFACE,NO);mpc.set(GENERATE_SIMULINK_INTERFACE,NO);if(mpc.exportCode(export_mpcclose)!SUCCESSFUL_RETURN)return1;return0;}我的cmakelist如下只需要关注相关内容即可cmake_minimum_required(VERSION3.10)project(MyACADOProject)# 添加 CMake 模块路径list(APPEND CMAKE_MODULE_PATH${CMAKE_SOURCE_DIR}/cmake)#SET(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}${PROJECT_SOURCE_DIR})# 查找 ACADOfind_package(ACADO REQUIRED)file(GLOB_RECURSE SOURCESsrc/*.cppsrc/*.c)file(GLOB_RECURSE SOURCES2src2/*.cppsrc2/*.c)file(GLOB_RECURSE SOURCES3src3/*.cppsrc3/*.c)file(GLOB_RECURSE SOURCES4src4/*.cppsrc4/*.c)file(GLOB_RECURSE SOURCES_CODEGENsrc_codegen/*.cppsrc_codegen/*.c)# # 创建可执行文件自动包含所有源文件#add_executable(${PROJECT_NAME}_racket ${SOURCES})# # 添加头文件路径#target_include_directories(${PROJECT_NAME}_racket PRIVATE include ${ACADO_INCLUDE_DIRS})# # 链接 ACADO#target_link_libraries(${PROJECT_NAME}_racket ${ACADO_SHARED_LIBRARIES})# #message(STATUSACADO_INCLUDE_DIRS: ${ACADO_INCLUDE_DIRS})# 创建可执行文件自动包含所有源文件add_executable(${PROJECT_NAME}_mpc ${SOURCES2})# 添加头文件路径target_include_directories(${PROJECT_NAME}_mpc PRIVATE include ${ACADO_INCLUDE_DIRS})# 链接 ACADOtarget_link_libraries(${PROJECT_NAME}_mpc ${ACADO_SHARED_LIBRARIES})# 创建可执行文件自动包含所有源文件add_executable(${PROJECT_NAME}_2obj ${SOURCES3})# 添加头文件路径target_include_directories(${PROJECT_NAME}_2obj PRIVATE include ${ACADO_INCLUDE_DIRS})# 链接 ACADOtarget_link_libraries(${PROJECT_NAME}_2obj ${ACADO_SHARED_LIBRARIES})# 创建可执行文件自动包含所有源文件add_executable(${PROJECT_NAME}_mpcclose ${SOURCES4})# 添加头文件路径target_include_directories(${PROJECT_NAME}_mpcclose PRIVATE include ${ACADO_INCLUDE_DIRS})# 链接 ACADOtarget_link_libraries(${PROJECT_NAME}_mpcclose ${ACADO_SHARED_LIBRARIES})#ACADO CodeGeneration(CGT)driver:runthisexecutable toexportMPC code.add_executable(${PROJECT_NAME}_codegen ${SOURCES_CODEGEN})target_include_directories(${PROJECT_NAME}_codegen PRIVATE include ${ACADO_INCLUDE_DIRS})target_link_libraries(${PROJECT_NAME}_codegen ${ACADO_SHARED_LIBRARIES})红框框内为运行生成器会出现的文件其中 qpoases文件夹子下是配套的求解器需要手动放入acado文件夹子下会送你这个文件夹手动拷贝到这个目录下使用即可。官网教程也有写到基本是在 ACADOtoolkit/external_packages/qpoases 里运行之后还会自动赠送 生成一个test 用例 这里是test.c test.o 可以使用你生成的代码 来测试你的求解问题。关于生成的每一个文件的作用请见如下copilot 解释ACADO 把你的 OCP 固化成一个“专用求解器”的源码包固定维度、固定离散化、固定求解流程。 acado_common.h 导出求解器的“总接口常量定义”头文件维度状态数、控制数、步数 N、数组大小、类型定义real_t、以及一些公共结构/宏。 你把导出求解器集成进自己工程时这个通常是最核心的 include 入口之一。 acado_solver.c 导出 MPC 的“主求解器逻辑”RTI/SQP 的一次迭代做什么、怎么组装 QP、怎么调用积分器和 QP 求解器、怎么更新解。 可以理解为“这个文件就是你的 MPC 算法本体针对该问题专门生成的”。 acado_integrator.c 动力学离散化/积分相关代码你设置的是 RK4multiple shooting。 会计算离散后的状态推进以及通常需要的敏感度/线性化信息供 QP 近似用。 acado_auxiliary_functions.hacado_auxiliary_functions.c 一堆“辅助函数”常见包括初始化变量、移窗shift操作、设置初值/参考、打印/调试输出等。 你看到的 “Differential variables/Control variables” 这类打印很多就是从辅助函数/测试程序调用来的。 acado_qpoases_interface.hppacado_qpoases_interface.cpp QP 子问题求解器的封装层把导出求解器内部的 QP 数据结构转换成 qpOASES 的调用方式并做 hotstart 等。 因为 qpOASES 是 C库所以这里是.cpp/.hpp。 Makefile 让你在“没有 CMake、没有完整工程”的情况下直接 make 就能把导出的 solver 编出来生成 libacado_exported_rti.a 和 test。 你也看到了它默认-I./qpoases...并且会编译./qpoases/SRC/*.cpp所以需要把 qpOASES 源码放进来。 test.c 和 test test.c 是 ACADO 自动生成的“示例主程序”演示如何调用导出的 solver并打印你看到的 RTI/KKT、状态轨迹、控制序列。 test 是你编译出来的测试可执行文件。 qpoases 目录你拷进去的 qpoases/INCLUDEqpOASES 头文件 qpoases/SRCqpOASES 源码 导出包把 qpOASES 当作“随包一起编译的依赖”所以需要放进来或者你改 Makefile/工程链接系统 qpOASES 也行。注意他的解释 “ACADO 把你的 OCP 固化成一个“专用求解器”的源码包固定维度、固定离散化、固定求解流程。“ 这也是为什么不是想其他工程一样我们是特化了这个问题生成的固定代码为什么要用“代码生成”不能直接用原代码编译跑 两者的定位不一样 你原来的写法比如用 OCPRealTimeAlgorithmController是“用 ACADO 工具箱在运行时搭建并求解问题” 优点改模型/改代价/改约束很方便写起来像脚本适合研究/验证。 缺点通常更依赖 ACADO 运行库、C抽象层更多、运行时开销更大、实时性/可移植性更难做到“工程级”。 CGT 导出的写法是“把问题固化成一个专用求解器”维度、N、积分器、QP 求解器接口全固定 优点最关键的几个 快数组大小、循环次数、稀疏结构都固定编译器能更好优化省掉很多运行时的通用性开销。 更可控/更像工程代码更少动态分配/模板/复杂依赖便于做实时控制你只要保证每周期调用一次 solver。 部署容易目标机上不一定要装完整 ACADO很多场景只需要导出的 C/C文件qpOASES。 缺点 灵活性下降改 N、改模型、改代价结构通常要重新export重新编译。 支持范围有限你之前遇到的报错就是例子——CGT 对目标函数形式有要求标准 LSQ、需要 terminal cost。 所以总结一句 “直接编译原代码”更像研究/原型 “代码生成”更像把 MPC 变成可交付、可嵌入、可实时运行的控制器模块横纵控制模型先行放置部分手写
RELATED — 相关阅读

相关资讯

LATEST — 最新资讯

最新发布

TODAY — 本日精选

新闻

WEEKLY — 本周精选

新闻

MONTHLY — 本月精选

新闻