花了一整天的时间,终于把acado的例程给跑通了,我整合了一下目前我所能搜到的信息,写一篇博客来记录一下我的使用过程,并把这些和大家分享一下。
这篇博客主要分为4个部分
(1)什么是acado求解库,这个求解库和其他求解库的区别是什么?这部分内容可能只是简单介绍一下,如果有错误,各位大佬可以在评论区补充一下。
(2)第二部分主要是针对Linix系统的acado库的安装。这部分网上也有挺多教程的,不过最好还是跟着官方给的例子进行。
https://acado.github.io/install_linux.html(Linux系统的acado安装教程)
https://acado.sourceforge.net/doc/html/index.html(acado的简介)
https://acado.sourceforge.net/doc/pdf/acado_manual.pdf(acado使用手册)
这是官方提供的文档,还是很详细的。
https://blog.csdn.net/weixin_46479223/article/details/133743263
https://blog.csdn.net/tzr0725/article/details/120632370
https://zhuanlan.zhihu.com/p/635352092
这是在网上参考的相关教程,大家都可以去参考一下。
(3)第三部分主要是讲一下acado库的配置和使用了,这里主要是讲一下使用catkin_make去构建工作空间的情况。
(4)最后一部分是应用一下acado库的其他demo。系统大家看完之后如果觉得有用的话,可以点赞收藏一下,谢谢!!!
一.什么是ACADO工具包?
**
网上查找相关教程可以看到以下相关工具概念 ACADO Toolkit、ACADOS 、Matlab环境下的ACADO ,笔者理解他们是同一个工具的不同扩展,解释如下,以免在学习中不同资料i产生混淆:
ACADO Toolkit:ACADO (Automatic Control and Dynamic Optimization)是一个用于自动控制和动态优化的开源C++库。它提供了一组工具和功能,使用户能够轻松地建立、求解和部署动态优化问题,包括最优控制、模型预测控制(MPC)等。ACADO Toolkit的特点包括符号微分、生成C++代码、支持多种数值优化方法等。它是一个独立的C++库,用户可以直接使用它来建模和求解控制和优化问题。
ACADOS:ACADOS(Automatic Control and Dynamic Optimization Suite)是一个开源的自动控制和动态优化套件,它是建立在ACADO Toolkit的基础上的。ACADOS扩展了ACADO Toolkit的功能,提供了更多的工具和接口,支持多个编程语言,包括C、MATLAB、Python和Julia。ACADOS的目标是为不同领域的研究人员和工程师提供一个更广泛的工具集,以满足不同需求。
ACADO Matlab:ACADO Toolkit还提供了一个专门的MATLAB接口,称为ACADO Matlab。这个接口使MATLAB用户能够使用ACADO Toolkit的功能,尤其是在MATLAB环境中建立和求解动态优化问题。ACADO Matlab提供了与ACADO Toolkit相似的功能,但可以更容易地与MATLAB集成。
类似求解器的优劣:
-
ACADO
优点:
(1)功能强大且灵活:支持多种优化问题,包括最优控制问题(OCP)、非线性模型预测控制(NMPC)、线性模型预测控制(LMPC)等。
(2)用户友好:提供了高层次的C++接口,便于定义优化问题。
(3)自动代码生成:可以生成高效的C代码,用于嵌入式系统。
(4)广泛的文档和示例:提供了详细的文档和丰富的示例代码,有助于快速上手。
缺点:
(1)性能有限:在处理大规模或高频率的优化问题时,性能可能不如一些更现代的工具。
(2)社区支持有限:相比于一些新兴工具,社区活跃度和支持可能较低。 -
ACADOS
优点:
(1)高性能:专为实时优化设计,具有高性能和高效率,适合嵌入式系统。
(2)现代化:基于现代算法和数据结构,支持多种求解器(如HPIPM、QP_OASES、OSQP等)。
(3)灵活性:支持多种优化问题,包括OCP、NMPC等,且可以与MATLAB、Python等接口集成。
(4)活跃的社区和开发:有一个活跃的开发社区,频繁更新和改进。
缺点
(1)学习曲线较陡峭:尽管功能强大,但初学者可能需要一些时间来熟悉其API和工作流程。
(2)文档相对复杂:虽然有详细的文档,但由于功能多样,可能需要更多时间来理解。 -
qpOASES
优点:
(1)专注于QP问题:特别优化用于求解二次规划(QP)问题,性能优异。
(2)易于集成:轻量级,易于集成到各种应用中,包括嵌入式系统。
(3)实时性能:设计初衷是为实时应用提供高效的QP求解器。
缺点
(1)仅限于QP问题:只能求解QP问题,不支持其他类型的优化问题(如非线性规划)。
(2)功能相对单一:不如其他工具那么多功能和灵活。 -
OSQP
优点:
(1)开源和高效:开源项目,专注于快速求解二次锥规划(QCP)问题,性能优异。
(2)鲁棒性:采用ADMM算法,具有良好的鲁棒性和稳定性。
(3)易于使用:提供了简单易用的API,支持多种编程语言(如C、Python等)。
(4)活跃的社区:有一个活跃的开发和用户社区,持续更新和改进。
缺点:
(1)仅限于QP和QCP问题:虽然性能强大,但功能范围有限,只能求解QP和QCP问题。
(2)文档相对简单:虽然文档齐全,但对于复杂应用场景可能需要更多的用户探索。 -
Control Toolbox (CT)
优点:
(1)全面的控制工具集:提供了广泛的控制算法和工具,包括线性和非线性控制、优化、仿真等。
(2)模块化设计:设计灵活,模块化强,易于扩展和集成。
(3)实时性:优化了实时控制性能,适合嵌入式和实时应用。
(4)丰富的文档:提供详细的文档和示例代码,支持快速上手。
缺点
(1)复杂性:功能全面,但对于初学者来说,可能会显得过于复杂。
(2)性能依赖于具体实现:实际性能可能依赖于具体的实现和配置,可能需要一定的调优。 -
CasADi
优点
(1)符号计算和自动微分:CasADi 擅长符号计算和自动微分,能够自动生成高效的导数计算代码,这对于优化问题尤其重要。
(2)灵活性:支持多种优化问题,包括非线性规划(NLP)、二次规划(QP)、微分代数方程(DAE)等。
(3)接口丰富:提供了Python和C++接口,方便不同用户的需求。
(4)集成求解器:可以与多种求解器(如 IPOPT、SNOPT、qpOASES)集成使用,用户可以根据需求选择最合适的求解器。
(5)良好支持:有一个活跃的开发社区和详细的文档,便于用户学习和使用。
缺点
(1)性能依赖于外部求解器:CasADi 本身并不是一个求解器,而是一个工具包,求解性能主要依赖于所选的外部求解器。
(2)学习曲线:对于初学者来说,可能需要一些时间来熟悉其符号计算和自动微分的机制。 -
IPOPT (Interior Point OPTimizer)
优点
(1)强大的非线性优化:IPOPT 是一个高效的非线性规划(NLP)求解器,适用于大规模优化问题。
(2)稳健性:对于多种复杂的非线性问题具有良好的稳健性和收敛性。
(3)广泛应用:在控制、经济学、工程等领域有广泛应用。
缺点
(1)依赖线性求解器:IPOPT 的性能依赖于所使用的线性求解器(如MA27、MA57等),这些线性求解器可能需要单独安装和配置。
(2)不支持混合整数规划:IPOPT 仅支持连续优化问题,不支持混合整数规划(MIP)。
这部分只是一些简单的介绍了,然后在网上收索资料的过程中,有看到知乎评论里聊到Acado停止了维护,CasADi很多人在用,但是Acado的求解速度比CasADi快,这里还没有一一对比求证以上消息,仅供参考也欢迎大家留言交流,未来研究一下其他求解器。
二.Acado的安装
这里有官网的详细的安装过程,我这里也是直接按照官网的步骤来进行,使用的是ubuntu20.04的版本。
https://acado.github.io/install_linux.html
2.1首先,需要通过 apt-get 包管理器下载一些包(您需要 root 权限):
sudo apt-get install gcc g++ cmake git gnuplot doxygen graphviz
Gnuplot, Doxygen and Graphviz 不是必须的,但是为了可视化和生成API,故推荐安装
2.2 下载源码
git clone https://github.com/acado/acado.git -b stable ACADOtoolkit
这里官网有两个版本,一般推荐的是使用stable的版本。 如果这个代码安装不了的话,就去上面的官网链接下载。
2.3编译
和安装其他求解库一样,在ACADOtoolkit功能包目录下建一个build文件夹,在其中进行操作编译。
cd ACADOtoolkit
mkdir build
cd build
cmake ..
make
sudo make install
这里补充一下最后一步sudo make install的作用,虽然官网没有用上,但是安装其他求解库一般是会用上的,使用 sudo 提升权限,运行 make install 命令,可以将编译好的文件复制到系统的标准目录中。
sudo make install 是一个常见的步骤。它的主要目的是将编译好的程序、库文件和相关资源安装到系统的标准位置。
sudo make install 的目的
(1)安装编译好的文件:
将编译好的二进制文件(如可执行文件、库文件)复制到系统的标准目录(如 /usr/local/bin, /usr/local/lib)。
安装过程中会将库文件放置在 /usr/local/lib,头文件放置在 /usr/local/include,可执行文件放置在 /usr/local/bin,以及其他资源文件放置在相应的目录中。
(2)设置权限:
使用 sudo 命令以超级用户(root)权限运行 make install,确保有权限将文件复制到系统的受保护目录中。
一般用户对这些系统目录没有写权限,所以需要使用 sudo 来提升权限。
(3)配置环境:
安装过程中可能会执行一些脚本来配置系统环境,如更新共享库缓存(ldconfig),添加环境变量等。
完成编译之后,ACADOtoolkit包的内容大概如下:
2.4 检查测试
可以使用自带的范例测试,范例文件夹下有很多参考供研究,我这里还是按照官网的给的案例来运行。
cd ..
cd examples/getting_started
./simple_ocp
具体的运行效果如下,如果能够成功运行,那就说明你已经安装成功了。
如果你还想测试一下其他的例程可以允许一下其他的示例源文件:
三.Acado的使用
3.1 刷新环境变量
首先我们需要将Acado的库加入系统变量里面,方便以后使用,操作和所有加path一样,将:
source <YourAcadoPath>/build/acado_env.sh
YourAcadoPath,这个得子行去查看该文件的路径。然后加入到根目录.bashrc下,最后使用下面的指令刷新一下:
. ~/.bashrc
3.2 功能包的创建
(1)创建工作空间并初始化
mkdir -p Acado_ws/src
cd Acado_ws
catkin_make
上述命令,首先会创建一个工作空间以及一个 src 子目录,然后再进入工作空间调用 catkin_make命令编译。
(2)进入 src 创建 ros 包并添加依赖
cd src
catkin_create_pkg acado_test roscpp rospy std_msgs geometry_msgs
上述命令,会在工作空间下生成一个功能包,该功能包依赖于 roscpp、rospy 与 std_msgs,其中roscpp是使用C++实现的库,而rospy则是使用python实现的库,std_msgs是标准消息库,创建ROS功能包时,一般都会依赖这三个库实现。
然后就可以正常建立工程文件目录,结构如图,其中红框中的文件必须要放置,否则编译如下的cmakelsit时候会报找不到一些文件,它在/cmake/FindACADO.cmake中
在ACODO/camke里找到FindACADO.cmake,放进你的工程包Acado_ws里面,然后新建一个cmake用于存放FindACADO.cmake。
3.3 CMakeLists的配置
然后是配置cmakelist,大家关注acado相关的内容即可,尤其是这一行增加了检索路径,去找到我们拷贝的cmake文件
set( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR} )
最后我的CMakeLists.txt文件的配置如下:
cmake_minimum_required(VERSION 3.0.2) // cmake_minimum_required(VERSION 3.0.2):指定所需的CMake最低版本为3.0.2。
project(acado_test) // project(acado_test):定义项目名称为 acado_test。
find_package(Eigen3 REQUIRED) // 查找并加载 Eigen3 库,这是一个用于线性代数计算的C++库。
find_package(ACADO REQUIRED) // 查找并加载 ACADO 工具包,这是一个用于优化控制的工具库。
// 将项目根目录添加到 CMake 模块路径中。这可以使得 CMake 在该目录中查找自定义的模块文件。
SET( CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR} )
//查找并加载 Catkin 工具包以及所需的 ROS 组件
//包括 roscpp(C++接口)、rospy(Python接口)、std_msgs(标准消息类型)和 geometry_msgs(几何消息类型)。
find_package(catkin REQUIRED COMPONENTS
roscpp
rospy
std_msgs
geometry_msgs
)
catkin_package(
# INCLUDE_DIRS include
# LIBRARIES acado_test
# CATKIN_DEPENDS roscpp rospy std_msgs
# DEPENDS system_lib
)
include_directories(
include
${catkin_INCLUDE_DIRS}
${EIGEN3_INCLUDE_DIRS}
${ACADO_INCLUDE_DIRS} // ACADO 工具包的头文件目录。
)
// 可执行文件,每个文件对应一个源文件。
add_executable(test_acado src/test_acado.cpp)
add_executable(main src/main.cpp)
add_executable(MPC src/MPC.cpp)
// 为每个可执行文件指定需要链接的库文件。
target_link_libraries(test_acado
${catkin_LIBRARIES} // Catkin 包的库文件
${ACADO_SHARED_LIBRARIES} // ACADO 工具包的共享库文件。
)
target_link_libraries(main
${catkin_LIBRARIES}
${ACADO_SHARED_LIBRARIES}
)
target_link_libraries(MPC
${catkin_LIBRARIES}
${ACADO_SHARED_LIBRARIES}
)
3.4 简单实例
例子1:以最优控制问题官方示例src举例:火箭以最小时间走完。(我存放在了main.cpp)
#include <acado_toolkit.hpp>
#include <acado_gnuplot.hpp>
int main()
{
USING_NAMESPACE_ACADO
DifferentialState s, v, m; // 微分状态量
Control u;
Parameter T;
DifferentialEquation f(0.0, T);
// ----------------------------
OCP ocp(0.0, T);
ocp.minimizeMayerTerm(T);
f << dot(s) == v;
f << dot(v) == (u - 0.2 * v * v) / m;
f << dot(m) == -0.01 * u * u;
ocp.subjectTo(f);
// 状态初始化
ocp.subjectTo(AT_START, s == 0.0);
ocp.subjectTo(AT_START, v == 0.0);
ocp.subjectTo(AT_START, m == 1.0);
// 终止条件约束
ocp.subjectTo(AT_END, s == 10.0);
ocp.subjectTo(AT_END, v == 0.0);
// 其他条件约束
ocp.subjectTo(-0.1 <= v <= 1.7);
ocp.subjectTo(-1.1 <= u <= 1.1);
ocp.subjectTo(5.0 <= T <= 15.0);
//------------------------------
GnuplotWindow window; // 在窗口中结果可视化
window.addSubplot(s, "DISTANCE s");
window.addSubplot(v, "VELOCITY v");
window.addSubplot(m, "MASS m");
window.addSubplot(u, "CONTROL u");
OptimizationAlgorithm algorithm(ocp); // 构建优化算法
algorithm << window;
algorithm.solve();
return 0;
}
写完main函数之后就保存,然后通过catkin_make去编译,然后通过rosrun去运行,具体代码如下:
cd Acado_ws/
catkin_make
source ./devel/setup.bash // 刷新环境变量
rosrun acado_test main
运行后出现下面的窗口就说明成功了!!这和我们一开始的测试代码是一致的。
例子2:MPC控制器
令 x 表示状态,u 表示控制输入,pa 表示时间常数参数,T 表示 MPC 优化问题的时间范围。我们感兴趣的是跟踪 MPC 问题,其一般形式为:
这里,函数 f 表示模型方程,s 表示路径约束,r 表示终端约束。请注意,在线情况下,必须迭代解决上述问题以改变 x0 和 t0 。此外,我们在此假设目标以最小二乘形式给出。实践中出现的大多数跟踪问题都可以用这种形式来表示,其中 η 和 μ 表示跟踪和终端参考。
具体代码如下,存放在(MPC.cpp):
#include <acado_toolkit.hpp>
#include <acado_gnuplot.hpp>
using namespace std;
USING_NAMESPACE_ACADO
int main( )
{
// INTRODUCE THE VARIABLES:
// -------------------------
DifferentialState xB;
DifferentialState xW;
DifferentialState vB;
DifferentialState vW;
Control R;
Control F;
double mB = 350.0;
double mW = 50.0;
double kS = 20000.0;
double kT = 200000.0;
// DEFINE A DIFFERENTIAL EQUATION:
// -------------------------------
DifferentialEquation f;// 创建微分方程
f << dot(xB) == vB;
f << dot(xW) == vW;
f << dot(vB) == ( -kS*xB + kS*xW + F ) / mB;
f << dot(vW) == ( kS*xB - (kT+kS)*xW + kT*R - F ) / mW;
// DEFINE LEAST SQUARE FUNCTION:
// -----------------------------
Function h;
//函数 h 用于定义最小二乘(Least Squares)问题中的cost函数
//平方和并没有在 h 中直接计算,而是在优化问题的目标函数中由 ocp.minimizeLSQ(Q, h, r) 执行。这个函数会将这些项加权并计算它们的平方和,其中权重由矩阵 Q 控制。也就是典型的最小二乘带权重,ps 推荐下bilibili老王和DR. Can 视频,最优估计,最优控制,机器学习感觉很多理论共用。
h << xB;
h << xW;
h << vB;
h << vW;
DMatrix Q(4,4);
Q.setIdentity();
Q(0,0) = 10.0;
Q(1,1) = 10.0;
//参考值 ,量测值或者 可观测值转为对应状态量测值
DVector r(4);
r.setAll( 0.0 );
// DEFINE AN OPTIMAL CONTROL PROBLEM:
// ----------------------------------
const double t_start = 0.0;
const double t_end = 1.0;
OCP ocp( t_start, t_end, 20 );
// 这里设置了步长20,则实际求解间隔为1/20 =0.05,可以从我截图的红框内看出
//换一句话说0.05 即为mpc根据状态空间方程外推下一步状态的时长
ocp.minimizeLSQ( Q, h, r );
// 这里不再使用mayer,使用了最小二乘作为cost函数
// Q:权重矩阵,用于调整每个目标项的相对重要性。
// h:目标函数的描述。
// r:期望的目标值。
ocp.subjectTo( f );
ocp.subjectTo( -500.0 <= F <= 500.0 );
ocp.subjectTo( R == 0.0 );
//笔者认为这里mpc设置已经ok,后续在设置仿真环境
// SETTING UP THE (SIMULATED) PROCESS:
// -----------------------------------
OutputFcn identity;
//创建了一个名为 identity 的输出函数对象。输出函数通常用于记录系统状态和控制输入的信息
DynamicSystem dynamicSystem( f,identity );
//创建了一个名为 dynamicSystem 的动态系统对象,它用于描述系统的动态行为。
//它需要两个参数: f:前面定义的微分方程对象,用于描述系统的状态变化。 identity:前面创建的输出函数对象,用于记录系统状态和控制输入。
Process process( dynamicSystem,INT_RK45 );
//创建了一个名为 process 的进程对象,用于模拟系统的行为。它需要两个参数:
// dynamicSystem:前面创建的动态系统对象,用于描述系统的动态行为. INT_RK45:表示使用4/5阶Runge-Kutta积分器进行系统模拟
// SETTING UP THE MPC CONTROLLER:
// ------------------------------
RealTimeAlgorithm alg( ocp,0.05 );
//建立算法对象
// 这里有一个值得注意的点
//RealTimeAlgorithm alg(ocp, 0.05); 也就是这里的0.05是执行一次ocp对象,也就是我们mpc算法的时间间隔
//而之前的OCP ocp(0,1, 20) 恰好也是0.05的时间长度,但他是一次mpc过程中,滚动迭代的小周期,也是利用状态方程外推下一步状态的时间步长。
//0到1的1秒时间长度为我的mpc的预测优化时域
DVector x0(4);
x0(0) = 0.01;
x0(1) = 0.0;
x0(2) = 0.0;
x0(3) = 0.0;
//初始化输出向量
alg.set( MAX_NUM_ITERATIONS, 2 );
//以下应该是是demo用来仿真的代码,建立controller和一些设置作图给用户展示,不再研究
StaticReferenceTrajectory zeroReference;
Controller controller( alg,zeroReference );
// SETTING UP THE SIMULATION ENVIRONMENT, RUN THE EXAMPLE...
// ----------------------------------------------------------
SimulationEnvironment sim( 0.0,3.0,process,controller );
if (sim.init( x0 ) != SUCCESSFUL_RETURN)
exit( EXIT_FAILURE );
if (sim.run( ) != SUCCESSFUL_RETURN)
exit( EXIT_FAILURE );
// ...AND PLOT THE RESULTS
// ----------------------------------------------------------
VariablesGrid sampledProcessOutput;
sim.getSampledProcessOutput( sampledProcessOutput );
VariablesGrid feedbackControl;
sim.getFeedbackControl( feedbackControl );
GnuplotWindow window;
window.addSubplot( sampledProcessOutput(0), "Body Position [m]" );
window.addSubplot( sampledProcessOutput(1), "Wheel Position [m]" );
window.addSubplot( sampledProcessOutput(2), "Body Velocity [m/s]" );
window.addSubplot( sampledProcessOutput(3), "Wheel Velocity [m/s]" );
window.addSubplot( feedbackControl(1), "Damping Force [N]" );
window.addSubplot( feedbackControl(0), "Road Excitation [m]" );
window.plot( );
return EXIT_SUCCESS;
}
编译后运行也是一样的步骤
cd Acado_ws/
catkin_make
source ./devel/setup.bash // 刷新环境变量
rosrun acado_test MPC
效果如下:
4.生成代码
具体步骤也是参考官方提供的例程:
这里将详细描述如何设置一个简单的示例,并使用 ACADO 代码生成工具 (CGT) 为 NMPC 应用程序生成优化代码。我们还概述了如何运行生成的代码。
4.1问题描述
我们考虑以下教程示例:一台起重机,其质量为
m
m
m ,线长为
L
L
L,激励角度为
ϕ
\phi
ϕ,水平小车位置为
p
p
p。我们的控制输入是小车的加速度
a
a
a。
v
v
v为小车速度,
ω
\omega
ω为质点的角速度,该系统可以用一个简单但非线性的微分方程系统来描述:
其中
b
b
b= 0.2J ,
s
s
s是正阻尼常数,我们使用参数
m
m
m= 1 千克、
L
L
L= 1m,和
g
g
g= 9.81 * m / s^2。
我们的目标是反复解决以下最优控制问题(OCP):
其中
F
(
⋅
)
F(\cdot)
F(⋅),描述前面描述的离散系统动力学。为简单起见,我们将定义参考函数如下:
以及加权矩阵 W = I 5 W = I_5 W=I5, W N = 5 ⋅ I 4 W_N = 5 \cdot I_4 WN=5⋅I4。对于此示例,我们选择使用$N = 10 控制(预测)间隔和采样时间 控制(预测)间隔和采样时间 控制(预测)间隔和采样时间T_s = 0.3s。
生成代码
大纲
为了使用 CGT 为本教程示例生成优化代码,需要执行以下步骤:
(1)设置一个源文件,使用 ACADO 语法描述您的非线性 MPC 问题,定义所需选项并为导出的代码指定目标目录。编译此源文件。
(2)运行编译的源文件,将代码(即完整的非线性 MPC 算法)导出到目标目录中。
(3)如果您使用qpOASES QP 求解器,则需要将求解器源代码文件复制到导出文件夹中,更准确地说,复制到子文件夹 qpoases 中。
我们现在将详细描述这些步骤。
4.2 用代码描述你的求解问题
首先制定非线性 MPC 问题
现在我们将逐步讨论上面问题描述的可能的非线性 MPC 公式。完整源代码也可在找到examples/code_generation/getting_started.cpp。有关 ACADO 语法的更多详细信息,请参阅 ACADO 用户手册。
全部代码如下,存放在test_acado.cpp :
//---------------------code generator---------------------
#include <acado_toolkit.hpp>
int main()
{
USING_NAMESPACE_ACADO
// Variables:
DifferentialState p; // the trolley position
DifferentialState v; // the trolley velocity
DifferentialState phi; // the excitation angle
DifferentialState omega; // the angular velocity
Control a; // the acc. of the trolley
const double g = 9.81; // the gravitational constant
const double b = 0.20; // the friction coefficient
// Model equations:
DifferentialEquation f;
f << dot(p) == v;
f << dot(v) == a;
f << dot(phi) == omega;
f << dot(omega) == -g * sin(phi) - a * cos(phi) - b * omega;
// Reference functions and weighting matrices:
Function h, hN;
h << p << v << phi << omega << a;
hN << p << v << phi << omega;
DMatrix W = DMatrix::Identity(h.getDim(), h.getDim());
DMatrix WN = DMatrix::Identity(hN.getDim(), hN.getDim());
WN *= 5;
std::cout << "W" << std::endl;
std::cout << W << std::endl;
std::cout << "h.getDim()" << std::endl;
std::cout << h.getDim() << std::endl;
std::cout << "WN" << std::endl;
std::cout << WN << std::endl;
//
// Optimal Control Problem
//
OCP ocp(0.0, 3.0, 10);
ocp.subjectTo(f);
ocp.minimizeLSQ(W, h);
ocp.minimizeLSQEndTerm(WN, hN);
ocp.subjectTo(-1.0 <= a <= 1.0);
ocp.subjectTo(-0.5 <= v <= 1.5);
// Export the code:
OCPexport mpc(ocp);
mpc.set(HESSIAN_APPROXIMATION, GAUSS_NEWTON);
mpc.set(DISCRETIZATION_TYPE, SINGLE_SHOOTING);
mpc.set(INTEGRATOR_TYPE, INT_RK4);
mpc.set(NUM_INTEGRATOR_STEPS, 30);
mpc.set(QP_SOLVER, QP_QPOASES);
mpc.set(GENERATE_TEST_FILE, YES);
mpc.set(GENERATE_MAKE_FILE, YES);
mpc.set(GENERATE_MATLAB_INTERFACE, YES);
mpc.set(GENERATE_SIMULINK_INTERFACE, YES);
if (mpc.exportCode("getting_started_export") != SUCCESSFUL_RETURN)
exit(EXIT_FAILURE);
mpc.printDimensionsQP();
return EXIT_SUCCESS;
}
4.3 编译生成代码
还是相同的步骤,写好代码后通过下面步骤编译生成代码
cd Acado_ws/
catkin_make
source ./devel/setup.bash // 刷新环境变量
rosrun acado_test test_acado
运行后会出现下面的情况:
然后就会新增加了一个功能包getting_started_export
然后我们设定使用qpoases求解,所以需要在在安装ACADOtoolkit的地方找到external_packages/qpoases,然后将他放进我们新增加的getting_started_export功能包里
然后进入到getting_started_export里面,因为里面有个Makefile,我们可以直接make 来编译这个makefile,完成输出。
cd Acado_ws/getting_started_export/
make
然后他就会生成对应的test可执行文件,我们运行一下,以下即为刚才print的结果们:
./test
下面就是打印的结果了。
到此已经完成所有案例的实现了,写到这里也接近16000多字了,因为也是刚刚复现了一下acado的使用,只是为了记录一下,还存在很多不动的地方,后续还会继续在实际使用中发现更多的问题,如果你看到了这里,也麻烦能给个点赞或者收藏一下吧,有其他问题也可以在评论区讨论一下。