跳转至

构建最优控制问题

简介

Pockit 将连续时间最优控制模型转录为有限维非线性规划。动力学、代价、 约束和端点都由 System 及其阶段提供的 SymPy 符号定义;Pockit 再据此 构造配点方程和稀疏导数。

本页通过一个有效的最短时间模型说明核心建模调用。完整的求解与验证流程见 快速开始;阶段连接、共享变量和状态重置的严格定义见 多阶段指南

选择转录方法

Radau 和 Lobatto 使用相同的建模接口。一个模型只应导入其中一套 System, 不要用后一次导入覆盖前一次导入。

from pockit.radau import System
from pockit.lobatto import System

节点类型的选择方法见 Radau 与 Lobatto 插值。下面的 最短时间模型使用 Radau,因为最优加速度会在已知网格边界处跳变。

构建最小模型

下列代码定义一个双积分器。物体从距离目标一米处静止出发,加速度限制为 一米每二次方秒,终止时间自由:

from pockit.radau import System

system = System(0)
phase = system.new_phase(
    ["position", "velocity"],
    ["acceleration"],
)

position, velocity = phase.x
(acceleration,) = phase.u

phase.set_dynamics([velocity, acceleration])
phase.set_integral([1.0])
phase.set_phase_constraint(
    [acceleration],
    [-1.0],
    [1.0],
    True,
)
phase.set_boundary_condition(
    [1.0, 0.0],
    [0.0, 0.0],
    0.0,
    None,
)
phase.set_discretization([0.0, 0.5, 1.0], [6, 6])

system.set_phase([phase])
system.set_objective(phase.I[0])

System(0) 表示系统没有静态参数。System.new_phase() 会创建状态、控制和 时间符号,阶段内的所有表达式都必须使用这些符号。终止时间传入 None 后会 成为优化变量;常数 1 的积分就是阶段时长,因此最小化 phase.I[0] 等价于 最小化终止时间。

最后一个 True 将加速度约束标记为 bang-bang,供 Pockit 的间断检查使用; 该标记本身不能证明任意模型都具有 bang-bang 最优解。

阶段配置参考

把阶段加入系统之前,先完成阶段配置:

建模内容 方法 输入关系
状态导数 Phase.set_dynamics Phase.x 顺序为每个状态提供一个表达式
运行积分项 Phase.set_integral 求解后通过 Phase.I 访问各积分
路径边界 Phase.set_phase_constraint 表达式、下界和上界列表必须等长
状态与时间端点 Phase.set_boundary_condition None 表示自由,数值表示固定,静态参数表达式表示共享关系
网格与多项式点数 Phase.set_discretization 使用均匀计数,或归一化网格坐标及逐区间点数

阶段表达式可以使用 Phase.xPhase.uPhase.tPhase.s。单边约束 可在开放的一侧使用 -numpy.infnumpy.inf。单独的状态、控制、时间或 静态参数符号会转为变量边界;一般 SymPy 表达式则保留为代数路径约束。

静态参数与多个阶段

静态参数是不随时间变化的优化变量。构造系统时为其命名,随后即可在端点、 目标函数或跨阶段表达式中使用对应符号:

system = System(["event_time"])
(event_time,) = system.s
phase = system.new_phase(["position", "velocity"], ["acceleration"])

# 同一符号可以作为前一阶段的终点和后一阶段的起点。
phase.set_boundary_condition(
    [1.0, 0.0],
    [0.0, 0.0],
    0.0,
    event_time,
)

多阶段系统按照实际发生顺序接收各阶段:

system.set_phase([phase_0, phase_1])
system.set_objective(objective)
system.set_system_constraint(expressions, lower_bounds, upper_bounds)

最后一个片段中的名称表示已经配置好的阶段对象和 SymPy 表达式。 多阶段指南给出了完整数学模式,并链接到三个可运行应用。

修改已配置模型

set_* 调用需要对符号表达式求导并编译数值函数,因此可能耗时较长。在 notebook 中可将主要设置放在不同单元格,只重跑发生变化的关系。若阶段已通过 System.set_phase() 加入系统,修改该阶段后应调用 System.update(),刷新 系统层索引和导数。

配置完成后,还需要构造初值、求解非线性规划,并在配点之间验证重构轨迹。 优化器指南说明两种求解后端;误差检查与网格调整 介绍当前支持的检查与调整流程。