换档

人生如同一台在路上跑的车,也许有目的,也许没有。而车本身,则希望尽快到达前方,车子在不断加速、减速、换档、刹车。

在一个档位,车子的极限速度是一定的,任何车都如此,即使无级变速的车,不过自动换档而已。有人终生没有换档,有人喜欢自动档,有人喜欢手档,但依然尊造30公里换档、60公里收油的教诲,当然也有人喜欢强制换档,在空当轰油门,强制切高档,获得极限的推背感,当然缺点就是效率不高,太费油了,对人生来说,就是大红大紫。强制换档的方式很多,更有高速切低档,获得车子在冰雪路面的掌控感,对人生来说,就是大材小用,却也安享人生。

我喜欢什么档?

[@more@]

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/7570639/viewspace-926611/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/7570639/viewspace-926611/

clc; clear all; format long; % 数据加载 %nedc = cell2mat(struct2cell(load('D:\matlab2022\nedc.mat'))); %nedc = cell2mat(struct2cell(load('D:\画图指标数据\CLTC-WLTC-NEDC-CHTC等七种主流工况数据MATLAB格式\cycles_chtc_ht.mat'))); cltc= readtable('D:/matlab2022/降噪CLTC-HT.xlsx'); nedc= table2array(cltc(:, 1)); time=table2array(cltc(:,2)); x_tot=trapz(time,nedc./3.6)/1000; data = readtable('C:/Users/10058061/Desktop/发动机map2.xlsx'); engine_RPM_Axis = table2array(data(:, 1)); Ttq = table2array(data(:, 2)); engine_Torque_max = [2423.5 2430.6 2437.8 2434.2 2421.8 2429.8 2375.2 2317.4 2279.8 2251.2]; engine_RPM_Axis_max = [800 900 1000 1100 1200 1300 1400 1500 1600 1700]; mf_kn = table2array(data(:, 3)); engine_be_Data = table2array(data(:, 6)); % 确保mf_kn是二维矩阵 if ~ismatrix(mf_kn) || size(mf_kn, 2) == 1 mf_kn = reshape(mf_kn, length(engine_RPM_Axis), []); end % 整车参数 igt = [12.26, 9.556, 7.356, 5.734, 4.521, 3.524, 2.712, 2.114, 1.627, 1.268, 1, 0.779]; i0 = 3.083; Rw = 0.522; Mass = 8200; Cx = 0.6; S = 9.09; f = 0.015; g = 9.8; det = 1.05; Jw = 14.87; itatgb = 0.96; itatfd = 0.95; itat = 0.912; n_engine = [800, 1700]; shift = 20; % 计算加速度和车轮转矩 K = length(nedc); acc = zeros(K, 1); Twheel = zeros(K, 1); for kk = 1:K - 1 acc(kk + 1) = (nedc(kk + 1) - nedc(kk))/2; end for kk = 1:K - 1 if nedc(kk) == 0 && acc(kk) == 0 Twheel(kk) = 0; else Twheel(kk) = (Mass * g * f + 0.5 * 1.225 * Cx * S * (nedc(kk)/3.6)^2 + det * Mass * acc(kk)) * Rw; end end % 确定车辆行驶状态变化点 S_r = []; nnn = 1; for kk = K:-1:2 if nedc(kk) == 0 && acc(kk) < 0 && nedc(kk - 1) > 0 S_r(nnn) = kk; nnn = nnn + 1; end end S_r = fliplr(S_r); S_1 = []; mmm = 1; for kk = 2:K if nedc(kk) > 0 && nedc(kk - 1) == 0 && acc(kk) > 0 S_1(mmm) = kk; mmm = mmm + 1; end end S_rr = []; www = 1; for hh = 1:length(S_1) for tt = S_r(hh):-1:S_1(hh) if Twheel(tt) > 0 S_rr(www) = tt; break; end end www = www + 1; end % 初步筛选适合的档位 igt_fea = zeros(length(igt), length(S_rr)); for h = 1:length(S_rr) N_ice = 30 * nedc(S_rr(h)) * igt * i0 / (pi * Rw); for pp = 1:12 if N_ice(pp) <= 1700 && N_ice(pp) >= 800 igt_fea(pp, h) = pp; end end end % 根据转矩限制进一步筛选档位 S_rr_igt = zeros(length(igt), length(S_rr)); for hh = 1:length(S_rr) for pp = 1:12 if igt_fea(pp, hh) ~= 0 nee = 30 * nedc(S_rr(hh)) * igt(igt_fea(pp, hh)) * i0 / (pi * Rw); te = Twheel(S_rr(hh)) / (i0 * igt(igt_fea(pp, hh)) * itat); temax = interp1(engine_RPM_Axis_max, engine_Torque_max, nee, 'cubic'); if te <= temax S_rr_igt(pp, hh) = igt_fea(pp, hh); end end end end % 计算每个档位下的燃油消耗(改进版) S_rr_fuel = ones(length(igt), length(S_rr)) * 100000; for hh = 1:length(S_rr) for pp = 1:12 if S_rr_igt(pp, hh) == 0 continue; end gear = S_rr_igt(pp, hh); nee = 30 * nedc(S_rr(hh)) * igt(gear) * i0 / (pi * Rw); te = Twheel(S_rr(hh)) / (i0 * igt(gear) * itat); ne_clamped = max(min(nee, max(engine_RPM_Axis)), min(engine_RPM_Axis)); te_clamped = max(min(te, max(Ttq)), min(Ttq)); try sfuel = griddata(engine_RPM_Axis, Ttq, engine_be_Data, ne_clamped, te_clamped, 'cubic'); catch sfuel = griddata(engine_RPM_Axis, Ttq, engine_be_Data, ne_clamped, te_clamped, 'linear'); end if isnan(sfuel) [~, ne_idx] = min(abs(engine_RPM_Axis - ne_clamped)); [~, te_idx] = min(abs(Ttq - te_clamped)); ne_idx = max(1, min(ne_idx, size(mf_kn, 1))); te_idx = max(1, min(te_idx, size(mf_kn, 2))); sfuel = mf_kn(ne_idx, te_idx); end S_rr_fuel(pp, hh) = sfuel; end end % 选择每个阶段的最佳档位 S_rr_f = zeros(length(S_rr), 1); for hh = 1:length(S_rr) [~, y2] = min(S_rr_fuel(:, hh)); S_rr_f(hh) = y2; end % 动态规划算法确定最佳换挡策略 ne_final = zeros(length(nedc), 1); te_final = zeros(length(nedc), 1); gear_final = zeros(length(nedc), 1); fuel_final = zeros(length(nedc), 1); N = length(igt); f_n = zeros(length(S_1), 1); for hh = 1:length(S_1) f_n(hh) = S_rr(hh) - S_1(hh) + 1; end for hh = 1:length(S_1) Fuel = zeros(N, f_n(hh)); for ii = 1:N if ii == S_rr_f(hh) Fuel(ii, f_n(hh)) = 0.05; else Fuel(ii, f_n(hh)) = 10900; end end Gear_con = [-1, 0, 1]; Gear = zeros(N, f_n(hh)); for kk = (f_n(hh) - 1):-1:1 N_ice = 30 * nedc(kk - 1 + S_1(hh)) * igt * i0 / (pi * Rw); tr_cost_1 = zeros(12, 1); for ii = 1:12 if N_ice(ii) > 1699.99999 || N_ice(ii) < 799.9999 tr_cost_1(ii) = 10007; else tr_cost_1(ii) = 0.0001; end end if tr_cost_1(1) == 10007 for ii = 1:12 if tr_cost_1(ii) >= 1699.99 x1 = ii; Fuel(ii, kk) = tr_cost_1(ii); Gear(ii, kk) = 17; end end x1 = x1 + 1; x2 = 12; elseif tr_cost_1(1) == 0.0001 && tr_cost_1(12) == 0.0001 x1 = 1; x2 = 12; elseif tr_cost_1(12) == 10007 for ii = 12:-1:1 if tr_cost_1(ii) >= 1699.999 x2 = ii; Gear(ii, kk) = 17; Fuel(ii, kk) = tr_cost_1(ii); end end x1 = 1; x2 = x2 - 1; else x1 = 0; x2 = 0; end if x1 > 0 && x2 > 0 Ne = 30 * nedc(kk - 1 + S_1(hh)) * igt(x2) * i0 / (pi * Rw); Te = Twheel(kk - 1 + S_1(hh)) / (i0 * igt(x2) * itat); Temax = interp1(engine_RPM_Axis_max, engine_Torque_max, Ne, 'cubic'); nn = 0; while Te > Temax x2 = x2 - 1; Ne = 30 * nedc(kk - 1 + S_1(hh)) * igt(x2) * i0 / (pi * Rw); Te = Twheel(kk - 1 + S_1(hh)) / (i0 * igt(x2) * itat); Temax = interp1(engine_RPM_Axis_max, engine_Torque_max, Ne, 'cubic'); nn = nn + 1; end for ii = (x2 + nn):-1:(x2 + 1) Fuel(ii, kk) = 20007; Gear(ii, kk) = 777; end end if Twheel(kk - 1 + S_1(hh)) >= 0.01 for ii = x1:x2 fuel = zeros(3, 1); for jj = 1:3 if ii + Gear_con(jj) < 1 || ii + Gear_con(jj) > 12 fuel(jj) = Fuel(ii, kk + 1) + 10500; else v_current = nedc(kk - 1 + S_1(hh)); gear_candidate = ii + Gear_con(jj); % 修正:使用连续的发动机转速范围计算车速范围 ne_range = n_engine(1):n_engine(2); v_gear = 0.377 * ne_range * Rw / (igt(gear_candidate) * i0); v_min = min(v_gear); v_max = max(v_gear); penalty = 0; if v_current < v_min || v_current > v_max penalty = 1000; % 车速超出档位合理范围的惩罚 end if 30 * v_current * igt(gear_candidate) * i0 / (pi * Rw) < n_engine(1) || ... 30 * v_current * igt(gear_candidate) * i0 / (pi * Rw) > n_engine(2) for pp = 1:12 if ii + Gear_con(jj) >= pp && ii + Gear_con(jj) <= pp + 1 fuel(jj) = Fuel(pp, kk + 1) + 10500 + penalty; else break; end end else ne = 30 * v_current * igt(gear_candidate) * i0 / (pi * Rw); te = Twheel(kk - 1 + S_1(hh)) / (i0 * igt(gear_candidate) * itat); ne_clamped = max(min(ne, max(engine_RPM_Axis)), min(engine_RPM_Axis)); te_clamped = max(min(te, max(Ttq)), min(Ttq)); try tr_cost = griddata(engine_RPM_Axis, Ttq, engine_be_Data, ne_clamped, te_clamped, 'cubic'); catch tr_cost = griddata(engine_RPM_Axis, Ttq, engine_be_Data, ne_clamped, te_clamped, 'linear'); end if isnan(tr_cost) [~, ne_idx] = min(abs(engine_RPM_Axis - ne_clamped)); [~, te_idx] = min(abs(engine_RPM_Axis - ne_clamped)); ne_idx = max(1, min(ne_idx, size(engine_be_Data, 1))); te_idx = max(1, min(te_idx, size(engine_be_Data, 2))); tr_cost = engine_be_Data(ne_idx, te_idx); end for pp = 1:12 if gear_candidate >= pp && gear_candidate < pp + 1 fuel(jj) = Fuel(pp, kk + 1) + tr_cost + penalty; break; end end end end end [x22, x3] = min(fuel); Fuel(ii, kk) = x22; Gear(ii, kk) = Gear_con(x3); end else for ii = 1:12 Fuel(ii, kk) = Fuel(ii, kk + 1); Gear(ii, kk) = 0; end end end re_gear = zeros(f_n(hh), 1); re_G = zeros(f_n(hh), 1); re_Fuel = zeros(f_n(hh), 1); re_ne = zeros(f_n(hh), 1); re_te = zeros(f_n(hh), 1); re_gear(1) = 1; for ii = 1:12 if re_gear(1) == ii re_G(1) = Gear(ii, 1); re_G(1) = max(min(re_G(1), 1), -1); break; end end current_gear = min(max(re_gear(1) + re_G(1), 1), 12); re_ne(1) = 30 * nedc(S_1(hh)) * igt(current_gear) * i0 / (pi * Rw); re_te(1) = Twheel(S_1(hh)) / (i0 * igt(current_gear)*itat); re_Fuel(1) = 0; for kk = 2:f_n(hh) current_gear = min(max(re_gear(kk - 1) + re_G(kk - 1), 1), 12); re_ne(kk) = 30 * nedc(kk - 1 + S_1(hh)) * igt(current_gear) * i0 / (pi * Rw); if Twheel(kk - 1 + S_1(hh)) > 0.001 re_te(kk) = Twheel(kk - 1 + S_1(hh)) / (i0 * igt(current_gear)*itat); else re_te(kk) = re_te(kk - 1); end ne_clamped = max(min(re_ne(kk), max(engine_RPM_Axis)), min(engine_RPM_Axis)); te_clamped = max(min(re_te(kk), max(Ttq)), min(Ttq)); try re_fuel = griddata(engine_RPM_Axis, Ttq, engine_be_Data, ne_clamped, te_clamped, 'cubic'); catch re_fuel = griddata(engine_RPM_Axis, Ttq, engine_be_Data, ne_clamped, te_clamped, 'linear'); end if isnan(re_fuel) [~, ne_idx] = min(abs(engine_RPM_Axis - ne_clamped)); [~, te_idx] = min(abs(Ttq - te_clamped)); ne_idx = max(1, min(ne_idx, size(engine_be_Data, 1))); te_idx = max(1, min(te_idx, size(engine_be_Data, 2))); re_fuel = mf_kn(ne_idx, te_idx); end re_Fuel(kk) = re_Fuel(kk - 1) + re_fuel; for pp = 1:12 if igt(current_gear) == igt(pp) x4 = pp; break; end end x4 = min(max(x4, 1), 12); re_G(kk) = Gear(x4, kk); re_G(kk) = max(min(re_G(kk), 1), -1); re_gear(kk) = current_gear; end for pp = S_1(hh):S_rr(hh) idx = pp - S_1(hh) + 1; if idx <= length(re_ne) && idx <= length(re_te) && idx <= length(re_gear) && idx <= length(re_Fuel) ne_final(pp) = re_ne(idx); te_final(pp) = re_te(idx); gear_final(pp) = re_gear(idx); fuel_final(pp) = re_Fuel(idx); end end end regions_to_smooth = [129,140;358,383;425,436;437,465;587,593;594,611;733,737;738,744;745,753;787,811;812,842;843,877;953,957;958,964;965,993;1176,1182;1390,1404]; % 保存原始数据的副本,用于回退 original_gear = gear_final; original_ne = ne_final; original_te = te_final; for r = 1:size(regions_to_smooth, 1) start_idx = regions_to_smooth(r, 1); end_idx = regions_to_smooth(r, 2); % 确保索引在有效范围内 if start_idx < 1 || end_idx > length(gear_final) continue; end % 获取区域内的两个档位及出现次数 region_gears = gear_final(start_idx:end_idx); unique_gears = unique(region_gears); % 确认只有两个档位 if length(unique_gears) == 2 gear1 = unique_gears(1); gear2 = unique_gears(2); % 统计两个档位的出现次数 count1 = sum(region_gears == gear1); count2 = sum(region_gears == gear2); % 选择出现次数多的档位(若相同则选高档) if count1 > count2 final_gear = gear1; elseif count2 > count1 final_gear = gear2; else final_gear = max(gear1, gear2); end % 标记变量,记录区域是否被完全应用 region_applied = true; % 尝试应用最终档位到整个区域 for i = start_idx:end_idx new_ne = 30 * nedc(i) * igt(final_gear) * i0 / (pi * Rw); % 放宽转速限制,允许短暂低于最低转速 if new_ne >= max(n_engine(1) - 100, 700) && new_ne <= n_engine(2) gear_final(i) = final_gear; ne_final(i) = new_ne; te_final(i) = Twheel(i) / (i0 * igt(final_gear) * itat); else % 只要有一个点不满足条件,标记区域为未完全应用 region_applied = false; end end % 如果区域未被完全应用,则整体回退到平滑档位,但使用原始转速和扭矩 if ~region_applied for i = start_idx:end_idx gear_final(i) = final_gear; % 应用平滑后的档位 ne_final(i) = original_ne(i); % 使用原始转速 te_final(i) = original_te(i); % 使用原始扭矩 end end end end figure(1); time = (1:length(nedc)); plot(time,nedc); title('NEDC工况车速'); xlabel('时间 (s)'); ylabel('车速 (km/h)'); grid on; figure(2); plot(gear_final); title('改进的动态规划优化换挡策略'); xlabel('时间 (s)'); ylabel('挡位'); ylim([0 15]); grid on; figure(3); plot(ne_final/1.5, te_final, 'b.', engine_RPM_Axis_max, engine_Torque_max, 'r-'); title('发动机工作点分布'); xlabel('发动机转速 (rpm)'); ylabel('发动机转矩 (N·m)'); grid on; legend('优化工作点', '外特性曲线'); figure(4); plot(ne_final/1.5); title('转速变化'); xlabel('时间(s)'); ylabel('转速'); grid on; figure(5); plot(te_final); title('扭矩变化'); xlabel('时间(s)'); ylabel('扭矩'); grid on; fuel_final=diff(fuel_final); % 计算总燃油消耗 % 计算总燃油消耗(排除fuel_final为0的点) valid_idx = fuel_final > 0; % 找出fuel_final中不为0的索引 valid_time = time(valid_idx); % 获取对应的时间点 valid_fuel = fuel_final(valid_idx); % 获取对应的燃油消耗值 Fuel = trapz(valid_time, valid_fuel/3600); % 使用有效数据计算总燃油量 fuel_economy = Fuel/x_tot*100; % 计算百公里油耗 fprintf('总燃油消耗: %.2f L/100km\n', fuel_economy);将上述基于动态规划的换档策略改进成dp-mpc的换挡策略,给出改进后的完整代码
06-06
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值