【VS2022 配置 casadi 求解 NLP问题】

1. 前言

在这里插入图片描述

最近在研究 船舶NMPC 控制时,主要是非线性约束的凸二次优化问题属于NLP问题,找到了 casadi 这个求解库,最初是在MATLAB平台上搭建的,虽然最终的运行效果挺好,但是团队现在软件是基于Visual Studio From架构设计的测试软件,之后再系统的移植过去。

1.1 来回扁椭圆

在这里插入图片描述

1.2 椭圆轨迹

在这里插入图片描述

1.3 月牙形轨迹

在这里插入图片描述

2. 部署优化求解工具 casadi

下载 ipopt 的 vs2022 预编译程序
ipopt 的 github 官方仓库中找到 vs2022 的预编译版本,就是基于 vs2022 已经编译好的,不需要自行编译。可以直接选择较新的版本,记得要选择后面带有 msvs2022 的压缩包
在这里插入图片描述

3. 下载 casadi 的源码

casadi 的 github 官方仓库中找到适合的版本,下载对应的 Source Code 压缩包即可

在这里插入图片描述

4. 组合编译casadi和ipopt

由于下载的 ipopt 不需要编译,所以就只需要编译 casadi 即可。把上述的 ipopt 和 casadi 的源码放到一个不会被删掉的地方,建议是有一个比较统一存放 C++ 依赖库的地方,如下图所示
在这里插入图片描述

然后在 casadi 的目录下新建一个 install 目录下,并且在 casadi 目录下新建一个 run.bat 文件,这个文件中需要写入 casadi 的编译和安装脚本,但是一般双击 .bat 文件时会直接运行,所以可以先新建一个 run.txt 文件,之后再重命名即可。在文件中写入如下指令

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"
cmake --build build --config Release
cmake --install build

下面是我自己的配置参考

cmake -G "Visual Studio 17 2022" -A x64 -B build -DWITH_IPOPT=ON -DIPOPT_LIBRARIES:FILEPATH="E:/cpplibrary/Ipopt/lib/ipopt.dll.lib" -DIPOPT_INCLUDE_DIRS:PATH="E:/cpplibrary/Ipopt/include/coin-or"  -DCMAKE_INSTALL_PREFIX:PATH="E:/cpplibrary/casadi/install"
cmake --build build --config Release
cmake --install build

后面demo只支持Release x64版本,进行二次封装可以解除版本限制就可以支持Debug x64版本
在这里插入图片描述

之后双击运行,等待其编译安装结束
在这里插入图片描述

打开install文件夹后,就会生成casadi的release版本的调用DLL库
在这里插入图片描述

5. 在 vs 中配置 casadi

编译完成之后需要在 vs2022 的 IDE 中进行配置。就可以看到在 Release x64 ,然后点击项目右键打开其属性,开始编辑Visual Studio2022项目属性
先新建项目
在这里插入图片描述
选C++控制台应用,点击下一步
在这里插入图片描述

项目名称取NLP
在这里插入图片描述
项目程序是打印Hello world,可以基于release x64环境运行,终端窗口打印可以Hello world,就可以开始配置Casadi 非线性优化问题了,
在这里插入图片描述

5.1 包含目录

位于 VC++ 目录下,在其中添加新项目,如下

casadi存放目录\install\casadi\include
casadi存放目录\install\casadi

在这里插入图片描述

5.2 外部包含目录

位于 VC++ 目录下,在其中添加新项目

casadi存放目录\install\casadi
casadi存放目录\install\casadi\include

在这里插入图片描述

5.3 库目录

位于 VC++ 目录下,在其中添加新项目

casadi存放目录\build\Release
casadi存放目录

在这里插入图片描述

5.4 附加依赖项

位于链接器-输入下,在其中添加新项目,如下

casadi.lib

在这里插入图片描述
最后点击应用

6. 火箭发射模型

casadi求解器的C++demo在源码路径中E:\cpplibrary\casadi\docs\examples\cplusplus
我们这次采用rocket_ipopt.cpp实例
在这里插入图片描述

6.1 rocket_ipopt.cpp实例

将其源码复制到Hello world代码中

/*
 *    MIT No Attribution
 *
 *    Copyright (C) 2010-2023 Joel Andersson, Joris Gillis, Moritz Diehl, KU Leuven.
 *
 *    Permission is hereby granted, free of charge, to any person obtaining a copy of this
 *    software and associated documentation files (the "Software"), to deal in the Software
 *    without restriction, including without limitation the rights to use, copy, modify,
 *    merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
 *    permit persons to whom the Software is furnished to do so.
 *
 *    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
 *    INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 *    PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 *    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 *    OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 *    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 */


#include <iostream>
#include <fstream>
#include <ctime>
#include <casadi/casadi.hpp>

using namespace casadi;

int main(){
  std::cout << "program started" << std::endl;

  // Dimensions
  int nu = 20;  // Number of control segments
  int nj = 100; // Number of integration steps per control segment

  // optimization variable
  SX u = SX::sym("u", nu); // control

  SX s_0 = 0; // initial position
  SX v_0 = 0; // initial speed
  SX m_0 = 1; // initial mass

  SX dt = 10.0/(nj*nu); // time step
  SX alpha = 0.05; // friction
  SX beta = 0.1; // fuel consumption rate

  // Trajectory
  std::vector<SX> s_k, v_k, m_k;

  // Integrate over the interval with Euler forward
  SX s = s_0, v = v_0, m = m_0;
  for(int k=0; k<nu; ++k){
    for(int j=0; j<nj; ++j){
      s += dt*v;
      v += dt / m * (u(k)- alpha * v*v);
      m += -dt * beta*u(k)*u(k);
    }
    s_k.push_back(s);
    v_k.push_back(v);
    m_k.push_back(m);
  }
  SX s_all=vertcat(s_k), v_all=vertcat(v_k), m_all=vertcat(m_k);

  // Objective function
  SX f = dot(u, u);

  // Terminal constraints
  SX g = vertcat(s, v, v_all);

  // Create the NLP
  SXDict nlp = {{"x", u}, {"f", f}, {"g", g}};

  // Allocate an NLP solver and buffers
  Function solver = nlpsol("solver", "ipopt", nlp);

  // Bounds on g
  std::vector<double> gmin = {10, 0};
  std::vector<double> gmax = {10, 0};
  gmin.resize(2+nu, -std::numeric_limits<double>::infinity());
  gmax.resize(2+nu, 1.1);

  // Solve the problem
  DMDict arg = {{"lbx", -10},
                     {"ubx", 10},
                     {"x0", 0.4},
                     {"lbg", gmin},
                     {"ubg", gmax}};
  DMDict res = solver(arg);

  // Print the optimal cost
  double cost(res.at("f"));
  std::cout << "optimal cost: " << cost << std::endl;

  // Print the optimal solution
  std::vector<double> uopt(res.at("x"));
  std::cout << "optimal control: " << uopt << std::endl;

  // Get the state trajectory
  Function xfcn("xfcn", {u}, {s_all, v_all, m_all});
  std::vector<double> sopt, vopt, mopt;
  xfcn({uopt}, {&sopt, &vopt, &mopt});
  std::cout << "position: " << sopt << std::endl;
  std::cout << "velocity: " << vopt << std::endl;
  std::cout << "mass:     " << mopt << std::endl;

  // Create Matlab script to plot the solution
  std::ofstream file;
  std::string filename = "rocket_ipopt_results.m";
  file.open(filename.c_str());
  file << "% Results file from " __FILE__ << std::endl;
  file << "% Generated " __DATE__ " at " __TIME__ << std::endl;
  file << std::endl;
  file << "cost = " << cost << ";" << std::endl;
  file << "u = " << uopt << ";" << std::endl;

  // Save results to file
  file << "t = linspace(0,10.0," << nu << ");"<< std::endl;
  file << "s = " << sopt << ";" << std::endl;
  file << "v = " << vopt << ";" << std::endl;
  file << "m = " << mopt << ";" << std::endl;

  // Finalize the results file
  file << std::endl;
  file << "% Plot the results" << std::endl;
  file << "figure(1);" << std::endl;
  file << "clf;" << std::endl << std::endl;

  file << "subplot(2,2,1);" << std::endl;
  file << "plot(t,s);" << std::endl;
  file << "grid on;" << std::endl;
  file << "xlabel('time [s]');" << std::endl;
  file << "ylabel('position [m]');" << std::endl << std::endl;

  file << "subplot(2,2,2);" << std::endl;
  file << "plot(t,v);" << std::endl;
  file << "grid on;" << std::endl;
  file << "xlabel('time [s]');" << std::endl;
  file << "ylabel('velocity [m/s]');" << std::endl << std::endl;

  file << "subplot(2,2,3);" << std::endl;
  file << "plot(t,m);" << std::endl;
  file << "grid on;" << std::endl;
  file << "xlabel('time [s]');" << std::endl;
  file << "ylabel('mass [kg]');" << std::endl << std::endl;

  file << "subplot(2,2,4);" << std::endl;
  file << "plot(t,u);" << std::endl;
  file << "grid on;" << std::endl;
  file << "xlabel('time [s]');" << std::endl;
  file << "ylabel('Thrust [kg m/s^2]');" << std::endl << std::endl;

  file.close();
  std::cout << "Results saved to \"" << filename << "\"" << std::endl;

  return 0;
}

6.2 添加动态链接库文件

动态链接库 dll 文件是运行 exe 文件时实时调用的,因此需要将dll文件复制粘贴到生成的 exe 文件同级目录C:\Users\DMU\source\repos\nlp\x64\Release,将编译生成的 casadi.dll 以及 casadi_nlpsol_ipopt.dll 文件粘贴到和生成的 exe 文件同级的C:\Users\DMU\source\repos\nlp\x64\Release文件夹内
在这里插入图片描述

一般这两个文件都存在于 casadi 的install安装目录下,即 casadi存放目录\install\casadi

6.3 配置环境变量

添加过链接库之后,还会提示找不到 casadi_nlpsol_ipopt.dll 文件的错误,就需要将 ipopt 的程序路径添加到系统环境变量中
在这里插入图片描述

6.4 运行结果

配置Release x64环境,一切都配置好后点击运行
在这里插入图片描述

运行结果如下,我的电脑运行还是非常快滴🤞🤞🤞

NOTE: Other linear solvers might be more efficient (see Ipopt documentation).

Number of nonzeros in equality constraint Jacobian...:       40
Number of nonzeros in inequality constraint Jacobian.:      210
Number of nonzeros in Lagrangian Hessian.............:      210

Total number of variables............................:       20
                     variables with only lower bounds:        0
                variables with lower and upper bounds:       20
                     variables with only upper bounds:        0
Total number of equality constraints.................:        2
Total number of inequality constraints...............:       20
        inequality constraints with only lower bounds:        0
   inequality constraints with lower and upper bounds:        0
        inequality constraints with only upper bounds:       20

iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
   0  3.2000000e+00 6.01e+00 7.73e-02  -1.0 0.00e+00    -  0.00e+00 0.00e+00   0
   1  2.6179074e+00 2.76e+00 4.77e+01  -1.0 2.21e+00    -  1.09e-02 5.35e-01f  1
   2  4.1657553e+00 5.88e-01 1.18e+01  -1.0 7.57e-01    -  5.81e-01 7.51e-01h  1
   3  5.0636497e+00 3.55e-02 1.14e+00  -1.0 3.45e-01    -  9.82e-01 9.04e-01h  1
   4  5.0061347e+00 1.84e-03 1.04e-02  -1.0 1.13e-01    -  1.00e+00 1.00e+00f  1
   5  4.3948828e+00 1.10e-02 8.37e-01  -2.5 2.39e-01    -  6.20e-01 1.00e+00f  1
   6  4.1377025e+00 2.44e-03 1.83e-02  -2.5 1.11e-01    -  1.00e+00 1.00e+00f  1
   7  4.0166442e+00 3.62e-04 7.13e-02  -3.8 4.27e-02    -  7.51e-01 1.00e+00f  1
   8  4.0011959e+00 1.63e-05 7.41e-05  -3.8 9.52e-03    -  1.00e+00 1.00e+00h  1
   9  3.9985771e+00 1.94e-07 1.21e-06  -5.7 9.59e-04    -  1.00e+00 1.00e+00h  1
iter    objective    inf_pr   inf_du lg(mu)  ||d||  lg(rg) alpha_du alpha_pr  ls
  10  3.9985414e+00 3.20e-11 1.97e-10  -8.6 1.20e-05    -  1.00e+00 1.00e+00h  1

Number of Iterations....: 10

                                   (scaled)                 (unscaled)
Objective...............:   3.9985414424319439e+00    3.9985414424319439e+00
Dual infeasibility......:   1.9744241264419726e-10    1.9744241264419726e-10
Constraint violation....:   3.2043783425306227e-11    3.2043783425306227e-11
Complementarity.........:   2.6648571233142114e-09    2.6648571233142114e-09
Overall NLP error.......:   2.6648571233142114e-09    2.6648571233142114e-09


Number of objective function evaluations             = 11
Number of objective gradient evaluations             = 11
Number of equality constraint evaluations            = 11
Number of inequality constraint evaluations          = 11
Number of equality constraint Jacobian evaluations   = 11
Number of inequality constraint Jacobian evaluations = 11
Number of Lagrangian Hessian evaluations             = 10
Total CPU secs in IPOPT (w/o function evaluations)   =      0.059
Total CPU secs in NLP function evaluations           =      0.041

EXIT: Optimal Solution Found.
      solver  :   t_proc      (avg)   t_wall      (avg)    n_eval
       nlp_f  |        0 (       0)  15.30us (  1.39us)        11
       nlp_g  |        0 (       0) 833.10us ( 75.74us)        11
  nlp_grad_f  |        0 (       0)  58.10us (  4.84us)        12
  nlp_hess_l  |  30.00ms (  3.00ms)  27.38ms (  2.74ms)        10
   nlp_jac_g  |  11.00ms (916.67us)   9.10ms (758.09us)        12
       total  | 102.00ms (102.00ms) 101.97ms (101.97ms)         1
optimal cost: 3.99854
optimal control: [1.32045, 0.701825, 0.138416, 0.0605, 0.0605, 0.0605, 0.0605, 0.0605, 0.0605, 0.0605, 0.0605, 0.0605, 0.0605, 0.0605, 0.0605, 0.0605, 0.0605, -0.00694958, -0.601974, -1.15307]
position: [0.167788, 0.602475, 1.14116, 1.69116, 2.24116, 2.79116, 3.34116, 3.89116, 4.44116, 4.99116, 5.54116, 6.09116, 6.64116, 7.19116, 7.74116, 8.29116, 8.84116, 9.38191, 9.82234, 10]
velocity: [0.686414, 1.05473, 1.1, 1.1, 1.1, 1.1, 1.1, 1.1, 1.1, 1.1, 1.1, 1.1, 1.1, 1.1, 1.1, 1.1, 1.1, 1.06302, 0.696855, -3.20438e-11]
mass:     [0.912821, 0.888193, 0.887235, 0.887052, 0.886869, 0.886686, 0.886503, 0.88632, 0.886137, 0.885954, 0.885771, 0.885588, 0.885405, 0.885222, 0.885039, 0.884856, 0.884673, 0.884671, 0.866552, 0.800073]
Results saved to "rocket_ipopt_results.m"

C:\Users\DMU\source\repos\nlp\x64\Release\nlp.exe (进程 42480)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .

7 总结

恭喜你,学习了VS2022 配置 casadi 求解 NLP问题,从而实现对外部世界进行感知,充分认识这个有机与无机的环境,科学地合理地进行创作和发挥效益,然后为人类社会发展贡献一点微薄之力。🤣🤣🤣

  1. 我会持续更新对应专栏博客,非常期待你的三连!!!🎉🎉🎉
  2. 如果鹏鹏有哪里说的不妥,还请大佬多多评论指教!!!👍👍👍
  3. 下面有我的🐧🐧🐧群推广,欢迎志同道合的朋友们加入,期待与你的思维碰撞😘😘😘

参考文献:VS2022 配置 casadi 求解 NMPC 问题

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

2345VOR

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值