1. PSO(粒子群优化):粒子速度/位置更新公式
粒子群优化算法(Particle Swarm Optimization, PSO)是一种基于群体智能的启发式算法,模拟了鸟群觅食的行为。在优化问题中,每个"粒子"代表解空间中的一个候选解。
它的核心就在于两个更新公式。假设在 D D D 维搜索空间中,第 i i i 个粒子的位置为 x i = ( x i 1 , x i 2 , ... , x i D ) x_i = (x_{i1}, x_{i2}, \dots, x_{iD}) xi=(xi1,xi2,...,xiD),速度为 v i = ( v i 1 , v i 2 , ... , v i D ) v_i = (v_{i1}, v_{i2}, \dots, v_{iD}) vi=(vi1,vi2,...,viD)。
- 速度更新公式:
v i ( t + 1 ) = w ⋅ v i ( t ) + c 1 ⋅ r 1 ⋅ ( p b e s t i − x i ( t ) ) + c 2 ⋅ r 2 ⋅ ( g b e s t − x i ( t ) ) v_{i}(t+1) = w \cdot v_{i}(t) + c_1 \cdot r_1 \cdot (pbest_{i} - x_{i}(t)) + c_2 \cdot r_2 \cdot (gbest - x_{i}(t)) vi(t+1)=w⋅vi(t)+c1⋅r1⋅(pbesti−xi(t))+c2⋅r2⋅(gbest−xi(t)) - 位置更新公式:
x i ( t + 1 ) = x i ( t ) + v i ( t + 1 ) x_{i}(t+1) = x_{i}(t) + v_{i}(t+1) xi(t+1)=xi(t)+vi(t+1)
公式参数详解(这是你在论文和代码中需要重点关注的):
- w w w (惯性权重 Inertia Weight): 决定了粒子保持原有速度的趋势。 w w w 较大时,全局寻优(探索)能力强; w w w 较小时,局部寻优(开发)能力强。
- c 1 c_1 c1 (个体学习因子 Cognitive Factor): 粒子向自身历史最优位置 ( p b e s t i pbest_i pbesti) 靠近的步长。代表粒子的"自我经验"。
- c 2 c_2 c2 (社会学习因子 Social Factor): 粒子向全局历史最优位置 ( g b e s t gbest gbest) 靠近的步长。代表群体间的信息共享和"向榜样学习"。
- r 1 , r 2 r_1, r_2 r1,r2:在 [ 0 , 1 ] [0,1] [0,1] 之间均匀分布的随机数,增加搜索的随机性,避免陷入局部最优。
2. Matlab:PSO 优化参数实战
在 Matlab 中使用 PSO 优化参数,通常是为了解决非线性、非凸的复杂系统寻优问题。在 HEV 仿真中,这通常表现为**"Matlab 脚本 (PSO 算法) + Simulink 模型 (HEV 物理模型)"**的联合仿真。
实战工作流与代码逻辑:
- 定义适应度函数 (Fitness Function): 这是优化的目标。例如在
hev_test01这样的项目中,适应度函数通常需要调用 Simulink 模型运行仿真,然后提取输出变量(如out_Fuel、out_SOC、out_I_bat)来计算综合成本。- 代价函数示例: J = α ⋅ Fuel + β ⋅ ∣ SOC f i n a l − SOC t a r g e t ∣ J = \alpha \cdot \text{Fuel} + \beta \cdot |\text{SOC}{final} - \text{SOC}{target}| J=α⋅Fuel+β⋅∣SOCfinal−SOCtarget∣
- 设置 PSO 参数并调用函数: 在 Matlab 中,可以使用自带的
particleswarm函数,或者自己编写 PSO 循环。- 需要定义变量的上下限(例如控制策略中某个阈值或 PI 控制器的 K p , K i K_p, K_i Kp,Ki 范围)。
- Simulink 交互: 在适应度函数内部,使用
assignin('base', 'param_name', x)将 PSO 生成的当前粒子参数传递给工作区,然后使用sim('hev_test01')运行模型,最后将仿真结果返回给 PSO 算法评估。
3. 控制理论在混动应用总结(论文引言创新对比)
这一部分是为论文的 Introduction (引言) 准备的,目的是通过对比现有控制理论的优缺点,引出你所采用方法的创新性 (Novelty)。混动汽车的能量管理策略 (EMS) 控制理论通常可以总结为以下三大类,你可以按照这个递进逻辑来撰写论文:
A. 基于规则的控制策略 (Rule-based Strategies)
- 代表方法: 确定性规则(如 CD-CS 模式切换、恒温器控制)、模糊逻辑控制 (Fuzzy Logic)。
- 特点: 依赖专家经验,计算量小,易于在实车控制器中实现。
- 局限性: 适应性差,无法保证在各种复杂工况(Drive Cycles)下都能达到燃油经济性最优。
- 引入 PSO 的契机: 传统规则的阈值或模糊控制的隶属度函数通常是人工标定的,可以使用 PSO 算法对这些规则参数进行全局寻优,从而提升规则策略的性能。
B. 基于优化的控制策略 (Optimization-based Strategies)
- 全局优化: 动态规划 (Dynamic Programming, DP)。
- 对比点: 能提供理论上的绝对最优解(通常作为 Benchmark),但存在"维数灾难",且需要预知全部路况,无法实时在线应用。
- 瞬时优化: 等效燃油消耗极小化策略 (ECMS)、模型预测控制 (MPC)。
- 对比点: 可以在线实时计算。但 ECMS 的核心等效因子 (Equivalence Factor) 极其敏感,固定等效因子难以适应工况变化(可引入 PSO 在线或离线优化该因子)。MPC 则非常依赖精确的被控对象数学模型。
C. 基于学习的智能控制策略 (Learning-based / Data-driven)
- 代表方法: 强化学习 (Reinforcement Learning),特别是深度强化学习如 DQN (Deep Q-Network)。
- 创新对比(重点展示): 相比于传统控制和优化策略,强化学习(如 DQN)具有无模型依赖 (Model-free) 的强大优势。它不需要建立极其复杂的 HEV 内部精确物理模型,而是通过与环境(Simulink 模型)的不断交互(trial-and-error),通过状态(如 SOC、车速、需求扭矩)和奖励(如低油耗、维持 SOC)来自动学习最优控制动作。
- 逻辑闭环: 引言可以先陈述规则策略的非最优性,再指出优化策略对模型和算力的苛刻要求,最后引出深度强化学习(DQN)在处理复杂非线性 HEV 能量管理中的自适应性和优越性,以及启发式算法(如PSO)在辅助参数整定方面的作用。
场景设定:寻找最佳的发动机启停阈值
假设你的 Simulink 模型中采用了一个最基础的"恒温器控制策略"(基于规则的控制)。
- 规则是这样的: 当电池电量 (SOC) 低于阈值
SOC_low时,发动机强制启动充电;当 SOC 高于阈值SOC_high时,发动机停机,纯电行驶。 - 优化目标: 这两个阈值到底设置成多少,才能让整车在跑完一个循环工况(比如 WLTC 测试循环)后,总油耗最低?靠人工经验很难试出最优解,这就需要 PSO 出马。
角色分工
- 粒子 (Particle): 代表算法提出的一组"候选方案",也就是一对具体的数值
[SOC_low, SOC_high]。 - 适应度 (Fitness): 评判这组方案好坏的标准,在这里就是总油耗。油耗越低,说明这组参数的适应度越好。
- 环境 (Environment): 你的 Simulink 模型。它负责模拟真实的车辆物理反馈。
实战演练流程 (以一次迭代为例)
1. 随机撒网 (Matlab 端初始化)
算法一开始并不知道正确答案,于是随机生成了几组"粒子"(假设只有3个,便于理解):
- 粒子 A 方案:
[0.30, 0.80] - 粒子 B 方案:
[0.45, 0.65] - 粒子 C 方案:
[0.20, 0.90]
2. 跑仿真测油耗 (Matlab 驱动 Simulink)
Matlab 拿着粒子 A 的方案 [0.30, 0.80],把它赋值给工作区。然后,Matlab 通过代码自动触发 Simulink 运行。
Simulink 模型带着这对阈值跑完了一次完整的驾驶工况,输出一个最终结果:消耗燃油 5.2 L。
紧接着:
- Simulink 跑粒子 B 方案,得出油耗 4.8 L。
- Simulink 跑粒子 C 方案,得出油耗 5.8 L。
3. 总结经验 (Matlab 端评估)
现在,PSO 算法心里有数了:目前表现最好的是粒子 B (4.8 L)。
- 对于这三个粒子来说,它们把当前的参数记为自己的"历史最佳" ( p b e s t pbest pbest)。
- 整个群体把粒子 B 的方案
[0.45, 0.65]记为目前的"全局最佳" ( g b e s t gbest gbest),也就是大家都要学习的榜样。
4. 调整策略 (PSO 核心公式发挥作用)
接下来,粒子们要准备下一轮尝试了。它们会利用速度和位置更新公式 来调整自己的数值。
以粒子 A 为例:
- 它发现自己的成绩 (5.2 L) 不如群体的榜样 B (4.8 L)。
- 于是,受公式中 社会学习因子 ( c 2 c_2 c2) 的驱动,粒子 A 下一次产生的新参数,会不自觉地向榜样的数值
[0.45, 0.65]靠拢。 - 经过公式计算,粒子 A 下一次可能就变为了新方案:
[0.38, 0.72]。
5. 循环往复,直到收敛
所有的粒子都会在 Matlab 的指挥下,不断重复 "生成新参数 -> 发给 Simulink 跑仿真 -> 看油耗结果 -> 更新最佳纪录 -> 调整下一次方向" 这个循环。
经过几十代甚至上百代的迭代,所有的粒子最终都会慢慢聚集在一个点上(比如 [0.35, 0.75])。当算法发现不管怎么调整,油耗都无法再低于 4.5 L 时,迭代结束。
此时,[0.35, 0.75] 就是 PSO 帮你找到的最优控制参数。
第一步:新建模型与全局设置
- 打开 MATLAB (R2022b),在主页点击 Simulink ,选择 Blank Model(空白模型)。
- 保存文件并严格命名为
hev_test01.slx,确保存放在与 PSO 脚本相同的文件夹中。 - 按
Ctrl + E打开模型配置参数 (Model Configuration Parameters):- Solver selection -> Type: 选择
Fixed-step(定步长)。 - Solver: 选择
ode3 (Bogacki-Shampine)或auto。 - Fixed-step size: 输入
1(代表仿真步长为 1 秒)。 - 仿真时间 (Stop time) 设为
1000。
- Solver selection -> Type: 选择
第二步:添加核心模块与参数配置
在 Simulink 库浏览器 (Library Browser) 中找到以下模块拖入画布,并双击修改对应的参数:
1. 工作区变量输入 (接收 PSO 参数)
- Constant (常量模块) x 2 (路径: Simulink / Sources)
- 第 1 个:将
Constant value改为SOC_low。 - 第 2 个:将
Constant value改为SOC_high。 - (注:画布上会报错显示未定义,没关系,运行 PSO 脚本时会自动注入。)
- 第 1 个:将
2. 工况与负载模拟 (模拟驾驶员需求功率)
- Sine Wave (正弦波模块) (路径: Simulink / Sources)
Amplitude(振幅):20Bias(偏置):30Frequency(频率):0.01- (代表需求功率 P r e q P_{req} Preq 在 10kW 到 50kW 之间波动)
3. 能量管理控制器 (核心逻辑)
-
MATLAB Function (自定义代码块) (路径: User-Defined Functions)
- 双击打开编辑器,将里面的代码完全替换为以下逻辑(这是一个带记忆功能的恒温器控制逻辑):
matlabfunction Eng_State = fcn(SOC, SOC_low, SOC_high) % 声明持久变量以记住上一秒的发动机状态 persistent state; if isempty(state) state = 0; % 初始状态:发动机关闭 end % 启停逻辑 if SOC <= SOC_low state = 1; % 强制启动充电 elseif SOC >= SOC_high state = 0; % 电池够用,停机 end Eng_State = state; end
4. 动力学计算 (发动机与电池)
- Gain (增益模块) x 3 (路径: Simulink / Math Operations)
- 第 1 个 (计算发动机发电功率):
Gain设为40(假设发动机启动时恒定输出 40kW)。 - 第 2 个 (计算电池消耗速率):
Gain设为-1000 / (300 * 50 * 3600)。(公式含义:将千瓦转为安秒,除以300V电压和50Ah容量的电池总能量,得到每秒 SOC 变化率)。 - 第 3 个 (计算瞬时油耗):
Gain设为3(假设发动机启动时,每秒耗油 3 克)。
- 第 1 个 (计算发动机发电功率):
- Sum (求和模块) (路径: Simulink / Math Operations)
List of signs:+-(用于计算电池实际承担的功率: P b a t = P r e q − P e n g P_{bat} = P_{req} - P_{eng} Pbat=Preq−Peng)。
- Integrator (积分器模块) x 2 (路径: Simulink / Continuous)
- 第 1 个 (用于计算实时 SOC):
Initial condition(初始值) 设为0.6。 - 第 2 个 (用于计算累计油耗):
Initial condition设为0。
- 第 1 个 (用于计算实时 SOC):
5. 仿真结果输出 (传回给 PSO)
- To Workspace (输出到工作区) x 3 (路径: Simulink / Sinks)
- 非常关键的设置(三个模块都要改): 双击打开,将
Save format从默认的Timeseries改为Array。 - 第 1 个:
Variable name改为out_Fuel。 - 第 2 个:
Variable name改为out_SOC。 - 第 3 个:
Variable name改为out_I_bat。
- 非常关键的设置(三个模块都要改): 双击打开,将
第三步:模块连接方式 (信号流向)
现在,请按照以下逻辑将上述模块用信号线连接起来:
- 控制器触发:
- 将两个 Constant 模块 (
SOC_low和SOC_high) 分别连到 MATLAB Function 的第 2 和第 3 个输入端口。
- 将两个 Constant 模块 (
- 功率分配计算:
- 将 MATLAB Function 的输出 (
Eng_State) 连接到 Gain 模块1 (40kW)。这代表发动机的实际输出功率 P e n g P_{eng} Peng。 - 将 Sine Wave (工况 P r e q P_{req} Preq) 连到 Sum 模块 的
+端口。 - 将 Gain 模块1 ( P e n g P_{eng} Peng) 连到 Sum 模块 的
-端口。这样 Sum 的输出就是电池需要提供的功率 P b a t P_{bat} Pbat。
- 将 MATLAB Function 的输出 (
- 电池 SOC 闭环:
- 将 Sum 模块 的输出连到 Gain 模块2 (计算 SOC 变化率)。
- 将 Gain 模块2 的输出连到 第 1 个 Integrator (计算实时 SOC)。
- 闭环关键步: 将 第 1 个 Integrator 的输出,回连到 MATLAB Function 的第 1 个输入端口 (
SOC)。同时将一根分支连到 To Workspace (out_SOC)。 - 将 Sum 模块 的输出引出一根分支,连到 To Workspace (
out_I_bat) (此处为简化,直接记录功率波动代替电流)。
- 油耗计算:
- 从 MATLAB Function 的输出 (
Eng_State) 引出一条线,连到 Gain 模块3 (耗油率 3g/s)。 - 将 Gain 模块3 的输出连到 第 2 个 Integrator。
- 将 第 2 个 Integrator 的输出连到 To Workspace (
out_Fuel)。
- 从 MATLAB Function 的输出 (
按照上述步骤搭建完毕后,你的 Simulink 模型就已经具备了物理仿真和逻辑控制的能力,并且接口名称与你的 PSO 脚本完全对应。现在你可以直接运行上一轮提供的 main_pso_hev.m 了。
1. PSO 主脚本 (main_pso_hev.m)
这段代码是"指挥官",负责初始化粒子群并配置算法参数。
matlab
% main_pso_hev.m
% PSO 优化 HEV 能量管理策略 (SOC上下限)
clear; clc;
% 1. 设置优化变量
nVars = 2; % 优化变量个数:[SOC_low, SOC_high]
% 变量的下限 [SOC_low_min, SOC_high_min]
lb = [0.20, 0.60];
% 变量的上限 [SOC_low_max, SOC_high_max]
ub = [0.45, 0.90];
% 2. PSO 算法配置
% 使用 MATLAB 自带的 particleswarm 函数
options = optimoptions('particleswarm', ...
'SwarmSize', 20, ... % 粒子群规模 (建议20-50)
'MaxIterations', 30, ... % 最大迭代次数
'Display', 'iter', ... % 在命令行实时显示每次迭代的最优代价
'UseParallel', false); % 是否并行计算 (若为 true,需提前开 parpool)
% 3. 运行 PSO 算法
fprintf('开始启动联合仿真优化...\n');
% @fitness_hev 是我们下一步要定义的适应度函数
[best_vars, best_cost, exitflag, output] = particleswarm(@fitness_hev, nVars, lb, ub, options);
% 4. 输出最终优化结果
fprintf('\n--- 优化完成 ---\n');
fprintf('最佳 SOC_low 阈值 : %.4f\n', best_vars(1));
fprintf('最佳 SOC_high 阈值: %.4f\n', best_vars(2));
fprintf('最低综合惩罚代价 : %.4f\n', best_cost);
2. 适应度函数 (fitness_hev.m)
这段代码是连接 PSO 与 Simulink 的"桥梁"。它负责将粒子生成的参数压入工作区,驱动模型运行,并提取 out_Fuel 等结果计算代价。
matlab
% fitness_hev.m
function cost = fitness_hev(x)
% 输入参数 x 是一个 1x2 向量: x(1) 为 SOC_low, x(2) 为 SOC_high
% 逻辑约束:强行惩罚 SOC_low 大于等于 SOC_high 的无效粒子
if x(1) >= x(2)
cost = 1e6; % 返回极大的代价,算法会自动淘汰这个粒子
return;
end
% 1. 将粒子参数传递给基础工作区,供 Simulink 中的常量模块调用
assignin('base', 'SOC_low', x(1));
assignin('base', 'SOC_high', x(2));
% 2. 运行 Simulink 模型
try
% 驱动 hev_test01 模型,并捕获工作区输出
simOut = sim('hev_test01', 'ReturnWorkspaceOutputs', 'on');
% 3. 提取仿真输出数据
% 提取模型运行结束时的累计油耗和电池状态
fuel_consumed = simOut.out_Fuel(end);
final_soc = simOut.out_SOC(end);
% i_bat_trajectory = simOut.out_I_bat; % 备用,可用于电池寿命衰减计算
% 4. 计算综合适应度 (代价 Cost)
% HEV 优化的核心在于"等效油耗"。需要对维持 SOC 进行惩罚。
% 假设我们希望循环工况结束后,SOC 能维持在初始值 0.6 附近
target_soc = 0.6;
soc_penalty_weight = 50; % 惩罚系数,需要根据实际电池容量标定
% 代价 = 实际消耗燃油 + SOC 偏差惩罚
soc_penalty = abs(final_soc - target_soc) * soc_penalty_weight;
cost = fuel_consumed + soc_penalty;
catch ME
% 如果仿真报错(例如代数环报错),捕获错误并赋予极大代价,保证 PSO 循环不中断
warning('Simulink 运行出错: %s', ME.message);
cost = 1e6;
end
end
3. Simulink 模型的对应设置要求
为了让上面的代码完美运行,你需要确保 hev_test01.slx 模型内部具备以下结构和配置:
- 输入参数模块 (Parameters):
- 在模型中建立两个
Constant(常量)模块。 - 将第一个常量模块的 Value 参数设为
SOC_low,第二个设为SOC_high。它们会自动读取 MATLAB 工作区由assignin注入的值。
- 在模型中建立两个
- 控制逻辑模块 (Controller Logic):
- 使用
Relational Operator(关系运算符)将实时获取的车辆SOC信号与SOC_low和SOC_high进行比较。 - 连接方式:将
SOC <= SOC_low的布尔信号接入一个 SR 触发器(S-R Flip-Flop 或 Stateflow 图)的 Set 端口(置位启动发动机),将SOC >= SOC_high接入 Reset 端口(复位关闭发动机)。
- 使用
- 数据输出模块 (To Workspace):
- 准备三个
To Workspace模块。 - 分别连接记录发动机累计油耗的信号、电池实时 SOC 信号、电池电流信号。
- 关键参数设置: 双击这三个
To Workspace模块,将它们的 Variable name 分别严格命名为out_Fuel、out_SOC和out_I_bat。并将 Save format 设置为 Array 或 Timeseries。
- 准备三个
你只需将这两个 .m 文件与你的 hev_test01.slx 模型放在同一个文件夹下,运行主脚本,就可以直观地看到粒子群寻找最佳控制阈值的迭代过程了。
bash
> 位置:test06_2 (第 38 行)
位置: fcnvectorizer (第 19 行)
位置: particleswarm>pswcore (第 370 行)
位置: particleswarm (第 154 行)
位置: test06_1 (第 23 行)
警告: Simulink 运行出错: 检测到程序中断(Ctrl-C)。
这是一个在 MATLAB/Simulink 联合仿真中非常经典且常见的报错 。你遇到的问题核心在于:连续系统与离散状态记忆的冲突。
为什么会报错?
在你之前的配置中,模型使用的是 ode3 求解器(这是一个连续时间 求解器)。在连续系统中,仿真引擎为了保证精度,会在1秒钟内进行多次"微小步长"的试探性计算(称为 Minor Time Steps)。
如果在 MATLAB Function 里使用了 persistent(持久变量)来记忆上一秒的状态,Simulink 在进行那些微小的试探性计算时,会不断意外地覆盖和改写这个记忆变量,导致系统逻辑完全混乱。因此,Simulink 严禁在连续采样时间的模块中使用 persistent 变量,并抛出了这个报错。
(至于你看到的第二个报错 检测到程序中断(Ctrl-C),是因为第一个报错导致 Simulink 陷入了逻辑死锁或无限报错循环,你被迫手动停止了它,这很正常。)
解决方案:将"内部记忆"改为"外部记忆"
为了完美解决这个问题,我们需要把"记住上一秒状态"的任务从代码内部(persistent)拿出来,交给 Simulink 专用的延迟模块来做。这在 Simulink 建模中被称为状态反馈 (State Feedback)。
请按照以下两步修改你的 hev_test01.slx 模型:
第一步:修改 MATLAB Function 的代码
双击打开你的 MATLAB Function 模块,把里面的代码全部替换为以下内容:
matlab
function Eng_State = fcn(SOC, SOC_low, SOC_high, Prev_State)
% 移除 persistent 变量,新增一个输入端口 Prev_State
% Prev_State 代表从外部传入的"上一时刻的发动机状态"
if SOC <= SOC_low
Eng_State = 1; % 强制启动充电
elseif SOC >= SOC_high
Eng_State = 0; % 电池够用,停机
else
Eng_State = Prev_State; % 维持上一时刻的状态
end
end
保存代码后回到 Simulink 画布,你会发现 MATLAB Function 模块多出了一个输入端口:Prev_State。
第二步:在 Simulink 中添加 Memory 模块闭环
现在我们需要把输出的结果"延迟一步"后送回到这个新端口。
- 添加 Memory 模块: 在 Simulink 库浏览器中,找到 Simulink -> Discrete ,将 Memory (记忆)模块拖入画布。(如果找不到,在画布空白处双击,输入
Memory并回车)。 - 连接反馈回路:
- 将 MATLAB Function 的输出线 (
Eng_State) 引出一条分支,连接到 Memory 模块的输入端。 - 将 Memory 模块的输出端,连接到 MATLAB Function 新增的
Prev_State输入端口。
- 将 MATLAB Function 的输出线 (
- 设置初始值: 双击 Memory 模块,将其
Initial condition(初始状态)设置为0(代表一开始发动机是关闭的)。
这样改的好处:
加上 Memory 模块后,你不仅完美避开了 Simulink 的报错规则,同时 Memory 模块还起到了"打破代数环 (Algebraic Loop)"的关键作用。它明确告诉 Simulink:"拿上一次计算的确定结果,作为这一次逻辑判断的依据",这样连续求解器就不会产生逻辑死锁了。
bash
开始启动联合仿真优化...
Best Mean Stall
Iteration f-count f(x) f(x) Iterations
0 20 3006 3006 0
1 40 3006 3006 0
2 60 3006 3006 1
3 80 3006 3006 2
4 100 3006 3006 3
5 120 3006 3006 4
6 140 3006 3006 5
7 160 3006 3006 6
8 180 3006 3006 7
9 200 3006 3006 8
10 220 3006 3006 9
11 240 3006 3006 10
12 260 3006 3006 11
13 280 3006 3006 12
14 300 3006 3006 13
15 320 3006 3006 14
16 340 3006 3006 15
17 360 3006 3006 16
18 380 3006 3006 17
19 400 3006 3006 18
20 420 3006 3006 19
21 440 3006 3006 20
Optimization ended: relative change in the objective value
over the last OPTIONS.MaxStallIterations iterations is less than OPTIONS.FunctionTolerance.
--- 优化完成 ---
最佳 SOC_low 阈值 : 0.2305
最佳 SOC_high 阈值: 0.7010
最低综合惩罚代价 : 3005.8536