You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Dymos中为两个串联阶段的状态设置终值边界约束?

在Dymos中为串联独立阶段添加状态边界约束的优化方案

你完全可以利用Dymos的**多阶段轨迹(Trajectory)**功能来实现需求,这种方式不仅逻辑清晰,还能针对不同阶段设置差异化的转录精度,完美解决你提到的网格细化效率问题。具体步骤如下:

1. 创建两个独立的阶段

分别定义带控制的第一阶段和无控制的第二阶段,复用同一个ODE系统即可,第二阶段只需将控制变量固定为0(或根据需求设置为恒定值)。同时为两个阶段设置不同的转录参数——无控制阶段用更粗的网格来节省计算资源。

2. 用Trajectory串联阶段并添加边界约束

通过Trajectory将两个阶段组合,然后直接添加阶段间的状态连接约束,让第一阶段的终态与第二阶段的初态相等。终时间可设为自由变量,既可以单独控制每个阶段的时长,也可以将总时长作为设计变量。

代码示例

import openmdao.api as om
import dymos as dm
import numpy as np

# 假设你的ODE系统定义如下(根据实际需求调整)
class MyDynamics(om.ExplicitComponent):
    def initialize(self):
        self.options.declare('num_nodes', types=int)
    
    def setup(self):
        nn = self.options['num_nodes']
        # 状态变量
        self.add_input('x', shape=(nn,), units='m')
        # 控制变量
        self.add_input('u', shape=(nn,), units='m/s^2')
        # 状态导数
        self.add_output('x_dot', shape=(nn,), units='m/s')
        
        # 声明雅可比矩阵
        arange = np.arange(nn)
        self.declare_partials(of='x_dot', wrt='x', rows=arange, cols=arange)
        self.declare_partials(of='x_dot', wrt='u', rows=arange, cols=arange)
    
    def compute(self, inputs, outputs):
        x = inputs['x']
        u = inputs['u']
        outputs['x_dot'] = x + u  # 示例动力学方程,替换为你的实际ODE
    
    def compute_partials(self, inputs, jacobian):
        jacobian['x_dot', 'x'] = 1.0
        jacobian['x_dot', 'u'] = 1.0

# 初始化优化问题
prob = om.Problem()
traj = prob.model.add_subsystem('traj', dm.Trajectory())

# 第一阶段:带控制,使用较精细的网格
phase1 = traj.add_phase(
    'phase1',
    dm.Phase(
        ode_class=MyDynamics,
        transcription=dm.Radau(num_segments=10, order=3)  # 精细网格适配带控制的动力学
    )
)
phase1.set_time_options(fix_initial=True, duration_bounds=(1.0, 10.0), units='s')
phase1.add_state('x', fix_initial=True, rate_source='x_dot', units='m')
phase1.add_control('u', units='m/s^2', lower=-5, upper=5)

# 第二阶段:无控制,使用粗网格
phase2 = traj.add_phase(
    'phase2',
    dm.Phase(
        ode_class=MyDynamics,
        transcription=dm.Radau(num_segments=2, order=3)  # 粗网格满足无控制的动力学需求
    )
)
phase2.set_time_options(fix_initial=False, duration_bounds=(1.0, 10.0), units='s')
phase2.add_state('x', fix_initial=False, rate_source='x_dot', units='m')
# 固定控制变量为0,实现无控制阶段
phase2.add_control('u', units='m/s^2', val=0.0, fix=True)

# 添加阶段间的状态约束:phase1的终态x等于phase2的初态x
traj.add_link_constraint('phase1.x', 'phase2.x', loc1='final', loc2='initial')

# 设置终时间为自由变量(可选:将总时长设为设计变量)
prob.model.add_subsystem('total_duration', om.ExecComp(
    'T = t1 + t2',
    t1={'units':'s'}, t2={'units':'s'}, T={'units':'s'}
))
prob.model.connect('traj.phase1.duration', 'total_duration.t1')
prob.model.connect('traj.phase2.duration', 'total_duration.t2')
prob.model.add_design_var('total_duration.T', lower=2.0, upper=20.0)

# 配置求解器并运行
prob.driver = om.ScipyOptimizeDriver()
prob.setup()
prob.run_driver()

方案优势

  • 计算效率更高:两个阶段独立设置网格精度,无控制阶段用粗网格大幅减少计算量,网格细化仅作用于需要精细描述的带控制阶段。
  • 逻辑更清晰:将不同动力学特性的阶段拆分,代码可读性和可维护性更强。
  • 灵活性更强:可单独调整每个阶段的时间边界、约束条件,适配更复杂的任务需求。

内容的提问来源于stack exchange,提问作者wonderboy3489

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 21:20:00