【记录】linux安装osqp、osqp-eigen过程,并实现计算
·
提前准备资源:
eigen库—安装ros时已经安装好
cmake版本应该与osqp库对应
ooqp版本 libglog.so.0.6.0
osqp-eigen版本 libOsqpEigen.so.0.8.1
osqp及osqp-eigen包下载:
https://download.csdn.net/download/weixin_58477062/90001430
1.Cmake安装
Cmake如果版本不对,请升级版本 Index of /files
tar -xzvf cmake-3.18.5.tar.gz
cd cmake-3.24.3
./bootstrap
make
sudo make install

查看Cmake版本
cmake --version
2.安装osqp库
进入下载好的osqp文件夹
cd osqp
# 编译并安装
mkdir build
cd build
cmake ..
make
sudo make install
3.安装osqp-eigen库
cd osqp-eigen
mkdir build
cd build
cmake ..
make
sudo make install
4.ros创建功能包调用
参考代码
Using osqp-eigen in MPC fashion | osqp-eigen
// osqp-eigen
#include "OsqpEigen/OsqpEigen.h"
// eigen
#include <Eigen/Dense>
#include <iostream>
void setDynamicsMatrices(Eigen::Matrix<double, 12, 12>& a, Eigen::Matrix<double, 12, 4>& b)
{
a << 1., 0., 0., 0., 0., 0., 0.1, 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0.1, 0., 0.,
0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0.1, 0., 0., 0., 0.0488, 0., 0., 1., 0., 0., 0.0016,
0., 0., 0.0992, 0., 0., 0., -0.0488, 0., 0., 1., 0., 0., -0.0016, 0., 0., 0.0992, 0., 0.,
0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0.0992, 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0.,
0., 0., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 0.,
0., 0., 0.9734, 0., 0., 0., 0., 0., 0.0488, 0., 0., 0.9846, 0., 0., 0., -0.9734, 0., 0., 0.,
0., 0., -0.0488, 0., 0., 0.9846, 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.9846;
b << 0., -0.0726, 0., 0.0726, -0.0726, 0., 0.0726, 0., -0.0152, 0.0152, -0.0152, 0.0152, -0.,
-0.0006, -0., 0.0006, 0.0006, 0., -0.0006, 0.0000, 0.0106, 0.0106, 0.0106, 0.0106, 0,
-1.4512, 0., 1.4512, -1.4512, 0., 1.4512, 0., -0.3049, 0.3049, -0.3049, 0.3049, -0.,
-0.0236, 0., 0.0236, 0.0236, 0., -0.0236, 0., 0.2107, 0.2107, 0.2107, 0.2107;
}
void setInequalityConstraints(Eigen::Matrix<double, 12, 1>& xMax,
Eigen::Matrix<double, 12, 1>& xMin,
Eigen::Matrix<double, 4, 1>& uMax,
Eigen::Matrix<double, 4, 1>& uMin)
{
double u0 = 10.5916;
// input inequality constraints
uMin << 9.6 - u0, 9.6 - u0, 9.6 - u0, 9.6 - u0;
uMax << 13 - u0, 13 - u0, 13 - u0, 13 - u0;
// state inequality constraints
xMin << -M_PI / 6, -M_PI / 6, -OsqpEigen::INFTY, -OsqpEigen::INFTY, -OsqpEigen::INFTY, -1.,
-OsqpEigen::INFTY, -OsqpEigen::INFTY, -OsqpEigen::INFTY, -OsqpEigen::INFTY,
-OsqpEigen::INFTY, -OsqpEigen::INFTY;
xMax << M_PI / 6, M_PI / 6, OsqpEigen::INFTY, OsqpEigen::INFTY, OsqpEigen::INFTY,
OsqpEigen::INFTY, OsqpEigen::INFTY, OsqpEigen::INFTY, OsqpEigen::INFTY, OsqpEigen::INFTY,
OsqpEigen::INFTY, OsqpEigen::INFTY;
}
void setWeightMatrices(Eigen::DiagonalMatrix<double, 12>& Q, Eigen::DiagonalMatrix<double, 4>& R)
{
Q.diagonal() << 0, 0, 10., 10., 10., 10., 0, 0, 0, 5., 5., 5.;
R.diagonal() << 0.1, 0.1, 0.1, 0.1;
}
void castMPCToQPHessian(const Eigen::DiagonalMatrix<double, 12>& Q,
const Eigen::DiagonalMatrix<double, 4>& R,
int mpcWindow,
Eigen::SparseMatrix<double>& hessianMatrix)
{
hessianMatrix.resize(12 * (mpcWindow + 1) + 4 * mpcWindow,
12 * (mpcWindow + 1) + 4 * mpcWindow);
// populate hessian matrix
for (int i = 0; i < 12 * (mpcWindow + 1) + 4 * mpcWindow; i++)
{
if (i < 12 * (mpcWindow + 1))
{
int posQ = i % 12;
float value = Q.diagonal()[posQ];
if (value != 0)
hessianMatrix.insert(i, i) = value;
} else
{
int posR = i % 4;
float value = R.diagonal()[posR];
if (value != 0)
hessianMatrix.insert(i, i) = value;
}
}
}
void castMPCToQPGradient(const Eigen::DiagonalMatrix<double, 12>& Q,
const Eigen::Matrix<double, 12, 1>& xRef,
int mpcWindow,
Eigen::VectorXd& gradient)
{
Eigen::Matrix<double, 12, 1> Qx_ref;
Qx_ref = Q * (-xRef);
// populate the gradient vector
gradient = Eigen::VectorXd::Zero(12 * (mpcWindow + 1) + 4 * mpcWindow, 1);
for (int i = 0; i < 12 * (mpcWindow + 1); i++)
{
int posQ = i % 12;
float value = Qx_ref(posQ, 0);
gradient(i, 0) = value;
}
}
void castMPCToQPConstraintMatrix(const Eigen::Matrix<double, 12, 12>& dynamicMatrix,
const Eigen::Matrix<double, 12, 4>& controlMatrix,
int mpcWindow,
Eigen::SparseMatrix<double>& constraintMatrix)
{
constraintMatrix.resize(12 * (mpcWindow + 1) + 12 * (mpcWindow + 1) + 4 * mpcWindow,
12 * (mpcWindow + 1) + 4 * mpcWindow);
// populate linear constraint matrix
for (int i = 0; i < 12 * (mpcWindow + 1); i++)
{
constraintMatrix.insert(i, i) = -1;
}
for (int i = 0; i < mpcWindow; i++)
for (int j = 0; j < 12; j++)
for (int k = 0; k < 12; k++)
{
float value = dynamicMatrix(j, k);
if (value != 0)
{
constraintMatrix.insert(12 * (i + 1) + j, 12 * i + k) = value;
}
}
for (int i = 0; i < mpcWindow; i++)
for (int j = 0; j < 12; j++)
for (int k = 0; k < 4; k++)
{
float value = controlMatrix(j, k);
if (value != 0)
{
constraintMatrix.insert(12 * (i + 1) + j, 4 * i + k + 12 * (mpcWindow + 1))
= value;
}
}
for (int i = 0; i < 12 * (mpcWindow + 1) + 4 * mpcWindow; i++)
{
constraintMatrix.insert(i + (mpcWindow + 1) * 12, i) = 1;
}
}
void castMPCToQPConstraintVectors(const Eigen::Matrix<double, 12, 1>& xMax,
const Eigen::Matrix<double, 12, 1>& xMin,
const Eigen::Matrix<double, 4, 1>& uMax,
const Eigen::Matrix<double, 4, 1>& uMin,
const Eigen::Matrix<double, 12, 1>& x0,
int mpcWindow,
Eigen::VectorXd& lowerBound,
Eigen::VectorXd& upperBound)
{
// evaluate the lower and the upper inequality vectors
Eigen::VectorXd lowerInequality
= Eigen::MatrixXd::Zero(12 * (mpcWindow + 1) + 4 * mpcWindow, 1);
Eigen::VectorXd upperInequality
= Eigen::MatrixXd::Zero(12 * (mpcWindow + 1) + 4 * mpcWindow, 1);
for (int i = 0; i < mpcWindow + 1; i++)
{
lowerInequality.block(12 * i, 0, 12, 1) = xMin;
upperInequality.block(12 * i, 0, 12, 1) = xMax;
}
for (int i = 0; i < mpcWindow; i++)
{
lowerInequality.block(4 * i + 12 * (mpcWindow + 1), 0, 4, 1) = uMin;
upperInequality.block(4 * i + 12 * (mpcWindow + 1), 0, 4, 1) = uMax;
}
// evaluate the lower and the upper equality vectors
Eigen::VectorXd lowerEquality = Eigen::MatrixXd::Zero(12 * (mpcWindow + 1), 1);
Eigen::VectorXd upperEquality;
lowerEquality.block(0, 0, 12, 1) = -x0;
upperEquality = lowerEquality;
lowerEquality = lowerEquality;
// merge inequality and equality vectors
lowerBound = Eigen::MatrixXd::Zero(2 * 12 * (mpcWindow + 1) + 4 * mpcWindow, 1);
lowerBound << lowerEquality, lowerInequality;
upperBound = Eigen::MatrixXd::Zero(2 * 12 * (mpcWindow + 1) + 4 * mpcWindow, 1);
upperBound << upperEquality, upperInequality;
}
void updateConstraintVectors(const Eigen::Matrix<double, 12, 1>& x0,
Eigen::VectorXd& lowerBound,
Eigen::VectorXd& upperBound)
{
lowerBound.block(0, 0, 12, 1) = -x0;
upperBound.block(0, 0, 12, 1) = -x0;
}
double getErrorNorm(const Eigen::Matrix<double, 12, 1>& x, const Eigen::Matrix<double, 12, 1>& xRef)
{
// evaluate the error
Eigen::Matrix<double, 12, 1> error = x - xRef;
// return the norm
return error.norm();
}
int main()
{
// set the preview window
int mpcWindow = 20;
// allocate the dynamics matrices
Eigen::Matrix<double, 12, 12> a;
Eigen::Matrix<double, 12, 4> b;
// allocate the constraints vector
Eigen::Matrix<double, 12, 1> xMax;
Eigen::Matrix<double, 12, 1> xMin;
Eigen::Matrix<double, 4, 1> uMax;
Eigen::Matrix<double, 4, 1> uMin;
// allocate the weight matrices
Eigen::DiagonalMatrix<double, 12> Q;
Eigen::DiagonalMatrix<double, 4> R;
// allocate the initial and the reference state space
Eigen::Matrix<double, 12, 1> x0;
Eigen::Matrix<double, 12, 1> xRef;
// allocate QP problem matrices and vectors
Eigen::SparseMatrix<double> hessian;
Eigen::VectorXd gradient;
Eigen::SparseMatrix<double> linearMatrix;
Eigen::VectorXd lowerBound;
Eigen::VectorXd upperBound;
// set the initial and the desired states
x0 << 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
xRef << 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0;
// set MPC problem quantities
setDynamicsMatrices(a, b);
setInequalityConstraints(xMax, xMin, uMax, uMin);
setWeightMatrices(Q, R);
// cast the MPC problem as QP problem
castMPCToQPHessian(Q, R, mpcWindow, hessian);
castMPCToQPGradient(Q, xRef, mpcWindow, gradient);
castMPCToQPConstraintMatrix(a, b, mpcWindow, linearMatrix);
castMPCToQPConstraintVectors(xMax, xMin, uMax, uMin, x0, mpcWindow, lowerBound, upperBound);
// instantiate the solver
OsqpEigen::Solver solver;
// settings
// solver.settings()->setVerbosity(false);
solver.settings()->setWarmStart(true);
// set the initial data of the QP solver
solver.data()->setNumberOfVariables(12 * (mpcWindow + 1) + 4 * mpcWindow);
solver.data()->setNumberOfConstraints(2 * 12 * (mpcWindow + 1) + 4 * mpcWindow);
if (!solver.data()->setHessianMatrix(hessian))
return 1;
if (!solver.data()->setGradient(gradient))
return 1;
if (!solver.data()->setLinearConstraintsMatrix(linearMatrix))
return 1;
if (!solver.data()->setLowerBound(lowerBound))
return 1;
if (!solver.data()->setUpperBound(upperBound))
return 1;
// instantiate the solver
if (!solver.initSolver())
return 1;
// controller input and QPSolution vector
Eigen::Vector4d ctr;
Eigen::VectorXd QPSolution;
// number of iteration steps
int numberOfSteps = 50;
for (int i = 0; i < numberOfSteps; i++)
{
// solve the QP problem
if (solver.solveProblem() != OsqpEigen::ErrorExitFlag::NoError)
return 1;
// get the controller input
QPSolution = solver.getSolution();
ctr = QPSolution.block(12 * (mpcWindow + 1), 0, 4, 1);
// save data into file
auto x0Data = x0.data();
// propagate the model
x0 = a * x0 + b * ctr;
// update the constraint bound
updateConstraintVectors(x0, lowerBound, upperBound);
if (!solver.updateBounds(lowerBound, upperBound))
return 1;
}
return 0;
}
Cmake配置文件
cmake_minimum_required(VERSION 3.0.2)
project(eigen_demo)
find_package(catkin REQUIRED COMPONENTS
roscpp
std_msgs
)
find_package(Eigen3 REQUIRED)
catkin_package(
INCLUDE_DIRS include
LIBRARIES eigen_demo
CATKIN_DEPENDS roscpp std_msgs
# DEPENDS system_lib
)
include_directories(
include
${catkin_INCLUDE_DIRS}
${EIGEN3_INCLUDE_DIR}
/usr/local/include/osqp # OSQP头文件路径
/usr/local/include/OsqpEigen # OSQP-Eigen头文件路径,需要替换为实际路
)
link_directories(
/usr/local/lib
)
## Declare a C++ library
# add_library(${PROJECT_NAME}
# src/${PROJECT_NAME}/eigen_demo.cpp
# )
add_executable(eigen_demo_node src/eigen_demo_node.cpp)
target_link_libraries(eigen_demo_node
${catkin_LIBRARIES}
osqp
OsqpEigen
)
运行结果:

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐

所有评论(0)