
插电式混合动力车辆PHEV的能源管理说穿了就是一句话每一时刻驱动系统需要的功率到底谁来出发动机出多少、电机出多少、电池往里充还是往外放。但这个“一句话问题”落到实际工程里牵扯出来的东西相当多——发动机万有特性是非线性的、电池SOC有硬边界、电机效率随工况变化、驾驶员需求功率还在实时波动。我去年做了一套基于Matlab的能量管理方案核心是用凸优化建模MPC做滚动优化再用ADMM把在线求解的时延压到毫秒级。这篇文章把整个思路、数学原理、代码结构和踩过的坑都说一遍适合正在做PHEV/HEV能量管理、或者对凸优化和MPC结合感兴趣的研究生和工程师参考。1. 先把问题说清楚PHEV能量管理到底在优化什么1.1 动力系统结构与功率流插电式混合动力车辆的结构可以简单分成串联、并联和混联几种我在项目里用的是并联构型。并联构型里发动机和电机都通过机械路径连接到驱动轴两者输出的转矩叠加后经过变速器驱动车轮。这种拓扑最大的特点是发动机和电机的功率可以按任意比例分配电池既能提供助力也能回收制动能量。写代码之前我先列出一组核心方程需求功率(P_{req}(t)v(t)\cdot\left(mg f0.5\rho_a C_d A_f v^2(t)m\delta a(t)\right)/1000)单位kW其中(f)是滚动阻力系数(\delta)是旋转质量换算系数。功率平衡(P_{req}(t)P_{ice}(t)P_{mot}(t))即发动机和电机的功率之和等于驱动需求。电池功率(P_{bat}(t)P_{mot}(t)/\eta_{mot})电动工况(P_{bat}(t)P_{mot}(t)\cdot\eta_{mot})发电工况。这些方程看似基础但它们决定了整个优化问题最底层的耦合关系。发动机、电机、电池三个子系统通过功率平衡互相牵制而SOC状态又通过电池功率的积分和未来时刻的驱动能力挂钩。1.2 优化目标与硬约束PHEV能量管理优化目标一般有两层一层是经济性另一层是排放或驾驶性但工程上最核心的还是等效燃油消耗最小。单独追求发动机燃油消耗最低会导致电池SOC迅速耗尽所以目标函数里必须加入电能的“代价”。我的做法是用等效因子法[ J\sum_{k0}^{N-1}\left(\dot{m}f(k)\cdot T_ss_e\cdot P{bat}(k)\cdot T_s\right) ]其中(\dot{m}f)是瞬时燃油消耗率(s_e)是电能等效燃油系数(P{bat})是电池输出功率。这个目标函数把“电”和“油”统一到了同一个量纲下后面凸化处理就顺理成章了。约束条件包括以下几类发动机功率范围(P_{ice,min}\le P_{ice}\le P_{ice,max})还附带转速、转矩的MAP限制。电机功率范围(P_{mot,min}\le P_{mot}\le P_{mot,max})。电池SOC边界(SOC_{min}\le SOC\le SOC_{max})以及终端SOC约束防止“用完即弃”。功率平衡等式约束。1.3 这问题的难点在哪里难点之一是发动机燃油消耗率是高度非线性的MAP电机效率同样是二维查表函数电池开路电压还随SOC变化直接扔给通用非线性优化器解起来既慢又不稳定。难点之二是实时性车载ECU的算力远不如一台高性能PC不可能在每个采样周期都调用重型优化算法。难点之三是预测的不确定性驾驶员下一脚油门踩多深根本不知道控制器只能基于有限时域做局部决策。理解了这三层困难才能理解后面为什么要走“凸优化建模MPC滚动ADMM加速”这条路。每一层都是在解决某一个具体瓶颈。2. 为什么要用MPC从后验最优到滚动优化2.1 离线全局优化为什么不能直接用很多刚接触能量管理的同学第一反应是“既然要最小化整个工况的燃油消耗那直接做动态规划DP或者全局寻优不就行了”理论上确实可以动态规划在已知完整工况的前提下能得到全局最优解我前期也用它做过基准对标。但问题在于全局优化是“事后诸葛亮”。它需要知道未来整个行驶工况的速度轨迹这在真实驾驶场景里是做不到的。而且DP的计算量和状态网格数呈指数关系工况一长计算时间就是指数爆炸。更麻烦的是DP解出来的是开环控制序列一旦实际工况和预测轨迹有偏差这个解立刻失效。所以说全局优化只能作为离线标定的参考基准不能直接装车。2.2 MPC的滚动时域逻辑模型预测控制解决这个问题的方式很务实每个控制周期只优化未来一段有限时间窗口执行完当前步的控制量之后下一次采样到来时把窗口向前滚动一格再重新优化。这种“边走边看”的策略天然带有反馈校正能力对模型误差和工况扰动有一定鲁棒性。具体到PHEV能量管理MPC在每个采样时刻要做的事是获取当前SOC、车速、预测的未来车速序列可以用导航/交通预测数据也可以简单用马尔可夫链预测。在预测时域(N_p)内求解一个有限时域最优控制问题得到发动机功率、电机功率的最优序列。只把序列中的第一步控制量施加到被控对象上。下一采样时刻重复上述过程。MPC的另外一个好处是可以显式处理约束。发动机功率限值、电机转矩限值、SOC边界、甚至发动机启停逻辑都可以写进优化问题的约束里。这一点和基于规则的能量管理策略形成鲜明对比规则策略靠的是“IF-THEN”查表遇到边界工况往往要么太保守要么太激进而MPC是在约束可行域内做最优抉择。2.3 预测模型与凸化假设MPC的性能很大程度上取决于预测模型的精度和形式。在PHEV能量管理中预测模型就是车辆纵向动力学加电池SOC动态。为了后面能和凸优化对接我在模型中做了两个关键简化这也是实际项目中常见且合理的工程近似。第一个简化在预测时域内假设电池开路电压和内阻基本不变。文献和实测都表明在SOC变化范围不大比如±5%时OCV变化很小这个假设是站得住的。第二个简化把电机损耗和电池损耗统一近似为功率的二次函数或者分段线性凸函数。这样整个MPC子问题就变成了一个凸二次规划或者凸分段线性规划。这个“窄范围化”思路是整篇方法的核心说白了就是既然完整非线性问题解不动那就先在一个局部可信的范围内把模型凸化利用凸优化的强对偶性和快速求解算法来逼近全局最优。实际测下来这个套路在绝大多数驾驶工况下和DP全局最优的差距能控制在3%以内性价比非常高。3. 凸优化与CVX如何把非线性难题变成“可解问题”3.1 凸优化为什么香在优化领域凸优化的地位有点像线性代数里的矩阵分解——它有一整套成熟的理论保证和高效算法。一个凸优化问题具有一个让人安心的性质任何局部最优解都是全局最优解。这意味着求解器可以放心大胆地沿梯度方向搜索不用怕掉进局部极值点出不来。更重要的一点工程意义上的“快”。凸优化有内点法、一阶法、交替方向乘子法等一大把高效求解算法即使问题规模到几十万变量也能在可接受时间内找到高精度解。这跟非线性规划NLP动不动就要靠初始点、容易数值病态形成鲜明对比。所以把PHEV能量管理问题“折腾”成凸优化问题本质上是在放弃一部分模型精度换取求解的确定性、快速性和全局最优保证。这个取舍在实际工程里往往是被接受的。3.2 非线性能源管理问题的凸化套路把原始非凸问题变成凸问题需要三个步骤。第一步是把目标函数凸化。发动机燃油消耗率(\dot{m}f(P{ice}))通过多项式拟合或者分段线性拟合成凸函数我实测用二次凸函数拟合在常用功率区间内精度就足够好。对于电池电能部分前面等效因子法已经把它变成SOC状态的线性函数线性天然是凸的。第二步是约束凸化。发动机、电机功率的上限和下限是线性不等式天然凸SOC动态方程如果离散成线性形式那么整个等式约束也是仿射的保持凸性。电池的内阻损耗如果以SOC状态和功率的二次型形式出现只要二次项系数矩阵半正定就依然是凸的。第三步是处理不可行问题。实际工程里约束可能互相冲突比如SOC已经很低了驾驶员还要求大功率加速这时原问题无解。我的做法是在目标函数里加入松弛变量把SOC软约束化配合适当的惩罚系数保证优化器永远能给出一个“尽量不违反约束”的解。这个技巧在下一章CVX建模里具体展开。3.3 CVX建模怎么用更少代码实现凸优化CVX是Matlab环境下最常用的凸优化建模工具它的设计哲学就是“把数学形式直接写成代码”。用户不需要关心内部用了什么算法、矩阵怎么分解只需要用CVX的语法定义变量、目标函数和约束CVX会自动检测问题的凸性然后调用后端的求解器如SEDUMI、SDPT3或者支持Gurobi/Mosek做接口来完成求解。我用CVX的典型MPC问题建模框架大概长这样%% 单个MPC步长的CVX求解 cvx_begin quiet variable P_ice(Np) % 发动机功率序列 variable P_bat(Np) % 电池功率序列 variable SOC(Np1) % SOC轨迹 % 目标燃油消耗 电能等效消耗 软约束惩罚 J sum(m_fuel_rate(P_ice)) * Ts ... S_e * sum(P_bat) * Ts ... C_soft * sum(pos(SOC - SOC_max) pos(SOC_min - SOC)); minimize(J) subject to % 动力学离散模型 SOC(1) SOC_0; for k 1:Np SOC(k1) SOC(k) - Ts/E_bat * P_bat(k); end % 功率平衡 P_ice P_bat P_req(1:Np); % 功率限值 P_ice_min P_ice P_ice_max; P_bat_min P_bat P_bat_max; % SOC软边界 SOC_min SOC SOC_max; cvx_end这里有一个很多人容易踩的坑CVX的变量不能参与非凸运算。比如SOC和P_bat相乘形成双线性项或者对功率查表插值都会导致CVX报错或者直接判定非凸。解决办法就是前面说的把模型在窄范围内线性化、把查表换成凸拟合函数。另一个实战经验是CVX里的pos()函数和松弛变量配合非常好用。pos(x)相当于max{x,0}是一个凸函数作为软约束惩罚项加入目标函数后既能软化约束又能保持问题凸性非常适合处理SOC越界和功率超限的模糊边界。求解器选择也有讲究。SDPT3和SeDuMi是CVX默认自带的求解器通用性强但速度一般大规模MPC问题会有点慢。如果装了Gurobi或Mosek可以设置cvx_solver gurobi线性规划和二次规划问题的求解速度会明显提升我在多步MPC测试里Gurobi比SDPT3能快3到5倍。如果没有商业求解器授权Academic License对高校用户通常是免费的申请流程也不复杂。4. ADMM的加入让MPC在车载算力上跑得起来4.1 ADMM的数学内核ADMM交替方向乘子法是一种求解可分结构凸优化问题的一阶算法。它把一个复杂的全局问题拆分成多个相对简单的子问题通过交替求解和更新对偶变量来逼近原问题的最优解。考虑标准形式的凸优化问题[ \min_{x,z} \ f(x)g(z) \quad \text{s.t.} \quad AxBzc ]构造增广拉格朗日函数[ L_\rho(x,z,\lambda)f(x)g(z)\lambda^T(AxBz-c)\frac{\rho}{2}|AxBz-c|_2^2 ]迭代步骤就三步(x^{k1}\arg\min_x L_\rho(x,z^k,\lambda^k))(z^{k1}\arg\min_z L_\rho(x^{k1},z,\lambda^k))(\lambda^{k1}\lambda^k\rho(Ax^{k1}Bz^{k1}-c))这里(x)更新和(z)更新是解耦的可以分别针对各自子问题的最简单结构求解。在很多情况下这两个子问题都有闭式解或者非常廉价的数值解这是ADMM快的关键。4.2 ADMM为什么适配MPCMPC每个采样周期要解决一个凸二次规划如果用内点法需要在每次迭代里求解一个大型线性方程组矩阵分解的复杂度大约是(O(n^3))。当预测时域长、状态变量多时这个成本相当可观。ADMM直接把这个大问题拆成了多个带有特殊结构的小问题每步迭代的计算量大幅下降而且迭代次数通常在中高精度需求下控制在几十次以内实际求解时间可以从几十毫秒压缩到几毫秒。MPC问题天然适合ADMM分解因为它的结构就是典型的目标函数可分约束可分。状态轨迹的动力学约束、控制量的限值约束都可以各自独立处理。我在实现里这样拆(x)子问题处理系统的动力学递推即给定控制量序列时更新状态轨迹和SOC轨迹。这本质上是一个带线性等式约束的最小二乘问题由于递推矩阵是稀疏带状结构可以预计算一次矩阵分解之后每次迭代只需要做前代回代速度极快。(z)子问题处理控制量的箱式约束和功率平衡约束耦合部分等价于做一个带限幅的投影算子直接把控制量截断到可行区间内。(\lambda)更新就是简单的向量加法和缩放计算量几乎可以忽略。4.3 ADMM和CVX怎么配合我在项目里的分工是这样的离线阶段用CVX把MPC问题建模、验证凸性、求高精度的参考解用这个参考解去校验ADMM实现的正确性。在线阶段则把ADMM作为实时求解器CVX不再参与实际控制循环。简单说就是“CVX负责验证ADMM负责上线”。这样做还有一个额外的好处后续如果换模型参数或者改约束条件可以直接在CVX里快速改代码重新验证完全不影响ADMM求解器的结构。我在调试过程中对比CVX高精度解和ADMM迭代50次左右的结果目标函数值的相对偏差一般在0.1%以内这个精度对能量管理完全够用。另一个技术细节是惩罚参数(\rho)的选取。ADMM的收敛速度对(\rho)非常敏感(\rho)太大会导致对偶变量振荡收敛反而慢(\rho)太小又会让原始变量收敛极慢。经验做法是先取一个中等值比如(\rho10)然后根据迭代残差动态调整类似自适应ADMM。标准化的做法是监控原始残差和对偶残差如果两者比值长期偏离均衡就相应调整(\rho)。5. Matlab代码实现CVX离线验证 ADMM在线求解的完整流程5.1 代码结构与数据流整套代码我分成五个模块用脚本文件的方式组织方便调试和复用模块文件名作用参数初始化init_vehicle_params.m整车参数、电池参数、MPC参数、ADMM参数工况生成generate_drive_cycle.m生成WLTC/UDDS工况输出速度时间序列参考求解solve_cvx_ref.m用CVX离线求解给定工况的MPC问题得到参考解在线求解solve_admm_mpc.m用ADMM实现实时MPC求解输出控制序列结果评估evaluate_results.m对比燃油消耗、SOC轨迹、求解时间等指标数据流是这样走的参数初始化模块定义一切常量和模型系数→工况生成模块算好每个时刻的需求功率序列→参考求解模块把完整问题用CVX跑一遍拿到基准解→在线求解模块按MPC滚动时域逻辑在每一采样步调用ADMM求解当前窗口的优化问题→结果评估模块汇总两条链路的输出做对比分析。5.2 关键代码段解析第一段是车辆与电池的初始化和模型系数% 整车参数 m 1700; % 整车质量 kg g 9.8; f 0.012; % 滚动阻力系数 rho_air 1.225; % 空气密度 kg/m^3 Cd 0.3; % 风阻系数 Af 2.3; % 迎风面积 m^2 delta_r 1.05; % 旋转质量换算系数 % 电池参数 E_bat 12; % 可用能量 kWh SOC_min 0.25; SOC_max 0.9; SOC_0 0.8; P_bat_max 45; % 最大充放电功率 kW % MPC参数 Np 20; % 预测时域步数 Ts 1; % 采样周期 s % ADMM参数 rho_admm 20; % 惩罚参数 max_iter 80; % 最大迭代次数 tol_primal 1e-3; tol_dual 1e-3;第二段是ADMM在线求解器的主循环这也是整个代码的核心。以单个MPC采样步为例内部要做的事情包括初值更新、预测窗口生成、ADMM迭代function [P_ice_opt, P_bat_opt] solve_admm_mpc(SOC_now, P_req_pred, params) Np params.Np; rho params.rho_admm; % 初始化 P_bat zeros(Np,1); P_ice P_req_pred; lambda zeros(Np,1); % 预计算系数动力学递推的矩阵分解 [A_soc, B_soc, M_inv] precompute_matrices(params); for iter 1:params.max_iter % x更新SOC轨迹在给定P_bat下的最优状态 SOC M_inv * (A_soc * SOC_now B_soc * P_bat); % z更新投影到功率平衡与限值可行域 z project_feasible(P_req_pred, P_ice, P_bat, params); % lambda更新对偶上升 lambda lambda rho * (z - P_bat); % 收敛检查 r_prim norm(z - P_bat); r_dual rho * norm(z - P_bat_prev); if r_prim params.tol_primal r_dual params.tol_dual break; end P_bat_prev P_bat; end end这里project_feasible函数做的是把控制量投影到可行域内保证P_ice P_bat P_req同时P_ice和P_bat都在各自的上下界内。由于这些约束都是简单的区间和线性等式投影计算有解析形式不需要迭代求解这也是ADMM高效的原因。第三段是MPC滚动控制的主循环for k 1:length(P_req)-Np % 取预测窗口内的需求功率 P_req_window P_req(k:kNp-1); % 调用ADMM求解当前窗口的控制序列 [P_ice_seq, P_bat_seq] solve_admm_mpc(SOC_hist(k), P_req_window, params); % 只执行第一个控制量 P_ice_opt(k) P_ice_seq(1); P_bat_opt(k) P_bat_seq(1); % 更新SOC SOC_hist(k1) SOC_hist(k) - Ts/E_bat * P_bat_seq(1); end这个循环体现了MPC的“滚动”本质每个采样步都重新求解一次优化问题但只实施第一步指令。5.3 参考求解与基准校验用CVX求参考解的方法就是把上面ADMM内部复杂的迭代逻辑整个替换成一次完整的凸优化求解。前面3.3节给的代码就是参考求解的核心。我通常是先跑CVX把结果存成mat文件再用ADMM的结果和它做逐时刻对比。对比指标有三个燃油消耗总量、电池SOC轨迹、以及求解耗时的平均值和最大值。我还做了一个自动化脚本随机生成多条工况分别用两种方法求解然后把误差统计打印出来。这个脚本帮我发现了一个很有意思的现象ADMM在平稳工况下的解和CVX几乎完全一致但在剧烈加减速的片段会有轻度偏差。原因是工况剧烈变化时ADMM的初始点离最优解比较远有限迭代次数内没能完全收敛。解决办法是在每个MPC采样步用上一个窗口的最优解作为当前窗口迭代的初始点也就是“热启动”。这个技巧显著减少了迭代次数要求80次迭代的精度直接提升了一个数量级。6. 典型工况结果与调参经验6.1 工况测试与控制效果我用的验证工况是WLTC全球轻型车测试循环和UDDS城市工况两种也加了一段自定义的激烈驾驶循环。先说结论在WLTC上MPC无论CVX还是ADMM相比传统的CD-CS电量消耗-电量维持规则策略等效燃油消耗降低了约8%到10%相比在线瞬时优化策略ECMS即时调节等效因子还能再省1%到2%。这个结果符合预期规则策略是固定阈值切换完全忽略未来驾驶需求ECMS虽然也是优化但只看当前时刻没有前瞻性MPC因为有预测窗口能在预见坡度、预见停车减速的情况下提前调整发动机工作点自然更省油。SOC轨迹的表现也很有代表性。MPC会让SOC在预测窗口内平缓下降接近约束边界时提前回收电能而不是像CD-CS那样简单粗暴地在SOC掉到阈值后强制切到CS模式。从驾驶性角度看MPC的发动机启停、模式切换次数更少整车NVH体验会更好。6.2 参数敏感性分析先看预测时域(N_p)的影响。我把(N_p)从10步扫到40步发现燃油消耗随(N_p)增大单调下降但下降速度会饱和从10步到20步能省大约2%的油从20步到40步只再省0.5%。而求解时间几乎和(N_p)成正比增长。综合权衡下来20步到30步是比较甜点的区间再长就得不偿失了。ADMM惩罚参数(\rho)的影响前面提到过。参数太小收敛慢参数太大对偶变量振荡。我用的是自适应方案每次迭代后比较原始残差和对偶残差如果前者大于后者的10倍就调大(\rho)反之调小(\rho)。实测稳健性比固定(\rho)好很多对不同工况的适应性也更强。迭代次数上限我控制在60到100之间。80次迭代在绝大多数工况下能达到高精度偶尔遇到剧烈变化的工况窗口靠热启动也能在40次以内收敛到可接受精度。如果追求极致实时性可以把迭代次数压到30次配合早停准则代价是精度略有下降但在线控制的闭环误差会被下一采样步的部分校正抵消总体表现并不会差太多。7. 踩坑实录常见问题与排查方法7.1 CVX安装与许可证问题CVX安装本身不复杂从官网下载对应平台的压缩包解压后在Matlab里cvx_setup即可。但许可证这个问题很经典CVX需要申请一个免费的学术许可证文件cvx_license.dat申请时填写的邮箱收到许可后需要把文件放到CVX的安装目录下然后重新运行cvx_setup。很多人搞不定是因为下载的是破解版或者旧版本文件损坏导致许可证检查不通过。官方学术许可完全免费没必要折腾。常见的报错是Error: “cvx/begin” is not found先检查路径是否设置正确addpath(genpath(cvx目录))之后运行cvx_setup看到提示“CVX is ready”才算成功。7.2 cvx变量与double混用的坑CVX变量在求解之前是一个特殊的cvx对象不能直接和普通Matlab数组做加减乘除除非操作是CVX支持的“表达式构建”操作。我踩过最典型的一个坑是在CVX约束里写if SOC(k) SOC_max这种判断语句CVX直接报错。正确做法是用pos(SOC - SOC_max)或者max(SOC, SOC_max)这种凸算子来构建软约束。另一个常见问题是求解结束后cvx_optval已经更新了但value(variable)提取结果时没有加括号或者提取的是旧值。解决方法是求解完成后立即调用SOC_sol value(SOC);赋值给普通变量再继续做其他处理避免拿着cvx对象去做绘图或传参。7.3 求解器的数值警告CVX默认用SeDuMi或SDPT3求解QP时偶尔会蹦出“Numerical problems”或者“Status: Failed”的警告。这种现象多半是问题本身的数值尺度差异太大导致的比如发动机功率的单位是kWSOC无量纲且范围在0到1之间两者在矩阵里的量级差了三个数量级。我的处理办法是做完所有变量的归一化功率统一除以一个基准功率比如100kWSOC以0.5为中心除以0.5做归一化。这样所有优化变量都落在差不多的数量级数值问题基本消失。如果还不行就换Gurobi或Mosek作为后端求解器这类商业求解器的预处理和数值稳定性确实比免费求解器好很多。7.4 MPC无解与递归可行性MPC在工程实现中最大的坑之一就是不可行问题。比如SOC已经逼近下限而预测窗口内还要求持续大功率输出此时原始约束互相冲突优化问题无解。如果没有处理机制MPC控制器会直接崩溃。我的方案在3.2节提到过给SOC约束加松弛变量并把松弛惩罚加入目标函数。这样优化器永远不会“无解”只会尽量把SOC的越界程度降到最低。实际效果是在SOC比较极端的时候控制器会自动提前减少电池出力、加大发动机出力相当于“软避让”整车依然能稳定运行。7.5 ADMM收敛不稳定的调试技巧ADMM迭代发散或者振荡先别急着调(\rho)先检查子问题求解是否正确。一个简单的验证方法就是把ADMM的迭代残差画出来如果原始残差一直下降但对偶残差上升通常是(\rho)偏小如果原始残差振荡停不下来通常是(\rho)偏大或者是热启动初始点差异过大。另一个技巧是用“诊断模式”在代码里加开关每10次迭代输出残差和目标函数值对比CVX的参考值判断收敛趋势是否正常。ADMM算法理论上有全局收敛保证实际不收敛几乎都是实现细节的问题比如投影算子写错、矩阵分解没有随参数更新、或者对偶变量更新方向搞反了。写在最后的小心得这套“凸优化MPCADMM”的组合解决的核心矛盾就是精度和实时性不可兼得的问题。CVX负责把数学模型快速搭起来帮你在算法层面验证可行性ADMM负责在硬件上跑出可用的求解速度。我个人最大的体会是调模型比调算法重要把问题凸化成形之后后面的一切都顺理成章了。如果你只做离线仿真研究CVXMPC已经够用如果要往实车控制器或者嵌入式方向走那ADMM或者同类的一阶方法是必由之路。我在测试中还发现ADMM的迭代次数在热启动情况下可以大幅压缩配合C代码生成完全可以跑在车载ECU级别的算力上。最后分享一个操作细节不管用CVX还是ADMM先把模型、约束、目标函数的量纲统一好写代码之前用纸笔把数学形式推一遍比在Matlab里反复试错有效得多。这个项目后续如果能加上坡度预测、交通信号灯信息MPC的前瞻性还能再上一个台阶这也是我下一步准备做的方向。