VS2022 配置 casadi 求解 NMPC 问题
前言
最近在研究 NMPC 时,找到了 casadi 这个求解库,本来是在 ros+gazebo 平台上搭建的,但是最终的运行效果不太好,所以就打算先使用自己比较熟悉的 webots+vs 平台上进行测试,之后再移植过去
部署优化求解工具 casadi
下载 ipopt 的 vs2022 预编译程序
在 ipopt 的 github 官方仓库中找到 vs2022 的预编译版本,就是基于 vs2022 已经编译好的,不需要自行编译。可以直接选择较新的版本,记得要选择后面带有 msvs2022
的压缩包
下载 casadi 的源码
在 casadi 的 github 官方仓库中找到适合的版本,下载对应的 Source Code 压缩包即可
编译
由于下载的 ipopt 不需要编译,所以就只需要编译 casadi 即可。把上述的 ipopt 和 casadi 的源码放到一个不会被删掉的地方,建议是有一个比较统一存放 C++ 依赖库的地方,如下图所示
然后在 casadi 的目录下新建一个 install
目录下,并且在 casadi 目录下新建一个 run.bat
文件,这个文件中需要写入 casadi 的编译和安装脚本,但是一般双击 .bat
文件时会直接运行,所以可以先新建一个 run.txt
文件,之后再重命名即可。在文件中写入如下指令
1 | cmake -G "Visual Studio 17 2022" -A x64 -B build -DWITH_IPOPT=ON -DIPOPT_LIBRARIES:FILEPATH="ipopt的目录/lib/ipopt.dll.lib" -DIPOPT_INCLUDE_DIRS:PATH="ipopt的目录/include/coin-or" -DCMAKE_INSTALL_PREFIX:PATH="casadi的目录/install" |
之后双击运行,等待其编译安装结束
在 vs 中配置 casadi
编译完成之后需要在 vs2022 的 IDE 中进行配置。由于这个配置是针对于项目的,所以可以做一个属性表,就能够重复利用到多个项目中
制作属性表
打开一个项目,并且在项目中打开 视图-其他窗口-属性管理器,在属性管理器中添加新新项目属性表
就可以看到在 Release x64 下有个 casadi 的配置,然后右键打开其属性,开始编辑属性
包含目录
位于 VC++ 目录下,在其中添加新项目,如下
1 | casadi存放目录\install\casadi\include |
外部包含目录
位于 VC++ 目录下,在其中添加新项目
1 | casadi存放目录\install\casadi |
库目录
位于 VC++ 目录下,在其中添加新项目
1 | casadi存放目录\build\Release |
附加库目录
位于链接器-常规下,在其中添加新项目,如下
1 | casadi存放目录\casadi\core\runtime |
附加依赖项
位于链接器-输入下,在其中添加新项目,如下
1 | casadi.lib |
到此属性表就制作完毕了,之后就可以选中对应的属性表,右键保存之后就可以在该项目的目录下看到这个 casadi.props
文件。在之后的使用中就直接把这个文件复制到对应的项目目录下,在该项目的属性管理器中导入该属性表即可。需要注意的是,如果你的依赖库的位置发生了改变,属性表也需要改变
添加动态链接库文件
动态链接库 dll 文件是运行 exe 文件时实时调用的,因此需要将dll文件复制粘贴到生成的 exe 文件同级目录,将编译生成的 casadi.dll
以及 casadi_nlpsol_ipopt.dll
文件粘贴到和生成的 exe 文件同级的文件夹内
一般这两个文件都存在于 casadi 的安装目录下,即 casadi存放目录\install\casadi
配置环境变量
添加过链接库之后,还会提示找不到 casadi_nlpsol_ipopt.dll
文件的错误,就需要将 ipopt 的程序路径添加到系统环境变量中
1 | ipopt存放目录\bin |
一些其他的问题
vs2022 创建属性表闪退
在创建属性表时有时会遇到创建属性表之后 vs2022 卡死闪退的情况,解决方法如下
- 在 Visual Studio Installer 中查看是否有 vs2022 的更新,如果有就更新到最新版
- 使用
win+R
输入cmd
打开终端,在其中输入指令regsvr32 jscript9Legacy.dll
并运行
之后就可以成功创建了
casadi 求解 NMPC
利用简单的一阶倒立摆来验证算法
动力学分析
-
底座分析
-
x 方向上
-
y 方向上
-
-
摆杆分析
-
x 方向上
-
y 方向上
-
扭矩
-
求解系统状态空间方程
根据上述公式 联立求解出 ,如下
设置 NMPC 的参数
计算完上述的 之后,还需要设定 NMPC 的步长,预测步数和权重矩阵
- 步长的选择
- 对于快速动态系统,步长一般都较长,一般就是 10 ms 到 100 ms
- 对于高阶离散方法(例如 4 阶龙格库塔方法),允许使用较大点的步长
- 对于低阶方法(例如欧拉方法)需要更小的步长来保证精度
- 预测步数选择
- 预测时域通常需要覆盖掉系统动态的过渡阶段,通常为系统稳定时间的 1-2 倍
- 步数过多会增加优化变量维度,可能超出实时计算能力,若需要减少计算量,可适当缩小预测步数或增大步长
- 惩罚矩阵
- 状态跟踪误差权重矩阵 ,用于调节状态误差的优先级
- 控制输入权重矩阵 ,用于限制控制输入的幅值或变化率
- 终端误差权重矩阵 ,用于强调终端状态的准确性
- 当 与 过于接近的话,会导致 的变化致使代价函数 的变化不明显,从而最终求解得到的 很小
可以设定一些初始值来计算代价函数,以此来设定 NMPC 的步长和预测步数,代码如下所示,可以根据设定一个初始的力 ,不断改变时间常数来计算相对应的代价函数,对比之后选择合适的时间常数。需要注意的是代价函数之间差别较小的话,会导致求解 NMPC 时陷入局部最优解,从而能很快得到结果,但是效果很差。若代价函数值过大的话,会导致计算周期长,甚至求解错误
1 | predict_n = 10; |
示例运行结果
该示例基于 webots+vs2022 平台实现。状态值为 ,设定目标值为 ,运行结果如下
NMPC 求解器代码示例介绍
计算代价函数
1 | SX J = 0; |
设定求解器的参数
1 | SXDict nlp = { |
求解结果
1 | SX lbu = repmat(_u_min, predict_n, 1); |
代码地址