在Ubuntu 20.04上从源码编译CasADi C++库,顺便搞定Ipopt和HSL依赖(保姆级避坑指南)

张开发
2026/4/8 3:16:00 15 分钟阅读

分享文章

在Ubuntu 20.04上从源码编译CasADi C++库,顺便搞定Ipopt和HSL依赖(保姆级避坑指南)
在Ubuntu 20.04上从源码编译CasADi C库完整避坑指南与实战解析CasADi作为一款强大的符号计算框架在机器人控制、优化计算和科学工程领域广受欢迎。然而其复杂的依赖关系和编译过程常常让开发者望而却步。本文将带你彻底解决Ubuntu 20.04环境下CasADi C版本的编译难题涵盖从基础依赖到高级配置的全流程特别针对HSL库注册、Ipopt编译等关键环节提供详细解决方案。1. 环境准备与基础依赖安装在开始编译CasADi之前我们需要确保系统具备完整的开发环境。Ubuntu 20.04虽然提供了许多现成的软件包但仍需特别注意版本兼容性问题。首先更新系统软件包并安装基础编译工具链sudo apt update sudo apt upgrade -y sudo apt install -y build-essential cmake git wget接下来安装CasADi的核心依赖项这些工具将用于数值计算和接口生成sudo apt install -y gcc g gfortran liblapack-dev libblas-dev pkg-config \ python3-dev python3-numpy python3-scipy swig提示如果计划使用Python接口建议同时安装matplotlib和ipython3以便后续调试验证gcc版本是否至少为7.0gcc --version若版本过低可通过以下命令安装新版编译器sudo apt install -y software-properties-common sudo add-apt-repository ppa:ubuntu-toolchain-r/test sudo apt install -y gcc-9 g-9 gfortran-9 sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-9 902. Ipopt及其依赖项的编译安装Ipopt作为CasADi最常用的求解器之一其编译过程最为复杂。我们需要按顺序安装ASL、HSL、MUMPS等关键组件。2.1 ASL库的安装与验证ASL(Ampl Solver Library)是Ipopt处理AMPL格式问题所必需的组件git clone https://github.com/coin-or-tools/ThirdParty-ASL.git cd ThirdParty-ASL ./get.ASL ./configure --prefix/usr/local make -j$(nproc) sudo make install安装完成后检查是否成功ls /usr/local/lib | grep coin应能看到libcoinasl相关的库文件。2.2 HSL线性求解器获取与编译HSL(HSL Mathematical Software Library)是Ipopt的高性能线性求解器需要单独获取授权访问HSL官方网站注册账号在下载页面选择MA27/MA57/MA97等求解器组合包完成订单流程后下载最新版本的coinhsl-x.y.z.tar.gz将下载的压缩包解压并放置到ThirdParty-HSL目录git clone https://github.com/coin-or-tools/ThirdParty-HSL.git cd ThirdParty-HSL tar -xvzf ~/Downloads/coinhsl-2021.05.05.tar.gz mv coinhsl-2021.05.05 coinhsl配置编译选项时建议启用共享库以方便后续使用./configure --prefix/usr/local --enable-shared make -j$(nproc) sudo make install常见问题排查若遇到permission denied错误尝试先执行chmod x configure编译失败时检查fortran编译器是否安装正确2.3 MUMPS并行求解器安装MUMPS(MUltifrontal Massively Parallel Solver)是另一个重要的线性代数求解器git clone https://github.com/coin-or-tools/ThirdParty-Mumps.git cd ThirdParty-Mumps ./get.Mumps ./configure --prefix/usr/local make -j$(nproc) sudo make install同时安装系统提供的开发包sudo apt install -y libmumps-seq-dev2.4 Ipopt核心库编译现在可以编译Ipopt本身了配置时需要明确指定各依赖项的位置git clone https://github.com/coin-or/Ipopt.git cd Ipopt mkdir build cd build ../configure --prefix/usr/local \ --with-mumps \ --with-mumps-cflags-I/usr/local/include/coin-or/mumps \ --with-mumps-lflags-L/usr/local/lib -lcoinmumps \ --with-hsl \ --with-hsl-cflags-I/usr/local/include/coin-or/hsl \ --with-hsl-lflags-L/usr/local/lib -lcoinhsl make -j$(nproc) sudo make install验证安装ipopt --version应能看到类似3.14.4的版本信息输出。3. CasADi核心库的编译与安装有了完整的依赖环境后我们可以开始编译CasADi本体了。建议从官方发布页面下载稳定版本而非直接使用git master分支wget https://github.com/casadi/casadi/releases/download/3.7.1/casadi-3.7.1.tar.gz tar -xvzf casadi-3.7.1.tar.gz cd casadi-3.7.1 mkdir build cd build配置CMake时根据需求启用不同模块cmake .. -DCMAKE_INSTALL_PREFIX/usr/local \ -DWITH_PYTHONON \ -DWITH_PYTHON3ON \ -DWITH_IPOPTON \ -DWITH_MUMPSON \ -DWITH_OPENMPON make -j$(nproc) sudo make install关键CMake选项说明WITH_IPOPTON启用Ipopt支持WITH_PYTHON3ON构建Python接口ENABLE_STATICOFF禁用静态库以减小体积安装完成后更新动态链接库缓存sudo ldconfig4. 环境配置与验证测试为确保系统能找到所有安装的库需要设置适当的环境变量。编辑~/.bashrc文件echo export LD_LIBRARY_PATH/usr/local/lib:$LD_LIBRARY_PATH ~/.bashrc echo export CASADI_PREFIX/usr/local ~/.bashrc source ~/.bashrc创建一个简单的测试程序test_casadi.cpp验证安装#include casadi/casadi.hpp #include iostream int main() { // 创建符号变量 casadi::MX x casadi::MX::sym(x); casadi::MX y casadi::MX::sym(y); // 构建表达式 casadi::MX f pow(x,2) pow(y,2); casadi::MX g x y - 10; // 创建NLP求解器 casadi::MXDict nlp {{x, casadi::MX::vertcat({x,y})}, {f, f}, {g, g}}; casadi::Dict opts {{ipopt.print_level, 0}}; casadi::Function solver casadi::nlpsol(solver, ipopt, nlp, opts); // 求解问题 std::mapstd::string, casadi::DM res solver( {{x0, std::vectordouble{0,0}}, {lbg, 0}, {ubg, 0}}); std::cout Optimal solution: res.at(x) std::endl; return 0; }编译并运行测试程序g test_casadi.cpp -o test_casadi -lcasadi ./test_casadi应能看到类似Optimal solution: [5, 5]的输出结果。5. 高级配置与性能优化5.1 多线程支持配置要充分利用现代CPU的多核性能可以在编译时启用OpenMP支持sudo apt install -y libomp-dev重新编译CasADi时添加cmake .. -DWITH_OPENMPON5.2 自定义BLAS/LAPACK实现系统自带的BLAS可能不是最优选择可以替换为OpenBLASsudo apt install -y libopenblas-dev然后在Ipopt和CasADi的配置中添加--with-blas-lopenblas --with-lapack-lopenblas5.3 调试符号与优化级别开发阶段可能需要调试信息可以在CMake配置中添加-DCMAKE_BUILD_TYPEDebug生产环境则应使用最高优化级别-DCMAKE_BUILD_TYPERelease6. 常见问题解决方案6.1 运行时库找不到错误若出现error while loading shared libraries检查ldd /usr/local/lib/libcasadi.so确保所有依赖都能找到必要时更新LD_LIBRARY_PATH。6.2 HSL相关编译错误常见的HSL问题包括许可证文件缺失确保将HSL下载包中的LICENSE文件放在正确位置符号冲突尝试禁用系统自带的BLAS库6.3 Python接口导入失败Python找不到CasADi模块时检查python3 -c import sys; print(sys.path)确保/usr/local/lib/python3.8/site-packages在路径中。7. 实际应用倒立摆控制案例下面展示一个完整的倒立摆非线性模型预测控制(NMPC)实现演示CasADi在实际控制问题中的应用。#include casadi/casadi.hpp #include chrono namespace cd casadi; int main() { // 系统参数 const int nx 2; // 状态维度 [角度, 角速度] const int nu 1; // 控制维度 [力矩] const int N 20; // 预测时域 const double dt 0.05; // 采样时间 // 定义符号变量 cd::MX x cd::MX::sym(x, nx); cd::MX u cd::MX::sym(u, nu); // 系统动力学 (倒立摆模型) cd::MX theta x(0), dtheta x(1); cd::MX dynamics cd::MX::vertcat({ dtheta, cd::MX::sin(theta) u // 简化模型 }); // 创建RK4积分器 auto rk4 [](cd::MX x, cd::MX u, double h) { std::vectorcd::MX k cd::MX::vertsplit( cd::MX::mtimes(cd::MX::blockcat({ {cd::MX::zeros(nx,nx), cd::MX::eye(nx)}, {cd::MX::zeros(nx,nx), cd::MX::zeros(nx,nx)} }), cd::MX::vertcat({x, dynamics})) cd::MX::vertcat({cd::MX::zeros(nx,1), u}), nx ); return x (h/6)*(k[0] 2*k[1] 2*k[2] k[3]); }; // 构建NMPC问题 cd::Opti opti; cd::MX X opti.variable(nx, N1); // 状态轨迹 cd::MX U opti.variable(nu, N); // 控制序列 cd::MX x0 opti.parameter(nx); // 初始状态 cd::MX x_ref opti.parameter(nx); // 参考状态 // 添加动力学约束 for(int k0; kN; k) { opti.subject_to(X(cd::Slice(), k1) rk4(X(cd::Slice(), k), U(cd::Slice(), k), dt)); } // 添加边界约束 opti.subject_to(opti.bounded(-2.0, U, 2.0)); // 控制输入限制 opti.subject_to(opti.bounded(-M_PI, X(0, cd::Slice()), M_PI)); // 角度限制 // 设置代价函数 cd::MX cost 0; for(int k0; kN; k) { cost cd::MX::sumsqr(X(cd::Slice(), k) - x_ref) 0.1*cd::MX::sumsqr(U(cd::Slice(), k)); } opti.minimize(cost); // 配置求解器 cd::Dict opts; opts[ipopt.print_level] 0; opts[print_time] false; opti.solver(ipopt, opts); // 设置初始猜测 opti.set_initial(X, 0); opti.set_initial(U, 0); // 模拟闭环控制 std::vectordouble current_state {0.1, 0}; // 初始偏移 std::vectordouble target_state {0, 0}; // 平衡位置 for(int step0; step50; step) { // 设置参数值 opti.set_value(x0, current_state); opti.set_value(x_ref, target_state); // 求解优化问题 auto t1 std::chrono::high_resolution_clock::now(); cd::OptiSol sol opti.solve(); auto t2 std::chrono::high_resolution_clock::now(); // 获取最优控制 std::vectordouble u_opt sol.value(U(cd::Slice(), 0)); std::cout Step step : Control u_opt[0] | Solve time std::chrono::durationdouble(t2-t1).count()*1000 ms std::endl; // 模拟系统响应 current_state std::vectordouble{ current_state[0] dt*current_state[1], current_state[1] dt*(sin(current_state[0]) u_opt[0]) }; } return 0; }这个案例展示了如何利用CasADi快速实现一个完整的NMPC控制器包括非线性系统建模RK4离散化优化问题构建实时闭环控制编译时需要链接所有相关库g inverted_pendulum.cpp -o pendulum -lcasadi -lcoinmumps -lcoinhsl -lipopt

更多文章