PSOPT软件包解读
一、总体思路
给定最优控制问题,包含目标函数、动态约束、路径约束和边界条件等,利用基于节点基的伪谱方法将其转化为非线性规划问题,再利用ipopt软件包进行求解。
前面的一系列操作都是为了构造与ipopt相对应的接口,使得问题能够被ipopt操作。
ipopt软件包的使用方法可以参考官方说明文档:ipopt的C++接口
二、问题定义
alpine.cxx
首先给出问题涉及到的函数,以alpine为例,给出了目标函数、动态约束、路径约束、边界条件(分别定义了四个相应的函数)。
其次需要定义:
- algorithm结构体(存放与算法相关的变量);
- problem类(存放与问题相关的变量和函数,这里的函数就是上面说的函数)
- solution类(存放与解相关的变量和函数,这里的函数是与得到问题的解(如控制、状态、时间、参数)相关的函数)。
定义好类和结构体之后,根据问题给里面的变量赋值,调整大小以及给定初始猜测值。
三、伪谱法
psopt.cxx
定义好问题相关的函数及变量,并给定初始值之后,调用psopt进行后续的转化操作。
- 利用unique_ptr独享指针,定义一个workspace,把algorithm、problem、solution都放到里面,这样后面可以直接利用指针(*)或者引用(&)传workspace就能对三者里面的变量进行操作了。接着对solution里面的变量进行了初始化,然后调用psopt的主函数。
- psopt的主函数里,首先是得到一些区间、点的数量,并将变量的大小进行resize,可能是为了方便运算。
- 接着计算LGL配置点(workspace->snodes)、权重(workspace->w[i])、以及伪谱微分矩阵(workspace->D[i]),并对配置点进行排序。(这里的配置点就是伪谱配置法所选择的节点,伪谱微分矩阵就是后面转化所需要的系数矩阵)
- 根据主函数中的定义,给定NLP的初始猜测值,包括初始时间、参数、控制、状态,
并对un和xn根据初始点,在给定的点进行线性插值。给定的点是时间转化后得到的点。后续也是类似的给定初始猜测值,只不过多了一个拉格朗日插值。 - 然后再利用预先设定的值乘以缩放的比例,得到NLP问题的各种边界,统一存放到xu和xl中。
- 随后调用NLP_interface函数,该函数是PSOPT与IPOPT的接口函数,通过将之前初始化好的算法、x0初始值、数值微分的NLP成本函数、数值微分的NLP不等式约束、nlp限制的数量、nlp等式的数量、x的下上边界传进去就可以求得结果。(也就是说,这里就把前面需要准备的变量等都准备好了,传入了IPOPT的接口,调用后就可以得到结果。可以参考ipopt的C++接口)