在最小二乘法一章节中我给出了基于matlab仿真下的手推最小二乘解方法,最终采用广义法能将任意多组数据求最小二乘解转换为求取固定矩阵元素平均值的形式从而避免数据增长带来的计算量增大:
https://zhuanlan.zhihu.com/p/267156837zhuanlan.zhihu.com为实现编程应用可以将求解算法单独写入matlab文件的函数中再使用coder将其转换为c或c++代码。最小二乘法的理论知识实际为我们后续基于QP优化或LQR,MPC等最优化控制算法的应用提供了基础的理论支撑,在我的基于QP优化的四足机器人矢量平面足底力优化文章:
https://zhuanlan.zhihu.com/p/264814614zhuanlan.zhihu.com中已经给出介绍了如何基于MATLAB自带优化库构建一个带锥约束的力分配优化问题,但该函数是无法自带转换为代码的,想在如Webots或嵌入式控制器上进行验证测试需要采用专业的非线性优化库。
目前有许多非线性优化算法库如MIT Mini Cheetha开源猎豹机器人中就使用了qpOASES,而在Python环境下能使用Pip命令方便地安装Scipy或cvxopt 等优化库,而在SLAM中g2o或Ceres Solver等能求解大规模优化问题的高性能非线性优化库更被广泛应用。
由于我目前开展的8自由度并联四足机器人仿真在Webots中搭建,基于我知乎中三通道解耦等文章已经实现了稳定的对角步态移动,但对如Bound或Gallop等非对角腿着地情况其力分配的数值求解方程难以列出,同时由于8自由度转向采用差速形式,足底打滑会严重影响位姿控制稳定,需要进一步引入摩擦圆锥约束,因此为在Webots中验证QP力分配的可行性,下面给出这几天在Windows环境下配置非线性优化和矩阵运算库踩过的坑。
(1)建立Webots下的Visual Studio工程
在之前的仿真中由于我使用自己STM32单片机的Moco 12舵狗代码为基础,因此直接采用Webots建立C工程编程,但为使用Eigen等数学库需要转换到C++框架下,因此首先建立在系统中安装VSCoder,原因是后续许多Windows下的cmake或gcc中间件在打开对应文件后其会自动弹出对于插件进行安装。下面首先在Webots中新建C++工程,并再安装VS IDE(原因是可以直接使用VS完成许多库的路径快速准确配置,否则如选用Webots自带的gcc编译器,则需要自己修改makefile来链接需要的库,这将十分麻烦毕竟我们主要是为了研究算法),这里我安装的是VS2017专业版(秘钥KBJFW-NXHK6-W4WJM-CRMQB-G3CDH)。
(2)下载配置Eigen库
在完成VS的安装后打开Webots建立的.sln工程,下面首先安装矩阵运算所需要的Eigen库,从官网下载(http://eigen.tuxfamily.org/index.php?title=Main_Page),当然我在本文最后会贴上所用到的软件资料。由于Eigen库均在头文件中因此,可以其解压直接放置在C盘根目录下,通过在项目属性中配置包含目录可将其快速加入工程中:
之后可以在Webots项目主文件中编辑如下测试代码,点击资源管理器中显示所有文件查看是否包含Eigen目录验证:
#include <Eigen/Dense>
using namespace Eigen;
using namespace std;
void test_eigen(){
Eigen::MatrixXd m = MatrixXd::Random(3, 3); //随机生成3*3的double型矩阵
m = (m + MatrixXd::Constant(3, 3, 1.2)) * 50; //MatrixXd::Constant(3,3,1.2)表示生成3*3的double型矩阵,该矩阵所有元素均为1.2
cout << "m =" << endl << m << endl;
VectorXd v(3); // 定义v为3*1的double型向量
v << 1, 2, 3; // 向量赋值
cout << "v =" << endl << v << endl;
cout << "m * v =" << endl << m * v << endl;
}
编译无误后,在Webots仿真环境中点击运行,查看Eigen矩阵运算结果:
m =
10.1251 90.8741 45.0291
66.3585 68.5009 99.5962
29.3304 57.9873 92.284
v =
1
2
3
m * v =
326.961
502.149
422.157
(3)编译qpOASES
为实现后续在Webots中进行优化仿真和MPC控制仿真,这里给出非线性优化库的配置方法,为实现与MIT相关代码的对应因此我仍然使用qpOASES,qpOASES是一个开源c++项目,是一个可结构开发的有效集求解器可用于解决具有一下标准形式的二次型优化问题:
对于在Windows下配置qpOASES库最麻烦的一点是需要使用make等GNU链接器对下载的源码进行编译,首次编译时我遇到的问题是Window没安装该toolchain使得在qpOASES文件目录下make出错,在我安装MinGW后编译仍然无果,因此我尝试成功的方法是首先使用cmake自动产生对于的makefile之后再进行编译。
当然这也是使用Vscode的好处,当你打开其对应的CMakeLists文件后Vscode会自动检查是否安装,并自动安装cmake插件,在安装完成后CD到对于目录下建立build文件夹在其中输入cmake ..则会自动产生如下配置文件:
之后可以继续使用make命令产生相应的静态库,但由于我GNU配置错误无法执行,因此我安装了VS2017打开其cmake后输出的.sln工程,使用VS2017完成对项目的生成结果如下:
cmake后的工程中有许多example例子可以直接删除仅保留需要的qpOASES相关库,之后如编译报出工具集142故障可以在属性中修改为VS版本的工具集:
编译后在将lib文件夹下产生对应的静态库:
(4)调用测试qpOASES非线性优化库
在生成所需优化库lib后,我们重新回到Webots生成的VS工程中在属性和库目录下包含对应的头文件路径,并通过在项目浏览串口右键添加qpOASES.lib:
之后再在代码中增加对应头文件和如下测试代码验证QP优化库是否工作正常:
#include <qpOASES.hpp>
using namespace qpOASES;
int testQP()
{
/* Setup data of first QP. */
real_t H[2 * 2] = { 1.0, 0.0, 0.0, 0.5 };
real_t A[1 * 2] = { 1.0, 1.0 };
real_t g[2] = { 1.5, 1.0 };
real_t lb[2] = { 0.5, -2.0 };
real_t ub[2] = { 5.0, 2.0 };
real_t lbA[1] = { -1.0 };
real_t ubA[1] = { 2.0 };
/* Setup data of second QP. */
real_t g_new[2] = { 1.0, 1.5 };
real_t lb_new[2] = { 0.0, -1.0 };
real_t ub_new[2] = { 5.0, -0.5 };
real_t lbA_new[1] = { -2.0 };
real_t ubA_new[1] = { 1.0 };
/* Setting up QProblem object. */
QProblem example(2, 1);
/* Solve first QP. */
int_t nWSR = 10;
example.init(H, g, A, lb, ub, lbA, ubA, nWSR);
/* Solve second QP. */
nWSR = 10;
example.hotstart(g_new, lb_new, ub_new, lbA_new, ubA_new, nWSR);
/* Get and print solution of second QP. */
real_t xOpt[2];
example.getPrimalSolution(xOpt);
printf("n xOpt = [ %e, %e ]; objVal = %enn",
xOpt[0], xOpt[1], example.getObjVal());
return 0;
}
编译后返回Webots软件中点击运行,则在控制台中打印如下字符验证库已经安装运行正常:
以上就是我尝试在Webots中建立c++工程并配置Eigen矩阵运算库与QP非线性优化库的大致流程,相关编译后的文件与库函数可在此下载:
链接:https://pan.baidu.com/s/1hzzo3B6Rl7r3XyMz6DRRdQ
提取码:qqvu
则基于上述配置好的环境我们可以对之前提到的最小二乘法或者QP足力优化使用Eigen或qpOASEs库来分别实现,当然在后续文章中会具体给出相关代码实现方法。