最速降线¶
背景¶
最速降线问题要求寻找这样一条曲线:小球从静止释放,在均匀重力场中无摩擦运动,并以最短时间到达较低的目标点。它的解不是直线而是摆线,因此常用于检验最优控制和变分法。
问题定义¶
这里规定 \(y\) 轴向下为正,路径角 \(\theta\) 从竖直向下方向量起。最短时间问题为
\[
\begin{aligned}
\min_{x,y,v,\theta,t_f}\quad & t_f=\int_0^{t_f}1\,\mathrm{d}t \\
\text{约束}\quad
& \dot{x}=v\sin\theta, \\
& \dot{y}=v\cos\theta, \\
& \dot{v}=g\cos\theta, \qquad g=9.81\ \mathrm{m/s^2}, \\
& [x(0),y(0),v(0)]=[0,0,0], \\
& [x(t_f),y(t_f)]=[2,2], \\
& v\ge0, \qquad 0\le\theta\le\frac{\pi}{2}.
\end{aligned}
\]
终端速度和终止时间均为自由变量。
变量与单位¶
| 符号 | 含义 | 单位 |
|---|---|---|
| \(t\) | 时间 | s |
| \(x\) | 水平位移 | m |
| \(y\) | 向下位移 | m |
| \(v\) | 沿曲线运动的速率 | m/s |
| \(\theta\) | 相对竖直向下方向的路径角 | rad |
| \(g\) | 重力加速度 | \(9.81\ \mathrm{m/s^2}\) |
建模选择¶
采用向下为正的位移,可以让模型中的重力加速度保持正号。速率约束排除了路径参数发生非物理反向的情况,角度边界则选定向右、向下的单调运动。初始猜测采用直线下降路径,并令速率满足 \(v=\sqrt{2gy}\),从而符合机械能守恒。
运行示例¶
在仓库根目录运行:
如需保存图片且不打开窗口:
关键实现¶
import numpy as np
import sympy as sp
from pockit.lobatto import System, linear_guess
system = System(0)
phase = system.new_phase(["x", "y", "speed"], ["path_angle"])
_, _, speed = phase.x
(path_angle,) = phase.u
phase.set_dynamics(
[
speed * sp.sin(path_angle),
speed * sp.cos(path_angle),
9.81 * sp.cos(path_angle),
]
)
phase.set_integral([1.0])
phase.set_phase_constraint(
[speed, path_angle], [0.0, 0.0], [np.inf, np.pi / 2.0]
)
phase.set_boundary_condition([0.0, 0.0, 0.0], [2.0, 2.0, None], 0.0, None)
phase.set_discretization(10, 8)
system.set_phase([phase])
system.set_objective(phase.I[0])
guess = linear_guess(phase, 0.0)
guess.t_f = 1.0
完整示例使用 Ipopt 求解,根据端点几何关系构造解析摆线,并检查数值运动时间是否与解析结果一致。
已验证结果¶
Pockit 得到的最短运动时间为 \(0.824338670697\ \mathrm{s}\),解析摆线结果为 \(0.824338669439\ \mathrm{s}\),两者相差约 \(1.3\times10^{-9}\ \mathrm{s}\)。图中的数值路径与摆线在视觉上重合。

源码¶
完整可运行示例见 examples/brachistochrone.py。